aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPetr Hosek <phosek@google.com>2020-06-04 20:18:35 -0700
committerPetr Hosek <phosek@google.com>2020-06-04 20:18:35 -0700
commitd76e62fdb7a93d9a33f642b6b528f2562cc3c3f4 (patch)
treebaa6e108faaf722521001c9a0254c6b65c41f7a6
parente5158b52730d323bb8cd2cba6dc6c89b90cba452 (diff)
downloadllvm-d76e62fdb7a93d9a33f642b6b528f2562cc3c3f4.zip
llvm-d76e62fdb7a93d9a33f642b6b528f2562cc3c3f4.tar.gz
llvm-d76e62fdb7a93d9a33f642b6b528f2562cc3c3f4.tar.bz2
[AddressSanitizer] Don't use weak linkage for __{start,stop}_asan_globals
It should not be necessary to use weak linkage for these. Doing so implies interposablity and thus PIC generates indirections and dynamic relocations, which are unnecessary and suboptimal. Aside from this, ASan instrumentation never introduces GOT indirection relocations where there were none before--only new absolute relocs in RELRO sections for metadata, which are less problematic for special linkage situations that take pains to avoid GOT generation. Patch By: mcgrathr Differential Revision: https://reviews.llvm.org/D80605
-rw-r--r--llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp38
-rw-r--r--llvm/test/Instrumentation/AddressSanitizer/global_metadata.ll4
2 files changed, 31 insertions, 11 deletions
diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
index 816b8b1..f622702 100644
--- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -2072,10 +2072,23 @@ void ModuleAddressSanitizer::InstrumentGlobalsELF(
SetComdatForGlobalMetadata(G, Metadata, UniqueModuleId);
}
+ // This should never be called when there are no globals, by the logic that
+ // computes the UniqueModuleId string, which is "" when there are no globals.
+ // It's important that this path is only used when there are actually some
+ // globals, because that means that there will certainly be a live
+ // `asan_globals` input section at link time and thus `__start_asan_globals`
+ // and `__stop_asan_globals` symbols will definitely be defined at link time.
+ // This means there's no need for the references to them to be weak, which
+ // enables better code generation because ExternalWeakLinkage implies
+ // isInterposable() and thus requires GOT indirection for PIC. Since these
+ // are known-defined hidden/dso_local symbols, direct PIC accesses without
+ // dynamic relocation are always sufficient.
+ assert(!MetadataGlobals.empty());
+ assert(!UniqueModuleId.empty());
+
// Update llvm.compiler.used, adding the new metadata globals. This is
// needed so that during LTO these variables stay alive.
- if (!MetadataGlobals.empty())
- appendToCompilerUsed(M, MetadataGlobals);
+ appendToCompilerUsed(M, MetadataGlobals);
// RegisteredFlag serves two purposes. First, we can pass it to dladdr()
// to look up the loaded image that contains it. Second, we can store in it
@@ -2088,15 +2101,18 @@ void ModuleAddressSanitizer::InstrumentGlobalsELF(
ConstantInt::get(IntptrTy, 0), kAsanGlobalsRegisteredFlagName);
RegisteredFlag->setVisibility(GlobalVariable::HiddenVisibility);
- // Create start and stop symbols.
- GlobalVariable *StartELFMetadata = new GlobalVariable(
- M, IntptrTy, false, GlobalVariable::ExternalWeakLinkage, nullptr,
- "__start_" + getGlobalMetadataSection());
- StartELFMetadata->setVisibility(GlobalVariable::HiddenVisibility);
- GlobalVariable *StopELFMetadata = new GlobalVariable(
- M, IntptrTy, false, GlobalVariable::ExternalWeakLinkage, nullptr,
- "__stop_" + getGlobalMetadataSection());
- StopELFMetadata->setVisibility(GlobalVariable::HiddenVisibility);
+ // Create start and stop symbols. These are known to be defined by
+ // the linker, see comment above.
+ auto MakeStartStopGV = [&](const char *Prefix) {
+ GlobalVariable *StartStop =
+ new GlobalVariable(M, IntptrTy, false, GlobalVariable::ExternalLinkage,
+ nullptr, Prefix + getGlobalMetadataSection());
+ StartStop->setVisibility(GlobalVariable::HiddenVisibility);
+ assert(StartStop->isImplicitDSOLocal());
+ return StartStop;
+ };
+ GlobalVariable *StartELFMetadata = MakeStartStopGV("__start_");
+ GlobalVariable *StopELFMetadata = MakeStartStopGV("__stop_");
// Create a call to register the globals with the runtime.
IRB.CreateCall(AsanRegisterElfGlobals,
diff --git a/llvm/test/Instrumentation/AddressSanitizer/global_metadata.ll b/llvm/test/Instrumentation/AddressSanitizer/global_metadata.ll
index ea9f2cf..4a6f426 100644
--- a/llvm/test/Instrumentation/AddressSanitizer/global_metadata.ll
+++ b/llvm/test/Instrumentation/AddressSanitizer/global_metadata.ll
@@ -28,6 +28,10 @@ target triple = "x86_64-unknown-linux-gnu"
; during LTO.
; CHECK: @llvm.compiler.used {{.*}} @__asan_global_global {{.*}} section "llvm.metadata"
+; Check that start and stop symbols will be accessed as dso_local.
+; CHECK: @__start_asan_globals = external hidden global i64
+; CHECK: @__stop_asan_globals = external hidden global i64
+
; Check that location descriptors and global names were passed into __asan_register_globals:
; CHECK: call void @__asan_register_elf_globals(i64 ptrtoint (i64* @___asan_globals_registered to i64), i64 ptrtoint (i64* @__start_asan_globals to i64), i64 ptrtoint (i64* @__stop_asan_globals to i64))