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));
880TransformedFunction DataFlowSanitizer::getCustomFunctionType(
FunctionType *
T) {
887 std::vector<unsigned> ArgumentIndexMapping;
888 for (
unsigned I = 0, E =
T->getNumParams();
I != E; ++
I) {
889 Type *ParamType =
T->getParamType(
I);
890 ArgumentIndexMapping.push_back(ArgTypes.
size());
893 for (
unsigned I = 0, E =
T->getNumParams();
I != E; ++
I)
896 ArgTypes.
push_back(PrimitiveShadowPtrTy);
897 Type *RetType =
T->getReturnType();
899 ArgTypes.
push_back(PrimitiveShadowPtrTy);
901 if (shouldTrackOrigins()) {
902 for (
unsigned I = 0, E =
T->getNumParams();
I != E; ++
I)
910 return TransformedFunction(
911 T, FunctionType::get(
T->getReturnType(), ArgTypes,
T->isVarArg()),
912 ArgumentIndexMapping);
915bool DataFlowSanitizer::isZeroShadow(
Value *V) {
917 if (!isa<ArrayType>(
T) && !isa<StructType>(
T)) {
918 if (
const ConstantInt *CI = dyn_cast<ConstantInt>(V))
923 return isa<ConstantAggregateZero>(V);
926bool DataFlowSanitizer::hasLoadSizeForFastPath(
uint64_t Size) {
928 return ShadowSize % 8 == 0 || ShadowSize == 4;
931bool DataFlowSanitizer::shouldTrackOrigins() {
933 return ShouldTrackOrigins;
936Constant *DataFlowSanitizer::getZeroShadow(
Type *OrigTy) {
937 if (!isa<ArrayType>(OrigTy) && !isa<StructType>(OrigTy))
938 return ZeroPrimitiveShadow;
939 Type *ShadowTy = getShadowTy(OrigTy);
944 return getZeroShadow(
V->getType());
950 if (!isa<ArrayType>(SubShadowTy) && !isa<StructType>(SubShadowTy))
953 if (
ArrayType *AT = dyn_cast<ArrayType>(SubShadowTy)) {
954 for (
unsigned Idx = 0;
Idx < AT->getNumElements();
Idx++) {
957 Shadow, Indices, AT->getElementType(), PrimitiveShadow, IRB);
963 if (
StructType *ST = dyn_cast<StructType>(SubShadowTy)) {
964 for (
unsigned Idx = 0;
Idx < ST->getNumElements();
Idx++) {
967 Shadow, Indices, ST->getElementType(
Idx), PrimitiveShadow, IRB);
975bool DFSanFunction::shouldInstrumentWithCall() {
980Value *DFSanFunction::expandFromPrimitiveShadow(
Type *
T,
Value *PrimitiveShadow,
982 Type *ShadowTy = DFS.getShadowTy(
T);
984 if (!isa<ArrayType>(ShadowTy) && !isa<StructType>(ShadowTy))
985 return PrimitiveShadow;
987 if (DFS.isZeroShadow(PrimitiveShadow))
988 return DFS.getZeroShadow(ShadowTy);
994 PrimitiveShadow, IRB);
997 CachedCollapsedShadows[Shadow] = PrimitiveShadow;
1001template <
class AggregateType>
1002Value *DFSanFunction::collapseAggregateShadow(AggregateType *AT,
Value *Shadow,
1004 if (!AT->getNumElements())
1005 return DFS.ZeroPrimitiveShadow;
1008 Value *Aggregator = collapseToPrimitiveShadow(FirstItem, IRB);
1010 for (
unsigned Idx = 1;
Idx < AT->getNumElements();
Idx++) {
1012 Value *ShadowInner = collapseToPrimitiveShadow(ShadowItem, IRB);
1013 Aggregator = IRB.
CreateOr(Aggregator, ShadowInner);
1018Value *DFSanFunction::collapseToPrimitiveShadow(
Value *Shadow,
1021 if (!isa<ArrayType>(ShadowTy) && !isa<StructType>(ShadowTy))
1023 if (
ArrayType *AT = dyn_cast<ArrayType>(ShadowTy))
1024 return collapseAggregateShadow<>(AT, Shadow, IRB);
1025 if (
StructType *ST = dyn_cast<StructType>(ShadowTy))
1026 return collapseAggregateShadow<>(ST, Shadow, IRB);
1030Value *DFSanFunction::collapseToPrimitiveShadow(
Value *Shadow,
1033 if (!isa<ArrayType>(ShadowTy) && !isa<StructType>(ShadowTy))
1037 Value *&CS = CachedCollapsedShadows[Shadow];
1042 Value *PrimitiveShadow = collapseToPrimitiveShadow(Shadow, IRB);
1044 CS = PrimitiveShadow;
1045 return PrimitiveShadow;
1048void DFSanFunction::addConditionalCallbacksIfEnabled(
Instruction &
I,
1054 Value *CondShadow = getShadow(Condition);
1056 if (DFS.shouldTrackOrigins()) {
1057 Value *CondOrigin = getOrigin(Condition);
1058 CI = IRB.
CreateCall(DFS.DFSanConditionalCallbackOriginFn,
1059 {CondShadow, CondOrigin});
1061 CI = IRB.
CreateCall(DFS.DFSanConditionalCallbackFn, {CondShadow});
1066void DFSanFunction::addReachesFunctionCallbacksIfEnabled(
IRBuilder<> &IRB,
1072 const DebugLoc &dbgloc =
I.getDebugLoc();
1073 Value *DataShadow = collapseToPrimitiveShadow(getShadow(Data), IRB);
1077 if (dbgloc.
get() ==
nullptr) {
1078 CILine = llvm::ConstantInt::get(
I.getContext(),
llvm::APInt(32, 0));
1080 I.getFunction()->getParent()->getSourceFileName());
1082 CILine = llvm::ConstantInt::get(
I.getContext(),
1091 std::vector<Value *>
args;
1093 if (DFS.shouldTrackOrigins()) {
1094 Value *DataOrigin = getOrigin(Data);
1095 args = { DataShadow, DataOrigin, FilePathPtr, CILine, FunctionNamePtr };
1096 CB = IRB.
CreateCall(DFS.DFSanReachesFunctionCallbackOriginFn,
args);
1098 args = { DataShadow, FilePathPtr, CILine, FunctionNamePtr };
1105Type *DataFlowSanitizer::getShadowTy(
Type *OrigTy) {
1107 return PrimitiveShadowTy;
1108 if (isa<IntegerType>(OrigTy))
1109 return PrimitiveShadowTy;
1110 if (isa<VectorType>(OrigTy))
1111 return PrimitiveShadowTy;
1112 if (
ArrayType *AT = dyn_cast<ArrayType>(OrigTy))
1113 return ArrayType::get(getShadowTy(AT->getElementType()),
1114 AT->getNumElements());
1115 if (
StructType *ST = dyn_cast<StructType>(OrigTy)) {
1117 for (
unsigned I = 0,
N =
ST->getNumElements();
I <
N; ++
I)
1118 Elements.push_back(getShadowTy(
ST->getElementType(
I)));
1121 return PrimitiveShadowTy;
1124Type *DataFlowSanitizer::getShadowTy(
Value *V) {
1125 return getShadowTy(
V->getType());
1128bool DataFlowSanitizer::initializeModule(
Module &M) {
1129 Triple TargetTriple(
M.getTargetTriple());
1134 switch (TargetTriple.getArch()) {
1149 Ctx = &
M.getContext();
1150 Int8Ptr = PointerType::getUnqual(*Ctx);
1152 OriginPtrTy = PointerType::getUnqual(*Ctx);
1154 PrimitiveShadowPtrTy = PointerType::getUnqual(*Ctx);
1155 IntptrTy =
DL.getIntPtrType(*Ctx);
1159 Type *DFSanUnionLoadArgs[2] = {PrimitiveShadowPtrTy, IntptrTy};
1160 DFSanUnionLoadFnTy = FunctionType::get(PrimitiveShadowTy, DFSanUnionLoadArgs,
1162 Type *DFSanLoadLabelAndOriginArgs[2] = {Int8Ptr, IntptrTy};
1163 DFSanLoadLabelAndOriginFnTy =
1166 DFSanUnimplementedFnTy = FunctionType::get(
1168 Type *DFSanWrapperExternWeakNullArgs[2] = {Int8Ptr, Int8Ptr};
1169 DFSanWrapperExternWeakNullFnTy =
1170 FunctionType::get(
Type::getVoidTy(*Ctx), DFSanWrapperExternWeakNullArgs,
1172 Type *DFSanSetLabelArgs[4] = {PrimitiveShadowTy, OriginTy,
1173 PointerType::getUnqual(*Ctx), IntptrTy};
1175 DFSanSetLabelArgs,
false);
1178 DFSanVarargWrapperFnTy = FunctionType::get(
1180 DFSanConditionalCallbackFnTy =
1183 Type *DFSanConditionalCallbackOriginArgs[2] = {PrimitiveShadowTy, OriginTy};
1184 DFSanConditionalCallbackOriginFnTy = FunctionType::get(
1187 Type *DFSanReachesFunctionCallbackArgs[4] = {PrimitiveShadowTy, Int8Ptr,
1189 DFSanReachesFunctionCallbackFnTy =
1190 FunctionType::get(
Type::getVoidTy(*Ctx), DFSanReachesFunctionCallbackArgs,
1192 Type *DFSanReachesFunctionCallbackOriginArgs[5] = {
1193 PrimitiveShadowTy, OriginTy, Int8Ptr, OriginTy, Int8Ptr};
1194 DFSanReachesFunctionCallbackOriginFnTy = FunctionType::get(
1197 DFSanCmpCallbackFnTy =
1200 DFSanChainOriginFnTy =
1201 FunctionType::get(OriginTy, OriginTy,
false);
1202 Type *DFSanChainOriginIfTaintedArgs[2] = {PrimitiveShadowTy, OriginTy};
1203 DFSanChainOriginIfTaintedFnTy = FunctionType::get(
1204 OriginTy, DFSanChainOriginIfTaintedArgs,
false);
1206 Int8Ptr, IntptrTy, OriginTy};
1207 DFSanMaybeStoreOriginFnTy = FunctionType::get(
1209 Type *DFSanMemOriginTransferArgs[3] = {Int8Ptr, Int8Ptr, IntptrTy};
1210 DFSanMemOriginTransferFnTy = FunctionType::get(
1212 Type *DFSanMemShadowOriginTransferArgs[3] = {Int8Ptr, Int8Ptr, IntptrTy};
1213 DFSanMemShadowOriginTransferFnTy =
1214 FunctionType::get(
Type::getVoidTy(*Ctx), DFSanMemShadowOriginTransferArgs,
1216 Type *DFSanMemShadowOriginConditionalExchangeArgs[5] = {
1218 DFSanMemShadowOriginConditionalExchangeFnTy = FunctionType::get(
1221 Type *DFSanLoadStoreCallbackArgs[2] = {PrimitiveShadowTy, Int8Ptr};
1222 DFSanLoadStoreCallbackFnTy =
1225 Type *DFSanMemTransferCallbackArgs[2] = {PrimitiveShadowPtrTy, IntptrTy};
1226 DFSanMemTransferCallbackFnTy =
1227 FunctionType::get(
Type::getVoidTy(*Ctx), DFSanMemTransferCallbackArgs,
1235bool DataFlowSanitizer::isInstrumented(
const Function *
F) {
1236 return !ABIList.isIn(*
F,
"uninstrumented");
1239bool DataFlowSanitizer::isInstrumented(
const GlobalAlias *GA) {
1240 return !ABIList.isIn(*GA,
"uninstrumented");
1243bool DataFlowSanitizer::isForceZeroLabels(
const Function *
F) {
1244 return ABIList.isIn(*
F,
"force_zero_labels");
1247DataFlowSanitizer::WrapperKind DataFlowSanitizer::getWrapperKind(
Function *
F) {
1248 if (ABIList.isIn(*
F,
"functional"))
1249 return WK_Functional;
1250 if (ABIList.isIn(*
F,
"discard"))
1252 if (ABIList.isIn(*
F,
"custom"))
1258void DataFlowSanitizer::addGlobalNameSuffix(
GlobalValue *GV) {
1259 std::string GVName = std::string(GV->
getName()), Suffix =
".dfsan";
1268 std::string SearchStr =
".symver " + GVName +
",";
1269 size_t Pos =
Asm.find(SearchStr);
1270 if (Pos != std::string::npos) {
1271 Asm.replace(Pos, SearchStr.size(),
".symver " + GVName + Suffix +
",");
1272 Pos =
Asm.find(
'@');
1274 if (Pos == std::string::npos)
1277 Asm.replace(Pos, 1, Suffix +
"@");
1282void DataFlowSanitizer::buildExternWeakCheckIfNeeded(
IRBuilder<> &IRB,
1292 std::vector<Value *>
Args;
1295 IRB.
CreateCall(DFSanWrapperExternWeakNullFn, Args);
1305 NewFName,
F->getParent());
1311 if (
F->isVarArg()) {
1314 IRBuilder<>(BB).CreateGlobalString(
F->getName()),
"", BB);
1318 std::vector<Value *>
Args(ArgIt, ArgIt + FT->getNumParams());
1321 if (FT->getReturnType()->isVoidTy())
1331void DataFlowSanitizer::initializeRuntimeFunctions(
Module &M) {
1335 AL =
AL.addFnAttribute(
C, Attribute::NoUnwind);
1336 AL =
AL.addFnAttribute(
1338 AL =
AL.addRetAttribute(
C, Attribute::ZExt);
1340 Mod->getOrInsertFunction(
"__dfsan_union_load", DFSanUnionLoadFnTy, AL);
1344 AL =
AL.addFnAttribute(
C, Attribute::NoUnwind);
1345 AL =
AL.addFnAttribute(
1347 AL =
AL.addRetAttribute(
C, Attribute::ZExt);
1348 DFSanLoadLabelAndOriginFn =
Mod->getOrInsertFunction(
1349 "__dfsan_load_label_and_origin", DFSanLoadLabelAndOriginFnTy, AL);
1351 DFSanUnimplementedFn =
1352 Mod->getOrInsertFunction(
"__dfsan_unimplemented", DFSanUnimplementedFnTy);
1353 DFSanWrapperExternWeakNullFn =
Mod->getOrInsertFunction(
1354 "__dfsan_wrapper_extern_weak_null", DFSanWrapperExternWeakNullFnTy);
1357 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1358 AL =
AL.addParamAttribute(
M.getContext(), 1, Attribute::ZExt);
1360 Mod->getOrInsertFunction(
"__dfsan_set_label", DFSanSetLabelFnTy, AL);
1362 DFSanNonzeroLabelFn =
1363 Mod->getOrInsertFunction(
"__dfsan_nonzero_label", DFSanNonzeroLabelFnTy);
1364 DFSanVarargWrapperFn =
Mod->getOrInsertFunction(
"__dfsan_vararg_wrapper",
1365 DFSanVarargWrapperFnTy);
1368 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1369 AL =
AL.addRetAttribute(
M.getContext(), Attribute::ZExt);
1370 DFSanChainOriginFn =
Mod->getOrInsertFunction(
"__dfsan_chain_origin",
1371 DFSanChainOriginFnTy, AL);
1375 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1376 AL =
AL.addParamAttribute(
M.getContext(), 1, Attribute::ZExt);
1377 AL =
AL.addRetAttribute(
M.getContext(), Attribute::ZExt);
1378 DFSanChainOriginIfTaintedFn =
Mod->getOrInsertFunction(
1379 "__dfsan_chain_origin_if_tainted", DFSanChainOriginIfTaintedFnTy, AL);
1381 DFSanMemOriginTransferFn =
Mod->getOrInsertFunction(
1382 "__dfsan_mem_origin_transfer", DFSanMemOriginTransferFnTy);
1384 DFSanMemShadowOriginTransferFn =
Mod->getOrInsertFunction(
1385 "__dfsan_mem_shadow_origin_transfer", DFSanMemShadowOriginTransferFnTy);
1387 DFSanMemShadowOriginConditionalExchangeFn =
1388 Mod->getOrInsertFunction(
"__dfsan_mem_shadow_origin_conditional_exchange",
1389 DFSanMemShadowOriginConditionalExchangeFnTy);
1393 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1394 AL =
AL.addParamAttribute(
M.getContext(), 3, Attribute::ZExt);
1395 DFSanMaybeStoreOriginFn =
Mod->getOrInsertFunction(
1396 "__dfsan_maybe_store_origin", DFSanMaybeStoreOriginFnTy, AL);
1399 DFSanRuntimeFunctions.
insert(
1401 DFSanRuntimeFunctions.
insert(
1403 DFSanRuntimeFunctions.
insert(
1405 DFSanRuntimeFunctions.
insert(
1407 DFSanRuntimeFunctions.
insert(
1409 DFSanRuntimeFunctions.
insert(
1411 DFSanRuntimeFunctions.
insert(
1413 DFSanRuntimeFunctions.
insert(
1415 DFSanRuntimeFunctions.
insert(
1417 DFSanRuntimeFunctions.
insert(
1419 DFSanRuntimeFunctions.
insert(
1421 DFSanRuntimeFunctions.
insert(
1423 DFSanRuntimeFunctions.
insert(
1425 DFSanRuntimeFunctions.
insert(
1427 DFSanRuntimeFunctions.
insert(
1429 DFSanRuntimeFunctions.
insert(
1431 DFSanRuntimeFunctions.
insert(
1433 DFSanRuntimeFunctions.
insert(
1435 DFSanRuntimeFunctions.
insert(
1437 DFSanRuntimeFunctions.
insert(
1438 DFSanMemShadowOriginConditionalExchangeFn.
getCallee()
1440 DFSanRuntimeFunctions.
insert(
1445void DataFlowSanitizer::initializeCallbackFunctions(
Module &M) {
1448 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1449 DFSanLoadCallbackFn =
Mod->getOrInsertFunction(
1450 "__dfsan_load_callback", DFSanLoadStoreCallbackFnTy, AL);
1454 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1455 DFSanStoreCallbackFn =
Mod->getOrInsertFunction(
1456 "__dfsan_store_callback", DFSanLoadStoreCallbackFnTy, AL);
1458 DFSanMemTransferCallbackFn =
Mod->getOrInsertFunction(
1459 "__dfsan_mem_transfer_callback", DFSanMemTransferCallbackFnTy);
1462 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1463 DFSanCmpCallbackFn =
Mod->getOrInsertFunction(
"__dfsan_cmp_callback",
1464 DFSanCmpCallbackFnTy, AL);
1468 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1469 DFSanConditionalCallbackFn =
Mod->getOrInsertFunction(
1470 "__dfsan_conditional_callback", DFSanConditionalCallbackFnTy, AL);
1474 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1475 DFSanConditionalCallbackOriginFn =
1476 Mod->getOrInsertFunction(
"__dfsan_conditional_callback_origin",
1477 DFSanConditionalCallbackOriginFnTy, AL);
1481 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1482 DFSanReachesFunctionCallbackFn =
1483 Mod->getOrInsertFunction(
"__dfsan_reaches_function_callback",
1484 DFSanReachesFunctionCallbackFnTy, AL);
1488 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1489 DFSanReachesFunctionCallbackOriginFn =
1490 Mod->getOrInsertFunction(
"__dfsan_reaches_function_callback_origin",
1491 DFSanReachesFunctionCallbackOriginFnTy, AL);
1495bool DataFlowSanitizer::runImpl(
1497 initializeModule(M);
1499 if (ABIList.isIn(M,
"skip"))
1502 const unsigned InitialGlobalSize =
M.global_size();
1503 const unsigned InitialModuleSize =
M.size();
1505 bool Changed =
false;
1510 Changed |=
G->getThreadLocalMode() != GlobalVariable::InitialExecTLSModel;
1511 G->setThreadLocalMode(GlobalVariable::InitialExecTLSModel);
1517 GetOrInsertGlobal(
"__dfsan_arg_tls",
1519 RetvalTLS = GetOrInsertGlobal(
1520 "__dfsan_retval_tls",
1522 ArgOriginTLSTy = ArrayType::get(OriginTy, NumOfElementsInArgOrgTLS);
1523 ArgOriginTLS = GetOrInsertGlobal(
"__dfsan_arg_origin_tls", ArgOriginTLSTy);
1524 RetvalOriginTLS = GetOrInsertGlobal(
"__dfsan_retval_origin_tls", OriginTy);
1526 (void)
Mod->getOrInsertGlobal(
"__dfsan_track_origins", OriginTy, [&] {
1532 "__dfsan_track_origins");
1535 initializeCallbackFunctions(M);
1536 initializeRuntimeFunctions(M);
1538 std::vector<Function *> FnsToInstrument;
1543 if (!
F.isIntrinsic() && !DFSanRuntimeFunctions.
contains(&
F) &&
1544 !LibAtomicFunction(
F) &&
1545 !
F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation)) {
1546 FnsToInstrument.push_back(&
F);
1547 if (
F.hasPersonalityFn())
1548 PersonalityFns.
insert(
F.getPersonalityFn()->stripPointerCasts());
1552 for (
auto *
C : PersonalityFns) {
1553 assert(isa<Function>(
C) &&
"Personality routine is not a function!");
1555 if (!isInstrumented(
F))
1569 bool GAInst = isInstrumented(&GA), FInst = isInstrumented(
F);
1570 if (GAInst && FInst) {
1571 addGlobalNameSuffix(&GA);
1572 }
else if (GAInst != FInst) {
1577 buildWrapperFunction(
F,
"", GA.
getLinkage(),
F->getFunctionType());
1581 FnsToInstrument.push_back(NewF);
1590 for (std::vector<Function *>::iterator FI = FnsToInstrument.begin(),
1591 FE = FnsToInstrument.end();
1596 bool IsZeroArgsVoidRet = (FT->getNumParams() == 0 && !FT->isVarArg() &&
1597 FT->getReturnType()->isVoidTy());
1599 if (isInstrumented(&
F)) {
1600 if (isForceZeroLabels(&
F))
1601 FnsWithForceZeroLabel.
insert(&
F);
1606 addGlobalNameSuffix(&
F);
1607 }
else if (!IsZeroArgsVoidRet || getWrapperKind(&
F) == WK_Custom) {
1615 F.hasLocalLinkage() ?
F.getLinkage()
1618 Function *NewF = buildWrapperFunction(
1620 (shouldTrackOrigins() ? std::string(
"dfso$") : std::string(
"dfsw$")) +
1621 std::string(
F.getName()),
1622 WrapperLinkage, FT);
1642 auto IsNotCmpUse = [](
Use &
U) ->
bool {
1643 User *Usr =
U.getUser();
1646 if (
CE->getOpcode() == Instruction::ICmp) {
1651 if (
I->getOpcode() == Instruction::ICmp) {
1657 F.replaceUsesWithIf(NewF, IsNotCmpUse);
1659 UnwrappedFnMap[NewF] = &
F;
1662 if (!
F.isDeclaration()) {
1672 size_t N = FI - FnsToInstrument.begin(),
1673 Count = FE - FnsToInstrument.begin();
1674 FnsToInstrument.push_back(&
F);
1675 FI = FnsToInstrument.begin() +
N;
1676 FE = FnsToInstrument.begin() + Count;
1680 }
else if (FT->isVarArg()) {
1681 UnwrappedFnMap[&
F] = &
F;
1687 if (!
F ||
F->isDeclaration())
1692 DFSanFunction DFSF(*
this,
F, FnsWithNativeABI.
count(
F),
1693 FnsWithForceZeroLabel.
count(
F), GetTLI(*
F));
1697 for (
auto &FArg :
F->args()) {
1699 Value *FArgShadow = DFSF.getShadow(&FArg);
1700 if (isZeroShadow(FArgShadow))
1702 if (
Instruction *FArgShadowInst = dyn_cast<Instruction>(FArgShadow)) {
1705 if (shouldTrackOrigins()) {
1707 dyn_cast<Instruction>(DFSF.getOrigin(&FArg))) {
1716 DFSF.addReachesFunctionCallbacksIfEnabled(IRB, *Next, &FArg);
1734 if (!DFSF.SkipInsts.count(Inst))
1735 DFSanVisitor(DFSF).visit(Inst);
1746 for (DFSanFunction::PHIFixupElement &
P : DFSF.PHIFixups) {
1747 for (
unsigned Val = 0,
N =
P.Phi->getNumIncomingValues(); Val !=
N;
1749 P.ShadowPhi->setIncomingValue(
1750 Val, DFSF.getShadow(
P.Phi->getIncomingValue(Val)));
1752 P.OriginPhi->setIncomingValue(
1753 Val, DFSF.getOrigin(
P.Phi->getIncomingValue(Val)));
1762 for (
Value *V : DFSF.NonZeroChecks) {
1765 Pos = std::next(
I->getIterator());
1767 Pos = DFSF.F->getEntryBlock().begin();
1768 while (isa<PHINode>(Pos) || isa<AllocaInst>(Pos))
1769 Pos = std::next(Pos->getIterator());
1771 Value *PrimitiveShadow = DFSF.collapseToPrimitiveShadow(V, Pos);
1773 IRB.
CreateICmpNE(PrimitiveShadow, DFSF.DFS.ZeroPrimitiveShadow);
1775 Ne, Pos,
false, ColdCallWeights));
1777 ThenIRB.CreateCall(DFSF.DFS.DFSanNonzeroLabelFn, {});
1782 return Changed || !FnsToInstrument.empty() ||
1783 M.global_size() != InitialGlobalSize ||
M.size() != InitialModuleSize;
1798Value *DFSanFunction::getRetvalOriginTLS() {
return DFS.RetvalOriginTLS; }
1802 ArgNo,
"_dfsarg_o");
1806 assert(DFS.shouldTrackOrigins());
1807 if (!isa<Argument>(V) && !isa<Instruction>(V))
1808 return DFS.ZeroOrigin;
1809 Value *&Origin = ValOriginMap[
V];
1811 if (
Argument *
A = dyn_cast<Argument>(V)) {
1813 return DFS.ZeroOrigin;
1814 if (
A->getArgNo() < DFS.NumOfElementsInArgOrgTLS) {
1815 Instruction *ArgOriginTLSPos = &*
F->getEntryBlock().begin();
1817 Value *ArgOriginPtr = getArgOriginTLS(
A->getArgNo(), IRB);
1818 Origin = IRB.
CreateLoad(DFS.OriginTy, ArgOriginPtr);
1821 Origin = DFS.ZeroOrigin;
1824 Origin = DFS.ZeroOrigin;
1831 if (!DFS.shouldTrackOrigins())
1835 ValOriginMap[
I] = Origin;
1839 unsigned ArgOffset = 0;
1841 for (
auto &FArg :
F->args()) {
1842 if (!FArg.getType()->isSized()) {
1848 unsigned Size =
DL.getTypeAllocSize(DFS.getShadowTy(&FArg));
1861 Value *ArgShadowPtr = getArgTLS(FArg.getType(), ArgOffset, IRB);
1866 return DFS.getZeroShadow(
A);
1870 if (!isa<Argument>(V) && !isa<Instruction>(V))
1871 return DFS.getZeroShadow(V);
1872 if (IsForceZeroLabels)
1873 return DFS.getZeroShadow(V);
1874 Value *&Shadow = ValShadowMap[
V];
1876 if (
Argument *
A = dyn_cast<Argument>(V)) {
1878 return DFS.getZeroShadow(V);
1879 Shadow = getShadowForTLSArgument(
A);
1880 NonZeroChecks.push_back(Shadow);
1882 Shadow = DFS.getZeroShadow(V);
1890 ValShadowMap[
I] = Shadow;
1898 assert(
Addr != RetvalTLS &&
"Reinstrumenting?");
1901 uint64_t AndMask = MapParams->AndMask;
1904 IRB.
CreateAnd(OffsetLong, ConstantInt::get(IntptrTy, ~AndMask));
1906 uint64_t XorMask = MapParams->XorMask;
1908 OffsetLong = IRB.
CreateXor(OffsetLong, ConstantInt::get(IntptrTy, XorMask));
1912std::pair<Value *, Value *>
1913DataFlowSanitizer::getShadowOriginAddress(
Value *
Addr,
Align InstAlignment,
1917 Value *ShadowOffset = getShadowOffset(
Addr, IRB);
1918 Value *ShadowLong = ShadowOffset;
1919 uint64_t ShadowBase = MapParams->ShadowBase;
1920 if (ShadowBase != 0) {
1922 IRB.
CreateAdd(ShadowLong, ConstantInt::get(IntptrTy, ShadowBase));
1925 Value *OriginPtr =
nullptr;
1926 if (shouldTrackOrigins()) {
1927 Value *OriginLong = ShadowOffset;
1928 uint64_t OriginBase = MapParams->OriginBase;
1929 if (OriginBase != 0)
1931 IRB.
CreateAdd(OriginLong, ConstantInt::get(IntptrTy, OriginBase));
1937 OriginLong = IRB.
CreateAnd(OriginLong, ConstantInt::get(IntptrTy, ~Mask));
1941 return std::make_pair(ShadowPtr, OriginPtr);
1946 Value *ShadowOffset) {
1954 Value *ShadowOffset = getShadowOffset(
Addr, IRB);
1955 return getShadowAddress(
Addr, Pos, ShadowOffset);
1960 Value *PrimitiveValue = combineShadows(V1, V2, Pos);
1961 return expandFromPrimitiveShadow(
T, PrimitiveValue, Pos);
1968 if (DFS.isZeroShadow(V1))
1969 return collapseToPrimitiveShadow(V2, Pos);
1970 if (DFS.isZeroShadow(V2))
1971 return collapseToPrimitiveShadow(V1, Pos);
1973 return collapseToPrimitiveShadow(V1, Pos);
1975 auto V1Elems = ShadowElements.
find(V1);
1976 auto V2Elems = ShadowElements.
find(V2);
1977 if (V1Elems != ShadowElements.
end() && V2Elems != ShadowElements.
end()) {
1979 return collapseToPrimitiveShadow(V1, Pos);
1982 return collapseToPrimitiveShadow(V2, Pos);
1984 }
else if (V1Elems != ShadowElements.
end()) {
1985 if (V1Elems->second.count(V2))
1986 return collapseToPrimitiveShadow(V1, Pos);
1987 }
else if (V2Elems != ShadowElements.
end()) {
1988 if (V2Elems->second.count(V1))
1989 return collapseToPrimitiveShadow(V2, Pos);
1992 auto Key = std::make_pair(V1, V2);
1995 CachedShadow &CCS = CachedShadows[
Key];
1996 if (CCS.Block && DT.
dominates(CCS.Block, Pos->getParent()))
2000 Value *PV1 = collapseToPrimitiveShadow(V1, Pos);
2001 Value *PV2 = collapseToPrimitiveShadow(V2, Pos);
2004 CCS.Block = Pos->getParent();
2005 CCS.Shadow = IRB.
CreateOr(PV1, PV2);
2007 std::set<Value *> UnionElems;
2008 if (V1Elems != ShadowElements.
end()) {
2009 UnionElems = V1Elems->second;
2011 UnionElems.insert(V1);
2013 if (V2Elems != ShadowElements.
end()) {
2014 UnionElems.insert(V2Elems->second.begin(), V2Elems->second.end());
2016 UnionElems.insert(V2);
2018 ShadowElements[CCS.Shadow] = std::move(UnionElems);
2028 return DFS.getZeroShadow(Inst);
2032 Shadow = combineShadows(Shadow, getShadow(Inst->
getOperand(
I)),
2035 return expandFromPrimitiveShadow(Inst->
getType(), Shadow,
2040 Value *CombinedShadow = DFSF.combineOperandShadows(&
I);
2041 DFSF.setShadow(&
I, CombinedShadow);
2042 visitInstOperandOrigins(
I);
2045Value *DFSanFunction::combineOrigins(
const std::vector<Value *> &Shadows,
2046 const std::vector<Value *> &Origins,
2049 assert(Shadows.size() == Origins.size());
2050 size_t Size = Origins.size();
2052 return DFS.ZeroOrigin;
2053 Value *Origin =
nullptr;
2055 Zero = DFS.ZeroPrimitiveShadow;
2056 for (
size_t I = 0;
I !=
Size; ++
I) {
2057 Value *OpOrigin = Origins[
I];
2058 Constant *ConstOpOrigin = dyn_cast<Constant>(OpOrigin);
2059 if (ConstOpOrigin && ConstOpOrigin->
isNullValue())
2065 Value *OpShadow = Shadows[
I];
2066 Value *PrimitiveShadow = collapseToPrimitiveShadow(OpShadow, Pos);
2071 return Origin ? Origin : DFS.ZeroOrigin;
2076 std::vector<Value *> Shadows(
Size);
2077 std::vector<Value *> Origins(
Size);
2078 for (
unsigned I = 0;
I !=
Size; ++
I) {
2082 return combineOrigins(Shadows, Origins, Inst->
getIterator());
2085void DFSanVisitor::visitInstOperandOrigins(
Instruction &
I) {
2086 if (!DFSF.DFS.shouldTrackOrigins())
2088 Value *CombinedOrigin = DFSF.combineOperandOrigins(&
I);
2089 DFSF.setOrigin(&
I, CombinedOrigin);
2092Align DFSanFunction::getShadowAlign(
Align InstAlignment) {
2094 return Align(Alignment.
value() * DFS.ShadowWidthBytes);
2097Align DFSanFunction::getOriginAlign(
Align InstAlignment) {
2102bool DFSanFunction::isLookupTableConstant(
Value *
P) {
2103 if (
GlobalVariable *GV = dyn_cast<GlobalVariable>(
P->stripPointerCasts()))
2104 if (GV->isConstant() && GV->
hasName())
2105 return DFS.CombineTaintLookupTableNames.count(GV->
getName());
2110bool DFSanFunction::useCallbackLoadLabelAndOrigin(
uint64_t Size,
2111 Align InstAlignment) {
2135 Value **OriginAddr) {
2138 IRB.
CreateGEP(OriginTy, *OriginAddr, ConstantInt::get(IntptrTy, 1));
2142std::pair<Value *, Value *> DFSanFunction::loadShadowFast(
2145 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins();
2146 const uint64_t ShadowSize =
Size * DFS.ShadowWidthBytes;
2148 assert(
Size >= 4 &&
"Not large enough load size for fast path!");
2151 std::vector<Value *> Shadows;
2152 std::vector<Value *> Origins;
2165 Type *WideShadowTy =
2169 Value *CombinedWideShadow =
2173 const uint64_t BytesPerWideShadow = WideShadowBitWidth / DFS.ShadowWidthBits;
2175 auto AppendWideShadowAndOrigin = [&](
Value *WideShadow,
Value *Origin) {
2176 if (BytesPerWideShadow > 4) {
2177 assert(BytesPerWideShadow == 8);
2185 WideShadow, ConstantInt::get(WideShadowTy, WideShadowBitWidth / 2));
2186 Shadows.push_back(WideShadow);
2187 Origins.push_back(DFS.loadNextOrigin(Pos, OriginAlign, &OriginAddr));
2189 Shadows.push_back(WideShadowLo);
2190 Origins.push_back(Origin);
2192 Shadows.push_back(WideShadow);
2193 Origins.push_back(Origin);
2197 if (ShouldTrackOrigins)
2198 AppendWideShadowAndOrigin(CombinedWideShadow, FirstOrigin);
2205 for (
uint64_t ByteOfs = BytesPerWideShadow; ByteOfs <
Size;
2206 ByteOfs += BytesPerWideShadow) {
2207 ShadowAddr = IRB.
CreateGEP(WideShadowTy, ShadowAddr,
2208 ConstantInt::get(DFS.IntptrTy, 1));
2209 Value *NextWideShadow =
2211 CombinedWideShadow = IRB.
CreateOr(CombinedWideShadow, NextWideShadow);
2212 if (ShouldTrackOrigins) {
2213 Value *NextOrigin = DFS.loadNextOrigin(Pos, OriginAlign, &OriginAddr);
2214 AppendWideShadowAndOrigin(NextWideShadow, NextOrigin);
2217 for (
unsigned Width = WideShadowBitWidth / 2; Width >= DFS.ShadowWidthBits;
2220 CombinedWideShadow = IRB.
CreateOr(CombinedWideShadow, ShrShadow);
2222 return {IRB.
CreateTrunc(CombinedWideShadow, DFS.PrimitiveShadowTy),
2224 ? combineOrigins(Shadows, Origins, Pos,
2229std::pair<Value *, Value *> DFSanFunction::loadShadowOriginSansLoadTracking(
2231 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins();
2235 const auto SI = AllocaShadowMap.
find(AI);
2236 if (SI != AllocaShadowMap.
end()) {
2239 const auto OI = AllocaOriginMap.
find(AI);
2240 assert(!ShouldTrackOrigins || OI != AllocaOriginMap.
end());
2241 return {ShadowLI, ShouldTrackOrigins
2250 bool AllConstants =
true;
2251 for (
const Value *Obj : Objs) {
2252 if (isa<Function>(Obj) || isa<BlockAddress>(Obj))
2254 if (isa<GlobalVariable>(Obj) && cast<GlobalVariable>(Obj)->
isConstant())
2257 AllConstants =
false;
2261 return {DFS.ZeroPrimitiveShadow,
2262 ShouldTrackOrigins ? DFS.ZeroOrigin :
nullptr};
2265 return {DFS.ZeroPrimitiveShadow,
2266 ShouldTrackOrigins ? DFS.ZeroOrigin :
nullptr};
2270 if (ShouldTrackOrigins &&
2271 useCallbackLoadLabelAndOrigin(
Size, InstAlignment)) {
2274 IRB.
CreateCall(DFS.DFSanLoadLabelAndOriginFn,
2275 {Addr, ConstantInt::get(DFS.IntptrTy, Size)});
2276 Call->addRetAttr(Attribute::ZExt);
2278 DFS.PrimitiveShadowTy),
2283 Value *ShadowAddr, *OriginAddr;
2284 std::tie(ShadowAddr, OriginAddr) =
2285 DFS.getShadowOriginAddress(
Addr, InstAlignment, Pos);
2287 const Align ShadowAlign = getShadowAlign(InstAlignment);
2288 const Align OriginAlign = getOriginAlign(InstAlignment);
2289 Value *Origin =
nullptr;
2290 if (ShouldTrackOrigins) {
2301 return {LI, Origin};
2305 Value *ShadowAddr1 = IRB.
CreateGEP(DFS.PrimitiveShadowTy, ShadowAddr,
2306 ConstantInt::get(DFS.IntptrTy, 1));
2311 return {combineShadows(Load, Load1, Pos), Origin};
2314 bool HasSizeForFastPath = DFS.hasLoadSizeForFastPath(
Size);
2316 if (HasSizeForFastPath)
2317 return loadShadowFast(ShadowAddr, OriginAddr,
Size, ShadowAlign,
2318 OriginAlign, Origin, Pos);
2322 DFS.DFSanUnionLoadFn, {ShadowAddr, ConstantInt::get(DFS.IntptrTy, Size)});
2324 return {FallbackCall, Origin};
2327std::pair<Value *, Value *>
2330 Value *PrimitiveShadow, *Origin;
2331 std::tie(PrimitiveShadow, Origin) =
2332 loadShadowOriginSansLoadTracking(
Addr,
Size, InstAlignment, Pos);
2333 if (DFS.shouldTrackOrigins()) {
2336 auto *ConstantShadow = dyn_cast<Constant>(PrimitiveShadow);
2337 if (!ConstantShadow || !ConstantShadow->isZeroValue())
2338 Origin = updateOriginIfTainted(PrimitiveShadow, Origin, IRB);
2341 return {PrimitiveShadow, Origin};
2346 case AtomicOrdering::NotAtomic:
2347 return AtomicOrdering::NotAtomic;
2348 case AtomicOrdering::Unordered:
2349 case AtomicOrdering::Monotonic:
2350 case AtomicOrdering::Acquire:
2351 return AtomicOrdering::Acquire;
2352 case AtomicOrdering::Release:
2353 case AtomicOrdering::AcquireRelease:
2354 return AtomicOrdering::AcquireRelease;
2355 case AtomicOrdering::SequentiallyConsistent:
2356 return AtomicOrdering::SequentiallyConsistent;
2362 if (!V->getType()->isPointerTy())
2370 if (
auto *
GEP = dyn_cast<GEPOperator>(V)) {
2371 V =
GEP->getPointerOperand();
2373 V = cast<Operator>(V)->getOperand(0);
2374 if (!V->getType()->isPointerTy())
2376 }
else if (isa<GlobalAlias>(V)) {
2377 V = cast<GlobalAlias>(V)->getAliasee();
2379 }
while (Visited.
insert(V).second);
2384void DFSanVisitor::visitLoadInst(
LoadInst &LI) {
2388 DFSF.setShadow(&LI, DFSF.DFS.getZeroShadow(&LI));
2389 DFSF.setOrigin(&LI, DFSF.DFS.ZeroOrigin);
2404 Pos = std::next(Pos);
2406 std::vector<Value *> Shadows;
2407 std::vector<Value *> Origins;
2408 Value *PrimitiveShadow, *Origin;
2409 std::tie(PrimitiveShadow, Origin) =
2411 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
2412 if (ShouldTrackOrigins) {
2413 Shadows.push_back(PrimitiveShadow);
2414 Origins.push_back(Origin);
2417 DFSF.isLookupTableConstant(
2420 PrimitiveShadow = DFSF.combineShadows(PrimitiveShadow, PtrShadow, Pos);
2421 if (ShouldTrackOrigins) {
2422 Shadows.push_back(PtrShadow);
2426 if (!DFSF.DFS.isZeroShadow(PrimitiveShadow))
2427 DFSF.NonZeroChecks.push_back(PrimitiveShadow);
2430 DFSF.expandFromPrimitiveShadow(LI.
getType(), PrimitiveShadow, Pos);
2431 DFSF.setShadow(&LI, Shadow);
2433 if (ShouldTrackOrigins) {
2434 DFSF.setOrigin(&LI, DFSF.combineOrigins(Shadows, Origins, Pos));
2441 IRB.
CreateCall(DFSF.DFS.DFSanLoadCallbackFn, {PrimitiveShadow, Addr});
2446 DFSF.addReachesFunctionCallbacksIfEnabled(IRB, LI, &LI);
2449Value *DFSanFunction::updateOriginIfTainted(
Value *Shadow,
Value *Origin,
2451 assert(DFS.shouldTrackOrigins());
2452 return IRB.
CreateCall(DFS.DFSanChainOriginIfTaintedFn, {Shadow, Origin});
2456 if (!DFS.shouldTrackOrigins())
2458 return IRB.
CreateCall(DFS.DFSanChainOriginFn, V);
2462 const unsigned OriginSize = DataFlowSanitizer::OriginWidthBytes;
2464 unsigned IntptrSize =
DL.getTypeStoreSize(DFS.IntptrTy);
2465 if (IntptrSize == OriginSize)
2467 assert(IntptrSize == OriginSize * 2);
2473 Value *StoreOriginAddr,
2475 const unsigned OriginSize = DataFlowSanitizer::OriginWidthBytes;
2477 const Align IntptrAlignment =
DL.getABITypeAlign(DFS.IntptrTy);
2478 unsigned IntptrSize =
DL.getTypeStoreSize(DFS.IntptrTy);
2480 assert(IntptrSize >= OriginSize);
2483 Align CurrentAlignment = Alignment;
2484 if (Alignment >= IntptrAlignment && IntptrSize > OriginSize) {
2485 Value *IntptrOrigin = originToIntptr(IRB, Origin);
2486 Value *IntptrStoreOriginPtr =
2488 for (
unsigned I = 0;
I < StoreOriginSize / IntptrSize; ++
I) {
2491 : IntptrStoreOriginPtr;
2493 Ofs += IntptrSize / OriginSize;
2494 CurrentAlignment = IntptrAlignment;
2498 for (
unsigned I = Ofs;
I < (StoreOriginSize + OriginSize - 1) / OriginSize;
2509 Type *VTy =
V->getType();
2519 Value *StoreOriginAddr,
Align InstAlignment) {
2522 const Align OriginAlignment = getOriginAlign(InstAlignment);
2523 Value *CollapsedShadow = collapseToPrimitiveShadow(Shadow, Pos);
2525 if (
auto *ConstantShadow = dyn_cast<Constant>(CollapsedShadow)) {
2526 if (!ConstantShadow->isZeroValue())
2527 paintOrigin(IRB, updateOrigin(Origin, IRB), StoreOriginAddr,
Size,
2532 if (shouldInstrumentWithCall()) {
2534 DFS.DFSanMaybeStoreOriginFn,
2535 {CollapsedShadow, Addr, ConstantInt::get(DFS.IntptrTy, Size), Origin});
2537 Value *
Cmp = convertToBool(CollapsedShadow, IRB,
"_dfscmp");
2540 Cmp, &*IRB.
GetInsertPoint(),
false, DFS.OriginStoreWeights, &DTU);
2542 paintOrigin(IRBNew, updateOrigin(Origin, IRBNew), StoreOriginAddr,
Size,
2554 Value *ExtZeroShadow = ConstantInt::get(ShadowTy, 0);
2555 Value *ShadowAddr = DFS.getShadowAddress(
Addr, Pos);
2562 Align InstAlignment,
2563 Value *PrimitiveShadow,
2566 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins() && Origin;
2569 const auto SI = AllocaShadowMap.
find(AI);
2570 if (SI != AllocaShadowMap.
end()) {
2576 if (ShouldTrackOrigins && !DFS.isZeroShadow(PrimitiveShadow)) {
2577 const auto OI = AllocaOriginMap.
find(AI);
2578 assert(OI != AllocaOriginMap.
end() && Origin);
2585 const Align ShadowAlign = getShadowAlign(InstAlignment);
2586 if (DFS.isZeroShadow(PrimitiveShadow)) {
2587 storeZeroPrimitiveShadow(
Addr,
Size, ShadowAlign, Pos);
2592 Value *ShadowAddr, *OriginAddr;
2593 std::tie(ShadowAddr, OriginAddr) =
2594 DFS.getShadowOriginAddress(
Addr, InstAlignment, Pos);
2596 const unsigned ShadowVecSize = 8;
2597 assert(ShadowVecSize * DFS.ShadowWidthBits <= 128 &&
2598 "Shadow vector is too large!");
2602 if (LeftSize >= ShadowVecSize) {
2606 for (
unsigned I = 0;
I != ShadowVecSize; ++
I) {
2608 ShadowVec, PrimitiveShadow,
2612 Value *CurShadowVecAddr =
2615 LeftSize -= ShadowVecSize;
2617 }
while (LeftSize >= ShadowVecSize);
2620 while (LeftSize > 0) {
2621 Value *CurShadowAddr =
2628 if (ShouldTrackOrigins) {
2629 storeOrigin(Pos,
Addr,
Size, PrimitiveShadow, Origin, OriginAddr,
2636 case AtomicOrdering::NotAtomic:
2637 return AtomicOrdering::NotAtomic;
2638 case AtomicOrdering::Unordered:
2639 case AtomicOrdering::Monotonic:
2640 case AtomicOrdering::Release:
2641 return AtomicOrdering::Release;
2642 case AtomicOrdering::Acquire:
2643 case AtomicOrdering::AcquireRelease:
2644 return AtomicOrdering::AcquireRelease;
2645 case AtomicOrdering::SequentiallyConsistent:
2646 return AtomicOrdering::SequentiallyConsistent;
2651void DFSanVisitor::visitStoreInst(
StoreInst &SI) {
2652 auto &
DL =
SI.getDataLayout();
2653 Value *Val =
SI.getValueOperand();
2666 const bool ShouldTrackOrigins =
2667 DFSF.DFS.shouldTrackOrigins() && !
SI.isAtomic();
2668 std::vector<Value *> Shadows;
2669 std::vector<Value *> Origins;
2672 SI.isAtomic() ? DFSF.DFS.getZeroShadow(Val) : DFSF.getShadow(Val);
2674 if (ShouldTrackOrigins) {
2675 Shadows.push_back(Shadow);
2676 Origins.push_back(DFSF.getOrigin(Val));
2679 Value *PrimitiveShadow;
2681 Value *PtrShadow = DFSF.getShadow(
SI.getPointerOperand());
2682 if (ShouldTrackOrigins) {
2683 Shadows.push_back(PtrShadow);
2684 Origins.push_back(DFSF.getOrigin(
SI.getPointerOperand()));
2686 PrimitiveShadow = DFSF.combineShadows(Shadow, PtrShadow,
SI.getIterator());
2688 PrimitiveShadow = DFSF.collapseToPrimitiveShadow(Shadow,
SI.getIterator());
2690 Value *Origin =
nullptr;
2691 if (ShouldTrackOrigins)
2692 Origin = DFSF.combineOrigins(Shadows, Origins,
SI.getIterator());
2693 DFSF.storePrimitiveShadowOrigin(
SI.getPointerOperand(),
Size,
SI.getAlign(),
2694 PrimitiveShadow, Origin,
SI.getIterator());
2699 IRB.
CreateCall(DFSF.DFS.DFSanStoreCallbackFn, {PrimitiveShadow, Addr});
2705 assert(isa<AtomicRMWInst>(
I) || isa<AtomicCmpXchgInst>(
I));
2707 Value *Val =
I.getOperand(1);
2708 const auto &
DL =
I.getDataLayout();
2717 const Align ShadowAlign = DFSF.getShadowAlign(InstAlignment);
2718 DFSF.storeZeroPrimitiveShadow(
Addr,
Size, ShadowAlign,
I.getIterator());
2719 DFSF.setShadow(&
I, DFSF.DFS.getZeroShadow(&
I));
2720 DFSF.setOrigin(&
I, DFSF.DFS.ZeroOrigin);
2724 visitCASOrRMW(
I.getAlign(),
I);
2731 visitCASOrRMW(
I.getAlign(),
I);
2738 visitInstOperands(UO);
2742 visitInstOperands(BO);
2745void DFSanVisitor::visitBitCastInst(
BitCastInst &BCI) {
2749 if (
auto *CI = dyn_cast<CallInst>(BCI.
getOperand(0)))
2752 visitInstOperands(BCI);
2755void DFSanVisitor::visitCastInst(
CastInst &CI) { visitInstOperands(CI); }
2757void DFSanVisitor::visitCmpInst(
CmpInst &CI) {
2758 visitInstOperands(CI);
2761 Value *CombinedShadow = DFSF.getShadow(&CI);
2763 IRB.
CreateCall(DFSF.DFS.DFSanCmpCallbackFn, CombinedShadow);
2780 DFSF.setShadow(&LPI, DFSF.DFS.getZeroShadow(&LPI));
2781 DFSF.setOrigin(&LPI, DFSF.DFS.ZeroOrigin);
2786 DFSF.isLookupTableConstant(
2788 visitInstOperands(GEPI);
2795 DFSF.setShadow(&GEPI, DFSF.getShadow(BasePointer));
2796 if (DFSF.DFS.shouldTrackOrigins())
2797 DFSF.setOrigin(&GEPI, DFSF.getOrigin(BasePointer));
2801 visitInstOperands(
I);
2805 visitInstOperands(
I);
2809 visitInstOperands(
I);
2814 Value *Agg =
I.getAggregateOperand();
2815 Value *AggShadow = DFSF.getShadow(Agg);
2817 DFSF.setShadow(&
I, ResShadow);
2818 visitInstOperandOrigins(
I);
2823 Value *AggShadow = DFSF.getShadow(
I.getAggregateOperand());
2824 Value *InsShadow = DFSF.getShadow(
I.getInsertedValueOperand());
2826 DFSF.setShadow(&
I, Res);
2827 visitInstOperandOrigins(
I);
2830void DFSanVisitor::visitAllocaInst(
AllocaInst &
I) {
2831 bool AllLoadsStores =
true;
2832 for (
User *U :
I.users()) {
2833 if (isa<LoadInst>(U))
2836 if (
StoreInst *SI = dyn_cast<StoreInst>(U)) {
2837 if (
SI->getPointerOperand() == &
I)
2841 AllLoadsStores =
false;
2844 if (AllLoadsStores) {
2846 DFSF.AllocaShadowMap[&
I] = IRB.
CreateAlloca(DFSF.DFS.PrimitiveShadowTy);
2847 if (DFSF.DFS.shouldTrackOrigins()) {
2848 DFSF.AllocaOriginMap[&
I] =
2852 DFSF.setShadow(&
I, DFSF.DFS.ZeroPrimitiveShadow);
2853 DFSF.setOrigin(&
I, DFSF.DFS.ZeroOrigin);
2856void DFSanVisitor::visitSelectInst(
SelectInst &
I) {
2857 Value *CondShadow = DFSF.getShadow(
I.getCondition());
2858 Value *TrueShadow = DFSF.getShadow(
I.getTrueValue());
2859 Value *FalseShadow = DFSF.getShadow(
I.getFalseValue());
2860 Value *ShadowSel =
nullptr;
2861 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
2862 std::vector<Value *> Shadows;
2863 std::vector<Value *> Origins;
2865 ShouldTrackOrigins ? DFSF.getOrigin(
I.getTrueValue()) :
nullptr;
2866 Value *FalseOrigin =
2867 ShouldTrackOrigins ? DFSF.getOrigin(
I.getFalseValue()) :
nullptr;
2869 DFSF.addConditionalCallbacksIfEnabled(
I,
I.getCondition());
2871 if (isa<VectorType>(
I.getCondition()->getType())) {
2872 ShadowSel = DFSF.combineShadowsThenConvert(
I.getType(), TrueShadow,
2873 FalseShadow,
I.getIterator());
2874 if (ShouldTrackOrigins) {
2875 Shadows.push_back(TrueShadow);
2876 Shadows.push_back(FalseShadow);
2877 Origins.push_back(TrueOrigin);
2878 Origins.push_back(FalseOrigin);
2881 if (TrueShadow == FalseShadow) {
2882 ShadowSel = TrueShadow;
2883 if (ShouldTrackOrigins) {
2884 Shadows.push_back(TrueShadow);
2885 Origins.push_back(TrueOrigin);
2889 "",
I.getIterator());
2890 if (ShouldTrackOrigins) {
2891 Shadows.push_back(ShadowSel);
2893 FalseOrigin,
"",
I.getIterator()));
2898 I.getType(), CondShadow,
2899 ShadowSel,
I.getIterator())
2901 if (ShouldTrackOrigins) {
2903 Shadows.push_back(CondShadow);
2904 Origins.push_back(DFSF.getOrigin(
I.getCondition()));
2906 DFSF.setOrigin(&
I, DFSF.combineOrigins(Shadows, Origins,
I.getIterator()));
2910void DFSanVisitor::visitMemSetInst(
MemSetInst &
I) {
2912 Value *ValShadow = DFSF.getShadow(
I.getValue());
2913 Value *ValOrigin = DFSF.DFS.shouldTrackOrigins()
2914 ? DFSF.getOrigin(
I.getValue())
2915 : DFSF.DFS.ZeroOrigin;
2917 {ValShadow, ValOrigin, I.getDest(),
2918 IRB.CreateZExtOrTrunc(I.getLength(), DFSF.DFS.IntptrTy)});
2926 if (DFSF.DFS.shouldTrackOrigins()) {
2928 DFSF.DFS.DFSanMemOriginTransferFn,
2929 {I.getArgOperand(0), I.getArgOperand(1),
2930 IRB.CreateIntCast(I.getArgOperand(2), DFSF.DFS.IntptrTy, false)});
2933 Value *DestShadow = DFSF.DFS.getShadowAddress(
I.getDest(),
I.getIterator());
2934 Value *SrcShadow = DFSF.DFS.getShadowAddress(
I.getSource(),
I.getIterator());
2936 IRB.
CreateMul(
I.getLength(), ConstantInt::get(
I.getLength()->getType(),
2937 DFSF.DFS.ShadowWidthBytes));
2938 auto *MTI = cast<MemTransferInst>(
2939 IRB.
CreateCall(
I.getFunctionType(),
I.getCalledOperand(),
2940 {DestShadow, SrcShadow, LenShadow, I.getVolatileCst()}));
2941 MTI->setDestAlignment(DFSF.getShadowAlign(
I.getDestAlign().valueOrOne()));
2942 MTI->setSourceAlignment(DFSF.getShadowAlign(
I.getSourceAlign().valueOrOne()));
2945 DFSF.DFS.DFSanMemTransferCallbackFn,
2946 {DestShadow, IRB.CreateZExtOrTrunc(I.getLength(), DFSF.DFS.IntptrTy)});
2950void DFSanVisitor::visitBranchInst(
BranchInst &BR) {
2951 if (!
BR.isConditional())
2954 DFSF.addConditionalCallbacksIfEnabled(BR,
BR.getCondition());
2957void DFSanVisitor::visitSwitchInst(
SwitchInst &SW) {
2958 DFSF.addConditionalCallbacksIfEnabled(SW, SW.
getCondition());
2963 if (
auto *
I = dyn_cast<BitCastInst>(RetVal)) {
2964 RetVal =
I->getOperand(0);
2966 if (
auto *
I = dyn_cast<CallInst>(RetVal)) {
2967 return I->isMustTailCall();
2972void DFSanVisitor::visitReturnInst(
ReturnInst &RI) {
2980 Type *RT = DFSF.F->getFunctionType()->getReturnType();
2981 unsigned Size = getDataLayout().getTypeAllocSize(DFSF.DFS.getShadowTy(RT));
2987 if (DFSF.DFS.shouldTrackOrigins()) {
2995 std::vector<Value *> &Args,
3002 for (
unsigned N = FT->getNumParams();
N != 0; ++
I, --
N)
3004 DFSF.collapseToPrimitiveShadow(DFSF.getShadow(*
I), CB.
getIterator()));
3007 if (FT->isVarArg()) {
3008 auto *LabelVATy = ArrayType::get(DFSF.DFS.PrimitiveShadowTy,
3009 CB.
arg_size() - FT->getNumParams());
3010 auto *LabelVAAlloca =
3011 new AllocaInst(LabelVATy, getDataLayout().getAllocaAddrSpace(),
3012 "labelva", DFSF.F->getEntryBlock().begin());
3014 for (
unsigned N = 0;
I != CB.
arg_end(); ++
I, ++
N) {
3017 DFSF.collapseToPrimitiveShadow(DFSF.getShadow(*
I), CB.
getIterator()),
3025 if (!FT->getReturnType()->isVoidTy()) {
3026 if (!DFSF.LabelReturnAlloca) {
3028 DFSF.DFS.PrimitiveShadowTy, getDataLayout().getAllocaAddrSpace(),
3029 "labelreturn", DFSF.F->getEntryBlock().begin());
3031 Args.push_back(DFSF.LabelReturnAlloca);
3036 std::vector<Value *> &Args,
3043 for (
unsigned N = FT->getNumParams();
N != 0; ++
I, --
N)
3044 Args.push_back(DFSF.getOrigin(*
I));
3047 if (FT->isVarArg()) {
3049 ArrayType::get(DFSF.DFS.OriginTy, CB.
arg_size() - FT->getNumParams());
3050 auto *OriginVAAlloca =
3051 new AllocaInst(OriginVATy, getDataLayout().getAllocaAddrSpace(),
3052 "originva", DFSF.F->getEntryBlock().begin());
3054 for (
unsigned N = 0;
I != CB.
arg_end(); ++
I, ++
N) {
3063 if (!FT->getReturnType()->isVoidTy()) {
3064 if (!DFSF.OriginReturnAlloca) {
3066 DFSF.DFS.OriginTy, getDataLayout().getAllocaAddrSpace(),
3067 "originreturn", DFSF.F->getEntryBlock().begin());
3069 Args.push_back(DFSF.OriginReturnAlloca);
3075 switch (DFSF.DFS.getWrapperKind(&
F)) {
3076 case DataFlowSanitizer::WK_Warning:
3078 IRB.
CreateCall(DFSF.DFS.DFSanUnimplementedFn,
3080 DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &
F);
3081 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3082 DFSF.setOrigin(&CB, DFSF.DFS.ZeroOrigin);
3084 case DataFlowSanitizer::WK_Discard:
3086 DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &
F);
3087 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3088 DFSF.setOrigin(&CB, DFSF.DFS.ZeroOrigin);
3090 case DataFlowSanitizer::WK_Functional:
3092 DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &
F);
3093 visitInstOperands(CB);
3095 case DataFlowSanitizer::WK_Custom:
3099 CallInst *CI = dyn_cast<CallInst>(&CB);
3103 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
3105 TransformedFunction CustomFn = DFSF.DFS.getCustomFunctionType(FT);
3106 std::string CustomFName = ShouldTrackOrigins ?
"__dfso_" :
"__dfsw_";
3107 CustomFName +=
F.getName();
3109 CustomFName, CustomFn.TransformedType);
3111 CustomFn->copyAttributesFrom(&
F);
3114 if (!FT->getReturnType()->isVoidTy()) {
3115 CustomFn->removeFnAttrs(DFSF.DFS.ReadOnlyNoneAttrs);
3119 std::vector<Value *>
Args;
3123 for (
unsigned N = FT->getNumParams();
N != 0; ++
I, --
N) {
3128 const unsigned ShadowArgStart =
Args.size();
3129 addShadowArguments(
F, CB, Args, IRB);
3132 const unsigned OriginArgStart =
Args.size();
3133 if (ShouldTrackOrigins)
3134 addOriginArguments(
F, CB, Args, IRB);
3147 for (
unsigned N = 0;
N < FT->getNumParams();
N++) {
3148 const unsigned ArgNo = ShadowArgStart +
N;
3150 DFSF.DFS.PrimitiveShadowTy)
3152 if (ShouldTrackOrigins) {
3153 const unsigned OriginArgNo = OriginArgStart +
N;
3161 if (!FT->getReturnType()->isVoidTy()) {
3163 IRB.
CreateLoad(DFSF.DFS.PrimitiveShadowTy, DFSF.LabelReturnAlloca);
3164 DFSF.setShadow(CustomCI,
3165 DFSF.expandFromPrimitiveShadow(
3166 FT->getReturnType(), LabelLoad, CB.
getIterator()));
3167 if (ShouldTrackOrigins) {
3169 IRB.
CreateLoad(DFSF.DFS.OriginTy, DFSF.OriginReturnAlloca);
3170 DFSF.setOrigin(CustomCI, OriginLoad);
3182 constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
3183 uint32_t OrderingTable[NumOrderings] = {};
3185 OrderingTable[(int)AtomicOrderingCABI::relaxed] =
3186 OrderingTable[(
int)AtomicOrderingCABI::acquire] =
3187 OrderingTable[(int)AtomicOrderingCABI::consume] =
3188 (
int)AtomicOrderingCABI::acquire;
3189 OrderingTable[(int)AtomicOrderingCABI::release] =
3190 OrderingTable[(
int)AtomicOrderingCABI::acq_rel] =
3191 (int)AtomicOrderingCABI::acq_rel;
3192 OrderingTable[(int)AtomicOrderingCABI::seq_cst] =
3193 (
int)AtomicOrderingCABI::seq_cst;
3198void DFSanVisitor::visitLibAtomicLoad(
CallBase &CB) {
3200 assert(isa<CallInst>(CB));
3209 Value *NewOrdering =
3214 NextIRB.SetCurrentDebugLocation(CB.
getDebugLoc());
3220 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3221 {DstPtr, SrcPtr, NextIRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3225 constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
3226 uint32_t OrderingTable[NumOrderings] = {};
3228 OrderingTable[(int)AtomicOrderingCABI::relaxed] =
3229 OrderingTable[(
int)AtomicOrderingCABI::release] =
3230 (int)AtomicOrderingCABI::release;
3231 OrderingTable[(int)AtomicOrderingCABI::consume] =
3232 OrderingTable[(
int)AtomicOrderingCABI::acquire] =
3233 OrderingTable[(int)AtomicOrderingCABI::acq_rel] =
3234 (
int)AtomicOrderingCABI::acq_rel;
3235 OrderingTable[(int)AtomicOrderingCABI::seq_cst] =
3236 (
int)AtomicOrderingCABI::seq_cst;
3241void DFSanVisitor::visitLibAtomicStore(
CallBase &CB) {
3249 Value *NewOrdering =
3257 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3258 {DstPtr, SrcPtr, IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3261void DFSanVisitor::visitLibAtomicExchange(
CallBase &CB) {
3277 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3278 {DstPtr, TargetPtr, IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3282 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3283 {TargetPtr, SrcPtr, IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3286void DFSanVisitor::visitLibAtomicCompareExchange(
CallBase &CB) {
3300 NextIRB.SetCurrentDebugLocation(CB.
getDebugLoc());
3302 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3306 NextIRB.CreateCall(DFSF.DFS.DFSanMemShadowOriginConditionalExchangeFn,
3307 {NextIRB.CreateIntCast(&CB, NextIRB.getInt8Ty(), false),
3308 TargetPtr, ExpectedPtr, DesiredPtr,
3309 NextIRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3312void DFSanVisitor::visitCallBase(
CallBase &CB) {
3315 visitInstOperands(CB);
3321 if (
F == DFSF.DFS.DFSanVarargWrapperFn.getCallee()->stripPointerCasts())
3325 if (DFSF.TLI.getLibFunc(CB, LF)) {
3330 case LibFunc_atomic_load:
3331 if (!isa<CallInst>(CB)) {
3332 llvm::errs() <<
"DFSAN -- cannot instrument invoke of libatomic load. "
3336 visitLibAtomicLoad(CB);
3338 case LibFunc_atomic_store:
3339 visitLibAtomicStore(CB);
3347 if (
F &&
F->hasName() && !
F->isVarArg()) {
3348 if (
F->getName() ==
"__atomic_exchange") {
3349 visitLibAtomicExchange(CB);
3352 if (
F->getName() ==
"__atomic_compare_exchange") {
3353 visitLibAtomicCompareExchange(CB);
3360 if (UnwrappedFnIt != DFSF.DFS.UnwrappedFnMap.end())
3361 if (visitWrappedCallBase(*UnwrappedFnIt->second, CB))
3366 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
3371 unsigned ArgOffset = 0;
3372 for (
unsigned I = 0,
N = FT->getNumParams();
I !=
N; ++
I) {
3373 if (ShouldTrackOrigins) {
3376 if (
I < DFSF.DFS.NumOfElementsInArgOrgTLS &&
3377 !DFSF.DFS.isZeroShadow(ArgShadow))
3379 DFSF.getArgOriginTLS(
I, IRB));
3383 DL.getTypeAllocSize(DFSF.DFS.getShadowTy(FT->getParamType(
I)));
3389 DFSF.getArgTLS(FT->getParamType(
I), ArgOffset, IRB),
3397 if (
II->getNormalDest()->getSinglePredecessor()) {
3398 Next = &
II->getNormalDest()->front();
3402 Next = &NewBB->
front();
3410 if (isa<CallInst>(CB) && cast<CallInst>(CB).isMustTailCall())
3415 unsigned Size =
DL.getTypeAllocSize(DFSF.DFS.getShadowTy(&CB));
3418 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3420 LoadInst *LI = NextIRB.CreateAlignedLoad(
3421 DFSF.DFS.getShadowTy(&CB), DFSF.getRetvalTLS(CB.
getType(), NextIRB),
3423 DFSF.SkipInsts.insert(LI);
3424 DFSF.setShadow(&CB, LI);
3425 DFSF.NonZeroChecks.push_back(LI);
3428 if (ShouldTrackOrigins) {
3429 LoadInst *LI = NextIRB.CreateLoad(DFSF.DFS.OriginTy,
3430 DFSF.getRetvalOriginTLS(),
"_dfsret_o");
3431 DFSF.SkipInsts.insert(LI);
3432 DFSF.setOrigin(&CB, LI);
3435 DFSF.addReachesFunctionCallbacksIfEnabled(NextIRB, CB, &CB);
3439void DFSanVisitor::visitPHINode(
PHINode &PN) {
3440 Type *ShadowTy = DFSF.DFS.getShadowTy(&PN);
3449 DFSF.setShadow(&PN, ShadowPN);
3452 if (DFSF.DFS.shouldTrackOrigins()) {
3458 DFSF.setOrigin(&PN, OriginPN);
3461 DFSF.PHIFixups.push_back({&PN, ShadowPN, OriginPN});
3474 if (!DataFlowSanitizer(ABIListFiles).runImpl(M, GetTLI))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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
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,...
LLVM_ABI AttributeSet getFnAttrs() const
The function attributes are returned.
static LLVM_ABI AttributeList get(LLVMContext &C, ArrayRef< std::pair< unsigned, Attribute > > Attrs)
Create an AttributeList with the specified parameters in it.
LLVM_ABI AttributeSet getRetAttrs() const
The attributes for the ret value are returned.
LLVM_ABI unsigned getNumAttrSets() const
LLVM_ABI 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 LLVM_ABI 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 LLVM_ABI ConstantAggregateZero * get(Type *Ty)
static LLVM_ABI 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.
LLVM_ABI bool isNullValue() const
Return true if this is the value that would be returned by getNullValue.
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
A parsed version of the target data layout string in and methods for querying it.
LLVM_ABI unsigned getLine() const
LLVM_ABI 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.
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
static LLVM_ABI 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()
LLVM_ABI void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
LLVM_ABI 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="")
LLVM_ABI 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 * 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 * CreateOr(Value *LHS, Value *RHS, const Twine &Name="", bool IsDisjoint=false)
Value * CreateMul(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
LLVM_ABI 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.
LLVM_ABI bool isAtomic() const LLVM_READONLY
Return true if this instruction has an AtomicOrdering of unordered or higher.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
bool isTerminator() const
LLVM_ABI 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.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
Class to represent integer types.
static LLVM_ABI 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.
LLVM_ABI 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 LLVM_ABI 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.
PreservedAnalyses & 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 LLVM_ABI 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.
void insert_range(Range &&R)
Class to represent struct types.
static LLVM_ABI 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.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
bool isSized(SmallPtrSetImpl< Type * > *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
bool isIntegerTy() const
True if this is an instance of IntegerType.
bool isVoidTy() const
Return true if this is 'void'.
LLVM_ABI unsigned getIntegerBitWidth() const
static LLVM_ABI 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.
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVM_ABI const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
LLVM_ABI LLVMContext & getContext() const
All values hold a context through their type.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
LLVM_ABI 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.
LLVM_ABI 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
LLVM_ABI 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.
bool includes(R1 &&Range1, R2 &&Range2)
Provide wrappers to std::includes which take ranges instead of having to pass begin/end explicitly.
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:
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
LLVM_ABI 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.
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)
LLVM_ABI 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 ...
LLVM_ABI 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...
LLVM_ABI void getUnderlyingObjects(const Value *V, SmallVectorImpl< const Value * > &Objects, const LoopInfo *LI=nullptr, unsigned MaxLookup=MaxLookupSearchDepth)
This method is similar to getUnderlyingObject except that it can look through phi and select instruct...
LLVM_ABI bool removeUnreachableBlocks(Function &F, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr)
Remove all blocks that can not be reached from the function's entry.
LLVM_ABI 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.