forked from OSchip/llvm-project
[dfsan] Fix clang-tidy warnings
This addresses ~50 clang-tidy warnings on dfsan instrumentation pass. It also contains some refactoring (all non-functional changes) to eliminate some variables and simplify code. Reviewed By: stephan.yichao.zhao Differential Revision: https://reviews.llvm.org/D97714
This commit is contained in:
parent
a189b3b9e8
commit
6ff18b08e6
|
@ -58,6 +58,7 @@
|
||||||
#include "llvm/ADT/StringExtras.h"
|
#include "llvm/ADT/StringExtras.h"
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
#include "llvm/ADT/Triple.h"
|
#include "llvm/ADT/Triple.h"
|
||||||
|
#include "llvm/ADT/iterator.h"
|
||||||
#include "llvm/Analysis/ValueTracking.h"
|
#include "llvm/Analysis/ValueTracking.h"
|
||||||
#include "llvm/IR/Argument.h"
|
#include "llvm/IR/Argument.h"
|
||||||
#include "llvm/IR/Attributes.h"
|
#include "llvm/IR/Attributes.h"
|
||||||
|
@ -109,19 +110,19 @@
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
// This must be consistent with ShadowWidthBits.
|
// This must be consistent with ShadowWidthBits.
|
||||||
static const Align kShadowTLSAlignment = Align(2);
|
static const Align ShadowTLSAlignment = Align(2);
|
||||||
|
|
||||||
static const Align kMinOriginAlignment = Align(4);
|
static const Align MinOriginAlignment = Align(4);
|
||||||
|
|
||||||
// The size of TLS variables. These constants must be kept in sync with the ones
|
// The size of TLS variables. These constants must be kept in sync with the ones
|
||||||
// in dfsan.cpp.
|
// in dfsan.cpp.
|
||||||
static const unsigned kArgTLSSize = 800;
|
static const unsigned ArgTLSSize = 800;
|
||||||
static const unsigned kRetvalTLSSize = 800;
|
static const unsigned RetvalTLSSize = 800;
|
||||||
|
|
||||||
// External symbol to be used when generating the shadow address for
|
// External symbol to be used when generating the shadow address for
|
||||||
// architectures with multiple VMAs. Instead of using a constant integer
|
// architectures with multiple VMAs. Instead of using a constant integer
|
||||||
// the runtime will set the external mask based on the VMA range.
|
// the runtime will set the external mask based on the VMA range.
|
||||||
const char kDFSanExternShadowPtrMask[] = "__dfsan_shadow_ptr_mask";
|
const char DFSanExternShadowPtrMask[] = "__dfsan_shadow_ptr_mask";
|
||||||
|
|
||||||
// The -dfsan-preserve-alignment flag controls whether this pass assumes that
|
// The -dfsan-preserve-alignment flag controls whether this pass assumes that
|
||||||
// alignment requirements provided by the input IR are correct. For example,
|
// alignment requirements provided by the input IR are correct. For example,
|
||||||
|
@ -148,10 +149,10 @@ static cl::list<std::string> ClABIListFiles(
|
||||||
|
|
||||||
// Controls whether the pass uses IA_Args or IA_TLS as the ABI for instrumented
|
// Controls whether the pass uses IA_Args or IA_TLS as the ABI for instrumented
|
||||||
// functions (see DataFlowSanitizer::InstrumentedABI below).
|
// functions (see DataFlowSanitizer::InstrumentedABI below).
|
||||||
static cl::opt<bool> ClArgsABI(
|
static cl::opt<bool>
|
||||||
"dfsan-args-abi",
|
ClArgsABI("dfsan-args-abi",
|
||||||
cl::desc("Use the argument ABI rather than the TLS ABI"),
|
cl::desc("Use the argument ABI rather than the TLS ABI"),
|
||||||
cl::Hidden);
|
cl::Hidden);
|
||||||
|
|
||||||
// Controls whether the pass includes or ignores the labels of pointers in load
|
// Controls whether the pass includes or ignores the labels of pointers in load
|
||||||
// instructions.
|
// instructions.
|
||||||
|
@ -213,7 +214,7 @@ static cl::opt<int> ClTrackOrigins("dfsan-track-origins",
|
||||||
cl::desc("Track origins of labels"),
|
cl::desc("Track origins of labels"),
|
||||||
cl::Hidden, cl::init(0));
|
cl::Hidden, cl::init(0));
|
||||||
|
|
||||||
static StringRef GetGlobalTypeString(const GlobalValue &G) {
|
static StringRef getGlobalTypeString(const GlobalValue &G) {
|
||||||
// Types of GlobalVariables are always pointer types.
|
// Types of GlobalVariables are always pointer types.
|
||||||
Type *GType = G.getValueType();
|
Type *GType = G.getValueType();
|
||||||
// For now we support excluding struct types only.
|
// For now we support excluding struct types only.
|
||||||
|
@ -229,7 +230,7 @@ namespace {
|
||||||
class DFSanABIList {
|
class DFSanABIList {
|
||||||
std::unique_ptr<SpecialCaseList> SCL;
|
std::unique_ptr<SpecialCaseList> SCL;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DFSanABIList() = default;
|
DFSanABIList() = default;
|
||||||
|
|
||||||
void set(std::unique_ptr<SpecialCaseList> List) { SCL = std::move(List); }
|
void set(std::unique_ptr<SpecialCaseList> List) { SCL = std::move(List); }
|
||||||
|
@ -253,7 +254,7 @@ class DFSanABIList {
|
||||||
return SCL->inSection("dataflow", "fun", GA.getName(), Category);
|
return SCL->inSection("dataflow", "fun", GA.getName(), Category);
|
||||||
|
|
||||||
return SCL->inSection("dataflow", "global", GA.getName(), Category) ||
|
return SCL->inSection("dataflow", "global", GA.getName(), Category) ||
|
||||||
SCL->inSection("dataflow", "type", GetGlobalTypeString(GA),
|
SCL->inSection("dataflow", "type", getGlobalTypeString(GA),
|
||||||
Category);
|
Category);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,20 +268,18 @@ class DFSanABIList {
|
||||||
/// function type into another. This struct is immutable. It holds metadata
|
/// function type into another. This struct is immutable. It holds metadata
|
||||||
/// useful for updating calls of the old function to the new type.
|
/// useful for updating calls of the old function to the new type.
|
||||||
struct TransformedFunction {
|
struct TransformedFunction {
|
||||||
TransformedFunction(FunctionType* OriginalType,
|
TransformedFunction(FunctionType *OriginalType, FunctionType *TransformedType,
|
||||||
FunctionType* TransformedType,
|
|
||||||
std::vector<unsigned> ArgumentIndexMapping)
|
std::vector<unsigned> ArgumentIndexMapping)
|
||||||
: OriginalType(OriginalType),
|
: OriginalType(OriginalType), TransformedType(TransformedType),
|
||||||
TransformedType(TransformedType),
|
|
||||||
ArgumentIndexMapping(ArgumentIndexMapping) {}
|
ArgumentIndexMapping(ArgumentIndexMapping) {}
|
||||||
|
|
||||||
// Disallow copies.
|
// Disallow copies.
|
||||||
TransformedFunction(const TransformedFunction&) = delete;
|
TransformedFunction(const TransformedFunction &) = delete;
|
||||||
TransformedFunction& operator=(const TransformedFunction&) = delete;
|
TransformedFunction &operator=(const TransformedFunction &) = delete;
|
||||||
|
|
||||||
// Allow moves.
|
// Allow moves.
|
||||||
TransformedFunction(TransformedFunction&&) = default;
|
TransformedFunction(TransformedFunction &&) = default;
|
||||||
TransformedFunction& operator=(TransformedFunction&&) = default;
|
TransformedFunction &operator=(TransformedFunction &&) = default;
|
||||||
|
|
||||||
/// Type of the function before the transformation.
|
/// Type of the function before the transformation.
|
||||||
FunctionType *OriginalType;
|
FunctionType *OriginalType;
|
||||||
|
@ -299,9 +298,9 @@ struct TransformedFunction {
|
||||||
/// Given function attributes from a call site for the original function,
|
/// Given function attributes from a call site for the original function,
|
||||||
/// return function attributes appropriate for a call to the transformed
|
/// return function attributes appropriate for a call to the transformed
|
||||||
/// function.
|
/// function.
|
||||||
AttributeList TransformFunctionAttributes(
|
AttributeList
|
||||||
const TransformedFunction& TransformedFunction,
|
transformFunctionAttributes(const TransformedFunction &TransformedFunction,
|
||||||
LLVMContext& Ctx, AttributeList CallSiteAttrs) {
|
LLVMContext &Ctx, AttributeList CallSiteAttrs) {
|
||||||
|
|
||||||
// Construct a vector of AttributeSet for each function argument.
|
// Construct a vector of AttributeSet for each function argument.
|
||||||
std::vector<llvm::AttributeSet> ArgumentAttributes(
|
std::vector<llvm::AttributeSet> ArgumentAttributes(
|
||||||
|
@ -310,23 +309,22 @@ AttributeList TransformFunctionAttributes(
|
||||||
// Copy attributes from the parameter of the original function to the
|
// Copy attributes from the parameter of the original function to the
|
||||||
// transformed version. 'ArgumentIndexMapping' holds the mapping from
|
// transformed version. 'ArgumentIndexMapping' holds the mapping from
|
||||||
// old argument position to new.
|
// old argument position to new.
|
||||||
for (unsigned i=0, ie = TransformedFunction.ArgumentIndexMapping.size();
|
for (unsigned I = 0, IE = TransformedFunction.ArgumentIndexMapping.size();
|
||||||
i < ie; ++i) {
|
I < IE; ++I) {
|
||||||
unsigned TransformedIndex = TransformedFunction.ArgumentIndexMapping[i];
|
unsigned TransformedIndex = TransformedFunction.ArgumentIndexMapping[I];
|
||||||
ArgumentAttributes[TransformedIndex] = CallSiteAttrs.getParamAttributes(i);
|
ArgumentAttributes[TransformedIndex] = CallSiteAttrs.getParamAttributes(I);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy annotations on varargs arguments.
|
// Copy annotations on varargs arguments.
|
||||||
for (unsigned i = TransformedFunction.OriginalType->getNumParams(),
|
for (unsigned I = TransformedFunction.OriginalType->getNumParams(),
|
||||||
ie = CallSiteAttrs.getNumAttrSets(); i<ie; ++i) {
|
IE = CallSiteAttrs.getNumAttrSets();
|
||||||
ArgumentAttributes.push_back(CallSiteAttrs.getParamAttributes(i));
|
I < IE; ++I) {
|
||||||
|
ArgumentAttributes.push_back(CallSiteAttrs.getParamAttributes(I));
|
||||||
}
|
}
|
||||||
|
|
||||||
return AttributeList::get(
|
return AttributeList::get(Ctx, CallSiteAttrs.getFnAttributes(),
|
||||||
Ctx,
|
CallSiteAttrs.getRetAttributes(),
|
||||||
CallSiteAttrs.getFnAttributes(),
|
llvm::makeArrayRef(ArgumentAttributes));
|
||||||
CallSiteAttrs.getRetAttributes(),
|
|
||||||
llvm::makeArrayRef(ArgumentAttributes));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class DataFlowSanitizer {
|
class DataFlowSanitizer {
|
||||||
|
@ -489,7 +487,7 @@ class DataFlowSanitizer {
|
||||||
/// Returns the shadow type of of V's type.
|
/// Returns the shadow type of of V's type.
|
||||||
Type *getShadowTy(Value *V);
|
Type *getShadowTy(Value *V);
|
||||||
|
|
||||||
const uint64_t kNumOfElementsInArgOrgTLS = kArgTLSSize / OriginWidthBytes;
|
const uint64_t NumOfElementsInArgOrgTLS = ArgTLSSize / OriginWidthBytes;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DataFlowSanitizer(const std::vector<std::string> &ABIListFiles);
|
DataFlowSanitizer(const std::vector<std::string> &ABIListFiles);
|
||||||
|
@ -722,17 +720,16 @@ TransformedFunction DataFlowSanitizer::getCustomFunctionType(FunctionType *T) {
|
||||||
// at call sites can be updated.
|
// at call sites can be updated.
|
||||||
std::vector<unsigned> ArgumentIndexMapping;
|
std::vector<unsigned> ArgumentIndexMapping;
|
||||||
for (unsigned I = 0, E = T->getNumParams(); I != E; ++I) {
|
for (unsigned I = 0, E = T->getNumParams(); I != E; ++I) {
|
||||||
Type *Param_type = T->getParamType(I);
|
Type *ParamType = T->getParamType(I);
|
||||||
FunctionType *FT;
|
FunctionType *FT;
|
||||||
if (isa<PointerType>(Param_type) &&
|
if (isa<PointerType>(ParamType) &&
|
||||||
(FT = dyn_cast<FunctionType>(
|
(FT = dyn_cast<FunctionType>(ParamType->getPointerElementType()))) {
|
||||||
cast<PointerType>(Param_type)->getElementType()))) {
|
|
||||||
ArgumentIndexMapping.push_back(ArgTypes.size());
|
ArgumentIndexMapping.push_back(ArgTypes.size());
|
||||||
ArgTypes.push_back(getTrampolineFunctionType(FT)->getPointerTo());
|
ArgTypes.push_back(getTrampolineFunctionType(FT)->getPointerTo());
|
||||||
ArgTypes.push_back(Type::getInt8PtrTy(*Ctx));
|
ArgTypes.push_back(Type::getInt8PtrTy(*Ctx));
|
||||||
} else {
|
} else {
|
||||||
ArgumentIndexMapping.push_back(ArgTypes.size());
|
ArgumentIndexMapping.push_back(ArgTypes.size());
|
||||||
ArgTypes.push_back(Param_type);
|
ArgTypes.push_back(ParamType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (unsigned I = 0, E = T->getNumParams(); I != E; ++I)
|
for (unsigned I = 0, E = T->getNumParams(); I != E; ++I)
|
||||||
|
@ -772,10 +769,10 @@ bool DataFlowSanitizer::isZeroShadow(Value *V) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DataFlowSanitizer::shouldTrackOrigins() {
|
bool DataFlowSanitizer::shouldTrackOrigins() {
|
||||||
static const bool kShouldTrackOrigins =
|
static const bool ShouldTrackOrigins =
|
||||||
ClTrackOrigins && getInstrumentedABI() == DataFlowSanitizer::IA_TLS &&
|
ClTrackOrigins && getInstrumentedABI() == DataFlowSanitizer::IA_TLS &&
|
||||||
ClFast16Labels;
|
ClFast16Labels;
|
||||||
return kShouldTrackOrigins;
|
return ShouldTrackOrigins;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DataFlowSanitizer::shouldTrackFieldsAndIndices() {
|
bool DataFlowSanitizer::shouldTrackFieldsAndIndices() {
|
||||||
|
@ -922,11 +919,6 @@ Type *DataFlowSanitizer::getShadowTy(Value *V) {
|
||||||
|
|
||||||
bool DataFlowSanitizer::init(Module &M) {
|
bool DataFlowSanitizer::init(Module &M) {
|
||||||
Triple TargetTriple(M.getTargetTriple());
|
Triple TargetTriple(M.getTargetTriple());
|
||||||
bool IsX86_64 = TargetTriple.getArch() == Triple::x86_64;
|
|
||||||
bool IsMIPS64 = TargetTriple.isMIPS64();
|
|
||||||
bool IsAArch64 = TargetTriple.getArch() == Triple::aarch64 ||
|
|
||||||
TargetTriple.getArch() == Triple::aarch64_be;
|
|
||||||
|
|
||||||
const DataLayout &DL = M.getDataLayout();
|
const DataLayout &DL = M.getDataLayout();
|
||||||
|
|
||||||
Mod = &M;
|
Mod = &M;
|
||||||
|
@ -941,15 +933,23 @@ bool DataFlowSanitizer::init(Module &M) {
|
||||||
ShadowPtrMul = ConstantInt::getSigned(IntptrTy, ShadowWidthBytes);
|
ShadowPtrMul = ConstantInt::getSigned(IntptrTy, ShadowWidthBytes);
|
||||||
OriginBase = ConstantInt::get(IntptrTy, 0x200000000000LL);
|
OriginBase = ConstantInt::get(IntptrTy, 0x200000000000LL);
|
||||||
ZeroOrigin = ConstantInt::getSigned(OriginTy, 0);
|
ZeroOrigin = ConstantInt::getSigned(OriginTy, 0);
|
||||||
if (IsX86_64)
|
|
||||||
|
switch (TargetTriple.getArch()) {
|
||||||
|
case Triple::x86_64:
|
||||||
ShadowPtrMask = ConstantInt::getSigned(IntptrTy, ~0x700000000000LL);
|
ShadowPtrMask = ConstantInt::getSigned(IntptrTy, ~0x700000000000LL);
|
||||||
else if (IsMIPS64)
|
break;
|
||||||
|
case Triple::mips64:
|
||||||
|
case Triple::mips64el:
|
||||||
ShadowPtrMask = ConstantInt::getSigned(IntptrTy, ~0xF000000000LL);
|
ShadowPtrMask = ConstantInt::getSigned(IntptrTy, ~0xF000000000LL);
|
||||||
// AArch64 supports multiple VMAs and the shadow mask is set at runtime.
|
break;
|
||||||
else if (IsAArch64)
|
case Triple::aarch64:
|
||||||
|
case Triple::aarch64_be:
|
||||||
|
// AArch64 supports multiple VMAs and the shadow mask is set at runtime.
|
||||||
DFSanRuntimeShadowMask = true;
|
DFSanRuntimeShadowMask = true;
|
||||||
else
|
break;
|
||||||
|
default:
|
||||||
report_fatal_error("unsupported triple");
|
report_fatal_error("unsupported triple");
|
||||||
|
}
|
||||||
|
|
||||||
Type *DFSanUnionArgs[2] = {PrimitiveShadowTy, PrimitiveShadowTy};
|
Type *DFSanUnionArgs[2] = {PrimitiveShadowTy, PrimitiveShadowTy};
|
||||||
DFSanUnionFnTy =
|
DFSanUnionFnTy =
|
||||||
|
@ -1059,10 +1059,9 @@ DataFlowSanitizer::buildWrapperFunction(Function *F, StringRef NewFName,
|
||||||
BB);
|
BB);
|
||||||
new UnreachableInst(*Ctx, BB);
|
new UnreachableInst(*Ctx, BB);
|
||||||
} else {
|
} else {
|
||||||
std::vector<Value *> Args;
|
auto ArgIt = pointer_iterator<Argument *>(NewF->arg_begin());
|
||||||
unsigned n = FT->getNumParams();
|
std::vector<Value *> Args(ArgIt, ArgIt + FT->getNumParams());
|
||||||
for (Function::arg_iterator ai = NewF->arg_begin(); n != 0; ++ai, --n)
|
|
||||||
Args.push_back(&*ai);
|
|
||||||
CallInst *CI = CallInst::Create(F, Args, "", BB);
|
CallInst *CI = CallInst::Create(F, Args, "", BB);
|
||||||
if (FT->getReturnType()->isVoidTy())
|
if (FT->getReturnType()->isVoidTy())
|
||||||
ReturnInst::Create(*Ctx, BB);
|
ReturnInst::Create(*Ctx, BB);
|
||||||
|
@ -1082,16 +1081,13 @@ Constant *DataFlowSanitizer::getOrBuildTrampolineFunction(FunctionType *FT,
|
||||||
F->setLinkage(GlobalValue::LinkOnceODRLinkage);
|
F->setLinkage(GlobalValue::LinkOnceODRLinkage);
|
||||||
BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", F);
|
BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", F);
|
||||||
std::vector<Value *> Args;
|
std::vector<Value *> Args;
|
||||||
Function::arg_iterator AI = F->arg_begin(); ++AI;
|
Function::arg_iterator AI = F->arg_begin() + 1;
|
||||||
for (unsigned N = FT->getNumParams(); N != 0; ++AI, --N)
|
for (unsigned N = FT->getNumParams(); N != 0; ++AI, --N)
|
||||||
Args.push_back(&*AI);
|
Args.push_back(&*AI);
|
||||||
CallInst *CI = CallInst::Create(FT, &*F->arg_begin(), Args, "", BB);
|
CallInst *CI = CallInst::Create(FT, &*F->arg_begin(), Args, "", BB);
|
||||||
ReturnInst *RI;
|
|
||||||
Type *RetType = FT->getReturnType();
|
Type *RetType = FT->getReturnType();
|
||||||
if (RetType->isVoidTy())
|
ReturnInst *RI = RetType->isVoidTy() ? ReturnInst::Create(*Ctx, BB)
|
||||||
RI = ReturnInst::Create(*Ctx, BB);
|
: ReturnInst::Create(*Ctx, CI, BB);
|
||||||
else
|
|
||||||
RI = ReturnInst::Create(*Ctx, CI, BB);
|
|
||||||
|
|
||||||
// F is called by a wrapped custom function with primitive shadows. So
|
// F is called by a wrapped custom function with primitive shadows. So
|
||||||
// its arguments and return value need conversion.
|
// its arguments and return value need conversion.
|
||||||
|
@ -1299,7 +1295,7 @@ bool DataFlowSanitizer::runImpl(Module &M) {
|
||||||
|
|
||||||
bool Changed = false;
|
bool Changed = false;
|
||||||
|
|
||||||
auto getOrInsertGlobal = [this, &Changed](StringRef Name,
|
auto GetOrInsertGlobal = [this, &Changed](StringRef Name,
|
||||||
Type *Ty) -> Constant * {
|
Type *Ty) -> Constant * {
|
||||||
Constant *C = Mod->getOrInsertGlobal(Name, Ty);
|
Constant *C = Mod->getOrInsertGlobal(Name, Ty);
|
||||||
if (GlobalVariable *G = dyn_cast<GlobalVariable>(C)) {
|
if (GlobalVariable *G = dyn_cast<GlobalVariable>(C)) {
|
||||||
|
@ -1310,15 +1306,15 @@ bool DataFlowSanitizer::runImpl(Module &M) {
|
||||||
};
|
};
|
||||||
|
|
||||||
// These globals must be kept in sync with the ones in dfsan.cpp.
|
// These globals must be kept in sync with the ones in dfsan.cpp.
|
||||||
ArgTLS = getOrInsertGlobal(
|
ArgTLS =
|
||||||
"__dfsan_arg_tls",
|
GetOrInsertGlobal("__dfsan_arg_tls",
|
||||||
ArrayType::get(Type::getInt64Ty(*Ctx), kArgTLSSize / 8));
|
ArrayType::get(Type::getInt64Ty(*Ctx), ArgTLSSize / 8));
|
||||||
RetvalTLS = getOrInsertGlobal(
|
RetvalTLS = GetOrInsertGlobal(
|
||||||
"__dfsan_retval_tls",
|
"__dfsan_retval_tls",
|
||||||
ArrayType::get(Type::getInt64Ty(*Ctx), kRetvalTLSSize / 8));
|
ArrayType::get(Type::getInt64Ty(*Ctx), RetvalTLSSize / 8));
|
||||||
ArgOriginTLSTy = ArrayType::get(OriginTy, kNumOfElementsInArgOrgTLS);
|
ArgOriginTLSTy = ArrayType::get(OriginTy, NumOfElementsInArgOrgTLS);
|
||||||
ArgOriginTLS = getOrInsertGlobal("__dfsan_arg_origin_tls", ArgOriginTLSTy);
|
ArgOriginTLS = GetOrInsertGlobal("__dfsan_arg_origin_tls", ArgOriginTLSTy);
|
||||||
RetvalOriginTLS = getOrInsertGlobal("__dfsan_retval_origin_tls", OriginTy);
|
RetvalOriginTLS = GetOrInsertGlobal("__dfsan_retval_origin_tls", OriginTy);
|
||||||
|
|
||||||
(void)Mod->getOrInsertGlobal("__dfsan_track_origins", OriginTy, [&] {
|
(void)Mod->getOrInsertGlobal("__dfsan_track_origins", OriginTy, [&] {
|
||||||
Changed = true;
|
Changed = true;
|
||||||
|
@ -1331,39 +1327,42 @@ bool DataFlowSanitizer::runImpl(Module &M) {
|
||||||
injectMetadataGlobals(M);
|
injectMetadataGlobals(M);
|
||||||
|
|
||||||
ExternalShadowMask =
|
ExternalShadowMask =
|
||||||
Mod->getOrInsertGlobal(kDFSanExternShadowPtrMask, IntptrTy);
|
Mod->getOrInsertGlobal(DFSanExternShadowPtrMask, IntptrTy);
|
||||||
|
|
||||||
initializeCallbackFunctions(M);
|
initializeCallbackFunctions(M);
|
||||||
initializeRuntimeFunctions(M);
|
initializeRuntimeFunctions(M);
|
||||||
|
|
||||||
std::vector<Function *> FnsToInstrument;
|
std::vector<Function *> FnsToInstrument;
|
||||||
SmallPtrSet<Function *, 2> FnsWithNativeABI;
|
SmallPtrSet<Function *, 2> FnsWithNativeABI;
|
||||||
for (Function &i : M)
|
for (Function &F : M)
|
||||||
if (!i.isIntrinsic() && !DFSanRuntimeFunctions.contains(&i))
|
if (!F.isIntrinsic() && !DFSanRuntimeFunctions.contains(&F))
|
||||||
FnsToInstrument.push_back(&i);
|
FnsToInstrument.push_back(&F);
|
||||||
|
|
||||||
// Give function aliases prefixes when necessary, and build wrappers where the
|
// Give function aliases prefixes when necessary, and build wrappers where the
|
||||||
// instrumentedness is inconsistent.
|
// instrumentedness is inconsistent.
|
||||||
for (Module::alias_iterator i = M.alias_begin(), e = M.alias_end(); i != e;) {
|
for (Module::alias_iterator AI = M.alias_begin(), AE = M.alias_end();
|
||||||
GlobalAlias *GA = &*i;
|
AI != AE;) {
|
||||||
++i;
|
GlobalAlias *GA = &*AI;
|
||||||
|
++AI;
|
||||||
// Don't stop on weak. We assume people aren't playing games with the
|
// Don't stop on weak. We assume people aren't playing games with the
|
||||||
// instrumentedness of overridden weak aliases.
|
// instrumentedness of overridden weak aliases.
|
||||||
if (auto F = dyn_cast<Function>(GA->getBaseObject())) {
|
auto *F = dyn_cast<Function>(GA->getBaseObject());
|
||||||
bool GAInst = isInstrumented(GA), FInst = isInstrumented(F);
|
if (!F)
|
||||||
if (GAInst && FInst) {
|
continue;
|
||||||
addGlobalNamePrefix(GA);
|
|
||||||
} else if (GAInst != FInst) {
|
bool GAInst = isInstrumented(GA), FInst = isInstrumented(F);
|
||||||
// Non-instrumented alias of an instrumented function, or vice versa.
|
if (GAInst && FInst) {
|
||||||
// Replace the alias with a native-ABI wrapper of the aliasee. The pass
|
addGlobalNamePrefix(GA);
|
||||||
// below will take care of instrumenting it.
|
} else if (GAInst != FInst) {
|
||||||
Function *NewF =
|
// Non-instrumented alias of an instrumented function, or vice versa.
|
||||||
buildWrapperFunction(F, "", GA->getLinkage(), F->getFunctionType());
|
// Replace the alias with a native-ABI wrapper of the aliasee. The pass
|
||||||
GA->replaceAllUsesWith(ConstantExpr::getBitCast(NewF, GA->getType()));
|
// below will take care of instrumenting it.
|
||||||
NewF->takeName(GA);
|
Function *NewF =
|
||||||
GA->eraseFromParent();
|
buildWrapperFunction(F, "", GA->getLinkage(), F->getFunctionType());
|
||||||
FnsToInstrument.push_back(NewF);
|
GA->replaceAllUsesWith(ConstantExpr::getBitCast(NewF, GA->getType()));
|
||||||
}
|
NewF->takeName(GA);
|
||||||
|
GA->eraseFromParent();
|
||||||
|
FnsToInstrument.push_back(NewF);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1372,10 +1371,10 @@ bool DataFlowSanitizer::runImpl(Module &M) {
|
||||||
|
|
||||||
// First, change the ABI of every function in the module. ABI-listed
|
// First, change the ABI of every function in the module. ABI-listed
|
||||||
// functions keep their original ABI and get a wrapper function.
|
// functions keep their original ABI and get a wrapper function.
|
||||||
for (std::vector<Function *>::iterator i = FnsToInstrument.begin(),
|
for (std::vector<Function *>::iterator FI = FnsToInstrument.begin(),
|
||||||
e = FnsToInstrument.end();
|
FE = FnsToInstrument.end();
|
||||||
i != e; ++i) {
|
FI != FE; ++FI) {
|
||||||
Function &F = **i;
|
Function &F = **FI;
|
||||||
FunctionType *FT = F.getFunctionType();
|
FunctionType *FT = F.getFunctionType();
|
||||||
|
|
||||||
bool IsZeroArgsVoidRet = (FT->getNumParams() == 0 && !FT->isVarArg() &&
|
bool IsZeroArgsVoidRet = (FT->getNumParams() == 0 && !FT->isVarArg() &&
|
||||||
|
@ -1414,7 +1413,7 @@ bool DataFlowSanitizer::runImpl(Module &M) {
|
||||||
ConstantExpr::getBitCast(NewF, PointerType::getUnqual(FT)));
|
ConstantExpr::getBitCast(NewF, PointerType::getUnqual(FT)));
|
||||||
NewF->takeName(&F);
|
NewF->takeName(&F);
|
||||||
F.eraseFromParent();
|
F.eraseFromParent();
|
||||||
*i = NewF;
|
*FI = NewF;
|
||||||
addGlobalNamePrefix(NewF);
|
addGlobalNamePrefix(NewF);
|
||||||
} else {
|
} else {
|
||||||
addGlobalNamePrefix(&F);
|
addGlobalNamePrefix(&F);
|
||||||
|
@ -1423,22 +1422,20 @@ bool DataFlowSanitizer::runImpl(Module &M) {
|
||||||
// Build a wrapper function for F. The wrapper simply calls F, and is
|
// Build a wrapper function for F. The wrapper simply calls F, and is
|
||||||
// added to FnsToInstrument so that any instrumentation according to its
|
// added to FnsToInstrument so that any instrumentation according to its
|
||||||
// WrapperKind is done in the second pass below.
|
// WrapperKind is done in the second pass below.
|
||||||
FunctionType *NewFT = getInstrumentedABI() == IA_Args
|
FunctionType *NewFT =
|
||||||
? getArgsFunctionType(FT)
|
getInstrumentedABI() == IA_Args ? getArgsFunctionType(FT) : FT;
|
||||||
: FT;
|
|
||||||
|
|
||||||
// If the function being wrapped has local linkage, then preserve the
|
// If the function being wrapped has local linkage, then preserve the
|
||||||
// function's linkage in the wrapper function.
|
// function's linkage in the wrapper function.
|
||||||
GlobalValue::LinkageTypes wrapperLinkage =
|
GlobalValue::LinkageTypes WrapperLinkage =
|
||||||
F.hasLocalLinkage()
|
F.hasLocalLinkage() ? F.getLinkage()
|
||||||
? F.getLinkage()
|
: GlobalValue::LinkOnceODRLinkage;
|
||||||
: GlobalValue::LinkOnceODRLinkage;
|
|
||||||
|
|
||||||
Function *NewF = buildWrapperFunction(
|
Function *NewF = buildWrapperFunction(
|
||||||
&F,
|
&F,
|
||||||
(shouldTrackOrigins() ? std::string("dfso$") : std::string("dfsw$")) +
|
(shouldTrackOrigins() ? std::string("dfso$") : std::string("dfsw$")) +
|
||||||
std::string(F.getName()),
|
std::string(F.getName()),
|
||||||
wrapperLinkage, NewFT);
|
WrapperLinkage, NewFT);
|
||||||
if (getInstrumentedABI() == IA_TLS)
|
if (getInstrumentedABI() == IA_TLS)
|
||||||
NewF->removeAttributes(AttributeList::FunctionIndex, ReadOnlyNoneAttrs);
|
NewF->removeAttributes(AttributeList::FunctionIndex, ReadOnlyNoneAttrs);
|
||||||
|
|
||||||
|
@ -1447,7 +1444,7 @@ bool DataFlowSanitizer::runImpl(Module &M) {
|
||||||
F.replaceAllUsesWith(WrappedFnCst);
|
F.replaceAllUsesWith(WrappedFnCst);
|
||||||
|
|
||||||
UnwrappedFnMap[WrappedFnCst] = &F;
|
UnwrappedFnMap[WrappedFnCst] = &F;
|
||||||
*i = NewF;
|
*FI = NewF;
|
||||||
|
|
||||||
if (!F.isDeclaration()) {
|
if (!F.isDeclaration()) {
|
||||||
// This function is probably defining an interposition of an
|
// This function is probably defining an interposition of an
|
||||||
|
@ -1459,34 +1456,34 @@ bool DataFlowSanitizer::runImpl(Module &M) {
|
||||||
// This code needs to rebuild the iterators, as they may be invalidated
|
// This code needs to rebuild the iterators, as they may be invalidated
|
||||||
// by the push_back, taking care that the new range does not include
|
// by the push_back, taking care that the new range does not include
|
||||||
// any functions added by this code.
|
// any functions added by this code.
|
||||||
size_t N = i - FnsToInstrument.begin(),
|
size_t N = FI - FnsToInstrument.begin(),
|
||||||
Count = e - FnsToInstrument.begin();
|
Count = FE - FnsToInstrument.begin();
|
||||||
FnsToInstrument.push_back(&F);
|
FnsToInstrument.push_back(&F);
|
||||||
i = FnsToInstrument.begin() + N;
|
FI = FnsToInstrument.begin() + N;
|
||||||
e = FnsToInstrument.begin() + Count;
|
FE = FnsToInstrument.begin() + Count;
|
||||||
}
|
}
|
||||||
// Hopefully, nobody will try to indirectly call a vararg
|
// Hopefully, nobody will try to indirectly call a vararg
|
||||||
// function... yet.
|
// function... yet.
|
||||||
} else if (FT->isVarArg()) {
|
} else if (FT->isVarArg()) {
|
||||||
UnwrappedFnMap[&F] = &F;
|
UnwrappedFnMap[&F] = &F;
|
||||||
*i = nullptr;
|
*FI = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Function *i : FnsToInstrument) {
|
for (Function *F : FnsToInstrument) {
|
||||||
if (!i || i->isDeclaration())
|
if (!F || F->isDeclaration())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
removeUnreachableBlocks(*i);
|
removeUnreachableBlocks(*F);
|
||||||
|
|
||||||
DFSanFunction DFSF(*this, i, FnsWithNativeABI.count(i));
|
DFSanFunction DFSF(*this, F, FnsWithNativeABI.count(F));
|
||||||
|
|
||||||
// DFSanVisitor may create new basic blocks, which confuses df_iterator.
|
// DFSanVisitor may create new basic blocks, which confuses df_iterator.
|
||||||
// Build a copy of the list before iterating over it.
|
// Build a copy of the list before iterating over it.
|
||||||
SmallVector<BasicBlock *, 4> BBList(depth_first(&i->getEntryBlock()));
|
SmallVector<BasicBlock *, 4> BBList(depth_first(&F->getEntryBlock()));
|
||||||
|
|
||||||
for (BasicBlock *i : BBList) {
|
for (BasicBlock *BB : BBList) {
|
||||||
Instruction *Inst = &i->front();
|
Instruction *Inst = &BB->front();
|
||||||
while (true) {
|
while (true) {
|
||||||
// DFSanVisitor may split the current basic block, changing the current
|
// DFSanVisitor may split the current basic block, changing the current
|
||||||
// instruction's next pointer and moving the next instruction to the
|
// instruction's next pointer and moving the next instruction to the
|
||||||
|
@ -1507,14 +1504,12 @@ bool DataFlowSanitizer::runImpl(Module &M) {
|
||||||
// until we have visited every block. Therefore, the code that handles phi
|
// until we have visited every block. Therefore, the code that handles phi
|
||||||
// nodes adds them to the PHIFixups list so that they can be properly
|
// nodes adds them to the PHIFixups list so that they can be properly
|
||||||
// handled here.
|
// handled here.
|
||||||
for (std::vector<std::pair<PHINode *, PHINode *>>::iterator
|
for (auto PHIFixup : DFSF.PHIFixups) {
|
||||||
i = DFSF.PHIFixups.begin(),
|
PHINode *PN, *ShadowPN;
|
||||||
e = DFSF.PHIFixups.end();
|
std::tie(PN, ShadowPN) = PHIFixup;
|
||||||
i != e; ++i) {
|
for (unsigned Val = 0, N = PN->getNumIncomingValues(); Val < N; ++Val) {
|
||||||
for (unsigned val = 0, n = i->first->getNumIncomingValues(); val != n;
|
ShadowPN->setIncomingValue(Val,
|
||||||
++val) {
|
DFSF.getShadow(PN->getIncomingValue(Val)));
|
||||||
i->second->setIncomingValue(
|
|
||||||
val, DFSF.getShadow(i->first->getIncomingValue(val)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1578,7 +1573,7 @@ Value *DFSanFunction::getOrigin(Value *V) {
|
||||||
return DFS.ZeroOrigin;
|
return DFS.ZeroOrigin;
|
||||||
switch (IA) {
|
switch (IA) {
|
||||||
case DataFlowSanitizer::IA_TLS: {
|
case DataFlowSanitizer::IA_TLS: {
|
||||||
if (A->getArgNo() < DFS.kNumOfElementsInArgOrgTLS) {
|
if (A->getArgNo() < DFS.NumOfElementsInArgOrgTLS) {
|
||||||
Instruction *ArgOriginTLSPos = &*F->getEntryBlock().begin();
|
Instruction *ArgOriginTLSPos = &*F->getEntryBlock().begin();
|
||||||
IRBuilder<> IRB(ArgOriginTLSPos);
|
IRBuilder<> IRB(ArgOriginTLSPos);
|
||||||
Value *ArgOriginPtr = getArgOriginTLS(A->getArgNo(), IRB);
|
Value *ArgOriginPtr = getArgOriginTLS(A->getArgNo(), IRB);
|
||||||
|
@ -1621,20 +1616,20 @@ Value *DFSanFunction::getShadowForTLSArgument(Argument *A) {
|
||||||
|
|
||||||
unsigned Size = DL.getTypeAllocSize(DFS.getShadowTy(&FArg));
|
unsigned Size = DL.getTypeAllocSize(DFS.getShadowTy(&FArg));
|
||||||
if (A != &FArg) {
|
if (A != &FArg) {
|
||||||
ArgOffset += alignTo(Size, kShadowTLSAlignment);
|
ArgOffset += alignTo(Size, ShadowTLSAlignment);
|
||||||
if (ArgOffset > kArgTLSSize)
|
if (ArgOffset > ArgTLSSize)
|
||||||
break; // ArgTLS overflows, uses a zero shadow.
|
break; // ArgTLS overflows, uses a zero shadow.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ArgOffset + Size > kArgTLSSize)
|
if (ArgOffset + Size > ArgTLSSize)
|
||||||
break; // ArgTLS overflows, uses a zero shadow.
|
break; // ArgTLS overflows, uses a zero shadow.
|
||||||
|
|
||||||
Instruction *ArgTLSPos = &*F->getEntryBlock().begin();
|
Instruction *ArgTLSPos = &*F->getEntryBlock().begin();
|
||||||
IRBuilder<> IRB(ArgTLSPos);
|
IRBuilder<> IRB(ArgTLSPos);
|
||||||
Value *ArgShadowPtr = getArgTLS(FArg.getType(), ArgOffset, IRB);
|
Value *ArgShadowPtr = getArgTLS(FArg.getType(), ArgOffset, IRB);
|
||||||
return IRB.CreateAlignedLoad(DFS.getShadowTy(&FArg), ArgShadowPtr,
|
return IRB.CreateAlignedLoad(DFS.getShadowTy(&FArg), ArgShadowPtr,
|
||||||
kShadowTLSAlignment);
|
ShadowTLSAlignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
return DFS.getZeroShadow(A);
|
return DFS.getZeroShadow(A);
|
||||||
|
@ -1655,10 +1650,9 @@ Value *DFSanFunction::getShadow(Value *V) {
|
||||||
}
|
}
|
||||||
case DataFlowSanitizer::IA_Args: {
|
case DataFlowSanitizer::IA_Args: {
|
||||||
unsigned ArgIdx = A->getArgNo() + F->arg_size() / 2;
|
unsigned ArgIdx = A->getArgNo() + F->arg_size() / 2;
|
||||||
Function::arg_iterator i = F->arg_begin();
|
Function::arg_iterator Arg = F->arg_begin();
|
||||||
while (ArgIdx--)
|
std::advance(Arg, ArgIdx);
|
||||||
++i;
|
Shadow = &*Arg;
|
||||||
Shadow = &*i;
|
|
||||||
assert(Shadow->getType() == DFS.PrimitiveShadowTy);
|
assert(Shadow->getType() == DFS.PrimitiveShadowTy);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1704,8 +1698,8 @@ DataFlowSanitizer::getShadowOriginAddress(Value *Addr, Align InstAlignment,
|
||||||
const Align Alignment = llvm::assumeAligned(InstAlignment.value());
|
const Align Alignment = llvm::assumeAligned(InstAlignment.value());
|
||||||
// When alignment is >= 4, Addr must be aligned to 4, otherwise it is UB.
|
// When alignment is >= 4, Addr must be aligned to 4, otherwise it is UB.
|
||||||
// So Mask is unnecessary.
|
// So Mask is unnecessary.
|
||||||
if (Alignment < kMinOriginAlignment) {
|
if (Alignment < MinOriginAlignment) {
|
||||||
uint64_t Mask = kMinOriginAlignment.value() - 1;
|
uint64_t Mask = MinOriginAlignment.value() - 1;
|
||||||
OriginLong = IRB.CreateAnd(OriginLong, ConstantInt::get(IntptrTy, ~Mask));
|
OriginLong = IRB.CreateAnd(OriginLong, ConstantInt::get(IntptrTy, ~Mask));
|
||||||
}
|
}
|
||||||
OriginPtr = IRB.CreateIntToPtr(OriginLong, OriginPtrTy);
|
OriginPtr = IRB.CreateIntToPtr(OriginLong, OriginPtrTy);
|
||||||
|
@ -1743,8 +1737,9 @@ Value *DFSanFunction::combineShadows(Value *V1, Value *V2, Instruction *Pos) {
|
||||||
if (std::includes(V1Elems->second.begin(), V1Elems->second.end(),
|
if (std::includes(V1Elems->second.begin(), V1Elems->second.end(),
|
||||||
V2Elems->second.begin(), V2Elems->second.end())) {
|
V2Elems->second.begin(), V2Elems->second.end())) {
|
||||||
return collapseToPrimitiveShadow(V1, Pos);
|
return collapseToPrimitiveShadow(V1, Pos);
|
||||||
} else if (std::includes(V2Elems->second.begin(), V2Elems->second.end(),
|
}
|
||||||
V1Elems->second.begin(), V1Elems->second.end())) {
|
if (std::includes(V2Elems->second.begin(), V2Elems->second.end(),
|
||||||
|
V1Elems->second.begin(), V1Elems->second.end())) {
|
||||||
return collapseToPrimitiveShadow(V2, Pos);
|
return collapseToPrimitiveShadow(V2, Pos);
|
||||||
}
|
}
|
||||||
} else if (V1Elems != ShadowElements.end()) {
|
} else if (V1Elems != ShadowElements.end()) {
|
||||||
|
@ -1823,9 +1818,9 @@ Value *DFSanFunction::combineOperandShadows(Instruction *Inst) {
|
||||||
return DFS.getZeroShadow(Inst);
|
return DFS.getZeroShadow(Inst);
|
||||||
|
|
||||||
Value *Shadow = getShadow(Inst->getOperand(0));
|
Value *Shadow = getShadow(Inst->getOperand(0));
|
||||||
for (unsigned i = 1, n = Inst->getNumOperands(); i != n; ++i) {
|
for (unsigned I = 1, N = Inst->getNumOperands(); I < N; ++I)
|
||||||
Shadow = combineShadows(Shadow, getShadow(Inst->getOperand(i)), Inst);
|
Shadow = combineShadows(Shadow, getShadow(Inst->getOperand(I)), Inst);
|
||||||
}
|
|
||||||
return expandFromPrimitiveShadow(Inst->getType(), Shadow, Inst);
|
return expandFromPrimitiveShadow(Inst->getType(), Shadow, Inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1985,10 +1980,10 @@ Value *DFSanFunction::loadLegacyShadowFast(Value *ShadowAddr, uint64_t Size,
|
||||||
Value *DFSanFunction::loadShadow(Value *Addr, uint64_t Size, uint64_t Align,
|
Value *DFSanFunction::loadShadow(Value *Addr, uint64_t Size, uint64_t Align,
|
||||||
Instruction *Pos) {
|
Instruction *Pos) {
|
||||||
if (AllocaInst *AI = dyn_cast<AllocaInst>(Addr)) {
|
if (AllocaInst *AI = dyn_cast<AllocaInst>(Addr)) {
|
||||||
const auto i = AllocaShadowMap.find(AI);
|
const auto I = AllocaShadowMap.find(AI);
|
||||||
if (i != AllocaShadowMap.end()) {
|
if (I != AllocaShadowMap.end()) {
|
||||||
IRBuilder<> IRB(Pos);
|
IRBuilder<> IRB(Pos);
|
||||||
return IRB.CreateLoad(DFS.PrimitiveShadowTy, i->second);
|
return IRB.CreateLoad(DFS.PrimitiveShadowTy, I->second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2116,10 +2111,10 @@ void DFSanFunction::storePrimitiveShadow(Value *Addr, uint64_t Size,
|
||||||
Value *PrimitiveShadow,
|
Value *PrimitiveShadow,
|
||||||
Instruction *Pos) {
|
Instruction *Pos) {
|
||||||
if (AllocaInst *AI = dyn_cast<AllocaInst>(Addr)) {
|
if (AllocaInst *AI = dyn_cast<AllocaInst>(Addr)) {
|
||||||
const auto i = AllocaShadowMap.find(AI);
|
const auto I = AllocaShadowMap.find(AI);
|
||||||
if (i != AllocaShadowMap.end()) {
|
if (I != AllocaShadowMap.end()) {
|
||||||
IRBuilder<> IRB(Pos);
|
IRBuilder<> IRB(Pos);
|
||||||
IRB.CreateStore(PrimitiveShadow, i->second);
|
IRB.CreateStore(PrimitiveShadow, I->second);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2138,10 +2133,10 @@ void DFSanFunction::storePrimitiveShadow(Value *Addr, uint64_t Size,
|
||||||
auto *ShadowVecTy =
|
auto *ShadowVecTy =
|
||||||
FixedVectorType::get(DFS.PrimitiveShadowTy, ShadowVecSize);
|
FixedVectorType::get(DFS.PrimitiveShadowTy, ShadowVecSize);
|
||||||
Value *ShadowVec = UndefValue::get(ShadowVecTy);
|
Value *ShadowVec = UndefValue::get(ShadowVecTy);
|
||||||
for (unsigned i = 0; i != ShadowVecSize; ++i) {
|
for (unsigned I = 0; I != ShadowVecSize; ++I) {
|
||||||
ShadowVec = IRB.CreateInsertElement(
|
ShadowVec = IRB.CreateInsertElement(
|
||||||
ShadowVec, PrimitiveShadow,
|
ShadowVec, PrimitiveShadow,
|
||||||
ConstantInt::get(Type::getInt32Ty(*DFS.Ctx), i));
|
ConstantInt::get(Type::getInt32Ty(*DFS.Ctx), I));
|
||||||
}
|
}
|
||||||
Value *ShadowVecAddr =
|
Value *ShadowVecAddr =
|
||||||
IRB.CreateBitCast(ShadowAddr, PointerType::getUnqual(ShadowVecTy));
|
IRB.CreateBitCast(ShadowAddr, PointerType::getUnqual(ShadowVecTy));
|
||||||
|
@ -2431,11 +2426,11 @@ void DFSanVisitor::visitReturnInst(ReturnInst &RI) {
|
||||||
Type *RT = DFSF.F->getFunctionType()->getReturnType();
|
Type *RT = DFSF.F->getFunctionType()->getReturnType();
|
||||||
unsigned Size =
|
unsigned Size =
|
||||||
getDataLayout().getTypeAllocSize(DFSF.DFS.getShadowTy(RT));
|
getDataLayout().getTypeAllocSize(DFSF.DFS.getShadowTy(RT));
|
||||||
if (Size <= kRetvalTLSSize) {
|
if (Size <= RetvalTLSSize) {
|
||||||
// If the size overflows, stores nothing. At callsite, oversized return
|
// If the size overflows, stores nothing. At callsite, oversized return
|
||||||
// shadows are set to zero.
|
// shadows are set to zero.
|
||||||
IRB.CreateAlignedStore(S, DFSF.getRetvalTLS(RT, IRB),
|
IRB.CreateAlignedStore(S, DFSF.getRetvalTLS(RT, IRB),
|
||||||
kShadowTLSAlignment);
|
ShadowTLSAlignment);
|
||||||
}
|
}
|
||||||
if (DFSF.DFS.shouldTrackOrigins()) {
|
if (DFSF.DFS.shouldTrackOrigins()) {
|
||||||
Value *O = DFSF.getOrigin(RI.getReturnValue());
|
Value *O = DFSF.getOrigin(RI.getReturnValue());
|
||||||
|
@ -2582,14 +2577,13 @@ bool DFSanVisitor::visitWrappedCallBase(Function &F, CallBase &CB) {
|
||||||
|
|
||||||
// Adds non-variable arguments.
|
// Adds non-variable arguments.
|
||||||
auto *I = CB.arg_begin();
|
auto *I = CB.arg_begin();
|
||||||
for (unsigned n = FT->getNumParams(); n != 0; ++I, --n) {
|
for (unsigned N = FT->getNumParams(); N != 0; ++I, --N) {
|
||||||
Type *T = (*I)->getType();
|
Type *T = (*I)->getType();
|
||||||
FunctionType *ParamFT;
|
FunctionType *ParamFT;
|
||||||
if (isa<PointerType>(T) &&
|
if (isa<PointerType>(T) &&
|
||||||
(ParamFT = dyn_cast<FunctionType>(
|
(ParamFT = dyn_cast<FunctionType>(T->getPointerElementType()))) {
|
||||||
cast<PointerType>(T)->getElementType()))) {
|
|
||||||
std::string TName = "dfst";
|
std::string TName = "dfst";
|
||||||
TName += utostr(FT->getNumParams() - n);
|
TName += utostr(FT->getNumParams() - N);
|
||||||
TName += "$";
|
TName += "$";
|
||||||
TName += F.getName();
|
TName += F.getName();
|
||||||
Constant *T = DFSF.DFS.getOrBuildTrampolineFunction(ParamFT, TName);
|
Constant *T = DFSF.DFS.getOrBuildTrampolineFunction(ParamFT, TName);
|
||||||
|
@ -2615,7 +2609,7 @@ bool DFSanVisitor::visitWrappedCallBase(Function &F, CallBase &CB) {
|
||||||
|
|
||||||
CallInst *CustomCI = IRB.CreateCall(CustomF, Args);
|
CallInst *CustomCI = IRB.CreateCall(CustomF, Args);
|
||||||
CustomCI->setCallingConv(CI->getCallingConv());
|
CustomCI->setCallingConv(CI->getCallingConv());
|
||||||
CustomCI->setAttributes(TransformFunctionAttributes(
|
CustomCI->setAttributes(transformFunctionAttributes(
|
||||||
CustomFn, CI->getContext(), CI->getAttributes()));
|
CustomFn, CI->getContext(), CI->getAttributes()));
|
||||||
|
|
||||||
// Update the parameter attributes of the custom call instruction to
|
// Update the parameter attributes of the custom call instruction to
|
||||||
|
@ -2666,10 +2660,10 @@ void DFSanVisitor::visitCallBase(CallBase &CB) {
|
||||||
if (F == DFSF.DFS.DFSanVarargWrapperFn.getCallee()->stripPointerCasts())
|
if (F == DFSF.DFS.DFSanVarargWrapperFn.getCallee()->stripPointerCasts())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
DenseMap<Value *, Function *>::iterator i =
|
DenseMap<Value *, Function *>::iterator UnwrappedFnIt =
|
||||||
DFSF.DFS.UnwrappedFnMap.find(CB.getCalledOperand());
|
DFSF.DFS.UnwrappedFnMap.find(CB.getCalledOperand());
|
||||||
if (i != DFSF.DFS.UnwrappedFnMap.end())
|
if (UnwrappedFnIt != DFSF.DFS.UnwrappedFnMap.end())
|
||||||
if (visitWrappedCallBase(*i->second, CB))
|
if (visitWrappedCallBase(*UnwrappedFnIt->second, CB))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
IRBuilder<> IRB(&CB);
|
IRBuilder<> IRB(&CB);
|
||||||
|
@ -2684,7 +2678,7 @@ void DFSanVisitor::visitCallBase(CallBase &CB) {
|
||||||
if (ShouldTrackOrigins) {
|
if (ShouldTrackOrigins) {
|
||||||
// Ignore overflowed origins
|
// Ignore overflowed origins
|
||||||
Value *ArgShadow = DFSF.getShadow(CB.getArgOperand(I));
|
Value *ArgShadow = DFSF.getShadow(CB.getArgOperand(I));
|
||||||
if (I < DFSF.DFS.kNumOfElementsInArgOrgTLS &&
|
if (I < DFSF.DFS.NumOfElementsInArgOrgTLS &&
|
||||||
!DFSF.DFS.isZeroShadow(ArgShadow))
|
!DFSF.DFS.isZeroShadow(ArgShadow))
|
||||||
IRB.CreateStore(DFSF.getOrigin(CB.getArgOperand(I)),
|
IRB.CreateStore(DFSF.getOrigin(CB.getArgOperand(I)),
|
||||||
DFSF.getArgOriginTLS(I, IRB));
|
DFSF.getArgOriginTLS(I, IRB));
|
||||||
|
@ -2694,13 +2688,13 @@ void DFSanVisitor::visitCallBase(CallBase &CB) {
|
||||||
DL.getTypeAllocSize(DFSF.DFS.getShadowTy(FT->getParamType(I)));
|
DL.getTypeAllocSize(DFSF.DFS.getShadowTy(FT->getParamType(I)));
|
||||||
// Stop storing if arguments' size overflows. Inside a function, arguments
|
// Stop storing if arguments' size overflows. Inside a function, arguments
|
||||||
// after overflow have zero shadow values.
|
// after overflow have zero shadow values.
|
||||||
if (ArgOffset + Size > kArgTLSSize)
|
if (ArgOffset + Size > ArgTLSSize)
|
||||||
break;
|
break;
|
||||||
IRB.CreateAlignedStore(
|
IRB.CreateAlignedStore(
|
||||||
DFSF.getShadow(CB.getArgOperand(I)),
|
DFSF.getShadow(CB.getArgOperand(I)),
|
||||||
DFSF.getArgTLS(FT->getParamType(I), ArgOffset, IRB),
|
DFSF.getArgTLS(FT->getParamType(I), ArgOffset, IRB),
|
||||||
kShadowTLSAlignment);
|
ShadowTLSAlignment);
|
||||||
ArgOffset += alignTo(Size, kShadowTLSAlignment);
|
ArgOffset += alignTo(Size, ShadowTLSAlignment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2724,13 +2718,13 @@ void DFSanVisitor::visitCallBase(CallBase &CB) {
|
||||||
IRBuilder<> NextIRB(Next);
|
IRBuilder<> NextIRB(Next);
|
||||||
const DataLayout &DL = getDataLayout();
|
const DataLayout &DL = getDataLayout();
|
||||||
unsigned Size = DL.getTypeAllocSize(DFSF.DFS.getShadowTy(&CB));
|
unsigned Size = DL.getTypeAllocSize(DFSF.DFS.getShadowTy(&CB));
|
||||||
if (Size > kRetvalTLSSize) {
|
if (Size > RetvalTLSSize) {
|
||||||
// Set overflowed return shadow to be zero.
|
// Set overflowed return shadow to be zero.
|
||||||
DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
|
DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
|
||||||
} else {
|
} else {
|
||||||
LoadInst *LI = NextIRB.CreateAlignedLoad(
|
LoadInst *LI = NextIRB.CreateAlignedLoad(
|
||||||
DFSF.DFS.getShadowTy(&CB), DFSF.getRetvalTLS(CB.getType(), NextIRB),
|
DFSF.DFS.getShadowTy(&CB), DFSF.getRetvalTLS(CB.getType(), NextIRB),
|
||||||
kShadowTLSAlignment, "_dfsret");
|
ShadowTLSAlignment, "_dfsret");
|
||||||
DFSF.SkipInsts.insert(LI);
|
DFSF.SkipInsts.insert(LI);
|
||||||
DFSF.setShadow(&CB, LI);
|
DFSF.setShadow(&CB, LI);
|
||||||
DFSF.NonZeroChecks.push_back(LI);
|
DFSF.NonZeroChecks.push_back(LI);
|
||||||
|
@ -2751,30 +2745,35 @@ void DFSanVisitor::visitCallBase(CallBase &CB) {
|
||||||
FunctionType *NewFT = DFSF.DFS.getArgsFunctionType(FT);
|
FunctionType *NewFT = DFSF.DFS.getArgsFunctionType(FT);
|
||||||
Value *Func =
|
Value *Func =
|
||||||
IRB.CreateBitCast(CB.getCalledOperand(), PointerType::getUnqual(NewFT));
|
IRB.CreateBitCast(CB.getCalledOperand(), PointerType::getUnqual(NewFT));
|
||||||
std::vector<Value *> Args;
|
|
||||||
|
|
||||||
auto i = CB.arg_begin(), E = CB.arg_end();
|
const unsigned NumParams = FT->getNumParams();
|
||||||
for (unsigned n = FT->getNumParams(); n != 0; ++i, --n)
|
|
||||||
Args.push_back(*i);
|
|
||||||
|
|
||||||
i = CB.arg_begin();
|
// Copy original arguments.
|
||||||
for (unsigned n = FT->getNumParams(); n != 0; ++i, --n)
|
auto *ArgIt = CB.arg_begin(), *ArgEnd = CB.arg_end();
|
||||||
Args.push_back(DFSF.getShadow(*i));
|
std::vector<Value *> Args(NumParams);
|
||||||
|
std::copy_n(ArgIt, NumParams, Args.begin());
|
||||||
|
|
||||||
|
// Add shadow arguments by transforming original arguments.
|
||||||
|
std::generate_n(std::back_inserter(Args), NumParams,
|
||||||
|
[&]() { return DFSF.getShadow(*ArgIt++); });
|
||||||
|
|
||||||
if (FT->isVarArg()) {
|
if (FT->isVarArg()) {
|
||||||
unsigned VarArgSize = CB.arg_size() - FT->getNumParams();
|
unsigned VarArgSize = CB.arg_size() - NumParams;
|
||||||
ArrayType *VarArgArrayTy =
|
ArrayType *VarArgArrayTy =
|
||||||
ArrayType::get(DFSF.DFS.PrimitiveShadowTy, VarArgSize);
|
ArrayType::get(DFSF.DFS.PrimitiveShadowTy, VarArgSize);
|
||||||
AllocaInst *VarArgShadow =
|
AllocaInst *VarArgShadow =
|
||||||
new AllocaInst(VarArgArrayTy, getDataLayout().getAllocaAddrSpace(),
|
new AllocaInst(VarArgArrayTy, getDataLayout().getAllocaAddrSpace(),
|
||||||
"", &DFSF.F->getEntryBlock().front());
|
"", &DFSF.F->getEntryBlock().front());
|
||||||
Args.push_back(IRB.CreateConstGEP2_32(VarArgArrayTy, VarArgShadow, 0, 0));
|
Args.push_back(IRB.CreateConstGEP2_32(VarArgArrayTy, VarArgShadow, 0, 0));
|
||||||
for (unsigned n = 0; i != E; ++i, ++n) {
|
|
||||||
|
// Copy remaining var args.
|
||||||
|
unsigned GepIndex = 0;
|
||||||
|
std::for_each(ArgIt, ArgEnd, [&](Value *Arg) {
|
||||||
IRB.CreateStore(
|
IRB.CreateStore(
|
||||||
DFSF.getShadow(*i),
|
DFSF.getShadow(Arg),
|
||||||
IRB.CreateConstGEP2_32(VarArgArrayTy, VarArgShadow, 0, n));
|
IRB.CreateConstGEP2_32(VarArgArrayTy, VarArgShadow, 0, GepIndex++));
|
||||||
Args.push_back(*i);
|
Args.push_back(Arg);
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
CallBase *NewCB;
|
CallBase *NewCB;
|
||||||
|
@ -2811,10 +2810,8 @@ void DFSanVisitor::visitPHINode(PHINode &PN) {
|
||||||
|
|
||||||
// Give the shadow phi node valid predecessors to fool SplitEdge into working.
|
// Give the shadow phi node valid predecessors to fool SplitEdge into working.
|
||||||
Value *UndefShadow = UndefValue::get(ShadowTy);
|
Value *UndefShadow = UndefValue::get(ShadowTy);
|
||||||
for (PHINode::block_iterator i = PN.block_begin(), e = PN.block_end(); i != e;
|
for (BasicBlock *BB : PN.blocks())
|
||||||
++i) {
|
ShadowPN->addIncoming(UndefShadow, BB);
|
||||||
ShadowPN->addIncoming(UndefShadow, *i);
|
|
||||||
}
|
|
||||||
|
|
||||||
DFSF.PHIFixups.push_back(std::make_pair(&PN, ShadowPN));
|
DFSF.PHIFixups.push_back(std::make_pair(&PN, ShadowPN));
|
||||||
DFSF.setShadow(&PN, ShadowPN);
|
DFSF.setShadow(&PN, ShadowPN);
|
||||||
|
|
Loading…
Reference in New Issue