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;
1801Value *DFSanFunction::getRetvalOriginTLS() {
return DFS.RetvalOriginTLS; }
1805 ArgNo,
"_dfsarg_o");
1809 assert(DFS.shouldTrackOrigins());
1810 if (!isa<Argument>(V) && !isa<Instruction>(V))
1811 return DFS.ZeroOrigin;
1812 Value *&Origin = ValOriginMap[
V];
1814 if (
Argument *
A = dyn_cast<Argument>(V)) {
1816 return DFS.ZeroOrigin;
1817 if (
A->getArgNo() < DFS.NumOfElementsInArgOrgTLS) {
1818 Instruction *ArgOriginTLSPos = &*
F->getEntryBlock().begin();
1820 Value *ArgOriginPtr = getArgOriginTLS(
A->getArgNo(), IRB);
1821 Origin = IRB.
CreateLoad(DFS.OriginTy, ArgOriginPtr);
1824 Origin = DFS.ZeroOrigin;
1827 Origin = DFS.ZeroOrigin;
1834 if (!DFS.shouldTrackOrigins())
1838 ValOriginMap[
I] = Origin;
1842 unsigned ArgOffset = 0;
1844 for (
auto &FArg :
F->args()) {
1845 if (!FArg.getType()->isSized()) {
1851 unsigned Size =
DL.getTypeAllocSize(DFS.getShadowTy(&FArg));
1864 Value *ArgShadowPtr = getArgTLS(FArg.getType(), ArgOffset, IRB);
1869 return DFS.getZeroShadow(
A);
1873 if (!isa<Argument>(V) && !isa<Instruction>(V))
1874 return DFS.getZeroShadow(V);
1875 if (IsForceZeroLabels)
1876 return DFS.getZeroShadow(V);
1877 Value *&Shadow = ValShadowMap[
V];
1879 if (
Argument *
A = dyn_cast<Argument>(V)) {
1881 return DFS.getZeroShadow(V);
1882 Shadow = getShadowForTLSArgument(
A);
1883 NonZeroChecks.push_back(Shadow);
1885 Shadow = DFS.getZeroShadow(V);
1893 ValShadowMap[
I] = Shadow;
1901 assert(
Addr != RetvalTLS &&
"Reinstrumenting?");
1904 uint64_t AndMask = MapParams->AndMask;
1907 IRB.
CreateAnd(OffsetLong, ConstantInt::get(IntptrTy, ~AndMask));
1909 uint64_t XorMask = MapParams->XorMask;
1911 OffsetLong = IRB.
CreateXor(OffsetLong, ConstantInt::get(IntptrTy, XorMask));
1915std::pair<Value *, Value *>
1916DataFlowSanitizer::getShadowOriginAddress(
Value *
Addr,
Align InstAlignment,
1920 Value *ShadowOffset = getShadowOffset(
Addr, IRB);
1921 Value *ShadowLong = ShadowOffset;
1922 uint64_t ShadowBase = MapParams->ShadowBase;
1923 if (ShadowBase != 0) {
1925 IRB.
CreateAdd(ShadowLong, ConstantInt::get(IntptrTy, ShadowBase));
1928 Value *OriginPtr =
nullptr;
1929 if (shouldTrackOrigins()) {
1930 Value *OriginLong = ShadowOffset;
1931 uint64_t OriginBase = MapParams->OriginBase;
1932 if (OriginBase != 0)
1934 IRB.
CreateAdd(OriginLong, ConstantInt::get(IntptrTy, OriginBase));
1940 OriginLong = IRB.
CreateAnd(OriginLong, ConstantInt::get(IntptrTy, ~Mask));
1944 return std::make_pair(ShadowPtr, OriginPtr);
1949 Value *ShadowOffset) {
1957 Value *ShadowOffset = getShadowOffset(
Addr, IRB);
1958 return getShadowAddress(
Addr, Pos, ShadowOffset);
1963 Value *PrimitiveValue = combineShadows(V1, V2, Pos);
1964 return expandFromPrimitiveShadow(
T, PrimitiveValue, Pos);
1971 if (DFS.isZeroShadow(V1))
1972 return collapseToPrimitiveShadow(V2, Pos);
1973 if (DFS.isZeroShadow(V2))
1974 return collapseToPrimitiveShadow(V1, Pos);
1976 return collapseToPrimitiveShadow(V1, Pos);
1978 auto V1Elems = ShadowElements.
find(V1);
1979 auto V2Elems = ShadowElements.
find(V2);
1980 if (V1Elems != ShadowElements.
end() && V2Elems != ShadowElements.
end()) {
1981 if (std::includes(V1Elems->second.begin(), V1Elems->second.end(),
1982 V2Elems->second.begin(), V2Elems->second.end())) {
1983 return collapseToPrimitiveShadow(V1, Pos);
1985 if (std::includes(V2Elems->second.begin(), V2Elems->second.end(),
1986 V1Elems->second.begin(), V1Elems->second.end())) {
1987 return collapseToPrimitiveShadow(V2, Pos);
1989 }
else if (V1Elems != ShadowElements.
end()) {
1990 if (V1Elems->second.count(V2))
1991 return collapseToPrimitiveShadow(V1, Pos);
1992 }
else if (V2Elems != ShadowElements.
end()) {
1993 if (V2Elems->second.count(V1))
1994 return collapseToPrimitiveShadow(V2, Pos);
1997 auto Key = std::make_pair(V1, V2);
2000 CachedShadow &CCS = CachedShadows[
Key];
2001 if (CCS.Block && DT.
dominates(CCS.Block, Pos->getParent()))
2005 Value *PV1 = collapseToPrimitiveShadow(V1, Pos);
2006 Value *PV2 = collapseToPrimitiveShadow(V2, Pos);
2009 CCS.Block = Pos->getParent();
2010 CCS.Shadow = IRB.
CreateOr(PV1, PV2);
2012 std::set<Value *> UnionElems;
2013 if (V1Elems != ShadowElements.
end()) {
2014 UnionElems = V1Elems->second;
2016 UnionElems.insert(V1);
2018 if (V2Elems != ShadowElements.
end()) {
2019 UnionElems.insert(V2Elems->second.begin(), V2Elems->second.end());
2021 UnionElems.insert(V2);
2023 ShadowElements[CCS.Shadow] = std::move(UnionElems);
2033 return DFS.getZeroShadow(Inst);
2037 Shadow = combineShadows(Shadow, getShadow(Inst->
getOperand(
I)),
2040 return expandFromPrimitiveShadow(Inst->
getType(), Shadow,
2045 Value *CombinedShadow = DFSF.combineOperandShadows(&
I);
2046 DFSF.setShadow(&
I, CombinedShadow);
2047 visitInstOperandOrigins(
I);
2050Value *DFSanFunction::combineOrigins(
const std::vector<Value *> &Shadows,
2051 const std::vector<Value *> &Origins,
2054 assert(Shadows.size() == Origins.size());
2055 size_t Size = Origins.size();
2057 return DFS.ZeroOrigin;
2058 Value *Origin =
nullptr;
2060 Zero = DFS.ZeroPrimitiveShadow;
2061 for (
size_t I = 0;
I !=
Size; ++
I) {
2062 Value *OpOrigin = Origins[
I];
2063 Constant *ConstOpOrigin = dyn_cast<Constant>(OpOrigin);
2064 if (ConstOpOrigin && ConstOpOrigin->
isNullValue())
2070 Value *OpShadow = Shadows[
I];
2071 Value *PrimitiveShadow = collapseToPrimitiveShadow(OpShadow, Pos);
2076 return Origin ? Origin : DFS.ZeroOrigin;
2081 std::vector<Value *> Shadows(
Size);
2082 std::vector<Value *> Origins(
Size);
2083 for (
unsigned I = 0;
I !=
Size; ++
I) {
2087 return combineOrigins(Shadows, Origins, Inst->
getIterator());
2090void DFSanVisitor::visitInstOperandOrigins(
Instruction &
I) {
2091 if (!DFSF.DFS.shouldTrackOrigins())
2093 Value *CombinedOrigin = DFSF.combineOperandOrigins(&
I);
2094 DFSF.setOrigin(&
I, CombinedOrigin);
2097Align DFSanFunction::getShadowAlign(
Align InstAlignment) {
2099 return Align(Alignment.
value() * DFS.ShadowWidthBytes);
2102Align DFSanFunction::getOriginAlign(
Align InstAlignment) {
2107bool DFSanFunction::isLookupTableConstant(
Value *
P) {
2108 if (
GlobalVariable *GV = dyn_cast<GlobalVariable>(
P->stripPointerCasts()))
2109 if (GV->isConstant() && GV->
hasName())
2110 return DFS.CombineTaintLookupTableNames.count(GV->
getName());
2115bool DFSanFunction::useCallbackLoadLabelAndOrigin(
uint64_t Size,
2116 Align InstAlignment) {
2140 Value **OriginAddr) {
2143 IRB.
CreateGEP(OriginTy, *OriginAddr, ConstantInt::get(IntptrTy, 1));
2147std::pair<Value *, Value *> DFSanFunction::loadShadowFast(
2150 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins();
2151 const uint64_t ShadowSize =
Size * DFS.ShadowWidthBytes;
2153 assert(
Size >= 4 &&
"Not large enough load size for fast path!");
2156 std::vector<Value *> Shadows;
2157 std::vector<Value *> Origins;
2170 Type *WideShadowTy =
2174 Value *CombinedWideShadow =
2178 const uint64_t BytesPerWideShadow = WideShadowBitWidth / DFS.ShadowWidthBits;
2180 auto AppendWideShadowAndOrigin = [&](
Value *WideShadow,
Value *Origin) {
2181 if (BytesPerWideShadow > 4) {
2182 assert(BytesPerWideShadow == 8);
2190 WideShadow, ConstantInt::get(WideShadowTy, WideShadowBitWidth / 2));
2191 Shadows.push_back(WideShadow);
2192 Origins.push_back(DFS.loadNextOrigin(Pos, OriginAlign, &OriginAddr));
2194 Shadows.push_back(WideShadowLo);
2195 Origins.push_back(Origin);
2197 Shadows.push_back(WideShadow);
2198 Origins.push_back(Origin);
2202 if (ShouldTrackOrigins)
2203 AppendWideShadowAndOrigin(CombinedWideShadow, FirstOrigin);
2210 for (
uint64_t ByteOfs = BytesPerWideShadow; ByteOfs <
Size;
2211 ByteOfs += BytesPerWideShadow) {
2212 ShadowAddr = IRB.
CreateGEP(WideShadowTy, ShadowAddr,
2213 ConstantInt::get(DFS.IntptrTy, 1));
2214 Value *NextWideShadow =
2216 CombinedWideShadow = IRB.
CreateOr(CombinedWideShadow, NextWideShadow);
2217 if (ShouldTrackOrigins) {
2218 Value *NextOrigin = DFS.loadNextOrigin(Pos, OriginAlign, &OriginAddr);
2219 AppendWideShadowAndOrigin(NextWideShadow, NextOrigin);
2222 for (
unsigned Width = WideShadowBitWidth / 2; Width >= DFS.ShadowWidthBits;
2225 CombinedWideShadow = IRB.
CreateOr(CombinedWideShadow, ShrShadow);
2227 return {IRB.
CreateTrunc(CombinedWideShadow, DFS.PrimitiveShadowTy),
2229 ? combineOrigins(Shadows, Origins, Pos,
2234std::pair<Value *, Value *> DFSanFunction::loadShadowOriginSansLoadTracking(
2236 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins();
2240 const auto SI = AllocaShadowMap.
find(AI);
2241 if (SI != AllocaShadowMap.
end()) {
2244 const auto OI = AllocaOriginMap.
find(AI);
2245 assert(!ShouldTrackOrigins || OI != AllocaOriginMap.
end());
2246 return {ShadowLI, ShouldTrackOrigins
2255 bool AllConstants =
true;
2256 for (
const Value *Obj : Objs) {
2257 if (isa<Function>(Obj) || isa<BlockAddress>(Obj))
2259 if (isa<GlobalVariable>(Obj) && cast<GlobalVariable>(Obj)->
isConstant())
2262 AllConstants =
false;
2266 return {DFS.ZeroPrimitiveShadow,
2267 ShouldTrackOrigins ? DFS.ZeroOrigin :
nullptr};
2270 return {DFS.ZeroPrimitiveShadow,
2271 ShouldTrackOrigins ? DFS.ZeroOrigin :
nullptr};
2275 if (ShouldTrackOrigins &&
2276 useCallbackLoadLabelAndOrigin(
Size, InstAlignment)) {
2279 IRB.
CreateCall(DFS.DFSanLoadLabelAndOriginFn,
2280 {Addr, ConstantInt::get(DFS.IntptrTy, Size)});
2281 Call->addRetAttr(Attribute::ZExt);
2283 DFS.PrimitiveShadowTy),
2288 Value *ShadowAddr, *OriginAddr;
2289 std::tie(ShadowAddr, OriginAddr) =
2290 DFS.getShadowOriginAddress(
Addr, InstAlignment, Pos);
2292 const Align ShadowAlign = getShadowAlign(InstAlignment);
2293 const Align OriginAlign = getOriginAlign(InstAlignment);
2294 Value *Origin =
nullptr;
2295 if (ShouldTrackOrigins) {
2306 return {LI, Origin};
2310 Value *ShadowAddr1 = IRB.
CreateGEP(DFS.PrimitiveShadowTy, ShadowAddr,
2311 ConstantInt::get(DFS.IntptrTy, 1));
2316 return {combineShadows(Load, Load1, Pos), Origin};
2319 bool HasSizeForFastPath = DFS.hasLoadSizeForFastPath(
Size);
2321 if (HasSizeForFastPath)
2322 return loadShadowFast(ShadowAddr, OriginAddr,
Size, ShadowAlign,
2323 OriginAlign, Origin, Pos);
2327 DFS.DFSanUnionLoadFn, {ShadowAddr, ConstantInt::get(DFS.IntptrTy, Size)});
2329 return {FallbackCall, Origin};
2332std::pair<Value *, Value *>
2335 Value *PrimitiveShadow, *Origin;
2336 std::tie(PrimitiveShadow, Origin) =
2337 loadShadowOriginSansLoadTracking(
Addr,
Size, InstAlignment, Pos);
2338 if (DFS.shouldTrackOrigins()) {
2341 auto *ConstantShadow = dyn_cast<Constant>(PrimitiveShadow);
2342 if (!ConstantShadow || !ConstantShadow->isZeroValue())
2343 Origin = updateOriginIfTainted(PrimitiveShadow, Origin, IRB);
2346 return {PrimitiveShadow, Origin};
2351 case AtomicOrdering::NotAtomic:
2352 return AtomicOrdering::NotAtomic;
2353 case AtomicOrdering::Unordered:
2354 case AtomicOrdering::Monotonic:
2355 case AtomicOrdering::Acquire:
2356 return AtomicOrdering::Acquire;
2357 case AtomicOrdering::Release:
2358 case AtomicOrdering::AcquireRelease:
2359 return AtomicOrdering::AcquireRelease;
2360 case AtomicOrdering::SequentiallyConsistent:
2361 return AtomicOrdering::SequentiallyConsistent;
2367 if (!V->getType()->isPointerTy())
2375 if (
auto *
GEP = dyn_cast<GEPOperator>(V)) {
2376 V =
GEP->getPointerOperand();
2378 V = cast<Operator>(V)->getOperand(0);
2379 if (!V->getType()->isPointerTy())
2381 }
else if (isa<GlobalAlias>(V)) {
2382 V = cast<GlobalAlias>(V)->getAliasee();
2384 }
while (Visited.
insert(V).second);
2389void DFSanVisitor::visitLoadInst(
LoadInst &LI) {
2393 DFSF.setShadow(&LI, DFSF.DFS.getZeroShadow(&LI));
2394 DFSF.setOrigin(&LI, DFSF.DFS.ZeroOrigin);
2409 Pos = std::next(Pos);
2411 std::vector<Value *> Shadows;
2412 std::vector<Value *> Origins;
2413 Value *PrimitiveShadow, *Origin;
2414 std::tie(PrimitiveShadow, Origin) =
2416 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
2417 if (ShouldTrackOrigins) {
2418 Shadows.push_back(PrimitiveShadow);
2419 Origins.push_back(Origin);
2422 DFSF.isLookupTableConstant(
2425 PrimitiveShadow = DFSF.combineShadows(PrimitiveShadow, PtrShadow, Pos);
2426 if (ShouldTrackOrigins) {
2427 Shadows.push_back(PtrShadow);
2431 if (!DFSF.DFS.isZeroShadow(PrimitiveShadow))
2432 DFSF.NonZeroChecks.push_back(PrimitiveShadow);
2435 DFSF.expandFromPrimitiveShadow(LI.
getType(), PrimitiveShadow, Pos);
2436 DFSF.setShadow(&LI, Shadow);
2438 if (ShouldTrackOrigins) {
2439 DFSF.setOrigin(&LI, DFSF.combineOrigins(Shadows, Origins, Pos));
2446 IRB.
CreateCall(DFSF.DFS.DFSanLoadCallbackFn, {PrimitiveShadow, Addr});
2451 DFSF.addReachesFunctionCallbacksIfEnabled(IRB, LI, &LI);
2454Value *DFSanFunction::updateOriginIfTainted(
Value *Shadow,
Value *Origin,
2456 assert(DFS.shouldTrackOrigins());
2457 return IRB.
CreateCall(DFS.DFSanChainOriginIfTaintedFn, {Shadow, Origin});
2461 if (!DFS.shouldTrackOrigins())
2463 return IRB.
CreateCall(DFS.DFSanChainOriginFn, V);
2467 const unsigned OriginSize = DataFlowSanitizer::OriginWidthBytes;
2469 unsigned IntptrSize =
DL.getTypeStoreSize(DFS.IntptrTy);
2470 if (IntptrSize == OriginSize)
2472 assert(IntptrSize == OriginSize * 2);
2478 Value *StoreOriginAddr,
2480 const unsigned OriginSize = DataFlowSanitizer::OriginWidthBytes;
2482 const Align IntptrAlignment =
DL.getABITypeAlign(DFS.IntptrTy);
2483 unsigned IntptrSize =
DL.getTypeStoreSize(DFS.IntptrTy);
2485 assert(IntptrSize >= OriginSize);
2488 Align CurrentAlignment = Alignment;
2489 if (Alignment >= IntptrAlignment && IntptrSize > OriginSize) {
2490 Value *IntptrOrigin = originToIntptr(IRB, Origin);
2491 Value *IntptrStoreOriginPtr =
2493 for (
unsigned I = 0;
I < StoreOriginSize / IntptrSize; ++
I) {
2496 : IntptrStoreOriginPtr;
2498 Ofs += IntptrSize / OriginSize;
2499 CurrentAlignment = IntptrAlignment;
2503 for (
unsigned I = Ofs;
I < (StoreOriginSize + OriginSize - 1) / OriginSize;
2514 Type *VTy =
V->getType();
2524 Value *StoreOriginAddr,
Align InstAlignment) {
2527 const Align OriginAlignment = getOriginAlign(InstAlignment);
2528 Value *CollapsedShadow = collapseToPrimitiveShadow(Shadow, Pos);
2530 if (
auto *ConstantShadow = dyn_cast<Constant>(CollapsedShadow)) {
2531 if (!ConstantShadow->isZeroValue())
2532 paintOrigin(IRB, updateOrigin(Origin, IRB), StoreOriginAddr,
Size,
2537 if (shouldInstrumentWithCall()) {
2539 DFS.DFSanMaybeStoreOriginFn,
2540 {CollapsedShadow, Addr, ConstantInt::get(DFS.IntptrTy, Size), Origin});
2542 Value *
Cmp = convertToBool(CollapsedShadow, IRB,
"_dfscmp");
2545 Cmp, &*IRB.
GetInsertPoint(),
false, DFS.OriginStoreWeights, &DTU);
2547 paintOrigin(IRBNew, updateOrigin(Origin, IRBNew), StoreOriginAddr,
Size,
2559 Value *ExtZeroShadow = ConstantInt::get(ShadowTy, 0);
2560 Value *ShadowAddr = DFS.getShadowAddress(
Addr, Pos);
2567 Align InstAlignment,
2568 Value *PrimitiveShadow,
2571 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins() && Origin;
2574 const auto SI = AllocaShadowMap.
find(AI);
2575 if (SI != AllocaShadowMap.
end()) {
2581 if (ShouldTrackOrigins && !DFS.isZeroShadow(PrimitiveShadow)) {
2582 const auto OI = AllocaOriginMap.
find(AI);
2583 assert(OI != AllocaOriginMap.
end() && Origin);
2590 const Align ShadowAlign = getShadowAlign(InstAlignment);
2591 if (DFS.isZeroShadow(PrimitiveShadow)) {
2592 storeZeroPrimitiveShadow(
Addr,
Size, ShadowAlign, Pos);
2597 Value *ShadowAddr, *OriginAddr;
2598 std::tie(ShadowAddr, OriginAddr) =
2599 DFS.getShadowOriginAddress(
Addr, InstAlignment, Pos);
2601 const unsigned ShadowVecSize = 8;
2602 assert(ShadowVecSize * DFS.ShadowWidthBits <= 128 &&
2603 "Shadow vector is too large!");
2607 if (LeftSize >= ShadowVecSize) {
2611 for (
unsigned I = 0;
I != ShadowVecSize; ++
I) {
2613 ShadowVec, PrimitiveShadow,
2617 Value *CurShadowVecAddr =
2620 LeftSize -= ShadowVecSize;
2622 }
while (LeftSize >= ShadowVecSize);
2625 while (LeftSize > 0) {
2626 Value *CurShadowAddr =
2633 if (ShouldTrackOrigins) {
2634 storeOrigin(Pos,
Addr,
Size, PrimitiveShadow, Origin, OriginAddr,
2641 case AtomicOrdering::NotAtomic:
2642 return AtomicOrdering::NotAtomic;
2643 case AtomicOrdering::Unordered:
2644 case AtomicOrdering::Monotonic:
2645 case AtomicOrdering::Release:
2646 return AtomicOrdering::Release;
2647 case AtomicOrdering::Acquire:
2648 case AtomicOrdering::AcquireRelease:
2649 return AtomicOrdering::AcquireRelease;
2650 case AtomicOrdering::SequentiallyConsistent:
2651 return AtomicOrdering::SequentiallyConsistent;
2656void DFSanVisitor::visitStoreInst(
StoreInst &SI) {
2657 auto &
DL =
SI.getDataLayout();
2658 Value *Val =
SI.getValueOperand();
2671 const bool ShouldTrackOrigins =
2672 DFSF.DFS.shouldTrackOrigins() && !
SI.isAtomic();
2673 std::vector<Value *> Shadows;
2674 std::vector<Value *> Origins;
2677 SI.isAtomic() ? DFSF.DFS.getZeroShadow(Val) : DFSF.getShadow(Val);
2679 if (ShouldTrackOrigins) {
2680 Shadows.push_back(Shadow);
2681 Origins.push_back(DFSF.getOrigin(Val));
2684 Value *PrimitiveShadow;
2686 Value *PtrShadow = DFSF.getShadow(
SI.getPointerOperand());
2687 if (ShouldTrackOrigins) {
2688 Shadows.push_back(PtrShadow);
2689 Origins.push_back(DFSF.getOrigin(
SI.getPointerOperand()));
2691 PrimitiveShadow = DFSF.combineShadows(Shadow, PtrShadow,
SI.getIterator());
2693 PrimitiveShadow = DFSF.collapseToPrimitiveShadow(Shadow,
SI.getIterator());
2695 Value *Origin =
nullptr;
2696 if (ShouldTrackOrigins)
2697 Origin = DFSF.combineOrigins(Shadows, Origins,
SI.getIterator());
2698 DFSF.storePrimitiveShadowOrigin(
SI.getPointerOperand(),
Size,
SI.getAlign(),
2699 PrimitiveShadow, Origin,
SI.getIterator());
2704 IRB.
CreateCall(DFSF.DFS.DFSanStoreCallbackFn, {PrimitiveShadow, Addr});
2710 assert(isa<AtomicRMWInst>(
I) || isa<AtomicCmpXchgInst>(
I));
2712 Value *Val =
I.getOperand(1);
2713 const auto &
DL =
I.getDataLayout();
2722 const Align ShadowAlign = DFSF.getShadowAlign(InstAlignment);
2723 DFSF.storeZeroPrimitiveShadow(
Addr,
Size, ShadowAlign,
I.getIterator());
2724 DFSF.setShadow(&
I, DFSF.DFS.getZeroShadow(&
I));
2725 DFSF.setOrigin(&
I, DFSF.DFS.ZeroOrigin);
2729 visitCASOrRMW(
I.getAlign(),
I);
2736 visitCASOrRMW(
I.getAlign(),
I);
2743 visitInstOperands(UO);
2747 visitInstOperands(BO);
2750void DFSanVisitor::visitBitCastInst(
BitCastInst &BCI) {
2754 if (
auto *CI = dyn_cast<CallInst>(BCI.
getOperand(0)))
2757 visitInstOperands(BCI);
2760void DFSanVisitor::visitCastInst(
CastInst &CI) { visitInstOperands(CI); }
2762void DFSanVisitor::visitCmpInst(
CmpInst &CI) {
2763 visitInstOperands(CI);
2766 Value *CombinedShadow = DFSF.getShadow(&CI);
2768 IRB.
CreateCall(DFSF.DFS.DFSanCmpCallbackFn, CombinedShadow);
2785 DFSF.setShadow(&LPI, DFSF.DFS.getZeroShadow(&LPI));
2786 DFSF.setOrigin(&LPI, DFSF.DFS.ZeroOrigin);
2791 DFSF.isLookupTableConstant(
2793 visitInstOperands(GEPI);
2800 DFSF.setShadow(&GEPI, DFSF.getShadow(BasePointer));
2801 if (DFSF.DFS.shouldTrackOrigins())
2802 DFSF.setOrigin(&GEPI, DFSF.getOrigin(BasePointer));
2806 visitInstOperands(
I);
2810 visitInstOperands(
I);
2814 visitInstOperands(
I);
2819 Value *Agg =
I.getAggregateOperand();
2820 Value *AggShadow = DFSF.getShadow(Agg);
2822 DFSF.setShadow(&
I, ResShadow);
2823 visitInstOperandOrigins(
I);
2828 Value *AggShadow = DFSF.getShadow(
I.getAggregateOperand());
2829 Value *InsShadow = DFSF.getShadow(
I.getInsertedValueOperand());
2831 DFSF.setShadow(&
I, Res);
2832 visitInstOperandOrigins(
I);
2835void DFSanVisitor::visitAllocaInst(
AllocaInst &
I) {
2836 bool AllLoadsStores =
true;
2837 for (
User *U :
I.users()) {
2838 if (isa<LoadInst>(U))
2841 if (
StoreInst *SI = dyn_cast<StoreInst>(U)) {
2842 if (
SI->getPointerOperand() == &
I)
2846 AllLoadsStores =
false;
2849 if (AllLoadsStores) {
2851 DFSF.AllocaShadowMap[&
I] = IRB.
CreateAlloca(DFSF.DFS.PrimitiveShadowTy);
2852 if (DFSF.DFS.shouldTrackOrigins()) {
2853 DFSF.AllocaOriginMap[&
I] =
2857 DFSF.setShadow(&
I, DFSF.DFS.ZeroPrimitiveShadow);
2858 DFSF.setOrigin(&
I, DFSF.DFS.ZeroOrigin);
2861void DFSanVisitor::visitSelectInst(
SelectInst &
I) {
2862 Value *CondShadow = DFSF.getShadow(
I.getCondition());
2863 Value *TrueShadow = DFSF.getShadow(
I.getTrueValue());
2864 Value *FalseShadow = DFSF.getShadow(
I.getFalseValue());
2865 Value *ShadowSel =
nullptr;
2866 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
2867 std::vector<Value *> Shadows;
2868 std::vector<Value *> Origins;
2870 ShouldTrackOrigins ? DFSF.getOrigin(
I.getTrueValue()) :
nullptr;
2871 Value *FalseOrigin =
2872 ShouldTrackOrigins ? DFSF.getOrigin(
I.getFalseValue()) :
nullptr;
2874 DFSF.addConditionalCallbacksIfEnabled(
I,
I.getCondition());
2876 if (isa<VectorType>(
I.getCondition()->getType())) {
2877 ShadowSel = DFSF.combineShadowsThenConvert(
I.getType(), TrueShadow,
2878 FalseShadow,
I.getIterator());
2879 if (ShouldTrackOrigins) {
2880 Shadows.push_back(TrueShadow);
2881 Shadows.push_back(FalseShadow);
2882 Origins.push_back(TrueOrigin);
2883 Origins.push_back(FalseOrigin);
2886 if (TrueShadow == FalseShadow) {
2887 ShadowSel = TrueShadow;
2888 if (ShouldTrackOrigins) {
2889 Shadows.push_back(TrueShadow);
2890 Origins.push_back(TrueOrigin);
2894 "",
I.getIterator());
2895 if (ShouldTrackOrigins) {
2896 Shadows.push_back(ShadowSel);
2898 FalseOrigin,
"",
I.getIterator()));
2903 I.getType(), CondShadow,
2904 ShadowSel,
I.getIterator())
2906 if (ShouldTrackOrigins) {
2908 Shadows.push_back(CondShadow);
2909 Origins.push_back(DFSF.getOrigin(
I.getCondition()));
2911 DFSF.setOrigin(&
I, DFSF.combineOrigins(Shadows, Origins,
I.getIterator()));
2915void DFSanVisitor::visitMemSetInst(
MemSetInst &
I) {
2917 Value *ValShadow = DFSF.getShadow(
I.getValue());
2918 Value *ValOrigin = DFSF.DFS.shouldTrackOrigins()
2919 ? DFSF.getOrigin(
I.getValue())
2920 : DFSF.DFS.ZeroOrigin;
2922 {ValShadow, ValOrigin, I.getDest(),
2923 IRB.CreateZExtOrTrunc(I.getLength(), DFSF.DFS.IntptrTy)});
2931 if (DFSF.DFS.shouldTrackOrigins()) {
2933 DFSF.DFS.DFSanMemOriginTransferFn,
2934 {I.getArgOperand(0), I.getArgOperand(1),
2935 IRB.CreateIntCast(I.getArgOperand(2), DFSF.DFS.IntptrTy, false)});
2938 Value *DestShadow = DFSF.DFS.getShadowAddress(
I.getDest(),
I.getIterator());
2939 Value *SrcShadow = DFSF.DFS.getShadowAddress(
I.getSource(),
I.getIterator());
2941 IRB.
CreateMul(
I.getLength(), ConstantInt::get(
I.getLength()->getType(),
2942 DFSF.DFS.ShadowWidthBytes));
2943 auto *MTI = cast<MemTransferInst>(
2944 IRB.
CreateCall(
I.getFunctionType(),
I.getCalledOperand(),
2945 {DestShadow, SrcShadow, LenShadow, I.getVolatileCst()}));
2946 MTI->setDestAlignment(DFSF.getShadowAlign(
I.getDestAlign().valueOrOne()));
2947 MTI->setSourceAlignment(DFSF.getShadowAlign(
I.getSourceAlign().valueOrOne()));
2950 DFSF.DFS.DFSanMemTransferCallbackFn,
2951 {DestShadow, IRB.CreateZExtOrTrunc(I.getLength(), DFSF.DFS.IntptrTy)});
2955void DFSanVisitor::visitBranchInst(
BranchInst &BR) {
2956 if (!
BR.isConditional())
2959 DFSF.addConditionalCallbacksIfEnabled(BR,
BR.getCondition());
2962void DFSanVisitor::visitSwitchInst(
SwitchInst &SW) {
2963 DFSF.addConditionalCallbacksIfEnabled(SW, SW.
getCondition());
2968 if (
auto *
I = dyn_cast<BitCastInst>(RetVal)) {
2969 RetVal =
I->getOperand(0);
2971 if (
auto *
I = dyn_cast<CallInst>(RetVal)) {
2972 return I->isMustTailCall();
2977void DFSanVisitor::visitReturnInst(
ReturnInst &RI) {
2985 Type *RT = DFSF.F->getFunctionType()->getReturnType();
2986 unsigned Size = getDataLayout().getTypeAllocSize(DFSF.DFS.getShadowTy(RT));
2992 if (DFSF.DFS.shouldTrackOrigins()) {
3000 std::vector<Value *> &Args,
3007 for (
unsigned N = FT->getNumParams();
N != 0; ++
I, --
N)
3009 DFSF.collapseToPrimitiveShadow(DFSF.getShadow(*
I), CB.
getIterator()));
3012 if (FT->isVarArg()) {
3013 auto *LabelVATy = ArrayType::get(DFSF.DFS.PrimitiveShadowTy,
3014 CB.
arg_size() - FT->getNumParams());
3015 auto *LabelVAAlloca =
3016 new AllocaInst(LabelVATy, getDataLayout().getAllocaAddrSpace(),
3017 "labelva", DFSF.F->getEntryBlock().begin());
3019 for (
unsigned N = 0;
I != CB.
arg_end(); ++
I, ++
N) {
3022 DFSF.collapseToPrimitiveShadow(DFSF.getShadow(*
I), CB.
getIterator()),
3030 if (!FT->getReturnType()->isVoidTy()) {
3031 if (!DFSF.LabelReturnAlloca) {
3033 DFSF.DFS.PrimitiveShadowTy, getDataLayout().getAllocaAddrSpace(),
3034 "labelreturn", DFSF.F->getEntryBlock().begin());
3036 Args.push_back(DFSF.LabelReturnAlloca);
3041 std::vector<Value *> &Args,
3048 for (
unsigned N = FT->getNumParams();
N != 0; ++
I, --
N)
3049 Args.push_back(DFSF.getOrigin(*
I));
3052 if (FT->isVarArg()) {
3054 ArrayType::get(DFSF.DFS.OriginTy, CB.
arg_size() - FT->getNumParams());
3055 auto *OriginVAAlloca =
3056 new AllocaInst(OriginVATy, getDataLayout().getAllocaAddrSpace(),
3057 "originva", DFSF.F->getEntryBlock().begin());
3059 for (
unsigned N = 0;
I != CB.
arg_end(); ++
I, ++
N) {
3068 if (!FT->getReturnType()->isVoidTy()) {
3069 if (!DFSF.OriginReturnAlloca) {
3071 DFSF.DFS.OriginTy, getDataLayout().getAllocaAddrSpace(),
3072 "originreturn", DFSF.F->getEntryBlock().begin());
3074 Args.push_back(DFSF.OriginReturnAlloca);
3080 switch (DFSF.DFS.getWrapperKind(&
F)) {
3081 case DataFlowSanitizer::WK_Warning:
3083 IRB.
CreateCall(DFSF.DFS.DFSanUnimplementedFn,
3085 DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &
F);
3086 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3087 DFSF.setOrigin(&CB, DFSF.DFS.ZeroOrigin);
3089 case DataFlowSanitizer::WK_Discard:
3091 DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &
F);
3092 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3093 DFSF.setOrigin(&CB, DFSF.DFS.ZeroOrigin);
3095 case DataFlowSanitizer::WK_Functional:
3097 DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &
F);
3098 visitInstOperands(CB);
3100 case DataFlowSanitizer::WK_Custom:
3104 CallInst *CI = dyn_cast<CallInst>(&CB);
3108 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
3110 TransformedFunction CustomFn = DFSF.DFS.getCustomFunctionType(FT);
3111 std::string CustomFName = ShouldTrackOrigins ?
"__dfso_" :
"__dfsw_";
3112 CustomFName +=
F.getName();
3114 CustomFName, CustomFn.TransformedType);
3116 CustomFn->copyAttributesFrom(&
F);
3119 if (!FT->getReturnType()->isVoidTy()) {
3120 CustomFn->removeFnAttrs(DFSF.DFS.ReadOnlyNoneAttrs);
3124 std::vector<Value *>
Args;
3128 for (
unsigned N = FT->getNumParams();
N != 0; ++
I, --
N) {
3133 const unsigned ShadowArgStart =
Args.size();
3134 addShadowArguments(
F, CB, Args, IRB);
3137 const unsigned OriginArgStart =
Args.size();
3138 if (ShouldTrackOrigins)
3139 addOriginArguments(
F, CB, Args, IRB);
3152 for (
unsigned N = 0;
N < FT->getNumParams();
N++) {
3153 const unsigned ArgNo = ShadowArgStart +
N;
3155 DFSF.DFS.PrimitiveShadowTy)
3157 if (ShouldTrackOrigins) {
3158 const unsigned OriginArgNo = OriginArgStart +
N;
3166 if (!FT->getReturnType()->isVoidTy()) {
3168 IRB.
CreateLoad(DFSF.DFS.PrimitiveShadowTy, DFSF.LabelReturnAlloca);
3169 DFSF.setShadow(CustomCI,
3170 DFSF.expandFromPrimitiveShadow(
3171 FT->getReturnType(), LabelLoad, CB.
getIterator()));
3172 if (ShouldTrackOrigins) {
3174 IRB.
CreateLoad(DFSF.DFS.OriginTy, DFSF.OriginReturnAlloca);
3175 DFSF.setOrigin(CustomCI, OriginLoad);
3187 constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
3188 uint32_t OrderingTable[NumOrderings] = {};
3190 OrderingTable[(int)AtomicOrderingCABI::relaxed] =
3191 OrderingTable[(
int)AtomicOrderingCABI::acquire] =
3192 OrderingTable[(int)AtomicOrderingCABI::consume] =
3193 (
int)AtomicOrderingCABI::acquire;
3194 OrderingTable[(int)AtomicOrderingCABI::release] =
3195 OrderingTable[(
int)AtomicOrderingCABI::acq_rel] =
3196 (int)AtomicOrderingCABI::acq_rel;
3197 OrderingTable[(int)AtomicOrderingCABI::seq_cst] =
3198 (
int)AtomicOrderingCABI::seq_cst;
3203void DFSanVisitor::visitLibAtomicLoad(
CallBase &CB) {
3205 assert(isa<CallInst>(CB));
3214 Value *NewOrdering =
3219 NextIRB.SetCurrentDebugLocation(CB.
getDebugLoc());
3225 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3226 {DstPtr, SrcPtr, NextIRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3230 constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
3231 uint32_t OrderingTable[NumOrderings] = {};
3233 OrderingTable[(int)AtomicOrderingCABI::relaxed] =
3234 OrderingTable[(
int)AtomicOrderingCABI::release] =
3235 (int)AtomicOrderingCABI::release;
3236 OrderingTable[(int)AtomicOrderingCABI::consume] =
3237 OrderingTable[(
int)AtomicOrderingCABI::acquire] =
3238 OrderingTable[(int)AtomicOrderingCABI::acq_rel] =
3239 (
int)AtomicOrderingCABI::acq_rel;
3240 OrderingTable[(int)AtomicOrderingCABI::seq_cst] =
3241 (
int)AtomicOrderingCABI::seq_cst;
3246void DFSanVisitor::visitLibAtomicStore(
CallBase &CB) {
3254 Value *NewOrdering =
3262 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3263 {DstPtr, SrcPtr, IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3266void DFSanVisitor::visitLibAtomicExchange(
CallBase &CB) {
3282 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3283 {DstPtr, TargetPtr, IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3287 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3288 {TargetPtr, SrcPtr, IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3291void DFSanVisitor::visitLibAtomicCompareExchange(
CallBase &CB) {
3305 NextIRB.SetCurrentDebugLocation(CB.
getDebugLoc());
3307 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3311 NextIRB.CreateCall(DFSF.DFS.DFSanMemShadowOriginConditionalExchangeFn,
3312 {NextIRB.CreateIntCast(&CB, NextIRB.getInt8Ty(), false),
3313 TargetPtr, ExpectedPtr, DesiredPtr,
3314 NextIRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3317void DFSanVisitor::visitCallBase(
CallBase &CB) {
3320 visitInstOperands(CB);
3326 if (
F == DFSF.DFS.DFSanVarargWrapperFn.getCallee()->stripPointerCasts())
3330 if (DFSF.TLI.getLibFunc(CB, LF)) {
3335 case LibFunc_atomic_load:
3336 if (!isa<CallInst>(CB)) {
3337 llvm::errs() <<
"DFSAN -- cannot instrument invoke of libatomic load. "
3341 visitLibAtomicLoad(CB);
3343 case LibFunc_atomic_store:
3344 visitLibAtomicStore(CB);
3352 if (
F &&
F->hasName() && !
F->isVarArg()) {
3353 if (
F->getName() ==
"__atomic_exchange") {
3354 visitLibAtomicExchange(CB);
3357 if (
F->getName() ==
"__atomic_compare_exchange") {
3358 visitLibAtomicCompareExchange(CB);
3365 if (UnwrappedFnIt != DFSF.DFS.UnwrappedFnMap.end())
3366 if (visitWrappedCallBase(*UnwrappedFnIt->second, CB))
3371 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
3376 unsigned ArgOffset = 0;
3377 for (
unsigned I = 0,
N = FT->getNumParams();
I !=
N; ++
I) {
3378 if (ShouldTrackOrigins) {
3381 if (
I < DFSF.DFS.NumOfElementsInArgOrgTLS &&
3382 !DFSF.DFS.isZeroShadow(ArgShadow))
3384 DFSF.getArgOriginTLS(
I, IRB));
3388 DL.getTypeAllocSize(DFSF.DFS.getShadowTy(FT->getParamType(
I)));
3394 DFSF.getArgTLS(FT->getParamType(
I), ArgOffset, IRB),
3402 if (
II->getNormalDest()->getSinglePredecessor()) {
3403 Next = &
II->getNormalDest()->front();
3407 Next = &NewBB->
front();
3415 if (isa<CallInst>(CB) && cast<CallInst>(CB).isMustTailCall())
3420 unsigned Size =
DL.getTypeAllocSize(DFSF.DFS.getShadowTy(&CB));
3423 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3425 LoadInst *LI = NextIRB.CreateAlignedLoad(
3426 DFSF.DFS.getShadowTy(&CB), DFSF.getRetvalTLS(CB.
getType(), NextIRB),
3428 DFSF.SkipInsts.insert(LI);
3429 DFSF.setShadow(&CB, LI);
3430 DFSF.NonZeroChecks.push_back(LI);
3433 if (ShouldTrackOrigins) {
3434 LoadInst *LI = NextIRB.CreateLoad(DFSF.DFS.OriginTy,
3435 DFSF.getRetvalOriginTLS(),
"_dfsret_o");
3436 DFSF.SkipInsts.insert(LI);
3437 DFSF.setOrigin(&CB, LI);
3440 DFSF.addReachesFunctionCallbacksIfEnabled(NextIRB, CB, &CB);
3444void DFSanVisitor::visitPHINode(
PHINode &PN) {
3445 Type *ShadowTy = DFSF.DFS.getShadowTy(&PN);
3454 DFSF.setShadow(&PN, ShadowPN);
3457 if (DFSF.DFS.shouldTrackOrigins()) {
3463 DFSF.setOrigin(&PN, OriginPN);
3466 DFSF.PHIFixups.push_back({&PN, ShadowPN, OriginPN});
3479 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.