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 Value *ShadowOffset);
522 std::pair<Value *, Value *> getShadowOriginAddress(
Value *
Addr,
527 bool isForceZeroLabels(
const Function *
F);
535 void initializeCallbackFunctions(
Module &M);
536 void initializeRuntimeFunctions(
Module &M);
537 bool initializeModule(
Module &M);
549 bool shouldTrackOrigins();
561 bool isZeroShadow(
Value *V);
575 DataFlowSanitizer(
const std::vector<std::string> &ABIListFiles);
581struct DFSanFunction {
582 DataFlowSanitizer &DFS;
586 bool IsForceZeroLabels;
595 struct PHIFixupElement {
600 std::vector<PHIFixupElement> PHIFixups;
603 std::vector<Value *> NonZeroChecks;
605 struct CachedShadow {
618 DFSanFunction(DataFlowSanitizer &DFS,
Function *F,
bool IsNativeABI,
620 : DFS(DFS),
F(
F), IsNativeABI(IsNativeABI),
621 IsForceZeroLabels(IsForceZeroLabels), TLI(TLI) {
639 Value *getRetvalOriginTLS();
651 Value *combineOrigins(
const std::vector<Value *> &Shadows,
652 const std::vector<Value *> &Origins,
711 bool isLookupTableConstant(
Value *
P);
716 template <
class AggregateType>
717 Value *collapseAggregateShadow(AggregateType *AT,
Value *Shadow,
726 std::pair<Value *, Value *>
767 Align InstAlignment);
772 bool shouldInstrumentWithCall();
778 std::pair<Value *, Value *>
782 int NumOriginStores = 0;
785class DFSanVisitor :
public InstVisitor<DFSanVisitor> {
789 DFSanVisitor(DFSanFunction &DFSF) : DFSF(DFSF) {}
792 return DFSF.F->getParent()->getDataLayout();
810 void visitLibAtomicLoad(
CallBase &CB);
811 void visitLibAtomicStore(
CallBase &CB);
812 void visitLibAtomicExchange(
CallBase &CB);
813 void visitLibAtomicCompareExchange(
CallBase &CB);
847bool LibAtomicFunction(
const Function &
F) {
853 if (!
F.hasName() ||
F.isVarArg())
855 switch (
F.arg_size()) {
857 return F.getName() ==
"__atomic_load" ||
F.getName() ==
"__atomic_store";
859 return F.getName() ==
"__atomic_exchange";
861 return F.getName() ==
"__atomic_compare_exchange";
869DataFlowSanitizer::DataFlowSanitizer(
870 const std::vector<std::string> &ABIListFiles) {
871 std::vector<std::string> AllABIListFiles(std::move(ABIListFiles));
878 CombineTaintLookupTableNames.
insert(v);
881TransformedFunction DataFlowSanitizer::getCustomFunctionType(
FunctionType *
T) {
888 std::vector<unsigned> ArgumentIndexMapping;
889 for (
unsigned I = 0,
E =
T->getNumParams();
I !=
E; ++
I) {
890 Type *ParamType =
T->getParamType(
I);
891 ArgumentIndexMapping.push_back(ArgTypes.
size());
894 for (
unsigned I = 0,
E =
T->getNumParams();
I !=
E; ++
I)
897 ArgTypes.
push_back(PrimitiveShadowPtrTy);
898 Type *RetType =
T->getReturnType();
900 ArgTypes.
push_back(PrimitiveShadowPtrTy);
902 if (shouldTrackOrigins()) {
903 for (
unsigned I = 0,
E =
T->getNumParams();
I !=
E; ++
I)
911 return TransformedFunction(
912 T, FunctionType::get(
T->getReturnType(), ArgTypes,
T->isVarArg()),
913 ArgumentIndexMapping);
916bool DataFlowSanitizer::isZeroShadow(
Value *V) {
918 if (!isa<ArrayType>(
T) && !isa<StructType>(
T)) {
919 if (
const ConstantInt *CI = dyn_cast<ConstantInt>(V))
924 return isa<ConstantAggregateZero>(V);
927bool DataFlowSanitizer::hasLoadSizeForFastPath(
uint64_t Size) {
929 return ShadowSize % 8 == 0 || ShadowSize == 4;
932bool DataFlowSanitizer::shouldTrackOrigins() {
934 return ShouldTrackOrigins;
937Constant *DataFlowSanitizer::getZeroShadow(
Type *OrigTy) {
938 if (!isa<ArrayType>(OrigTy) && !isa<StructType>(OrigTy))
939 return ZeroPrimitiveShadow;
940 Type *ShadowTy = getShadowTy(OrigTy);
945 return getZeroShadow(
V->getType());
951 if (!isa<ArrayType>(SubShadowTy) && !isa<StructType>(SubShadowTy))
954 if (
ArrayType *AT = dyn_cast<ArrayType>(SubShadowTy)) {
955 for (
unsigned Idx = 0;
Idx < AT->getNumElements();
Idx++) {
958 Shadow, Indices, AT->getElementType(), PrimitiveShadow, IRB);
964 if (
StructType *ST = dyn_cast<StructType>(SubShadowTy)) {
965 for (
unsigned Idx = 0;
Idx < ST->getNumElements();
Idx++) {
968 Shadow, Indices, ST->getElementType(
Idx), PrimitiveShadow, IRB);
976bool DFSanFunction::shouldInstrumentWithCall() {
981Value *DFSanFunction::expandFromPrimitiveShadow(
Type *
T,
Value *PrimitiveShadow,
983 Type *ShadowTy = DFS.getShadowTy(
T);
985 if (!isa<ArrayType>(ShadowTy) && !isa<StructType>(ShadowTy))
986 return PrimitiveShadow;
988 if (DFS.isZeroShadow(PrimitiveShadow))
989 return DFS.getZeroShadow(ShadowTy);
995 PrimitiveShadow, IRB);
998 CachedCollapsedShadows[Shadow] = PrimitiveShadow;
1002template <
class AggregateType>
1003Value *DFSanFunction::collapseAggregateShadow(AggregateType *AT,
Value *Shadow,
1005 if (!AT->getNumElements())
1006 return DFS.ZeroPrimitiveShadow;
1009 Value *Aggregator = collapseToPrimitiveShadow(FirstItem, IRB);
1011 for (
unsigned Idx = 1;
Idx < AT->getNumElements();
Idx++) {
1013 Value *ShadowInner = collapseToPrimitiveShadow(ShadowItem, IRB);
1014 Aggregator = IRB.
CreateOr(Aggregator, ShadowInner);
1019Value *DFSanFunction::collapseToPrimitiveShadow(
Value *Shadow,
1022 if (!isa<ArrayType>(ShadowTy) && !isa<StructType>(ShadowTy))
1024 if (
ArrayType *AT = dyn_cast<ArrayType>(ShadowTy))
1025 return collapseAggregateShadow<>(AT, Shadow, IRB);
1026 if (
StructType *ST = dyn_cast<StructType>(ShadowTy))
1027 return collapseAggregateShadow<>(ST, Shadow, IRB);
1031Value *DFSanFunction::collapseToPrimitiveShadow(
Value *Shadow,
1034 if (!isa<ArrayType>(ShadowTy) && !isa<StructType>(ShadowTy))
1038 Value *&CS = CachedCollapsedShadows[Shadow];
1043 Value *PrimitiveShadow = collapseToPrimitiveShadow(Shadow, IRB);
1045 CS = PrimitiveShadow;
1046 return PrimitiveShadow;
1049void DFSanFunction::addConditionalCallbacksIfEnabled(
Instruction &
I,
1055 Value *CondShadow = getShadow(Condition);
1057 if (DFS.shouldTrackOrigins()) {
1058 Value *CondOrigin = getOrigin(Condition);
1059 CI = IRB.
CreateCall(DFS.DFSanConditionalCallbackOriginFn,
1060 {CondShadow, CondOrigin});
1062 CI = IRB.
CreateCall(DFS.DFSanConditionalCallbackFn, {CondShadow});
1067void DFSanFunction::addReachesFunctionCallbacksIfEnabled(
IRBuilder<> &IRB,
1073 const DebugLoc &dbgloc =
I.getDebugLoc();
1074 Value *DataShadow = collapseToPrimitiveShadow(getShadow(Data), IRB);
1078 if (dbgloc.
get() ==
nullptr) {
1079 CILine = llvm::ConstantInt::get(
I.getContext(),
llvm::APInt(32, 0));
1081 I.getFunction()->getParent()->getSourceFileName());
1083 CILine = llvm::ConstantInt::get(
I.getContext(),
1093 std::vector<Value *>
args;
1095 if (DFS.shouldTrackOrigins()) {
1096 Value *DataOrigin = getOrigin(Data);
1097 args = { DataShadow, DataOrigin, FilePathPtr, CILine, FunctionNamePtr };
1098 CB = IRB.
CreateCall(DFS.DFSanReachesFunctionCallbackOriginFn,
args);
1100 args = { DataShadow, FilePathPtr, CILine, FunctionNamePtr };
1107Type *DataFlowSanitizer::getShadowTy(
Type *OrigTy) {
1109 return PrimitiveShadowTy;
1110 if (isa<IntegerType>(OrigTy))
1111 return PrimitiveShadowTy;
1112 if (isa<VectorType>(OrigTy))
1113 return PrimitiveShadowTy;
1114 if (
ArrayType *AT = dyn_cast<ArrayType>(OrigTy))
1115 return ArrayType::get(getShadowTy(AT->getElementType()),
1116 AT->getNumElements());
1117 if (
StructType *ST = dyn_cast<StructType>(OrigTy)) {
1119 for (
unsigned I = 0,
N =
ST->getNumElements();
I <
N; ++
I)
1120 Elements.push_back(getShadowTy(
ST->getElementType(
I)));
1123 return PrimitiveShadowTy;
1126Type *DataFlowSanitizer::getShadowTy(
Value *V) {
1127 return getShadowTy(
V->getType());
1130bool DataFlowSanitizer::initializeModule(
Module &M) {
1131 Triple TargetTriple(
M.getTargetTriple());
1136 switch (TargetTriple.getArch()) {
1151 Ctx = &
M.getContext();
1152 Int8Ptr = PointerType::getUnqual(*Ctx);
1154 OriginPtrTy = PointerType::getUnqual(OriginTy);
1156 PrimitiveShadowPtrTy = PointerType::getUnqual(PrimitiveShadowTy);
1157 IntptrTy =
DL.getIntPtrType(*Ctx);
1161 Type *DFSanUnionLoadArgs[2] = {PrimitiveShadowPtrTy, IntptrTy};
1162 DFSanUnionLoadFnTy = FunctionType::get(PrimitiveShadowTy, DFSanUnionLoadArgs,
1164 Type *DFSanLoadLabelAndOriginArgs[2] = {Int8Ptr, IntptrTy};
1165 DFSanLoadLabelAndOriginFnTy =
1168 DFSanUnimplementedFnTy = FunctionType::get(
1170 Type *DFSanWrapperExternWeakNullArgs[2] = {Int8Ptr, Int8Ptr};
1171 DFSanWrapperExternWeakNullFnTy =
1172 FunctionType::get(
Type::getVoidTy(*Ctx), DFSanWrapperExternWeakNullArgs,
1174 Type *DFSanSetLabelArgs[4] = {PrimitiveShadowTy, OriginTy,
1175 PointerType::getUnqual(*Ctx), IntptrTy};
1177 DFSanSetLabelArgs,
false);
1178 DFSanNonzeroLabelFnTy = FunctionType::get(
Type::getVoidTy(*Ctx), std::nullopt,
1180 DFSanVarargWrapperFnTy = FunctionType::get(
1182 DFSanConditionalCallbackFnTy =
1185 Type *DFSanConditionalCallbackOriginArgs[2] = {PrimitiveShadowTy, OriginTy};
1186 DFSanConditionalCallbackOriginFnTy = FunctionType::get(
1189 Type *DFSanReachesFunctionCallbackArgs[4] = {PrimitiveShadowTy, Int8Ptr,
1191 DFSanReachesFunctionCallbackFnTy =
1192 FunctionType::get(
Type::getVoidTy(*Ctx), DFSanReachesFunctionCallbackArgs,
1194 Type *DFSanReachesFunctionCallbackOriginArgs[5] = {
1195 PrimitiveShadowTy, OriginTy, Int8Ptr, OriginTy, Int8Ptr};
1196 DFSanReachesFunctionCallbackOriginFnTy = FunctionType::get(
1199 DFSanCmpCallbackFnTy =
1202 DFSanChainOriginFnTy =
1203 FunctionType::get(OriginTy, OriginTy,
false);
1204 Type *DFSanChainOriginIfTaintedArgs[2] = {PrimitiveShadowTy, OriginTy};
1205 DFSanChainOriginIfTaintedFnTy = FunctionType::get(
1206 OriginTy, DFSanChainOriginIfTaintedArgs,
false);
1208 Int8Ptr, IntptrTy, OriginTy};
1209 DFSanMaybeStoreOriginFnTy = FunctionType::get(
1211 Type *DFSanMemOriginTransferArgs[3] = {Int8Ptr, Int8Ptr, IntptrTy};
1212 DFSanMemOriginTransferFnTy = FunctionType::get(
1214 Type *DFSanMemShadowOriginTransferArgs[3] = {Int8Ptr, Int8Ptr, IntptrTy};
1215 DFSanMemShadowOriginTransferFnTy =
1216 FunctionType::get(
Type::getVoidTy(*Ctx), DFSanMemShadowOriginTransferArgs,
1218 Type *DFSanMemShadowOriginConditionalExchangeArgs[5] = {
1220 DFSanMemShadowOriginConditionalExchangeFnTy = FunctionType::get(
1223 Type *DFSanLoadStoreCallbackArgs[2] = {PrimitiveShadowTy, Int8Ptr};
1224 DFSanLoadStoreCallbackFnTy =
1227 Type *DFSanMemTransferCallbackArgs[2] = {PrimitiveShadowPtrTy, IntptrTy};
1228 DFSanMemTransferCallbackFnTy =
1229 FunctionType::get(
Type::getVoidTy(*Ctx), DFSanMemTransferCallbackArgs,
1237bool DataFlowSanitizer::isInstrumented(
const Function *
F) {
1238 return !ABIList.isIn(*
F,
"uninstrumented");
1241bool DataFlowSanitizer::isInstrumented(
const GlobalAlias *GA) {
1242 return !ABIList.isIn(*GA,
"uninstrumented");
1245bool DataFlowSanitizer::isForceZeroLabels(
const Function *
F) {
1246 return ABIList.isIn(*
F,
"force_zero_labels");
1249DataFlowSanitizer::WrapperKind DataFlowSanitizer::getWrapperKind(
Function *
F) {
1250 if (ABIList.isIn(*
F,
"functional"))
1251 return WK_Functional;
1252 if (ABIList.isIn(*
F,
"discard"))
1254 if (ABIList.isIn(*
F,
"custom"))
1260void DataFlowSanitizer::addGlobalNameSuffix(
GlobalValue *GV) {
1261 std::string GVName = std::string(GV->
getName()), Suffix =
".dfsan";
1270 std::string SearchStr =
".symver " + GVName +
",";
1271 size_t Pos =
Asm.find(SearchStr);
1272 if (Pos != std::string::npos) {
1273 Asm.replace(Pos, SearchStr.size(),
".symver " + GVName + Suffix +
",");
1274 Pos =
Asm.find(
'@');
1276 if (Pos == std::string::npos)
1279 Asm.replace(Pos, 1, Suffix +
"@");
1284void DataFlowSanitizer::buildExternWeakCheckIfNeeded(
IRBuilder<> &IRB,
1294 std::vector<Value *>
Args;
1297 IRB.
CreateCall(DFSanWrapperExternWeakNullFn, Args);
1307 NewFName,
F->getParent());
1313 if (
F->isVarArg()) {
1316 IRBuilder<>(BB).CreateGlobalStringPtr(
F->getName()),
"",
1321 std::vector<Value *>
Args(ArgIt, ArgIt + FT->getNumParams());
1324 if (FT->getReturnType()->isVoidTy())
1334void DataFlowSanitizer::initializeRuntimeFunctions(
Module &M) {
1338 AL =
AL.addFnAttribute(
C, Attribute::NoUnwind);
1339 AL =
AL.addFnAttribute(
1341 AL =
AL.addRetAttribute(
C, Attribute::ZExt);
1347 AL =
AL.addFnAttribute(
C, Attribute::NoUnwind);
1348 AL =
AL.addFnAttribute(
1350 AL =
AL.addRetAttribute(
C, Attribute::ZExt);
1352 "__dfsan_load_label_and_origin", DFSanLoadLabelAndOriginFnTy, AL);
1354 DFSanUnimplementedFn =
1357 "__dfsan_wrapper_extern_weak_null", DFSanWrapperExternWeakNullFnTy);
1360 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1361 AL =
AL.addParamAttribute(
M.getContext(), 1, Attribute::ZExt);
1365 DFSanNonzeroLabelFn =
1368 DFSanVarargWrapperFnTy);
1371 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1372 AL =
AL.addRetAttribute(
M.getContext(), Attribute::ZExt);
1374 DFSanChainOriginFnTy, AL);
1378 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1379 AL =
AL.addParamAttribute(
M.getContext(), 1, Attribute::ZExt);
1380 AL =
AL.addRetAttribute(
M.getContext(), Attribute::ZExt);
1382 "__dfsan_chain_origin_if_tainted", DFSanChainOriginIfTaintedFnTy, AL);
1385 "__dfsan_mem_origin_transfer", DFSanMemOriginTransferFnTy);
1388 "__dfsan_mem_shadow_origin_transfer", DFSanMemShadowOriginTransferFnTy);
1390 DFSanMemShadowOriginConditionalExchangeFn =
1392 DFSanMemShadowOriginConditionalExchangeFnTy);
1396 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1397 AL =
AL.addParamAttribute(
M.getContext(), 3, Attribute::ZExt);
1399 "__dfsan_maybe_store_origin", DFSanMaybeStoreOriginFnTy, AL);
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(
1438 DFSanRuntimeFunctions.
insert(
1440 DFSanRuntimeFunctions.
insert(
1441 DFSanMemShadowOriginConditionalExchangeFn.
getCallee()
1443 DFSanRuntimeFunctions.
insert(
1448void DataFlowSanitizer::initializeCallbackFunctions(
Module &M) {
1451 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1453 "__dfsan_load_callback", DFSanLoadStoreCallbackFnTy, AL);
1457 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1459 "__dfsan_store_callback", DFSanLoadStoreCallbackFnTy, AL);
1462 "__dfsan_mem_transfer_callback", DFSanMemTransferCallbackFnTy);
1465 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1467 DFSanCmpCallbackFnTy, AL);
1471 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1473 "__dfsan_conditional_callback", DFSanConditionalCallbackFnTy, AL);
1477 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1478 DFSanConditionalCallbackOriginFn =
1480 DFSanConditionalCallbackOriginFnTy, AL);
1484 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1485 DFSanReachesFunctionCallbackFn =
1487 DFSanReachesFunctionCallbackFnTy, AL);
1491 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1492 DFSanReachesFunctionCallbackOriginFn =
1494 DFSanReachesFunctionCallbackOriginFnTy, AL);
1498bool DataFlowSanitizer::runImpl(
1500 initializeModule(M);
1502 if (ABIList.isIn(M,
"skip"))
1505 const unsigned InitialGlobalSize =
M.global_size();
1506 const unsigned InitialModuleSize =
M.size();
1508 bool Changed =
false;
1514 Changed |=
G->getThreadLocalMode() != GlobalVariable::InitialExecTLSModel;
1515 G->setThreadLocalMode(GlobalVariable::InitialExecTLSModel);
1522 GetOrInsertGlobal(
"__dfsan_arg_tls",
1524 RetvalTLS = GetOrInsertGlobal(
1525 "__dfsan_retval_tls",
1527 ArgOriginTLSTy = ArrayType::get(OriginTy, NumOfElementsInArgOrgTLS);
1528 ArgOriginTLS = GetOrInsertGlobal(
"__dfsan_arg_origin_tls", ArgOriginTLSTy);
1529 RetvalOriginTLS = GetOrInsertGlobal(
"__dfsan_retval_origin_tls", OriginTy);
1537 "__dfsan_track_origins");
1540 initializeCallbackFunctions(M);
1541 initializeRuntimeFunctions(M);
1543 std::vector<Function *> FnsToInstrument;
1548 if (!
F.isIntrinsic() && !DFSanRuntimeFunctions.
contains(&
F) &&
1549 !LibAtomicFunction(
F)) {
1550 FnsToInstrument.push_back(&
F);
1551 if (
F.hasPersonalityFn())
1552 PersonalityFns.
insert(
F.getPersonalityFn()->stripPointerCasts());
1556 for (
auto *
C : PersonalityFns) {
1557 assert(isa<Function>(
C) &&
"Personality routine is not a function!");
1559 if (!isInstrumented(
F))
1573 bool GAInst = isInstrumented(&GA), FInst = isInstrumented(
F);
1574 if (GAInst && FInst) {
1575 addGlobalNameSuffix(&GA);
1576 }
else if (GAInst != FInst) {
1581 buildWrapperFunction(
F,
"", GA.
getLinkage(),
F->getFunctionType());
1585 FnsToInstrument.push_back(NewF);
1594 for (std::vector<Function *>::iterator FI = FnsToInstrument.begin(),
1595 FE = FnsToInstrument.end();
1600 bool IsZeroArgsVoidRet = (FT->getNumParams() == 0 && !FT->isVarArg() &&
1601 FT->getReturnType()->isVoidTy());
1603 if (isInstrumented(&
F)) {
1604 if (isForceZeroLabels(&
F))
1605 FnsWithForceZeroLabel.
insert(&
F);
1610 addGlobalNameSuffix(&
F);
1611 }
else if (!IsZeroArgsVoidRet || getWrapperKind(&
F) == WK_Custom) {
1619 F.hasLocalLinkage() ?
F.getLinkage()
1622 Function *NewF = buildWrapperFunction(
1624 (shouldTrackOrigins() ? std::string(
"dfso$") : std::string(
"dfsw$")) +
1625 std::string(
F.getName()),
1626 WrapperLinkage, FT);
1646 auto IsNotCmpUse = [](
Use &
U) ->
bool {
1647 User *Usr =
U.getUser();
1650 if (
CE->getOpcode() == Instruction::ICmp) {
1655 if (
I->getOpcode() == Instruction::ICmp) {
1661 F.replaceUsesWithIf(NewF, IsNotCmpUse);
1663 UnwrappedFnMap[NewF] = &
F;
1666 if (!
F.isDeclaration()) {
1676 size_t N = FI - FnsToInstrument.begin(),
1677 Count = FE - FnsToInstrument.begin();
1678 FnsToInstrument.push_back(&
F);
1679 FI = FnsToInstrument.begin() +
N;
1680 FE = FnsToInstrument.begin() + Count;
1684 }
else if (FT->isVarArg()) {
1685 UnwrappedFnMap[&
F] = &
F;
1691 if (!
F ||
F->isDeclaration())
1696 DFSanFunction DFSF(*
this,
F, FnsWithNativeABI.
count(
F),
1697 FnsWithForceZeroLabel.
count(
F), GetTLI(*
F));
1701 for (
auto &FArg :
F->args()) {
1703 Value *FArgShadow = DFSF.getShadow(&FArg);
1704 if (isZeroShadow(FArgShadow))
1706 if (
Instruction *FArgShadowInst = dyn_cast<Instruction>(FArgShadow)) {
1709 if (shouldTrackOrigins()) {
1711 dyn_cast<Instruction>(DFSF.getOrigin(&FArg))) {
1720 DFSF.addReachesFunctionCallbacksIfEnabled(IRB, *Next, &FArg);
1738 if (!DFSF.SkipInsts.count(Inst))
1739 DFSanVisitor(DFSF).visit(Inst);
1750 for (DFSanFunction::PHIFixupElement &
P : DFSF.PHIFixups) {
1751 for (
unsigned Val = 0,
N =
P.Phi->getNumIncomingValues(); Val !=
N;
1753 P.ShadowPhi->setIncomingValue(
1754 Val, DFSF.getShadow(
P.Phi->getIncomingValue(Val)));
1756 P.OriginPhi->setIncomingValue(
1757 Val, DFSF.getOrigin(
P.Phi->getIncomingValue(Val)));
1766 for (
Value *V : DFSF.NonZeroChecks) {
1769 Pos = std::next(
I->getIterator());
1771 Pos = DFSF.F->getEntryBlock().begin();
1772 while (isa<PHINode>(Pos) || isa<AllocaInst>(Pos))
1773 Pos = std::next(Pos->getIterator());
1775 Value *PrimitiveShadow = DFSF.collapseToPrimitiveShadow(V, Pos);
1777 IRB.
CreateICmpNE(PrimitiveShadow, DFSF.DFS.ZeroPrimitiveShadow);
1779 Ne, Pos,
false, ColdCallWeights));
1781 ThenIRB.CreateCall(DFSF.DFS.DFSanNonzeroLabelFn, {});
1786 return Changed || !FnsToInstrument.empty() ||
1787 M.global_size() != InitialGlobalSize ||
M.size() != InitialModuleSize;
1800 DFS.RetvalTLS, PointerType::get(DFS.getShadowTy(
T), 0),
"_dfsret");
1803Value *DFSanFunction::getRetvalOriginTLS() {
return DFS.RetvalOriginTLS; }
1811 assert(DFS.shouldTrackOrigins());
1812 if (!isa<Argument>(V) && !isa<Instruction>(V))
1813 return DFS.ZeroOrigin;
1814 Value *&Origin = ValOriginMap[
V];
1816 if (
Argument *
A = dyn_cast<Argument>(V)) {
1818 return DFS.ZeroOrigin;
1819 if (
A->getArgNo() < DFS.NumOfElementsInArgOrgTLS) {
1820 Instruction *ArgOriginTLSPos = &*
F->getEntryBlock().begin();
1822 Value *ArgOriginPtr = getArgOriginTLS(
A->getArgNo(), IRB);
1823 Origin = IRB.
CreateLoad(DFS.OriginTy, ArgOriginPtr);
1826 Origin = DFS.ZeroOrigin;
1829 Origin = DFS.ZeroOrigin;
1836 if (!DFS.shouldTrackOrigins())
1840 ValOriginMap[
I] = Origin;
1844 unsigned ArgOffset = 0;
1846 for (
auto &FArg :
F->args()) {
1847 if (!FArg.getType()->isSized()) {
1853 unsigned Size =
DL.getTypeAllocSize(DFS.getShadowTy(&FArg));
1866 Value *ArgShadowPtr = getArgTLS(FArg.getType(), ArgOffset, IRB);
1871 return DFS.getZeroShadow(
A);
1875 if (!isa<Argument>(V) && !isa<Instruction>(V))
1876 return DFS.getZeroShadow(V);
1877 if (IsForceZeroLabels)
1878 return DFS.getZeroShadow(V);
1879 Value *&Shadow = ValShadowMap[
V];
1881 if (
Argument *
A = dyn_cast<Argument>(V)) {
1883 return DFS.getZeroShadow(V);
1884 Shadow = getShadowForTLSArgument(
A);
1885 NonZeroChecks.push_back(Shadow);
1887 Shadow = DFS.getZeroShadow(V);
1895 ValShadowMap[
I] = Shadow;
1903 assert(
Addr != RetvalTLS &&
"Reinstrumenting?");
1906 uint64_t AndMask = MapParams->AndMask;
1909 IRB.
CreateAnd(OffsetLong, ConstantInt::get(IntptrTy, ~AndMask));
1911 uint64_t XorMask = MapParams->XorMask;
1913 OffsetLong = IRB.
CreateXor(OffsetLong, ConstantInt::get(IntptrTy, XorMask));
1917std::pair<Value *, Value *>
1918DataFlowSanitizer::getShadowOriginAddress(
Value *
Addr,
Align InstAlignment,
1922 Value *ShadowOffset = getShadowOffset(
Addr, IRB);
1923 Value *ShadowLong = ShadowOffset;
1924 uint64_t ShadowBase = MapParams->ShadowBase;
1925 if (ShadowBase != 0) {
1927 IRB.
CreateAdd(ShadowLong, ConstantInt::get(IntptrTy, ShadowBase));
1932 Value *OriginPtr =
nullptr;
1933 if (shouldTrackOrigins()) {
1934 Value *OriginLong = ShadowOffset;
1935 uint64_t OriginBase = MapParams->OriginBase;
1936 if (OriginBase != 0)
1938 IRB.
CreateAdd(OriginLong, ConstantInt::get(IntptrTy, OriginBase));
1944 OriginLong = IRB.
CreateAnd(OriginLong, ConstantInt::get(IntptrTy, ~Mask));
1948 return std::make_pair(ShadowPtr, OriginPtr);
1953 Value *ShadowOffset) {
1961 Value *ShadowOffset = getShadowOffset(
Addr, IRB);
1962 return getShadowAddress(
Addr, Pos, ShadowOffset);
1967 Value *PrimitiveValue = combineShadows(V1, V2, Pos);
1968 return expandFromPrimitiveShadow(
T, PrimitiveValue, Pos);
1975 if (DFS.isZeroShadow(V1))
1976 return collapseToPrimitiveShadow(V2, Pos);
1977 if (DFS.isZeroShadow(V2))
1978 return collapseToPrimitiveShadow(V1, Pos);
1980 return collapseToPrimitiveShadow(V1, Pos);
1982 auto V1Elems = ShadowElements.
find(V1);
1983 auto V2Elems = ShadowElements.
find(V2);
1984 if (V1Elems != ShadowElements.
end() && V2Elems != ShadowElements.
end()) {
1985 if (std::includes(V1Elems->second.begin(), V1Elems->second.end(),
1986 V2Elems->second.begin(), V2Elems->second.end())) {
1987 return collapseToPrimitiveShadow(V1, Pos);
1989 if (std::includes(V2Elems->second.begin(), V2Elems->second.end(),
1990 V1Elems->second.begin(), V1Elems->second.end())) {
1991 return collapseToPrimitiveShadow(V2, Pos);
1993 }
else if (V1Elems != ShadowElements.
end()) {
1994 if (V1Elems->second.count(V2))
1995 return collapseToPrimitiveShadow(V1, Pos);
1996 }
else if (V2Elems != ShadowElements.
end()) {
1997 if (V2Elems->second.count(V1))
1998 return collapseToPrimitiveShadow(V2, Pos);
2001 auto Key = std::make_pair(V1, V2);
2004 CachedShadow &CCS = CachedShadows[
Key];
2005 if (CCS.Block && DT.
dominates(CCS.Block, Pos->getParent()))
2009 Value *PV1 = collapseToPrimitiveShadow(V1, Pos);
2010 Value *PV2 = collapseToPrimitiveShadow(V2, Pos);
2013 CCS.Block = Pos->getParent();
2014 CCS.Shadow = IRB.
CreateOr(PV1, PV2);
2016 std::set<Value *> UnionElems;
2017 if (V1Elems != ShadowElements.
end()) {
2018 UnionElems = V1Elems->second;
2020 UnionElems.insert(V1);
2022 if (V2Elems != ShadowElements.
end()) {
2023 UnionElems.insert(V2Elems->second.begin(), V2Elems->second.end());
2025 UnionElems.insert(V2);
2027 ShadowElements[CCS.Shadow] = std::move(UnionElems);
2037 return DFS.getZeroShadow(Inst);
2041 Shadow = combineShadows(Shadow, getShadow(Inst->
getOperand(
I)),
2044 return expandFromPrimitiveShadow(Inst->
getType(), Shadow,
2049 Value *CombinedShadow = DFSF.combineOperandShadows(&
I);
2050 DFSF.setShadow(&
I, CombinedShadow);
2051 visitInstOperandOrigins(
I);
2054Value *DFSanFunction::combineOrigins(
const std::vector<Value *> &Shadows,
2055 const std::vector<Value *> &Origins,
2058 assert(Shadows.size() == Origins.size());
2059 size_t Size = Origins.size();
2061 return DFS.ZeroOrigin;
2062 Value *Origin =
nullptr;
2064 Zero = DFS.ZeroPrimitiveShadow;
2065 for (
size_t I = 0;
I !=
Size; ++
I) {
2066 Value *OpOrigin = Origins[
I];
2067 Constant *ConstOpOrigin = dyn_cast<Constant>(OpOrigin);
2068 if (ConstOpOrigin && ConstOpOrigin->
isNullValue())
2074 Value *OpShadow = Shadows[
I];
2075 Value *PrimitiveShadow = collapseToPrimitiveShadow(OpShadow, Pos);
2080 return Origin ? Origin : DFS.ZeroOrigin;
2085 std::vector<Value *> Shadows(
Size);
2086 std::vector<Value *> Origins(
Size);
2087 for (
unsigned I = 0;
I !=
Size; ++
I) {
2091 return combineOrigins(Shadows, Origins, Inst->
getIterator());
2094void DFSanVisitor::visitInstOperandOrigins(
Instruction &
I) {
2095 if (!DFSF.DFS.shouldTrackOrigins())
2097 Value *CombinedOrigin = DFSF.combineOperandOrigins(&
I);
2098 DFSF.setOrigin(&
I, CombinedOrigin);
2101Align DFSanFunction::getShadowAlign(
Align InstAlignment) {
2103 return Align(Alignment.
value() * DFS.ShadowWidthBytes);
2106Align DFSanFunction::getOriginAlign(
Align InstAlignment) {
2111bool DFSanFunction::isLookupTableConstant(
Value *
P) {
2112 if (
GlobalVariable *GV = dyn_cast<GlobalVariable>(
P->stripPointerCasts()))
2113 if (GV->isConstant() && GV->
hasName())
2114 return DFS.CombineTaintLookupTableNames.count(GV->
getName());
2119bool DFSanFunction::useCallbackLoadLabelAndOrigin(
uint64_t Size,
2120 Align InstAlignment) {
2144 Value **OriginAddr) {
2147 IRB.
CreateGEP(OriginTy, *OriginAddr, ConstantInt::get(IntptrTy, 1));
2151std::pair<Value *, Value *> DFSanFunction::loadShadowFast(
2154 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins();
2155 const uint64_t ShadowSize =
Size * DFS.ShadowWidthBytes;
2157 assert(
Size >= 4 &&
"Not large enough load size for fast path!");
2160 std::vector<Value *> Shadows;
2161 std::vector<Value *> Origins;
2174 Type *WideShadowTy =
2178 Value *CombinedWideShadow =
2182 const uint64_t BytesPerWideShadow = WideShadowBitWidth / DFS.ShadowWidthBits;
2184 auto AppendWideShadowAndOrigin = [&](
Value *WideShadow,
Value *Origin) {
2185 if (BytesPerWideShadow > 4) {
2186 assert(BytesPerWideShadow == 8);
2194 WideShadow, ConstantInt::get(WideShadowTy, WideShadowBitWidth / 2));
2195 Shadows.push_back(WideShadow);
2196 Origins.push_back(DFS.loadNextOrigin(Pos, OriginAlign, &OriginAddr));
2198 Shadows.push_back(WideShadowLo);
2199 Origins.push_back(Origin);
2201 Shadows.push_back(WideShadow);
2202 Origins.push_back(Origin);
2206 if (ShouldTrackOrigins)
2207 AppendWideShadowAndOrigin(CombinedWideShadow, FirstOrigin);
2214 for (
uint64_t ByteOfs = BytesPerWideShadow; ByteOfs <
Size;
2215 ByteOfs += BytesPerWideShadow) {
2216 ShadowAddr = IRB.
CreateGEP(WideShadowTy, ShadowAddr,
2217 ConstantInt::get(DFS.IntptrTy, 1));
2218 Value *NextWideShadow =
2220 CombinedWideShadow = IRB.
CreateOr(CombinedWideShadow, NextWideShadow);
2221 if (ShouldTrackOrigins) {
2222 Value *NextOrigin = DFS.loadNextOrigin(Pos, OriginAlign, &OriginAddr);
2223 AppendWideShadowAndOrigin(NextWideShadow, NextOrigin);
2226 for (
unsigned Width = WideShadowBitWidth / 2; Width >= DFS.ShadowWidthBits;
2229 CombinedWideShadow = IRB.
CreateOr(CombinedWideShadow, ShrShadow);
2231 return {IRB.
CreateTrunc(CombinedWideShadow, DFS.PrimitiveShadowTy),
2233 ? combineOrigins(Shadows, Origins, Pos,
2238std::pair<Value *, Value *> DFSanFunction::loadShadowOriginSansLoadTracking(
2240 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins();
2244 const auto SI = AllocaShadowMap.
find(AI);
2245 if (SI != AllocaShadowMap.
end()) {
2248 const auto OI = AllocaOriginMap.
find(AI);
2249 assert(!ShouldTrackOrigins || OI != AllocaOriginMap.
end());
2250 return {ShadowLI, ShouldTrackOrigins
2259 bool AllConstants =
true;
2260 for (
const Value *Obj : Objs) {
2261 if (isa<Function>(Obj) || isa<BlockAddress>(Obj))
2263 if (isa<GlobalVariable>(Obj) && cast<GlobalVariable>(Obj)->
isConstant())
2266 AllConstants =
false;
2270 return {DFS.ZeroPrimitiveShadow,
2271 ShouldTrackOrigins ? DFS.ZeroOrigin :
nullptr};
2274 return {DFS.ZeroPrimitiveShadow,
2275 ShouldTrackOrigins ? DFS.ZeroOrigin :
nullptr};
2279 if (ShouldTrackOrigins &&
2280 useCallbackLoadLabelAndOrigin(
Size, InstAlignment)) {
2283 IRB.
CreateCall(DFS.DFSanLoadLabelAndOriginFn,
2284 {Addr, ConstantInt::get(DFS.IntptrTy, Size)});
2285 Call->addRetAttr(Attribute::ZExt);
2287 DFS.PrimitiveShadowTy),
2292 Value *ShadowAddr, *OriginAddr;
2293 std::tie(ShadowAddr, OriginAddr) =
2294 DFS.getShadowOriginAddress(
Addr, InstAlignment, Pos);
2296 const Align ShadowAlign = getShadowAlign(InstAlignment);
2297 const Align OriginAlign = getOriginAlign(InstAlignment);
2298 Value *Origin =
nullptr;
2299 if (ShouldTrackOrigins) {
2310 return {LI, Origin};
2314 Value *ShadowAddr1 = IRB.
CreateGEP(DFS.PrimitiveShadowTy, ShadowAddr,
2315 ConstantInt::get(DFS.IntptrTy, 1));
2320 return {combineShadows(Load, Load1, Pos), Origin};
2323 bool HasSizeForFastPath = DFS.hasLoadSizeForFastPath(
Size);
2325 if (HasSizeForFastPath)
2326 return loadShadowFast(ShadowAddr, OriginAddr,
Size, ShadowAlign,
2327 OriginAlign, Origin, Pos);
2331 DFS.DFSanUnionLoadFn, {ShadowAddr, ConstantInt::get(DFS.IntptrTy, Size)});
2333 return {FallbackCall, Origin};
2336std::pair<Value *, Value *>
2339 Value *PrimitiveShadow, *Origin;
2340 std::tie(PrimitiveShadow, Origin) =
2341 loadShadowOriginSansLoadTracking(
Addr,
Size, InstAlignment, Pos);
2342 if (DFS.shouldTrackOrigins()) {
2345 auto *ConstantShadow = dyn_cast<Constant>(PrimitiveShadow);
2346 if (!ConstantShadow || !ConstantShadow->isZeroValue())
2347 Origin = updateOriginIfTainted(PrimitiveShadow, Origin, IRB);
2350 return {PrimitiveShadow, Origin};
2355 case AtomicOrdering::NotAtomic:
2356 return AtomicOrdering::NotAtomic;
2357 case AtomicOrdering::Unordered:
2358 case AtomicOrdering::Monotonic:
2359 case AtomicOrdering::Acquire:
2360 return AtomicOrdering::Acquire;
2361 case AtomicOrdering::Release:
2362 case AtomicOrdering::AcquireRelease:
2363 return AtomicOrdering::AcquireRelease;
2364 case AtomicOrdering::SequentiallyConsistent:
2365 return AtomicOrdering::SequentiallyConsistent;
2371 if (!V->getType()->isPointerTy())
2379 if (
auto *
GEP = dyn_cast<GEPOperator>(V)) {
2380 V =
GEP->getPointerOperand();
2382 V = cast<Operator>(V)->getOperand(0);
2383 if (!V->getType()->isPointerTy())
2385 }
else if (isa<GlobalAlias>(V)) {
2386 V = cast<GlobalAlias>(V)->getAliasee();
2388 }
while (Visited.
insert(V).second);
2393void DFSanVisitor::visitLoadInst(
LoadInst &LI) {
2397 DFSF.setShadow(&LI, DFSF.DFS.getZeroShadow(&LI));
2398 DFSF.setOrigin(&LI, DFSF.DFS.ZeroOrigin);
2413 Pos = std::next(Pos);
2415 std::vector<Value *> Shadows;
2416 std::vector<Value *> Origins;
2417 Value *PrimitiveShadow, *Origin;
2418 std::tie(PrimitiveShadow, Origin) =
2420 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
2421 if (ShouldTrackOrigins) {
2422 Shadows.push_back(PrimitiveShadow);
2423 Origins.push_back(Origin);
2426 DFSF.isLookupTableConstant(
2429 PrimitiveShadow = DFSF.combineShadows(PrimitiveShadow, PtrShadow, Pos);
2430 if (ShouldTrackOrigins) {
2431 Shadows.push_back(PtrShadow);
2435 if (!DFSF.DFS.isZeroShadow(PrimitiveShadow))
2436 DFSF.NonZeroChecks.push_back(PrimitiveShadow);
2439 DFSF.expandFromPrimitiveShadow(LI.
getType(), PrimitiveShadow, Pos);
2440 DFSF.setShadow(&LI, Shadow);
2442 if (ShouldTrackOrigins) {
2443 DFSF.setOrigin(&LI, DFSF.combineOrigins(Shadows, Origins, Pos));
2450 IRB.
CreateCall(DFSF.DFS.DFSanLoadCallbackFn, {PrimitiveShadow, Addr});
2455 DFSF.addReachesFunctionCallbacksIfEnabled(IRB, LI, &LI);
2458Value *DFSanFunction::updateOriginIfTainted(
Value *Shadow,
Value *Origin,
2460 assert(DFS.shouldTrackOrigins());
2461 return IRB.
CreateCall(DFS.DFSanChainOriginIfTaintedFn, {Shadow, Origin});
2465 if (!DFS.shouldTrackOrigins())
2467 return IRB.
CreateCall(DFS.DFSanChainOriginFn, V);
2471 const unsigned OriginSize = DataFlowSanitizer::OriginWidthBytes;
2473 unsigned IntptrSize =
DL.getTypeStoreSize(DFS.IntptrTy);
2474 if (IntptrSize == OriginSize)
2476 assert(IntptrSize == OriginSize * 2);
2482 Value *StoreOriginAddr,
2484 const unsigned OriginSize = DataFlowSanitizer::OriginWidthBytes;
2486 const Align IntptrAlignment =
DL.getABITypeAlign(DFS.IntptrTy);
2487 unsigned IntptrSize =
DL.getTypeStoreSize(DFS.IntptrTy);
2489 assert(IntptrSize >= OriginSize);
2492 Align CurrentAlignment = Alignment;
2493 if (Alignment >= IntptrAlignment && IntptrSize > OriginSize) {
2494 Value *IntptrOrigin = originToIntptr(IRB, Origin);
2496 StoreOriginAddr, PointerType::get(DFS.IntptrTy, 0));
2497 for (
unsigned I = 0;
I < StoreOriginSize / IntptrSize; ++
I) {
2500 : IntptrStoreOriginPtr;
2502 Ofs += IntptrSize / OriginSize;
2503 CurrentAlignment = IntptrAlignment;
2507 for (
unsigned I = Ofs;
I < (StoreOriginSize + OriginSize - 1) / OriginSize;
2518 Type *VTy =
V->getType();
2528 Value *StoreOriginAddr,
Align InstAlignment) {
2531 const Align OriginAlignment = getOriginAlign(InstAlignment);
2532 Value *CollapsedShadow = collapseToPrimitiveShadow(Shadow, Pos);
2534 if (
auto *ConstantShadow = dyn_cast<Constant>(CollapsedShadow)) {
2535 if (!ConstantShadow->isZeroValue())
2536 paintOrigin(IRB, updateOrigin(Origin, IRB), StoreOriginAddr,
Size,
2541 if (shouldInstrumentWithCall()) {
2543 DFS.DFSanMaybeStoreOriginFn,
2544 {CollapsedShadow, Addr, ConstantInt::get(DFS.IntptrTy, Size), Origin});
2546 Value *
Cmp = convertToBool(CollapsedShadow, IRB,
"_dfscmp");
2549 Cmp, &*IRB.
GetInsertPoint(),
false, DFS.OriginStoreWeights, &DTU);
2551 paintOrigin(IRBNew, updateOrigin(Origin, IRBNew), StoreOriginAddr,
Size,
2563 Value *ExtZeroShadow = ConstantInt::get(ShadowTy, 0);
2564 Value *ShadowAddr = DFS.getShadowAddress(
Addr, Pos);
2571 Align InstAlignment,
2572 Value *PrimitiveShadow,
2575 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins() && Origin;
2578 const auto SI = AllocaShadowMap.
find(AI);
2579 if (SI != AllocaShadowMap.
end()) {
2585 if (ShouldTrackOrigins && !DFS.isZeroShadow(PrimitiveShadow)) {
2586 const auto OI = AllocaOriginMap.
find(AI);
2587 assert(OI != AllocaOriginMap.
end() && Origin);
2594 const Align ShadowAlign = getShadowAlign(InstAlignment);
2595 if (DFS.isZeroShadow(PrimitiveShadow)) {
2596 storeZeroPrimitiveShadow(
Addr,
Size, ShadowAlign, Pos);
2601 Value *ShadowAddr, *OriginAddr;
2602 std::tie(ShadowAddr, OriginAddr) =
2603 DFS.getShadowOriginAddress(
Addr, InstAlignment, Pos);
2605 const unsigned ShadowVecSize = 8;
2606 assert(ShadowVecSize * DFS.ShadowWidthBits <= 128 &&
2607 "Shadow vector is too large!");
2611 if (LeftSize >= ShadowVecSize) {
2615 for (
unsigned I = 0;
I != ShadowVecSize; ++
I) {
2617 ShadowVec, PrimitiveShadow,
2621 Value *CurShadowVecAddr =
2624 LeftSize -= ShadowVecSize;
2626 }
while (LeftSize >= ShadowVecSize);
2629 while (LeftSize > 0) {
2630 Value *CurShadowAddr =
2637 if (ShouldTrackOrigins) {
2638 storeOrigin(Pos,
Addr,
Size, PrimitiveShadow, Origin, OriginAddr,
2645 case AtomicOrdering::NotAtomic:
2646 return AtomicOrdering::NotAtomic;
2647 case AtomicOrdering::Unordered:
2648 case AtomicOrdering::Monotonic:
2649 case AtomicOrdering::Release:
2650 return AtomicOrdering::Release;
2651 case AtomicOrdering::Acquire:
2652 case AtomicOrdering::AcquireRelease:
2653 return AtomicOrdering::AcquireRelease;
2654 case AtomicOrdering::SequentiallyConsistent:
2655 return AtomicOrdering::SequentiallyConsistent;
2660void DFSanVisitor::visitStoreInst(
StoreInst &SI) {
2661 auto &
DL =
SI.getModule()->getDataLayout();
2662 Value *Val =
SI.getValueOperand();
2675 const bool ShouldTrackOrigins =
2676 DFSF.DFS.shouldTrackOrigins() && !
SI.isAtomic();
2677 std::vector<Value *> Shadows;
2678 std::vector<Value *> Origins;
2681 SI.isAtomic() ? DFSF.DFS.getZeroShadow(Val) : DFSF.getShadow(Val);
2683 if (ShouldTrackOrigins) {
2684 Shadows.push_back(Shadow);
2685 Origins.push_back(DFSF.getOrigin(Val));
2688 Value *PrimitiveShadow;
2690 Value *PtrShadow = DFSF.getShadow(
SI.getPointerOperand());
2691 if (ShouldTrackOrigins) {
2692 Shadows.push_back(PtrShadow);
2693 Origins.push_back(DFSF.getOrigin(
SI.getPointerOperand()));
2695 PrimitiveShadow = DFSF.combineShadows(Shadow, PtrShadow,
SI.getIterator());
2697 PrimitiveShadow = DFSF.collapseToPrimitiveShadow(Shadow,
SI.getIterator());
2699 Value *Origin =
nullptr;
2700 if (ShouldTrackOrigins)
2701 Origin = DFSF.combineOrigins(Shadows, Origins,
SI.getIterator());
2702 DFSF.storePrimitiveShadowOrigin(
SI.getPointerOperand(),
Size,
SI.getAlign(),
2703 PrimitiveShadow, Origin,
SI.getIterator());
2708 IRB.
CreateCall(DFSF.DFS.DFSanStoreCallbackFn, {PrimitiveShadow, Addr});
2714 assert(isa<AtomicRMWInst>(
I) || isa<AtomicCmpXchgInst>(
I));
2716 Value *Val =
I.getOperand(1);
2717 const auto &
DL =
I.getModule()->getDataLayout();
2726 const Align ShadowAlign = DFSF.getShadowAlign(InstAlignment);
2727 DFSF.storeZeroPrimitiveShadow(
Addr,
Size, ShadowAlign,
I.getIterator());
2728 DFSF.setShadow(&
I, DFSF.DFS.getZeroShadow(&
I));
2729 DFSF.setOrigin(&
I, DFSF.DFS.ZeroOrigin);
2733 visitCASOrRMW(
I.getAlign(),
I);
2740 visitCASOrRMW(
I.getAlign(),
I);
2747 visitInstOperands(UO);
2751 visitInstOperands(BO);
2754void DFSanVisitor::visitBitCastInst(
BitCastInst &BCI) {
2758 if (
auto *CI = dyn_cast<CallInst>(BCI.
getOperand(0)))
2761 visitInstOperands(BCI);
2764void DFSanVisitor::visitCastInst(
CastInst &CI) { visitInstOperands(CI); }
2766void DFSanVisitor::visitCmpInst(
CmpInst &CI) {
2767 visitInstOperands(CI);
2770 Value *CombinedShadow = DFSF.getShadow(&CI);
2772 IRB.
CreateCall(DFSF.DFS.DFSanCmpCallbackFn, CombinedShadow);
2789 DFSF.setShadow(&LPI, DFSF.DFS.getZeroShadow(&LPI));
2790 DFSF.setOrigin(&LPI, DFSF.DFS.ZeroOrigin);
2795 DFSF.isLookupTableConstant(
2797 visitInstOperands(GEPI);
2804 DFSF.setShadow(&GEPI, DFSF.getShadow(BasePointer));
2805 if (DFSF.DFS.shouldTrackOrigins())
2806 DFSF.setOrigin(&GEPI, DFSF.getOrigin(BasePointer));
2810 visitInstOperands(
I);
2814 visitInstOperands(
I);
2818 visitInstOperands(
I);
2823 Value *Agg =
I.getAggregateOperand();
2824 Value *AggShadow = DFSF.getShadow(Agg);
2826 DFSF.setShadow(&
I, ResShadow);
2827 visitInstOperandOrigins(
I);
2832 Value *AggShadow = DFSF.getShadow(
I.getAggregateOperand());
2833 Value *InsShadow = DFSF.getShadow(
I.getInsertedValueOperand());
2835 DFSF.setShadow(&
I, Res);
2836 visitInstOperandOrigins(
I);
2839void DFSanVisitor::visitAllocaInst(
AllocaInst &
I) {
2840 bool AllLoadsStores =
true;
2841 for (
User *U :
I.users()) {
2842 if (isa<LoadInst>(U))
2845 if (
StoreInst *SI = dyn_cast<StoreInst>(U)) {
2846 if (
SI->getPointerOperand() == &
I)
2850 AllLoadsStores =
false;
2853 if (AllLoadsStores) {
2855 DFSF.AllocaShadowMap[&
I] = IRB.
CreateAlloca(DFSF.DFS.PrimitiveShadowTy);
2856 if (DFSF.DFS.shouldTrackOrigins()) {
2857 DFSF.AllocaOriginMap[&
I] =
2861 DFSF.setShadow(&
I, DFSF.DFS.ZeroPrimitiveShadow);
2862 DFSF.setOrigin(&
I, DFSF.DFS.ZeroOrigin);
2865void DFSanVisitor::visitSelectInst(
SelectInst &
I) {
2866 Value *CondShadow = DFSF.getShadow(
I.getCondition());
2867 Value *TrueShadow = DFSF.getShadow(
I.getTrueValue());
2868 Value *FalseShadow = DFSF.getShadow(
I.getFalseValue());
2869 Value *ShadowSel =
nullptr;
2870 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
2871 std::vector<Value *> Shadows;
2872 std::vector<Value *> Origins;
2874 ShouldTrackOrigins ? DFSF.getOrigin(
I.getTrueValue()) :
nullptr;
2875 Value *FalseOrigin =
2876 ShouldTrackOrigins ? DFSF.getOrigin(
I.getFalseValue()) :
nullptr;
2878 DFSF.addConditionalCallbacksIfEnabled(
I,
I.getCondition());
2880 if (isa<VectorType>(
I.getCondition()->getType())) {
2881 ShadowSel = DFSF.combineShadowsThenConvert(
I.getType(), TrueShadow,
2882 FalseShadow,
I.getIterator());
2883 if (ShouldTrackOrigins) {
2884 Shadows.push_back(TrueShadow);
2885 Shadows.push_back(FalseShadow);
2886 Origins.push_back(TrueOrigin);
2887 Origins.push_back(FalseOrigin);
2890 if (TrueShadow == FalseShadow) {
2891 ShadowSel = TrueShadow;
2892 if (ShouldTrackOrigins) {
2893 Shadows.push_back(TrueShadow);
2894 Origins.push_back(TrueOrigin);
2898 "",
I.getIterator());
2899 if (ShouldTrackOrigins) {
2900 Shadows.push_back(ShadowSel);
2902 FalseOrigin,
"",
I.getIterator()));
2907 I.getType(), CondShadow,
2908 ShadowSel,
I.getIterator())
2910 if (ShouldTrackOrigins) {
2912 Shadows.push_back(CondShadow);
2913 Origins.push_back(DFSF.getOrigin(
I.getCondition()));
2915 DFSF.setOrigin(&
I, DFSF.combineOrigins(Shadows, Origins,
I.getIterator()));
2919void DFSanVisitor::visitMemSetInst(
MemSetInst &
I) {
2921 Value *ValShadow = DFSF.getShadow(
I.getValue());
2922 Value *ValOrigin = DFSF.DFS.shouldTrackOrigins()
2923 ? DFSF.getOrigin(
I.getValue())
2924 : DFSF.DFS.ZeroOrigin;
2926 {ValShadow, ValOrigin, I.getDest(),
2927 IRB.CreateZExtOrTrunc(I.getLength(), DFSF.DFS.IntptrTy)});
2935 if (DFSF.DFS.shouldTrackOrigins()) {
2937 DFSF.DFS.DFSanMemOriginTransferFn,
2938 {I.getArgOperand(0), I.getArgOperand(1),
2939 IRB.CreateIntCast(I.getArgOperand(2), DFSF.DFS.IntptrTy, false)});
2942 Value *DestShadow = DFSF.DFS.getShadowAddress(
I.getDest(),
I.getIterator());
2943 Value *SrcShadow = DFSF.DFS.getShadowAddress(
I.getSource(),
I.getIterator());
2945 IRB.
CreateMul(
I.getLength(), ConstantInt::get(
I.getLength()->getType(),
2946 DFSF.DFS.ShadowWidthBytes));
2947 auto *MTI = cast<MemTransferInst>(
2948 IRB.
CreateCall(
I.getFunctionType(),
I.getCalledOperand(),
2949 {DestShadow, SrcShadow, LenShadow, I.getVolatileCst()}));
2950 MTI->setDestAlignment(DFSF.getShadowAlign(
I.getDestAlign().valueOrOne()));
2951 MTI->setSourceAlignment(DFSF.getShadowAlign(
I.getSourceAlign().valueOrOne()));
2954 DFSF.DFS.DFSanMemTransferCallbackFn,
2955 {DestShadow, IRB.CreateZExtOrTrunc(I.getLength(), DFSF.DFS.IntptrTy)});
2959void DFSanVisitor::visitBranchInst(
BranchInst &BR) {
2960 if (!
BR.isConditional())
2963 DFSF.addConditionalCallbacksIfEnabled(BR,
BR.getCondition());
2966void DFSanVisitor::visitSwitchInst(
SwitchInst &SW) {
2967 DFSF.addConditionalCallbacksIfEnabled(SW, SW.
getCondition());
2972 if (
auto *
I = dyn_cast<BitCastInst>(RetVal)) {
2973 RetVal =
I->getOperand(0);
2975 if (
auto *
I = dyn_cast<CallInst>(RetVal)) {
2976 return I->isMustTailCall();
2981void DFSanVisitor::visitReturnInst(
ReturnInst &RI) {
2989 Type *RT = DFSF.F->getFunctionType()->getReturnType();
2990 unsigned Size = getDataLayout().getTypeAllocSize(DFSF.DFS.getShadowTy(RT));
2996 if (DFSF.DFS.shouldTrackOrigins()) {
3004 std::vector<Value *> &Args,
3011 for (
unsigned N = FT->getNumParams();
N != 0; ++
I, --
N)
3013 DFSF.collapseToPrimitiveShadow(DFSF.getShadow(*
I), CB.
getIterator()));
3016 if (FT->isVarArg()) {
3017 auto *LabelVATy = ArrayType::get(DFSF.DFS.PrimitiveShadowTy,
3018 CB.
arg_size() - FT->getNumParams());
3019 auto *LabelVAAlloca =
3020 new AllocaInst(LabelVATy, getDataLayout().getAllocaAddrSpace(),
3021 "labelva", DFSF.F->getEntryBlock().begin());
3023 for (
unsigned N = 0;
I != CB.
arg_end(); ++
I, ++
N) {
3026 DFSF.collapseToPrimitiveShadow(DFSF.getShadow(*
I), CB.
getIterator()),
3034 if (!FT->getReturnType()->isVoidTy()) {
3035 if (!DFSF.LabelReturnAlloca) {
3037 DFSF.DFS.PrimitiveShadowTy, getDataLayout().getAllocaAddrSpace(),
3038 "labelreturn", DFSF.F->getEntryBlock().begin());
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().begin());
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().begin());
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,
3174 DFSF.expandFromPrimitiveShadow(
3175 FT->getReturnType(), LabelLoad, CB.
getIterator()));
3176 if (ShouldTrackOrigins) {
3178 IRB.
CreateLoad(DFSF.DFS.OriginTy, DFSF.OriginReturnAlloca);
3179 DFSF.setOrigin(CustomCI, OriginLoad);
3191 constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
3192 uint32_t OrderingTable[NumOrderings] = {};
3194 OrderingTable[(int)AtomicOrderingCABI::relaxed] =
3195 OrderingTable[(
int)AtomicOrderingCABI::acquire] =
3196 OrderingTable[(int)AtomicOrderingCABI::consume] =
3197 (
int)AtomicOrderingCABI::acquire;
3198 OrderingTable[(int)AtomicOrderingCABI::release] =
3199 OrderingTable[(
int)AtomicOrderingCABI::acq_rel] =
3200 (int)AtomicOrderingCABI::acq_rel;
3201 OrderingTable[(int)AtomicOrderingCABI::seq_cst] =
3202 (
int)AtomicOrderingCABI::seq_cst;
3205 ArrayRef(OrderingTable, NumOrderings));
3208void DFSanVisitor::visitLibAtomicLoad(
CallBase &CB) {
3210 assert(isa<CallInst>(CB));
3219 Value *NewOrdering =
3224 NextIRB.SetCurrentDebugLocation(CB.
getDebugLoc());
3230 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3231 {DstPtr, SrcPtr, 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 =
3268 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3269 {DstPtr, SrcPtr, IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3272void DFSanVisitor::visitLibAtomicExchange(
CallBase &CB) {
3288 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3289 {DstPtr, TargetPtr, IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3293 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3294 {TargetPtr, SrcPtr, IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3297void DFSanVisitor::visitLibAtomicCompareExchange(
CallBase &CB) {
3311 NextIRB.SetCurrentDebugLocation(CB.
getDebugLoc());
3313 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3317 NextIRB.CreateCall(DFSF.DFS.DFSanMemShadowOriginConditionalExchangeFn,
3318 {NextIRB.CreateIntCast(&CB, NextIRB.getInt8Ty(), false),
3319 TargetPtr, ExpectedPtr, DesiredPtr,
3320 NextIRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3323void DFSanVisitor::visitCallBase(
CallBase &CB) {
3326 visitInstOperands(CB);
3332 if (
F == DFSF.DFS.DFSanVarargWrapperFn.getCallee()->stripPointerCasts())
3336 if (DFSF.TLI.getLibFunc(CB, LF)) {
3341 case LibFunc_atomic_load:
3342 if (!isa<CallInst>(CB)) {
3343 llvm::errs() <<
"DFSAN -- cannot instrument invoke of libatomic load. "
3347 visitLibAtomicLoad(CB);
3349 case LibFunc_atomic_store:
3350 visitLibAtomicStore(CB);
3358 if (
F &&
F->hasName() && !
F->isVarArg()) {
3359 if (
F->getName() ==
"__atomic_exchange") {
3360 visitLibAtomicExchange(CB);
3363 if (
F->getName() ==
"__atomic_compare_exchange") {
3364 visitLibAtomicCompareExchange(CB);
3371 if (UnwrappedFnIt != DFSF.DFS.UnwrappedFnMap.end())
3372 if (visitWrappedCallBase(*UnwrappedFnIt->second, CB))
3377 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
3382 unsigned ArgOffset = 0;
3383 for (
unsigned I = 0,
N = FT->getNumParams();
I !=
N; ++
I) {
3384 if (ShouldTrackOrigins) {
3387 if (
I < DFSF.DFS.NumOfElementsInArgOrgTLS &&
3388 !DFSF.DFS.isZeroShadow(ArgShadow))
3390 DFSF.getArgOriginTLS(
I, IRB));
3394 DL.getTypeAllocSize(DFSF.DFS.getShadowTy(FT->getParamType(
I)));
3400 DFSF.getArgTLS(FT->getParamType(
I), ArgOffset, IRB),
3407 if (
InvokeInst *II = dyn_cast<InvokeInst>(&CB)) {
3408 if (II->getNormalDest()->getSinglePredecessor()) {
3409 Next = &II->getNormalDest()->front();
3412 SplitEdge(II->getParent(), II->getNormalDest(), &DFSF.DT);
3413 Next = &NewBB->
front();
3421 if (isa<CallInst>(CB) && cast<CallInst>(CB).isMustTailCall())
3426 unsigned Size =
DL.getTypeAllocSize(DFSF.DFS.getShadowTy(&CB));
3429 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3431 LoadInst *LI = NextIRB.CreateAlignedLoad(
3432 DFSF.DFS.getShadowTy(&CB), DFSF.getRetvalTLS(CB.
getType(), NextIRB),
3434 DFSF.SkipInsts.insert(LI);
3435 DFSF.setShadow(&CB, LI);
3436 DFSF.NonZeroChecks.push_back(LI);
3439 if (ShouldTrackOrigins) {
3440 LoadInst *LI = NextIRB.CreateLoad(DFSF.DFS.OriginTy,
3441 DFSF.getRetvalOriginTLS(),
"_dfsret_o");
3442 DFSF.SkipInsts.insert(LI);
3443 DFSF.setOrigin(&CB, LI);
3446 DFSF.addReachesFunctionCallbacksIfEnabled(NextIRB, CB, &CB);
3450void DFSanVisitor::visitPHINode(
PHINode &PN) {
3451 Type *ShadowTy = DFSF.DFS.getShadowTy(&PN);
3460 DFSF.setShadow(&PN, ShadowPN);
3463 if (DFSF.DFS.shouldTrackOrigins()) {
3469 DFSF.setOrigin(&PN, OriginPN);
3472 DFSF.PHIFixups.push_back({&PN, ShadowPN, OriginPN});
3482 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.
InstListType::iterator iterator
Instruction iterators...
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.
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr, BasicBlock::iterator InsertBefore)
bool isMustTailCall() const
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.
This is the shared class of boolean and integer constants.
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...
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="")
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)
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
InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
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...
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, BasicBlock::iterator InsertBefore)
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, BasicBlock::iterator InsertBefore)
This class represents the LLVM 'select' instruction.
static SelectInst * Create(Value *C, Value *S1, Value *S2, const Twine &NameStr, BasicBlock::iterator InsertBefore, 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 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 range R to container C.
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 erase(Container &C, ValueType V)
Wrapper function to remove a value from a container:
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...
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.