llvm.org GIT mirror llvm / f1366c5
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 Peter Collingbourne 7 years ago
10 changed file(s) with 87 addition(s) and 29 deletion(s). Raw diff Collapse all Expand all
178178
179179 Value *getShadowAddress(Value *Addr, Instruction *Pos);
180180 Value *combineShadows(Value *V1, Value *V2, Instruction *Pos);
181 bool isInstrumented(Function *F);
181 bool isInstrumented(const Function *F);
182 bool isInstrumented(const GlobalAlias *GA);
182183 FunctionType *getArgsFunctionType(FunctionType *T);
183184 FunctionType *getCustomFunctionType(FunctionType *T);
184185 InstrumentedABI getInstrumentedABI();
185186 WrapperKind getWrapperKind(Function *F);
187 void addGlobalNamePrefix(GlobalValue *GV);
186188
187189 public:
188190 DataFlowSanitizer(StringRef ABIListFile = StringRef(),
342344 return true;
343345 }
344346
345 bool DataFlowSanitizer::isInstrumented(Function *F) {
347 bool DataFlowSanitizer::isInstrumented(const Function *F) {
346348 return !ABIList->isIn(*F, "uninstrumented");
349 }
350
351 bool DataFlowSanitizer::isInstrumented(const GlobalAlias *GA) {
352 return !ABIList->isIn(*GA, "uninstrumented");
347353 }
348354
349355 DataFlowSanitizer::InstrumentedABI DataFlowSanitizer::getInstrumentedABI() {
359365 return WK_Custom;
360366
361367 return WK_Warning;
368 }
369
370 void DataFlowSanitizer::addGlobalNamePrefix(GlobalValue *GV) {
371 std::string GVName = GV->getName(), Prefix = "dfs$";
372 GV->setName(Prefix + GVName);
373
374 // Try to change the name of the function in module inline asm. We only do
375 // this for specific asm directives, currently only ".symver", to try to avoid
376 // corrupting asm which happens to contain the symbol name as a substring.
377 // Note that the substitution for .symver assumes that the versioned symbol
378 // also has an instrumented name.
379 std::string Asm = GV->getParent()->getModuleInlineAsm();
380 std::string SearchStr = ".symver " + GVName + ",";
381 size_t Pos = Asm.find(SearchStr);
382 if (Pos != std::string::npos) {
383 Asm.replace(Pos, SearchStr.size(),
384 ".symver " + Prefix + GVName + "," + Prefix);
385 GV->getParent()->setModuleInlineAsm(Asm);
386 }
362387 }
363388
364389 bool DataFlowSanitizer::runOnModule(Module &M) {
414439 FnsToInstrument.push_back(&*i);
415440 }
416441
442 // Give function aliases prefixes when necessary.
443 for (Module::alias_iterator i = M.alias_begin(), e = M.alias_end(); i != e;) {
444 GlobalAlias *GA = &*i;
445 ++i;
446 // Don't stop on weak. We assume people aren't playing games with the
447 // instrumentedness of overridden weak aliases.
448 if (Function *F = dyn_cast(
449 GA->resolveAliasedGlobal(/*stopOnWeak=*/false))) {
450 bool GAInst = isInstrumented(GA), FInst = isInstrumented(F);
451 if (GAInst && FInst) {
452 addGlobalNamePrefix(GA);
453 }
454 }
455 }
456
417457 AttrBuilder B;
418458 B.addAttribute(Attribute::ReadOnly).addAttribute(Attribute::ReadNone);
419459 ReadOnlyNoneAttrs = AttributeSet::get(*Ctx, AttributeSet::FunctionIndex, B);
426466 Function &F = **i;
427467 FunctionType *FT = F.getFunctionType();
428468
429 if (FT->getNumParams() == 0 && !FT->isVarArg() &&
430 FT->getReturnType()->isVoidTy())
431 continue;
469 bool IsZeroArgsVoidRet = (FT->getNumParams() == 0 && !FT->isVarArg() &&
470 FT->getReturnType()->isVoidTy());
432471
433472 if (isInstrumented(&F)) {
434 if (getInstrumentedABI() == IA_Args) {
473 // Instrumented functions get a 'dfs$' prefix. This allows us to more
474 // easily identify cases of mismatching ABIs.
475 if (getInstrumentedABI() == IA_Args && !IsZeroArgsVoidRet) {
435476 FunctionType *NewFT = getArgsFunctionType(FT);
436477 Function *NewF = Function::Create(NewFT, F.getLinkage(), "", &M);
437478 NewF->copyAttributesFrom(&F);
462503 NewF->takeName(&F);
463504 F.eraseFromParent();
464505 *i = NewF;
506 addGlobalNamePrefix(NewF);
507 } else {
508 addGlobalNamePrefix(&F);
465509 }
466510 // Hopefully, nobody will try to indirectly call a vararg
467511 // function... yet.
468512 } else if (FT->isVarArg()) {
469513 UnwrappedFnMap[&F] = &F;
470514 *i = 0;
471 } else {
515 } else if (!IsZeroArgsVoidRet || getWrapperKind(&F) == WK_Custom) {
472516 // Build a wrapper function for F. The wrapper simply calls F, and is
473517 // added to FnsToInstrument so that any instrumentation according to its
474518 // WrapperKind is done in the second pass below.
1515
1616 declare i32 @custom2(i32 %a, i32 %b)
1717
18 ; CHECK: @f
18 ; CHECK: @"dfs$f"
1919 define void @f() {
2020 ; CHECK: %[[LABELRETURN:.*]] = alloca i16
2121
3636 ; CHECK: insertvalue {{.*}}[[RVSHADOW]], 1
3737 ; CHECK: ret { i32, i16 }
3838
39 ; CHECK: @g
39 ; CHECK: @"dfs$g"
4040 define i32 (i32, i32)* @g() {
4141 ; CHECK: ret {{.*}} @"dfsw$custom2"
4242 ret i32 (i32, i32)* @custom2
0 ; RUN: opt < %s -dfsan -verify -dfsan-args-abi -S | FileCheck %s
11 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
22
3 ; CHECK-LABEL: @unreachable_bb1
3 ; CHECK-LABEL: @"dfs$unreachable_bb1"
44 define i8 @unreachable_bb1() {
55 ; CHECK: ret { i8, i16 } { i8 1, i16 0 }
66 ; CHECK-NOT: bb2:
2020
2121 declare void @abort() noreturn
2222
23 ; CHECK-LABEL: @unreachable_bb2
23 ; CHECK-LABEL: @"dfs$unreachable_bb2"
2424 define i8 @unreachable_bb2() {
2525 call void @abort() noreturn
2626 ; CHECK-NOT: i8 12
11 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
22
33 define i8 @add(i8 %a, i8 %b) {
4 ; CHECK: @add
4 ; CHECK: @"dfs$add"
55 ; CHECK: load{{.*}}__dfsan_arg_tls
66 ; CHECK: load{{.*}}__dfsan_arg_tls
77 ; CHECK: call{{.*}}__dfsan_union
1313 }
1414
1515 define i8 @sub(i8 %a, i8 %b) {
16 ; CHECK: @sub
16 ; CHECK: @"dfs$sub"
1717 ; CHECK: load{{.*}}__dfsan_arg_tls
1818 ; CHECK: load{{.*}}__dfsan_arg_tls
1919 ; CHECK: call{{.*}}__dfsan_union
2525 }
2626
2727 define i8 @mul(i8 %a, i8 %b) {
28 ; CHECK: @mul
28 ; CHECK: @"dfs$mul"
2929 ; CHECK: load{{.*}}__dfsan_arg_tls
3030 ; CHECK: load{{.*}}__dfsan_arg_tls
3131 ; CHECK: call{{.*}}__dfsan_union
3737 }
3838
3939 define i8 @sdiv(i8 %a, i8 %b) {
40 ; CHECK: @sdiv
40 ; CHECK: @"dfs$sdiv"
4141 ; CHECK: load{{.*}}__dfsan_arg_tls
4242 ; CHECK: load{{.*}}__dfsan_arg_tls
4343 ; CHECK: call{{.*}}__dfsan_union
4949 }
5050
5151 define i8 @udiv(i8 %a, i8 %b) {
52 ; CHECK: @udiv
52 ; CHECK: @"dfs$udiv"
5353 ; CHECK: load{{.*}}__dfsan_arg_tls
5454 ; CHECK: load{{.*}}__dfsan_arg_tls
5555 ; CHECK: call{{.*}}__dfsan_union
66 declare i32 @f(i32)
77 declare float @llvm.sqrt.f32(float)
88
9 ; CHECK: @call
9 ; CHECK: @"dfs$call"
1010 define i32 @call() {
1111 ; CHECK: store{{.*}}__dfsan_arg_tls
12 ; CHECK: call{{.*}}@f
12 ; CHECK: call{{.*}}@"dfs$f"
1313 ; CHECK: load{{.*}}__dfsan_retval_tls
1414 %r = call i32 @f(i32 0)
1515
22
33 declare i32 @g()
44
5 ; CHECK: define { i32, i16 } @f(i32, i16)
5 ; CHECK: define { i32, i16 } @"dfs$f"(i32, i16)
66 define i32 @f(i32) {
77 ; CHECK: [[LOCALLABELALLOCA:%.*]] = alloca i16
88 ; CHECK: [[ARGCMP:%.*]] = icmp ne i16 %1, 0
99 ; CHECK: br i1 [[ARGCMP]]
1010 %i = alloca i32
1111 store i32 %0, i32* %i
12 ; CHECK: [[CALL:%.*]] = call { i32, i16 } @g()
12 ; CHECK: [[CALL:%.*]] = call { i32, i16 } @"dfs$g"()
1313 ; CHECK: [[CALLLABEL:%.*]] = extractvalue { i32, i16 } [[CALL]], 1
1414 ; CHECK: [[CALLCMP:%.*]] = icmp ne i16 [[CALLLABEL]], 0
1515 ; CHECK: br i1 [[CALLCMP]]
11 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
22
33 define i8 @load8(i8* %p) {
4 ; CHECK: @load8
4 ; CHECK: @"dfs$load8"
55 ; CHECK: ptrtoint
66 ; CHECK: and
77 ; CHECK: mul
1414 }
1515
1616 define i16 @load16(i16* %p) {
17 ; CHECK: @load16
17 ; CHECK: @"dfs$load16"
1818 ; CHECK: ptrtoint
1919 ; CHECK: and
2020 ; CHECK: mul
3030 }
3131
3232 define i32 @load32(i32* %p) {
33 ; CHECK: @load32
33 ; CHECK: @"dfs$load32"
3434 ; CHECK: ptrtoint
3535 ; CHECK: and
3636 ; CHECK: mul
5353 }
5454
5555 define i64 @load64(i64* %p) {
56 ; CHECK: @load64
56 ; CHECK: @"dfs$load64"
5757 ; CHECK: ptrtoint
5858 ; CHECK: and
5959 ; CHECK: mul
33 declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1)
44
55 define void @ms(i8* %p, i8 %v) {
6 ; CHECK-LABEL: @ms(i8*, i8, i16, i16)
6 ; CHECK-LABEL: @"dfs$ms"(i8*, i8, i16, i16)
77 ; CHECK: call void @__dfsan_set_label(i16 %3, i8* %0, i64 1)
88 call void @llvm.memset.p0i8.i64(i8* %p, i8 %v, i64 1, i32 1, i1 1)
99 ret void
0 ; RUN: opt < %s -dfsan -S | FileCheck %s
1 ; RUN: opt < %s -dfsan -dfsan-args-abi -S | FileCheck %s
2 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
3
4 ; CHECK: module asm ".symver dfs$f1,dfs$f@@version1"
5 module asm ".symver f1,f@@version1"
6
7 ; CHECK: @"dfs$f2" = alias {{.*}} @"dfs$f1"
8 @f2 = alias void ()* @f1
9
10 ; CHECK: define void @"dfs$f1"
11 define void @f1() {
12 ret void
13 }
11 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
22
33 define void @store8(i8 %v, i8* %p) {
4 ; CHECK: @store8
4 ; CHECK: @"dfs$store8"
55 ; CHECK: load{{.*}}__dfsan_arg_tls
66 ; CHECK: ptrtoint
77 ; CHECK: and
1515 }
1616
1717 define void @store16(i16 %v, i16* %p) {
18 ; CHECK: @store16
18 ; CHECK: @"dfs$store16"
1919 ; CHECK: load{{.*}}__dfsan_arg_tls
2020 ; CHECK: ptrtoint
2121 ; CHECK: and
3131 }
3232
3333 define void @store32(i32 %v, i32* %p) {
34 ; CHECK: @store32
34 ; CHECK: @"dfs$store32"
3535 ; CHECK: load{{.*}}__dfsan_arg_tls
3636 ; CHECK: ptrtoint
3737 ; CHECK: and
5151 }
5252
5353 define void @store64(i64 %v, i64* %p) {
54 ; CHECK: @store64
54 ; CHECK: @"dfs$store64"
5555 ; CHECK: load{{.*}}__dfsan_arg_tls
5656 ; CHECK: ptrtoint
5757 ; CHECK: and