#include "llvm/Transforms/Instrumentation/DataFlowSanitizer.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/iterator.h"
#include "llvm/Analysis/DomTreeUpdater.h"
#include "llvm/Analysis/GlobalsModRef.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/Argument.h"
#include "llvm/IR/AttributeMask.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalAlias.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InstVisitor.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/User.h"
#include "llvm/IR/Value.h"
#include "llvm/Support/Alignment.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/SpecialCaseList.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/TargetParser/Triple.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Instrumentation.h"
#include "llvm/Transforms/Utils/Local.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <set>
#include <string>
#include <utility>
#include <vector>
usingnamespacellvm;
static const Align ShadowTLSAlignment = …;
static const Align MinOriginAlignment = …;
static const unsigned ArgTLSSize = …;
static const unsigned RetvalTLSSize = …;
static cl::opt<bool> ClPreserveAlignment(
"dfsan-preserve-alignment",
cl::desc("respect alignment requirements provided by input IR"), cl::Hidden,
cl::init(false));
static cl::list<std::string> ClABIListFiles(
"dfsan-abilist",
cl::desc("File listing native ABI functions and how the pass treats them"),
cl::Hidden);
static cl::opt<bool> ClCombinePointerLabelsOnLoad(
"dfsan-combine-pointer-labels-on-load",
cl::desc("Combine the label of the pointer with the label of the data when "
"loading from memory."),
cl::Hidden, cl::init(true));
static cl::opt<bool> ClCombinePointerLabelsOnStore(
"dfsan-combine-pointer-labels-on-store",
cl::desc("Combine the label of the pointer with the label of the data when "
"storing in memory."),
cl::Hidden, cl::init(false));
static cl::opt<bool> ClCombineOffsetLabelsOnGEP(
"dfsan-combine-offset-labels-on-gep",
cl::desc(
"Combine the label of the offset with the label of the pointer when "
"doing pointer arithmetic."),
cl::Hidden, cl::init(true));
static cl::list<std::string> ClCombineTaintLookupTables(
"dfsan-combine-taint-lookup-table",
cl::desc(
"When dfsan-combine-offset-labels-on-gep and/or "
"dfsan-combine-pointer-labels-on-load are false, this flag can "
"be used to re-enable combining offset and/or pointer taint when "
"loading specific constant global variables (i.e. lookup tables)."),
cl::Hidden);
static cl::opt<bool> ClDebugNonzeroLabels(
"dfsan-debug-nonzero-labels",
cl::desc("Insert calls to __dfsan_nonzero_label on observing a parameter, "
"load or return with a nonzero label"),
cl::Hidden);
static cl::opt<bool> ClEventCallbacks(
"dfsan-event-callbacks",
cl::desc("Insert calls to __dfsan_*_callback functions on data events."),
cl::Hidden, cl::init(false));
static cl::opt<bool> ClConditionalCallbacks(
"dfsan-conditional-callbacks",
cl::desc("Insert calls to callback functions on conditionals."), cl::Hidden,
cl::init(false));
static cl::opt<bool> ClReachesFunctionCallbacks(
"dfsan-reaches-function-callbacks",
cl::desc("Insert calls to callback functions on data reaching a function."),
cl::Hidden, cl::init(false));
static cl::opt<bool> ClTrackSelectControlFlow(
"dfsan-track-select-control-flow",
cl::desc("Propagate labels from condition values of select instructions "
"to results."),
cl::Hidden, cl::init(true));
static cl::opt<int> ClInstrumentWithCallThreshold(
"dfsan-instrument-with-call-threshold",
cl::desc("If the function being instrumented requires more than "
"this number of origin stores, use callbacks instead of "
"inline checks (-1 means never use callbacks)."),
cl::Hidden, cl::init(3500));
static cl::opt<int> ClTrackOrigins("dfsan-track-origins",
cl::desc("Track origins of labels"),
cl::Hidden, cl::init(0));
static cl::opt<bool> ClIgnorePersonalityRoutine(
"dfsan-ignore-personality-routine",
cl::desc("If a personality routine is marked uninstrumented from the ABI "
"list, do not create a wrapper for it."),
cl::Hidden, cl::init(false));
static StringRef getGlobalTypeString(const GlobalValue &G) { … }
namespace {
struct MemoryMapParams { … };
}
const MemoryMapParams Linux_AArch64_MemoryMapParams = …;
const MemoryMapParams Linux_X86_64_MemoryMapParams = …;
const MemoryMapParams Linux_LoongArch64_MemoryMapParams = …;
namespace {
class DFSanABIList { … };
struct TransformedFunction { … };
AttributeList
transformFunctionAttributes(const TransformedFunction &TransformedFunction,
LLVMContext &Ctx, AttributeList CallSiteAttrs) { … }
class DataFlowSanitizer { … };
struct DFSanFunction { … };
class DFSanVisitor : public InstVisitor<DFSanVisitor> { … };
bool LibAtomicFunction(const Function &F) { … }
}
DataFlowSanitizer::DataFlowSanitizer(
const std::vector<std::string> &ABIListFiles) { … }
TransformedFunction DataFlowSanitizer::getCustomFunctionType(FunctionType *T) { … }
bool DataFlowSanitizer::isZeroShadow(Value *V) { … }
bool DataFlowSanitizer::hasLoadSizeForFastPath(uint64_t Size) { … }
bool DataFlowSanitizer::shouldTrackOrigins() { … }
Constant *DataFlowSanitizer::getZeroShadow(Type *OrigTy) { … }
Constant *DataFlowSanitizer::getZeroShadow(Value *V) { … }
static Value *expandFromPrimitiveShadowRecursive(
Value *Shadow, SmallVector<unsigned, 4> &Indices, Type *SubShadowTy,
Value *PrimitiveShadow, IRBuilder<> &IRB) { … }
bool DFSanFunction::shouldInstrumentWithCall() { … }
Value *DFSanFunction::expandFromPrimitiveShadow(Type *T, Value *PrimitiveShadow,
BasicBlock::iterator Pos) { … }
template <class AggregateType>
Value *DFSanFunction::collapseAggregateShadow(AggregateType *AT, Value *Shadow,
IRBuilder<> &IRB) { … }
Value *DFSanFunction::collapseToPrimitiveShadow(Value *Shadow,
IRBuilder<> &IRB) { … }
Value *DFSanFunction::collapseToPrimitiveShadow(Value *Shadow,
BasicBlock::iterator Pos) { … }
void DFSanFunction::addConditionalCallbacksIfEnabled(Instruction &I,
Value *Condition) { … }
void DFSanFunction::addReachesFunctionCallbacksIfEnabled(IRBuilder<> &IRB,
Instruction &I,
Value *Data) { … }
Type *DataFlowSanitizer::getShadowTy(Type *OrigTy) { … }
Type *DataFlowSanitizer::getShadowTy(Value *V) { … }
bool DataFlowSanitizer::initializeModule(Module &M) { … }
bool DataFlowSanitizer::isInstrumented(const Function *F) { … }
bool DataFlowSanitizer::isInstrumented(const GlobalAlias *GA) { … }
bool DataFlowSanitizer::isForceZeroLabels(const Function *F) { … }
DataFlowSanitizer::WrapperKind DataFlowSanitizer::getWrapperKind(Function *F) { … }
void DataFlowSanitizer::addGlobalNameSuffix(GlobalValue *GV) { … }
void DataFlowSanitizer::buildExternWeakCheckIfNeeded(IRBuilder<> &IRB,
Function *F) { … }
Function *
DataFlowSanitizer::buildWrapperFunction(Function *F, StringRef NewFName,
GlobalValue::LinkageTypes NewFLink,
FunctionType *NewFT) { … }
void DataFlowSanitizer::initializeRuntimeFunctions(Module &M) { … }
void DataFlowSanitizer::initializeCallbackFunctions(Module &M) { … }
bool DataFlowSanitizer::runImpl(
Module &M, llvm::function_ref<TargetLibraryInfo &(Function &)> GetTLI) { … }
Value *DFSanFunction::getArgTLS(Type *T, unsigned ArgOffset, IRBuilder<> &IRB) { … }
Value *DFSanFunction::getRetvalTLS(Type *T, IRBuilder<> &IRB) { … }
Value *DFSanFunction::getRetvalOriginTLS() { … }
Value *DFSanFunction::getArgOriginTLS(unsigned ArgNo, IRBuilder<> &IRB) { … }
Value *DFSanFunction::getOrigin(Value *V) { … }
void DFSanFunction::setOrigin(Instruction *I, Value *Origin) { … }
Value *DFSanFunction::getShadowForTLSArgument(Argument *A) { … }
Value *DFSanFunction::getShadow(Value *V) { … }
void DFSanFunction::setShadow(Instruction *I, Value *Shadow) { … }
Value *DataFlowSanitizer::getShadowOffset(Value *Addr, IRBuilder<> &IRB) { … }
std::pair<Value *, Value *>
DataFlowSanitizer::getShadowOriginAddress(Value *Addr, Align InstAlignment,
BasicBlock::iterator Pos) { … }
Value *DataFlowSanitizer::getShadowAddress(Value *Addr,
BasicBlock::iterator Pos,
Value *ShadowOffset) { … }
Value *DataFlowSanitizer::getShadowAddress(Value *Addr,
BasicBlock::iterator Pos) { … }
Value *DFSanFunction::combineShadowsThenConvert(Type *T, Value *V1, Value *V2,
BasicBlock::iterator Pos) { … }
Value *DFSanFunction::combineShadows(Value *V1, Value *V2,
BasicBlock::iterator Pos) { … }
Value *DFSanFunction::combineOperandShadows(Instruction *Inst) { … }
void DFSanVisitor::visitInstOperands(Instruction &I) { … }
Value *DFSanFunction::combineOrigins(const std::vector<Value *> &Shadows,
const std::vector<Value *> &Origins,
BasicBlock::iterator Pos,
ConstantInt *Zero) { … }
Value *DFSanFunction::combineOperandOrigins(Instruction *Inst) { … }
void DFSanVisitor::visitInstOperandOrigins(Instruction &I) { … }
Align DFSanFunction::getShadowAlign(Align InstAlignment) { … }
Align DFSanFunction::getOriginAlign(Align InstAlignment) { … }
bool DFSanFunction::isLookupTableConstant(Value *P) { … }
bool DFSanFunction::useCallbackLoadLabelAndOrigin(uint64_t Size,
Align InstAlignment) { … }
Value *DataFlowSanitizer::loadNextOrigin(BasicBlock::iterator Pos,
Align OriginAlign,
Value **OriginAddr) { … }
std::pair<Value *, Value *> DFSanFunction::loadShadowFast(
Value *ShadowAddr, Value *OriginAddr, uint64_t Size, Align ShadowAlign,
Align OriginAlign, Value *FirstOrigin, BasicBlock::iterator Pos) { … }
std::pair<Value *, Value *> DFSanFunction::loadShadowOriginSansLoadTracking(
Value *Addr, uint64_t Size, Align InstAlignment, BasicBlock::iterator Pos) { … }
std::pair<Value *, Value *>
DFSanFunction::loadShadowOrigin(Value *Addr, uint64_t Size, Align InstAlignment,
BasicBlock::iterator Pos) { … }
static AtomicOrdering addAcquireOrdering(AtomicOrdering AO) { … }
Value *StripPointerGEPsAndCasts(Value *V) { … }
void DFSanVisitor::visitLoadInst(LoadInst &LI) { … }
Value *DFSanFunction::updateOriginIfTainted(Value *Shadow, Value *Origin,
IRBuilder<> &IRB) { … }
Value *DFSanFunction::updateOrigin(Value *V, IRBuilder<> &IRB) { … }
Value *DFSanFunction::originToIntptr(IRBuilder<> &IRB, Value *Origin) { … }
void DFSanFunction::paintOrigin(IRBuilder<> &IRB, Value *Origin,
Value *StoreOriginAddr,
uint64_t StoreOriginSize, Align Alignment) { … }
Value *DFSanFunction::convertToBool(Value *V, IRBuilder<> &IRB,
const Twine &Name) { … }
void DFSanFunction::storeOrigin(BasicBlock::iterator Pos, Value *Addr,
uint64_t Size, Value *Shadow, Value *Origin,
Value *StoreOriginAddr, Align InstAlignment) { … }
void DFSanFunction::storeZeroPrimitiveShadow(Value *Addr, uint64_t Size,
Align ShadowAlign,
BasicBlock::iterator Pos) { … }
void DFSanFunction::storePrimitiveShadowOrigin(Value *Addr, uint64_t Size,
Align InstAlignment,
Value *PrimitiveShadow,
Value *Origin,
BasicBlock::iterator Pos) { … }
static AtomicOrdering addReleaseOrdering(AtomicOrdering AO) { … }
void DFSanVisitor::visitStoreInst(StoreInst &SI) { … }
void DFSanVisitor::visitCASOrRMW(Align InstAlignment, Instruction &I) { … }
void DFSanVisitor::visitAtomicRMWInst(AtomicRMWInst &I) { … }
void DFSanVisitor::visitAtomicCmpXchgInst(AtomicCmpXchgInst &I) { … }
void DFSanVisitor::visitUnaryOperator(UnaryOperator &UO) { … }
void DFSanVisitor::visitBinaryOperator(BinaryOperator &BO) { … }
void DFSanVisitor::visitBitCastInst(BitCastInst &BCI) { … }
void DFSanVisitor::visitCastInst(CastInst &CI) { … }
void DFSanVisitor::visitCmpInst(CmpInst &CI) { … }
void DFSanVisitor::visitLandingPadInst(LandingPadInst &LPI) { … }
void DFSanVisitor::visitGetElementPtrInst(GetElementPtrInst &GEPI) { … }
void DFSanVisitor::visitExtractElementInst(ExtractElementInst &I) { … }
void DFSanVisitor::visitInsertElementInst(InsertElementInst &I) { … }
void DFSanVisitor::visitShuffleVectorInst(ShuffleVectorInst &I) { … }
void DFSanVisitor::visitExtractValueInst(ExtractValueInst &I) { … }
void DFSanVisitor::visitInsertValueInst(InsertValueInst &I) { … }
void DFSanVisitor::visitAllocaInst(AllocaInst &I) { … }
void DFSanVisitor::visitSelectInst(SelectInst &I) { … }
void DFSanVisitor::visitMemSetInst(MemSetInst &I) { … }
void DFSanVisitor::visitMemTransferInst(MemTransferInst &I) { … }
void DFSanVisitor::visitBranchInst(BranchInst &BR) { … }
void DFSanVisitor::visitSwitchInst(SwitchInst &SW) { … }
static bool isAMustTailRetVal(Value *RetVal) { … }
void DFSanVisitor::visitReturnInst(ReturnInst &RI) { … }
void DFSanVisitor::addShadowArguments(Function &F, CallBase &CB,
std::vector<Value *> &Args,
IRBuilder<> &IRB) { … }
void DFSanVisitor::addOriginArguments(Function &F, CallBase &CB,
std::vector<Value *> &Args,
IRBuilder<> &IRB) { … }
bool DFSanVisitor::visitWrappedCallBase(Function &F, CallBase &CB) { … }
Value *DFSanVisitor::makeAddAcquireOrderingTable(IRBuilder<> &IRB) { … }
void DFSanVisitor::visitLibAtomicLoad(CallBase &CB) { … }
Value *DFSanVisitor::makeAddReleaseOrderingTable(IRBuilder<> &IRB) { … }
void DFSanVisitor::visitLibAtomicStore(CallBase &CB) { … }
void DFSanVisitor::visitLibAtomicExchange(CallBase &CB) { … }
void DFSanVisitor::visitLibAtomicCompareExchange(CallBase &CB) { … }
void DFSanVisitor::visitCallBase(CallBase &CB) { … }
void DFSanVisitor::visitPHINode(PHINode &PN) { … }
PreservedAnalyses DataFlowSanitizerPass::run(Module &M,
ModuleAnalysisManager &AM) { … }