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 const 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->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(),
1092 std::vector<Value *>
args;
1094 if (DFS.shouldTrackOrigins()) {
1095 Value *DataOrigin = getOrigin(Data);
1096 args = { DataShadow, DataOrigin, FilePathPtr, CILine, FunctionNamePtr };
1097 CB = IRB.
CreateCall(DFS.DFSanReachesFunctionCallbackOriginFn,
args);
1099 args = { DataShadow, FilePathPtr, CILine, FunctionNamePtr };
1106Type *DataFlowSanitizer::getShadowTy(
Type *OrigTy) {
1108 return PrimitiveShadowTy;
1109 if (isa<IntegerType>(OrigTy))
1110 return PrimitiveShadowTy;
1111 if (isa<VectorType>(OrigTy))
1112 return PrimitiveShadowTy;
1113 if (
ArrayType *AT = dyn_cast<ArrayType>(OrigTy))
1114 return ArrayType::get(getShadowTy(AT->getElementType()),
1115 AT->getNumElements());
1116 if (
StructType *ST = dyn_cast<StructType>(OrigTy)) {
1118 for (
unsigned I = 0,
N =
ST->getNumElements();
I <
N; ++
I)
1119 Elements.push_back(getShadowTy(
ST->getElementType(
I)));
1122 return PrimitiveShadowTy;
1125Type *DataFlowSanitizer::getShadowTy(
Value *V) {
1126 return getShadowTy(
V->getType());
1129bool DataFlowSanitizer::initializeModule(
Module &M) {
1130 Triple TargetTriple(
M.getTargetTriple());
1135 switch (TargetTriple.getArch()) {
1150 Ctx = &
M.getContext();
1151 Int8Ptr = PointerType::getUnqual(*Ctx);
1153 OriginPtrTy = PointerType::getUnqual(OriginTy);
1155 PrimitiveShadowPtrTy = PointerType::getUnqual(PrimitiveShadowTy);
1156 IntptrTy =
DL.getIntPtrType(*Ctx);
1160 Type *DFSanUnionLoadArgs[2] = {PrimitiveShadowPtrTy, IntptrTy};
1161 DFSanUnionLoadFnTy = FunctionType::get(PrimitiveShadowTy, DFSanUnionLoadArgs,
1163 Type *DFSanLoadLabelAndOriginArgs[2] = {Int8Ptr, IntptrTy};
1164 DFSanLoadLabelAndOriginFnTy =
1167 DFSanUnimplementedFnTy = FunctionType::get(
1169 Type *DFSanWrapperExternWeakNullArgs[2] = {Int8Ptr, Int8Ptr};
1170 DFSanWrapperExternWeakNullFnTy =
1171 FunctionType::get(
Type::getVoidTy(*Ctx), DFSanWrapperExternWeakNullArgs,
1173 Type *DFSanSetLabelArgs[4] = {PrimitiveShadowTy, OriginTy,
1174 PointerType::getUnqual(*Ctx), IntptrTy};
1176 DFSanSetLabelArgs,
false);
1179 DFSanVarargWrapperFnTy = FunctionType::get(
1181 DFSanConditionalCallbackFnTy =
1184 Type *DFSanConditionalCallbackOriginArgs[2] = {PrimitiveShadowTy, OriginTy};
1185 DFSanConditionalCallbackOriginFnTy = FunctionType::get(
1188 Type *DFSanReachesFunctionCallbackArgs[4] = {PrimitiveShadowTy, Int8Ptr,
1190 DFSanReachesFunctionCallbackFnTy =
1191 FunctionType::get(
Type::getVoidTy(*Ctx), DFSanReachesFunctionCallbackArgs,
1193 Type *DFSanReachesFunctionCallbackOriginArgs[5] = {
1194 PrimitiveShadowTy, OriginTy, Int8Ptr, OriginTy, Int8Ptr};
1195 DFSanReachesFunctionCallbackOriginFnTy = FunctionType::get(
1198 DFSanCmpCallbackFnTy =
1201 DFSanChainOriginFnTy =
1202 FunctionType::get(OriginTy, OriginTy,
false);
1203 Type *DFSanChainOriginIfTaintedArgs[2] = {PrimitiveShadowTy, OriginTy};
1204 DFSanChainOriginIfTaintedFnTy = FunctionType::get(
1205 OriginTy, DFSanChainOriginIfTaintedArgs,
false);
1207 Int8Ptr, IntptrTy, OriginTy};
1208 DFSanMaybeStoreOriginFnTy = FunctionType::get(
1210 Type *DFSanMemOriginTransferArgs[3] = {Int8Ptr, Int8Ptr, IntptrTy};
1211 DFSanMemOriginTransferFnTy = FunctionType::get(
1213 Type *DFSanMemShadowOriginTransferArgs[3] = {Int8Ptr, Int8Ptr, IntptrTy};
1214 DFSanMemShadowOriginTransferFnTy =
1215 FunctionType::get(
Type::getVoidTy(*Ctx), DFSanMemShadowOriginTransferArgs,
1217 Type *DFSanMemShadowOriginConditionalExchangeArgs[5] = {
1219 DFSanMemShadowOriginConditionalExchangeFnTy = FunctionType::get(
1222 Type *DFSanLoadStoreCallbackArgs[2] = {PrimitiveShadowTy, Int8Ptr};
1223 DFSanLoadStoreCallbackFnTy =
1226 Type *DFSanMemTransferCallbackArgs[2] = {PrimitiveShadowPtrTy, IntptrTy};
1227 DFSanMemTransferCallbackFnTy =
1228 FunctionType::get(
Type::getVoidTy(*Ctx), DFSanMemTransferCallbackArgs,
1236bool DataFlowSanitizer::isInstrumented(
const Function *
F) {
1237 return !ABIList.isIn(*
F,
"uninstrumented");
1240bool DataFlowSanitizer::isInstrumented(
const GlobalAlias *GA) {
1241 return !ABIList.isIn(*GA,
"uninstrumented");
1244bool DataFlowSanitizer::isForceZeroLabels(
const Function *
F) {
1245 return ABIList.isIn(*
F,
"force_zero_labels");
1248DataFlowSanitizer::WrapperKind DataFlowSanitizer::getWrapperKind(
Function *
F) {
1249 if (ABIList.isIn(*
F,
"functional"))
1250 return WK_Functional;
1251 if (ABIList.isIn(*
F,
"discard"))
1253 if (ABIList.isIn(*
F,
"custom"))
1259void DataFlowSanitizer::addGlobalNameSuffix(
GlobalValue *GV) {
1260 std::string GVName = std::string(GV->
getName()), Suffix =
".dfsan";
1269 std::string SearchStr =
".symver " + GVName +
",";
1270 size_t Pos =
Asm.find(SearchStr);
1271 if (Pos != std::string::npos) {
1272 Asm.replace(Pos, SearchStr.size(),
".symver " + GVName + Suffix +
",");
1273 Pos =
Asm.find(
'@');
1275 if (Pos == std::string::npos)
1278 Asm.replace(Pos, 1, Suffix +
"@");
1283void DataFlowSanitizer::buildExternWeakCheckIfNeeded(
IRBuilder<> &IRB,
1293 std::vector<Value *>
Args;
1296 IRB.
CreateCall(DFSanWrapperExternWeakNullFn, Args);
1306 NewFName,
F->getParent());
1312 if (
F->isVarArg()) {
1315 IRBuilder<>(BB).CreateGlobalString(
F->getName()),
"", BB);
1319 std::vector<Value *>
Args(ArgIt, ArgIt + FT->getNumParams());
1322 if (FT->getReturnType()->isVoidTy())
1332void DataFlowSanitizer::initializeRuntimeFunctions(
Module &M) {
1336 AL =
AL.addFnAttribute(
C, Attribute::NoUnwind);
1337 AL =
AL.addFnAttribute(
1339 AL =
AL.addRetAttribute(
C, Attribute::ZExt);
1341 Mod->getOrInsertFunction(
"__dfsan_union_load", DFSanUnionLoadFnTy, AL);
1345 AL =
AL.addFnAttribute(
C, Attribute::NoUnwind);
1346 AL =
AL.addFnAttribute(
1348 AL =
AL.addRetAttribute(
C, Attribute::ZExt);
1349 DFSanLoadLabelAndOriginFn =
Mod->getOrInsertFunction(
1350 "__dfsan_load_label_and_origin", DFSanLoadLabelAndOriginFnTy, AL);
1352 DFSanUnimplementedFn =
1353 Mod->getOrInsertFunction(
"__dfsan_unimplemented", DFSanUnimplementedFnTy);
1354 DFSanWrapperExternWeakNullFn =
Mod->getOrInsertFunction(
1355 "__dfsan_wrapper_extern_weak_null", DFSanWrapperExternWeakNullFnTy);
1358 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1359 AL =
AL.addParamAttribute(
M.getContext(), 1, Attribute::ZExt);
1361 Mod->getOrInsertFunction(
"__dfsan_set_label", DFSanSetLabelFnTy, AL);
1363 DFSanNonzeroLabelFn =
1364 Mod->getOrInsertFunction(
"__dfsan_nonzero_label", DFSanNonzeroLabelFnTy);
1365 DFSanVarargWrapperFn =
Mod->getOrInsertFunction(
"__dfsan_vararg_wrapper",
1366 DFSanVarargWrapperFnTy);
1369 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1370 AL =
AL.addRetAttribute(
M.getContext(), Attribute::ZExt);
1371 DFSanChainOriginFn =
Mod->getOrInsertFunction(
"__dfsan_chain_origin",
1372 DFSanChainOriginFnTy, AL);
1376 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1377 AL =
AL.addParamAttribute(
M.getContext(), 1, Attribute::ZExt);
1378 AL =
AL.addRetAttribute(
M.getContext(), Attribute::ZExt);
1379 DFSanChainOriginIfTaintedFn =
Mod->getOrInsertFunction(
1380 "__dfsan_chain_origin_if_tainted", DFSanChainOriginIfTaintedFnTy, AL);
1382 DFSanMemOriginTransferFn =
Mod->getOrInsertFunction(
1383 "__dfsan_mem_origin_transfer", DFSanMemOriginTransferFnTy);
1385 DFSanMemShadowOriginTransferFn =
Mod->getOrInsertFunction(
1386 "__dfsan_mem_shadow_origin_transfer", DFSanMemShadowOriginTransferFnTy);
1388 DFSanMemShadowOriginConditionalExchangeFn =
1389 Mod->getOrInsertFunction(
"__dfsan_mem_shadow_origin_conditional_exchange",
1390 DFSanMemShadowOriginConditionalExchangeFnTy);
1394 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1395 AL =
AL.addParamAttribute(
M.getContext(), 3, Attribute::ZExt);
1396 DFSanMaybeStoreOriginFn =
Mod->getOrInsertFunction(
1397 "__dfsan_maybe_store_origin", DFSanMaybeStoreOriginFnTy, AL);
1400 DFSanRuntimeFunctions.
insert(
1402 DFSanRuntimeFunctions.
insert(
1404 DFSanRuntimeFunctions.
insert(
1406 DFSanRuntimeFunctions.
insert(
1408 DFSanRuntimeFunctions.
insert(
1410 DFSanRuntimeFunctions.
insert(
1412 DFSanRuntimeFunctions.
insert(
1414 DFSanRuntimeFunctions.
insert(
1416 DFSanRuntimeFunctions.
insert(
1418 DFSanRuntimeFunctions.
insert(
1420 DFSanRuntimeFunctions.
insert(
1422 DFSanRuntimeFunctions.
insert(
1424 DFSanRuntimeFunctions.
insert(
1426 DFSanRuntimeFunctions.
insert(
1428 DFSanRuntimeFunctions.
insert(
1430 DFSanRuntimeFunctions.
insert(
1432 DFSanRuntimeFunctions.
insert(
1434 DFSanRuntimeFunctions.
insert(
1436 DFSanRuntimeFunctions.
insert(
1438 DFSanRuntimeFunctions.
insert(
1439 DFSanMemShadowOriginConditionalExchangeFn.
getCallee()
1441 DFSanRuntimeFunctions.
insert(
1446void DataFlowSanitizer::initializeCallbackFunctions(
Module &M) {
1449 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1450 DFSanLoadCallbackFn =
Mod->getOrInsertFunction(
1451 "__dfsan_load_callback", DFSanLoadStoreCallbackFnTy, AL);
1455 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1456 DFSanStoreCallbackFn =
Mod->getOrInsertFunction(
1457 "__dfsan_store_callback", DFSanLoadStoreCallbackFnTy, AL);
1459 DFSanMemTransferCallbackFn =
Mod->getOrInsertFunction(
1460 "__dfsan_mem_transfer_callback", DFSanMemTransferCallbackFnTy);
1463 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1464 DFSanCmpCallbackFn =
Mod->getOrInsertFunction(
"__dfsan_cmp_callback",
1465 DFSanCmpCallbackFnTy, AL);
1469 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1470 DFSanConditionalCallbackFn =
Mod->getOrInsertFunction(
1471 "__dfsan_conditional_callback", DFSanConditionalCallbackFnTy, AL);
1475 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1476 DFSanConditionalCallbackOriginFn =
1477 Mod->getOrInsertFunction(
"__dfsan_conditional_callback_origin",
1478 DFSanConditionalCallbackOriginFnTy, AL);
1482 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1483 DFSanReachesFunctionCallbackFn =
1484 Mod->getOrInsertFunction(
"__dfsan_reaches_function_callback",
1485 DFSanReachesFunctionCallbackFnTy, AL);
1489 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1490 DFSanReachesFunctionCallbackOriginFn =
1491 Mod->getOrInsertFunction(
"__dfsan_reaches_function_callback_origin",
1492 DFSanReachesFunctionCallbackOriginFnTy, AL);
1496bool DataFlowSanitizer::runImpl(
1498 initializeModule(M);
1500 if (ABIList.isIn(M,
"skip"))
1503 const unsigned InitialGlobalSize =
M.global_size();
1504 const unsigned InitialModuleSize =
M.size();
1506 bool Changed =
false;
1512 Changed |=
G->getThreadLocalMode() != GlobalVariable::InitialExecTLSModel;
1513 G->setThreadLocalMode(GlobalVariable::InitialExecTLSModel);
1520 GetOrInsertGlobal(
"__dfsan_arg_tls",
1522 RetvalTLS = GetOrInsertGlobal(
1523 "__dfsan_retval_tls",
1525 ArgOriginTLSTy = ArrayType::get(OriginTy, NumOfElementsInArgOrgTLS);
1526 ArgOriginTLS = GetOrInsertGlobal(
"__dfsan_arg_origin_tls", ArgOriginTLSTy);
1527 RetvalOriginTLS = GetOrInsertGlobal(
"__dfsan_retval_origin_tls", OriginTy);
1529 (void)
Mod->getOrInsertGlobal(
"__dfsan_track_origins", OriginTy, [&] {
1535 "__dfsan_track_origins");
1538 initializeCallbackFunctions(M);
1539 initializeRuntimeFunctions(M);
1541 std::vector<Function *> FnsToInstrument;
1546 if (!
F.isIntrinsic() && !DFSanRuntimeFunctions.
contains(&
F) &&
1547 !LibAtomicFunction(
F) &&
1548 !
F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation)) {
1549 FnsToInstrument.push_back(&
F);
1550 if (
F.hasPersonalityFn())
1551 PersonalityFns.
insert(
F.getPersonalityFn()->stripPointerCasts());
1555 for (
auto *
C : PersonalityFns) {
1556 assert(isa<Function>(
C) &&
"Personality routine is not a function!");
1558 if (!isInstrumented(
F))
1572 bool GAInst = isInstrumented(&GA), FInst = isInstrumented(
F);
1573 if (GAInst && FInst) {
1574 addGlobalNameSuffix(&GA);
1575 }
else if (GAInst != FInst) {
1580 buildWrapperFunction(
F,
"", GA.
getLinkage(),
F->getFunctionType());
1584 FnsToInstrument.push_back(NewF);
1593 for (std::vector<Function *>::iterator FI = FnsToInstrument.begin(),
1594 FE = FnsToInstrument.end();
1599 bool IsZeroArgsVoidRet = (FT->getNumParams() == 0 && !FT->isVarArg() &&
1600 FT->getReturnType()->isVoidTy());
1602 if (isInstrumented(&
F)) {
1603 if (isForceZeroLabels(&
F))
1604 FnsWithForceZeroLabel.
insert(&
F);
1609 addGlobalNameSuffix(&
F);
1610 }
else if (!IsZeroArgsVoidRet || getWrapperKind(&
F) == WK_Custom) {
1618 F.hasLocalLinkage() ?
F.getLinkage()
1621 Function *NewF = buildWrapperFunction(
1623 (shouldTrackOrigins() ? std::string(
"dfso$") : std::string(
"dfsw$")) +
1624 std::string(
F.getName()),
1625 WrapperLinkage, FT);
1645 auto IsNotCmpUse = [](
Use &
U) ->
bool {
1646 User *Usr =
U.getUser();
1649 if (
CE->getOpcode() == Instruction::ICmp) {
1654 if (
I->getOpcode() == Instruction::ICmp) {
1660 F.replaceUsesWithIf(NewF, IsNotCmpUse);
1662 UnwrappedFnMap[NewF] = &
F;
1665 if (!
F.isDeclaration()) {
1675 size_t N = FI - FnsToInstrument.begin(),
1676 Count = FE - FnsToInstrument.begin();
1677 FnsToInstrument.push_back(&
F);
1678 FI = FnsToInstrument.begin() +
N;
1679 FE = FnsToInstrument.begin() + Count;
1683 }
else if (FT->isVarArg()) {
1684 UnwrappedFnMap[&
F] = &
F;
1690 if (!
F ||
F->isDeclaration())
1695 DFSanFunction DFSF(*
this,
F, FnsWithNativeABI.
count(
F),
1696 FnsWithForceZeroLabel.
count(
F), GetTLI(*
F));
1700 for (
auto &FArg :
F->args()) {
1702 Value *FArgShadow = DFSF.getShadow(&FArg);
1703 if (isZeroShadow(FArgShadow))
1705 if (
Instruction *FArgShadowInst = dyn_cast<Instruction>(FArgShadow)) {
1708 if (shouldTrackOrigins()) {
1710 dyn_cast<Instruction>(DFSF.getOrigin(&FArg))) {
1719 DFSF.addReachesFunctionCallbacksIfEnabled(IRB, *Next, &FArg);
1737 if (!DFSF.SkipInsts.count(Inst))
1738 DFSanVisitor(DFSF).visit(Inst);
1749 for (DFSanFunction::PHIFixupElement &
P : DFSF.PHIFixups) {
1750 for (
unsigned Val = 0,
N =
P.Phi->getNumIncomingValues(); Val !=
N;
1752 P.ShadowPhi->setIncomingValue(
1753 Val, DFSF.getShadow(
P.Phi->getIncomingValue(Val)));
1755 P.OriginPhi->setIncomingValue(
1756 Val, DFSF.getOrigin(
P.Phi->getIncomingValue(Val)));
1765 for (
Value *V : DFSF.NonZeroChecks) {
1768 Pos = std::next(
I->getIterator());
1770 Pos = DFSF.F->getEntryBlock().begin();
1771 while (isa<PHINode>(Pos) || isa<AllocaInst>(Pos))
1772 Pos = std::next(Pos->getIterator());
1774 Value *PrimitiveShadow = DFSF.collapseToPrimitiveShadow(V, Pos);
1776 IRB.
CreateICmpNE(PrimitiveShadow, DFSF.DFS.ZeroPrimitiveShadow);
1778 Ne, Pos,
false, ColdCallWeights));
1780 ThenIRB.CreateCall(DFSF.DFS.DFSanNonzeroLabelFn, {});
1785 return Changed || !FnsToInstrument.empty() ||
1786 M.global_size() != InitialGlobalSize ||
M.size() != InitialModuleSize;
1799 DFS.RetvalTLS, PointerType::get(DFS.getShadowTy(
T), 0),
"_dfsret");
1802Value *DFSanFunction::getRetvalOriginTLS() {
return DFS.RetvalOriginTLS; }
1806 ArgNo,
"_dfsarg_o");
1810 assert(DFS.shouldTrackOrigins());
1811 if (!isa<Argument>(V) && !isa<Instruction>(V))
1812 return DFS.ZeroOrigin;
1813 Value *&Origin = ValOriginMap[
V];
1815 if (
Argument *
A = dyn_cast<Argument>(V)) {
1817 return DFS.ZeroOrigin;
1818 if (
A->getArgNo() < DFS.NumOfElementsInArgOrgTLS) {
1819 Instruction *ArgOriginTLSPos = &*
F->getEntryBlock().begin();
1821 Value *ArgOriginPtr = getArgOriginTLS(
A->getArgNo(), IRB);
1822 Origin = IRB.
CreateLoad(DFS.OriginTy, ArgOriginPtr);
1825 Origin = DFS.ZeroOrigin;
1828 Origin = DFS.ZeroOrigin;
1835 if (!DFS.shouldTrackOrigins())
1839 ValOriginMap[
I] = Origin;
1843 unsigned ArgOffset = 0;
1845 for (
auto &FArg :
F->args()) {
1846 if (!FArg.getType()->isSized()) {
1852 unsigned Size =
DL.getTypeAllocSize(DFS.getShadowTy(&FArg));
1865 Value *ArgShadowPtr = getArgTLS(FArg.getType(), ArgOffset, IRB);
1870 return DFS.getZeroShadow(
A);
1874 if (!isa<Argument>(V) && !isa<Instruction>(V))
1875 return DFS.getZeroShadow(V);
1876 if (IsForceZeroLabels)
1877 return DFS.getZeroShadow(V);
1878 Value *&Shadow = ValShadowMap[
V];
1880 if (
Argument *
A = dyn_cast<Argument>(V)) {
1882 return DFS.getZeroShadow(V);
1883 Shadow = getShadowForTLSArgument(
A);
1884 NonZeroChecks.push_back(Shadow);
1886 Shadow = DFS.getZeroShadow(V);
1894 ValShadowMap[
I] = Shadow;
1902 assert(
Addr != RetvalTLS &&
"Reinstrumenting?");
1905 uint64_t AndMask = MapParams->AndMask;
1908 IRB.
CreateAnd(OffsetLong, ConstantInt::get(IntptrTy, ~AndMask));
1910 uint64_t XorMask = MapParams->XorMask;
1912 OffsetLong = IRB.
CreateXor(OffsetLong, ConstantInt::get(IntptrTy, XorMask));
1916std::pair<Value *, Value *>
1917DataFlowSanitizer::getShadowOriginAddress(
Value *
Addr,
Align InstAlignment,
1921 Value *ShadowOffset = getShadowOffset(
Addr, IRB);
1922 Value *ShadowLong = ShadowOffset;
1923 uint64_t ShadowBase = MapParams->ShadowBase;
1924 if (ShadowBase != 0) {
1926 IRB.
CreateAdd(ShadowLong, ConstantInt::get(IntptrTy, ShadowBase));
1931 Value *OriginPtr =
nullptr;
1932 if (shouldTrackOrigins()) {
1933 Value *OriginLong = ShadowOffset;
1934 uint64_t OriginBase = MapParams->OriginBase;
1935 if (OriginBase != 0)
1937 IRB.
CreateAdd(OriginLong, ConstantInt::get(IntptrTy, OriginBase));
1943 OriginLong = IRB.
CreateAnd(OriginLong, ConstantInt::get(IntptrTy, ~Mask));
1947 return std::make_pair(ShadowPtr, OriginPtr);
1952 Value *ShadowOffset) {
1960 Value *ShadowOffset = getShadowOffset(
Addr, IRB);
1961 return getShadowAddress(
Addr, Pos, ShadowOffset);
1966 Value *PrimitiveValue = combineShadows(V1, V2, Pos);
1967 return expandFromPrimitiveShadow(
T, PrimitiveValue, Pos);
1974 if (DFS.isZeroShadow(V1))
1975 return collapseToPrimitiveShadow(V2, Pos);
1976 if (DFS.isZeroShadow(V2))
1977 return collapseToPrimitiveShadow(V1, Pos);
1979 return collapseToPrimitiveShadow(V1, Pos);
1981 auto V1Elems = ShadowElements.
find(V1);
1982 auto V2Elems = ShadowElements.
find(V2);
1983 if (V1Elems != ShadowElements.
end() && V2Elems != ShadowElements.
end()) {
1984 if (std::includes(V1Elems->second.begin(), V1Elems->second.end(),
1985 V2Elems->second.begin(), V2Elems->second.end())) {
1986 return collapseToPrimitiveShadow(V1, Pos);
1988 if (std::includes(V2Elems->second.begin(), V2Elems->second.end(),
1989 V1Elems->second.begin(), V1Elems->second.end())) {
1990 return collapseToPrimitiveShadow(V2, Pos);
1992 }
else if (V1Elems != ShadowElements.
end()) {
1993 if (V1Elems->second.count(V2))
1994 return collapseToPrimitiveShadow(V1, Pos);
1995 }
else if (V2Elems != ShadowElements.
end()) {
1996 if (V2Elems->second.count(V1))
1997 return collapseToPrimitiveShadow(V2, Pos);
2000 auto Key = std::make_pair(V1, V2);
2003 CachedShadow &CCS = CachedShadows[
Key];
2004 if (CCS.Block && DT.
dominates(CCS.Block, Pos->getParent()))
2008 Value *PV1 = collapseToPrimitiveShadow(V1, Pos);
2009 Value *PV2 = collapseToPrimitiveShadow(V2, Pos);
2012 CCS.Block = Pos->getParent();
2013 CCS.Shadow = IRB.
CreateOr(PV1, PV2);
2015 std::set<Value *> UnionElems;
2016 if (V1Elems != ShadowElements.
end()) {
2017 UnionElems = V1Elems->second;
2019 UnionElems.insert(V1);
2021 if (V2Elems != ShadowElements.
end()) {
2022 UnionElems.insert(V2Elems->second.begin(), V2Elems->second.end());
2024 UnionElems.insert(V2);
2026 ShadowElements[CCS.Shadow] = std::move(UnionElems);
2036 return DFS.getZeroShadow(Inst);
2040 Shadow = combineShadows(Shadow, getShadow(Inst->
getOperand(
I)),
2043 return expandFromPrimitiveShadow(Inst->
getType(), Shadow,
2048 Value *CombinedShadow = DFSF.combineOperandShadows(&
I);
2049 DFSF.setShadow(&
I, CombinedShadow);
2050 visitInstOperandOrigins(
I);
2053Value *DFSanFunction::combineOrigins(
const std::vector<Value *> &Shadows,
2054 const std::vector<Value *> &Origins,
2057 assert(Shadows.size() == Origins.size());
2058 size_t Size = Origins.size();
2060 return DFS.ZeroOrigin;
2061 Value *Origin =
nullptr;
2063 Zero = DFS.ZeroPrimitiveShadow;
2064 for (
size_t I = 0;
I !=
Size; ++
I) {
2065 Value *OpOrigin = Origins[
I];
2066 Constant *ConstOpOrigin = dyn_cast<Constant>(OpOrigin);
2067 if (ConstOpOrigin && ConstOpOrigin->
isNullValue())
2073 Value *OpShadow = Shadows[
I];
2074 Value *PrimitiveShadow = collapseToPrimitiveShadow(OpShadow, Pos);
2079 return Origin ? Origin : DFS.ZeroOrigin;
2084 std::vector<Value *> Shadows(
Size);
2085 std::vector<Value *> Origins(
Size);
2086 for (
unsigned I = 0;
I !=
Size; ++
I) {
2090 return combineOrigins(Shadows, Origins, Inst->
getIterator());
2093void DFSanVisitor::visitInstOperandOrigins(
Instruction &
I) {
2094 if (!DFSF.DFS.shouldTrackOrigins())
2096 Value *CombinedOrigin = DFSF.combineOperandOrigins(&
I);
2097 DFSF.setOrigin(&
I, CombinedOrigin);
2100Align DFSanFunction::getShadowAlign(
Align InstAlignment) {
2102 return Align(Alignment.
value() * DFS.ShadowWidthBytes);
2105Align DFSanFunction::getOriginAlign(
Align InstAlignment) {
2110bool DFSanFunction::isLookupTableConstant(
Value *
P) {
2111 if (
GlobalVariable *GV = dyn_cast<GlobalVariable>(
P->stripPointerCasts()))
2112 if (GV->isConstant() && GV->
hasName())
2113 return DFS.CombineTaintLookupTableNames.count(GV->
getName());
2118bool DFSanFunction::useCallbackLoadLabelAndOrigin(
uint64_t Size,
2119 Align InstAlignment) {
2143 Value **OriginAddr) {
2146 IRB.
CreateGEP(OriginTy, *OriginAddr, ConstantInt::get(IntptrTy, 1));
2150std::pair<Value *, Value *> DFSanFunction::loadShadowFast(
2153 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins();
2154 const uint64_t ShadowSize =
Size * DFS.ShadowWidthBytes;
2156 assert(
Size >= 4 &&
"Not large enough load size for fast path!");
2159 std::vector<Value *> Shadows;
2160 std::vector<Value *> Origins;
2173 Type *WideShadowTy =
2177 Value *CombinedWideShadow =
2181 const uint64_t BytesPerWideShadow = WideShadowBitWidth / DFS.ShadowWidthBits;
2183 auto AppendWideShadowAndOrigin = [&](
Value *WideShadow,
Value *Origin) {
2184 if (BytesPerWideShadow > 4) {
2185 assert(BytesPerWideShadow == 8);
2193 WideShadow, ConstantInt::get(WideShadowTy, WideShadowBitWidth / 2));
2194 Shadows.push_back(WideShadow);
2195 Origins.push_back(DFS.loadNextOrigin(Pos, OriginAlign, &OriginAddr));
2197 Shadows.push_back(WideShadowLo);
2198 Origins.push_back(Origin);
2200 Shadows.push_back(WideShadow);
2201 Origins.push_back(Origin);
2205 if (ShouldTrackOrigins)
2206 AppendWideShadowAndOrigin(CombinedWideShadow, FirstOrigin);
2213 for (
uint64_t ByteOfs = BytesPerWideShadow; ByteOfs <
Size;
2214 ByteOfs += BytesPerWideShadow) {
2215 ShadowAddr = IRB.
CreateGEP(WideShadowTy, ShadowAddr,
2216 ConstantInt::get(DFS.IntptrTy, 1));
2217 Value *NextWideShadow =
2219 CombinedWideShadow = IRB.
CreateOr(CombinedWideShadow, NextWideShadow);
2220 if (ShouldTrackOrigins) {
2221 Value *NextOrigin = DFS.loadNextOrigin(Pos, OriginAlign, &OriginAddr);
2222 AppendWideShadowAndOrigin(NextWideShadow, NextOrigin);
2225 for (
unsigned Width = WideShadowBitWidth / 2; Width >= DFS.ShadowWidthBits;
2228 CombinedWideShadow = IRB.
CreateOr(CombinedWideShadow, ShrShadow);
2230 return {IRB.
CreateTrunc(CombinedWideShadow, DFS.PrimitiveShadowTy),
2232 ? combineOrigins(Shadows, Origins, Pos,
2237std::pair<Value *, Value *> DFSanFunction::loadShadowOriginSansLoadTracking(
2239 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins();
2243 const auto SI = AllocaShadowMap.
find(AI);
2244 if (SI != AllocaShadowMap.
end()) {
2247 const auto OI = AllocaOriginMap.
find(AI);
2248 assert(!ShouldTrackOrigins || OI != AllocaOriginMap.
end());
2249 return {ShadowLI, ShouldTrackOrigins
2258 bool AllConstants =
true;
2259 for (
const Value *Obj : Objs) {
2260 if (isa<Function>(Obj) || isa<BlockAddress>(Obj))
2262 if (isa<GlobalVariable>(Obj) && cast<GlobalVariable>(Obj)->
isConstant())
2265 AllConstants =
false;
2269 return {DFS.ZeroPrimitiveShadow,
2270 ShouldTrackOrigins ? DFS.ZeroOrigin :
nullptr};
2273 return {DFS.ZeroPrimitiveShadow,
2274 ShouldTrackOrigins ? DFS.ZeroOrigin :
nullptr};
2278 if (ShouldTrackOrigins &&
2279 useCallbackLoadLabelAndOrigin(
Size, InstAlignment)) {
2282 IRB.
CreateCall(DFS.DFSanLoadLabelAndOriginFn,
2283 {Addr, ConstantInt::get(DFS.IntptrTy, Size)});
2284 Call->addRetAttr(Attribute::ZExt);
2286 DFS.PrimitiveShadowTy),
2291 Value *ShadowAddr, *OriginAddr;
2292 std::tie(ShadowAddr, OriginAddr) =
2293 DFS.getShadowOriginAddress(
Addr, InstAlignment, Pos);
2295 const Align ShadowAlign = getShadowAlign(InstAlignment);
2296 const Align OriginAlign = getOriginAlign(InstAlignment);
2297 Value *Origin =
nullptr;
2298 if (ShouldTrackOrigins) {
2309 return {LI, Origin};
2313 Value *ShadowAddr1 = IRB.
CreateGEP(DFS.PrimitiveShadowTy, ShadowAddr,
2314 ConstantInt::get(DFS.IntptrTy, 1));
2319 return {combineShadows(Load, Load1, Pos), Origin};
2322 bool HasSizeForFastPath = DFS.hasLoadSizeForFastPath(
Size);
2324 if (HasSizeForFastPath)
2325 return loadShadowFast(ShadowAddr, OriginAddr,
Size, ShadowAlign,
2326 OriginAlign, Origin, Pos);
2330 DFS.DFSanUnionLoadFn, {ShadowAddr, ConstantInt::get(DFS.IntptrTy, Size)});
2332 return {FallbackCall, Origin};
2335std::pair<Value *, Value *>
2338 Value *PrimitiveShadow, *Origin;
2339 std::tie(PrimitiveShadow, Origin) =
2340 loadShadowOriginSansLoadTracking(
Addr,
Size, InstAlignment, Pos);
2341 if (DFS.shouldTrackOrigins()) {
2344 auto *ConstantShadow = dyn_cast<Constant>(PrimitiveShadow);
2345 if (!ConstantShadow || !ConstantShadow->isZeroValue())
2346 Origin = updateOriginIfTainted(PrimitiveShadow, Origin, IRB);
2349 return {PrimitiveShadow, Origin};
2354 case AtomicOrdering::NotAtomic:
2355 return AtomicOrdering::NotAtomic;
2356 case AtomicOrdering::Unordered:
2357 case AtomicOrdering::Monotonic:
2358 case AtomicOrdering::Acquire:
2359 return AtomicOrdering::Acquire;
2360 case AtomicOrdering::Release:
2361 case AtomicOrdering::AcquireRelease:
2362 return AtomicOrdering::AcquireRelease;
2363 case AtomicOrdering::SequentiallyConsistent:
2364 return AtomicOrdering::SequentiallyConsistent;
2370 if (!V->getType()->isPointerTy())
2378 if (
auto *
GEP = dyn_cast<GEPOperator>(V)) {
2379 V =
GEP->getPointerOperand();
2381 V = cast<Operator>(V)->getOperand(0);
2382 if (!V->getType()->isPointerTy())
2384 }
else if (isa<GlobalAlias>(V)) {
2385 V = cast<GlobalAlias>(V)->getAliasee();
2387 }
while (Visited.
insert(V).second);
2392void DFSanVisitor::visitLoadInst(
LoadInst &LI) {
2396 DFSF.setShadow(&LI, DFSF.DFS.getZeroShadow(&LI));
2397 DFSF.setOrigin(&LI, DFSF.DFS.ZeroOrigin);
2412 Pos = std::next(Pos);
2414 std::vector<Value *> Shadows;
2415 std::vector<Value *> Origins;
2416 Value *PrimitiveShadow, *Origin;
2417 std::tie(PrimitiveShadow, Origin) =
2419 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
2420 if (ShouldTrackOrigins) {
2421 Shadows.push_back(PrimitiveShadow);
2422 Origins.push_back(Origin);
2425 DFSF.isLookupTableConstant(
2428 PrimitiveShadow = DFSF.combineShadows(PrimitiveShadow, PtrShadow, Pos);
2429 if (ShouldTrackOrigins) {
2430 Shadows.push_back(PtrShadow);
2434 if (!DFSF.DFS.isZeroShadow(PrimitiveShadow))
2435 DFSF.NonZeroChecks.push_back(PrimitiveShadow);
2438 DFSF.expandFromPrimitiveShadow(LI.
getType(), PrimitiveShadow, Pos);
2439 DFSF.setShadow(&LI, Shadow);
2441 if (ShouldTrackOrigins) {
2442 DFSF.setOrigin(&LI, DFSF.combineOrigins(Shadows, Origins, Pos));
2449 IRB.
CreateCall(DFSF.DFS.DFSanLoadCallbackFn, {PrimitiveShadow, Addr});
2454 DFSF.addReachesFunctionCallbacksIfEnabled(IRB, LI, &LI);
2457Value *DFSanFunction::updateOriginIfTainted(
Value *Shadow,
Value *Origin,
2459 assert(DFS.shouldTrackOrigins());
2460 return IRB.
CreateCall(DFS.DFSanChainOriginIfTaintedFn, {Shadow, Origin});
2464 if (!DFS.shouldTrackOrigins())
2466 return IRB.
CreateCall(DFS.DFSanChainOriginFn, V);
2470 const unsigned OriginSize = DataFlowSanitizer::OriginWidthBytes;
2472 unsigned IntptrSize =
DL.getTypeStoreSize(DFS.IntptrTy);
2473 if (IntptrSize == OriginSize)
2475 assert(IntptrSize == OriginSize * 2);
2481 Value *StoreOriginAddr,
2483 const unsigned OriginSize = DataFlowSanitizer::OriginWidthBytes;
2485 const Align IntptrAlignment =
DL.getABITypeAlign(DFS.IntptrTy);
2486 unsigned IntptrSize =
DL.getTypeStoreSize(DFS.IntptrTy);
2488 assert(IntptrSize >= OriginSize);
2491 Align CurrentAlignment = Alignment;
2492 if (Alignment >= IntptrAlignment && IntptrSize > OriginSize) {
2493 Value *IntptrOrigin = originToIntptr(IRB, Origin);
2495 StoreOriginAddr, PointerType::get(DFS.IntptrTy, 0));
2496 for (
unsigned I = 0;
I < StoreOriginSize / IntptrSize; ++
I) {
2499 : IntptrStoreOriginPtr;
2501 Ofs += IntptrSize / OriginSize;
2502 CurrentAlignment = IntptrAlignment;
2506 for (
unsigned I = Ofs;
I < (StoreOriginSize + OriginSize - 1) / OriginSize;
2517 Type *VTy =
V->getType();
2527 Value *StoreOriginAddr,
Align InstAlignment) {
2530 const Align OriginAlignment = getOriginAlign(InstAlignment);
2531 Value *CollapsedShadow = collapseToPrimitiveShadow(Shadow, Pos);
2533 if (
auto *ConstantShadow = dyn_cast<Constant>(CollapsedShadow)) {
2534 if (!ConstantShadow->isZeroValue())
2535 paintOrigin(IRB, updateOrigin(Origin, IRB), StoreOriginAddr,
Size,
2540 if (shouldInstrumentWithCall()) {
2542 DFS.DFSanMaybeStoreOriginFn,
2543 {CollapsedShadow, Addr, ConstantInt::get(DFS.IntptrTy, Size), Origin});
2545 Value *
Cmp = convertToBool(CollapsedShadow, IRB,
"_dfscmp");
2548 Cmp, &*IRB.
GetInsertPoint(),
false, DFS.OriginStoreWeights, &DTU);
2550 paintOrigin(IRBNew, updateOrigin(Origin, IRBNew), StoreOriginAddr,
Size,
2562 Value *ExtZeroShadow = ConstantInt::get(ShadowTy, 0);
2563 Value *ShadowAddr = DFS.getShadowAddress(
Addr, Pos);
2570 Align InstAlignment,
2571 Value *PrimitiveShadow,
2574 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins() && Origin;
2577 const auto SI = AllocaShadowMap.
find(AI);
2578 if (SI != AllocaShadowMap.
end()) {
2584 if (ShouldTrackOrigins && !DFS.isZeroShadow(PrimitiveShadow)) {
2585 const auto OI = AllocaOriginMap.
find(AI);
2586 assert(OI != AllocaOriginMap.
end() && Origin);
2593 const Align ShadowAlign = getShadowAlign(InstAlignment);
2594 if (DFS.isZeroShadow(PrimitiveShadow)) {
2595 storeZeroPrimitiveShadow(
Addr,
Size, ShadowAlign, Pos);
2600 Value *ShadowAddr, *OriginAddr;
2601 std::tie(ShadowAddr, OriginAddr) =
2602 DFS.getShadowOriginAddress(
Addr, InstAlignment, Pos);
2604 const unsigned ShadowVecSize = 8;
2605 assert(ShadowVecSize * DFS.ShadowWidthBits <= 128 &&
2606 "Shadow vector is too large!");
2610 if (LeftSize >= ShadowVecSize) {
2614 for (
unsigned I = 0;
I != ShadowVecSize; ++
I) {
2616 ShadowVec, PrimitiveShadow,
2620 Value *CurShadowVecAddr =
2623 LeftSize -= ShadowVecSize;
2625 }
while (LeftSize >= ShadowVecSize);
2628 while (LeftSize > 0) {
2629 Value *CurShadowAddr =
2636 if (ShouldTrackOrigins) {
2637 storeOrigin(Pos,
Addr,
Size, PrimitiveShadow, Origin, OriginAddr,
2644 case AtomicOrdering::NotAtomic:
2645 return AtomicOrdering::NotAtomic;
2646 case AtomicOrdering::Unordered:
2647 case AtomicOrdering::Monotonic:
2648 case AtomicOrdering::Release:
2649 return AtomicOrdering::Release;
2650 case AtomicOrdering::Acquire:
2651 case AtomicOrdering::AcquireRelease:
2652 return AtomicOrdering::AcquireRelease;
2653 case AtomicOrdering::SequentiallyConsistent:
2654 return AtomicOrdering::SequentiallyConsistent;
2659void DFSanVisitor::visitStoreInst(
StoreInst &SI) {
2660 auto &
DL =
SI.getDataLayout();
2661 Value *Val =
SI.getValueOperand();
2674 const bool ShouldTrackOrigins =
2675 DFSF.DFS.shouldTrackOrigins() && !
SI.isAtomic();
2676 std::vector<Value *> Shadows;
2677 std::vector<Value *> Origins;
2680 SI.isAtomic() ? DFSF.DFS.getZeroShadow(Val) : DFSF.getShadow(Val);
2682 if (ShouldTrackOrigins) {
2683 Shadows.push_back(Shadow);
2684 Origins.push_back(DFSF.getOrigin(Val));
2687 Value *PrimitiveShadow;
2689 Value *PtrShadow = DFSF.getShadow(
SI.getPointerOperand());
2690 if (ShouldTrackOrigins) {
2691 Shadows.push_back(PtrShadow);
2692 Origins.push_back(DFSF.getOrigin(
SI.getPointerOperand()));
2694 PrimitiveShadow = DFSF.combineShadows(Shadow, PtrShadow,
SI.getIterator());
2696 PrimitiveShadow = DFSF.collapseToPrimitiveShadow(Shadow,
SI.getIterator());
2698 Value *Origin =
nullptr;
2699 if (ShouldTrackOrigins)
2700 Origin = DFSF.combineOrigins(Shadows, Origins,
SI.getIterator());
2701 DFSF.storePrimitiveShadowOrigin(
SI.getPointerOperand(),
Size,
SI.getAlign(),
2702 PrimitiveShadow, Origin,
SI.getIterator());
2707 IRB.
CreateCall(DFSF.DFS.DFSanStoreCallbackFn, {PrimitiveShadow, Addr});
2713 assert(isa<AtomicRMWInst>(
I) || isa<AtomicCmpXchgInst>(
I));
2715 Value *Val =
I.getOperand(1);
2716 const auto &
DL =
I.getDataLayout();
2725 const Align ShadowAlign = DFSF.getShadowAlign(InstAlignment);
2726 DFSF.storeZeroPrimitiveShadow(
Addr,
Size, ShadowAlign,
I.getIterator());
2727 DFSF.setShadow(&
I, DFSF.DFS.getZeroShadow(&
I));
2728 DFSF.setOrigin(&
I, DFSF.DFS.ZeroOrigin);
2732 visitCASOrRMW(
I.getAlign(),
I);
2739 visitCASOrRMW(
I.getAlign(),
I);
2746 visitInstOperands(UO);
2750 visitInstOperands(BO);
2753void DFSanVisitor::visitBitCastInst(
BitCastInst &BCI) {
2757 if (
auto *CI = dyn_cast<CallInst>(BCI.
getOperand(0)))
2760 visitInstOperands(BCI);
2763void DFSanVisitor::visitCastInst(
CastInst &CI) { visitInstOperands(CI); }
2765void DFSanVisitor::visitCmpInst(
CmpInst &CI) {
2766 visitInstOperands(CI);
2769 Value *CombinedShadow = DFSF.getShadow(&CI);
2771 IRB.
CreateCall(DFSF.DFS.DFSanCmpCallbackFn, CombinedShadow);
2788 DFSF.setShadow(&LPI, DFSF.DFS.getZeroShadow(&LPI));
2789 DFSF.setOrigin(&LPI, DFSF.DFS.ZeroOrigin);
2794 DFSF.isLookupTableConstant(
2796 visitInstOperands(GEPI);
2803 DFSF.setShadow(&GEPI, DFSF.getShadow(BasePointer));
2804 if (DFSF.DFS.shouldTrackOrigins())
2805 DFSF.setOrigin(&GEPI, DFSF.getOrigin(BasePointer));
2809 visitInstOperands(
I);
2813 visitInstOperands(
I);
2817 visitInstOperands(
I);
2822 Value *Agg =
I.getAggregateOperand();
2823 Value *AggShadow = DFSF.getShadow(Agg);
2825 DFSF.setShadow(&
I, ResShadow);
2826 visitInstOperandOrigins(
I);
2831 Value *AggShadow = DFSF.getShadow(
I.getAggregateOperand());
2832 Value *InsShadow = DFSF.getShadow(
I.getInsertedValueOperand());
2834 DFSF.setShadow(&
I, Res);
2835 visitInstOperandOrigins(
I);
2838void DFSanVisitor::visitAllocaInst(
AllocaInst &
I) {
2839 bool AllLoadsStores =
true;
2840 for (
User *U :
I.users()) {
2841 if (isa<LoadInst>(U))
2844 if (
StoreInst *SI = dyn_cast<StoreInst>(U)) {
2845 if (
SI->getPointerOperand() == &
I)
2849 AllLoadsStores =
false;
2852 if (AllLoadsStores) {
2854 DFSF.AllocaShadowMap[&
I] = IRB.
CreateAlloca(DFSF.DFS.PrimitiveShadowTy);
2855 if (DFSF.DFS.shouldTrackOrigins()) {
2856 DFSF.AllocaOriginMap[&
I] =
2860 DFSF.setShadow(&
I, DFSF.DFS.ZeroPrimitiveShadow);
2861 DFSF.setOrigin(&
I, DFSF.DFS.ZeroOrigin);
2864void DFSanVisitor::visitSelectInst(
SelectInst &
I) {
2865 Value *CondShadow = DFSF.getShadow(
I.getCondition());
2866 Value *TrueShadow = DFSF.getShadow(
I.getTrueValue());
2867 Value *FalseShadow = DFSF.getShadow(
I.getFalseValue());
2868 Value *ShadowSel =
nullptr;
2869 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
2870 std::vector<Value *> Shadows;
2871 std::vector<Value *> Origins;
2873 ShouldTrackOrigins ? DFSF.getOrigin(
I.getTrueValue()) :
nullptr;
2874 Value *FalseOrigin =
2875 ShouldTrackOrigins ? DFSF.getOrigin(
I.getFalseValue()) :
nullptr;
2877 DFSF.addConditionalCallbacksIfEnabled(
I,
I.getCondition());
2879 if (isa<VectorType>(
I.getCondition()->getType())) {
2880 ShadowSel = DFSF.combineShadowsThenConvert(
I.getType(), TrueShadow,
2881 FalseShadow,
I.getIterator());
2882 if (ShouldTrackOrigins) {
2883 Shadows.push_back(TrueShadow);
2884 Shadows.push_back(FalseShadow);
2885 Origins.push_back(TrueOrigin);
2886 Origins.push_back(FalseOrigin);
2889 if (TrueShadow == FalseShadow) {
2890 ShadowSel = TrueShadow;
2891 if (ShouldTrackOrigins) {
2892 Shadows.push_back(TrueShadow);
2893 Origins.push_back(TrueOrigin);
2897 "",
I.getIterator());
2898 if (ShouldTrackOrigins) {
2899 Shadows.push_back(ShadowSel);
2901 FalseOrigin,
"",
I.getIterator()));
2906 I.getType(), CondShadow,
2907 ShadowSel,
I.getIterator())
2909 if (ShouldTrackOrigins) {
2911 Shadows.push_back(CondShadow);
2912 Origins.push_back(DFSF.getOrigin(
I.getCondition()));
2914 DFSF.setOrigin(&
I, DFSF.combineOrigins(Shadows, Origins,
I.getIterator()));
2918void DFSanVisitor::visitMemSetInst(
MemSetInst &
I) {
2920 Value *ValShadow = DFSF.getShadow(
I.getValue());
2921 Value *ValOrigin = DFSF.DFS.shouldTrackOrigins()
2922 ? DFSF.getOrigin(
I.getValue())
2923 : DFSF.DFS.ZeroOrigin;
2925 {ValShadow, ValOrigin, I.getDest(),
2926 IRB.CreateZExtOrTrunc(I.getLength(), DFSF.DFS.IntptrTy)});
2934 if (DFSF.DFS.shouldTrackOrigins()) {
2936 DFSF.DFS.DFSanMemOriginTransferFn,
2937 {I.getArgOperand(0), I.getArgOperand(1),
2938 IRB.CreateIntCast(I.getArgOperand(2), DFSF.DFS.IntptrTy, false)});
2941 Value *DestShadow = DFSF.DFS.getShadowAddress(
I.getDest(),
I.getIterator());
2942 Value *SrcShadow = DFSF.DFS.getShadowAddress(
I.getSource(),
I.getIterator());
2944 IRB.
CreateMul(
I.getLength(), ConstantInt::get(
I.getLength()->getType(),
2945 DFSF.DFS.ShadowWidthBytes));
2946 auto *MTI = cast<MemTransferInst>(
2947 IRB.
CreateCall(
I.getFunctionType(),
I.getCalledOperand(),
2948 {DestShadow, SrcShadow, LenShadow, I.getVolatileCst()}));
2949 MTI->setDestAlignment(DFSF.getShadowAlign(
I.getDestAlign().valueOrOne()));
2950 MTI->setSourceAlignment(DFSF.getShadowAlign(
I.getSourceAlign().valueOrOne()));
2953 DFSF.DFS.DFSanMemTransferCallbackFn,
2954 {DestShadow, IRB.CreateZExtOrTrunc(I.getLength(), DFSF.DFS.IntptrTy)});
2958void DFSanVisitor::visitBranchInst(
BranchInst &BR) {
2959 if (!
BR.isConditional())
2962 DFSF.addConditionalCallbacksIfEnabled(BR,
BR.getCondition());
2965void DFSanVisitor::visitSwitchInst(
SwitchInst &SW) {
2966 DFSF.addConditionalCallbacksIfEnabled(SW, SW.
getCondition());
2971 if (
auto *
I = dyn_cast<BitCastInst>(RetVal)) {
2972 RetVal =
I->getOperand(0);
2974 if (
auto *
I = dyn_cast<CallInst>(RetVal)) {
2975 return I->isMustTailCall();
2980void DFSanVisitor::visitReturnInst(
ReturnInst &RI) {
2988 Type *RT = DFSF.F->getFunctionType()->getReturnType();
2989 unsigned Size = getDataLayout().getTypeAllocSize(DFSF.DFS.getShadowTy(RT));
2995 if (DFSF.DFS.shouldTrackOrigins()) {
3003 std::vector<Value *> &Args,
3010 for (
unsigned N = FT->getNumParams();
N != 0; ++
I, --
N)
3012 DFSF.collapseToPrimitiveShadow(DFSF.getShadow(*
I), CB.
getIterator()));
3015 if (FT->isVarArg()) {
3016 auto *LabelVATy = ArrayType::get(DFSF.DFS.PrimitiveShadowTy,
3017 CB.
arg_size() - FT->getNumParams());
3018 auto *LabelVAAlloca =
3019 new AllocaInst(LabelVATy, getDataLayout().getAllocaAddrSpace(),
3020 "labelva", DFSF.F->getEntryBlock().begin());
3022 for (
unsigned N = 0;
I != CB.
arg_end(); ++
I, ++
N) {
3025 DFSF.collapseToPrimitiveShadow(DFSF.getShadow(*
I), CB.
getIterator()),
3033 if (!FT->getReturnType()->isVoidTy()) {
3034 if (!DFSF.LabelReturnAlloca) {
3036 DFSF.DFS.PrimitiveShadowTy, getDataLayout().getAllocaAddrSpace(),
3037 "labelreturn", DFSF.F->getEntryBlock().begin());
3039 Args.push_back(DFSF.LabelReturnAlloca);
3044 std::vector<Value *> &Args,
3051 for (
unsigned N = FT->getNumParams();
N != 0; ++
I, --
N)
3052 Args.push_back(DFSF.getOrigin(*
I));
3055 if (FT->isVarArg()) {
3057 ArrayType::get(DFSF.DFS.OriginTy, CB.
arg_size() - FT->getNumParams());
3058 auto *OriginVAAlloca =
3059 new AllocaInst(OriginVATy, getDataLayout().getAllocaAddrSpace(),
3060 "originva", DFSF.F->getEntryBlock().begin());
3062 for (
unsigned N = 0;
I != CB.
arg_end(); ++
I, ++
N) {
3071 if (!FT->getReturnType()->isVoidTy()) {
3072 if (!DFSF.OriginReturnAlloca) {
3074 DFSF.DFS.OriginTy, getDataLayout().getAllocaAddrSpace(),
3075 "originreturn", DFSF.F->getEntryBlock().begin());
3077 Args.push_back(DFSF.OriginReturnAlloca);
3083 switch (DFSF.DFS.getWrapperKind(&
F)) {
3084 case DataFlowSanitizer::WK_Warning:
3086 IRB.
CreateCall(DFSF.DFS.DFSanUnimplementedFn,
3088 DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &
F);
3089 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3090 DFSF.setOrigin(&CB, DFSF.DFS.ZeroOrigin);
3092 case DataFlowSanitizer::WK_Discard:
3094 DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &
F);
3095 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3096 DFSF.setOrigin(&CB, DFSF.DFS.ZeroOrigin);
3098 case DataFlowSanitizer::WK_Functional:
3100 DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &
F);
3101 visitInstOperands(CB);
3103 case DataFlowSanitizer::WK_Custom:
3107 CallInst *CI = dyn_cast<CallInst>(&CB);
3111 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
3113 TransformedFunction CustomFn = DFSF.DFS.getCustomFunctionType(FT);
3114 std::string CustomFName = ShouldTrackOrigins ?
"__dfso_" :
"__dfsw_";
3115 CustomFName +=
F.getName();
3117 CustomFName, CustomFn.TransformedType);
3119 CustomFn->copyAttributesFrom(&
F);
3122 if (!FT->getReturnType()->isVoidTy()) {
3123 CustomFn->removeFnAttrs(DFSF.DFS.ReadOnlyNoneAttrs);
3127 std::vector<Value *>
Args;
3131 for (
unsigned N = FT->getNumParams();
N != 0; ++
I, --
N) {
3136 const unsigned ShadowArgStart =
Args.size();
3137 addShadowArguments(
F, CB, Args, IRB);
3140 const unsigned OriginArgStart =
Args.size();
3141 if (ShouldTrackOrigins)
3142 addOriginArguments(
F, CB, Args, IRB);
3155 for (
unsigned N = 0;
N < FT->getNumParams();
N++) {
3156 const unsigned ArgNo = ShadowArgStart +
N;
3158 DFSF.DFS.PrimitiveShadowTy)
3160 if (ShouldTrackOrigins) {
3161 const unsigned OriginArgNo = OriginArgStart +
N;
3169 if (!FT->getReturnType()->isVoidTy()) {
3171 IRB.
CreateLoad(DFSF.DFS.PrimitiveShadowTy, DFSF.LabelReturnAlloca);
3172 DFSF.setShadow(CustomCI,
3173 DFSF.expandFromPrimitiveShadow(
3174 FT->getReturnType(), LabelLoad, CB.
getIterator()));
3175 if (ShouldTrackOrigins) {
3177 IRB.
CreateLoad(DFSF.DFS.OriginTy, DFSF.OriginReturnAlloca);
3178 DFSF.setOrigin(CustomCI, OriginLoad);
3190 constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
3191 uint32_t OrderingTable[NumOrderings] = {};
3193 OrderingTable[(int)AtomicOrderingCABI::relaxed] =
3194 OrderingTable[(
int)AtomicOrderingCABI::acquire] =
3195 OrderingTable[(int)AtomicOrderingCABI::consume] =
3196 (
int)AtomicOrderingCABI::acquire;
3197 OrderingTable[(int)AtomicOrderingCABI::release] =
3198 OrderingTable[(
int)AtomicOrderingCABI::acq_rel] =
3199 (int)AtomicOrderingCABI::acq_rel;
3200 OrderingTable[(int)AtomicOrderingCABI::seq_cst] =
3201 (
int)AtomicOrderingCABI::seq_cst;
3206void DFSanVisitor::visitLibAtomicLoad(
CallBase &CB) {
3208 assert(isa<CallInst>(CB));
3217 Value *NewOrdering =
3222 NextIRB.SetCurrentDebugLocation(CB.
getDebugLoc());
3228 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3229 {DstPtr, SrcPtr, NextIRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3233 constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
3234 uint32_t OrderingTable[NumOrderings] = {};
3236 OrderingTable[(int)AtomicOrderingCABI::relaxed] =
3237 OrderingTable[(
int)AtomicOrderingCABI::release] =
3238 (int)AtomicOrderingCABI::release;
3239 OrderingTable[(int)AtomicOrderingCABI::consume] =
3240 OrderingTable[(
int)AtomicOrderingCABI::acquire] =
3241 OrderingTable[(int)AtomicOrderingCABI::acq_rel] =
3242 (
int)AtomicOrderingCABI::acq_rel;
3243 OrderingTable[(int)AtomicOrderingCABI::seq_cst] =
3244 (
int)AtomicOrderingCABI::seq_cst;
3249void DFSanVisitor::visitLibAtomicStore(
CallBase &CB) {
3257 Value *NewOrdering =
3265 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3266 {DstPtr, SrcPtr, IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3269void DFSanVisitor::visitLibAtomicExchange(
CallBase &CB) {
3285 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3286 {DstPtr, TargetPtr, IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3290 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3291 {TargetPtr, SrcPtr, IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3294void DFSanVisitor::visitLibAtomicCompareExchange(
CallBase &CB) {
3308 NextIRB.SetCurrentDebugLocation(CB.
getDebugLoc());
3310 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3314 NextIRB.CreateCall(DFSF.DFS.DFSanMemShadowOriginConditionalExchangeFn,
3315 {NextIRB.CreateIntCast(&CB, NextIRB.getInt8Ty(), false),
3316 TargetPtr, ExpectedPtr, DesiredPtr,
3317 NextIRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3320void DFSanVisitor::visitCallBase(
CallBase &CB) {
3323 visitInstOperands(CB);
3329 if (
F == DFSF.DFS.DFSanVarargWrapperFn.getCallee()->stripPointerCasts())
3333 if (DFSF.TLI.getLibFunc(CB, LF)) {
3338 case LibFunc_atomic_load:
3339 if (!isa<CallInst>(CB)) {
3340 llvm::errs() <<
"DFSAN -- cannot instrument invoke of libatomic load. "
3344 visitLibAtomicLoad(CB);
3346 case LibFunc_atomic_store:
3347 visitLibAtomicStore(CB);
3355 if (
F &&
F->hasName() && !
F->isVarArg()) {
3356 if (
F->getName() ==
"__atomic_exchange") {
3357 visitLibAtomicExchange(CB);
3360 if (
F->getName() ==
"__atomic_compare_exchange") {
3361 visitLibAtomicCompareExchange(CB);
3368 if (UnwrappedFnIt != DFSF.DFS.UnwrappedFnMap.end())
3369 if (visitWrappedCallBase(*UnwrappedFnIt->second, CB))
3374 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
3379 unsigned ArgOffset = 0;
3380 for (
unsigned I = 0,
N = FT->getNumParams();
I !=
N; ++
I) {
3381 if (ShouldTrackOrigins) {
3384 if (
I < DFSF.DFS.NumOfElementsInArgOrgTLS &&
3385 !DFSF.DFS.isZeroShadow(ArgShadow))
3387 DFSF.getArgOriginTLS(
I, IRB));
3391 DL.getTypeAllocSize(DFSF.DFS.getShadowTy(FT->getParamType(
I)));
3397 DFSF.getArgTLS(FT->getParamType(
I), ArgOffset, IRB),
3405 if (
II->getNormalDest()->getSinglePredecessor()) {
3406 Next = &
II->getNormalDest()->front();
3410 Next = &NewBB->
front();
3418 if (isa<CallInst>(CB) && cast<CallInst>(CB).isMustTailCall())
3423 unsigned Size =
DL.getTypeAllocSize(DFSF.DFS.getShadowTy(&CB));
3426 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3428 LoadInst *LI = NextIRB.CreateAlignedLoad(
3429 DFSF.DFS.getShadowTy(&CB), DFSF.getRetvalTLS(CB.
getType(), NextIRB),
3431 DFSF.SkipInsts.insert(LI);
3432 DFSF.setShadow(&CB, LI);
3433 DFSF.NonZeroChecks.push_back(LI);
3436 if (ShouldTrackOrigins) {
3437 LoadInst *LI = NextIRB.CreateLoad(DFSF.DFS.OriginTy,
3438 DFSF.getRetvalOriginTLS(),
"_dfsret_o");
3439 DFSF.SkipInsts.insert(LI);
3440 DFSF.setOrigin(&CB, LI);
3443 DFSF.addReachesFunctionCallbacksIfEnabled(NextIRB, CB, &CB);
3447void DFSanVisitor::visitPHINode(
PHINode &PN) {
3448 Type *ShadowTy = DFSF.DFS.getShadowTy(&PN);
3457 DFSF.setShadow(&PN, ShadowPN);
3460 if (DFSF.DFS.shouldTrackOrigins()) {
3466 DFSF.setOrigin(&PN, OriginPN);
3469 DFSF.PHIFixups.push_back({&PN, ShadowPN, OriginPN});
3482 if (!DataFlowSanitizer(ABIListFiles).runImpl(M, GetTLI))
static bool isConstant(const MachineInstr &MI)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
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")
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.
This header defines various interfaces for pass management in LLVM.
uint64_t IntrinsicInst * II
if(auto Err=PB.parsePassPipeline(MPM, Passes)) return wrap(std MPM run * Mod
FunctionAnalysisManager FAM
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 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 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="", InsertPosition InsertBefore=nullptr)
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)
AttributeList getAttributes() const
Return the attribute list for this Function.
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 * 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)
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)
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 * CreateGEP(Type *Ty, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
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="")
Value * CreateConstInBoundsGEP2_64(Type *Ty, Value *Ptr, uint64_t Idx0, uint64_t Idx1, 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)
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateTrunc(Value *V, Type *DestTy, const Twine &Name="", bool IsNUW=false, bool IsNSW=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)
Value * CreateXor(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateMul(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
GlobalVariable * CreateGlobalString(StringRef Str, const Twine &Name="", unsigned AddressSpace=0, Module *M=nullptr, bool AddNull=true)
Make a new global variable with initializer type i8*.
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.
bool isAtomic() const LLVM_READONLY
Return true if this instruction has an AtomicOrdering of unordered or higher.
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.
const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
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 * createUnlikelyBranchWeights()
Return metadata containing two branch weights, with significant bias towards false destination.
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.
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
unsigned getNumIncomingValues() const
Return the number of incoming edges.
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
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, InsertPosition InsertBefore=nullptr)
This class represents the LLVM 'select' instruction.
static SelectInst * Create(Value *C, Value *S1, Value *S2, const Twine &NameStr="", InsertPosition InsertBefore=nullptr, Instruction *MDFrom=nullptr)
This instruction constructs a fixed permutation of two input vectors.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
static std::unique_ptr< SpecialCaseList > createOrDie(const std::vector< std::string > &Paths, llvm::vfs::FileSystem &FS)
Parses the special case list entries from files.
An instruction for storing to memory.
StringRef - Represent a constant reference to a string, i.e.
StringSet - A wrapper for StringMap that provides set-like functionality.
std::pair< typename Base::iterator, bool > insert(StringRef key)
Class to represent struct types.
static StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
Value * getCondition() const
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
Triple - Helper class for working with autoconf configuration names.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
unsigned getIntegerBitWidth() const
static Type * getVoidTy(LLVMContext &C)
bool isSized(SmallPtrSetImpl< Type * > *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
static 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.
const ParentTy * getParent() const
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, AttributeSet AS, 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.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
void getUnderlyingObjects(const Value *V, SmallVectorImpl< const Value * > &Objects, const LoopInfo *LI=nullptr, unsigned MaxLookup=6)
This method is similar to getUnderlyingObject except that it can look through phi and select instruct...
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.
bool checkIfAlreadyInstrumented(Module &M, StringRef Flag)
Check if module has flag attached, if not add the flag.
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.