diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 9bd61d7164f5..91f804193049 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -345,7 +345,7 @@ void CodeGenFunction::EmitStaticVarDecl(const VarDecl &D, DMEntry = castedAddr; CGM.setStaticLocalDeclAddress(&D, castedAddr); - CGM.reportGlobalToASan(var, D.getLocation()); + CGM.reportGlobalToASan(var, D); // Emit global variable debug descriptor for static vars. CGDebugInfo *DI = getDebugInfo(); diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 2f87392c3604..66ac524f2b9a 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1952,7 +1952,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { if (NeedsGlobalCtor || NeedsGlobalDtor) EmitCXXGlobalVarDeclInitFunc(D, GV, NeedsGlobalCtor); - reportGlobalToASan(GV, D->getLocation(), NeedsGlobalCtor); + reportGlobalToASan(GV, *D, NeedsGlobalCtor); // Emit global variable debug information. if (CGDebugInfo *DI = getModuleDebugInfo()) @@ -1961,24 +1961,25 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { } void CodeGenModule::reportGlobalToASan(llvm::GlobalVariable *GV, - SourceLocation Loc, bool IsDynInit) { + SourceLocation Loc, StringRef Name, + bool IsDynInit) { if (!LangOpts.Sanitize.Address) return; IsDynInit &= !SanitizerBL.isIn(*GV, "init"); bool IsBlacklisted = SanitizerBL.isIn(*GV); - llvm::LLVMContext &LLVMCtx = TheModule.getContext(); - llvm::GlobalVariable *LocDescr = nullptr; + llvm::GlobalVariable *GlobalName = nullptr; if (!IsBlacklisted) { - // Don't generate source location if a global is blacklisted - it won't - // be instrumented anyway. + // Don't generate source location and global name if it 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), + llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), + PLoc.getLine()), + llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), PLoc.getColumn()), }; auto LocStruct = llvm::ConstantStruct::getAnon(LocData); @@ -1990,14 +1991,17 @@ void CodeGenModule::reportGlobalToASan(llvm::GlobalVariable *GV, // the optimizer before the ASan instrumentation pass. addCompilerUsedGlobal(LocDescr); } + if (!Name.empty()) { + GlobalName = GetAddrOfConstantCString(Name); + // GlobalName shouldn't be removed by the optimizer. + addCompilerUsedGlobal(GlobalName); + } } llvm::Value *GlobalMetadata[] = { - GV, - LocDescr, - llvm::ConstantInt::get(llvm::Type::getInt1Ty(LLVMCtx), IsDynInit), - llvm::ConstantInt::get(llvm::Type::getInt1Ty(LLVMCtx), IsBlacklisted) - }; + GV, LocDescr, GlobalName, + llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext), IsDynInit), + llvm::ConstantInt::get(llvm::Type::getInt1Ty(VMContext), IsBlacklisted)}; llvm::MDNode *ThisGlobal = llvm::MDNode::get(VMContext, GlobalMetadata); llvm::NamedMDNode *AsanGlobals = @@ -2005,6 +2009,16 @@ void CodeGenModule::reportGlobalToASan(llvm::GlobalVariable *GV, AsanGlobals->addOperand(ThisGlobal); } +void CodeGenModule::reportGlobalToASan(llvm::GlobalVariable *GV, + const VarDecl &D, bool IsDynInit) { + if (!LangOpts.Sanitize.Address) + return; + std::string QualName; + llvm::raw_string_ostream OS(QualName); + D.printQualifiedName(OS); + reportGlobalToASan(GV, D.getLocation(), OS.str(), IsDynInit); +} + 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. @@ -2810,7 +2824,7 @@ CodeGenModule::GetAddrOfConstantStringFromLiteral(const StringLiteral *S) { if (Entry) Entry->setValue(GV); - reportGlobalToASan(GV, S->getStrTokenLoc(0)); + reportGlobalToASan(GV, S->getStrTokenLoc(0), ""); return GV; } diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index 342546974675..d6b694a88246 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -1015,8 +1015,10 @@ public: return SanitizerBL; } - void reportGlobalToASan(llvm::GlobalVariable *GV, SourceLocation Loc, + void reportGlobalToASan(llvm::GlobalVariable *GV, const VarDecl &D, bool IsDynInit = false); + void reportGlobalToASan(llvm::GlobalVariable *GV, SourceLocation Loc, + StringRef Name, bool IsDynInit = false); void addDeferredVTable(const CXXRecordDecl *RD) { DeferredVTables.push_back(RD); diff --git a/clang/test/CodeGen/asan-globals.cpp b/clang/test/CodeGen/asan-globals.cpp index 2702f1d45003..d9ecc6461542 100644 --- a/clang/test/CodeGen/asan-globals.cpp +++ b/clang/test/CodeGen/asan-globals.cpp @@ -6,27 +6,31 @@ int global; // CHECK: [[GLOBAL_LOC:@.asan_loc_descr[0-9]*]] = private unnamed_addr constant {{.*}} i32 [[@LINE-1]], i32 5 +// CHECK: [[GLOBAL_NAME:@.str[0-9]+]] = private unnamed_addr constant {{.*}} c"global\00" int dyn_init_global = global; // CHECK: [[DYN_INIT_LOC:@.asan_loc_descr[0-9]*]] = {{.*}} i32 [[@LINE-1]], i32 5 +// CHECK: [[DYN_INIT_NAME:@.str[0-9]+]] = private unnamed_addr constant {{.*}} c"dyn_init_global\00" int blacklisted_global; void func() { static int static_var = 0; // CHECK: [[STATIC_LOC:@.asan_loc_descr[0-9]*]] = {{.*}} i32 [[@LINE-1]], i32 14 + // CHECK: [[STATIC_NAME:@.str[0-9]+]] = private unnamed_addr constant {{.*}} c"static_var\00" const char *literal = "Hello, world!"; // CHECK: [[LITERAL_LOC:@.asan_loc_descr[0-9]*]] = {{.*}} i32 [[@LINE-1]], i32 25 + // CHECK: [[LITERAL_NAME:@.str[0-9]+]] = private unnamed_addr constant {{.*}} c"\00" } // 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} +// CHECK: ![[GLOBAL]] = metadata !{{{.*}} [[GLOBAL_LOC]], {{.*}} [[GLOBAL_NAME]], i1 false, i1 false} +// CHECK: ![[DYN_INIT_GLOBAL]] = metadata !{{{.*}} [[DYN_INIT_LOC]], {{.*}} [[DYN_INIT_NAME]], i1 true, i1 false} +// CHECK: ![[BLACKLISTED_GLOBAL]] = metadata !{{{.*}}, null, null, i1 false, i1 true} +// CHECK: ![[STATIC_VAR]] = metadata !{{{.*}} [[STATIC_LOC]], {{.*}} [[STATIC_NAME]], i1 false, i1 false} +// CHECK: ![[LITERAL]] = metadata !{{{.*}} [[LITERAL_LOC]], {{.*}} [[LITERAL_NAME]], i1 false, i1 false} // BLACKLIST-SRC: !llvm.asan.globals = !{![[GLOBAL:[0-9]+]], ![[DYN_INIT_GLOBAL:[0-9]+]], ![[BLACKLISTED_GLOBAL:[0-9]+]], ![[STATIC_VAR:[0-9]+]], ![[LITERAL:[0-9]+]]} -// BLACKLIST-SRC: ![[GLOBAL]] = metadata !{{{.*}} null, i1 false, i1 true} -// BLACKLIST-SRC: ![[DYN_INIT_GLOBAL]] = metadata !{{{.*}} null, i1 true, i1 true} -// BLACKLIST-SRC: ![[BLACKLISTED_GLOBAL]] = metadata !{{{.*}}, null, i1 false, i1 true} -// BLACKLIST-SRC: ![[STATIC_VAR]] = metadata !{{{.*}} null, i1 false, i1 true} -// BLACKLIST-SRC: ![[LITERAL]] = metadata !{{{.*}} null, i1 false, i1 true} +// BLACKLIST-SRC: ![[GLOBAL]] = metadata !{{{.*}} null, null, i1 false, i1 true} +// BLACKLIST-SRC: ![[DYN_INIT_GLOBAL]] = metadata !{{{.*}} null, null, i1 true, i1 true} +// BLACKLIST-SRC: ![[BLACKLISTED_GLOBAL]] = metadata !{{{.*}}, null, null, i1 false, i1 true} +// BLACKLIST-SRC: ![[STATIC_VAR]] = metadata !{{{.*}} null, null, i1 false, i1 true} +// BLACKLIST-SRC: ![[LITERAL]] = metadata !{{{.*}} null, null, i1 false, i1 true} diff --git a/compiler-rt/test/asan/TestCases/global-location.cc b/compiler-rt/test/asan/TestCases/global-location.cc index 54f205593b36..2f72bede446e 100644 --- a/compiler-rt/test/asan/TestCases/global-location.cc +++ b/compiler-rt/test/asan/TestCases/global-location.cc @@ -27,7 +27,7 @@ int main(int argc, char **argv) { 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 + // FUNC_STATIC: 0x{{.*}} is located 4 bytes to the right of global variable 'array' defined in '{{.*}}global-location.cc:[[@LINE-1]]:16' {{.*}} of size 40 memset(array, 0, 10); return array[one * 11]; case 'l': diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp index 17cfd92ff271..e42839c9c6b7 100644 --- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -216,8 +216,11 @@ namespace { class GlobalsMetadata { public: struct Entry { - Entry() : SourceLoc(nullptr), IsDynInit(false), IsBlacklisted(false) {} + Entry() + : SourceLoc(nullptr), Name(nullptr), IsDynInit(false), + IsBlacklisted(false) {} GlobalVariable *SourceLoc; + GlobalVariable *Name; bool IsDynInit; bool IsBlacklisted; }; @@ -232,7 +235,7 @@ class GlobalsMetadata { return; for (auto MDN : Globals->operands()) { // Metadata node contains the global and the fields of "Entry". - assert(MDN->getNumOperands() == 4); + assert(MDN->getNumOperands() == 5); Value *V = MDN->getOperand(0); // The optimizer may optimize away a global entirely. if (!V) @@ -246,9 +249,14 @@ class GlobalsMetadata { E.SourceLoc = GVLoc; addSourceLocationGlobal(GVLoc); } - ConstantInt *IsDynInit = cast(MDN->getOperand(2)); + if (Value *Name = MDN->getOperand(2)) { + GlobalVariable *GVName = cast(Name); + E.Name = GVName; + InstrumentationGlobals.insert(GVName); + } + ConstantInt *IsDynInit = cast(MDN->getOperand(3)); E.IsDynInit |= IsDynInit->isOne(); - ConstantInt *IsBlacklisted = cast(MDN->getOperand(3)); + ConstantInt *IsBlacklisted = cast(MDN->getOperand(4)); E.IsBlacklisted |= IsBlacklisted->isOne(); } } @@ -1049,6 +1057,14 @@ bool AddressSanitizerModule::InstrumentGlobals(IRBuilder<> &IRB, Module &M) { for (size_t i = 0; i < n; i++) { static const uint64_t kMaxGlobalRedzone = 1 << 18; GlobalVariable *G = GlobalsToChange[i]; + + auto MD = GlobalsMD.get(G); + // Create string holding the global name unless it was provided by + // the metadata. + GlobalVariable *Name = + MD.Name ? MD.Name : createPrivateGlobalForString(M, G->getName(), + /*AllowMerging*/ true); + PointerType *PtrTy = cast(G->getType()); Type *Ty = PtrTy->getElementType(); uint64_t SizeInBytes = DL->getTypeAllocSize(Ty); @@ -1070,9 +1086,6 @@ bool AddressSanitizerModule::InstrumentGlobals(IRBuilder<> &IRB, Module &M) { NewTy, G->getInitializer(), Constant::getNullValue(RightRedZoneTy), NULL); - GlobalVariable *Name = - createPrivateGlobalForString(M, G->getName(), /*AllowMerging*/true); - // Create a new global variable with enough space for a redzone. GlobalValue::LinkageTypes Linkage = G->getLinkage(); if (G->isConstant() && Linkage == GlobalValue::PrivateLinkage) @@ -1092,8 +1105,6 @@ bool AddressSanitizerModule::InstrumentGlobals(IRBuilder<> &IRB, Module &M) { NewGlobal->takeName(G); G->eraseFromParent(); - auto MD = GlobalsMD.get(G); - Initializers[i] = ConstantStruct::get( GlobalStructTy, ConstantExpr::getPointerCast(NewGlobal, IntptrTy), ConstantInt::get(IntptrTy, SizeInBytes), diff --git a/llvm/test/Instrumentation/AddressSanitizer/global_metadata.ll b/llvm/test/Instrumentation/AddressSanitizer/global_metadata.ll index 9641c3ed4d76..4dcd53b3ad83 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/global_metadata.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/global_metadata.ll @@ -18,12 +18,20 @@ target triple = "x86_64-unknown-linux-gnu" @.asan_loc_descr2 = private unnamed_addr constant { [22 x i8]*, i32, i32 } { [22 x i8]* @.str1, i32 12, i32 14 } @.asan_loc_descr4 = private unnamed_addr constant { [22 x i8]*, i32, i32 } { [22 x i8]* @.str1, i32 14, i32 25 } +; Global names: +@.str2 = private unnamed_addr constant [7 x i8] c"global\00", align 1 +@.str3 = private unnamed_addr constant [16 x i8] c"dyn_init_global\00", align 1 +@.str4 = private unnamed_addr constant [11 x i8] c"static_var\00", align 1 +@.str5 = private unnamed_addr constant [17 x i8] c"\00", align 1 + ; Check that globals were instrumented, but sanitizer location descriptors weren't: ; CHECK: @global = global { i32, [60 x i8] } zeroinitializer, align 32 ; CHECK: @.str = internal unnamed_addr constant { [14 x i8], [50 x i8] } { [14 x i8] c"Hello, world!\00", [50 x i8] zeroinitializer }, align 32 ; CHECK: @.asan_loc_descr = private unnamed_addr constant { [22 x i8]*, i32, i32 } { [22 x i8]* @.str1, i32 5, i32 5 } +; CHECK: @.str2 = private unnamed_addr constant [7 x i8] c"global\00", align 1 -; Check that location decriptors were passed into __asan_register_globals: +; Check that location decriptors and global names were passed into __asan_register_globals: +; CHECK: i64 ptrtoint ([7 x i8]* @.str2 to i64) ; CHECK: i64 ptrtoint ({ [22 x i8]*, i32, i32 }* @.asan_loc_descr to i64) ; Function Attrs: nounwind sanitize_address @@ -55,9 +63,9 @@ attributes #1 = { nounwind sanitize_address "less-precise-fpmad"="false" "no-fra !llvm.asan.globals = !{!0, !1, !2, !3, !4} !llvm.ident = !{!5} -!0 = metadata !{i32* @global, { [22 x i8]*, i32, i32 }* @.asan_loc_descr, i1 false, i1 false} -!1 = metadata !{i32* @dyn_init_global, { [22 x i8]*, i32, i32 }* @.asan_loc_descr1, i1 true, i1 false} -!2 = metadata !{i32* @blacklisted_global, null, i1 false, i1 true} -!3 = metadata !{i32* @_ZZ4funcvE10static_var, { [22 x i8]*, i32, i32 }* @.asan_loc_descr2, i1 false, i1 false} -!4 = metadata !{[14 x i8]* @.str, { [22 x i8]*, i32, i32 }* @.asan_loc_descr4, i1 false, i1 false} +!0 = metadata !{i32* @global, { [22 x i8]*, i32, i32 }* @.asan_loc_descr, [7 x i8]* @.str2, i1 false, i1 false} +!1 = metadata !{i32* @dyn_init_global, { [22 x i8]*, i32, i32 }* @.asan_loc_descr1, [16 x i8]* @.str3, i1 true, i1 false} +!2 = metadata !{i32* @blacklisted_global, null, null, i1 false, i1 true} +!3 = metadata !{i32* @_ZZ4funcvE10static_var, { [22 x i8]*, i32, i32 }* @.asan_loc_descr2, [11 x i8]* @.str4, i1 false, i1 false} +!4 = metadata !{[14 x i8]* @.str, { [22 x i8]*, i32, i32 }* @.asan_loc_descr4, [17 x i8]* @.str5, i1 false, i1 false} !5 = metadata !{metadata !"clang version 3.5.0 (211282)"} diff --git a/llvm/test/Instrumentation/AddressSanitizer/instrument_global.ll b/llvm/test/Instrumentation/AddressSanitizer/instrument_global.ll index 816ab2915660..80791d9a905f 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/instrument_global.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/instrument_global.ll @@ -69,7 +69,7 @@ entry: !llvm.asan.globals = !{!0} -!0 = metadata !{[10 x i32]* @GlobDy, null, i1 true, i1 false} +!0 = metadata !{[10 x i32]* @GlobDy, null, null, i1 true, i1 false} ; CHECK-LABEL: define internal void @asan.module_ctor ; CHECK-NOT: ret diff --git a/llvm/test/Instrumentation/AddressSanitizer/instrument_initializer_metadata.ll b/llvm/test/Instrumentation/AddressSanitizer/instrument_initializer_metadata.ll index 83ff53f6f514..c119879351a9 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/instrument_initializer_metadata.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/instrument_initializer_metadata.ll @@ -7,10 +7,10 @@ target triple = "x86_64-unknown-linux-gnu" @YYY = global i32 0, align 4 ; W/o dynamic initializer. ; Clang will emit the following metadata identifying @xxx as dynamically ; initialized. -!0 = metadata !{i32* @xxx, null, i1 true, i1 false} -!1 = metadata !{i32* @XXX, null, i1 true, i1 false} -!2 = metadata !{i32* @yyy, null, i1 false, i1 false} -!3 = metadata !{i32* @YYY, null, i1 false, i1 false} +!0 = metadata !{i32* @xxx, null, null, i1 true, i1 false} +!1 = metadata !{i32* @XXX, null, null, i1 true, i1 false} +!2 = metadata !{i32* @yyy, null, null, i1 false, i1 false} +!3 = metadata !{i32* @YYY, null, null, i1 false, i1 false} !llvm.asan.globals = !{!0, !1, !2, !3} define i32 @initializer() uwtable {