Index: lib/Transforms/Instrumentation/AddressSanitizer.cpp =================================================================== --- lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -101,6 +101,7 @@ 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_gen_"; static const char *const kSanCovGenPrefix = "__sancov_gen_"; static const char *const kAsanPoisonStackMemoryName = "__asan_poison_stack_memory"; @@ -226,6 +227,12 @@ cl::desc("Force optimization experiment (for testing)"), cl::Hidden, cl::init(0)); +static cl::opt + ClUsePrivateAliasForGlobals("asan-use-private-alias", + cl::desc("Use private aliases for global" + " variables"), + cl::Hidden, cl::init(false)); + // Debug flags. static cl::opt ClDebug("asan-debug", cl::desc("debug"), cl::Hidden, cl::init(0)); @@ -815,7 +822,8 @@ 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) { @@ -1307,6 +1315,7 @@ // A global is described by a structure // size_t beg; + // size_t odr_indicator; // size_t size; // size_t size_with_redzone; // const char *name; @@ -1316,7 +1325,7 @@ // 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 Initializers(n); bool HasDynamicallyInitializedGlobals = false; @@ -1332,10 +1341,11 @@ 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(); @@ -1383,8 +1393,33 @@ SourceLoc = ConstantInt::get(IntptrTy, 0); } + Constant *ODRIndicator = ConstantExpr::getNullValue(IntptrTy); + GlobalValue *InstrumentedGlobal = NewGlobal; + + if (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_genXXX to detect ODR violation. + auto *ODRIndicatorSym = + new GlobalVariable(M, IRB.getInt8Ty(), false, Linkage, + Constant::getNullValue(IRB.getInt8Ty()), + kODRGenPrefix + NameForGlobal, nullptr, + NewGlobal->getThreadLocalMode()); + + ODRIndicatorSym->copyAttributesFrom(NewGlobal); + ODRIndicator = ODRIndicatorSym; + InstrumentedGlobal = GA; + } + Initializers[i] = ConstantStruct::get( - GlobalStructTy, ConstantExpr::getPointerCast(NewGlobal, IntptrTy), + GlobalStructTy, + ConstantExpr::getPointerCast(InstrumentedGlobal, IntptrTy), + ConstantExpr::getPointerCast(ODRIndicator, IntptrTy), ConstantInt::get(IntptrTy, SizeInBytes), ConstantInt::get(IntptrTy, SizeInBytes + RightRedzoneSize), ConstantExpr::getPointerCast(Name, IntptrTy),