aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
diff options
context:
space:
mode:
authorPeter Collingbourne <peter@pcc.me.uk>2013-08-22 20:08:08 +0000
committerPeter Collingbourne <peter@pcc.me.uk>2013-08-22 20:08:08 +0000
commitf1366c552480f7c6b2b46b03e19bb798b3a47c66 (patch)
tree5277472cc316f2be70f568db1eca3074927ce6f3 /lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
parent094637408b806bb17c02daba2027f39eb73bb98a (diff)
downloadexternal_llvm-f1366c552480f7c6b2b46b03e19bb798b3a47c66.tar.gz
external_llvm-f1366c552480f7c6b2b46b03e19bb798b3a47c66.tar.bz2
external_llvm-f1366c552480f7c6b2b46b03e19bb798b3a47c66.zip
DataFlowSanitizer: Prefix the name of each instrumented function with "dfs$".
DFSan changes the ABI of each function in the module. This makes it possible for a function with the native ABI to be called with the instrumented ABI, or vice versa, thus possibly invoking undefined behavior. A simple way of statically detecting instances of this problem is to prepend the prefix "dfs$" to the name of each instrumented-ABI function. This will not catch every such problem; in particular function pointers passed across the instrumented-native barrier cannot be used on the other side. These problems could potentially be caught dynamically. Differential Revision: http://llvm-reviews.chandlerc.com/D1373 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@189052 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms/Instrumentation/DataFlowSanitizer.cpp')
-rw-r--r--lib/Transforms/Instrumentation/DataFlowSanitizer.cpp58
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.