Skip to content
This repository was archived by the owner on Apr 23, 2020. It is now read-only.

Commit 428ffed

Browse files
author
Maxim Ostapenko
committedFeb 8, 2016
[asan] Introduce new hidden -asan-use-private-alias option.
As discussed in google/sanitizers#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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@260075 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent f80c9dd commit 428ffed

File tree

2 files changed

+67
-6
lines changed

2 files changed

+67
-6
lines changed
 

‎lib/Transforms/Instrumentation/AddressSanitizer.cpp

+44-6
Original file line numberDiff line numberDiff line change
@@ -96,14 +96,15 @@ static const char *const kAsanPoisonGlobalsName = "__asan_before_dynamic_init";
9696
static const char *const kAsanUnpoisonGlobalsName = "__asan_after_dynamic_init";
9797
static const char *const kAsanInitName = "__asan_init";
9898
static const char *const kAsanVersionCheckName =
99-
"__asan_version_mismatch_check_v6";
99+
"__asan_version_mismatch_check_v7";
100100
static const char *const kAsanPtrCmp = "__sanitizer_ptr_cmp";
101101
static const char *const kAsanPtrSub = "__sanitizer_ptr_sub";
102102
static const char *const kAsanHandleNoReturnName = "__asan_handle_no_return";
103103
static const int kMaxAsanStackMallocSizeClass = 10;
104104
static const char *const kAsanStackMallocNameTemplate = "__asan_stack_malloc_";
105105
static const char *const kAsanStackFreeNameTemplate = "__asan_stack_free_";
106106
static const char *const kAsanGenPrefix = "__asan_gen_";
107+
static const char *const kODRGenPrefix = "__odr_asan_gen_";
107108
static const char *const kSanCovGenPrefix = "__sancov_gen_";
108109
static const char *const kAsanPoisonStackMemoryName =
109110
"__asan_poison_stack_memory";
@@ -229,6 +230,12 @@ static cl::opt<uint32_t> ClForceExperiment(
229230
cl::desc("Force optimization experiment (for testing)"), cl::Hidden,
230231
cl::init(0));
231232

