139 "dfsan-preserve-alignment",
161 cl::desc(
"File listing native ABI functions and how the pass treats them"),
167 "dfsan-combine-pointer-labels-on-load",
168 cl::desc(
"Combine the label of the pointer with the label of the data when "
169 "loading from memory."),
175 "dfsan-combine-pointer-labels-on-store",
176 cl::desc(
"Combine the label of the pointer with the label of the data when "
177 "storing in memory."),
182 "dfsan-combine-offset-labels-on-gep",
184 "Combine the label of the offset with the label of the pointer when "
185 "doing pointer arithmetic."),
189 "dfsan-combine-taint-lookup-table",
191 "When dfsan-combine-offset-labels-on-gep and/or "
192 "dfsan-combine-pointer-labels-on-load are false, this flag can "
193 "be used to re-enable combining offset and/or pointer taint when "
194 "loading specific constant global variables (i.e. lookup tables)."),
198 "dfsan-debug-nonzero-labels",
199 cl::desc(
"Insert calls to __dfsan_nonzero_label on observing a parameter, "
200 "load or return with a nonzero label"),
214 "dfsan-event-callbacks",
215 cl::desc(
"Insert calls to __dfsan_*_callback functions on data events."),
222 "dfsan-conditional-callbacks",
230 "dfsan-reaches-function-callbacks",
231 cl::desc(
"Insert calls to callback functions on data reaching a function."),
236 "dfsan-track-select-control-flow",
237 cl::desc(
"Propagate labels from condition values of select instructions "
243 "dfsan-instrument-with-call-threshold",
244 cl::desc(
"If the function being instrumented requires more than "
245 "this number of origin stores, use callbacks instead of "
246 "inline checks (-1 means never use callbacks)."),
255 cl::desc(
"Track origins of labels"),
259 "dfsan-ignore-personality-routine",
260 cl::desc(
"If a personality routine is marked uninstrumented from the ABI "
261 "list, do not create a wrapper for it."),
266 Type *GType =
G.getValueType();
268 if (
StructType *SGType = dyn_cast<StructType>(GType)) {
269 if (!SGType->isLiteral())
270 return SGType->getName();
272 return "<unknown type>";
281struct MemoryMapParams {
319 std::unique_ptr<SpecialCaseList> SCL;
322 DFSanABIList() =
default;
324 void set(std::unique_ptr<SpecialCaseList> List) { SCL = std::move(List); }
329 return isIn(*
F.getParent(), Category) ||
330 SCL->inSection(
"dataflow",
"fun",
F.getName(), Category);
342 return SCL->inSection(
"dataflow",
"fun", GA.
getName(), Category);
344 return SCL->inSection(
"dataflow",
"global", GA.
getName(), Category) ||
351 return SCL->inSection(
"dataflow",
"src",
M.getModuleIdentifier(), Category);
358struct TransformedFunction {
360 std::vector<unsigned> ArgumentIndexMapping)
362 ArgumentIndexMapping(ArgumentIndexMapping) {}
365 TransformedFunction(
const TransformedFunction &) =
delete;
366 TransformedFunction &operator=(
const TransformedFunction &) =
delete;
369 TransformedFunction(TransformedFunction &&) =
default;
370 TransformedFunction &operator=(TransformedFunction &&) =
default;
383 std::vector<unsigned> ArgumentIndexMapping;
390transformFunctionAttributes(
const TransformedFunction &TransformedFunction,
394 std::vector<llvm::AttributeSet> ArgumentAttributes(
395 TransformedFunction.TransformedType->getNumParams());
400 for (
unsigned I = 0, IE = TransformedFunction.ArgumentIndexMapping.size();
402 unsigned TransformedIndex = TransformedFunction.ArgumentIndexMapping[
I];
403 ArgumentAttributes[TransformedIndex] = CallSiteAttrs.
getParamAttrs(
I);
407 for (
unsigned I = TransformedFunction.OriginalType->getNumParams(),
418class DataFlowSanitizer {
419 friend struct DFSanFunction;
420 friend class DFSanVisitor;
422 enum { ShadowWidthBits = 8, ShadowWidthBytes = ShadowWidthBits / 8 };
424 enum { OriginWidthBits = 32, OriginWidthBytes = OriginWidthBits / 8 };
483 FunctionType *DFSanMemShadowOriginConditionalExchangeFnTy;
508 MDNode *OriginStoreWeights;
509 DFSanABIList ABIList;
516 const MemoryMapParams *MapParams;
521 std::pair<Value *, Value *>
525 bool isForceZeroLabels(
const Function *
F);
533 void initializeCallbackFunctions(
Module &M);
534 void initializeRuntimeFunctions(
Module &M);
535 bool initializeModule(
Module &M);
547 bool shouldTrackOrigins();
559 bool isZeroShadow(
Value *V);
573 DataFlowSanitizer(
const std::vector<std::string> &ABIListFiles);
579struct DFSanFunction {
580 DataFlowSanitizer &DFS;
584 bool IsForceZeroLabels;
593 struct PHIFixupElement {
598 std::vector<PHIFixupElement> PHIFixups;
601 std::vector<Value *> NonZeroChecks;
603 struct CachedShadow {
616 DFSanFunction(DataFlowSanitizer &DFS,
Function *F,
bool IsNativeABI,
618 : DFS(DFS),
F(
F), IsNativeABI(IsNativeABI),
619 IsForceZeroLabels(IsForceZeroLabels), TLI(TLI) {
637 Value *getRetvalOriginTLS();
649 Value *combineOrigins(
const std::vector<Value *> &Shadows,
650 const std::vector<Value *> &Origins,
Instruction *Pos,
709 bool isLookupTableConstant(
Value *
P);
714 template <
class AggregateType>
715 Value *collapseAggregateShadow(AggregateType *AT,
Value *Shadow,
724 std::pair<Value *, Value *>
769 bool shouldInstrumentWithCall();
775 std::pair<Value *, Value *>
778 int NumOriginStores = 0;
781class DFSanVisitor :
public InstVisitor<DFSanVisitor> {
785 DFSanVisitor(DFSanFunction &DFSF) : DFSF(DFSF) {}
788 return DFSF.F->getParent()->getDataLayout();
806 void visitLibAtomicLoad(
CallBase &CB);
807 void visitLibAtomicStore(
CallBase &CB);
808 void visitLibAtomicExchange(
CallBase &CB);
809 void visitLibAtomicCompareExchange(
CallBase &CB);
843bool LibAtomicFunction(
const Function &
F) {
849 if (!
F.hasName() ||
F.isVarArg())
851 switch (
F.arg_size()) {
853 return F.getName() ==
"__atomic_load" ||
F.getName() ==
"__atomic_store";
855 return F.getName() ==
"__atomic_exchange";
857 return F.getName() ==
"__atomic_compare_exchange";
865DataFlowSanitizer::DataFlowSanitizer(
866 const std::vector<std::string> &ABIListFiles) {
867 std::vector<std::string> AllABIListFiles(std::move(ABIListFiles));
874 CombineTaintLookupTableNames.
insert(v);
877TransformedFunction DataFlowSanitizer::getCustomFunctionType(
FunctionType *
T) {
884 std::vector<unsigned> ArgumentIndexMapping;
885 for (
unsigned I = 0,
E =
T->getNumParams();
I !=
E; ++
I) {
886 Type *ParamType =
T->getParamType(
I);
887 ArgumentIndexMapping.push_back(ArgTypes.
size());
890 for (
unsigned I = 0,
E =
T->getNumParams();
I !=
E; ++
I)
893 ArgTypes.
push_back(PrimitiveShadowPtrTy);
894 Type *RetType =
T->getReturnType();
896 ArgTypes.
push_back(PrimitiveShadowPtrTy);
898 if (shouldTrackOrigins()) {
899 for (
unsigned I = 0,
E =
T->getNumParams();
I !=
E; ++
I)
907 return TransformedFunction(
908 T, FunctionType::get(
T->getReturnType(), ArgTypes,
T->isVarArg()),
909 ArgumentIndexMapping);
912bool DataFlowSanitizer::isZeroShadow(
Value *V) {
914 if (!isa<ArrayType>(
T) && !isa<StructType>(
T)) {
915 if (
const ConstantInt *CI = dyn_cast<ConstantInt>(V))
920 return isa<ConstantAggregateZero>(V);
923bool DataFlowSanitizer::hasLoadSizeForFastPath(
uint64_t Size) {
925 return ShadowSize % 8 == 0 || ShadowSize == 4;
928bool DataFlowSanitizer::shouldTrackOrigins() {
930 return ShouldTrackOrigins;
933Constant *DataFlowSanitizer::getZeroShadow(
Type *OrigTy) {
934 if (!isa<ArrayType>(OrigTy) && !isa<StructType>(OrigTy))
935 return ZeroPrimitiveShadow;
936 Type *ShadowTy = getShadowTy(OrigTy);
941 return getZeroShadow(
V->getType());
947 if (!isa<ArrayType>(SubShadowTy) && !isa<StructType>(SubShadowTy))
950 if (
ArrayType *AT = dyn_cast<ArrayType>(SubShadowTy)) {
951 for (
unsigned Idx = 0;
Idx < AT->getNumElements();
Idx++) {
954 Shadow, Indices, AT->getElementType(), PrimitiveShadow, IRB);
960 if (
StructType *ST = dyn_cast<StructType>(SubShadowTy)) {
961 for (
unsigned Idx = 0;
Idx < ST->getNumElements();
Idx++) {
964 Shadow, Indices, ST->getElementType(
Idx), PrimitiveShadow, IRB);
972bool DFSanFunction::shouldInstrumentWithCall() {
977Value *DFSanFunction::expandFromPrimitiveShadow(
Type *
T,
Value *PrimitiveShadow,
979 Type *ShadowTy = DFS.getShadowTy(
T);
981 if (!isa<ArrayType>(ShadowTy) && !isa<StructType>(ShadowTy))
982 return PrimitiveShadow;
984 if (DFS.isZeroShadow(PrimitiveShadow))
985 return DFS.getZeroShadow(ShadowTy);
991 PrimitiveShadow, IRB);
994 CachedCollapsedShadows[Shadow] = PrimitiveShadow;
998template <
class AggregateType>
999Value *DFSanFunction::collapseAggregateShadow(AggregateType *AT,
Value *Shadow,
1001 if (!AT->getNumElements())
1002 return DFS.ZeroPrimitiveShadow;
1005 Value *Aggregator = collapseToPrimitiveShadow(FirstItem, IRB);
1007 for (
unsigned Idx = 1;
Idx < AT->getNumElements();
Idx++) {
1009 Value *ShadowInner = collapseToPrimitiveShadow(ShadowItem, IRB);
1010 Aggregator = IRB.
CreateOr(Aggregator, ShadowInner);
1015Value *DFSanFunction::collapseToPrimitiveShadow(
Value *Shadow,
1018 if (!isa<ArrayType>(ShadowTy) && !isa<StructType>(ShadowTy))
1020 if (
ArrayType *AT = dyn_cast<ArrayType>(ShadowTy))
1021 return collapseAggregateShadow<>(AT, Shadow, IRB);
1022 if (
StructType *ST = dyn_cast<StructType>(ShadowTy))
1023 return collapseAggregateShadow<>(ST, Shadow, IRB);
1027Value *DFSanFunction::collapseToPrimitiveShadow(
Value *Shadow,
1030 if (!isa<ArrayType>(ShadowTy) && !isa<StructType>(ShadowTy))
1034 Value *&CS = CachedCollapsedShadows[Shadow];
1039 Value *PrimitiveShadow = collapseToPrimitiveShadow(Shadow, IRB);
1041 CS = PrimitiveShadow;
1042 return PrimitiveShadow;
1045void DFSanFunction::addConditionalCallbacksIfEnabled(
Instruction &
I,
1051 Value *CondShadow = getShadow(Condition);
1053 if (DFS.shouldTrackOrigins()) {
1054 Value *CondOrigin = getOrigin(Condition);
1055 CI = IRB.
CreateCall(DFS.DFSanConditionalCallbackOriginFn,
1056 {CondShadow, CondOrigin});
1058 CI = IRB.
CreateCall(DFS.DFSanConditionalCallbackFn, {CondShadow});
1063void DFSanFunction::addReachesFunctionCallbacksIfEnabled(
IRBuilder<> &IRB,
1069 const DebugLoc &dbgloc =
I.getDebugLoc();
1070 Value *DataShadow = collapseToPrimitiveShadow(getShadow(
Data), IRB);
1074 if (dbgloc.
get() ==
nullptr) {
1077 I.getFunction()->getParent()->getSourceFileName());
1089 std::vector<Value *>
args;
1091 if (DFS.shouldTrackOrigins()) {
1093 args = { DataShadow, DataOrigin, FilePathPtr, CILine, FunctionNamePtr };
1094 CB = IRB.
CreateCall(DFS.DFSanReachesFunctionCallbackOriginFn,
args);
1096 args = { DataShadow, FilePathPtr, CILine, FunctionNamePtr };
1103Type *DataFlowSanitizer::getShadowTy(
Type *OrigTy) {
1105 return PrimitiveShadowTy;
1106 if (isa<IntegerType>(OrigTy))
1107 return PrimitiveShadowTy;
1108 if (isa<VectorType>(OrigTy))
1109 return PrimitiveShadowTy;
1110 if (
ArrayType *AT = dyn_cast<ArrayType>(OrigTy))
1111 return ArrayType::get(getShadowTy(AT->getElementType()),
1112 AT->getNumElements());
1113 if (
StructType *ST = dyn_cast<StructType>(OrigTy)) {
1115 for (
unsigned I = 0,
N =
ST->getNumElements();
I <
N; ++
I)
1116 Elements.push_back(getShadowTy(
ST->getElementType(
I)));
1119 return PrimitiveShadowTy;
1122Type *DataFlowSanitizer::getShadowTy(
Value *V) {
1123 return getShadowTy(
V->getType());
1126bool DataFlowSanitizer::initializeModule(
Module &M) {
1127 Triple TargetTriple(
M.getTargetTriple());
1132 switch (TargetTriple.getArch()) {
1147 Ctx = &
M.getContext();
1150 OriginPtrTy = PointerType::getUnqual(OriginTy);
1152 PrimitiveShadowPtrTy = PointerType::getUnqual(PrimitiveShadowTy);
1153 IntptrTy =
DL.getIntPtrType(*Ctx);
1157 Type *DFSanUnionLoadArgs[2] = {PrimitiveShadowPtrTy, IntptrTy};
1158 DFSanUnionLoadFnTy = FunctionType::get(PrimitiveShadowTy, DFSanUnionLoadArgs,
1160 Type *DFSanLoadLabelAndOriginArgs[2] = {Int8Ptr, IntptrTy};
1161 DFSanLoadLabelAndOriginFnTy =
1164 DFSanUnimplementedFnTy = FunctionType::get(
1166 Type *DFSanWrapperExternWeakNullArgs[2] = {Int8Ptr, Int8Ptr};
1167 DFSanWrapperExternWeakNullFnTy =
1168 FunctionType::get(
Type::getVoidTy(*Ctx), DFSanWrapperExternWeakNullArgs,
1170 Type *DFSanSetLabelArgs[4] = {PrimitiveShadowTy, OriginTy,
1173 DFSanSetLabelArgs,
false);
1174 DFSanNonzeroLabelFnTy = FunctionType::get(
Type::getVoidTy(*Ctx), std::nullopt,
1176 DFSanVarargWrapperFnTy = FunctionType::get(
1178 DFSanConditionalCallbackFnTy =
1181 Type *DFSanConditionalCallbackOriginArgs[2] = {PrimitiveShadowTy, OriginTy};
1182 DFSanConditionalCallbackOriginFnTy = FunctionType::get(
1185 Type *DFSanReachesFunctionCallbackArgs[4] = {PrimitiveShadowTy, Int8Ptr,
1187 DFSanReachesFunctionCallbackFnTy =
1188 FunctionType::get(
Type::getVoidTy(*Ctx), DFSanReachesFunctionCallbackArgs,
1190 Type *DFSanReachesFunctionCallbackOriginArgs[5] = {
1191 PrimitiveShadowTy, OriginTy, Int8Ptr, OriginTy, Int8Ptr};
1192 DFSanReachesFunctionCallbackOriginFnTy = FunctionType::get(
1195 DFSanCmpCallbackFnTy =
1198 DFSanChainOriginFnTy =
1199 FunctionType::get(OriginTy, OriginTy,
false);
1200 Type *DFSanChainOriginIfTaintedArgs[2] = {PrimitiveShadowTy, OriginTy};
1201 DFSanChainOriginIfTaintedFnTy = FunctionType::get(
1202 OriginTy, DFSanChainOriginIfTaintedArgs,
false);
1204 Int8Ptr, IntptrTy, OriginTy};
1205 DFSanMaybeStoreOriginFnTy = FunctionType::get(
1207 Type *DFSanMemOriginTransferArgs[3] = {Int8Ptr, Int8Ptr, IntptrTy};
1208 DFSanMemOriginTransferFnTy = FunctionType::get(
1210 Type *DFSanMemShadowOriginTransferArgs[3] = {Int8Ptr, Int8Ptr, IntptrTy};
1211 DFSanMemShadowOriginTransferFnTy =
1212 FunctionType::get(
Type::getVoidTy(*Ctx), DFSanMemShadowOriginTransferArgs,
1214 Type *DFSanMemShadowOriginConditionalExchangeArgs[5] = {
1216 DFSanMemShadowOriginConditionalExchangeFnTy = FunctionType::get(
1219 Type *DFSanLoadStoreCallbackArgs[2] = {PrimitiveShadowTy, Int8Ptr};
1220 DFSanLoadStoreCallbackFnTy =
1223 Type *DFSanMemTransferCallbackArgs[2] = {PrimitiveShadowPtrTy, IntptrTy};
1224 DFSanMemTransferCallbackFnTy =
1225 FunctionType::get(
Type::getVoidTy(*Ctx), DFSanMemTransferCallbackArgs,
1233bool DataFlowSanitizer::isInstrumented(
const Function *
F) {
1234 return !ABIList.isIn(*
F,
"uninstrumented");
1237bool DataFlowSanitizer::isInstrumented(
const GlobalAlias *GA) {
1238 return !ABIList.isIn(*GA,
"uninstrumented");
1241bool DataFlowSanitizer::isForceZeroLabels(
const Function *
F) {
1242 return ABIList.isIn(*
F,
"force_zero_labels");
1245DataFlowSanitizer::WrapperKind DataFlowSanitizer::getWrapperKind(
Function *
F) {
1246 if (ABIList.isIn(*
F,
"functional"))
1247 return WK_Functional;
1248 if (ABIList.isIn(*
F,
"discard"))
1250 if (ABIList.isIn(*
F,
"custom"))
1256void DataFlowSanitizer::addGlobalNameSuffix(
GlobalValue *GV) {
1257 std::string GVName = std::string(GV->
getName()), Suffix =
".dfsan";
1266 std::string SearchStr =
".symver " + GVName +
",";
1267 size_t Pos =
Asm.find(SearchStr);
1268 if (Pos != std::string::npos) {
1269 Asm.replace(Pos, SearchStr.size(),
".symver " + GVName + Suffix +
",");
1270 Pos =
Asm.find(
'@');
1272 if (Pos == std::string::npos)
1275 Asm.replace(Pos, 1, Suffix +
"@");
1280void DataFlowSanitizer::buildExternWeakCheckIfNeeded(
IRBuilder<> &IRB,
1290 std::vector<Value *>
Args;
1293 IRB.
CreateCall(DFSanWrapperExternWeakNullFn, Args);
1303 NewFName,
F->getParent());
1309 if (
F->isVarArg()) {
1312 IRBuilder<>(BB).CreateGlobalStringPtr(
F->getName()),
"",
1317 std::vector<Value *>
Args(ArgIt, ArgIt + FT->getNumParams());
1320 if (FT->getReturnType()->isVoidTy())
1330void DataFlowSanitizer::initializeRuntimeFunctions(
Module &M) {
1334 AL =
AL.addFnAttribute(
C, Attribute::NoUnwind);
1335 AL =
AL.addFnAttribute(
1337 AL =
AL.addRetAttribute(
C, Attribute::ZExt);
1343 AL =
AL.addFnAttribute(
C, Attribute::NoUnwind);
1344 AL =
AL.addFnAttribute(
1346 AL =
AL.addRetAttribute(
C, Attribute::ZExt);
1348 "__dfsan_load_label_and_origin", DFSanLoadLabelAndOriginFnTy, AL);
1350 DFSanUnimplementedFn =
1353 "__dfsan_wrapper_extern_weak_null", DFSanWrapperExternWeakNullFnTy);
1356 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1357 AL =
AL.addParamAttribute(
M.getContext(), 1, Attribute::ZExt);
1361 DFSanNonzeroLabelFn =
1364 DFSanVarargWrapperFnTy);
1367 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1368 AL =
AL.addRetAttribute(
M.getContext(), Attribute::ZExt);
1370 DFSanChainOriginFnTy, AL);
1374 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1375 AL =
AL.addParamAttribute(
M.getContext(), 1, Attribute::ZExt);
1376 AL =
AL.addRetAttribute(
M.getContext(), Attribute::ZExt);
1378 "__dfsan_chain_origin_if_tainted", DFSanChainOriginIfTaintedFnTy, AL);
1381 "__dfsan_mem_origin_transfer", DFSanMemOriginTransferFnTy);
1384 "__dfsan_mem_shadow_origin_transfer", DFSanMemShadowOriginTransferFnTy);
1386 DFSanMemShadowOriginConditionalExchangeFn =
1388 DFSanMemShadowOriginConditionalExchangeFnTy);
1392 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1393 AL =
AL.addParamAttribute(
M.getContext(), 3, Attribute::ZExt);
1395 "__dfsan_maybe_store_origin", DFSanMaybeStoreOriginFnTy, AL);
1398 DFSanRuntimeFunctions.
insert(
1400 DFSanRuntimeFunctions.
insert(
1402 DFSanRuntimeFunctions.
insert(
1404 DFSanRuntimeFunctions.
insert(
1406 DFSanRuntimeFunctions.
insert(
1408 DFSanRuntimeFunctions.
insert(
1410 DFSanRuntimeFunctions.
insert(
1412 DFSanRuntimeFunctions.
insert(
1414 DFSanRuntimeFunctions.
insert(
1416 DFSanRuntimeFunctions.
insert(
1418 DFSanRuntimeFunctions.
insert(
1420 DFSanRuntimeFunctions.
insert(
1422 DFSanRuntimeFunctions.
insert(
1424 DFSanRuntimeFunctions.
insert(
1426 DFSanRuntimeFunctions.
insert(
1428 DFSanRuntimeFunctions.
insert(
1430 DFSanRuntimeFunctions.
insert(
1432 DFSanRuntimeFunctions.
insert(
1434 DFSanRuntimeFunctions.
insert(
1436 DFSanRuntimeFunctions.
insert(
1437 DFSanMemShadowOriginConditionalExchangeFn.
getCallee()
1439 DFSanRuntimeFunctions.
insert(
1444void DataFlowSanitizer::initializeCallbackFunctions(
Module &M) {
1447 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1449 "__dfsan_load_callback", DFSanLoadStoreCallbackFnTy, AL);
1453 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1455 "__dfsan_store_callback", DFSanLoadStoreCallbackFnTy, AL);
1458 "__dfsan_mem_transfer_callback", DFSanMemTransferCallbackFnTy);
1461 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1463 DFSanCmpCallbackFnTy, AL);
1467 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1469 "__dfsan_conditional_callback", DFSanConditionalCallbackFnTy, AL);
1473 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1474 DFSanConditionalCallbackOriginFn =
1476 DFSanConditionalCallbackOriginFnTy, AL);
1480 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1481 DFSanReachesFunctionCallbackFn =
1483 DFSanReachesFunctionCallbackFnTy, AL);
1487 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1488 DFSanReachesFunctionCallbackOriginFn =
1490 DFSanReachesFunctionCallbackOriginFnTy, AL);
1494bool DataFlowSanitizer::runImpl(
1496 initializeModule(M);
1498 if (ABIList.isIn(M,
"skip"))
1501 const unsigned InitialGlobalSize =
M.global_size();
1502 const unsigned InitialModuleSize =
M.size();
1504 bool Changed =
false;
1510 Changed |=
G->getThreadLocalMode() != GlobalVariable::InitialExecTLSModel;
1511 G->setThreadLocalMode(GlobalVariable::InitialExecTLSModel);
1518 GetOrInsertGlobal(
"__dfsan_arg_tls",
1520 RetvalTLS = GetOrInsertGlobal(
1521 "__dfsan_retval_tls",
1523 ArgOriginTLSTy = ArrayType::get(OriginTy, NumOfElementsInArgOrgTLS);
1524 ArgOriginTLS = GetOrInsertGlobal(
"__dfsan_arg_origin_tls", ArgOriginTLSTy);
1525 RetvalOriginTLS = GetOrInsertGlobal(
"__dfsan_retval_origin_tls", OriginTy);
1533 "__dfsan_track_origins");
1536 initializeCallbackFunctions(M);
1537 initializeRuntimeFunctions(M);
1539 std::vector<Function *> FnsToInstrument;
1544 if (!
F.isIntrinsic() && !DFSanRuntimeFunctions.
contains(&
F) &&
1545 !LibAtomicFunction(
F)) {
1546 FnsToInstrument.push_back(&
F);
1547 if (
F.hasPersonalityFn())
1548 PersonalityFns.
insert(
F.getPersonalityFn()->stripPointerCasts());
1552 for (
auto *
C : PersonalityFns) {
1553 assert(isa<Function>(
C) &&
"Personality routine is not a function!");
1555 if (!isInstrumented(
F))
1569 bool GAInst = isInstrumented(&GA), FInst = isInstrumented(
F);
1570 if (GAInst && FInst) {
1571 addGlobalNameSuffix(&GA);
1572 }
else if (GAInst != FInst) {
1577 buildWrapperFunction(
F,
"", GA.
getLinkage(),
F->getFunctionType());
1581 FnsToInstrument.push_back(NewF);
1590 for (std::vector<Function *>::iterator FI = FnsToInstrument.begin(),
1591 FE = FnsToInstrument.end();
1596 bool IsZeroArgsVoidRet = (FT->getNumParams() == 0 && !FT->isVarArg() &&
1597 FT->getReturnType()->isVoidTy());
1599 if (isInstrumented(&
F)) {
1600 if (isForceZeroLabels(&
F))
1601 FnsWithForceZeroLabel.
insert(&
F);
1606 addGlobalNameSuffix(&
F);
1607 }
else if (!IsZeroArgsVoidRet || getWrapperKind(&
F) == WK_Custom) {
1615 F.hasLocalLinkage() ?
F.getLinkage()
1618 Function *NewF = buildWrapperFunction(
1620 (shouldTrackOrigins() ? std::string(
"dfso$") : std::string(
"dfsw$")) +
1621 std::string(
F.getName()),
1622 WrapperLinkage, FT);
1625 Value *WrappedFnCst =
1645 auto IsNotCmpUse = [](
Use &
U) ->
bool {
1646 User *Usr =
U.getUser();
1649 if (
CE->getOpcode() == Instruction::ICmp) {
1654 if (
I->getOpcode() == Instruction::ICmp) {
1660 F.replaceUsesWithIf(WrappedFnCst, IsNotCmpUse);
1662 UnwrappedFnMap[WrappedFnCst] = &
F;
1665 if (!
F.isDeclaration()) {
1675 size_t N = FI - FnsToInstrument.begin(),
1676 Count = FE - FnsToInstrument.begin();
1677 FnsToInstrument.push_back(&
F);
1678 FI = FnsToInstrument.begin() +
N;
1679 FE = FnsToInstrument.begin() + Count;
1683 }
else if (FT->isVarArg()) {
1684 UnwrappedFnMap[&
F] = &
F;
1690 if (!
F ||
F->isDeclaration())
1695 DFSanFunction DFSF(*
this,
F, FnsWithNativeABI.
count(
F),
1696 FnsWithForceZeroLabel.
count(
F), GetTLI(*
F));
1700 for (
auto &FArg :
F->args()) {
1702 Value *FArgShadow = DFSF.getShadow(&FArg);
1703 if (isZeroShadow(FArgShadow))
1705 if (
Instruction *FArgShadowInst = dyn_cast<Instruction>(FArgShadow)) {
1708 if (shouldTrackOrigins()) {
1710 dyn_cast<Instruction>(DFSF.getOrigin(&FArg))) {
1719 DFSF.addReachesFunctionCallbacksIfEnabled(IRB, *Next, &FArg);
1737 if (!DFSF.SkipInsts.count(Inst))
1738 DFSanVisitor(DFSF).visit(Inst);
1749 for (DFSanFunction::PHIFixupElement &
P : DFSF.PHIFixups) {
1750 for (
unsigned Val = 0,
N =
P.Phi->getNumIncomingValues(); Val !=
N;
1752 P.ShadowPhi->setIncomingValue(
1753 Val, DFSF.getShadow(
P.Phi->getIncomingValue(Val)));
1755 P.OriginPhi->setIncomingValue(
1756 Val, DFSF.getOrigin(
P.Phi->getIncomingValue(Val)));
1765 for (
Value *V : DFSF.NonZeroChecks) {
1768 Pos =
I->getNextNode();
1770 Pos = &DFSF.F->getEntryBlock().front();
1771 while (isa<PHINode>(Pos) || isa<AllocaInst>(Pos))
1774 Value *PrimitiveShadow = DFSF.collapseToPrimitiveShadow(V, Pos);
1776 IRB.
CreateICmpNE(PrimitiveShadow, DFSF.DFS.ZeroPrimitiveShadow);
1778 Ne, Pos,
false, ColdCallWeights));
1780 ThenIRB.CreateCall(DFSF.DFS.DFSanNonzeroLabelFn, {});
1785 return Changed || !FnsToInstrument.empty() ||
1786 M.global_size() != InitialGlobalSize ||
M.size() != InitialModuleSize;
1799 DFS.RetvalTLS, PointerType::get(DFS.getShadowTy(
T), 0),
"_dfsret");
1802Value *DFSanFunction::getRetvalOriginTLS() {
return DFS.RetvalOriginTLS; }
1810 assert(DFS.shouldTrackOrigins());
1811 if (!isa<Argument>(V) && !isa<Instruction>(V))
1812 return DFS.ZeroOrigin;
1813 Value *&Origin = ValOriginMap[
V];
1815 if (
Argument *
A = dyn_cast<Argument>(V)) {
1817 return DFS.ZeroOrigin;
1818 if (
A->getArgNo() < DFS.NumOfElementsInArgOrgTLS) {
1819 Instruction *ArgOriginTLSPos = &*
F->getEntryBlock().begin();
1821 Value *ArgOriginPtr = getArgOriginTLS(
A->getArgNo(), IRB);
1822 Origin = IRB.
CreateLoad(DFS.OriginTy, ArgOriginPtr);
1825 Origin = DFS.ZeroOrigin;
1828 Origin = DFS.ZeroOrigin;
1835 if (!DFS.shouldTrackOrigins())
1839 ValOriginMap[
I] = Origin;
1843 unsigned ArgOffset = 0;
1845 for (
auto &FArg :
F->args()) {
1846 if (!FArg.getType()->isSized()) {
1852 unsigned Size =
DL.getTypeAllocSize(DFS.getShadowTy(&FArg));
1865 Value *ArgShadowPtr = getArgTLS(FArg.getType(), ArgOffset, IRB);
1870 return DFS.getZeroShadow(
A);
1874 if (!isa<Argument>(V) && !isa<Instruction>(V))
1875 return DFS.getZeroShadow(V);
1876 if (IsForceZeroLabels)
1877 return DFS.getZeroShadow(V);
1878 Value *&Shadow = ValShadowMap[
V];
1880 if (
Argument *
A = dyn_cast<Argument>(V)) {
1882 return DFS.getZeroShadow(V);
1883 Shadow = getShadowForTLSArgument(
A);
1884 NonZeroChecks.push_back(Shadow);
1886 Shadow = DFS.getZeroShadow(V);
1894 ValShadowMap[
I] = Shadow;
1902 assert(
Addr != RetvalTLS &&
"Reinstrumenting?");
1905 uint64_t AndMask = MapParams->AndMask;
1910 uint64_t XorMask = MapParams->XorMask;
1916std::pair<Value *, Value *>
1917DataFlowSanitizer::getShadowOriginAddress(
Value *
Addr,
Align InstAlignment,
1921 Value *ShadowOffset = getShadowOffset(
Addr, IRB);
1922 Value *ShadowLong = ShadowOffset;
1923 uint64_t ShadowBase = MapParams->ShadowBase;
1924 if (ShadowBase != 0) {
1931 Value *OriginPtr =
nullptr;
1932 if (shouldTrackOrigins()) {
1933 Value *OriginLong = ShadowOffset;
1934 uint64_t OriginBase = MapParams->OriginBase;
1935 if (OriginBase != 0)
1947 return std::make_pair(ShadowPtr, OriginPtr);
1951 Value *ShadowOffset) {
1958 Value *ShadowOffset = getShadowOffset(
Addr, IRB);
1959 return getShadowAddress(
Addr, Pos, ShadowOffset);
1964 Value *PrimitiveValue = combineShadows(V1, V2, Pos);
1965 return expandFromPrimitiveShadow(
T, PrimitiveValue, Pos);
1971 if (DFS.isZeroShadow(V1))
1972 return collapseToPrimitiveShadow(V2, Pos);
1973 if (DFS.isZeroShadow(V2))
1974 return collapseToPrimitiveShadow(V1, Pos);
1976 return collapseToPrimitiveShadow(V1, Pos);
1978 auto V1Elems = ShadowElements.
find(V1);
1979 auto V2Elems = ShadowElements.
find(V2);
1980 if (V1Elems != ShadowElements.
end() && V2Elems != ShadowElements.
end()) {
1981 if (std::includes(V1Elems->second.begin(), V1Elems->second.end(),
1982 V2Elems->second.begin(), V2Elems->second.end())) {
1983 return collapseToPrimitiveShadow(V1, Pos);
1985 if (std::includes(V2Elems->second.begin(), V2Elems->second.end(),
1986 V1Elems->second.begin(), V1Elems->second.end())) {
1987 return collapseToPrimitiveShadow(V2, Pos);
1989 }
else if (V1Elems != ShadowElements.
end()) {
1990 if (V1Elems->second.count(V2))
1991 return collapseToPrimitiveShadow(V1, Pos);
1992 }
else if (V2Elems != ShadowElements.
end()) {
1993 if (V2Elems->second.count(V1))
1994 return collapseToPrimitiveShadow(V2, Pos);
1997 auto Key = std::make_pair(V1, V2);
2000 CachedShadow &CCS = CachedShadows[
Key];
2005 Value *PV1 = collapseToPrimitiveShadow(V1, Pos);
2006 Value *PV2 = collapseToPrimitiveShadow(V2, Pos);
2010 CCS.Shadow = IRB.
CreateOr(PV1, PV2);
2012 std::set<Value *> UnionElems;
2013 if (V1Elems != ShadowElements.
end()) {
2014 UnionElems = V1Elems->second;
2016 UnionElems.insert(V1);
2018 if (V2Elems != ShadowElements.
end()) {
2019 UnionElems.insert(V2Elems->second.begin(), V2Elems->second.end());
2021 UnionElems.insert(V2);
2023 ShadowElements[CCS.Shadow] = std::move(UnionElems);
2033 return DFS.getZeroShadow(Inst);
2037 Shadow = combineShadows(Shadow, getShadow(Inst->
getOperand(
I)), Inst);
2039 return expandFromPrimitiveShadow(Inst->
getType(), Shadow, Inst);
2043 Value *CombinedShadow = DFSF.combineOperandShadows(&
I);
2044 DFSF.setShadow(&
I, CombinedShadow);
2045 visitInstOperandOrigins(
I);
2048Value *DFSanFunction::combineOrigins(
const std::vector<Value *> &Shadows,
2049 const std::vector<Value *> &Origins,
2051 assert(Shadows.size() == Origins.size());
2052 size_t Size = Origins.size();
2054 return DFS.ZeroOrigin;
2055 Value *Origin =
nullptr;
2057 Zero = DFS.ZeroPrimitiveShadow;
2058 for (
size_t I = 0;
I !=
Size; ++
I) {
2059 Value *OpOrigin = Origins[
I];
2060 Constant *ConstOpOrigin = dyn_cast<Constant>(OpOrigin);
2061 if (ConstOpOrigin && ConstOpOrigin->
isNullValue())
2067 Value *OpShadow = Shadows[
I];
2068 Value *PrimitiveShadow = collapseToPrimitiveShadow(OpShadow, Pos);
2073 return Origin ? Origin : DFS.ZeroOrigin;
2078 std::vector<Value *> Shadows(
Size);
2079 std::vector<Value *> Origins(
Size);
2080 for (
unsigned I = 0;
I !=
Size; ++
I) {
2084 return combineOrigins(Shadows, Origins, Inst);
2087void DFSanVisitor::visitInstOperandOrigins(
Instruction &
I) {
2088 if (!DFSF.DFS.shouldTrackOrigins())
2090 Value *CombinedOrigin = DFSF.combineOperandOrigins(&
I);
2091 DFSF.setOrigin(&
I, CombinedOrigin);
2094Align DFSanFunction::getShadowAlign(
Align InstAlignment) {
2096 return Align(Alignment.
value() * DFS.ShadowWidthBytes);
2099Align DFSanFunction::getOriginAlign(
Align InstAlignment) {
2104bool DFSanFunction::isLookupTableConstant(
Value *
P) {
2105 if (
GlobalVariable *GV = dyn_cast<GlobalVariable>(
P->stripPointerCasts()))
2106 if (GV->isConstant() && GV->
hasName())
2107 return DFS.CombineTaintLookupTableNames.count(GV->
getName());
2112bool DFSanFunction::useCallbackLoadLabelAndOrigin(
uint64_t Size,
2113 Align InstAlignment) {
2136 Value **OriginAddr) {
2143std::pair<Value *, Value *> DFSanFunction::loadShadowFast(
2146 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins();
2147 const uint64_t ShadowSize =
Size * DFS.ShadowWidthBytes;
2149 assert(
Size >= 4 &&
"Not large enough load size for fast path!");
2152 std::vector<Value *> Shadows;
2153 std::vector<Value *> Origins;
2166 Type *WideShadowTy =
2170 Value *CombinedWideShadow =
2174 const uint64_t BytesPerWideShadow = WideShadowBitWidth / DFS.ShadowWidthBits;
2176 auto AppendWideShadowAndOrigin = [&](
Value *WideShadow,
Value *Origin) {
2177 if (BytesPerWideShadow > 4) {
2178 assert(BytesPerWideShadow == 8);
2187 Shadows.push_back(WideShadow);
2188 Origins.push_back(DFS.loadNextOrigin(Pos, OriginAlign, &OriginAddr));
2190 Shadows.push_back(WideShadowLo);
2191 Origins.push_back(Origin);
2193 Shadows.push_back(WideShadow);
2194 Origins.push_back(Origin);
2198 if (ShouldTrackOrigins)
2199 AppendWideShadowAndOrigin(CombinedWideShadow, FirstOrigin);
2206 for (
uint64_t ByteOfs = BytesPerWideShadow; ByteOfs <
Size;
2207 ByteOfs += BytesPerWideShadow) {
2208 ShadowAddr = IRB.
CreateGEP(WideShadowTy, ShadowAddr,
2210 Value *NextWideShadow =
2212 CombinedWideShadow = IRB.
CreateOr(CombinedWideShadow, NextWideShadow);
2213 if (ShouldTrackOrigins) {
2214 Value *NextOrigin = DFS.loadNextOrigin(Pos, OriginAlign, &OriginAddr);
2215 AppendWideShadowAndOrigin(NextWideShadow, NextOrigin);
2218 for (
unsigned Width = WideShadowBitWidth / 2;
Width >= DFS.ShadowWidthBits;
2221 CombinedWideShadow = IRB.
CreateOr(CombinedWideShadow, ShrShadow);
2223 return {IRB.
CreateTrunc(CombinedWideShadow, DFS.PrimitiveShadowTy),
2225 ? combineOrigins(Shadows, Origins, Pos,
2230std::pair<Value *, Value *> DFSanFunction::loadShadowOriginSansLoadTracking(
2232 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins();
2236 const auto SI = AllocaShadowMap.
find(AI);
2237 if (SI != AllocaShadowMap.
end()) {
2240 const auto OI = AllocaOriginMap.
find(AI);
2241 assert(!ShouldTrackOrigins || OI != AllocaOriginMap.
end());
2242 return {ShadowLI, ShouldTrackOrigins
2251 bool AllConstants =
true;
2252 for (
const Value *Obj : Objs) {
2253 if (isa<Function>(Obj) || isa<BlockAddress>(Obj))
2255 if (isa<GlobalVariable>(Obj) && cast<GlobalVariable>(Obj)->
isConstant())
2258 AllConstants =
false;
2262 return {DFS.ZeroPrimitiveShadow,
2263 ShouldTrackOrigins ? DFS.ZeroOrigin :
nullptr};
2266 return {DFS.ZeroPrimitiveShadow,
2267 ShouldTrackOrigins ? DFS.ZeroOrigin :
nullptr};
2271 if (ShouldTrackOrigins &&
2272 useCallbackLoadLabelAndOrigin(
Size, InstAlignment)) {
2275 IRB.
CreateCall(DFS.DFSanLoadLabelAndOriginFn,
2276 {IRB.CreatePointerCast(Addr, IRB.getInt8PtrTy()),
2277 ConstantInt::get(DFS.IntptrTy, Size)});
2278 Call->addRetAttr(Attribute::ZExt);
2280 DFS.PrimitiveShadowTy),
2285 Value *ShadowAddr, *OriginAddr;
2286 std::tie(ShadowAddr, OriginAddr) =
2287 DFS.getShadowOriginAddress(
Addr, InstAlignment, Pos);
2289 const Align ShadowAlign = getShadowAlign(InstAlignment);
2290 const Align OriginAlign = getOriginAlign(InstAlignment);
2291 Value *Origin =
nullptr;
2292 if (ShouldTrackOrigins) {
2303 return {LI, Origin};
2307 Value *ShadowAddr1 = IRB.
CreateGEP(DFS.PrimitiveShadowTy, ShadowAddr,
2313 return {combineShadows(Load, Load1, Pos), Origin};
2316 bool HasSizeForFastPath = DFS.hasLoadSizeForFastPath(
Size);
2318 if (HasSizeForFastPath)
2319 return loadShadowFast(ShadowAddr, OriginAddr,
Size, ShadowAlign,
2320 OriginAlign, Origin, Pos);
2324 DFS.DFSanUnionLoadFn, {ShadowAddr, ConstantInt::get(DFS.IntptrTy, Size)});
2326 return {FallbackCall, Origin};
2329std::pair<Value *, Value *> DFSanFunction::loadShadowOrigin(
Value *
Addr,
2331 Align InstAlignment,
2333 Value *PrimitiveShadow, *Origin;
2334 std::tie(PrimitiveShadow, Origin) =
2335 loadShadowOriginSansLoadTracking(
Addr,
Size, InstAlignment, Pos);
2336 if (DFS.shouldTrackOrigins()) {
2339 auto *ConstantShadow = dyn_cast<Constant>(PrimitiveShadow);
2340 if (!ConstantShadow || !ConstantShadow->isZeroValue())
2341 Origin = updateOriginIfTainted(PrimitiveShadow, Origin, IRB);
2344 return {PrimitiveShadow, Origin};
2349 case AtomicOrdering::NotAtomic:
2350 return AtomicOrdering::NotAtomic;
2351 case AtomicOrdering::Unordered:
2352 case AtomicOrdering::Monotonic:
2353 case AtomicOrdering::Acquire:
2354 return AtomicOrdering::Acquire;
2355 case AtomicOrdering::Release:
2356 case AtomicOrdering::AcquireRelease:
2357 return AtomicOrdering::AcquireRelease;
2358 case AtomicOrdering::SequentiallyConsistent:
2359 return AtomicOrdering::SequentiallyConsistent;
2365 if (!V->getType()->isPointerTy())
2373 if (
auto *
GEP = dyn_cast<GEPOperator>(V)) {
2374 V =
GEP->getPointerOperand();
2376 V = cast<Operator>(V)->getOperand(0);
2377 if (!V->getType()->isPointerTy())
2379 }
else if (isa<GlobalAlias>(V)) {
2380 V = cast<GlobalAlias>(V)->getAliasee();
2382 }
while (Visited.
insert(V).second);
2387void DFSanVisitor::visitLoadInst(
LoadInst &LI) {
2391 DFSF.setShadow(&LI, DFSF.DFS.getZeroShadow(&LI));
2392 DFSF.setOrigin(&LI, DFSF.DFS.ZeroOrigin);
2406 std::vector<Value *> Shadows;
2407 std::vector<Value *> Origins;
2408 Value *PrimitiveShadow, *Origin;
2409 std::tie(PrimitiveShadow, Origin) =
2411 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
2412 if (ShouldTrackOrigins) {
2413 Shadows.push_back(PrimitiveShadow);
2414 Origins.push_back(Origin);
2417 DFSF.isLookupTableConstant(
2420 PrimitiveShadow = DFSF.combineShadows(PrimitiveShadow, PtrShadow, Pos);
2421 if (ShouldTrackOrigins) {
2422 Shadows.push_back(PtrShadow);
2426 if (!DFSF.DFS.isZeroShadow(PrimitiveShadow))
2427 DFSF.NonZeroChecks.push_back(PrimitiveShadow);
2430 DFSF.expandFromPrimitiveShadow(LI.
getType(), PrimitiveShadow, Pos);
2431 DFSF.setShadow(&LI, Shadow);
2433 if (ShouldTrackOrigins) {
2434 DFSF.setOrigin(&LI, DFSF.combineOrigins(Shadows, Origins, Pos));
2441 IRB.
CreateCall(DFSF.DFS.DFSanLoadCallbackFn, {PrimitiveShadow, Addr8});
2446 DFSF.addReachesFunctionCallbacksIfEnabled(IRB, LI, &LI);
2449Value *DFSanFunction::updateOriginIfTainted(
Value *Shadow,
Value *Origin,
2451 assert(DFS.shouldTrackOrigins());
2452 return IRB.
CreateCall(DFS.DFSanChainOriginIfTaintedFn, {Shadow, Origin});
2456 if (!DFS.shouldTrackOrigins())
2458 return IRB.
CreateCall(DFS.DFSanChainOriginFn, V);
2462 const unsigned OriginSize = DataFlowSanitizer::OriginWidthBytes;
2464 unsigned IntptrSize =
DL.getTypeStoreSize(DFS.IntptrTy);
2465 if (IntptrSize == OriginSize)
2467 assert(IntptrSize == OriginSize * 2);
2473 Value *StoreOriginAddr,
2475 const unsigned OriginSize = DataFlowSanitizer::OriginWidthBytes;
2477 const Align IntptrAlignment =
DL.getABITypeAlign(DFS.IntptrTy);
2478 unsigned IntptrSize =
DL.getTypeStoreSize(DFS.IntptrTy);
2480 assert(IntptrSize >= OriginSize);
2483 Align CurrentAlignment = Alignment;
2484 if (Alignment >= IntptrAlignment && IntptrSize > OriginSize) {
2485 Value *IntptrOrigin = originToIntptr(IRB, Origin);
2487 StoreOriginAddr, PointerType::get(DFS.IntptrTy, 0));
2488 for (
unsigned I = 0;
I < StoreOriginSize / IntptrSize; ++
I) {
2491 : IntptrStoreOriginPtr;
2493 Ofs += IntptrSize / OriginSize;
2494 CurrentAlignment = IntptrAlignment;
2498 for (
unsigned I = Ofs;
I < (StoreOriginSize + OriginSize - 1) / OriginSize;
2509 Type *VTy =
V->getType();
2519 Value *StoreOriginAddr,
Align InstAlignment) {
2522 const Align OriginAlignment = getOriginAlign(InstAlignment);
2523 Value *CollapsedShadow = collapseToPrimitiveShadow(Shadow, Pos);
2525 if (
auto *ConstantShadow = dyn_cast<Constant>(CollapsedShadow)) {
2526 if (!ConstantShadow->isZeroValue())
2527 paintOrigin(IRB, updateOrigin(Origin, IRB), StoreOriginAddr,
Size,
2532 if (shouldInstrumentWithCall()) {
2535 IRB.CreatePointerCast(Addr, IRB.getInt8PtrTy()),
2536 ConstantInt::get(DFS.IntptrTy, Size), Origin});
2538 Value *
Cmp = convertToBool(CollapsedShadow, IRB,
"_dfscmp");
2541 Cmp, &*IRB.
GetInsertPoint(),
false, DFS.OriginStoreWeights, &DTU);
2543 paintOrigin(IRBNew, updateOrigin(Origin, IRBNew), StoreOriginAddr,
Size,
2556 Value *ShadowAddr = DFS.getShadowAddress(
Addr, Pos);
2557 Value *ExtShadowAddr =
2558 IRB.
CreateBitCast(ShadowAddr, PointerType::getUnqual(ShadowTy));
2565 Align InstAlignment,
2566 Value *PrimitiveShadow,
2569 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins() && Origin;
2572 const auto SI = AllocaShadowMap.
find(AI);
2573 if (SI != AllocaShadowMap.
end()) {
2579 if (ShouldTrackOrigins && !DFS.isZeroShadow(PrimitiveShadow)) {
2580 const auto OI = AllocaOriginMap.
find(AI);
2581 assert(OI != AllocaOriginMap.
end() && Origin);
2588 const Align ShadowAlign = getShadowAlign(InstAlignment);
2589 if (DFS.isZeroShadow(PrimitiveShadow)) {
2590 storeZeroPrimitiveShadow(
Addr,
Size, ShadowAlign, Pos);
2595 Value *ShadowAddr, *OriginAddr;
2596 std::tie(ShadowAddr, OriginAddr) =
2597 DFS.getShadowOriginAddress(
Addr, InstAlignment, Pos);
2599 const unsigned ShadowVecSize = 8;
2600 assert(ShadowVecSize * DFS.ShadowWidthBits <= 128 &&
2601 "Shadow vector is too large!");
2605 if (LeftSize >= ShadowVecSize) {
2609 for (
unsigned I = 0;
I != ShadowVecSize; ++
I) {
2611 ShadowVec, PrimitiveShadow,
2614 Value *ShadowVecAddr =
2615 IRB.
CreateBitCast(ShadowAddr, PointerType::getUnqual(ShadowVecTy));
2617 Value *CurShadowVecAddr =
2620 LeftSize -= ShadowVecSize;
2622 }
while (LeftSize >= ShadowVecSize);
2625 while (LeftSize > 0) {
2626 Value *CurShadowAddr =
2633 if (ShouldTrackOrigins) {
2634 storeOrigin(Pos,
Addr,
Size, PrimitiveShadow, Origin, OriginAddr,
2641 case AtomicOrdering::NotAtomic:
2642 return AtomicOrdering::NotAtomic;
2643 case AtomicOrdering::Unordered:
2644 case AtomicOrdering::Monotonic:
2645 case AtomicOrdering::Release:
2646 return AtomicOrdering::Release;
2647 case AtomicOrdering::Acquire:
2648 case AtomicOrdering::AcquireRelease:
2649 return AtomicOrdering::AcquireRelease;
2650 case AtomicOrdering::SequentiallyConsistent:
2651 return AtomicOrdering::SequentiallyConsistent;
2656void DFSanVisitor::visitStoreInst(
StoreInst &SI) {
2657 auto &
DL =
SI.getModule()->getDataLayout();
2658 Value *Val =
SI.getValueOperand();
2671 const bool ShouldTrackOrigins =
2672 DFSF.DFS.shouldTrackOrigins() && !
SI.isAtomic();
2673 std::vector<Value *> Shadows;
2674 std::vector<Value *> Origins;
2677 SI.isAtomic() ? DFSF.DFS.getZeroShadow(Val) : DFSF.getShadow(Val);
2679 if (ShouldTrackOrigins) {
2680 Shadows.push_back(Shadow);
2681 Origins.push_back(DFSF.getOrigin(Val));
2684 Value *PrimitiveShadow;
2686 Value *PtrShadow = DFSF.getShadow(
SI.getPointerOperand());
2687 if (ShouldTrackOrigins) {
2688 Shadows.push_back(PtrShadow);
2689 Origins.push_back(DFSF.getOrigin(
SI.getPointerOperand()));
2691 PrimitiveShadow = DFSF.combineShadows(Shadow, PtrShadow, &SI);
2693 PrimitiveShadow = DFSF.collapseToPrimitiveShadow(Shadow, &SI);
2695 Value *Origin =
nullptr;
2696 if (ShouldTrackOrigins)
2697 Origin = DFSF.combineOrigins(Shadows, Origins, &SI);
2698 DFSF.storePrimitiveShadowOrigin(
SI.getPointerOperand(),
Size,
SI.getAlign(),
2699 PrimitiveShadow, Origin, &SI);
2704 IRB.
CreateCall(DFSF.DFS.DFSanStoreCallbackFn, {PrimitiveShadow, Addr8});
2710 assert(isa<AtomicRMWInst>(
I) || isa<AtomicCmpXchgInst>(
I));
2712 Value *Val =
I.getOperand(1);
2713 const auto &
DL =
I.getModule()->getDataLayout();
2722 const Align ShadowAlign = DFSF.getShadowAlign(InstAlignment);
2723 DFSF.storeZeroPrimitiveShadow(
Addr,
Size, ShadowAlign, &
I);
2724 DFSF.setShadow(&
I, DFSF.DFS.getZeroShadow(&
I));
2725 DFSF.setOrigin(&
I, DFSF.DFS.ZeroOrigin);
2729 visitCASOrRMW(
I.getAlign(),
I);
2736 visitCASOrRMW(
I.getAlign(),
I);
2743 visitInstOperands(UO);
2747 visitInstOperands(BO);
2750void DFSanVisitor::visitBitCastInst(
BitCastInst &BCI) {
2754 if (
auto *CI = dyn_cast<CallInst>(BCI.
getOperand(0)))
2757 visitInstOperands(BCI);
2760void DFSanVisitor::visitCastInst(
CastInst &CI) { visitInstOperands(CI); }
2762void DFSanVisitor::visitCmpInst(
CmpInst &CI) {
2763 visitInstOperands(CI);
2766 Value *CombinedShadow = DFSF.getShadow(&CI);
2768 IRB.
CreateCall(DFSF.DFS.DFSanCmpCallbackFn, CombinedShadow);
2785 DFSF.setShadow(&LPI, DFSF.DFS.getZeroShadow(&LPI));
2786 DFSF.setOrigin(&LPI, DFSF.DFS.ZeroOrigin);
2791 DFSF.isLookupTableConstant(
2793 visitInstOperands(GEPI);
2800 DFSF.setShadow(&GEPI, DFSF.getShadow(BasePointer));
2801 if (DFSF.DFS.shouldTrackOrigins())
2802 DFSF.setOrigin(&GEPI, DFSF.getOrigin(BasePointer));
2806 visitInstOperands(
I);
2810 visitInstOperands(
I);
2814 visitInstOperands(
I);
2819 Value *Agg =
I.getAggregateOperand();
2820 Value *AggShadow = DFSF.getShadow(Agg);
2822 DFSF.setShadow(&
I, ResShadow);
2823 visitInstOperandOrigins(
I);
2828 Value *AggShadow = DFSF.getShadow(
I.getAggregateOperand());
2829 Value *InsShadow = DFSF.getShadow(
I.getInsertedValueOperand());
2831 DFSF.setShadow(&
I, Res);
2832 visitInstOperandOrigins(
I);
2835void DFSanVisitor::visitAllocaInst(
AllocaInst &
I) {
2836 bool AllLoadsStores =
true;
2837 for (
User *U :
I.users()) {
2838 if (isa<LoadInst>(U))
2841 if (
StoreInst *SI = dyn_cast<StoreInst>(U)) {
2842 if (
SI->getPointerOperand() == &
I)
2846 AllLoadsStores =
false;
2849 if (AllLoadsStores) {
2851 DFSF.AllocaShadowMap[&
I] = IRB.
CreateAlloca(DFSF.DFS.PrimitiveShadowTy);
2852 if (DFSF.DFS.shouldTrackOrigins()) {
2853 DFSF.AllocaOriginMap[&
I] =
2857 DFSF.setShadow(&
I, DFSF.DFS.ZeroPrimitiveShadow);
2858 DFSF.setOrigin(&
I, DFSF.DFS.ZeroOrigin);
2861void DFSanVisitor::visitSelectInst(
SelectInst &
I) {
2862 Value *CondShadow = DFSF.getShadow(
I.getCondition());
2863 Value *TrueShadow = DFSF.getShadow(
I.getTrueValue());
2864 Value *FalseShadow = DFSF.getShadow(
I.getFalseValue());
2865 Value *ShadowSel =
nullptr;
2866 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
2867 std::vector<Value *> Shadows;
2868 std::vector<Value *> Origins;
2870 ShouldTrackOrigins ? DFSF.getOrigin(
I.getTrueValue()) :
nullptr;
2871 Value *FalseOrigin =
2872 ShouldTrackOrigins ? DFSF.getOrigin(
I.getFalseValue()) :
nullptr;
2874 DFSF.addConditionalCallbacksIfEnabled(
I,
I.getCondition());
2876 if (isa<VectorType>(
I.getCondition()->getType())) {
2877 ShadowSel = DFSF.combineShadowsThenConvert(
I.getType(), TrueShadow,
2879 if (ShouldTrackOrigins) {
2880 Shadows.push_back(TrueShadow);
2881 Shadows.push_back(FalseShadow);
2882 Origins.push_back(TrueOrigin);
2883 Origins.push_back(FalseOrigin);
2886 if (TrueShadow == FalseShadow) {
2887 ShadowSel = TrueShadow;
2888 if (ShouldTrackOrigins) {
2889 Shadows.push_back(TrueShadow);
2890 Origins.push_back(TrueOrigin);
2895 if (ShouldTrackOrigins) {
2896 Shadows.push_back(ShadowSel);
2898 FalseOrigin,
"", &
I));
2903 ? DFSF.combineShadowsThenConvert(
2904 I.getType(), CondShadow, ShadowSel, &
I)
2906 if (ShouldTrackOrigins) {
2908 Shadows.push_back(CondShadow);
2909 Origins.push_back(DFSF.getOrigin(
I.getCondition()));
2911 DFSF.setOrigin(&
I, DFSF.combineOrigins(Shadows, Origins, &
I));
2915void DFSanVisitor::visitMemSetInst(
MemSetInst &
I) {
2917 Value *ValShadow = DFSF.getShadow(
I.getValue());
2918 Value *ValOrigin = DFSF.DFS.shouldTrackOrigins()
2919 ? DFSF.getOrigin(
I.getValue())
2920 : DFSF.DFS.ZeroOrigin;
2922 DFSF.DFS.DFSanSetLabelFn,
2923 {ValShadow, ValOrigin,
2924 IRB.CreateBitCast(I.getDest(), Type::getInt8PtrTy(*DFSF.DFS.Ctx)),
2925 IRB.CreateZExtOrTrunc(I.getLength(), DFSF.DFS.IntptrTy)});
2933 if (DFSF.DFS.shouldTrackOrigins()) {
2935 DFSF.DFS.DFSanMemOriginTransferFn,
2936 {IRB.CreatePointerCast(I.getArgOperand(0), IRB.getInt8PtrTy()),
2937 IRB.CreatePointerCast(I.getArgOperand(1), IRB.getInt8PtrTy()),
2938 IRB.CreateIntCast(I.getArgOperand(2), DFSF.DFS.IntptrTy, false)});
2941 Value *RawDestShadow = DFSF.DFS.getShadowAddress(
I.getDest(), &
I);
2942 Value *SrcShadow = DFSF.DFS.getShadowAddress(
I.getSource(), &
I);
2945 DFSF.DFS.ShadowWidthBytes));
2949 auto *MTI = cast<MemTransferInst>(
2950 IRB.
CreateCall(
I.getFunctionType(),
I.getCalledOperand(),
2951 {DestShadow, SrcShadow, LenShadow, I.getVolatileCst()}));
2952 MTI->setDestAlignment(DFSF.getShadowAlign(
I.getDestAlign().valueOrOne()));
2953 MTI->setSourceAlignment(DFSF.getShadowAlign(
I.getSourceAlign().valueOrOne()));
2955 IRB.
CreateCall(DFSF.DFS.DFSanMemTransferCallbackFn,
2957 IRB.CreateZExtOrTrunc(I.getLength(), DFSF.DFS.IntptrTy)});
2961void DFSanVisitor::visitBranchInst(
BranchInst &BR) {
2962 if (!
BR.isConditional())
2965 DFSF.addConditionalCallbacksIfEnabled(BR,
BR.getCondition());
2968void DFSanVisitor::visitSwitchInst(
SwitchInst &SW) {
2969 DFSF.addConditionalCallbacksIfEnabled(SW, SW.
getCondition());
2974 if (
auto *
I = dyn_cast<BitCastInst>(RetVal)) {
2975 RetVal =
I->getOperand(0);
2977 if (
auto *
I = dyn_cast<CallInst>(RetVal)) {
2978 return I->isMustTailCall();
2983void DFSanVisitor::visitReturnInst(
ReturnInst &RI) {
2991 Type *RT = DFSF.F->getFunctionType()->getReturnType();
2992 unsigned Size = getDataLayout().getTypeAllocSize(DFSF.DFS.getShadowTy(RT));
2998 if (DFSF.DFS.shouldTrackOrigins()) {
3006 std::vector<Value *> &Args,
3013 for (
unsigned N = FT->getNumParams();
N != 0; ++
I, --
N)
3014 Args.push_back(DFSF.collapseToPrimitiveShadow(DFSF.getShadow(*
I), &CB));
3017 if (FT->isVarArg()) {
3018 auto *LabelVATy = ArrayType::get(DFSF.DFS.PrimitiveShadowTy,
3019 CB.
arg_size() - FT->getNumParams());
3020 auto *LabelVAAlloca =
3021 new AllocaInst(LabelVATy, getDataLayout().getAllocaAddrSpace(),
3022 "labelva", &DFSF.F->getEntryBlock().front());
3024 for (
unsigned N = 0;
I != CB.
arg_end(); ++
I, ++
N) {
3026 IRB.
CreateStore(DFSF.collapseToPrimitiveShadow(DFSF.getShadow(*
I), &CB),
3034 if (!FT->getReturnType()->isVoidTy()) {
3035 if (!DFSF.LabelReturnAlloca) {
3037 DFSF.DFS.PrimitiveShadowTy, getDataLayout().getAllocaAddrSpace(),
3038 "labelreturn", &DFSF.F->getEntryBlock().front());
3040 Args.push_back(DFSF.LabelReturnAlloca);
3045 std::vector<Value *> &Args,
3052 for (
unsigned N = FT->getNumParams();
N != 0; ++
I, --
N)
3053 Args.push_back(DFSF.getOrigin(*
I));
3056 if (FT->isVarArg()) {
3058 ArrayType::get(DFSF.DFS.OriginTy, CB.
arg_size() - FT->getNumParams());
3059 auto *OriginVAAlloca =
3060 new AllocaInst(OriginVATy, getDataLayout().getAllocaAddrSpace(),
3061 "originva", &DFSF.F->getEntryBlock().front());
3063 for (
unsigned N = 0;
I != CB.
arg_end(); ++
I, ++
N) {
3072 if (!FT->getReturnType()->isVoidTy()) {
3073 if (!DFSF.OriginReturnAlloca) {
3075 DFSF.DFS.OriginTy, getDataLayout().getAllocaAddrSpace(),
3076 "originreturn", &DFSF.F->getEntryBlock().front());
3078 Args.push_back(DFSF.OriginReturnAlloca);
3084 switch (DFSF.DFS.getWrapperKind(&
F)) {
3085 case DataFlowSanitizer::WK_Warning:
3087 IRB.
CreateCall(DFSF.DFS.DFSanUnimplementedFn,
3089 DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &
F);
3090 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3091 DFSF.setOrigin(&CB, DFSF.DFS.ZeroOrigin);
3093 case DataFlowSanitizer::WK_Discard:
3095 DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &
F);
3096 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3097 DFSF.setOrigin(&CB, DFSF.DFS.ZeroOrigin);
3099 case DataFlowSanitizer::WK_Functional:
3101 DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &
F);
3102 visitInstOperands(CB);
3104 case DataFlowSanitizer::WK_Custom:
3108 CallInst *CI = dyn_cast<CallInst>(&CB);
3112 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
3114 TransformedFunction CustomFn = DFSF.DFS.getCustomFunctionType(FT);
3115 std::string CustomFName = ShouldTrackOrigins ?
"__dfso_" :
"__dfsw_";
3116 CustomFName +=
F.getName();
3118 CustomFName, CustomFn.TransformedType);
3120 CustomFn->copyAttributesFrom(&
F);
3123 if (!FT->getReturnType()->isVoidTy()) {
3124 CustomFn->removeFnAttrs(DFSF.DFS.ReadOnlyNoneAttrs);
3128 std::vector<Value *>
Args;
3132 for (
unsigned N = FT->getNumParams();
N != 0; ++
I, --
N) {
3137 const unsigned ShadowArgStart =
Args.size();
3138 addShadowArguments(
F, CB, Args, IRB);
3141 const unsigned OriginArgStart =
Args.size();
3142 if (ShouldTrackOrigins)
3143 addOriginArguments(
F, CB, Args, IRB);
3156 for (
unsigned N = 0;
N < FT->getNumParams();
N++) {
3157 const unsigned ArgNo = ShadowArgStart +
N;
3159 DFSF.DFS.PrimitiveShadowTy)
3161 if (ShouldTrackOrigins) {
3162 const unsigned OriginArgNo = OriginArgStart +
N;
3170 if (!FT->getReturnType()->isVoidTy()) {
3172 IRB.
CreateLoad(DFSF.DFS.PrimitiveShadowTy, DFSF.LabelReturnAlloca);
3173 DFSF.setShadow(CustomCI, DFSF.expandFromPrimitiveShadow(
3174 FT->getReturnType(), LabelLoad, &CB));
3175 if (ShouldTrackOrigins) {
3177 IRB.
CreateLoad(DFSF.DFS.OriginTy, DFSF.OriginReturnAlloca);
3178 DFSF.setOrigin(CustomCI, OriginLoad);
3190 constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
3191 uint32_t OrderingTable[NumOrderings] = {};
3193 OrderingTable[(int)AtomicOrderingCABI::relaxed] =
3194 OrderingTable[(
int)AtomicOrderingCABI::acquire] =
3195 OrderingTable[(int)AtomicOrderingCABI::consume] =
3196 (
int)AtomicOrderingCABI::acquire;
3197 OrderingTable[(int)AtomicOrderingCABI::release] =
3198 OrderingTable[(
int)AtomicOrderingCABI::acq_rel] =
3199 (int)AtomicOrderingCABI::acq_rel;
3200 OrderingTable[(int)AtomicOrderingCABI::seq_cst] =
3201 (
int)AtomicOrderingCABI::seq_cst;
3204 ArrayRef(OrderingTable, NumOrderings));
3207void DFSanVisitor::visitLibAtomicLoad(
CallBase &CB) {
3209 assert(isa<CallInst>(CB));
3218 Value *NewOrdering =
3223 NextIRB.SetCurrentDebugLocation(CB.
getDebugLoc());
3228 NextIRB.CreateCall(DFSF.DFS.DFSanMemShadowOriginTransferFn,
3229 {NextIRB.CreatePointerCast(DstPtr, NextIRB.getInt8PtrTy()),
3230 NextIRB.CreatePointerCast(SrcPtr, NextIRB.getInt8PtrTy()),
3231 NextIRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3235 constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
3236 uint32_t OrderingTable[NumOrderings] = {};
3238 OrderingTable[(int)AtomicOrderingCABI::relaxed] =
3239 OrderingTable[(
int)AtomicOrderingCABI::release] =
3240 (int)AtomicOrderingCABI::release;
3241 OrderingTable[(int)AtomicOrderingCABI::consume] =
3242 OrderingTable[(
int)AtomicOrderingCABI::acquire] =
3243 OrderingTable[(int)AtomicOrderingCABI::acq_rel] =
3244 (
int)AtomicOrderingCABI::acq_rel;
3245 OrderingTable[(int)AtomicOrderingCABI::seq_cst] =
3246 (
int)AtomicOrderingCABI::seq_cst;
3249 ArrayRef(OrderingTable, NumOrderings));
3252void DFSanVisitor::visitLibAtomicStore(
CallBase &CB) {
3260 Value *NewOrdering =
3267 IRB.
CreateCall(DFSF.DFS.DFSanMemShadowOriginTransferFn,
3268 {IRB.CreatePointerCast(DstPtr, IRB.getInt8PtrTy()),
3269 IRB.CreatePointerCast(SrcPtr, IRB.getInt8PtrTy()),
3270 IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3273void DFSanVisitor::visitLibAtomicExchange(
CallBase &CB) {
3288 IRB.
CreateCall(DFSF.DFS.DFSanMemShadowOriginTransferFn,
3289 {IRB.CreatePointerCast(DstPtr, IRB.getInt8PtrTy()),
3290 IRB.CreatePointerCast(TargetPtr, IRB.getInt8PtrTy()),
3291 IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3294 IRB.
CreateCall(DFSF.DFS.DFSanMemShadowOriginTransferFn,
3295 {IRB.CreatePointerCast(TargetPtr, IRB.getInt8PtrTy()),
3296 IRB.CreatePointerCast(SrcPtr, IRB.getInt8PtrTy()),
3297 IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3300void DFSanVisitor::visitLibAtomicCompareExchange(
CallBase &CB) {
3314 NextIRB.SetCurrentDebugLocation(CB.
getDebugLoc());
3316 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3321 DFSF.DFS.DFSanMemShadowOriginConditionalExchangeFn,
3322 {NextIRB.CreateIntCast(&CB, NextIRB.getInt8Ty(), false),
3323 NextIRB.CreatePointerCast(TargetPtr, NextIRB.getInt8PtrTy()),
3324 NextIRB.CreatePointerCast(ExpectedPtr, NextIRB.getInt8PtrTy()),
3325 NextIRB.CreatePointerCast(DesiredPtr, NextIRB.getInt8PtrTy()),
3326 NextIRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3329void DFSanVisitor::visitCallBase(
CallBase &CB) {
3332 visitInstOperands(CB);
3338 if (
F == DFSF.DFS.DFSanVarargWrapperFn.getCallee()->stripPointerCasts())
3342 if (DFSF.TLI.getLibFunc(CB, LF)) {
3347 case LibFunc_atomic_load:
3348 if (!isa<CallInst>(CB)) {
3349 llvm::errs() <<
"DFSAN -- cannot instrument invoke of libatomic load. "
3353 visitLibAtomicLoad(CB);
3355 case LibFunc_atomic_store:
3356 visitLibAtomicStore(CB);
3364 if (
F &&
F->hasName() && !
F->isVarArg()) {
3365 if (
F->getName() ==
"__atomic_exchange") {
3366 visitLibAtomicExchange(CB);
3369 if (
F->getName() ==
"__atomic_compare_exchange") {
3370 visitLibAtomicCompareExchange(CB);
3377 if (UnwrappedFnIt != DFSF.DFS.UnwrappedFnMap.end())
3378 if (visitWrappedCallBase(*UnwrappedFnIt->second, CB))
3383 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
3388 unsigned ArgOffset = 0;
3389 for (
unsigned I = 0,
N = FT->getNumParams();
I !=
N; ++
I) {
3390 if (ShouldTrackOrigins) {
3393 if (
I < DFSF.DFS.NumOfElementsInArgOrgTLS &&
3394 !DFSF.DFS.isZeroShadow(ArgShadow))
3396 DFSF.getArgOriginTLS(
I, IRB));
3400 DL.getTypeAllocSize(DFSF.DFS.getShadowTy(FT->getParamType(
I)));
3406 DFSF.getArgTLS(FT->getParamType(
I), ArgOffset, IRB),
3413 if (
InvokeInst *II = dyn_cast<InvokeInst>(&CB)) {
3414 if (II->getNormalDest()->getSinglePredecessor()) {
3415 Next = &II->getNormalDest()->front();
3418 SplitEdge(II->getParent(), II->getNormalDest(), &DFSF.DT);
3419 Next = &NewBB->
front();
3427 if (isa<CallInst>(CB) && cast<CallInst>(CB).isMustTailCall())
3432 unsigned Size =
DL.getTypeAllocSize(DFSF.DFS.getShadowTy(&CB));
3435 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3437 LoadInst *LI = NextIRB.CreateAlignedLoad(
3438 DFSF.DFS.getShadowTy(&CB), DFSF.getRetvalTLS(CB.
getType(), NextIRB),
3440 DFSF.SkipInsts.insert(LI);
3441 DFSF.setShadow(&CB, LI);
3442 DFSF.NonZeroChecks.push_back(LI);
3445 if (ShouldTrackOrigins) {
3446 LoadInst *LI = NextIRB.CreateLoad(DFSF.DFS.OriginTy,
3447 DFSF.getRetvalOriginTLS(),
"_dfsret_o");
3448 DFSF.SkipInsts.insert(LI);
3449 DFSF.setOrigin(&CB, LI);
3452 DFSF.addReachesFunctionCallbacksIfEnabled(NextIRB, CB, &CB);
3456void DFSanVisitor::visitPHINode(
PHINode &PN) {
3457 Type *ShadowTy = DFSF.DFS.getShadowTy(&PN);
3466 DFSF.setShadow(&PN, ShadowPN);
3469 if (DFSF.DFS.shouldTrackOrigins()) {
3475 DFSF.setOrigin(&PN, OriginPN);
3478 DFSF.PHIFixups.push_back({&PN, ShadowPN, OriginPN});
3488 if (!DataFlowSanitizer(ABIListFiles).runImpl(M, GetTLI))
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static bool isConstant(const MachineInstr &MI)
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
const MemoryMapParams Linux_LoongArch64_MemoryMapParams
const MemoryMapParams Linux_X86_64_MemoryMapParams
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::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 const Align MinOriginAlignment
static cl::opt< int > ClTrackOrigins("dfsan-track-origins", cl::desc("Track origins of labels"), cl::Hidden, cl::init(0))
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 > ClReachesFunctionCallbacks("dfsan-reaches-function-callbacks", cl::desc("Insert calls to callback functions on data reaching a function."), cl::Hidden, cl::init(false))
static Value * expandFromPrimitiveShadowRecursive(Value *Shadow, SmallVector< unsigned, 4 > &Indices, Type *SubShadowTy, Value *PrimitiveShadow, IRBuilder<> &IRB)
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< bool > ClPreserveAlignment("dfsan-preserve-alignment", cl::desc("respect alignment requirements provided by input IR"), cl::Hidden, cl::init(false))
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 > 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::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 const Align ShadowTLSAlignment
static AtomicOrdering addReleaseOrdering(AtomicOrdering AO)
static AtomicOrdering addAcquireOrdering(AtomicOrdering AO)
Value * StripPointerGEPsAndCasts(Value *V)
const MemoryMapParams Linux_AArch64_MemoryMapParams
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 > 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 StringRef getGlobalTypeString(const GlobalValue &G)
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 const unsigned ArgTLSSize
static const unsigned RetvalTLSSize
static bool isAMustTailRetVal(Value *RetVal)
static cl::opt< bool > ClEventCallbacks("dfsan-event-callbacks", cl::desc("Insert calls to __dfsan_*_callback functions on data events."), cl::Hidden, cl::init(false))
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
This file builds on the ADT/GraphTraits.h file to build generic depth first graph iterator.
static bool runImpl(Function &F, const TargetLowering &TLI)
This is the interface for a simple mod/ref and alias analysis over globals.
Module.h This file contains the declarations for the Module class.
FunctionAnalysisManager FAM
This header defines various interfaces for pass management in LLVM.
const SmallVectorImpl< MachineOperand > & Cond
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
StringSet - A set-like wrapper for the StringMap.
Defines the virtual file system interface vfs::FileSystem.
Class for arbitrary precision integers.
an instruction to allocate memory on the stack
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
This class represents an incoming formal argument to a Function.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
An instruction that atomically checks whether a specified value is in a memory location,...
an instruction that atomically reads a memory location, combines it with another value,...
AttributeSet getFnAttrs() const
The function attributes are returned.
static AttributeList get(LLVMContext &C, ArrayRef< std::pair< unsigned, Attribute > > Attrs)
Create an AttributeList with the specified parameters in it.
AttributeSet getRetAttrs() const
The attributes for the ret value are returned.
unsigned getNumAttrSets() const
AttributeSet getParamAttrs(unsigned ArgNo) const
The attributes for the argument or parameter at the given index are returned.
AttributeMask & addAttribute(Attribute::AttrKind Val)
Add an attribute to the mask.
static Attribute getWithMemoryEffects(LLVMContext &Context, MemoryEffects ME)
LLVM Basic Block Representation.
const Instruction & front() const
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
This class represents a no-op cast from one type to another.
Conditional or Unconditional Branch instruction.
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
bool isInlineAsm() const
Check if this call is an inline asm statement.
void setCallingConv(CallingConv::ID CC)
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
CallingConv::ID getCallingConv() const
User::op_iterator arg_begin()
Return the iterator pointing to the beginning of the argument list.
Value * getCalledOperand() const
void setAttributes(AttributeList A)
Set the parameter attributes for this call.
void addRetAttr(Attribute::AttrKind Kind)
Adds the attribute to the return value.
Value * getArgOperand(unsigned i) const
void setArgOperand(unsigned i, Value *v)
User::op_iterator arg_end()
Return the iterator pointing to the end of the argument list.
FunctionType * getFunctionType() const
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
unsigned arg_size() const
AttributeList getAttributes() const
Return the parameter attributes for this call.
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
Adds the attribute to the indicated argument.
void setCalledFunction(Function *Fn)
Sets the function called, including updating the function type.
This class represents a function call, abstracting a target machine's calling convention.
bool isMustTailCall() const
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
This is the base class for all instructions that perform data casts.
This class is the base class for the comparison instructions.
static ConstantAggregateZero * get(Type *Ty)
static Constant * get(LLVMContext &Context, ArrayRef< uint8_t > Elts)
get() constructors - Return a constant with vector type with an element count and element type matchi...
A constant value that is initialized with an expression using other constant values.
static Constant * getBitCast(Constant *C, Type *Ty, bool OnlyIfReduced=false)
This is the shared class of boolean and integer constants.
static Constant * get(Type *Ty, uint64_t V, bool IsSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
static ConstantInt * getSigned(IntegerType *Ty, int64_t V)
Return a ConstantInt with the specified value for the specified type.
This is an important base class in LLVM.
bool isNullValue() const
Return true if this is the value that would be returned by getNullValue.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
A parsed version of the target data layout string in and methods for querying it.
DILocation * get() const
Get the underlying DILocation.
iterator find(const_arg_type_t< KeyT > Val)
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Implements a dense probed hash-table based set.
void recalculate(ParentType &Func)
recalculate - compute a dominator tree for the given function
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
static FixedVectorType * get(Type *ElementType, unsigned NumElts)
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
void removeFnAttrs(const AttributeMask &Attrs)
void removeFnAttr(Attribute::AttrKind Kind)
Remove function attributes from this function.
void removeRetAttrs(const AttributeMask &Attrs)
removes the attributes from the return value list of attributes.
void copyAttributesFrom(const Function *Src)
copyAttributesFrom - copy all additional attributes (those not needed to create a Function) from the ...
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
Value * getPointerOperand()
void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
const GlobalObject * getAliaseeObject() const
static bool isExternalWeakLinkage(LinkageTypes Linkage)
LinkageTypes getLinkage() const
Module * getParent()
Get the module that this global value is contained inside of...
PointerType * getType() const
Global values are always pointers.
LinkageTypes
An enumeration for the kinds of linkage for global values.
@ WeakODRLinkage
Same, but only replaced by something equivalent.
@ LinkOnceODRLinkage
Same, but only replaced by something equivalent.
Type * getValueType() const
Analysis pass providing a never-invalidated alias analysis result.
Value * CreateTrunc(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateInsertElement(Type *VecTy, Value *NewElt, Value *Idx, const Twine &Name="")
Value * CreateConstGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, const Twine &Name="")
AllocaInst * CreateAlloca(Type *Ty, unsigned AddrSpace, Value *ArraySize=nullptr, const Twine &Name="")
Value * CreateInsertValue(Value *Agg, Value *Val, ArrayRef< unsigned > Idxs, const Twine &Name="")
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
LoadInst * CreateAlignedLoad(Type *Ty, Value *Ptr, MaybeAlign Align, const char *Name)
Constant * CreateGlobalStringPtr(StringRef Str, const Twine &Name="", unsigned AddressSpace=0, Module *M=nullptr)
Same as CreateGlobalString, but return a pointer with "i8*" type instead of a pointer to array of i8.
Value * CreatePointerCast(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")
Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="", Instruction *MDFrom=nullptr)
Value * CreateConstGEP2_64(Type *Ty, Value *Ptr, uint64_t Idx0, uint64_t Idx1, const Twine &Name="")
BasicBlock::iterator GetInsertPoint() const
Value * CreateStructGEP(Type *Ty, Value *Ptr, unsigned Idx, const Twine &Name="")
Value * CreateIntToPtr(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
IntegerType * getInt64Ty()
Fetch the type representing a 64-bit integer.
Value * CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
PointerType * getInt8PtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer to an 8-bit integer value.
LLVMContext & getContext() const
Value * CreateAnd(Value *LHS, Value *RHS, const Twine &Name="")
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateIntCast(Value *V, Type *DestTy, bool isSigned, const Twine &Name="")
StoreInst * CreateAlignedStore(Value *Val, Value *Ptr, MaybeAlign Align, bool isVolatile=false)
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args=std::nullopt, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateXor(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateGEP(Type *Ty, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="", bool IsInBounds=false)
Value * CreateMul(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...
This instruction inserts a single (scalar) element into a VectorType value.
This instruction inserts a struct field of array element value into an aggregate value.
Base class for instruction visitors.
RetTy visitCmpInst(CmpInst &I)
RetTy visitExtractElementInst(ExtractElementInst &I)
RetTy visitCallBase(CallBase &I)
RetTy visitInsertValueInst(InsertValueInst &I)
RetTy visitShuffleVectorInst(ShuffleVectorInst &I)
RetTy visitLandingPadInst(LandingPadInst &I)
RetTy visitAtomicCmpXchgInst(AtomicCmpXchgInst &I)
RetTy visitBitCastInst(BitCastInst &I)
RetTy visitSwitchInst(SwitchInst &I)
RetTy visitPHINode(PHINode &I)
RetTy visitReturnInst(ReturnInst &I)
RetTy visitExtractValueInst(ExtractValueInst &I)
RetTy visitUnaryOperator(UnaryOperator &I)
RetTy visitStoreInst(StoreInst &I)
RetTy visitInsertElementInst(InsertElementInst &I)
RetTy visitAtomicRMWInst(AtomicRMWInst &I)
RetTy visitAllocaInst(AllocaInst &I)
RetTy visitBinaryOperator(BinaryOperator &I)
RetTy visitMemTransferInst(MemTransferInst &I)
RetTy visitMemSetInst(MemSetInst &I)
RetTy visitCastInst(CastInst &I)
RetTy visitBranchInst(BranchInst &I)
RetTy visitSelectInst(SelectInst &I)
RetTy visitGetElementPtrInst(GetElementPtrInst &I)
RetTy visitLoadInst(LoadInst &I)
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
bool isAtomic() const LLVM_READONLY
Return true if this instruction has an AtomicOrdering of unordered or higher.
const BasicBlock * getParent() const
bool isTerminator() const
bool comesBefore(const Instruction *Other) const
Given an instruction Other in the same basic block as this instruction, return true if this instructi...
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
Class to represent integer types.
static IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
This is an important class for using LLVM in a threaded context.
The landingpad instruction holds all of the information necessary to generate correct exception handl...
An instruction for reading from memory.
void setAlignment(Align Align)
Value * getPointerOperand()
void setOrdering(AtomicOrdering Ordering)
Sets the ordering constraint of this load instruction.
AtomicOrdering getOrdering() const
Returns the ordering constraint of this load instruction.
Align getAlign() const
Return the alignment of the access that is being performed.
MDNode * createBranchWeights(uint32_t TrueWeight, uint32_t FalseWeight)
Return metadata containing two branch weights.
This class wraps the llvm.memset and llvm.memset.inline intrinsics.
This class wraps the llvm.memcpy/memmove intrinsics.
static MemoryEffectsBase readOnly()
Create MemoryEffectsBase that can read any memory.
A Module instance is used to store all the information related to an LLVM module.
const std::string & getModuleInlineAsm() const
Get any module-scope inline assembly blocks.
void setModuleInlineAsm(StringRef Asm)
Set the module-scope inline assembly blocks.
FunctionCallee getOrInsertFunction(StringRef Name, FunctionType *T, AttributeList AttributeList)
Look up the specified function in the module symbol table.
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
Constant * getOrInsertGlobal(StringRef Name, Type *Ty, function_ref< GlobalVariable *()> CreateGlobalCallback)
Look up the specified global in the module symbol table.
unsigned getOpcode() const
Return the opcode for this Instruction or ConstantExpr.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
iterator_range< const_block_iterator > blocks() const
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
unsigned getNumIncomingValues() const
Return the number of incoming edges.
static PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
void abandon()
Mark an analysis as abandoned.
Return a value (possibly void), from a function.
Value * getReturnValue() const
Convenience accessor. Returns null if there is no return value.
static ReturnInst * Create(LLVMContext &C, Value *retVal=nullptr, Instruction *InsertBefore=nullptr)
This class represents the LLVM 'select' instruction.
static SelectInst * Create(Value *C, Value *S1, Value *S2, const Twine &NameStr="", Instruction *InsertBefore=nullptr, Instruction *MDFrom=nullptr)
This instruction constructs a fixed permutation of two input vectors.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
static std::unique_ptr< SpecialCaseList > createOrDie(const std::vector< std::string > &Paths, llvm::vfs::FileSystem &FS)
Parses the special case list entries from files.
An instruction for storing to memory.
StringRef - Represent a constant reference to a string, i.e.
StringSet - A wrapper for StringMap that provides set-like functionality.
std::pair< typename Base::iterator, bool > insert(StringRef key)
Class to represent struct types.
static StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
Value * getCondition() const
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
Triple - Helper class for working with autoconf configuration names.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
unsigned getIntegerBitWidth() const
static Type * getVoidTy(LLVMContext &C)
bool isSized(SmallPtrSetImpl< Type * > *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
static IntegerType * getInt32Ty(LLVMContext &C)
static IntegerType * getInt64Ty(LLVMContext &C)
bool isIntegerTy() const
True if this is an instance of IntegerType.
bool isVoidTy() const
Return true if this is 'void'.
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
This function has undefined behavior.
A Use represents the edge between a Value definition and its users.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
void setName(const Twine &Name)
Change the name of the value.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
LLVMContext & getContext() const
All values hold a context through their type.
StringRef getName() const
Return a constant reference to the value's name.
void takeName(Value *V)
Transfer the name from V to this value.
An efficient, type-erasing, non-owning reference to a callable.
self_iterator getIterator()
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
AttributeMask typeIncompatible(Type *Ty, AttributeSafetyKind ASK=ASK_ALL)
Which attributes cannot be applied to a type.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ C
The default llvm calling convention, compatible with C.
@ BR
Control flow instructions. These all have token chains.
@ CE
Windows NT (Windows on ARM)
initializer< Ty > init(const Ty &Val)
NodeAddr< PhiNode * > Phi
NodeAddr< BlockNode * > Block
IntrusiveRefCntPtr< FileSystem > getRealFileSystem()
Gets an vfs::FileSystem for the 'real' file system, as seen by the operating system.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
void append_range(Container &C, Range &&R)
Wrapper function to append a range to a container.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
AtomicOrdering
Atomic ordering for LLVM's memory model.
void getUnderlyingObjects(const Value *V, SmallVectorImpl< const Value * > &Objects, LoopInfo *LI=nullptr, unsigned MaxLookup=6)
This method is similar to getUnderlyingObject except that it can look through phi and select instruct...
void erase_value(Container &C, ValueType V)
Wrapper function to remove a value from a container:
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Align assumeAligned(uint64_t Value)
Treats the value 0 as a 1, so Align is always at least 1.
iterator_range< df_iterator< T > > depth_first(const T &G)
Instruction * SplitBlockAndInsertIfThen(Value *Cond, BasicBlock::iterator SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
BasicBlock * SplitEdge(BasicBlock *From, BasicBlock *To, DominatorTree *DT=nullptr, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, const Twine &BBName="")
Split the edge connecting the specified blocks, and return the newly created basic block between From...
bool removeUnreachableBlocks(Function &F, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr)
Remove all blocks that can not be reached from the function's entry.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This struct is a compact representation of a valid (non-zero power of two) alignment.
uint64_t value() const
This is a hole in the type system and should not be abused.