Address kcc's comment. Add tests for the new functionality.
http://reviews.llvm.org/D4203
Files:
projects/compiler-rt/lib/asan/asan_interface_internal.h
projects/compiler-rt/lib/asan/asan_report.cc
projects/compiler-rt/test/asan/TestCases/global-location.cc
tools/clang/lib/CodeGen/CGDecl.cpp
tools/clang/lib/CodeGen/CodeGenModule.cpp
tools/clang/lib/CodeGen/CodeGenModule.h
tools/clang/test/CodeGen/asan-globals.cpp
tools/clang/test/CodeGen/sanitize-init-order.cpp
Index: projects/compiler-rt/lib/asan/asan_report.cc
===================================================================
--- projects/compiler-rt/lib/asan/asan_report.cc
+++ projects/compiler-rt/lib/asan/asan_report.cc
@@ -212,6 +212,26 @@
(char *)g.beg);
}
+static const char *GlobalFilename(const __asan_global &g) {
+ const char *res = g.module_name;
+ // Prefer the filename from source location, if is available.
+ if (g.location)
+ res = g.location->filename;
+ CHECK(res);
+ return res;
+}
+
+static void PrintGlobalLocation(InternalScopedString *str,
+ const __asan_global &g) {
+ str->append("%s", GlobalFilename(g));
+ if (!g.location)
+ return;
+ if (g.location->line_no)
+ str->append(":%d", g.location->line_no);
+ if (g.location->column_no)
+ str->append(":%d", g.location->column_no);
+}
+
bool DescribeAddressRelativeToGlobal(uptr addr, uptr size,
const __asan_global &g) {
static const uptr kMinimalDistanceFromAnotherGlobal = 64;
@@ -232,8 +252,10 @@
// Can it happen?
str.append("%p is located %zd bytes inside", (void *)addr, addr - g.beg);
}
- str.append(" of global variable '%s' from '%s' (0x%zx) of size %zu\n",
- MaybeDemangleGlobalName(g.name), g.module_name, g.beg, g.size);
+ str.append(" of global variable '%s' defined in '",
+ MaybeDemangleGlobalName(g.name));
+ PrintGlobalLocation(&str, g);
+ str.append("' (0x%zx) of size %zu\n", g.beg, g.size);
str.append("%s", d.EndLocation());
PrintGlobalNameIfASCII(&str, g);
Printf("%s", str.data());
@@ -741,11 +763,14 @@
Printf("%s", d.Warning());
Report("ERROR: AddressSanitizer: odr-violation (%p):\n", g1->beg);
Printf("%s", d.EndWarning());
- Printf(" [1] size=%zd %s %s\n", g1->size, g1->name, g1->module_name);
- Printf(" [2] size=%zd %s %s\n", g2->size, g2->name, g2->module_name);
+ InternalScopedString g1_loc(256), g2_loc(256);
+ PrintGlobalLocation(&g1_loc, *g1);
+ PrintGlobalLocation(&g2_loc, *g2);
+ Printf(" [1] size=%zd %s %s\n", g1->size, g1->name, g1_loc.data());
+ Printf(" [2] size=%zd %s %s\n", g2->size, g2->name, g2_loc.data());
Report("HINT: if you don't care about these warnings you may set "
"ASAN_OPTIONS=detect_odr_violation=0\n");
- ReportErrorSummary("odr-violation", g1->module_name, 0, g1->name);
+ ReportErrorSummary("odr-violation", g1_loc.data(), 0, g1->name);
}
// ----------------------- CheckForInvalidPointerPair ----------- {{{1
Index: projects/compiler-rt/lib/asan/asan_interface_internal.h
===================================================================
--- projects/compiler-rt/lib/asan/asan_interface_internal.h
+++ projects/compiler-rt/lib/asan/asan_interface_internal.h
@@ -33,6 +33,14 @@
SANITIZER_INTERFACE_ATTRIBUTE void __asan_init_v3();
#define __asan_init __asan_init_v3
+ // This structure is used to describe the source location of a place where
+ // global was defined.
+ struct __asan_global_source_location {
+ const char *filename;
+ int line_no;
+ int column_no;
+ };
+
// This structure describes an instrumented global variable.
struct __asan_global {
uptr beg; // The address of the global.
@@ -42,6 +50,8 @@
const char *module_name; // Module name as a C string. This pointer is a
// unique identifier of a module.
uptr has_dynamic_init; // Non-zero if the global has dynamic initializer.
+ __asan_global_source_location *location; // Source location of a global,
+ // or NULL if it is unknown.
};
// These two functions should be called by the instrumented code.
Index: projects/compiler-rt/test/asan/TestCases/global-location.cc
===================================================================
--- /dev/null
+++ projects/compiler-rt/test/asan/TestCases/global-location.cc
@@ -0,0 +1,39 @@
+// RUN: %clangxx_asan -O2 %s -o %t
+// RUN: not %run %t g 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=GLOB
+// RUN: not %run %t c 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=CLASS_STATIC
+// RUN: not %run %t f 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=FUNC_STATIC
+// RUN: not %run %t l 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=LITERAL
+
+// CHECK: AddressSanitizer: global-buffer-overflow
+
+#include <string.h>
+
+class C {
+ public:
+ static int array[10];
+};
+
+int global[10];
+// GLOB: 0x{{.*}} is located 4 bytes to the right of global variable 'global' defined in '{{.*}}/global-location.cc:[[@LINE-1]]:5' {{.*}} of size 40
+int C::array[10];
+// CLASS_STATIC: 0x{{.*}} is located 4 bytes to the right of global variable 'C::array' defined in '{{.*}}/global-location.cc:[[@LINE-1]]:8' {{.*}} of size 40
+
+int main(int argc, char **argv) {
+ int one = argc - 1;
+ switch (argv[1][0]) {
+ case 'g': return global[one * 11];
+ case 'c': return C::array[one * 11];
+ case 'f':
+ static int array[10];
+ // FUNC_STATIC: 0x{{.*}} is located 4 bytes to the right of global variable 'main::array' defined in '{{.*}}/global-location.cc:[[@LINE-1]]:16' {{.*}} of size 40
+ memset(array, 0, 10);
+ return array[one * 11];
+ case 'l':
+ const char *str = "0123456789";
+ // LITERAL: 0x{{.*}} is located 0 bytes to the right of global variable {{.*}} defined in '{{.*}}/global-location.cc:[[@LINE-1]]:23' {{.*}} of size 11
+ return str[one * 11];
+ }
+ return 0;
+}
+
+// CHECK: SUMMARY: AddressSanitizer: global-buffer-overflow
Index: tools/clang/lib/CodeGen/CodeGenModule.h
===================================================================
--- tools/clang/lib/CodeGen/CodeGenModule.h
+++ tools/clang/lib/CodeGen/CodeGenModule.h
@@ -1001,6 +1001,9 @@
const SanitizerOptions &getSanOpts() const { return SanOpts; }
+ void reportGlobalToASan(llvm::GlobalVariable *GV, SourceLocation Loc,
+ bool IsDynInit = false);
+
void addDeferredVTable(const CXXRecordDecl *RD) {
DeferredVTables.push_back(RD);
}
Index: tools/clang/lib/CodeGen/CodeGenModule.cpp
===================================================================
--- tools/clang/lib/CodeGen/CodeGenModule.cpp
+++ tools/clang/lib/CodeGen/CodeGenModule.cpp
@@ -1929,23 +1929,59 @@
if (NeedsGlobalCtor || NeedsGlobalDtor)
EmitCXXGlobalVarDeclInitFunc(D, GV, NeedsGlobalCtor);
- // If we are compiling with ASan, add metadata indicating dynamically
- // initialized (and not blacklisted) globals.
- if (SanOpts.Address && NeedsGlobalCtor &&
- !SanitizerBlacklist->isIn(*GV, "init")) {
- llvm::NamedMDNode *DynamicInitializers = TheModule.getOrInsertNamedMetadata(
- "llvm.asan.dynamically_initialized_globals");
- llvm::Value *GlobalToAdd[] = { GV };
- llvm::MDNode *ThisGlobal = llvm::MDNode::get(VMContext, GlobalToAdd);
- DynamicInitializers->addOperand(ThisGlobal);
- }
+ reportGlobalToASan(GV, D->getLocation(), NeedsGlobalCtor);
// Emit global variable debug information.
if (CGDebugInfo *DI = getModuleDebugInfo())
if (getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo)
DI->EmitGlobalVariable(GV, D);
}
+void CodeGenModule::reportGlobalToASan(llvm::GlobalVariable *GV,
+ SourceLocation Loc, bool IsDynInit) {
+ if (!SanOpts.Address)
+ return;
+ IsDynInit &= !SanitizerBlacklist->isIn(*GV, "init");
+ bool IsBlacklisted = SanitizerBlacklist->isIn(*GV);
+
+ llvm::LLVMContext &LLVMCtx = TheModule.getContext();
+
+ llvm::GlobalVariable *LocDescr = nullptr;
+ if (!IsBlacklisted) {
+ // Don't generate source location if a global is blacklisted - it won't
+ // be instrumented anyway.
+ PresumedLoc PLoc = Context.getSourceManager().getPresumedLoc(Loc);
+ if (PLoc.isValid()) {
+ llvm::Constant *LocData[] = {
+ GetAddrOfConstantCString(PLoc.getFilename()),
+ llvm::ConstantInt::get(llvm::Type::getInt32Ty(LLVMCtx), PLoc.getLine()),
+ llvm::ConstantInt::get(llvm::Type::getInt32Ty(LLVMCtx),
+ PLoc.getColumn()),
+ };
+ auto LocStruct = llvm::ConstantStruct::getAnon(LocData);
+ LocDescr = new llvm::GlobalVariable(TheModule, LocStruct->getType(), true,
+ llvm::GlobalValue::PrivateLinkage,
+ LocStruct, ".asan_loc_descr");
+ LocDescr->setUnnamedAddr(true);
+ // Add LocDescr to llvm.compiler.used, so that it won't be removed by
+ // the optimizer before the ASan instrumentation pass.
+ addCompilerUsedGlobal(LocDescr);
+ }
+ }
+
+ llvm::Value *GlobalMetadata[] = {
+ GV,
+ LocDescr,
+ llvm::ConstantInt::get(llvm::Type::getInt1Ty(LLVMCtx), IsDynInit),
+ llvm::ConstantInt::get(llvm::Type::getInt1Ty(LLVMCtx), IsBlacklisted)
+ };
+
+ llvm::MDNode *ThisGlobal = llvm::MDNode::get(VMContext, GlobalMetadata);
+ llvm::NamedMDNode *AsanGlobals =
+ TheModule.getOrInsertNamedMetadata("llvm.asan.globals");
+ AsanGlobals->addOperand(ThisGlobal);
+}
+
static bool isVarDeclStrongDefinition(const VarDecl *D, bool NoCommon) {
// Don't give variables common linkage if -fno-common was specified unless it
// was overridden by a NoCommon attribute.
@@ -2750,6 +2786,8 @@
auto GV = GenerateStringLiteral(C, LT, *this, GlobalVariableName, Alignment);
if (Entry)
Entry->setValue(GV);
+
+ reportGlobalToASan(GV, S->getStrTokenLoc(0));
return GV;
}
Index: tools/clang/lib/CodeGen/CGDecl.cpp
===================================================================
--- tools/clang/lib/CodeGen/CGDecl.cpp
+++ tools/clang/lib/CodeGen/CGDecl.cpp
@@ -345,6 +345,8 @@
DMEntry = castedAddr;
CGM.setStaticLocalDeclAddress(&D, castedAddr);
+ CGM.reportGlobalToASan(var, D.getLocation());
+
// Emit global variable debug descriptor for static vars.
CGDebugInfo *DI = getDebugInfo();
if (DI &&
Index: tools/clang/test/CodeGen/sanitize-init-order.cpp
===================================================================
--- tools/clang/test/CodeGen/sanitize-init-order.cpp
+++ tools/clang/test/CodeGen/sanitize-init-order.cpp
@@ -27,7 +27,12 @@
// Check that ASan init-order checking ignores structs with trivial default
// constructor.
-// CHECK: !llvm.asan.dynamically_initialized_globals = !{[[GLOB:![0-9]+]]}
-// CHECK: [[GLOB]] = metadata !{%struct.PODWithCtorAndDtor
-
-// BLACKLIST-NOT: llvm.asan.dynamically_initialized_globals
+// CHECK: !llvm.asan.globals = !{![[GLOB_1:[0-9]+]], ![[GLOB_2:[0-9]+]], ![[GLOB_3:[0-9]]]}
+// CHECK: ![[GLOB_1]] = metadata !{%struct.PODStruct* {{.*}}, i1 false, i1 false}
+// CHECK: ![[GLOB_2]] = metadata !{%struct.PODWithDtor* {{.*}}, i1 false, i1 false}
+// CHECK: ![[GLOB_3]] = metadata !{%struct.PODWithCtorAndDtor* {{.*}}, i1 true, i1 false}
+
+// BLACKLIST: !llvm.asan.globals = !{![[GLOB_1:[0-9]+]], ![[GLOB_2:[0-9]+]], ![[GLOB_3:[0-9]]]}
+// BLACKLIST: ![[GLOB_1]] = metadata !{%struct.PODStruct* {{.*}}, i1 false, i1 false}
+// BLACKLIST: ![[GLOB_2]] = metadata !{%struct.PODWithDtor* {{.*}}, i1 false, i1 false}
+// BLACKLIST: ![[GLOB_3]] = metadata !{%struct.PODWithCtorAndDtor* {{.*}}, i1 false, i1 false}
Index: tools/clang/test/CodeGen/asan-globals.cpp
===================================================================
--- /dev/null
+++ tools/clang/test/CodeGen/asan-globals.cpp
@@ -0,0 +1,23 @@
+// RUN: echo "global:*blacklisted_global*" > %t.blacklist
+// RUN: %clang_cc1 -fsanitize=address -fsanitize-blacklist=%t.blacklist -emit-llvm -o - %s | FileCheck %s
+// REQUIRES: shell
+
+int global;
+// CHECK: [[GLOBAL_LOC:@.asan_loc_descr[0-9]*]] = private unnamed_addr constant {{.*}} i32 [[@LINE-1]], i32 5
+int dyn_init_global = global;
+// CHECK: [[DYN_INIT_LOC:@.asan_loc_descr[0-9]*]] = {{.*}} i32 [[@LINE-1]], i32 5
+int blacklisted_global;
+
+void func() {
+ static int static_var = 0;
+ // CHECK: [[STATIC_LOC:@.asan_loc_descr[0-9]*]] = {{.*}} i32 [[@LINE-1]], i32 14
+ const char *literal = "Hello, world!";
+ // CHECK: [[LITERAL_LOC:@.asan_loc_descr[0-9]*]] = {{.*}} i32 [[@LINE-1]], i32 25
+}
+
+// CHECK: !llvm.asan.globals = !{![[GLOBAL:[0-9]+]], ![[DYN_INIT_GLOBAL:[0-9]+]], ![[BLACKLISTED_GLOBAL:[0-9]+]], ![[STATIC_VAR:[0-9]+]], ![[LITERAL:[0-9]+]]}
+// CHECK: ![[GLOBAL]] = metadata !{{{.*}} [[GLOBAL_LOC]], i1 false, i1 false}
+// CHECK: ![[DYN_INIT_GLOBAL]] = metadata !{{{.*}} [[DYN_INIT_LOC]], i1 true, i1 false}
+// CHECK: ![[BLACKLISTED_GLOBAL]] = metadata !{{{.*}}, null, i1 false, i1 true}
+// CHECK: ![[STATIC_VAR]] = metadata !{{{.*}} [[STATIC_LOC]], i1 false, i1 false}
+// CHECK: ![[LITERAL]] = metadata !{{{.*}} [[LITERAL_LOC]], i1 false, i1 false}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits