mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-09 05:47:13 +00:00
[asan] Introduce new hidden -asan-use-private-alias option.
As discussed in https://github.com/google/sanitizers/issues/398, with current implementation of poisoning globals we can have some CHECK failures or false positives in case of mixing instrumented and non-instrumented code due to ASan poisons innocent globals from non-sanitized binary/library. We can use private aliases to avoid such errors. In addition, to preserve ODR violation detection, we introduce new __odr_asan_gen_XXX symbol for each instrumented global that indicates if this global was already registered. To detect ODR violation in runtime, we should only check the value of indicator and report an error if it isn't equal to zero. Differential Revision: http://reviews.llvm.org/D15642 llvm-svn: 260075
This commit is contained in:
parent
33dc7c1040
commit
fce986a506
@ -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;
|
||||
|
||||
|
23
test/Instrumentation/AddressSanitizer/local_alias.ll
Normal file
23
test/Instrumentation/AddressSanitizer/local_alias.ll
Normal file
@ -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
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user