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 {
311 std::unique_ptr<SpecialCaseList> SCL;
314 DFSanABIList() =
default;
316 void set(std::unique_ptr<SpecialCaseList> List) { SCL = std::move(List); }
321 return isIn(*
F.getParent(), Category) ||
322 SCL->inSection(
"dataflow",
"fun",
F.getName(), Category);
334 return SCL->inSection(
"dataflow",
"fun", GA.
getName(), Category);
336 return SCL->inSection(
"dataflow",
"global", GA.
getName(), Category) ||
343 return SCL->inSection(
"dataflow",
"src",
M.getModuleIdentifier(), Category);
350struct TransformedFunction {
352 std::vector<unsigned> ArgumentIndexMapping)
353 : OriginalType(OriginalType), TransformedType(TransformedType),
354 ArgumentIndexMapping(ArgumentIndexMapping) {}
357 TransformedFunction(
const TransformedFunction &) =
delete;
358 TransformedFunction &operator=(
const TransformedFunction &) =
delete;
361 TransformedFunction(TransformedFunction &&) =
default;
362 TransformedFunction &operator=(TransformedFunction &&) =
default;
375 std::vector<unsigned> ArgumentIndexMapping;
382transformFunctionAttributes(
const TransformedFunction &TransformedFunction,
386 std::vector<llvm::AttributeSet> ArgumentAttributes(
387 TransformedFunction.TransformedType->getNumParams());
392 for (
unsigned I = 0, IE = TransformedFunction.ArgumentIndexMapping.size();
394 unsigned TransformedIndex = TransformedFunction.ArgumentIndexMapping[
I];
395 ArgumentAttributes[TransformedIndex] = CallSiteAttrs.
getParamAttrs(
I);
399 for (
unsigned I = TransformedFunction.OriginalType->getNumParams(),
410class DataFlowSanitizer {
411 friend struct DFSanFunction;
412 friend class DFSanVisitor;
414 enum { ShadowWidthBits = 8, ShadowWidthBytes = ShadowWidthBits / 8 };
416 enum { OriginWidthBits = 32, OriginWidthBytes = OriginWidthBits / 8 };
475 FunctionType *DFSanMemShadowOriginConditionalExchangeFnTy;
500 MDNode *OriginStoreWeights;
501 DFSanABIList ABIList;
508 const MemoryMapParams *MapParams;
513 std::pair<Value *, Value *>
517 bool isForceZeroLabels(
const Function *
F);
525 void initializeCallbackFunctions(
Module &M);
526 void initializeRuntimeFunctions(
Module &M);
527 bool initializeModule(
Module &M);
539 bool shouldTrackOrigins();
551 bool isZeroShadow(
Value *V);
565 DataFlowSanitizer(
const std::vector<std::string> &ABIListFiles);
571struct DFSanFunction {
572 DataFlowSanitizer &DFS;
576 bool IsForceZeroLabels;
585 struct PHIFixupElement {
590 std::vector<PHIFixupElement> PHIFixups;
593 std::vector<Value *> NonZeroChecks;
595 struct CachedShadow {
608 DFSanFunction(DataFlowSanitizer &DFS,
Function *F,
bool IsNativeABI,
610 : DFS(DFS),
F(
F), IsNativeABI(IsNativeABI),
611 IsForceZeroLabels(IsForceZeroLabels), TLI(TLI) {
629 Value *getRetvalOriginTLS();
641 Value *combineOrigins(
const std::vector<Value *> &Shadows,
642 const std::vector<Value *> &Origins,
Instruction *Pos,
701 bool isLookupTableConstant(
Value *
P);
706 template <
class AggregateType>
707 Value *collapseAggregateShadow(AggregateType *AT,
Value *Shadow,
716 std::pair<Value *, Value *>
761 bool shouldInstrumentWithCall();
767 std::pair<Value *, Value *>
770 int NumOriginStores = 0;
773class DFSanVisitor :
public InstVisitor<DFSanVisitor> {
777 DFSanVisitor(DFSanFunction &DFSF) : DFSF(DFSF) {}
780 return DFSF.F->getParent()->getDataLayout();
798 void visitLibAtomicLoad(
CallBase &CB);
799 void visitLibAtomicStore(
CallBase &CB);
800 void visitLibAtomicExchange(
CallBase &CB);
801 void visitLibAtomicCompareExchange(
CallBase &CB);
835bool LibAtomicFunction(
const Function &
F) {
841 if (!
F.hasName() ||
F.isVarArg())
843 switch (
F.arg_size()) {
845 return F.getName() ==
"__atomic_load" ||
F.getName() ==
"__atomic_store";
847 return F.getName() ==
"__atomic_exchange";
849 return F.getName() ==
"__atomic_compare_exchange";
857DataFlowSanitizer::DataFlowSanitizer(
858 const std::vector<std::string> &ABIListFiles) {
859 std::vector<std::string> AllABIListFiles(std::move(ABIListFiles));
866 CombineTaintLookupTableNames.
insert(v);
869TransformedFunction DataFlowSanitizer::getCustomFunctionType(
FunctionType *
T) {
876 std::vector<unsigned> ArgumentIndexMapping;
877 for (
unsigned I = 0,
E =
T->getNumParams();
I !=
E; ++
I) {
878 Type *ParamType =
T->getParamType(
I);
879 ArgumentIndexMapping.push_back(ArgTypes.
size());
882 for (
unsigned I = 0,
E =
T->getNumParams();
I !=
E; ++
I)
885 ArgTypes.
push_back(PrimitiveShadowPtrTy);
886 Type *RetType =
T->getReturnType();
888 ArgTypes.
push_back(PrimitiveShadowPtrTy);
890 if (shouldTrackOrigins()) {
891 for (
unsigned I = 0,
E =
T->getNumParams();
I !=
E; ++
I)
899 return TransformedFunction(
900 T, FunctionType::get(
T->getReturnType(), ArgTypes,
T->isVarArg()),
901 ArgumentIndexMapping);
904bool DataFlowSanitizer::isZeroShadow(
Value *V) {
906 if (!isa<ArrayType>(
T) && !isa<StructType>(
T)) {
907 if (
const ConstantInt *CI = dyn_cast<ConstantInt>(V))
912 return isa<ConstantAggregateZero>(V);
915bool DataFlowSanitizer::hasLoadSizeForFastPath(
uint64_t Size) {
917 return ShadowSize % 8 == 0 || ShadowSize == 4;
920bool DataFlowSanitizer::shouldTrackOrigins() {
922 return ShouldTrackOrigins;
925Constant *DataFlowSanitizer::getZeroShadow(
Type *OrigTy) {
926 if (!isa<ArrayType>(OrigTy) && !isa<StructType>(OrigTy))
927 return ZeroPrimitiveShadow;
928 Type *ShadowTy = getShadowTy(OrigTy);
933 return getZeroShadow(
V->getType());
939 if (!isa<ArrayType>(SubShadowTy) && !isa<StructType>(SubShadowTy))
942 if (
ArrayType *AT = dyn_cast<ArrayType>(SubShadowTy)) {
943 for (
unsigned Idx = 0;
Idx < AT->getNumElements();
Idx++) {
946 Shadow, Indices, AT->getElementType(), PrimitiveShadow, IRB);
952 if (
StructType *ST = dyn_cast<StructType>(SubShadowTy)) {
953 for (
unsigned Idx = 0;
Idx < ST->getNumElements();
Idx++) {
956 Shadow, Indices, ST->getElementType(
Idx), PrimitiveShadow, IRB);
964bool DFSanFunction::shouldInstrumentWithCall() {
969Value *DFSanFunction::expandFromPrimitiveShadow(
Type *
T,
Value *PrimitiveShadow,
971 Type *ShadowTy = DFS.getShadowTy(
T);
973 if (!isa<ArrayType>(ShadowTy) && !isa<StructType>(ShadowTy))
974 return PrimitiveShadow;
976 if (DFS.isZeroShadow(PrimitiveShadow))
977 return DFS.getZeroShadow(ShadowTy);
983 PrimitiveShadow, IRB);
986 CachedCollapsedShadows[Shadow] = PrimitiveShadow;
990template <
class AggregateType>
991Value *DFSanFunction::collapseAggregateShadow(AggregateType *AT,
Value *Shadow,
993 if (!AT->getNumElements())
994 return DFS.ZeroPrimitiveShadow;
997 Value *Aggregator = collapseToPrimitiveShadow(FirstItem, IRB);
999 for (
unsigned Idx = 1;
Idx < AT->getNumElements();
Idx++) {
1001 Value *ShadowInner = collapseToPrimitiveShadow(ShadowItem, IRB);
1002 Aggregator = IRB.
CreateOr(Aggregator, ShadowInner);
1007Value *DFSanFunction::collapseToPrimitiveShadow(
Value *Shadow,
1010 if (!isa<ArrayType>(ShadowTy) && !isa<StructType>(ShadowTy))
1012 if (
ArrayType *AT = dyn_cast<ArrayType>(ShadowTy))
1013 return collapseAggregateShadow<>(AT, Shadow, IRB);
1014 if (
StructType *ST = dyn_cast<StructType>(ShadowTy))
1015 return collapseAggregateShadow<>(ST, Shadow, IRB);
1019Value *DFSanFunction::collapseToPrimitiveShadow(
Value *Shadow,
1022 if (!isa<ArrayType>(ShadowTy) && !isa<StructType>(ShadowTy))
1026 Value *&CS = CachedCollapsedShadows[Shadow];
1031 Value *PrimitiveShadow = collapseToPrimitiveShadow(Shadow, IRB);
1033 CS = PrimitiveShadow;
1034 return PrimitiveShadow;
1037void DFSanFunction::addConditionalCallbacksIfEnabled(
Instruction &
I,
1043 Value *CondShadow = getShadow(Condition);
1045 if (DFS.shouldTrackOrigins()) {
1046 Value *CondOrigin = getOrigin(Condition);
1047 CI = IRB.
CreateCall(DFS.DFSanConditionalCallbackOriginFn,
1048 {CondShadow, CondOrigin});
1050 CI = IRB.
CreateCall(DFS.DFSanConditionalCallbackFn, {CondShadow});
1055void DFSanFunction::addReachesFunctionCallbacksIfEnabled(
IRBuilder<> &IRB,
1061 const DebugLoc &dbgloc =
I.getDebugLoc();
1062 Value *DataShadow = collapseToPrimitiveShadow(getShadow(
Data), IRB);
1066 if (dbgloc.
get() ==
nullptr) {
1069 I.getFunction()->getParent()->getSourceFileName());
1081 std::vector<Value *>
args;
1083 if (DFS.shouldTrackOrigins()) {
1085 args = { DataShadow, DataOrigin, FilePathPtr, CILine, FunctionNamePtr };
1086 CB = IRB.
CreateCall(DFS.DFSanReachesFunctionCallbackOriginFn,
args);
1088 args = { DataShadow, FilePathPtr, CILine, FunctionNamePtr };
1095Type *DataFlowSanitizer::getShadowTy(
Type *OrigTy) {
1097 return PrimitiveShadowTy;
1098 if (isa<IntegerType>(OrigTy))
1099 return PrimitiveShadowTy;
1100 if (isa<VectorType>(OrigTy))
1101 return PrimitiveShadowTy;
1102 if (
ArrayType *AT = dyn_cast<ArrayType>(OrigTy))
1103 return ArrayType::get(getShadowTy(AT->getElementType()),
1104 AT->getNumElements());
1105 if (
StructType *ST = dyn_cast<StructType>(OrigTy)) {
1107 for (
unsigned I = 0,
N =
ST->getNumElements();
I <
N; ++
I)
1108 Elements.push_back(getShadowTy(
ST->getElementType(
I)));
1111 return PrimitiveShadowTy;
1114Type *DataFlowSanitizer::getShadowTy(
Value *V) {
1115 return getShadowTy(
V->getType());
1118bool DataFlowSanitizer::initializeModule(
Module &M) {
1119 Triple TargetTriple(
M.getTargetTriple());
1124 switch (TargetTriple.getArch()) {
1136 Ctx = &
M.getContext();
1139 OriginPtrTy = PointerType::getUnqual(OriginTy);
1141 PrimitiveShadowPtrTy = PointerType::getUnqual(PrimitiveShadowTy);
1142 IntptrTy =
DL.getIntPtrType(*Ctx);
1146 Type *DFSanUnionLoadArgs[2] = {PrimitiveShadowPtrTy, IntptrTy};
1147 DFSanUnionLoadFnTy = FunctionType::get(PrimitiveShadowTy, DFSanUnionLoadArgs,
1149 Type *DFSanLoadLabelAndOriginArgs[2] = {Int8Ptr, IntptrTy};
1150 DFSanLoadLabelAndOriginFnTy =
1153 DFSanUnimplementedFnTy = FunctionType::get(
1155 Type *DFSanWrapperExternWeakNullArgs[2] = {Int8Ptr, Int8Ptr};
1156 DFSanWrapperExternWeakNullFnTy =
1157 FunctionType::get(
Type::getVoidTy(*Ctx), DFSanWrapperExternWeakNullArgs,
1159 Type *DFSanSetLabelArgs[4] = {PrimitiveShadowTy, OriginTy,
1162 DFSanSetLabelArgs,
false);
1163 DFSanNonzeroLabelFnTy = FunctionType::get(
Type::getVoidTy(*Ctx), std::nullopt,
1165 DFSanVarargWrapperFnTy = FunctionType::get(
1167 DFSanConditionalCallbackFnTy =
1170 Type *DFSanConditionalCallbackOriginArgs[2] = {PrimitiveShadowTy, OriginTy};
1171 DFSanConditionalCallbackOriginFnTy = FunctionType::get(
1174 Type *DFSanReachesFunctionCallbackArgs[4] = {PrimitiveShadowTy, Int8Ptr,
1176 DFSanReachesFunctionCallbackFnTy =
1177 FunctionType::get(
Type::getVoidTy(*Ctx), DFSanReachesFunctionCallbackArgs,
1179 Type *DFSanReachesFunctionCallbackOriginArgs[5] = {
1180 PrimitiveShadowTy, OriginTy, Int8Ptr, OriginTy, Int8Ptr};
1181 DFSanReachesFunctionCallbackOriginFnTy = FunctionType::get(
1184 DFSanCmpCallbackFnTy =
1187 DFSanChainOriginFnTy =
1188 FunctionType::get(OriginTy, OriginTy,
false);
1189 Type *DFSanChainOriginIfTaintedArgs[2] = {PrimitiveShadowTy, OriginTy};
1190 DFSanChainOriginIfTaintedFnTy = FunctionType::get(
1191 OriginTy, DFSanChainOriginIfTaintedArgs,
false);
1193 Int8Ptr, IntptrTy, OriginTy};
1194 DFSanMaybeStoreOriginFnTy = FunctionType::get(
1196 Type *DFSanMemOriginTransferArgs[3] = {Int8Ptr, Int8Ptr, IntptrTy};
1197 DFSanMemOriginTransferFnTy = FunctionType::get(
1199 Type *DFSanMemShadowOriginTransferArgs[3] = {Int8Ptr, Int8Ptr, IntptrTy};
1200 DFSanMemShadowOriginTransferFnTy =
1201 FunctionType::get(
Type::getVoidTy(*Ctx), DFSanMemShadowOriginTransferArgs,
1203 Type *DFSanMemShadowOriginConditionalExchangeArgs[5] = {
1205 DFSanMemShadowOriginConditionalExchangeFnTy = FunctionType::get(
1208 Type *DFSanLoadStoreCallbackArgs[2] = {PrimitiveShadowTy, Int8Ptr};
1209 DFSanLoadStoreCallbackFnTy =
1212 Type *DFSanMemTransferCallbackArgs[2] = {PrimitiveShadowPtrTy, IntptrTy};
1213 DFSanMemTransferCallbackFnTy =
1214 FunctionType::get(
Type::getVoidTy(*Ctx), DFSanMemTransferCallbackArgs,
1222bool DataFlowSanitizer::isInstrumented(
const Function *
F) {
1223 return !ABIList.isIn(*
F,
"uninstrumented");
1226bool DataFlowSanitizer::isInstrumented(
const GlobalAlias *GA) {
1227 return !ABIList.isIn(*GA,
"uninstrumented");
1230bool DataFlowSanitizer::isForceZeroLabels(
const Function *
F) {
1231 return ABIList.isIn(*
F,
"force_zero_labels");
1234DataFlowSanitizer::WrapperKind DataFlowSanitizer::getWrapperKind(
Function *
F) {
1235 if (ABIList.isIn(*
F,
"functional"))
1236 return WK_Functional;
1237 if (ABIList.isIn(*
F,
"discard"))
1239 if (ABIList.isIn(*
F,
"custom"))
1245void DataFlowSanitizer::addGlobalNameSuffix(
GlobalValue *GV) {
1246 std::string GVName = std::string(GV->
getName()), Suffix =
".dfsan";
1255 std::string SearchStr =
".symver " + GVName +
",";
1256 size_t Pos =
Asm.find(SearchStr);
1257 if (Pos != std::string::npos) {
1258 Asm.replace(Pos, SearchStr.size(),
".symver " + GVName + Suffix +
",");
1259 Pos =
Asm.find(
"@");
1261 if (Pos == std::string::npos)
1264 Asm.replace(Pos, 1, Suffix +
"@");
1269void DataFlowSanitizer::buildExternWeakCheckIfNeeded(
IRBuilder<> &IRB,
1279 std::vector<Value *>
Args;
1282 IRB.
CreateCall(DFSanWrapperExternWeakNullFn, Args);
1292 NewFName,
F->getParent());
1298 if (
F->isVarArg()) {
1301 IRBuilder<>(BB).CreateGlobalStringPtr(
F->getName()),
"",
1306 std::vector<Value *>
Args(ArgIt, ArgIt + FT->getNumParams());
1309 if (FT->getReturnType()->isVoidTy())
1319void DataFlowSanitizer::initializeRuntimeFunctions(
Module &M) {
1323 AL =
AL.addFnAttribute(
C, Attribute::NoUnwind);
1324 AL =
AL.addFnAttribute(
1326 AL =
AL.addRetAttribute(
C, Attribute::ZExt);
1332 AL =
AL.addFnAttribute(
C, Attribute::NoUnwind);
1333 AL =
AL.addFnAttribute(
1335 AL =
AL.addRetAttribute(
C, Attribute::ZExt);
1337 "__dfsan_load_label_and_origin", DFSanLoadLabelAndOriginFnTy, AL);
1339 DFSanUnimplementedFn =
1342 "__dfsan_wrapper_extern_weak_null", DFSanWrapperExternWeakNullFnTy);
1345 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1346 AL =
AL.addParamAttribute(
M.getContext(), 1, Attribute::ZExt);
1350 DFSanNonzeroLabelFn =
1353 DFSanVarargWrapperFnTy);
1356 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1357 AL =
AL.addRetAttribute(
M.getContext(), Attribute::ZExt);
1359 DFSanChainOriginFnTy, AL);
1363 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1364 AL =
AL.addParamAttribute(
M.getContext(), 1, Attribute::ZExt);
1365 AL =
AL.addRetAttribute(
M.getContext(), Attribute::ZExt);
1367 "__dfsan_chain_origin_if_tainted", DFSanChainOriginIfTaintedFnTy, AL);
1370 "__dfsan_mem_origin_transfer", DFSanMemOriginTransferFnTy);
1373 "__dfsan_mem_shadow_origin_transfer", DFSanMemShadowOriginTransferFnTy);
1375 DFSanMemShadowOriginConditionalExchangeFn =
1377 DFSanMemShadowOriginConditionalExchangeFnTy);
1381 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1382 AL =
AL.addParamAttribute(
M.getContext(), 3, Attribute::ZExt);
1384 "__dfsan_maybe_store_origin", DFSanMaybeStoreOriginFnTy, AL);
1387 DFSanRuntimeFunctions.
insert(
1389 DFSanRuntimeFunctions.
insert(
1391 DFSanRuntimeFunctions.
insert(
1393 DFSanRuntimeFunctions.
insert(
1395 DFSanRuntimeFunctions.
insert(
1397 DFSanRuntimeFunctions.
insert(
1399 DFSanRuntimeFunctions.
insert(
1401 DFSanRuntimeFunctions.
insert(
1403 DFSanRuntimeFunctions.
insert(
1405 DFSanRuntimeFunctions.
insert(
1407 DFSanRuntimeFunctions.
insert(
1409 DFSanRuntimeFunctions.
insert(
1411 DFSanRuntimeFunctions.
insert(
1413 DFSanRuntimeFunctions.
insert(
1415 DFSanRuntimeFunctions.
insert(
1417 DFSanRuntimeFunctions.
insert(
1419 DFSanRuntimeFunctions.
insert(
1421 DFSanRuntimeFunctions.
insert(
1423 DFSanRuntimeFunctions.
insert(
1425 DFSanRuntimeFunctions.
insert(
1426 DFSanMemShadowOriginConditionalExchangeFn.
getCallee()
1428 DFSanRuntimeFunctions.
insert(
1433void DataFlowSanitizer::initializeCallbackFunctions(
Module &M) {
1436 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1438 "__dfsan_load_callback", DFSanLoadStoreCallbackFnTy, AL);
1442 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1444 "__dfsan_store_callback", DFSanLoadStoreCallbackFnTy, AL);
1447 "__dfsan_mem_transfer_callback", DFSanMemTransferCallbackFnTy);
1450 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1452 DFSanCmpCallbackFnTy, AL);
1456 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1458 "__dfsan_conditional_callback", DFSanConditionalCallbackFnTy, AL);
1462 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1463 DFSanConditionalCallbackOriginFn =
1465 DFSanConditionalCallbackOriginFnTy, AL);
1469 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1470 DFSanReachesFunctionCallbackFn =
1472 DFSanReachesFunctionCallbackFnTy, AL);
1476 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1477 DFSanReachesFunctionCallbackOriginFn =
1479 DFSanReachesFunctionCallbackOriginFnTy, AL);
1483bool DataFlowSanitizer::runImpl(
1485 initializeModule(M);
1487 if (ABIList.isIn(M,
"skip"))
1490 const unsigned InitialGlobalSize =
M.global_size();
1491 const unsigned InitialModuleSize =
M.size();
1493 bool Changed =
false;
1499 Changed |=
G->getThreadLocalMode() != GlobalVariable::InitialExecTLSModel;
1500 G->setThreadLocalMode(GlobalVariable::InitialExecTLSModel);
1507 GetOrInsertGlobal(
"__dfsan_arg_tls",
1509 RetvalTLS = GetOrInsertGlobal(
1510 "__dfsan_retval_tls",
1512 ArgOriginTLSTy = ArrayType::get(OriginTy, NumOfElementsInArgOrgTLS);
1513 ArgOriginTLS = GetOrInsertGlobal(
"__dfsan_arg_origin_tls", ArgOriginTLSTy);
1514 RetvalOriginTLS = GetOrInsertGlobal(
"__dfsan_retval_origin_tls", OriginTy);
1522 "__dfsan_track_origins");
1525 initializeCallbackFunctions(M);
1526 initializeRuntimeFunctions(M);
1528 std::vector<Function *> FnsToInstrument;
1533 if (!
F.isIntrinsic() && !DFSanRuntimeFunctions.
contains(&
F) &&
1534 !LibAtomicFunction(
F)) {
1535 FnsToInstrument.push_back(&
F);
1536 if (
F.hasPersonalityFn())
1537 PersonalityFns.
insert(
F.getPersonalityFn()->stripPointerCasts());
1541 for (
auto *
C : PersonalityFns) {
1542 assert(isa<Function>(
C) &&
"Personality routine is not a function!");
1544 if (!isInstrumented(
F))
1558 bool GAInst = isInstrumented(&GA), FInst = isInstrumented(
F);
1559 if (GAInst && FInst) {
1560 addGlobalNameSuffix(&GA);
1561 }
else if (GAInst != FInst) {
1566 buildWrapperFunction(
F,
"", GA.
getLinkage(),
F->getFunctionType());
1570 FnsToInstrument.push_back(NewF);
1579 for (std::vector<Function *>::iterator FI = FnsToInstrument.begin(),
1580 FE = FnsToInstrument.end();
1585 bool IsZeroArgsVoidRet = (FT->getNumParams() == 0 && !FT->isVarArg() &&
1586 FT->getReturnType()->isVoidTy());
1588 if (isInstrumented(&
F)) {
1589 if (isForceZeroLabels(&
F))
1590 FnsWithForceZeroLabel.
insert(&
F);
1595 addGlobalNameSuffix(&
F);
1596 }
else if (!IsZeroArgsVoidRet || getWrapperKind(&
F) == WK_Custom) {
1604 F.hasLocalLinkage() ?
F.getLinkage()
1607 Function *NewF = buildWrapperFunction(
1609 (shouldTrackOrigins() ? std::string(
"dfso$") : std::string(
"dfsw$")) +
1610 std::string(
F.getName()),
1611 WrapperLinkage, FT);
1614 Value *WrappedFnCst =
1634 auto IsNotCmpUse = [](
Use &
U) ->
bool {
1635 User *Usr =
U.getUser();
1638 if (
CE->getOpcode() == Instruction::ICmp) {
1643 if (
I->getOpcode() == Instruction::ICmp) {
1649 F.replaceUsesWithIf(WrappedFnCst, IsNotCmpUse);
1651 UnwrappedFnMap[WrappedFnCst] = &
F;
1654 if (!
F.isDeclaration()) {
1664 size_t N = FI - FnsToInstrument.begin(),
1665 Count = FE - FnsToInstrument.begin();
1666 FnsToInstrument.push_back(&
F);
1667 FI = FnsToInstrument.begin() +
N;
1668 FE = FnsToInstrument.begin() + Count;
1672 }
else if (FT->isVarArg()) {
1673 UnwrappedFnMap[&
F] = &
F;
1679 if (!
F ||
F->isDeclaration())
1684 DFSanFunction DFSF(*
this,
F, FnsWithNativeABI.
count(
F),
1685 FnsWithForceZeroLabel.
count(
F), GetTLI(*
F));
1689 for (
auto &FArg :
F->args()) {
1691 Value *FArgShadow = DFSF.getShadow(&FArg);
1692 if (isZeroShadow(FArgShadow))
1694 if (
Instruction *FArgShadowInst = dyn_cast<Instruction>(FArgShadow)) {
1697 if (shouldTrackOrigins()) {
1699 dyn_cast<Instruction>(DFSF.getOrigin(&FArg))) {
1708 DFSF.addReachesFunctionCallbacksIfEnabled(IRB, *Next, &FArg);
1726 if (!DFSF.SkipInsts.count(Inst))
1727 DFSanVisitor(DFSF).visit(Inst);
1738 for (DFSanFunction::PHIFixupElement &
P : DFSF.PHIFixups) {
1739 for (
unsigned Val = 0,
N =
P.Phi->getNumIncomingValues(); Val !=
N;
1741 P.ShadowPhi->setIncomingValue(
1742 Val, DFSF.getShadow(
P.Phi->getIncomingValue(Val)));
1744 P.OriginPhi->setIncomingValue(
1745 Val, DFSF.getOrigin(
P.Phi->getIncomingValue(Val)));
1754 for (
Value *V : DFSF.NonZeroChecks) {
1757 Pos =
I->getNextNode();
1759 Pos = &DFSF.F->getEntryBlock().front();
1760 while (isa<PHINode>(Pos) || isa<AllocaInst>(Pos))
1763 Value *PrimitiveShadow = DFSF.collapseToPrimitiveShadow(V, Pos);
1765 IRB.
CreateICmpNE(PrimitiveShadow, DFSF.DFS.ZeroPrimitiveShadow);
1767 Ne, Pos,
false, ColdCallWeights));
1769 ThenIRB.CreateCall(DFSF.DFS.DFSanNonzeroLabelFn, {});
1774 return Changed || !FnsToInstrument.empty() ||
1775 M.global_size() != InitialGlobalSize ||
M.size() != InitialModuleSize;
1788 DFS.RetvalTLS, PointerType::get(DFS.getShadowTy(
T), 0),
"_dfsret");
1791Value *DFSanFunction::getRetvalOriginTLS() {
return DFS.RetvalOriginTLS; }
1799 assert(DFS.shouldTrackOrigins());
1800 if (!isa<Argument>(V) && !isa<Instruction>(V))
1801 return DFS.ZeroOrigin;
1802 Value *&Origin = ValOriginMap[
V];
1804 if (
Argument *
A = dyn_cast<Argument>(V)) {
1806 return DFS.ZeroOrigin;
1807 if (
A->getArgNo() < DFS.NumOfElementsInArgOrgTLS) {
1808 Instruction *ArgOriginTLSPos = &*
F->getEntryBlock().begin();
1810 Value *ArgOriginPtr = getArgOriginTLS(
A->getArgNo(), IRB);
1811 Origin = IRB.
CreateLoad(DFS.OriginTy, ArgOriginPtr);
1814 Origin = DFS.ZeroOrigin;
1817 Origin = DFS.ZeroOrigin;
1824 if (!DFS.shouldTrackOrigins())
1828 ValOriginMap[
I] = Origin;
1832 unsigned ArgOffset = 0;
1834 for (
auto &FArg :
F->args()) {
1835 if (!FArg.getType()->isSized()) {
1841 unsigned Size =
DL.getTypeAllocSize(DFS.getShadowTy(&FArg));
1854 Value *ArgShadowPtr = getArgTLS(FArg.getType(), ArgOffset, IRB);
1859 return DFS.getZeroShadow(
A);
1863 if (!isa<Argument>(V) && !isa<Instruction>(V))
1864 return DFS.getZeroShadow(V);
1865 if (IsForceZeroLabels)
1866 return DFS.getZeroShadow(V);
1867 Value *&Shadow = ValShadowMap[
V];
1869 if (
Argument *
A = dyn_cast<Argument>(V)) {
1871 return DFS.getZeroShadow(V);
1872 Shadow = getShadowForTLSArgument(
A);
1873 NonZeroChecks.push_back(Shadow);
1875 Shadow = DFS.getZeroShadow(V);
1883 ValShadowMap[
I] = Shadow;
1891 assert(
Addr != RetvalTLS &&
"Reinstrumenting?");
1894 uint64_t AndMask = MapParams->AndMask;
1899 uint64_t XorMask = MapParams->XorMask;
1905std::pair<Value *, Value *>
1906DataFlowSanitizer::getShadowOriginAddress(
Value *
Addr,
Align InstAlignment,
1910 Value *ShadowOffset = getShadowOffset(
Addr, IRB);
1911 Value *ShadowLong = ShadowOffset;
1912 uint64_t ShadowBase = MapParams->ShadowBase;
1913 if (ShadowBase != 0) {
1920 Value *OriginPtr =
nullptr;
1921 if (shouldTrackOrigins()) {
1922 Value *OriginLong = ShadowOffset;
1923 uint64_t OriginBase = MapParams->OriginBase;
1924 if (OriginBase != 0)
1936 return std::make_pair(ShadowPtr, OriginPtr);
1940 Value *ShadowOffset) {
1947 Value *ShadowOffset = getShadowOffset(
Addr, IRB);
1948 return getShadowAddress(
Addr, Pos, ShadowOffset);
1953 Value *PrimitiveValue = combineShadows(V1, V2, Pos);
1954 return expandFromPrimitiveShadow(
T, PrimitiveValue, Pos);
1960 if (DFS.isZeroShadow(V1))
1961 return collapseToPrimitiveShadow(V2, Pos);
1962 if (DFS.isZeroShadow(V2))
1963 return collapseToPrimitiveShadow(V1, Pos);
1965 return collapseToPrimitiveShadow(V1, Pos);
1967 auto V1Elems = ShadowElements.
find(V1);
1968 auto V2Elems = ShadowElements.
find(V2);
1969 if (V1Elems != ShadowElements.
end() && V2Elems != ShadowElements.
end()) {
1970 if (std::includes(V1Elems->second.begin(), V1Elems->second.end(),
1971 V2Elems->second.begin(), V2Elems->second.end())) {
1972 return collapseToPrimitiveShadow(V1, Pos);
1974 if (std::includes(V2Elems->second.begin(), V2Elems->second.end(),
1975 V1Elems->second.begin(), V1Elems->second.end())) {
1976 return collapseToPrimitiveShadow(V2, Pos);
1978 }
else if (V1Elems != ShadowElements.
end()) {
1979 if (V1Elems->second.count(V2))
1980 return collapseToPrimitiveShadow(V1, Pos);
1981 }
else if (V2Elems != ShadowElements.
end()) {
1982 if (V2Elems->second.count(V1))
1983 return collapseToPrimitiveShadow(V2, Pos);
1986 auto Key = std::make_pair(V1, V2);
1989 CachedShadow &CCS = CachedShadows[
Key];
1994 Value *PV1 = collapseToPrimitiveShadow(V1, Pos);
1995 Value *PV2 = collapseToPrimitiveShadow(V2, Pos);
1999 CCS.Shadow = IRB.
CreateOr(PV1, PV2);
2001 std::set<Value *> UnionElems;
2002 if (V1Elems != ShadowElements.
end()) {
2003 UnionElems = V1Elems->second;
2005 UnionElems.insert(V1);
2007 if (V2Elems != ShadowElements.
end()) {
2008 UnionElems.insert(V2Elems->second.begin(), V2Elems->second.end());
2010 UnionElems.insert(V2);
2012 ShadowElements[CCS.Shadow] = std::move(UnionElems);
2022 return DFS.getZeroShadow(Inst);
2026 Shadow = combineShadows(Shadow, getShadow(Inst->
getOperand(
I)), Inst);
2028 return expandFromPrimitiveShadow(Inst->
getType(), Shadow, Inst);
2032 Value *CombinedShadow = DFSF.combineOperandShadows(&
I);
2033 DFSF.setShadow(&
I, CombinedShadow);
2034 visitInstOperandOrigins(
I);
2037Value *DFSanFunction::combineOrigins(
const std::vector<Value *> &Shadows,
2038 const std::vector<Value *> &Origins,
2040 assert(Shadows.size() == Origins.size());
2041 size_t Size = Origins.size();
2043 return DFS.ZeroOrigin;
2044 Value *Origin =
nullptr;
2046 Zero = DFS.ZeroPrimitiveShadow;
2047 for (
size_t I = 0;
I !=
Size; ++
I) {
2048 Value *OpOrigin = Origins[
I];
2049 Constant *ConstOpOrigin = dyn_cast<Constant>(OpOrigin);
2050 if (ConstOpOrigin && ConstOpOrigin->
isNullValue())
2056 Value *OpShadow = Shadows[
I];
2057 Value *PrimitiveShadow = collapseToPrimitiveShadow(OpShadow, Pos);
2062 return Origin ? Origin : DFS.ZeroOrigin;
2067 std::vector<Value *> Shadows(
Size);
2068 std::vector<Value *> Origins(
Size);
2069 for (
unsigned I = 0;
I !=
Size; ++
I) {
2073 return combineOrigins(Shadows, Origins, Inst);
2076void DFSanVisitor::visitInstOperandOrigins(
Instruction &
I) {
2077 if (!DFSF.DFS.shouldTrackOrigins())
2079 Value *CombinedOrigin = DFSF.combineOperandOrigins(&
I);
2080 DFSF.setOrigin(&
I, CombinedOrigin);
2083Align DFSanFunction::getShadowAlign(
Align InstAlignment) {
2085 return Align(Alignment.
value() * DFS.ShadowWidthBytes);
2088Align DFSanFunction::getOriginAlign(
Align InstAlignment) {
2093bool DFSanFunction::isLookupTableConstant(
Value *
P) {
2094 if (
GlobalVariable *GV = dyn_cast<GlobalVariable>(
P->stripPointerCasts()))
2095 if (GV->isConstant() && GV->
hasName())
2096 return DFS.CombineTaintLookupTableNames.count(GV->
getName());
2101bool DFSanFunction::useCallbackLoadLabelAndOrigin(
uint64_t Size,
2102 Align InstAlignment) {
2125 Value **OriginAddr) {
2132std::pair<Value *, Value *> DFSanFunction::loadShadowFast(
2135 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins();
2136 const uint64_t ShadowSize =
Size * DFS.ShadowWidthBytes;
2138 assert(
Size >= 4 &&
"Not large enough load size for fast path!");
2141 std::vector<Value *> Shadows;
2142 std::vector<Value *> Origins;
2155 Type *WideShadowTy =
2160 Value *CombinedWideShadow =
2164 const uint64_t BytesPerWideShadow = WideShadowBitWidth / DFS.ShadowWidthBits;
2166 auto AppendWideShadowAndOrigin = [&](
Value *WideShadow,
Value *Origin) {
2167 if (BytesPerWideShadow > 4) {
2168 assert(BytesPerWideShadow == 8);
2177 Shadows.push_back(WideShadow);
2178 Origins.push_back(DFS.loadNextOrigin(Pos, OriginAlign, &OriginAddr));
2180 Shadows.push_back(WideShadowLo);
2181 Origins.push_back(Origin);
2183 Shadows.push_back(WideShadow);
2184 Origins.push_back(Origin);
2188 if (ShouldTrackOrigins)
2189 AppendWideShadowAndOrigin(CombinedWideShadow, FirstOrigin);
2196 for (
uint64_t ByteOfs = BytesPerWideShadow; ByteOfs <
Size;
2197 ByteOfs += BytesPerWideShadow) {
2198 WideAddr = IRB.
CreateGEP(WideShadowTy, WideAddr,
2200 Value *NextWideShadow =
2202 CombinedWideShadow = IRB.
CreateOr(CombinedWideShadow, NextWideShadow);
2203 if (ShouldTrackOrigins) {
2204 Value *NextOrigin = DFS.loadNextOrigin(Pos, OriginAlign, &OriginAddr);
2205 AppendWideShadowAndOrigin(NextWideShadow, NextOrigin);
2208 for (
unsigned Width = WideShadowBitWidth / 2;
Width >= DFS.ShadowWidthBits;
2211 CombinedWideShadow = IRB.
CreateOr(CombinedWideShadow, ShrShadow);
2213 return {IRB.
CreateTrunc(CombinedWideShadow, DFS.PrimitiveShadowTy),
2215 ? combineOrigins(Shadows, Origins, Pos,
2220std::pair<Value *, Value *> DFSanFunction::loadShadowOriginSansLoadTracking(
2222 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins();
2226 const auto SI = AllocaShadowMap.
find(AI);
2227 if (SI != AllocaShadowMap.
end()) {
2230 const auto OI = AllocaOriginMap.
find(AI);
2231 assert(!ShouldTrackOrigins || OI != AllocaOriginMap.
end());
2232 return {ShadowLI, ShouldTrackOrigins
2241 bool AllConstants =
true;
2242 for (
const Value *Obj : Objs) {
2243 if (isa<Function>(Obj) || isa<BlockAddress>(Obj))
2245 if (isa<GlobalVariable>(Obj) && cast<GlobalVariable>(Obj)->
isConstant())
2248 AllConstants =
false;
2252 return {DFS.ZeroPrimitiveShadow,
2253 ShouldTrackOrigins ? DFS.ZeroOrigin :
nullptr};
2256 return {DFS.ZeroPrimitiveShadow,
2257 ShouldTrackOrigins ? DFS.ZeroOrigin :
nullptr};
2261 if (ShouldTrackOrigins &&
2262 useCallbackLoadLabelAndOrigin(
Size, InstAlignment)) {
2265 IRB.
CreateCall(DFS.DFSanLoadLabelAndOriginFn,
2266 {IRB.CreatePointerCast(Addr, IRB.getInt8PtrTy()),
2267 ConstantInt::get(DFS.IntptrTy, Size)});
2268 Call->addRetAttr(Attribute::ZExt);
2270 DFS.PrimitiveShadowTy),
2275 Value *ShadowAddr, *OriginAddr;
2276 std::tie(ShadowAddr, OriginAddr) =
2277 DFS.getShadowOriginAddress(
Addr, InstAlignment, Pos);
2279 const Align ShadowAlign = getShadowAlign(InstAlignment);
2280 const Align OriginAlign = getOriginAlign(InstAlignment);
2281 Value *Origin =
nullptr;
2282 if (ShouldTrackOrigins) {
2293 return {LI, Origin};
2297 Value *ShadowAddr1 = IRB.
CreateGEP(DFS.PrimitiveShadowTy, ShadowAddr,
2303 return {combineShadows(Load, Load1, Pos), Origin};
2306 bool HasSizeForFastPath = DFS.hasLoadSizeForFastPath(
Size);
2308 if (HasSizeForFastPath)
2309 return loadShadowFast(ShadowAddr, OriginAddr,
Size, ShadowAlign,
2310 OriginAlign, Origin, Pos);
2314 DFS.DFSanUnionLoadFn, {ShadowAddr, ConstantInt::get(DFS.IntptrTy, Size)});
2316 return {FallbackCall, Origin};
2319std::pair<Value *, Value *> DFSanFunction::loadShadowOrigin(
Value *
Addr,
2321 Align InstAlignment,
2323 Value *PrimitiveShadow, *Origin;
2324 std::tie(PrimitiveShadow, Origin) =
2325 loadShadowOriginSansLoadTracking(
Addr,
Size, InstAlignment, Pos);
2326 if (DFS.shouldTrackOrigins()) {
2329 auto *ConstantShadow = dyn_cast<Constant>(PrimitiveShadow);
2330 if (!ConstantShadow || !ConstantShadow->isZeroValue())
2331 Origin = updateOriginIfTainted(PrimitiveShadow, Origin, IRB);
2334 return {PrimitiveShadow, Origin};
2339 case AtomicOrdering::NotAtomic:
2340 return AtomicOrdering::NotAtomic;
2341 case AtomicOrdering::Unordered:
2342 case AtomicOrdering::Monotonic:
2343 case AtomicOrdering::Acquire:
2344 return AtomicOrdering::Acquire;
2345 case AtomicOrdering::Release:
2346 case AtomicOrdering::AcquireRelease:
2347 return AtomicOrdering::AcquireRelease;
2348 case AtomicOrdering::SequentiallyConsistent:
2349 return AtomicOrdering::SequentiallyConsistent;
2355 if (!V->getType()->isPointerTy())
2363 if (
auto *
GEP = dyn_cast<GEPOperator>(V)) {
2364 V =
GEP->getPointerOperand();
2366 V = cast<Operator>(V)->getOperand(0);
2367 if (!V->getType()->isPointerTy())
2369 }
else if (isa<GlobalAlias>(V)) {
2370 V = cast<GlobalAlias>(V)->getAliasee();
2372 }
while (Visited.
insert(V).second);
2377void DFSanVisitor::visitLoadInst(
LoadInst &LI) {
2381 DFSF.setShadow(&LI, DFSF.DFS.getZeroShadow(&LI));
2382 DFSF.setOrigin(&LI, DFSF.DFS.ZeroOrigin);
2396 std::vector<Value *> Shadows;
2397 std::vector<Value *> Origins;
2398 Value *PrimitiveShadow, *Origin;
2399 std::tie(PrimitiveShadow, Origin) =
2401 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
2402 if (ShouldTrackOrigins) {
2403 Shadows.push_back(PrimitiveShadow);
2404 Origins.push_back(Origin);
2407 DFSF.isLookupTableConstant(
2410 PrimitiveShadow = DFSF.combineShadows(PrimitiveShadow, PtrShadow, Pos);
2411 if (ShouldTrackOrigins) {
2412 Shadows.push_back(PtrShadow);
2416 if (!DFSF.DFS.isZeroShadow(PrimitiveShadow))
2417 DFSF.NonZeroChecks.push_back(PrimitiveShadow);
2420 DFSF.expandFromPrimitiveShadow(LI.
getType(), PrimitiveShadow, Pos);
2421 DFSF.setShadow(&LI, Shadow);
2423 if (ShouldTrackOrigins) {
2424 DFSF.setOrigin(&LI, DFSF.combineOrigins(Shadows, Origins, Pos));
2431 IRB.
CreateCall(DFSF.DFS.DFSanLoadCallbackFn, {PrimitiveShadow, Addr8});
2436 DFSF.addReachesFunctionCallbacksIfEnabled(IRB, LI, &LI);
2439Value *DFSanFunction::updateOriginIfTainted(
Value *Shadow,
Value *Origin,
2441 assert(DFS.shouldTrackOrigins());
2442 return IRB.
CreateCall(DFS.DFSanChainOriginIfTaintedFn, {Shadow, Origin});
2446 if (!DFS.shouldTrackOrigins())
2448 return IRB.
CreateCall(DFS.DFSanChainOriginFn, V);
2452 const unsigned OriginSize = DataFlowSanitizer::OriginWidthBytes;
2454 unsigned IntptrSize =
DL.getTypeStoreSize(DFS.IntptrTy);
2455 if (IntptrSize == OriginSize)
2457 assert(IntptrSize == OriginSize * 2);
2463 Value *StoreOriginAddr,
2465 const unsigned OriginSize = DataFlowSanitizer::OriginWidthBytes;
2467 const Align IntptrAlignment =
DL.getABITypeAlign(DFS.IntptrTy);
2468 unsigned IntptrSize =
DL.getTypeStoreSize(DFS.IntptrTy);
2470 assert(IntptrSize >= OriginSize);
2473 Align CurrentAlignment = Alignment;
2474 if (Alignment >= IntptrAlignment && IntptrSize > OriginSize) {
2475 Value *IntptrOrigin = originToIntptr(IRB, Origin);
2477 StoreOriginAddr, PointerType::get(DFS.IntptrTy, 0));
2478 for (
unsigned I = 0;
I < StoreOriginSize / IntptrSize; ++
I) {
2481 : IntptrStoreOriginPtr;
2483 Ofs += IntptrSize / OriginSize;
2484 CurrentAlignment = IntptrAlignment;
2488 for (
unsigned I = Ofs;
I < (StoreOriginSize + OriginSize - 1) / OriginSize;
2499 Type *VTy =
V->getType();
2509 Value *StoreOriginAddr,
Align InstAlignment) {
2512 const Align OriginAlignment = getOriginAlign(InstAlignment);
2513 Value *CollapsedShadow = collapseToPrimitiveShadow(Shadow, Pos);
2515 if (
auto *ConstantShadow = dyn_cast<Constant>(CollapsedShadow)) {
2516 if (!ConstantShadow->isZeroValue())
2517 paintOrigin(IRB, updateOrigin(Origin, IRB), StoreOriginAddr,
Size,
2522 if (shouldInstrumentWithCall()) {
2525 IRB.CreatePointerCast(Addr, IRB.getInt8PtrTy()),
2526 ConstantInt::get(DFS.IntptrTy, Size), Origin});
2528 Value *
Cmp = convertToBool(CollapsedShadow, IRB,
"_dfscmp");
2530 Cmp, &*IRB.
GetInsertPoint(),
false, DFS.OriginStoreWeights, &DT);
2532 paintOrigin(IRBNew, updateOrigin(Origin, IRBNew), StoreOriginAddr,
Size,
2545 Value *ShadowAddr = DFS.getShadowAddress(
Addr, Pos);
2546 Value *ExtShadowAddr =
2547 IRB.
CreateBitCast(ShadowAddr, PointerType::getUnqual(ShadowTy));
2554 Align InstAlignment,
2555 Value *PrimitiveShadow,
2558 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins() && Origin;
2561 const auto SI = AllocaShadowMap.
find(AI);
2562 if (SI != AllocaShadowMap.
end()) {
2568 if (ShouldTrackOrigins && !DFS.isZeroShadow(PrimitiveShadow)) {
2569 const auto OI = AllocaOriginMap.
find(AI);
2570 assert(OI != AllocaOriginMap.
end() && Origin);
2577 const Align ShadowAlign = getShadowAlign(InstAlignment);
2578 if (DFS.isZeroShadow(PrimitiveShadow)) {
2579 storeZeroPrimitiveShadow(
Addr,
Size, ShadowAlign, Pos);
2584 Value *ShadowAddr, *OriginAddr;
2585 std::tie(ShadowAddr, OriginAddr) =
2586 DFS.getShadowOriginAddress(
Addr, InstAlignment, Pos);
2588 const unsigned ShadowVecSize = 8;
2589 assert(ShadowVecSize * DFS.ShadowWidthBits <= 128 &&
2590 "Shadow vector is too large!");
2594 if (LeftSize >= ShadowVecSize) {
2598 for (
unsigned I = 0;
I != ShadowVecSize; ++
I) {
2600 ShadowVec, PrimitiveShadow,
2603 Value *ShadowVecAddr =
2604 IRB.
CreateBitCast(ShadowAddr, PointerType::getUnqual(ShadowVecTy));
2606 Value *CurShadowVecAddr =
2609 LeftSize -= ShadowVecSize;
2611 }
while (LeftSize >= ShadowVecSize);
2614 while (LeftSize > 0) {
2615 Value *CurShadowAddr =
2622 if (ShouldTrackOrigins) {
2623 storeOrigin(Pos,
Addr,
Size, PrimitiveShadow, Origin, OriginAddr,
2630 case AtomicOrdering::NotAtomic:
2631 return AtomicOrdering::NotAtomic;
2632 case AtomicOrdering::Unordered:
2633 case AtomicOrdering::Monotonic:
2634 case AtomicOrdering::Release:
2635 return AtomicOrdering::Release;
2636 case AtomicOrdering::Acquire:
2637 case AtomicOrdering::AcquireRelease:
2638 return AtomicOrdering::AcquireRelease;
2639 case AtomicOrdering::SequentiallyConsistent:
2640 return AtomicOrdering::SequentiallyConsistent;
2645void DFSanVisitor::visitStoreInst(
StoreInst &SI) {
2646 auto &
DL =
SI.getModule()->getDataLayout();
2647 Value *Val =
SI.getValueOperand();
2660 const bool ShouldTrackOrigins =
2661 DFSF.DFS.shouldTrackOrigins() && !
SI.isAtomic();
2662 std::vector<Value *> Shadows;
2663 std::vector<Value *> Origins;
2666 SI.isAtomic() ? DFSF.DFS.getZeroShadow(Val) : DFSF.getShadow(Val);
2668 if (ShouldTrackOrigins) {
2669 Shadows.push_back(Shadow);
2670 Origins.push_back(DFSF.getOrigin(Val));
2673 Value *PrimitiveShadow;
2675 Value *PtrShadow = DFSF.getShadow(
SI.getPointerOperand());
2676 if (ShouldTrackOrigins) {
2677 Shadows.push_back(PtrShadow);
2678 Origins.push_back(DFSF.getOrigin(
SI.getPointerOperand()));
2680 PrimitiveShadow = DFSF.combineShadows(Shadow, PtrShadow, &SI);
2682 PrimitiveShadow = DFSF.collapseToPrimitiveShadow(Shadow, &SI);
2684 Value *Origin =
nullptr;
2685 if (ShouldTrackOrigins)
2686 Origin = DFSF.combineOrigins(Shadows, Origins, &SI);
2687 DFSF.storePrimitiveShadowOrigin(
SI.getPointerOperand(),
Size,
SI.getAlign(),
2688 PrimitiveShadow, Origin, &SI);
2693 IRB.
CreateCall(DFSF.DFS.DFSanStoreCallbackFn, {PrimitiveShadow, Addr8});
2699 assert(isa<AtomicRMWInst>(
I) || isa<AtomicCmpXchgInst>(
I));
2701 Value *Val =
I.getOperand(1);
2702 const auto &
DL =
I.getModule()->getDataLayout();
2711 const Align ShadowAlign = DFSF.getShadowAlign(InstAlignment);
2712 DFSF.storeZeroPrimitiveShadow(
Addr,
Size, ShadowAlign, &
I);
2713 DFSF.setShadow(&
I, DFSF.DFS.getZeroShadow(&
I));
2714 DFSF.setOrigin(&
I, DFSF.DFS.ZeroOrigin);
2718 visitCASOrRMW(
I.getAlign(),
I);
2725 visitCASOrRMW(
I.getAlign(),
I);
2732 visitInstOperands(UO);
2736 visitInstOperands(BO);
2739void DFSanVisitor::visitBitCastInst(
BitCastInst &BCI) {
2743 if (
auto *CI = dyn_cast<CallInst>(BCI.
getOperand(0)))
2746 visitInstOperands(BCI);
2749void DFSanVisitor::visitCastInst(
CastInst &CI) { visitInstOperands(CI); }
2751void DFSanVisitor::visitCmpInst(
CmpInst &CI) {
2752 visitInstOperands(CI);
2755 Value *CombinedShadow = DFSF.getShadow(&CI);
2757 IRB.
CreateCall(DFSF.DFS.DFSanCmpCallbackFn, CombinedShadow);
2774 DFSF.setShadow(&LPI, DFSF.DFS.getZeroShadow(&LPI));
2775 DFSF.setOrigin(&LPI, DFSF.DFS.ZeroOrigin);
2780 DFSF.isLookupTableConstant(
2782 visitInstOperands(GEPI);
2789 DFSF.setShadow(&GEPI, DFSF.getShadow(BasePointer));
2790 if (DFSF.DFS.shouldTrackOrigins())
2791 DFSF.setOrigin(&GEPI, DFSF.getOrigin(BasePointer));
2795 visitInstOperands(
I);
2799 visitInstOperands(
I);
2803 visitInstOperands(
I);
2808 Value *Agg =
I.getAggregateOperand();
2809 Value *AggShadow = DFSF.getShadow(Agg);
2811 DFSF.setShadow(&
I, ResShadow);
2812 visitInstOperandOrigins(
I);
2817 Value *AggShadow = DFSF.getShadow(
I.getAggregateOperand());
2818 Value *InsShadow = DFSF.getShadow(
I.getInsertedValueOperand());
2820 DFSF.setShadow(&
I, Res);
2821 visitInstOperandOrigins(
I);
2824void DFSanVisitor::visitAllocaInst(
AllocaInst &
I) {
2825 bool AllLoadsStores =
true;
2826 for (
User *U :
I.users()) {
2827 if (isa<LoadInst>(U))
2830 if (
StoreInst *SI = dyn_cast<StoreInst>(U)) {
2831 if (
SI->getPointerOperand() == &
I)
2835 AllLoadsStores =
false;
2838 if (AllLoadsStores) {
2840 DFSF.AllocaShadowMap[&
I] = IRB.
CreateAlloca(DFSF.DFS.PrimitiveShadowTy);
2841 if (DFSF.DFS.shouldTrackOrigins()) {
2842 DFSF.AllocaOriginMap[&
I] =
2846 DFSF.setShadow(&
I, DFSF.DFS.ZeroPrimitiveShadow);
2847 DFSF.setOrigin(&
I, DFSF.DFS.ZeroOrigin);
2850void DFSanVisitor::visitSelectInst(
SelectInst &
I) {
2851 Value *CondShadow = DFSF.getShadow(
I.getCondition());
2852 Value *TrueShadow = DFSF.getShadow(
I.getTrueValue());
2853 Value *FalseShadow = DFSF.getShadow(
I.getFalseValue());
2854 Value *ShadowSel =
nullptr;
2855 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
2856 std::vector<Value *> Shadows;
2857 std::vector<Value *> Origins;
2859 ShouldTrackOrigins ? DFSF.getOrigin(
I.getTrueValue()) :
nullptr;
2860 Value *FalseOrigin =
2861 ShouldTrackOrigins ? DFSF.getOrigin(
I.getFalseValue()) :
nullptr;
2863 DFSF.addConditionalCallbacksIfEnabled(
I,
I.getCondition());
2865 if (isa<VectorType>(
I.getCondition()->getType())) {
2866 ShadowSel = DFSF.combineShadowsThenConvert(
I.getType(), TrueShadow,
2868 if (ShouldTrackOrigins) {
2869 Shadows.push_back(TrueShadow);
2870 Shadows.push_back(FalseShadow);
2871 Origins.push_back(TrueOrigin);
2872 Origins.push_back(FalseOrigin);
2875 if (TrueShadow == FalseShadow) {
2876 ShadowSel = TrueShadow;
2877 if (ShouldTrackOrigins) {
2878 Shadows.push_back(TrueShadow);
2879 Origins.push_back(TrueOrigin);
2884 if (ShouldTrackOrigins) {
2885 Shadows.push_back(ShadowSel);
2887 FalseOrigin,
"", &
I));
2892 ? DFSF.combineShadowsThenConvert(
2893 I.getType(), CondShadow, ShadowSel, &
I)
2895 if (ShouldTrackOrigins) {
2897 Shadows.push_back(CondShadow);
2898 Origins.push_back(DFSF.getOrigin(
I.getCondition()));
2900 DFSF.setOrigin(&
I, DFSF.combineOrigins(Shadows, Origins, &
I));
2904void DFSanVisitor::visitMemSetInst(
MemSetInst &
I) {
2906 Value *ValShadow = DFSF.getShadow(
I.getValue());
2907 Value *ValOrigin = DFSF.DFS.shouldTrackOrigins()
2908 ? DFSF.getOrigin(
I.getValue())
2909 : DFSF.DFS.ZeroOrigin;
2911 DFSF.DFS.DFSanSetLabelFn,
2912 {ValShadow, ValOrigin,
2913 IRB.CreateBitCast(I.getDest(), Type::getInt8PtrTy(*DFSF.DFS.Ctx)),
2914 IRB.CreateZExtOrTrunc(I.getLength(), DFSF.DFS.IntptrTy)});
2922 if (DFSF.DFS.shouldTrackOrigins()) {
2924 DFSF.DFS.DFSanMemOriginTransferFn,
2925 {IRB.CreatePointerCast(I.getArgOperand(0), IRB.getInt8PtrTy()),
2926 IRB.CreatePointerCast(I.getArgOperand(1), IRB.getInt8PtrTy()),
2927 IRB.CreateIntCast(I.getArgOperand(2), DFSF.DFS.IntptrTy, false)});
2930 Value *RawDestShadow = DFSF.DFS.getShadowAddress(
I.getDest(), &
I);
2931 Value *SrcShadow = DFSF.DFS.getShadowAddress(
I.getSource(), &
I);
2934 DFSF.DFS.ShadowWidthBytes));
2938 auto *MTI = cast<MemTransferInst>(
2939 IRB.
CreateCall(
I.getFunctionType(),
I.getCalledOperand(),
2940 {DestShadow, SrcShadow, LenShadow, I.getVolatileCst()}));
2941 MTI->setDestAlignment(DFSF.getShadowAlign(
I.getDestAlign().valueOrOne()));
2942 MTI->setSourceAlignment(DFSF.getShadowAlign(
I.getSourceAlign().valueOrOne()));
2944 IRB.
CreateCall(DFSF.DFS.DFSanMemTransferCallbackFn,
2946 IRB.CreateZExtOrTrunc(I.getLength(), DFSF.DFS.IntptrTy)});
2950void DFSanVisitor::visitBranchInst(
BranchInst &BR) {
2951 if (!
BR.isConditional())
2954 DFSF.addConditionalCallbacksIfEnabled(BR,
BR.getCondition());
2957void DFSanVisitor::visitSwitchInst(
SwitchInst &SW) {
2958 DFSF.addConditionalCallbacksIfEnabled(SW, SW.
getCondition());
2963 if (
auto *
I = dyn_cast<BitCastInst>(RetVal)) {
2964 RetVal =
I->getOperand(0);
2966 if (
auto *
I = dyn_cast<CallInst>(RetVal)) {
2967 return I->isMustTailCall();
2972void DFSanVisitor::visitReturnInst(
ReturnInst &RI) {
2980 Type *RT = DFSF.F->getFunctionType()->getReturnType();
2981 unsigned Size = getDataLayout().getTypeAllocSize(DFSF.DFS.getShadowTy(RT));
2987 if (DFSF.DFS.shouldTrackOrigins()) {
2995 std::vector<Value *> &Args,
3002 for (
unsigned N = FT->getNumParams();
N != 0; ++
I, --
N)
3003 Args.push_back(DFSF.collapseToPrimitiveShadow(DFSF.getShadow(*
I), &CB));
3006 if (FT->isVarArg()) {
3007 auto *LabelVATy = ArrayType::get(DFSF.DFS.PrimitiveShadowTy,
3008 CB.
arg_size() - FT->getNumParams());
3009 auto *LabelVAAlloca =
3010 new AllocaInst(LabelVATy, getDataLayout().getAllocaAddrSpace(),
3011 "labelva", &DFSF.F->getEntryBlock().front());
3013 for (
unsigned N = 0;
I != CB.
arg_end(); ++
I, ++
N) {
3015 IRB.
CreateStore(DFSF.collapseToPrimitiveShadow(DFSF.getShadow(*
I), &CB),
3023 if (!FT->getReturnType()->isVoidTy()) {
3024 if (!DFSF.LabelReturnAlloca) {
3026 DFSF.DFS.PrimitiveShadowTy, getDataLayout().getAllocaAddrSpace(),
3027 "labelreturn", &DFSF.F->getEntryBlock().front());
3029 Args.push_back(DFSF.LabelReturnAlloca);
3034 std::vector<Value *> &Args,
3041 for (
unsigned N = FT->getNumParams();
N != 0; ++
I, --
N)
3042 Args.push_back(DFSF.getOrigin(*
I));
3045 if (FT->isVarArg()) {
3047 ArrayType::get(DFSF.DFS.OriginTy, CB.
arg_size() - FT->getNumParams());
3048 auto *OriginVAAlloca =
3049 new AllocaInst(OriginVATy, getDataLayout().getAllocaAddrSpace(),
3050 "originva", &DFSF.F->getEntryBlock().front());
3052 for (
unsigned N = 0;
I != CB.
arg_end(); ++
I, ++
N) {
3061 if (!FT->getReturnType()->isVoidTy()) {
3062 if (!DFSF.OriginReturnAlloca) {
3064 DFSF.DFS.OriginTy, getDataLayout().getAllocaAddrSpace(),
3065 "originreturn", &DFSF.F->getEntryBlock().front());
3067 Args.push_back(DFSF.OriginReturnAlloca);
3073 switch (DFSF.DFS.getWrapperKind(&
F)) {
3074 case DataFlowSanitizer::WK_Warning:
3076 IRB.
CreateCall(DFSF.DFS.DFSanUnimplementedFn,
3078 DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &
F);
3079 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3080 DFSF.setOrigin(&CB, DFSF.DFS.ZeroOrigin);
3082 case DataFlowSanitizer::WK_Discard:
3084 DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &
F);
3085 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3086 DFSF.setOrigin(&CB, DFSF.DFS.ZeroOrigin);
3088 case DataFlowSanitizer::WK_Functional:
3090 DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &
F);
3091 visitInstOperands(CB);
3093 case DataFlowSanitizer::WK_Custom:
3097 CallInst *CI = dyn_cast<CallInst>(&CB);
3101 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
3103 TransformedFunction CustomFn = DFSF.DFS.getCustomFunctionType(FT);
3104 std::string CustomFName = ShouldTrackOrigins ?
"__dfso_" :
"__dfsw_";
3105 CustomFName +=
F.getName();
3107 CustomFName, CustomFn.TransformedType);
3109 CustomFn->copyAttributesFrom(&
F);
3112 if (!FT->getReturnType()->isVoidTy()) {
3113 CustomFn->removeFnAttrs(DFSF.DFS.ReadOnlyNoneAttrs);
3117 std::vector<Value *>
Args;
3121 for (
unsigned N = FT->getNumParams();
N != 0; ++
I, --
N) {
3126 const unsigned ShadowArgStart =
Args.size();
3127 addShadowArguments(
F, CB, Args, IRB);
3130 const unsigned OriginArgStart =
Args.size();
3131 if (ShouldTrackOrigins)
3132 addOriginArguments(
F, CB, Args, IRB);
3145 for (
unsigned N = 0;
N < FT->getNumParams();
N++) {
3146 const unsigned ArgNo = ShadowArgStart +
N;
3148 DFSF.DFS.PrimitiveShadowTy)
3150 if (ShouldTrackOrigins) {
3151 const unsigned OriginArgNo = OriginArgStart +
N;
3159 if (!FT->getReturnType()->isVoidTy()) {
3161 IRB.
CreateLoad(DFSF.DFS.PrimitiveShadowTy, DFSF.LabelReturnAlloca);
3162 DFSF.setShadow(CustomCI, DFSF.expandFromPrimitiveShadow(
3163 FT->getReturnType(), LabelLoad, &CB));
3164 if (ShouldTrackOrigins) {
3166 IRB.
CreateLoad(DFSF.DFS.OriginTy, DFSF.OriginReturnAlloca);
3167 DFSF.setOrigin(CustomCI, OriginLoad);
3179 constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
3180 uint32_t OrderingTable[NumOrderings] = {};
3182 OrderingTable[(int)AtomicOrderingCABI::relaxed] =
3183 OrderingTable[(
int)AtomicOrderingCABI::acquire] =
3184 OrderingTable[(int)AtomicOrderingCABI::consume] =
3185 (
int)AtomicOrderingCABI::acquire;
3186 OrderingTable[(int)AtomicOrderingCABI::release] =
3187 OrderingTable[(
int)AtomicOrderingCABI::acq_rel] =
3188 (int)AtomicOrderingCABI::acq_rel;
3189 OrderingTable[(int)AtomicOrderingCABI::seq_cst] =
3190 (
int)AtomicOrderingCABI::seq_cst;
3193 ArrayRef(OrderingTable, NumOrderings));
3196void DFSanVisitor::visitLibAtomicLoad(
CallBase &CB) {
3198 assert(isa<CallInst>(CB));
3207 Value *NewOrdering =
3212 NextIRB.SetCurrentDebugLocation(CB.
getDebugLoc());
3217 NextIRB.CreateCall(DFSF.DFS.DFSanMemShadowOriginTransferFn,
3218 {NextIRB.CreatePointerCast(DstPtr, NextIRB.getInt8PtrTy()),
3219 NextIRB.CreatePointerCast(SrcPtr, NextIRB.getInt8PtrTy()),
3220 NextIRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3224 constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
3225 uint32_t OrderingTable[NumOrderings] = {};
3227 OrderingTable[(int)AtomicOrderingCABI::relaxed] =
3228 OrderingTable[(
int)AtomicOrderingCABI::release] =
3229 (int)AtomicOrderingCABI::release;
3230 OrderingTable[(int)AtomicOrderingCABI::consume] =
3231 OrderingTable[(
int)AtomicOrderingCABI::acquire] =
3232 OrderingTable[(int)AtomicOrderingCABI::acq_rel] =
3233 (
int)AtomicOrderingCABI::acq_rel;
3234 OrderingTable[(int)AtomicOrderingCABI::seq_cst] =
3235 (
int)AtomicOrderingCABI::seq_cst;
3238 ArrayRef(OrderingTable, NumOrderings));
3241void DFSanVisitor::visitLibAtomicStore(
CallBase &CB) {
3249 Value *NewOrdering =
3256 IRB.
CreateCall(DFSF.DFS.DFSanMemShadowOriginTransferFn,
3257 {IRB.CreatePointerCast(DstPtr, IRB.getInt8PtrTy()),
3258 IRB.CreatePointerCast(SrcPtr, IRB.getInt8PtrTy()),
3259 IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3262void DFSanVisitor::visitLibAtomicExchange(
CallBase &CB) {
3277 IRB.
CreateCall(DFSF.DFS.DFSanMemShadowOriginTransferFn,
3278 {IRB.CreatePointerCast(DstPtr, IRB.getInt8PtrTy()),
3279 IRB.CreatePointerCast(TargetPtr, IRB.getInt8PtrTy()),
3280 IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3283 IRB.
CreateCall(DFSF.DFS.DFSanMemShadowOriginTransferFn,
3284 {IRB.CreatePointerCast(TargetPtr, IRB.getInt8PtrTy()),
3285 IRB.CreatePointerCast(SrcPtr, IRB.getInt8PtrTy()),
3286 IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3289void DFSanVisitor::visitLibAtomicCompareExchange(
CallBase &CB) {
3303 NextIRB.SetCurrentDebugLocation(CB.
getDebugLoc());
3305 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3310 DFSF.DFS.DFSanMemShadowOriginConditionalExchangeFn,
3311 {NextIRB.CreateIntCast(&CB, NextIRB.getInt8Ty(), false),
3312 NextIRB.CreatePointerCast(TargetPtr, NextIRB.getInt8PtrTy()),
3313 NextIRB.CreatePointerCast(ExpectedPtr, NextIRB.getInt8PtrTy()),
3314 NextIRB.CreatePointerCast(DesiredPtr, NextIRB.getInt8PtrTy()),
3315 NextIRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3318void DFSanVisitor::visitCallBase(
CallBase &CB) {
3321 visitInstOperands(CB);
3327 if (
F == DFSF.DFS.DFSanVarargWrapperFn.getCallee()->stripPointerCasts())
3331 if (DFSF.TLI.getLibFunc(CB, LF)) {
3336 case LibFunc_atomic_load:
3337 if (!isa<CallInst>(CB)) {
3338 llvm::errs() <<
"DFSAN -- cannot instrument invoke of libatomic load. "
3342 visitLibAtomicLoad(CB);
3344 case LibFunc_atomic_store:
3345 visitLibAtomicStore(CB);
3353 if (
F &&
F->hasName() && !
F->isVarArg()) {
3354 if (
F->getName() ==
"__atomic_exchange") {
3355 visitLibAtomicExchange(CB);
3358 if (
F->getName() ==
"__atomic_compare_exchange") {
3359 visitLibAtomicCompareExchange(CB);
3366 if (UnwrappedFnIt != DFSF.DFS.UnwrappedFnMap.end())
3367 if (visitWrappedCallBase(*UnwrappedFnIt->second, CB))
3372 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
3377 unsigned ArgOffset = 0;
3378 for (
unsigned I = 0,
N = FT->getNumParams();
I !=
N; ++
I) {
3379 if (ShouldTrackOrigins) {
3382 if (
I < DFSF.DFS.NumOfElementsInArgOrgTLS &&
3383 !DFSF.DFS.isZeroShadow(ArgShadow))
3385 DFSF.getArgOriginTLS(
I, IRB));
3389 DL.getTypeAllocSize(DFSF.DFS.getShadowTy(FT->getParamType(
I)));
3395 DFSF.getArgTLS(FT->getParamType(
I), ArgOffset, IRB),
3402 if (
InvokeInst *II = dyn_cast<InvokeInst>(&CB)) {
3403 if (II->getNormalDest()->getSinglePredecessor()) {
3404 Next = &II->getNormalDest()->front();
3407 SplitEdge(II->getParent(), II->getNormalDest(), &DFSF.DT);
3408 Next = &NewBB->
front();
3421 unsigned Size =
DL.getTypeAllocSize(DFSF.DFS.getShadowTy(&CB));
3424 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3426 LoadInst *LI = NextIRB.CreateAlignedLoad(
3427 DFSF.DFS.getShadowTy(&CB), DFSF.getRetvalTLS(CB.
getType(), NextIRB),
3429 DFSF.SkipInsts.insert(LI);
3430 DFSF.setShadow(&CB, LI);
3431 DFSF.NonZeroChecks.push_back(LI);
3434 if (ShouldTrackOrigins) {
3435 LoadInst *LI = NextIRB.CreateLoad(DFSF.DFS.OriginTy,
3436 DFSF.getRetvalOriginTLS(),
"_dfsret_o");
3437 DFSF.SkipInsts.insert(LI);
3438 DFSF.setOrigin(&CB, LI);
3441 DFSF.addReachesFunctionCallbacksIfEnabled(NextIRB, CB, &CB);
3445void DFSanVisitor::visitPHINode(
PHINode &PN) {
3446 Type *ShadowTy = DFSF.DFS.getShadowTy(&PN);
3455 DFSF.setShadow(&PN, ShadowPN);
3458 if (DFSF.DFS.shouldTrackOrigins()) {
3464 DFSF.setOrigin(&PN, OriginPN);
3467 DFSF.PHIFixups.push_back({&PN, ShadowPN, OriginPN});
3477 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...
SmallVector< MachineOperand, 4 > Cond
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_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.
static bool isMustTailCall(Value *V)
Module.h This file contains the declarations for the Module class.
FunctionAnalysisManager FAM
This header defines various interfaces for pass management in LLVM.
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 MemoryEffects readOnly()
Create MemoryEffects 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.
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
FunctionCallee getOrInsertFunction(StringRef Name, FunctionType *T, AttributeList AttributeList)
Look up the specified function in the module symbol table.
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
PointerType * getPointerTo(unsigned AddrSpace=0) const
Return a pointer to the current type.
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)
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)
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...
Instruction * SplitBlockAndInsertIfThen(Value *Cond, Instruction *SplitBefore, bool Unreachable, MDNode *BranchWeights, DominatorTree *DT, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
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.