summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp50
-rw-r--r--llvm/test/Instrumentation/AddressSanitizer/local_alias.ll23
2 files changed, 67 insertions, 6 deletions
diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
index a3788af3de7..2f404fe1626 100644
--- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -96,7 +96,7 @@ 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";
static const char *const kAsanVersionCheckName =
- "__asan_version_mismatch_check_v6";
+ "__asan_version_mismatch_check_v7";
static const char *const kAsanPtrCmp = "__sanitizer_ptr_cmp";
static const char *const kAsanPtrSub = "__sanitizer_ptr_sub";
static const char *const kAsanHandleNoReturnName = "__asan_handle_no_return";
@@ -104,6 +104,7 @@ static const int kMaxAsanStackMallocSizeClass = 10;
static const char *const kAsanStackMallocNameTemplate = "__asan_stack_malloc_";
static const char *const kAsanStackFreeNameTemplate = "__asan_stack_free_";
static const char *const kAsanGenPrefix = "__asan_gen_";
+static const char *const kODRGenPrefix = "__odr_asan_gen_";
static const char *const kSanCovGenPrefix = "__sancov_gen_";
static const char *const kAsanPoisonStackMemoryName =
"__asan_poison_stack_memory";
@@ -229,6 +230,12 @@ static cl::opt<uint32_t> ClForceExperiment(
cl::desc("Force optimization experiment (for testing)"), cl::Hidden,
cl::init(0));
+static cl::opt<bool>
+ ClUsePrivateAliasForGlobals("asan-use-private-alias",
+ cl::desc("Use private aliases for global"
+ " variables"),
+ cl::Hidden, cl::init(false));
+
// Debug flags.
static cl::opt<int> ClDebug("asan-debug", cl::desc("debug"), cl::Hidden,
cl::init(0));
@@ -823,7 +830,8 @@ static GlobalVariable *createPrivateGlobalForSourceLoc(Module &M,
static bool GlobalWasGeneratedByAsan(GlobalVariable *G) {
return G->getName().find(kAsanGenPrefix) == 0 ||
- G->getName().find(kSanCovGenPrefix) == 0;
+ G->getName().find(kSanCovGenPrefix) == 0 ||
+ G->getName().find(kODRGenPrefix) == 0;
}
Value *AddressSanitizer::memToShadow(Value *Shadow, IRBuilder<> &IRB) {
@@ -1321,10 +1329,11 @@ bool AddressSanitizerModule::InstrumentGlobals(IRBuilder<> &IRB, Module &M) {
// const char *module_name;
// size_t has_dynamic_init;
// void *source_location;
+ // size_t odr_indicator;
// We initialize an array of such structures and pass it to a run-time call.
StructType *GlobalStructTy =
StructType::get(IntptrTy, IntptrTy, IntptrTy, IntptrTy, IntptrTy,
- IntptrTy, IntptrTy, nullptr);
+ IntptrTy, IntptrTy, IntptrTy, nullptr);
SmallVector<Constant *, 16> Initializers(n);
bool HasDynamicallyInitializedGlobals = false;
@@ -1340,10 +1349,11 @@ bool AddressSanitizerModule::InstrumentGlobals(IRBuilder<> &IRB, Module &M) {
GlobalVariable *G = GlobalsToChange[i];
auto MD = GlobalsMD.get(G);
+ StringRef NameForGlobal = G->getName();
// Create string holding the global name (use global name from metadata
// if it's available, otherwise just write the name of global variable).
GlobalVariable *Name = createPrivateGlobalForString(
- M, MD.Name.empty() ? G->getName() : MD.Name,
+ M, MD.Name.empty() ? NameForGlobal : MD.Name,
/*AllowMerging*/ true);
Type *Ty = G->getValueType();
@@ -1391,13 +1401,41 @@ bool AddressSanitizerModule::InstrumentGlobals(IRBuilder<> &IRB, Module &M) {
SourceLoc = ConstantInt::get(IntptrTy, 0);
}
+ Constant *ODRIndicator = ConstantExpr::getNullValue(IRB.getInt8PtrTy());
+ GlobalValue *InstrumentedGlobal = NewGlobal;
+
+ bool CanUsePrivateAliases = TargetTriple.isOSBinFormatELF();
+ if (CanUsePrivateAliases && ClUsePrivateAliasForGlobals) {
+ // Create local alias for NewGlobal to avoid crash on ODR between
+ // instrumented and non-instrumented libraries.
+ auto *GA = GlobalAlias::create(GlobalValue::InternalLinkage,
+ NameForGlobal + M.getName(), NewGlobal);
+
+ // With local aliases, we need to provide another externally visible
+ // symbol __odr_asan_XXX to detect ODR violation.
+ auto *ODRIndicatorSym =
+ new GlobalVariable(M, IRB.getInt8Ty(), false, Linkage,
+ Constant::getNullValue(IRB.getInt8Ty()),
+ kODRGenPrefix + NameForGlobal, nullptr,
+ NewGlobal->getThreadLocalMode());
+
+ // Set meaningful attributes for indicator symbol.
+ ODRIndicatorSym->setVisibility(NewGlobal->getVisibility());
+ ODRIndicatorSym->setDLLStorageClass(NewGlobal->getDLLStorageClass());
+ ODRIndicatorSym->setAlignment(1);
+ ODRIndicator = ODRIndicatorSym;
+ InstrumentedGlobal = GA;
+ }
+
Initializers[i] = ConstantStruct::get(
- GlobalStructTy, ConstantExpr::getPointerCast(NewGlobal, IntptrTy),
+ GlobalStructTy,
+ ConstantExpr::getPointerCast(InstrumentedGlobal, IntptrTy),
ConstantInt::get(IntptrTy, SizeInBytes),
ConstantInt::get(IntptrTy, SizeInBytes + RightRedzoneSize),
ConstantExpr::getPointerCast(Name, IntptrTy),
ConstantExpr::getPointerCast(ModuleName, IntptrTy),
- ConstantInt::get(IntptrTy, MD.IsDynInit), SourceLoc, nullptr);
+ ConstantInt::get(IntptrTy, MD.IsDynInit), SourceLoc,
+ ConstantExpr::getPointerCast(ODRIndicator, IntptrTy), nullptr);
if (ClInitializers && MD.IsDynInit) HasDynamicallyInitializedGlobals = true;
diff --git a/llvm/test/Instrumentation/AddressSanitizer/local_alias.ll b/llvm/test/Instrumentation/AddressSanitizer/local_alias.ll
new file mode 100644
index 00000000000..3db241d097f
--- /dev/null
+++ b/llvm/test/Instrumentation/AddressSanitizer/local_alias.ll
@@ -0,0 +1,23 @@
+; RUN: opt < %s -asan -asan-module -asan-use-private-alias=1 -S | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+@a = internal global [2 x i32] zeroinitializer, align 4
+
+; Check that we generate internal alias and odr indicator symbols for global to be protected.
+; CHECK: @__odr_asan_gen_a = internal global i8 0, align 1
+; CHECK: @"a<stdin>" = internal alias { [2 x i32], [56 x i8] }, { [2 x i32], [56 x i8] }* @a
+
+; Function Attrs: nounwind sanitize_address uwtable
+define i32 @foo(i32 %M) #0 {
+entry:
+ %M.addr = alloca i32, align 4
+ store i32 %M, i32* %M.addr, align 4
+ store volatile i32 6, i32* getelementptr inbounds ([2 x i32], [2 x i32]* @a, i64 2, i64 0), align 4
+ %0 = load i32, i32* %M.addr, align 4
+ %idxprom = sext i32 %0 to i64
+ %arrayidx = getelementptr inbounds [2 x i32], [2 x i32]* @a, i64 0, i64 %idxprom
+ %1 = load volatile i32, i32* %arrayidx, align 4
+ ret i32 %1
+}
OpenPOWER on IntegriCloud