|
@@ -101,6 +101,10 @@ static const char *const kAsanRegisterImageGlobalsName =
|
|
|
"__asan_register_image_globals";
|
|
|
static const char *const kAsanUnregisterImageGlobalsName =
|
|
|
"__asan_unregister_image_globals";
|
|
|
+static const char *const kAsanRegisterElfGlobalsName =
|
|
|
+ "__asan_register_elf_globals";
|
|
|
+static const char *const kAsanUnregisterElfGlobalsName =
|
|
|
+ "__asan_unregister_elf_globals";
|
|
|
static const char *const kAsanPoisonGlobalsName = "__asan_before_dynamic_init";
|
|
|
static const char *const kAsanUnpoisonGlobalsName = "__asan_after_dynamic_init";
|
|
|
static const char *const kAsanInitName = "__asan_init";
|
|
@@ -120,8 +124,11 @@ static const char *const kAsanPoisonStackMemoryName =
|
|
|
"__asan_poison_stack_memory";
|
|
|
static const char *const kAsanUnpoisonStackMemoryName =
|
|
|
"__asan_unpoison_stack_memory";
|
|
|
+
|
|
|
+// ASan version script has __asan_* wildcard. Triple underscore prevents a
|
|
|
+// linker (gold) warning about attempting to export a local symbol.
|
|
|
static const char *const kAsanGlobalsRegisteredFlagName =
|
|
|
- "__asan_globals_registered";
|
|
|
+ "___asan_globals_registered";
|
|
|
|
|
|
static const char *const kAsanOptionDetectUseAfterReturn =
|
|
|
"__asan_option_detect_stack_use_after_return";
|
|
@@ -610,6 +617,10 @@ private:
|
|
|
void InstrumentGlobalsCOFF(IRBuilder<> &IRB, Module &M,
|
|
|
ArrayRef<GlobalVariable *> ExtendedGlobals,
|
|
|
ArrayRef<Constant *> MetadataInitializers);
|
|
|
+ void InstrumentGlobalsELF(IRBuilder<> &IRB, Module &M,
|
|
|
+ ArrayRef<GlobalVariable *> ExtendedGlobals,
|
|
|
+ ArrayRef<Constant *> MetadataInitializers,
|
|
|
+ const std::string &UniqueModuleId);
|
|
|
void InstrumentGlobalsMachO(IRBuilder<> &IRB, Module &M,
|
|
|
ArrayRef<GlobalVariable *> ExtendedGlobals,
|
|
|
ArrayRef<Constant *> MetadataInitializers);
|
|
@@ -620,7 +631,8 @@ private:
|
|
|
|
|
|
GlobalVariable *CreateMetadataGlobal(Module &M, Constant *Initializer,
|
|
|
StringRef OriginalName);
|
|
|
- void SetComdatForGlobalMetadata(GlobalVariable *G, GlobalVariable *Metadata);
|
|
|
+ void SetComdatForGlobalMetadata(GlobalVariable *G, GlobalVariable *Metadata,
|
|
|
+ StringRef InternalSuffix);
|
|
|
IRBuilder<> CreateAsanModuleDtor(Module &M);
|
|
|
|
|
|
bool ShouldInstrumentGlobal(GlobalVariable *G);
|
|
@@ -645,6 +657,8 @@ private:
|
|
|
Function *AsanUnregisterGlobals;
|
|
|
Function *AsanRegisterImageGlobals;
|
|
|
Function *AsanUnregisterImageGlobals;
|
|
|
+ Function *AsanRegisterElfGlobals;
|
|
|
+ Function *AsanUnregisterElfGlobals;
|
|
|
|
|
|
Function *AsanCtorFunction = nullptr;
|
|
|
Function *AsanDtorFunction = nullptr;
|
|
@@ -1602,12 +1616,22 @@ void AddressSanitizerModule::initializeCallbacks(Module &M) {
|
|
|
checkSanitizerInterfaceFunction(M.getOrInsertFunction(
|
|
|
kAsanUnregisterImageGlobalsName, IRB.getVoidTy(), IntptrTy, nullptr));
|
|
|
AsanUnregisterImageGlobals->setLinkage(Function::ExternalLinkage);
|
|
|
+
|
|
|
+ AsanRegisterElfGlobals = checkSanitizerInterfaceFunction(
|
|
|
+ M.getOrInsertFunction(kAsanRegisterElfGlobalsName, IRB.getVoidTy(),
|
|
|
+ IntptrTy, IntptrTy, IntptrTy, nullptr));
|
|
|
+ AsanRegisterElfGlobals->setLinkage(Function::ExternalLinkage);
|
|
|
+
|
|
|
+ AsanUnregisterElfGlobals = checkSanitizerInterfaceFunction(
|
|
|
+ M.getOrInsertFunction(kAsanUnregisterElfGlobalsName, IRB.getVoidTy(),
|
|
|
+ IntptrTy, IntptrTy, IntptrTy, nullptr));
|
|
|
+ AsanUnregisterElfGlobals->setLinkage(Function::ExternalLinkage);
|
|
|
}
|
|
|
|
|
|
// Put the metadata and the instrumented global in the same group. This ensures
|
|
|
// that the metadata is discarded if the instrumented global is discarded.
|
|
|
void AddressSanitizerModule::SetComdatForGlobalMetadata(
|
|
|
- GlobalVariable *G, GlobalVariable *Metadata) {
|
|
|
+ GlobalVariable *G, GlobalVariable *Metadata, StringRef InternalSuffix) {
|
|
|
Module &M = *G->getParent();
|
|
|
Comdat *C = G->getComdat();
|
|
|
if (!C) {
|
|
@@ -1617,7 +1641,15 @@ void AddressSanitizerModule::SetComdatForGlobalMetadata(
|
|
|
assert(G->hasLocalLinkage());
|
|
|
G->setName(Twine(kAsanGenPrefix) + "_anon_global");
|
|
|
}
|
|
|
- C = M.getOrInsertComdat(G->getName());
|
|
|
+
|
|
|
+ if (!InternalSuffix.empty() && G->hasLocalLinkage()) {
|
|
|
+ std::string Name = G->getName();
|
|
|
+ Name += InternalSuffix;
|
|
|
+ C = M.getOrInsertComdat(Name);
|
|
|
+ } else {
|
|
|
+ C = M.getOrInsertComdat(G->getName());
|
|
|
+ }
|
|
|
+
|
|
|
// Make this IMAGE_COMDAT_SELECT_NODUPLICATES on COFF.
|
|
|
if (TargetTriple.isOSBinFormatCOFF())
|
|
|
C->setSelectionKind(Comdat::NoDuplicates);
|
|
@@ -1671,10 +1703,69 @@ void AddressSanitizerModule::InstrumentGlobalsCOFF(
|
|
|
"global metadata will not be padded appropriately");
|
|
|
Metadata->setAlignment(SizeOfGlobalStruct);
|
|
|
|
|
|
- SetComdatForGlobalMetadata(G, Metadata);
|
|
|
+ SetComdatForGlobalMetadata(G, Metadata, "");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+void AddressSanitizerModule::InstrumentGlobalsELF(
|
|
|
+ IRBuilder<> &IRB, Module &M, ArrayRef<GlobalVariable *> ExtendedGlobals,
|
|
|
+ ArrayRef<Constant *> MetadataInitializers,
|
|
|
+ const std::string &UniqueModuleId) {
|
|
|
+ assert(ExtendedGlobals.size() == MetadataInitializers.size());
|
|
|
+
|
|
|
+ SmallVector<GlobalValue *, 16> MetadataGlobals(ExtendedGlobals.size());
|
|
|
+ for (size_t i = 0; i < ExtendedGlobals.size(); i++) {
|
|
|
+ GlobalVariable *G = ExtendedGlobals[i];
|
|
|
+ GlobalVariable *Metadata =
|
|
|
+ CreateMetadataGlobal(M, MetadataInitializers[i], G->getName());
|
|
|
+ MDNode *MD = MDNode::get(M.getContext(), ValueAsMetadata::get(G));
|
|
|
+ Metadata->setMetadata(LLVMContext::MD_associated, MD);
|
|
|
+ MetadataGlobals[i] = Metadata;
|
|
|
+
|
|
|
+ SetComdatForGlobalMetadata(G, Metadata, UniqueModuleId);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 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);
|
|
|
+
|
|
|
+ // 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
|
|
|
+ // whether registration has already occurred, to prevent duplicate
|
|
|
+ // registration.
|
|
|
+ //
|
|
|
+ // Common linkage ensures that there is only one global per shared library.
|
|
|
+ GlobalVariable *RegisteredFlag = new GlobalVariable(
|
|
|
+ M, IntptrTy, false, GlobalVariable::CommonLinkage,
|
|
|
+ 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 a call to register the globals with the runtime.
|
|
|
+ IRB.CreateCall(AsanRegisterElfGlobals,
|
|
|
+ {IRB.CreatePointerCast(RegisteredFlag, IntptrTy),
|
|
|
+ IRB.CreatePointerCast(StartELFMetadata, IntptrTy),
|
|
|
+ IRB.CreatePointerCast(StopELFMetadata, IntptrTy)});
|
|
|
+
|
|
|
+ // We also need to unregister globals at the end, e.g., when a shared library
|
|
|
+ // gets closed.
|
|
|
+ IRBuilder<> IRB_Dtor = CreateAsanModuleDtor(M);
|
|
|
+ IRB_Dtor.CreateCall(AsanUnregisterElfGlobals,
|
|
|
+ {IRB.CreatePointerCast(RegisteredFlag, IntptrTy),
|
|
|
+ IRB.CreatePointerCast(StartELFMetadata, IntptrTy),
|
|
|
+ IRB.CreatePointerCast(StopELFMetadata, IntptrTy)});
|
|
|
+}
|
|
|
+
|
|
|
void AddressSanitizerModule::InstrumentGlobalsMachO(
|
|
|
IRBuilder<> &IRB, Module &M, ArrayRef<GlobalVariable *> ExtendedGlobals,
|
|
|
ArrayRef<Constant *> MetadataInitializers) {
|
|
@@ -1923,7 +2014,13 @@ bool AddressSanitizerModule::InstrumentGlobals(IRBuilder<> &IRB, Module &M, bool
|
|
|
Initializers[i] = Initializer;
|
|
|
}
|
|
|
|
|
|
- if (TargetTriple.isOSBinFormatCOFF()) {
|
|
|
+ std::string ELFUniqueModuleId =
|
|
|
+ TargetTriple.isOSBinFormatELF() ? getUniqueModuleId(&M) : "";
|
|
|
+
|
|
|
+ if (!ELFUniqueModuleId.empty()) {
|
|
|
+ InstrumentGlobalsELF(IRB, M, NewGlobals, Initializers, ELFUniqueModuleId);
|
|
|
+ *CtorComdat = true;
|
|
|
+ } else if (TargetTriple.isOSBinFormatCOFF()) {
|
|
|
InstrumentGlobalsCOFF(IRB, M, NewGlobals, Initializers);
|
|
|
} else if (ShouldUseMachOGlobalsSection()) {
|
|
|
InstrumentGlobalsMachO(IRB, M, NewGlobals, Initializers);
|