From 090f75dc839cbe1d94c8445bf8fabd0f19309f25 Mon Sep 17 00:00:00 2001 From: Mehdi Amini Date: Sat, 1 Oct 2016 00:05:34 +0000 Subject: [PATCH] [ASAN] Add the binder globals on Darwin to llvm.compiler.used to avoid LTO dead-stripping The binder is in a specific section that "reverse" the edges in a regular dead-stripping: the binder is live as long as a global it references is live. This is a big hammer that prevents LLVM from dead-stripping these, while still allowing linker dead-stripping (with special knowledge of the section). Differential Revision: https://reviews.llvm.org/D24673 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@282988 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Instrumentation/AddressSanitizer.cpp | 36 ++++++++++++++++++++-- .../AddressSanitizer/global_metadata_darwin.ll | 7 ++++- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/lib/Transforms/Instrumentation/AddressSanitizer.cpp index 07e63b2a7df..7db1a434937 100644 --- a/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -1626,6 +1626,10 @@ bool AddressSanitizerModule::InstrumentGlobals(IRBuilder<> &IRB, Module &M) { // variable to the metadata struct. StructType *LivenessTy = StructType::get(IntptrTy, IntptrTy, nullptr); + // Keep the list of "Liveness" GV created to be added to llvm.compiler.used + SmallVector LivenessGlobals; + LivenessGlobals.reserve(n); + for (size_t i = 0; i < n; i++) { GlobalVariable *Metadata = new GlobalVariable( M, GlobalStructTy, false, GlobalVariable::InternalLinkage, @@ -1637,10 +1641,38 @@ bool AddressSanitizerModule::InstrumentGlobals(IRBuilder<> &IRB, Module &M) { Initializers[i]->getAggregateElement(0u), ConstantExpr::getPointerCast(Metadata, IntptrTy), nullptr); + + // Recover the name of the variable this global is pointing to + StringRef GVName = + Initializers[i]->getAggregateElement(0u)->getOperand(0)->getName(); + GlobalVariable *Liveness = new GlobalVariable( - M, LivenessTy, false, GlobalVariable::InternalLinkage, - LivenessBinder, ""); + M, LivenessTy, false, GlobalVariable::InternalLinkage, LivenessBinder, + Twine("__asan_binder_") + GVName); Liveness->setSection("__DATA,__asan_liveness,regular,live_support"); + LivenessGlobals.push_back( + ConstantExpr::getBitCast(Liveness, IRB.getInt8PtrTy())); + } + + if (!LivenessGlobals.empty()) { + // Update llvm.compiler.used, adding the new liveness globals. This is + // needed so that during LTO these variables stay alive. The alternative + // would be to have the linker handling the LTO symbols, but libLTO + // current + // API does not expose access to the section for each symbol. + if (GlobalVariable *LLVMUsed = + M.getGlobalVariable("llvm.compiler.used")) { + ConstantArray *Inits = cast(LLVMUsed->getInitializer()); + for (auto &V : Inits->operands()) + LivenessGlobals.push_back(cast(&V)); + LLVMUsed->eraseFromParent(); + } + llvm::ArrayType *ATy = + llvm::ArrayType::get(IRB.getInt8PtrTy(), LivenessGlobals.size()); + auto *LLVMUsed = new llvm::GlobalVariable( + M, ATy, false, llvm::GlobalValue::AppendingLinkage, + llvm::ConstantArray::get(ATy, LivenessGlobals), "llvm.compiler.used"); + LLVMUsed->setSection("llvm.metadata"); } } else { // On all other platfoms, we just emit an array of global metadata diff --git a/test/Instrumentation/AddressSanitizer/global_metadata_darwin.ll b/test/Instrumentation/AddressSanitizer/global_metadata_darwin.ll index ea0daee3515..25b76405a1c 100644 --- a/test/Instrumentation/AddressSanitizer/global_metadata_darwin.ll +++ b/test/Instrumentation/AddressSanitizer/global_metadata_darwin.ll @@ -22,7 +22,12 @@ target triple = "x86_64-apple-macosx10.11.0" ; CHECK: [[METADATA:@[0-9]+]] = internal global {{.*}} @global {{.*}} section "__DATA,__asan_globals,regular", align 1 ; Find the liveness binder for @global and its metadata: -; CHECK: @{{[0-9]+}} = internal global {{.*}} @global {{.*}} [[METADATA]] {{.*}} section "__DATA,__asan_liveness,regular,live_support" +; CHECK: @__asan_binder_global = internal global {{.*}} @global {{.*}} [[METADATA]] {{.*}} section "__DATA,__asan_liveness,regular,live_support" + +; The binder has to be inserted to llvm.compiler.used to avoid being stripped +; during LTO. +; CHECK: @llvm.compiler.used {{.*}} @__asan_binder_global {{.*}} section "llvm.metadata" + ; Test that __asan_register_image_globals is invoked from the constructor: ; CHECK-LABEL: define internal void @asan.module_ctor -- 2.11.0