mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-21 06:30:16 +00:00
[msan] Remove indirect call wrapping code.
This functionality was only used in MSanDR, which is deprecated. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@222889 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
2b8e58cc82
commit
c0b24f7949
@ -187,18 +187,6 @@ static cl::opt<int> ClInstrumentationWithCallThreshold(
|
|||||||
"inline checks (-1 means never use callbacks)."),
|
"inline checks (-1 means never use callbacks)."),
|
||||||
cl::Hidden, cl::init(3500));
|
cl::Hidden, cl::init(3500));
|
||||||
|
|
||||||
// Experimental. Wraps all indirect calls in the instrumented code with
|
|
||||||
// a call to the given function. This is needed to assist the dynamic
|
|
||||||
// helper tool (MSanDR) to regain control on transition between instrumented and
|
|
||||||
// non-instrumented code.
|
|
||||||
static cl::opt<std::string> ClWrapIndirectCalls("msan-wrap-indirect-calls",
|
|
||||||
cl::desc("Wrap indirect calls with a given function"),
|
|
||||||
cl::Hidden);
|
|
||||||
|
|
||||||
static cl::opt<bool> ClWrapIndirectCallsFast("msan-wrap-indirect-calls-fast",
|
|
||||||
cl::desc("Do not wrap indirect calls with target in the same module"),
|
|
||||||
cl::Hidden, cl::init(true));
|
|
||||||
|
|
||||||
// This is an experiment to enable handling of cases where shadow is a non-zero
|
// This is an experiment to enable handling of cases where shadow is a non-zero
|
||||||
// compile-time constant. For some unexplainable reason they were silently
|
// compile-time constant. For some unexplainable reason they were silently
|
||||||
// ignored in the instrumentation.
|
// ignored in the instrumentation.
|
||||||
@ -219,8 +207,7 @@ class MemorySanitizer : public FunctionPass {
|
|||||||
: FunctionPass(ID),
|
: FunctionPass(ID),
|
||||||
TrackOrigins(std::max(TrackOrigins, (int)ClTrackOrigins)),
|
TrackOrigins(std::max(TrackOrigins, (int)ClTrackOrigins)),
|
||||||
DL(nullptr),
|
DL(nullptr),
|
||||||
WarningFn(nullptr),
|
WarningFn(nullptr) {}
|
||||||
WrapIndirectCalls(!ClWrapIndirectCalls.empty()) {}
|
|
||||||
const char *getPassName() const override { return "MemorySanitizer"; }
|
const char *getPassName() const override { return "MemorySanitizer"; }
|
||||||
bool runOnFunction(Function &F) override;
|
bool runOnFunction(Function &F) override;
|
||||||
bool doInitialization(Module &M) override;
|
bool doInitialization(Module &M) override;
|
||||||
@ -254,9 +241,6 @@ class MemorySanitizer : public FunctionPass {
|
|||||||
/// function.
|
/// function.
|
||||||
GlobalVariable *OriginTLS;
|
GlobalVariable *OriginTLS;
|
||||||
|
|
||||||
GlobalVariable *MsandrModuleStart;
|
|
||||||
GlobalVariable *MsandrModuleEnd;
|
|
||||||
|
|
||||||
/// \brief The run-time callback to print a warning.
|
/// \brief The run-time callback to print a warning.
|
||||||
Value *WarningFn;
|
Value *WarningFn;
|
||||||
// These arrays are indexed by log2(AccessSize).
|
// These arrays are indexed by log2(AccessSize).
|
||||||
@ -287,12 +271,6 @@ class MemorySanitizer : public FunctionPass {
|
|||||||
/// \brief An empty volatile inline asm that prevents callback merge.
|
/// \brief An empty volatile inline asm that prevents callback merge.
|
||||||
InlineAsm *EmptyAsm;
|
InlineAsm *EmptyAsm;
|
||||||
|
|
||||||
bool WrapIndirectCalls;
|
|
||||||
/// \brief Run-time wrapper for indirect calls.
|
|
||||||
Value *IndirectCallWrapperFn;
|
|
||||||
// Argument and return type of IndirectCallWrapperFn: void (*f)(void).
|
|
||||||
Type *AnyFunctionPtrTy;
|
|
||||||
|
|
||||||
friend struct MemorySanitizerVisitor;
|
friend struct MemorySanitizerVisitor;
|
||||||
friend struct VarArgAMD64Helper;
|
friend struct VarArgAMD64Helper;
|
||||||
};
|
};
|
||||||
@ -400,24 +378,6 @@ void MemorySanitizer::initializeCallbacks(Module &M) {
|
|||||||
EmptyAsm = InlineAsm::get(FunctionType::get(IRB.getVoidTy(), false),
|
EmptyAsm = InlineAsm::get(FunctionType::get(IRB.getVoidTy(), false),
|
||||||
StringRef(""), StringRef(""),
|
StringRef(""), StringRef(""),
|
||||||
/*hasSideEffects=*/true);
|
/*hasSideEffects=*/true);
|
||||||
|
|
||||||
if (WrapIndirectCalls) {
|
|
||||||
AnyFunctionPtrTy =
|
|
||||||
PointerType::getUnqual(FunctionType::get(IRB.getVoidTy(), false));
|
|
||||||
IndirectCallWrapperFn = M.getOrInsertFunction(
|
|
||||||
ClWrapIndirectCalls, AnyFunctionPtrTy, AnyFunctionPtrTy, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (WrapIndirectCalls && ClWrapIndirectCallsFast) {
|
|
||||||
MsandrModuleStart = new GlobalVariable(
|
|
||||||
M, IRB.getInt32Ty(), false, GlobalValue::ExternalLinkage,
|
|
||||||
nullptr, "__executable_start");
|
|
||||||
MsandrModuleStart->setVisibility(GlobalVariable::HiddenVisibility);
|
|
||||||
MsandrModuleEnd = new GlobalVariable(
|
|
||||||
M, IRB.getInt32Ty(), false, GlobalValue::ExternalLinkage,
|
|
||||||
nullptr, "_end");
|
|
||||||
MsandrModuleEnd->setVisibility(GlobalVariable::HiddenVisibility);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Module-level initialization.
|
/// \brief Module-level initialization.
|
||||||
@ -537,7 +497,6 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
|
|||||||
};
|
};
|
||||||
SmallVector<ShadowOriginAndInsertPoint, 16> InstrumentationList;
|
SmallVector<ShadowOriginAndInsertPoint, 16> InstrumentationList;
|
||||||
SmallVector<Instruction*, 16> StoreList;
|
SmallVector<Instruction*, 16> StoreList;
|
||||||
SmallVector<CallSite, 16> IndirectCallList;
|
|
||||||
|
|
||||||
MemorySanitizerVisitor(Function &F, MemorySanitizer &MS)
|
MemorySanitizerVisitor(Function &F, MemorySanitizer &MS)
|
||||||
: F(F), MS(MS), VAHelper(CreateVarArgHelper(F, MS, *this)) {
|
: F(F), MS(MS), VAHelper(CreateVarArgHelper(F, MS, *this)) {
|
||||||
@ -669,47 +628,6 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
|
|||||||
DEBUG(dbgs() << "DONE:\n" << F);
|
DEBUG(dbgs() << "DONE:\n" << F);
|
||||||
}
|
}
|
||||||
|
|
||||||
void materializeIndirectCalls() {
|
|
||||||
for (auto &CS : IndirectCallList) {
|
|
||||||
Instruction *I = CS.getInstruction();
|
|
||||||
BasicBlock *B = I->getParent();
|
|
||||||
IRBuilder<> IRB(I);
|
|
||||||
Value *Fn0 = CS.getCalledValue();
|
|
||||||
Value *Fn = IRB.CreateBitCast(Fn0, MS.AnyFunctionPtrTy);
|
|
||||||
|
|
||||||
if (ClWrapIndirectCallsFast) {
|
|
||||||
// Check that call target is inside this module limits.
|
|
||||||
Value *Start =
|
|
||||||
IRB.CreateBitCast(MS.MsandrModuleStart, MS.AnyFunctionPtrTy);
|
|
||||||
Value *End = IRB.CreateBitCast(MS.MsandrModuleEnd, MS.AnyFunctionPtrTy);
|
|
||||||
|
|
||||||
Value *NotInThisModule = IRB.CreateOr(IRB.CreateICmpULT(Fn, Start),
|
|
||||||
IRB.CreateICmpUGE(Fn, End));
|
|
||||||
|
|
||||||
PHINode *NewFnPhi =
|
|
||||||
IRB.CreatePHI(Fn0->getType(), 2, "msandr.indirect_target");
|
|
||||||
|
|
||||||
Instruction *CheckTerm = SplitBlockAndInsertIfThen(
|
|
||||||
NotInThisModule, NewFnPhi,
|
|
||||||
/* Unreachable */ false, MS.ColdCallWeights);
|
|
||||||
|
|
||||||
IRB.SetInsertPoint(CheckTerm);
|
|
||||||
// Slow path: call wrapper function to possibly transform the call
|
|
||||||
// target.
|
|
||||||
Value *NewFn = IRB.CreateBitCast(
|
|
||||||
IRB.CreateCall(MS.IndirectCallWrapperFn, Fn), Fn0->getType());
|
|
||||||
|
|
||||||
NewFnPhi->addIncoming(Fn0, B);
|
|
||||||
NewFnPhi->addIncoming(NewFn, dyn_cast<Instruction>(NewFn)->getParent());
|
|
||||||
CS.setCalledFunction(NewFnPhi);
|
|
||||||
} else {
|
|
||||||
Value *NewFn = IRB.CreateBitCast(
|
|
||||||
IRB.CreateCall(MS.IndirectCallWrapperFn, Fn), Fn0->getType());
|
|
||||||
CS.setCalledFunction(NewFn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \brief Add MemorySanitizer instrumentation to a function.
|
/// \brief Add MemorySanitizer instrumentation to a function.
|
||||||
bool runOnFunction() {
|
bool runOnFunction() {
|
||||||
MS.initializeCallbacks(*F.getParent());
|
MS.initializeCallbacks(*F.getParent());
|
||||||
@ -752,9 +670,6 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
|
|||||||
// Insert shadow value checks.
|
// Insert shadow value checks.
|
||||||
materializeChecks(InstrumentWithCalls);
|
materializeChecks(InstrumentWithCalls);
|
||||||
|
|
||||||
// Wrap indirect calls.
|
|
||||||
materializeIndirectCalls();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2337,9 +2252,6 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
|
|||||||
}
|
}
|
||||||
IRBuilder<> IRB(&I);
|
IRBuilder<> IRB(&I);
|
||||||
|
|
||||||
if (MS.WrapIndirectCalls && !CS.getCalledFunction())
|
|
||||||
IndirectCallList.push_back(CS);
|
|
||||||
|
|
||||||
unsigned ArgOffset = 0;
|
unsigned ArgOffset = 0;
|
||||||
DEBUG(dbgs() << " CallSite: " << I << "\n");
|
DEBUG(dbgs() << " CallSite: " << I << "\n");
|
||||||
for (CallSite::arg_iterator ArgIt = CS.arg_begin(), End = CS.arg_end();
|
for (CallSite::arg_iterator ArgIt = CS.arg_begin(), End = CS.arg_end();
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
; Test that MSan does not emit undefined symbol __executable_start when it is
|
|
||||||
; not needed (i.e. without -msan-wrap-indirect-calls).
|
|
||||||
|
|
||||||
; RUN: opt < %s -msan -S | FileCheck %s
|
|
||||||
|
|
||||||
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
|
||||||
target triple = "x86_64-unknown-linux-gnu"
|
|
||||||
|
|
||||||
; Function Attrs: nounwind uwtable
|
|
||||||
define void @_Z1fv() #0 {
|
|
||||||
entry:
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
|
|
||||||
attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
|
||||||
|
|
||||||
!llvm.ident = !{!0}
|
|
||||||
|
|
||||||
!0 = metadata !{metadata !"clang version 3.5.0 (208165)"}
|
|
||||||
|
|
||||||
; CHECK-NOT: __executable_start
|
|
@ -1,60 +0,0 @@
|
|||||||
; RUN: opt < %s -msan -msan-check-access-address=0 -msan-wrap-indirect-calls=zzz -msan-wrap-indirect-calls-fast=0 -S | FileCheck %s
|
|
||||||
; RUN: opt < %s -msan -msan-check-access-address=0 -msan-wrap-indirect-calls=zzz -msan-wrap-indirect-calls-fast=1 -S | FileCheck -check-prefix=CHECK-FAST %s
|
|
||||||
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"
|
|
||||||
target triple = "x86_64-unknown-linux-gnu"
|
|
||||||
|
|
||||||
; Test for -msan-wrap-indirect-calls functionality.
|
|
||||||
; Replaces indirect call to %f with a call to whatever is returned from the
|
|
||||||
; wrapper function.
|
|
||||||
|
|
||||||
; This does not depend on the sanitize_memory attribute.
|
|
||||||
define i32 @func1(i32 (i32, i32)* nocapture %f, i32 %x, i32 %y) {
|
|
||||||
entry:
|
|
||||||
%call = tail call i32 %f(i32 %x, i32 %y)
|
|
||||||
ret i32 %call
|
|
||||||
}
|
|
||||||
|
|
||||||
; CHECK: @func1
|
|
||||||
; CHECK: bitcast i32 (i32, i32)* %f to void ()*
|
|
||||||
; CHECK: call void ()* (void ()*)* @zzz(void ()*
|
|
||||||
; CHECK: [[A:%[01-9a-z_.]+]] = bitcast void ()* {{.*}} to i32 (i32, i32)*
|
|
||||||
; CHECK: call i32 {{.*}}[[A]](i32 {{.*}}, i32 {{.*}})
|
|
||||||
; CHECK: ret i32
|
|
||||||
|
|
||||||
; CHECK-FAST: @func1
|
|
||||||
; CHECK-FAST: bitcast i32 (i32, i32)* %f to void ()*
|
|
||||||
; CHECK-FAST-DAG: icmp ult void ()* {{.*}}, bitcast (i32* @__executable_start to void ()*)
|
|
||||||
; CHECK-FAST-DAG: icmp uge void ()* {{.*}}, bitcast (i32* @_end to void ()*)
|
|
||||||
; CHECK-FAST: or i1
|
|
||||||
; CHECK-FAST: br i1
|
|
||||||
; CHECK-FAST: call void ()* (void ()*)* @zzz(void ()*
|
|
||||||
; CHECK-FAST: br label
|
|
||||||
; CHECK-FAST: [[A:%[01-9a-z_.]+]] = phi i32 (i32, i32)* [ %f, %entry ], [ {{.*}} ]
|
|
||||||
; CHECK-FAST: call i32 {{.*}}[[A]](i32 {{.*}}, i32 {{.*}})
|
|
||||||
; CHECK-FAST: ret i32
|
|
||||||
|
|
||||||
|
|
||||||
; The same test, but with a complex expression as the call target.
|
|
||||||
|
|
||||||
declare i8* @callee(i32)
|
|
||||||
|
|
||||||
define i8* @func2(i64 %x) #1 {
|
|
||||||
entry:
|
|
||||||
%call = tail call i8* bitcast (i8* (i32)* @callee to i8* (i64)*)(i64 %x)
|
|
||||||
ret i8* %call
|
|
||||||
}
|
|
||||||
|
|
||||||
; CHECK: @func2
|
|
||||||
; CHECK: call {{.*}} @zzz
|
|
||||||
; CHECK: [[A:%[01-9a-z_.]+]] = bitcast void ()* {{.*}} to i8* (i64)*
|
|
||||||
; CHECK: call i8* {{.*}}[[A]](i64 {{.*}})
|
|
||||||
; CHECK: ret i8*
|
|
||||||
|
|
||||||
; CHECK-FAST: @func2
|
|
||||||
; CHECK-FAST: {{br i1 or .* icmp ult .* bitcast .* @callee .* @__executable_start.* icmp uge .* bitcast .* @callee .* @_end}}
|
|
||||||
; CHECK-FAST: {{call .* @zzz.* bitcast .*@callee}}
|
|
||||||
; CHECK-FAST: bitcast void ()* {{.*}} to i8* (i64)*
|
|
||||||
; CHECK-FAST: br label
|
|
||||||
; CHECK-FAST: [[A:%[01-9a-z_.]+]] = phi i8* (i64)* [{{.*bitcast .* @callee.*, %entry.*}}], [ {{.*}} ]
|
|
||||||
; CHECK-FAST: call i8* {{.*}}[[A]](i64 {{.*}})
|
|
||||||
; CHECK-FAST: ret i8*
|
|
Loading…
x
Reference in New Issue
Block a user