diff options
Diffstat (limited to 'lib/Transforms/Instrumentation/DataFlowSanitizer.cpp')
-rw-r--r-- | lib/Transforms/Instrumentation/DataFlowSanitizer.cpp | 58 |
1 files changed, 51 insertions, 7 deletions
diff --git a/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp b/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp index 7159cc0499..9a46911751 100644 --- a/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp +++ b/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp @@ -179,11 +179,13 @@ class DataFlowSanitizer : public ModulePass { Value *getShadowAddress(Value *Addr, Instruction *Pos); Value *combineShadows(Value *V1, Value *V2, Instruction *Pos); - bool isInstrumented(Function *F); + bool isInstrumented(const Function *F); + bool isInstrumented(const GlobalAlias *GA); FunctionType *getArgsFunctionType(FunctionType *T); FunctionType *getCustomFunctionType(FunctionType *T); InstrumentedABI getInstrumentedABI(); WrapperKind getWrapperKind(Function *F); + void addGlobalNamePrefix(GlobalValue *GV); public: DataFlowSanitizer(StringRef ABIListFile = StringRef(), @@ -343,10 +345,14 @@ bool DataFlowSanitizer::doInitialization(Module &M) { return true; } -bool DataFlowSanitizer::isInstrumented(Function *F) { +bool DataFlowSanitizer::isInstrumented(const Function *F) { return !ABIList->isIn(*F, "uninstrumented"); } +bool DataFlowSanitizer::isInstrumented(const GlobalAlias *GA) { + return !ABIList->isIn(*GA, "uninstrumented"); +} + DataFlowSanitizer::InstrumentedABI DataFlowSanitizer::getInstrumentedABI() { return ClArgsABI ? IA_Args : IA_TLS; } @@ -362,6 +368,25 @@ DataFlowSanitizer::WrapperKind DataFlowSanitizer::getWrapperKind(Function *F) { return WK_Warning; } +void DataFlowSanitizer::addGlobalNamePrefix(GlobalValue *GV) { + std::string GVName = GV->getName(), Prefix = "dfs$"; + GV->setName(Prefix + GVName); + + // Try to change the name of the function in module inline asm. We only do + // this for specific asm directives, currently only ".symver", to try to avoid + // corrupting asm which happens to contain the symbol name as a substring. + // Note that the substitution for .symver assumes that the versioned symbol + // also has an instrumented name. + std::string Asm = GV->getParent()->getModuleInlineAsm(); + std::string SearchStr = ".symver " + GVName + ","; + size_t Pos = Asm.find(SearchStr); + if (Pos != std::string::npos) { + Asm.replace(Pos, SearchStr.size(), + ".symver " + Prefix + GVName + "," + Prefix); + GV->getParent()->setModuleInlineAsm(Asm); + } +} + bool DataFlowSanitizer::runOnModule(Module &M) { if (!DL) return false; @@ -415,6 +440,21 @@ bool DataFlowSanitizer::runOnModule(Module &M) { FnsToInstrument.push_back(&*i); } + // Give function aliases prefixes when necessary. + for (Module::alias_iterator i = M.alias_begin(), e = M.alias_end(); i != e;) { + GlobalAlias *GA = &*i; + ++i; + // Don't stop on weak. We assume people aren't playing games with the + // instrumentedness of overridden weak aliases. + if (Function *F = dyn_cast<Function>( + GA->resolveAliasedGlobal(/*stopOnWeak=*/false))) { + bool GAInst = isInstrumented(GA), FInst = isInstrumented(F); + if (GAInst && FInst) { + addGlobalNamePrefix(GA); + } + } + } + AttrBuilder B; B.addAttribute(Attribute::ReadOnly).addAttribute(Attribute::ReadNone); ReadOnlyNoneAttrs = AttributeSet::get(*Ctx, AttributeSet::FunctionIndex, B); @@ -427,12 +467,13 @@ bool DataFlowSanitizer::runOnModule(Module &M) { Function &F = **i; FunctionType *FT = F.getFunctionType(); - if (FT->getNumParams() == 0 && !FT->isVarArg() && - FT->getReturnType()->isVoidTy()) - continue; + bool IsZeroArgsVoidRet = (FT->getNumParams() == 0 && !FT->isVarArg() && + FT->getReturnType()->isVoidTy()); if (isInstrumented(&F)) { - if (getInstrumentedABI() == IA_Args) { + // Instrumented functions get a 'dfs$' prefix. This allows us to more + // easily identify cases of mismatching ABIs. + if (getInstrumentedABI() == IA_Args && !IsZeroArgsVoidRet) { FunctionType *NewFT = getArgsFunctionType(FT); Function *NewF = Function::Create(NewFT, F.getLinkage(), "", &M); NewF->copyAttributesFrom(&F); @@ -463,13 +504,16 @@ bool DataFlowSanitizer::runOnModule(Module &M) { NewF->takeName(&F); F.eraseFromParent(); *i = NewF; + addGlobalNamePrefix(NewF); + } else { + addGlobalNamePrefix(&F); } // Hopefully, nobody will try to indirectly call a vararg // function... yet. } else if (FT->isVarArg()) { UnwrappedFnMap[&F] = &F; *i = 0; - } else { + } else if (!IsZeroArgsVoidRet || getWrapperKind(&F) == WK_Custom) { // Build a wrapper function for F. The wrapper simply calls F, and is // added to FnsToInstrument so that any instrumentation according to its // WrapperKind is done in the second pass below. |