llvm.org GIT mirror llvm / 428ffed
[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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@260075 91177308-0d34-0410-b5e6-96231b3b80d8 Maxim Ostapenko 4 years ago
2 changed file(s) with 67 addition(s) and 6 deletion(s). Raw diff Collapse all Expand all
9595 static const char *const kAsanUnpoisonGlobalsName = "__asan_after_dynamic_init";
9696 static const char *const kAsanInitName = "__asan_init";
9797 static const char *const kAsanVersionCheckName =
98 "__asan_version_mismatch_check_v6";
98 "__asan_version_mismatch_check_v7";
9999 static const char *const kAsanPtrCmp = "__sanitizer_ptr_cmp";
100100 static const char *const kAsanPtrSub = "__sanitizer_ptr_sub";
101101 static const char *const kAsanHandleNoReturnName = "__asan_handle_no_return";
103103 static const char *const kAsanStackMallocNameTemplate = "__asan_stack_malloc_";
104104 static const char *const kAsanStackFreeNameTemplate = "__asan_stack_free_";
105105 static const char *const kAsanGenPrefix = "__asan_gen_";
106 static const char *const kODRGenPrefix = "__odr_asan_gen_";
106107 static const char *const kSanCovGenPrefix = "__sancov_gen_";
107108 static const char *const kAsanPoisonStackMemoryName =
108109 "__asan_poison_stack_memory";
228229 cl::desc("Force optimization experiment (for testing)"), cl::Hidden,
229230 cl::init(0));
230231
232 static cl::opt
233 ClUsePrivateAliasForGlobals("asan-use-private-alias",
234 cl::desc("Use private aliases for global"
235 " variables"),
236 cl::Hidden, cl::init(false));
237
231238 // Debug flags.
232239 static cl::opt ClDebug("asan-debug", cl::desc("debug"), cl::Hidden,
233240 cl::init(0));
822829
823830 static bool GlobalWasGeneratedByAsan(GlobalVariable *G) {
824831 return G->getName().find(kAsanGenPrefix) == 0 ||
825 G->getName().find(kSanCovGenPrefix) == 0;
832 G->getName().find(kSanCovGenPrefix) == 0 ||
833 G->getName().find(kODRGenPrefix) == 0;
826834 }
827835
828836 Value *AddressSanitizer::memToShadow(Value *Shadow, IRBuilder<> &IRB) {
13201328 // const char *module_name;
13211329 // size_t has_dynamic_init;
13221330 // void *source_location;
1331 // size_t odr_indicator;
13231332 // We initialize an array of such structures and pass it to a run-time call.
13241333 StructType *GlobalStructTy =
13251334 StructType::get(IntptrTy, IntptrTy, IntptrTy, IntptrTy, IntptrTy,
1326 IntptrTy, IntptrTy, nullptr);
1335 IntptrTy, IntptrTy, IntptrTy, nullptr);
13271336 SmallVector Initializers(n);
13281337
13291338 bool HasDynamicallyInitializedGlobals = false;
13391348 GlobalVariable *G = GlobalsToChange[i];
13401349
13411350 auto MD = GlobalsMD.get(G);
1351 StringRef NameForGlobal = G->getName();
13421352 // Create string holding the global name (use global name from metadata
13431353 // if it's available, otherwise just write the name of global variable).
13441354 GlobalVariable *Name = createPrivateGlobalForString(
1345 M, MD.Name.empty() ? G->getName() : MD.Name,
1355 M, MD.Name.empty() ? NameForGlobal : MD.Name,
13461356 /*AllowMerging*/ true);
13471357
13481358 Type *Ty = G->getValueType();
13901400 SourceLoc = ConstantInt::get(IntptrTy, 0);
13911401 }
13921402
1403 Constant *ODRIndicator = ConstantExpr::getNullValue(IRB.getInt8PtrTy());
1404 GlobalValue *InstrumentedGlobal = NewGlobal;
1405
1406 bool CanUsePrivateAliases = TargetTriple.isOSBinFormatELF();
1407 if (CanUsePrivateAliases && ClUsePrivateAliasForGlobals) {
1408 // Create local alias for NewGlobal to avoid crash on ODR between
1409 // instrumented and non-instrumented libraries.
1410 auto *GA = GlobalAlias::create(GlobalValue::InternalLinkage,
1411 NameForGlobal + M.getName(), NewGlobal);
1412
1413 // With local aliases, we need to provide another externally visible
1414 // symbol __odr_asan_XXX to detect ODR violation.
1415 auto *ODRIndicatorSym =
1416 new GlobalVariable(M, IRB.getInt8Ty(), false, Linkage,
1417 Constant::getNullValue(IRB.getInt8Ty()),
1418 kODRGenPrefix + NameForGlobal, nullptr,
1419 NewGlobal->getThreadLocalMode());
1420
1421 // Set meaningful attributes for indicator symbol.
1422 ODRIndicatorSym->setVisibility(NewGlobal->getVisibility());
1423 ODRIndicatorSym->setDLLStorageClass(NewGlobal->getDLLStorageClass());
1424 ODRIndicatorSym->setAlignment(1);
1425 ODRIndicator = ODRIndicatorSym;
1426 InstrumentedGlobal = GA;
1427 }
1428
13931429 Initializers[i] = ConstantStruct::get(
1394 GlobalStructTy, ConstantExpr::getPointerCast(NewGlobal, IntptrTy),
1430 GlobalStructTy,
1431 ConstantExpr::getPointerCast(InstrumentedGlobal, IntptrTy),
13951432 ConstantInt::get(IntptrTy, SizeInBytes),
13961433 ConstantInt::get(IntptrTy, SizeInBytes + RightRedzoneSize),
13971434 ConstantExpr::getPointerCast(Name, IntptrTy),
13981435 ConstantExpr::getPointerCast(ModuleName, IntptrTy),
1399 ConstantInt::get(IntptrTy, MD.IsDynInit), SourceLoc, nullptr);
1436 ConstantInt::get(IntptrTy, MD.IsDynInit), SourceLoc,
1437 ConstantExpr::getPointerCast(ODRIndicator, IntptrTy), nullptr);
14001438
14011439 if (ClInitializers && MD.IsDynInit) HasDynamicallyInitializedGlobals = true;
14021440
0 ; RUN: opt < %s -asan -asan-module -asan-use-private-alias=1 -S | FileCheck %s
1
2 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
3 target triple = "x86_64-unknown-linux-gnu"
4
5 @a = internal global [2 x i32] zeroinitializer, align 4
6
7 ; Check that we generate internal alias and odr indicator symbols for global to be protected.
8 ; CHECK: @__odr_asan_gen_a = internal global i8 0, align 1
9 ; CHECK: @"a" = internal alias { [2 x i32], [56 x i8] }, { [2 x i32], [56 x i8] }* @a
10
11 ; Function Attrs: nounwind sanitize_address uwtable
12 define i32 @foo(i32 %M) #0 {
13 entry:
14 %M.addr = alloca i32, align 4
15 store i32 %M, i32* %M.addr, align 4
16 store volatile i32 6, i32* getelementptr inbounds ([2 x i32], [2 x i32]* @a, i64 2, i64 0), align 4
17 %0 = load i32, i32* %M.addr, align 4
18 %idxprom = sext i32 %0 to i64
19 %arrayidx = getelementptr inbounds [2 x i32], [2 x i32]* @a, i64 0, i64 %idxprom
20 %1 = load volatile i32, i32* %arrayidx, align 4
21 ret i32 %1
22 }