233+
static cl::opt<bool>
234+
ClUsePrivateAliasForGlobals("asan-use-private-alias",
235+
cl::desc("Use private aliases for global"
236+
" variables"),
237+
cl::Hidden, cl::init(false));
238+
232239
// Debug flags.
233240
static cl::opt<int> ClDebug("asan-debug", cl::desc("debug"), cl::Hidden,
234241
cl::init(0));
@@ -823,7 +830,8 @@ static GlobalVariable *createPrivateGlobalForSourceLoc(Module &M,
823830

824831
static bool GlobalWasGeneratedByAsan(GlobalVariable *G) {
825832
return G->getName().find(kAsanGenPrefix) == 0 ||
826-
G->getName().find(kSanCovGenPrefix) == 0;
833+
G->getName().find(kSanCovGenPrefix) == 0 ||
834+
G->getName().find(kODRGenPrefix) == 0;
827835
}
828836

829837
Value *AddressSanitizer::memToShadow(Value *Shadow, IRBuilder<> &IRB) {
@@ -1321,10 +1329,11 @@ bool AddressSanitizerModule::InstrumentGlobals(IRBuilder<> &IRB, Module &M) {
13211329
// const char *module_name;
13221330
// size_t has_dynamic_init;
13231331
// void *source_location;
1332+
// size_t odr_indicator;
13241333
// We initialize an array of such structures and pass it to a run-time call.
13251334
StructType *GlobalStructTy =
13261335
StructType::get(IntptrTy, IntptrTy, IntptrTy, IntptrTy, IntptrTy,
1327-
IntptrTy, IntptrTy, nullptr);
1336+
IntptrTy, IntptrTy, IntptrTy, nullptr);
13281337
SmallVector<Constant *, 16> Initializers(n);
13291338

13301339
bool HasDynamicallyInitializedGlobals = false;
@@ -1340,10 +1349,11 @@ bool AddressSanitizerModule::InstrumentGlobals(IRBuilder<> &IRB, Module &M) {
13401349
GlobalVariable *G = GlobalsToChange[i];
13411350

13421351
auto MD = GlobalsMD.get(G);
1352+
StringRef NameForGlobal = G->getName();
13431353
// Create string holding the global name (use global name from metadata
13441354
// if it's available, otherwise just write the name of global variable).
13451355
GlobalVariable *Name = createPrivateGlobalForString(
1346-
M, MD.Name.empty() ? G->getName() : MD.Name,
1356+
M, MD.Name.empty() ? NameForGlobal : MD.Name,
13471357
/*AllowMerging*/ true);
13481358

13491359
Type *Ty = G->getValueType();
@@ -1391,13 +1401,41 @@ bool AddressSanitizerModule::InstrumentGlobals(IRBuilder<> &IRB, Module &M) {
13911401
SourceLoc = ConstantInt::get(IntptrTy, 0);
13921402
}
13931403

1404+
Constant *ODRIndicator = ConstantExpr::getNullValue(IRB.getInt8PtrTy());
1405+
GlobalValue *InstrumentedGlobal = NewGlobal;
1406+
1407+
bool CanUsePrivateAliases = TargetTriple.isOSBinFormatELF();
1408+
if (CanUsePrivateAliases && ClUsePrivateAliasForGlobals) {
1409+
// Create local alias for NewGlobal to avoid crash on ODR between
1410+
// instrumented and non-instrumented libraries.
1411+
auto *GA = GlobalAlias::create(GlobalValue::InternalLinkage,
1412+
NameForGlobal + M.getName(), NewGlobal);
1413+
1414+
// With local aliases, we need to provide another externally visible
1415+
// symbol __odr_asan_XXX to detect ODR violation.
1416+
auto *ODRIndicatorSym =
1417+
new GlobalVariable(M, IRB.getInt8Ty(), false, Linkage,
1418+
Constant::getNullValue(IRB.getInt8Ty()),
1419+
kODRGenPrefix + NameForGlobal, nullptr,
1420+
NewGlobal->getThreadLocalMode());
1421+
1422+
// Set meaningful attributes for indicator symbol.
1423+
ODRIndicatorSym->setVisibility(NewGlobal->getVisibility());
1424+
ODRIndicatorSym->setDLLStorageClass(NewGlobal->getDLLStorageClass());
1425+
ODRIndicatorSym->setAlignment(1);
1426+
ODRIndicator = ODRIndicatorSym;
1427+
InstrumentedGlobal = GA;
1428+
}
1429+
13941430
Initializers[i] = ConstantStruct::get(
1395-
GlobalStructTy, ConstantExpr::getPointerCast(NewGlobal, IntptrTy),
1431+
GlobalStructTy,
1432+
ConstantExpr::getPointerCast(InstrumentedGlobal, IntptrTy),
13961433
ConstantInt::get(IntptrTy, SizeInBytes),
13971434
ConstantInt::get(IntptrTy, SizeInBytes + RightRedzoneSize),
13981435
ConstantExpr::getPointerCast(Name, IntptrTy),
13991436
ConstantExpr::getPointerCast(ModuleName, IntptrTy),
1400-
ConstantInt::get(IntptrTy, MD.IsDynInit), SourceLoc, nullptr);
1437+
ConstantInt::get(IntptrTy, MD.IsDynInit), SourceLoc,
1438+
ConstantExpr::getPointerCast(ODRIndicator, IntptrTy), nullptr);
14011439

14021440
if (ClInitializers && MD.IsDynInit) HasDynamicallyInitializedGlobals = true;
14031441

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
; RUN: opt < %s -asan -asan-module -asan-use-private-alias=1 -S | FileCheck %s
2+
3+
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
4+
target triple = "x86_64-unknown-linux-gnu"
5+
6+
@a = internal global [2 x i32] zeroinitializer, align 4
7+
8+
; Check that we generate internal alias and odr indicator symbols for global to be protected.
9+
; CHECK: @__odr_asan_gen_a = internal global i8 0, align 1
10+
; CHECK: @"a<stdin>" = internal alias { [2 x i32], [56 x i8] }, { [2 x i32], [56 x i8] }* @a
11+
12+
; Function Attrs: nounwind sanitize_address uwtable
13+
define i32 @foo(i32 %M) #0 {
14+
entry:
15+
%M.addr = alloca i32, align 4
16+
store i32 %M, i32* %M.addr, align 4
17+
store volatile i32 6, i32* getelementptr inbounds ([2 x i32], [2 x i32]* @a, i64 2, i64 0), align 4
18+
%0 = load i32, i32* %M.addr, align 4
19+
%idxprom = sext i32 %0 to i64
20+
%arrayidx = getelementptr inbounds [2 x i32], [2 x i32]* @a, i64 0, i64 %idxprom
21+
%1 = load volatile i32, i32* %arrayidx, align 4
22+
ret i32 %1
23+
}

0 commit comments

Comments
 (0)
This repository has been archived.