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(),
1093 std::vector<Value *>
args;
1095 if (DFS.shouldTrackOrigins()) {
1096 Value *DataOrigin = getOrigin(Data);
1097 args = { DataShadow, DataOrigin, FilePathPtr, CILine, FunctionNamePtr };
1098 CB = IRB.
CreateCall(DFS.DFSanReachesFunctionCallbackOriginFn,
args);
1100 args = { DataShadow, FilePathPtr, CILine, FunctionNamePtr };
1107Type *DataFlowSanitizer::getShadowTy(
Type *OrigTy) {
1109 return PrimitiveShadowTy;
1110 if (isa<IntegerType>(OrigTy))
1111 return PrimitiveShadowTy;
1112 if (isa<VectorType>(OrigTy))
1113 return PrimitiveShadowTy;
1114 if (
ArrayType *AT = dyn_cast<ArrayType>(OrigTy))
1115 return ArrayType::get(getShadowTy(AT->getElementType()),
1116 AT->getNumElements());
1117 if (
StructType *ST = dyn_cast<StructType>(OrigTy)) {
1119 for (
unsigned I = 0,
N =
ST->getNumElements();
I <
N; ++
I)
1120 Elements.push_back(getShadowTy(
ST->getElementType(
I)));
1123 return PrimitiveShadowTy;
1126Type *DataFlowSanitizer::getShadowTy(
Value *V) {
1127 return getShadowTy(
V->getType());
1130bool DataFlowSanitizer::initializeModule(
Module &M) {
1131 Triple TargetTriple(
M.getTargetTriple());
1136 switch (TargetTriple.getArch()) {
1151 Ctx = &
M.getContext();
1152 Int8Ptr = PointerType::getUnqual(*Ctx);
1154 OriginPtrTy = PointerType::getUnqual(OriginTy);
1156 PrimitiveShadowPtrTy = PointerType::getUnqual(PrimitiveShadowTy);
1157 IntptrTy =
DL.getIntPtrType(*Ctx);
1161 Type *DFSanUnionLoadArgs[2] = {PrimitiveShadowPtrTy, IntptrTy};
1162 DFSanUnionLoadFnTy = FunctionType::get(PrimitiveShadowTy, DFSanUnionLoadArgs,
1164 Type *DFSanLoadLabelAndOriginArgs[2] = {Int8Ptr, IntptrTy};
1165 DFSanLoadLabelAndOriginFnTy =
1168 DFSanUnimplementedFnTy = FunctionType::get(
1170 Type *DFSanWrapperExternWeakNullArgs[2] = {Int8Ptr, Int8Ptr};
1171 DFSanWrapperExternWeakNullFnTy =
1172 FunctionType::get(
Type::getVoidTy(*Ctx), DFSanWrapperExternWeakNullArgs,
1174 Type *DFSanSetLabelArgs[4] = {PrimitiveShadowTy, OriginTy,
1175 PointerType::getUnqual(*Ctx), IntptrTy};
1177 DFSanSetLabelArgs,
false);
1178 DFSanNonzeroLabelFnTy = FunctionType::get(
Type::getVoidTy(*Ctx), std::nullopt,
1180 DFSanVarargWrapperFnTy = FunctionType::get(
1182 DFSanConditionalCallbackFnTy =
1185 Type *DFSanConditionalCallbackOriginArgs[2] = {PrimitiveShadowTy, OriginTy};
1186 DFSanConditionalCallbackOriginFnTy = FunctionType::get(
1189 Type *DFSanReachesFunctionCallbackArgs[4] = {PrimitiveShadowTy, Int8Ptr,
1191 DFSanReachesFunctionCallbackFnTy =
1192 FunctionType::get(
Type::getVoidTy(*Ctx), DFSanReachesFunctionCallbackArgs,
1194 Type *DFSanReachesFunctionCallbackOriginArgs[5] = {
1195 PrimitiveShadowTy, OriginTy, Int8Ptr, OriginTy, Int8Ptr};
1196 DFSanReachesFunctionCallbackOriginFnTy = FunctionType::get(
1199 DFSanCmpCallbackFnTy =
1202 DFSanChainOriginFnTy =
1203 FunctionType::get(OriginTy, OriginTy,
false);
1204 Type *DFSanChainOriginIfTaintedArgs[2] = {PrimitiveShadowTy, OriginTy};
1205 DFSanChainOriginIfTaintedFnTy = FunctionType::get(
1206 OriginTy, DFSanChainOriginIfTaintedArgs,
false);
1208 Int8Ptr, IntptrTy, OriginTy};
1209 DFSanMaybeStoreOriginFnTy = FunctionType::get(
1211 Type *DFSanMemOriginTransferArgs[3] = {Int8Ptr, Int8Ptr, IntptrTy};
1212 DFSanMemOriginTransferFnTy = FunctionType::get(
1214 Type *DFSanMemShadowOriginTransferArgs[3] = {Int8Ptr, Int8Ptr, IntptrTy};
1215 DFSanMemShadowOriginTransferFnTy =
1216 FunctionType::get(
Type::getVoidTy(*Ctx), DFSanMemShadowOriginTransferArgs,
1218 Type *DFSanMemShadowOriginConditionalExchangeArgs[5] = {
1220 DFSanMemShadowOriginConditionalExchangeFnTy = FunctionType::get(
1223 Type *DFSanLoadStoreCallbackArgs[2] = {PrimitiveShadowTy, Int8Ptr};
1224 DFSanLoadStoreCallbackFnTy =
1227 Type *DFSanMemTransferCallbackArgs[2] = {PrimitiveShadowPtrTy, IntptrTy};
1228 DFSanMemTransferCallbackFnTy =
1229 FunctionType::get(
Type::getVoidTy(*Ctx), DFSanMemTransferCallbackArgs,
1237bool DataFlowSanitizer::isInstrumented(
const Function *
F) {
1238 return !ABIList.isIn(*
F,
"uninstrumented");
1241bool DataFlowSanitizer::isInstrumented(
const GlobalAlias *GA) {
1242 return !ABIList.isIn(*GA,
"uninstrumented");
1245bool DataFlowSanitizer::isForceZeroLabels(
const Function *
F) {
1246 return ABIList.isIn(*
F,
"force_zero_labels");
1249DataFlowSanitizer::WrapperKind DataFlowSanitizer::getWrapperKind(
Function *
F) {
1250 if (ABIList.isIn(*
F,
"functional"))
1251 return WK_Functional;
1252 if (ABIList.isIn(*
F,
"discard"))
1254 if (ABIList.isIn(*
F,
"custom"))
1260void DataFlowSanitizer::addGlobalNameSuffix(
GlobalValue *GV) {
1261 std::string GVName = std::string(GV->
getName()), Suffix =
".dfsan";
1270 std::string SearchStr =
".symver " + GVName +
",";
1271 size_t Pos =
Asm.find(SearchStr);
1272 if (Pos != std::string::npos) {
1273 Asm.replace(Pos, SearchStr.size(),
".symver " + GVName + Suffix +
",");
1274 Pos =
Asm.find(
'@');
1276 if (Pos == std::string::npos)
1279 Asm.replace(Pos, 1, Suffix +
"@");
1284void DataFlowSanitizer::buildExternWeakCheckIfNeeded(
IRBuilder<> &IRB,
1294 std::vector<Value *>
Args;
1297 IRB.
CreateCall(DFSanWrapperExternWeakNullFn, Args);
1307 NewFName,
F->getParent());
1313 if (
F->isVarArg()) {
1316 IRBuilder<>(BB).CreateGlobalStringPtr(
F->getName()),
"",
1321 std::vector<Value *>
Args(ArgIt, ArgIt + FT->getNumParams());
1324 if (FT->getReturnType()->isVoidTy())
1334void DataFlowSanitizer::initializeRuntimeFunctions(
Module &M) {
1338 AL =
AL.addFnAttribute(
C, Attribute::NoUnwind);
1339 AL =
AL.addFnAttribute(
1341 AL =
AL.addRetAttribute(
C, Attribute::ZExt);
1343 Mod->getOrInsertFunction(
"__dfsan_union_load", DFSanUnionLoadFnTy, AL);
1347 AL =
AL.addFnAttribute(
C, Attribute::NoUnwind);
1348 AL =
AL.addFnAttribute(
1350 AL =
AL.addRetAttribute(
C, Attribute::ZExt);
1351 DFSanLoadLabelAndOriginFn =
Mod->getOrInsertFunction(
1352 "__dfsan_load_label_and_origin", DFSanLoadLabelAndOriginFnTy, AL);
1354 DFSanUnimplementedFn =
1355 Mod->getOrInsertFunction(
"__dfsan_unimplemented", DFSanUnimplementedFnTy);
1356 DFSanWrapperExternWeakNullFn =
Mod->getOrInsertFunction(
1357 "__dfsan_wrapper_extern_weak_null", DFSanWrapperExternWeakNullFnTy);
1360 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1361 AL =
AL.addParamAttribute(
M.getContext(), 1, Attribute::ZExt);
1363 Mod->getOrInsertFunction(
"__dfsan_set_label", DFSanSetLabelFnTy, AL);
1365 DFSanNonzeroLabelFn =
1366 Mod->getOrInsertFunction(
"__dfsan_nonzero_label", DFSanNonzeroLabelFnTy);
1367 DFSanVarargWrapperFn =
Mod->getOrInsertFunction(
"__dfsan_vararg_wrapper",
1368 DFSanVarargWrapperFnTy);
1371 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1372 AL =
AL.addRetAttribute(
M.getContext(), Attribute::ZExt);
1373 DFSanChainOriginFn =
Mod->getOrInsertFunction(
"__dfsan_chain_origin",
1374 DFSanChainOriginFnTy, AL);
1378 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1379 AL =
AL.addParamAttribute(
M.getContext(), 1, Attribute::ZExt);
1380 AL =
AL.addRetAttribute(
M.getContext(), Attribute::ZExt);
1381 DFSanChainOriginIfTaintedFn =
Mod->getOrInsertFunction(
1382 "__dfsan_chain_origin_if_tainted", DFSanChainOriginIfTaintedFnTy, AL);
1384 DFSanMemOriginTransferFn =
Mod->getOrInsertFunction(
1385 "__dfsan_mem_origin_transfer", DFSanMemOriginTransferFnTy);
1387 DFSanMemShadowOriginTransferFn =
Mod->getOrInsertFunction(
1388 "__dfsan_mem_shadow_origin_transfer", DFSanMemShadowOriginTransferFnTy);
1390 DFSanMemShadowOriginConditionalExchangeFn =
1391 Mod->getOrInsertFunction(
"__dfsan_mem_shadow_origin_conditional_exchange",
1392 DFSanMemShadowOriginConditionalExchangeFnTy);
1396 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1397 AL =
AL.addParamAttribute(
M.getContext(), 3, Attribute::ZExt);
1398 DFSanMaybeStoreOriginFn =
Mod->getOrInsertFunction(
1399 "__dfsan_maybe_store_origin", DFSanMaybeStoreOriginFnTy, AL);
1402 DFSanRuntimeFunctions.
insert(
1404 DFSanRuntimeFunctions.
insert(
1406 DFSanRuntimeFunctions.
insert(
1408 DFSanRuntimeFunctions.
insert(
1410 DFSanRuntimeFunctions.
insert(
1412 DFSanRuntimeFunctions.
insert(
1414 DFSanRuntimeFunctions.
insert(
1416 DFSanRuntimeFunctions.
insert(
1418 DFSanRuntimeFunctions.
insert(
1420 DFSanRuntimeFunctions.
insert(
1422 DFSanRuntimeFunctions.
insert(
1424 DFSanRuntimeFunctions.
insert(
1426 DFSanRuntimeFunctions.
insert(
1428 DFSanRuntimeFunctions.
insert(
1430 DFSanRuntimeFunctions.
insert(
1432 DFSanRuntimeFunctions.
insert(
1434 DFSanRuntimeFunctions.
insert(
1436 DFSanRuntimeFunctions.
insert(
1438 DFSanRuntimeFunctions.
insert(
1440 DFSanRuntimeFunctions.
insert(
1441 DFSanMemShadowOriginConditionalExchangeFn.
getCallee()
1443 DFSanRuntimeFunctions.
insert(
1448void DataFlowSanitizer::initializeCallbackFunctions(
Module &M) {
1451 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1452 DFSanLoadCallbackFn =
Mod->getOrInsertFunction(
1453 "__dfsan_load_callback", DFSanLoadStoreCallbackFnTy, AL);
1457 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1458 DFSanStoreCallbackFn =
Mod->getOrInsertFunction(
1459 "__dfsan_store_callback", DFSanLoadStoreCallbackFnTy, AL);
1461 DFSanMemTransferCallbackFn =
Mod->getOrInsertFunction(
1462 "__dfsan_mem_transfer_callback", DFSanMemTransferCallbackFnTy);
1465 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1466 DFSanCmpCallbackFn =
Mod->getOrInsertFunction(
"__dfsan_cmp_callback",
1467 DFSanCmpCallbackFnTy, AL);
1471 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1472 DFSanConditionalCallbackFn =
Mod->getOrInsertFunction(
1473 "__dfsan_conditional_callback", DFSanConditionalCallbackFnTy, AL);
1477 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1478 DFSanConditionalCallbackOriginFn =
1479 Mod->getOrInsertFunction(
"__dfsan_conditional_callback_origin",
1480 DFSanConditionalCallbackOriginFnTy, AL);
1484 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1485 DFSanReachesFunctionCallbackFn =
1486 Mod->getOrInsertFunction(
"__dfsan_reaches_function_callback",
1487 DFSanReachesFunctionCallbackFnTy, AL);
1491 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1492 DFSanReachesFunctionCallbackOriginFn =
1493 Mod->getOrInsertFunction(
"__dfsan_reaches_function_callback_origin",
1494 DFSanReachesFunctionCallbackOriginFnTy, AL);
1498bool DataFlowSanitizer::runImpl(
1500 initializeModule(M);
1502 if (ABIList.isIn(M,
"skip"))
1505 const unsigned InitialGlobalSize =
M.global_size();
1506 const unsigned InitialModuleSize =
M.size();
1508 bool Changed =
false;
1514 Changed |=
G->getThreadLocalMode() != GlobalVariable::InitialExecTLSModel;
1515 G->setThreadLocalMode(GlobalVariable::InitialExecTLSModel);
1522 GetOrInsertGlobal(
"__dfsan_arg_tls",
1524 RetvalTLS = GetOrInsertGlobal(
1525 "__dfsan_retval_tls",
1527 ArgOriginTLSTy = ArrayType::get(OriginTy, NumOfElementsInArgOrgTLS);
1528 ArgOriginTLS = GetOrInsertGlobal(
"__dfsan_arg_origin_tls", ArgOriginTLSTy);
1529 RetvalOriginTLS = GetOrInsertGlobal(
"__dfsan_retval_origin_tls", OriginTy);
1531 (void)
Mod->getOrInsertGlobal(
"__dfsan_track_origins", OriginTy, [&] {
1537 "__dfsan_track_origins");
1540 initializeCallbackFunctions(M);
1541 initializeRuntimeFunctions(M);
1543 std::vector<Function *> FnsToInstrument;
1548 if (!
F.isIntrinsic() && !DFSanRuntimeFunctions.
contains(&
F) &&
1549 !LibAtomicFunction(
F) &&
1550 !
F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation)) {
1551 FnsToInstrument.push_back(&
F);
1552 if (
F.hasPersonalityFn())
1553 PersonalityFns.
insert(
F.getPersonalityFn()->stripPointerCasts());
1557 for (
auto *
C : PersonalityFns) {
1558 assert(isa<Function>(
C) &&
"Personality routine is not a function!");
1560 if (!isInstrumented(
F))
1574 bool GAInst = isInstrumented(&GA), FInst = isInstrumented(
F);
1575 if (GAInst && FInst) {
1576 addGlobalNameSuffix(&GA);
1577 }
else if (GAInst != FInst) {
1582 buildWrapperFunction(
F,
"", GA.
getLinkage(),
F->getFunctionType());
1586 FnsToInstrument.push_back(NewF);
1595 for (std::vector<Function *>::iterator FI = FnsToInstrument.begin(),
1596 FE = FnsToInstrument.end();
1601 bool IsZeroArgsVoidRet = (FT->getNumParams() == 0 && !FT->isVarArg() &&
1602 FT->getReturnType()->isVoidTy());
1604 if (isInstrumented(&
F)) {
1605 if (isForceZeroLabels(&
F))
1606 FnsWithForceZeroLabel.
insert(&
F);
1611 addGlobalNameSuffix(&
F);
1612 }
else if (!IsZeroArgsVoidRet || getWrapperKind(&
F) == WK_Custom) {
1620 F.hasLocalLinkage() ?
F.getLinkage()
1623 Function *NewF = buildWrapperFunction(
1625 (shouldTrackOrigins() ? std::string(
"dfso$") : std::string(
"dfsw$")) +
1626 std::string(
F.getName()),
1627 WrapperLinkage, FT);
1647 auto IsNotCmpUse = [](
Use &
U) ->
bool {
1648 User *Usr =
U.getUser();
1651 if (
CE->getOpcode() == Instruction::ICmp) {
1656 if (
I->getOpcode() == Instruction::ICmp) {
1662 F.replaceUsesWithIf(NewF, IsNotCmpUse);
1664 UnwrappedFnMap[NewF] = &
F;
1667 if (!
F.isDeclaration()) {
1677 size_t N = FI - FnsToInstrument.begin(),
1678 Count = FE - FnsToInstrument.begin();
1679 FnsToInstrument.push_back(&
F);
1680 FI = FnsToInstrument.begin() +
N;
1681 FE = FnsToInstrument.begin() + Count;
1685 }
else if (FT->isVarArg()) {
1686 UnwrappedFnMap[&
F] = &
F;
1692 if (!
F ||
F->isDeclaration())
1697 DFSanFunction DFSF(*
this,
F, FnsWithNativeABI.
count(
F),
1698 FnsWithForceZeroLabel.
count(
F), GetTLI(*
F));
1702 for (
auto &FArg :
F->args()) {
1704 Value *FArgShadow = DFSF.getShadow(&FArg);
1705 if (isZeroShadow(FArgShadow))
1707 if (
Instruction *FArgShadowInst = dyn_cast<Instruction>(FArgShadow)) {
1710 if (shouldTrackOrigins()) {
1712 dyn_cast<Instruction>(DFSF.getOrigin(&FArg))) {
1721 DFSF.addReachesFunctionCallbacksIfEnabled(IRB, *Next, &FArg);
1739 if (!DFSF.SkipInsts.count(Inst))
1740 DFSanVisitor(DFSF).visit(Inst);
1751 for (DFSanFunction::PHIFixupElement &
P : DFSF.PHIFixups) {
1752 for (
unsigned Val = 0,
N =
P.Phi->getNumIncomingValues(); Val !=
N;
1754 P.ShadowPhi->setIncomingValue(
1755 Val, DFSF.getShadow(
P.Phi->getIncomingValue(Val)));
1757 P.OriginPhi->setIncomingValue(
1758 Val, DFSF.getOrigin(
P.Phi->getIncomingValue(Val)));
1767 for (
Value *V : DFSF.NonZeroChecks) {
1770 Pos = std::next(
I->getIterator());
1772 Pos = DFSF.F->getEntryBlock().begin();
1773 while (isa<PHINode>(Pos) || isa<AllocaInst>(Pos))
1774 Pos = std::next(Pos->getIterator());
1776 Value *PrimitiveShadow = DFSF.collapseToPrimitiveShadow(V, Pos);
1778 IRB.
CreateICmpNE(PrimitiveShadow, DFSF.DFS.ZeroPrimitiveShadow);
1780 Ne, Pos,
false, ColdCallWeights));
1782 ThenIRB.CreateCall(DFSF.DFS.DFSanNonzeroLabelFn, {});
1787 return Changed || !FnsToInstrument.empty() ||
1788 M.global_size() != InitialGlobalSize ||
M.size() != InitialModuleSize;
1801 DFS.RetvalTLS, PointerType::get(DFS.getShadowTy(
T), 0),
"_dfsret");
1804Value *DFSanFunction::getRetvalOriginTLS() {
return DFS.RetvalOriginTLS; }
1808 ArgNo,
"_dfsarg_o");
1812 assert(DFS.shouldTrackOrigins());
1813 if (!isa<Argument>(V) && !isa<Instruction>(V))
1814 return DFS.ZeroOrigin;
1815 Value *&Origin = ValOriginMap[
V];
1817 if (
Argument *
A = dyn_cast<Argument>(V)) {
1819 return DFS.ZeroOrigin;
1820 if (
A->getArgNo() < DFS.NumOfElementsInArgOrgTLS) {
1821 Instruction *ArgOriginTLSPos = &*
F->getEntryBlock().begin();
1823 Value *ArgOriginPtr = getArgOriginTLS(
A->getArgNo(), IRB);
1824 Origin = IRB.
CreateLoad(DFS.OriginTy, ArgOriginPtr);
1827 Origin = DFS.ZeroOrigin;
1830 Origin = DFS.ZeroOrigin;
1837 if (!DFS.shouldTrackOrigins())
1841 ValOriginMap[
I] = Origin;
1845 unsigned ArgOffset = 0;
1847 for (
auto &FArg :
F->args()) {
1848 if (!FArg.getType()->isSized()) {
1854 unsigned Size =
DL.getTypeAllocSize(DFS.getShadowTy(&FArg));
1867 Value *ArgShadowPtr = getArgTLS(FArg.getType(), ArgOffset, IRB);
1872 return DFS.getZeroShadow(
A);
1876 if (!isa<Argument>(V) && !isa<Instruction>(V))
1877 return DFS.getZeroShadow(V);
1878 if (IsForceZeroLabels)
1879 return DFS.getZeroShadow(V);
1880 Value *&Shadow = ValShadowMap[
V];
1882 if (
Argument *
A = dyn_cast<Argument>(V)) {
1884 return DFS.getZeroShadow(V);
1885 Shadow = getShadowForTLSArgument(
A);
1886 NonZeroChecks.push_back(Shadow);
1888 Shadow = DFS.getZeroShadow(V);
1896 ValShadowMap[
I] = Shadow;
1904 assert(
Addr != RetvalTLS &&
"Reinstrumenting?");
1907 uint64_t AndMask = MapParams->AndMask;
1910 IRB.
CreateAnd(OffsetLong, ConstantInt::get(IntptrTy, ~AndMask));
1912 uint64_t XorMask = MapParams->XorMask;
1914 OffsetLong = IRB.
CreateXor(OffsetLong, ConstantInt::get(IntptrTy, XorMask));
1918std::pair<Value *, Value *>
1919DataFlowSanitizer::getShadowOriginAddress(
Value *
Addr,
Align InstAlignment,
1923 Value *ShadowOffset = getShadowOffset(
Addr, IRB);
1924 Value *ShadowLong = ShadowOffset;
1925 uint64_t ShadowBase = MapParams->ShadowBase;
1926 if (ShadowBase != 0) {
1928 IRB.
CreateAdd(ShadowLong, ConstantInt::get(IntptrTy, ShadowBase));
1933 Value *OriginPtr =
nullptr;
1934 if (shouldTrackOrigins()) {
1935 Value *OriginLong = ShadowOffset;
1936 uint64_t OriginBase = MapParams->OriginBase;
1937 if (OriginBase != 0)
1939 IRB.
CreateAdd(OriginLong, ConstantInt::get(IntptrTy, OriginBase));
1945 OriginLong = IRB.
CreateAnd(OriginLong, ConstantInt::get(IntptrTy, ~Mask));
1949 return std::make_pair(ShadowPtr, OriginPtr);
1954 Value *ShadowOffset) {
1962 Value *ShadowOffset = getShadowOffset(
Addr, IRB);
1963 return getShadowAddress(
Addr, Pos, ShadowOffset);
1968 Value *PrimitiveValue = combineShadows(V1, V2, Pos);
1969 return expandFromPrimitiveShadow(
T, PrimitiveValue, Pos);
1976 if (DFS.isZeroShadow(V1))
1977 return collapseToPrimitiveShadow(V2, Pos);
1978 if (DFS.isZeroShadow(V2))
1979 return collapseToPrimitiveShadow(V1, Pos);
1981 return collapseToPrimitiveShadow(V1, Pos);
1983 auto V1Elems = ShadowElements.
find(V1);
1984 auto V2Elems = ShadowElements.
find(V2);
1985 if (V1Elems != ShadowElements.
end() && V2Elems != ShadowElements.
end()) {
1986 if (std::includes(V1Elems->second.begin(), V1Elems->second.end(),
1987 V2Elems->second.begin(), V2Elems->second.end())) {
1988 return collapseToPrimitiveShadow(V1, Pos);
1990 if (std::includes(V2Elems->second.begin(), V2Elems->second.end(),
1991 V1Elems->second.begin(), V1Elems->second.end())) {
1992 return collapseToPrimitiveShadow(V2, Pos);
1994 }
else if (V1Elems != ShadowElements.
end()) {
1995 if (V1Elems->second.count(V2))
1996 return collapseToPrimitiveShadow(V1, Pos);
1997 }
else if (V2Elems != ShadowElements.
end()) {
1998 if (V2Elems->second.count(V1))
1999 return collapseToPrimitiveShadow(V2, Pos);
2002 auto Key = std::make_pair(V1, V2);
2005 CachedShadow &CCS = CachedShadows[
Key];
2006 if (CCS.Block && DT.
dominates(CCS.Block, Pos->getParent()))
2010 Value *PV1 = collapseToPrimitiveShadow(V1, Pos);
2011 Value *PV2 = collapseToPrimitiveShadow(V2, Pos);
2014 CCS.Block = Pos->getParent();
2015 CCS.Shadow = IRB.
CreateOr(PV1, PV2);
2017 std::set<Value *> UnionElems;
2018 if (V1Elems != ShadowElements.
end()) {
2019 UnionElems = V1Elems->second;
2021 UnionElems.insert(V1);
2023 if (V2Elems != ShadowElements.
end()) {
2024 UnionElems.insert(V2Elems->second.begin(), V2Elems->second.end());
2026 UnionElems.insert(V2);
2028 ShadowElements[CCS.Shadow] = std::move(UnionElems);
2038 return DFS.getZeroShadow(Inst);
2042 Shadow = combineShadows(Shadow, getShadow(Inst->
getOperand(
I)),
2045 return expandFromPrimitiveShadow(Inst->
getType(), Shadow,
2050 Value *CombinedShadow = DFSF.combineOperandShadows(&
I);
2051 DFSF.setShadow(&
I, CombinedShadow);
2052 visitInstOperandOrigins(
I);
2055Value *DFSanFunction::combineOrigins(
const std::vector<Value *> &Shadows,
2056 const std::vector<Value *> &Origins,
2059 assert(Shadows.size() == Origins.size());
2060 size_t Size = Origins.size();
2062 return DFS.ZeroOrigin;
2063 Value *Origin =
nullptr;
2065 Zero = DFS.ZeroPrimitiveShadow;
2066 for (
size_t I = 0;
I !=
Size; ++
I) {
2067 Value *OpOrigin = Origins[
I];
2068 Constant *ConstOpOrigin = dyn_cast<Constant>(OpOrigin);
2069 if (ConstOpOrigin && ConstOpOrigin->
isNullValue())
2075 Value *OpShadow = Shadows[
I];
2076 Value *PrimitiveShadow = collapseToPrimitiveShadow(OpShadow, Pos);
2081 return Origin ? Origin : DFS.ZeroOrigin;
2086 std::vector<Value *> Shadows(
Size);
2087 std::vector<Value *> Origins(
Size);
2088 for (
unsigned I = 0;
I !=
Size; ++
I) {
2092 return combineOrigins(Shadows, Origins, Inst->
getIterator());
2095void DFSanVisitor::visitInstOperandOrigins(
Instruction &
I) {
2096 if (!DFSF.DFS.shouldTrackOrigins())
2098 Value *CombinedOrigin = DFSF.combineOperandOrigins(&
I);
2099 DFSF.setOrigin(&
I, CombinedOrigin);
2102Align DFSanFunction::getShadowAlign(
Align InstAlignment) {
2104 return Align(Alignment.
value() * DFS.ShadowWidthBytes);
2107Align DFSanFunction::getOriginAlign(
Align InstAlignment) {
2112bool DFSanFunction::isLookupTableConstant(
Value *
P) {
2113 if (
GlobalVariable *GV = dyn_cast<GlobalVariable>(
P->stripPointerCasts()))
2114 if (GV->isConstant() && GV->
hasName())
2115 return DFS.CombineTaintLookupTableNames.count(GV->
getName());
2120bool DFSanFunction::useCallbackLoadLabelAndOrigin(
uint64_t Size,
2121 Align InstAlignment) {
2145 Value **OriginAddr) {
2148 IRB.
CreateGEP(OriginTy, *OriginAddr, ConstantInt::get(IntptrTy, 1));
2152std::pair<Value *, Value *> DFSanFunction::loadShadowFast(
2155 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins();
2156 const uint64_t ShadowSize =
Size * DFS.ShadowWidthBytes;
2158 assert(
Size >= 4 &&
"Not large enough load size for fast path!");
2161 std::vector<Value *> Shadows;
2162 std::vector<Value *> Origins;
2175 Type *WideShadowTy =
2179 Value *CombinedWideShadow =
2183 const uint64_t BytesPerWideShadow = WideShadowBitWidth / DFS.ShadowWidthBits;
2185 auto AppendWideShadowAndOrigin = [&](
Value *WideShadow,
Value *Origin) {
2186 if (BytesPerWideShadow > 4) {
2187 assert(BytesPerWideShadow == 8);
2195 WideShadow, ConstantInt::get(WideShadowTy, WideShadowBitWidth / 2));
2196 Shadows.push_back(WideShadow);
2197 Origins.push_back(DFS.loadNextOrigin(Pos, OriginAlign, &OriginAddr));
2199 Shadows.push_back(WideShadowLo);
2200 Origins.push_back(Origin);
2202 Shadows.push_back(WideShadow);
2203 Origins.push_back(Origin);
2207 if (ShouldTrackOrigins)
2208 AppendWideShadowAndOrigin(CombinedWideShadow, FirstOrigin);
2215 for (
uint64_t ByteOfs = BytesPerWideShadow; ByteOfs <
Size;
2216 ByteOfs += BytesPerWideShadow) {
2217 ShadowAddr = IRB.
CreateGEP(WideShadowTy, ShadowAddr,
2218 ConstantInt::get(DFS.IntptrTy, 1));
2219 Value *NextWideShadow =
2221 CombinedWideShadow = IRB.
CreateOr(CombinedWideShadow, NextWideShadow);
2222 if (ShouldTrackOrigins) {
2223 Value *NextOrigin = DFS.loadNextOrigin(Pos, OriginAlign, &OriginAddr);
2224 AppendWideShadowAndOrigin(NextWideShadow, NextOrigin);
2227 for (
unsigned Width = WideShadowBitWidth / 2; Width >= DFS.ShadowWidthBits;
2230 CombinedWideShadow = IRB.
CreateOr(CombinedWideShadow, ShrShadow);
2232 return {IRB.
CreateTrunc(CombinedWideShadow, DFS.PrimitiveShadowTy),
2234 ? combineOrigins(Shadows, Origins, Pos,
2239std::pair<Value *, Value *> DFSanFunction::loadShadowOriginSansLoadTracking(
2241 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins();
2245 const auto SI = AllocaShadowMap.
find(AI);
2246 if (SI != AllocaShadowMap.
end()) {
2249 const auto OI = AllocaOriginMap.
find(AI);
2250 assert(!ShouldTrackOrigins || OI != AllocaOriginMap.
end());
2251 return {ShadowLI, ShouldTrackOrigins
2260 bool AllConstants =
true;
2261 for (
const Value *Obj : Objs) {
2262 if (isa<Function>(Obj) || isa<BlockAddress>(Obj))
2264 if (isa<GlobalVariable>(Obj) && cast<GlobalVariable>(Obj)->
isConstant())
2267 AllConstants =
false;
2271 return {DFS.ZeroPrimitiveShadow,
2272 ShouldTrackOrigins ? DFS.ZeroOrigin :
nullptr};
2275 return {DFS.ZeroPrimitiveShadow,
2276 ShouldTrackOrigins ? DFS.ZeroOrigin :
nullptr};
2280 if (ShouldTrackOrigins &&
2281 useCallbackLoadLabelAndOrigin(
Size, InstAlignment)) {
2284 IRB.
CreateCall(DFS.DFSanLoadLabelAndOriginFn,
2285 {Addr, ConstantInt::get(DFS.IntptrTy, Size)});
2286 Call->addRetAttr(Attribute::ZExt);
2288 DFS.PrimitiveShadowTy),
2293 Value *ShadowAddr, *OriginAddr;
2294 std::tie(ShadowAddr, OriginAddr) =
2295 DFS.getShadowOriginAddress(
Addr, InstAlignment, Pos);
2297 const Align ShadowAlign = getShadowAlign(InstAlignment);
2298 const Align OriginAlign = getOriginAlign(InstAlignment);
2299 Value *Origin =
nullptr;
2300 if (ShouldTrackOrigins) {
2311 return {LI, Origin};
2315 Value *ShadowAddr1 = IRB.
CreateGEP(DFS.PrimitiveShadowTy, ShadowAddr,
2316 ConstantInt::get(DFS.IntptrTy, 1));
2321 return {combineShadows(Load, Load1, Pos), Origin};
2324 bool HasSizeForFastPath = DFS.hasLoadSizeForFastPath(
Size);
2326 if (HasSizeForFastPath)
2327 return loadShadowFast(ShadowAddr, OriginAddr,
Size, ShadowAlign,
2328 OriginAlign, Origin, Pos);
2332 DFS.DFSanUnionLoadFn, {ShadowAddr, ConstantInt::get(DFS.IntptrTy, Size)});
2334 return {FallbackCall, Origin};
2337std::pair<Value *, Value *>
2340 Value *PrimitiveShadow, *Origin;
2341 std::tie(PrimitiveShadow, Origin) =
2342 loadShadowOriginSansLoadTracking(
Addr,
Size, InstAlignment, Pos);
2343 if (DFS.shouldTrackOrigins()) {
2346 auto *ConstantShadow = dyn_cast<Constant>(PrimitiveShadow);
2347 if (!ConstantShadow || !ConstantShadow->isZeroValue())
2348 Origin = updateOriginIfTainted(PrimitiveShadow, Origin, IRB);
2351 return {PrimitiveShadow, Origin};
2356 case AtomicOrdering::NotAtomic:
2357 return AtomicOrdering::NotAtomic;
2358 case AtomicOrdering::Unordered:
2359 case AtomicOrdering::Monotonic:
2360 case AtomicOrdering::Acquire:
2361 return AtomicOrdering::Acquire;
2362 case AtomicOrdering::Release:
2363 case AtomicOrdering::AcquireRelease:
2364 return AtomicOrdering::AcquireRelease;
2365 case AtomicOrdering::SequentiallyConsistent:
2366 return AtomicOrdering::SequentiallyConsistent;
2372 if (!V->getType()->isPointerTy())
2380 if (
auto *
GEP = dyn_cast<GEPOperator>(V)) {
2381 V =
GEP->getPointerOperand();
2383 V = cast<Operator>(V)->getOperand(0);
2384 if (!V->getType()->isPointerTy())
2386 }
else if (isa<GlobalAlias>(V)) {
2387 V = cast<GlobalAlias>(V)->getAliasee();
2389 }
while (Visited.
insert(V).second);
2394void DFSanVisitor::visitLoadInst(
LoadInst &LI) {
2398 DFSF.setShadow(&LI, DFSF.DFS.getZeroShadow(&LI));
2399 DFSF.setOrigin(&LI, DFSF.DFS.ZeroOrigin);
2414 Pos = std::next(Pos);
2416 std::vector<Value *> Shadows;
2417 std::vector<Value *> Origins;
2418 Value *PrimitiveShadow, *Origin;
2419 std::tie(PrimitiveShadow, Origin) =
2421 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
2422 if (ShouldTrackOrigins) {
2423 Shadows.push_back(PrimitiveShadow);
2424 Origins.push_back(Origin);
2427 DFSF.isLookupTableConstant(
2430 PrimitiveShadow = DFSF.combineShadows(PrimitiveShadow, PtrShadow, Pos);
2431 if (ShouldTrackOrigins) {
2432 Shadows.push_back(PtrShadow);
2436 if (!DFSF.DFS.isZeroShadow(PrimitiveShadow))
2437 DFSF.NonZeroChecks.push_back(PrimitiveShadow);
2440 DFSF.expandFromPrimitiveShadow(LI.
getType(), PrimitiveShadow, Pos);
2441 DFSF.setShadow(&LI, Shadow);
2443 if (ShouldTrackOrigins) {
2444 DFSF.setOrigin(&LI, DFSF.combineOrigins(Shadows, Origins, Pos));
2451 IRB.
CreateCall(DFSF.DFS.DFSanLoadCallbackFn, {PrimitiveShadow, Addr});
2456 DFSF.addReachesFunctionCallbacksIfEnabled(IRB, LI, &LI);
2459Value *DFSanFunction::updateOriginIfTainted(
Value *Shadow,
Value *Origin,
2461 assert(DFS.shouldTrackOrigins());
2462 return IRB.
CreateCall(DFS.DFSanChainOriginIfTaintedFn, {Shadow, Origin});
2466 if (!DFS.shouldTrackOrigins())
2468 return IRB.
CreateCall(DFS.DFSanChainOriginFn, V);
2472 const unsigned OriginSize = DataFlowSanitizer::OriginWidthBytes;
2474 unsigned IntptrSize =
DL.getTypeStoreSize(DFS.IntptrTy);
2475 if (IntptrSize == OriginSize)
2477 assert(IntptrSize == OriginSize * 2);
2483 Value *StoreOriginAddr,
2485 const unsigned OriginSize = DataFlowSanitizer::OriginWidthBytes;
2487 const Align IntptrAlignment =
DL.getABITypeAlign(DFS.IntptrTy);
2488 unsigned IntptrSize =
DL.getTypeStoreSize(DFS.IntptrTy);
2490 assert(IntptrSize >= OriginSize);
2493 Align CurrentAlignment = Alignment;
2494 if (Alignment >= IntptrAlignment && IntptrSize > OriginSize) {
2495 Value *IntptrOrigin = originToIntptr(IRB, Origin);
2497 StoreOriginAddr, PointerType::get(DFS.IntptrTy, 0));
2498 for (
unsigned I = 0;
I < StoreOriginSize / IntptrSize; ++
I) {
2501 : IntptrStoreOriginPtr;
2503 Ofs += IntptrSize / OriginSize;
2504 CurrentAlignment = IntptrAlignment;
2508 for (
unsigned I = Ofs;
I < (StoreOriginSize + OriginSize - 1) / OriginSize;
2519 Type *VTy =
V->getType();
2529 Value *StoreOriginAddr,
Align InstAlignment) {
2532 const Align OriginAlignment = getOriginAlign(InstAlignment);
2533 Value *CollapsedShadow = collapseToPrimitiveShadow(Shadow, Pos);
2535 if (
auto *ConstantShadow = dyn_cast<Constant>(CollapsedShadow)) {
2536 if (!ConstantShadow->isZeroValue())
2537 paintOrigin(IRB, updateOrigin(Origin, IRB), StoreOriginAddr,
Size,
2542 if (shouldInstrumentWithCall()) {
2544 DFS.DFSanMaybeStoreOriginFn,
2545 {CollapsedShadow, Addr, ConstantInt::get(DFS.IntptrTy, Size), Origin});
2547 Value *
Cmp = convertToBool(CollapsedShadow, IRB,
"_dfscmp");
2550 Cmp, &*IRB.
GetInsertPoint(),
false, DFS.OriginStoreWeights, &DTU);
2552 paintOrigin(IRBNew, updateOrigin(Origin, IRBNew), StoreOriginAddr,
Size,
2564 Value *ExtZeroShadow = ConstantInt::get(ShadowTy, 0);
2565 Value *ShadowAddr = DFS.getShadowAddress(
Addr, Pos);
2572 Align InstAlignment,
2573 Value *PrimitiveShadow,
2576 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins() && Origin;
2579 const auto SI = AllocaShadowMap.
find(AI);
2580 if (SI != AllocaShadowMap.
end()) {
2586 if (ShouldTrackOrigins && !DFS.isZeroShadow(PrimitiveShadow)) {
2587 const auto OI = AllocaOriginMap.
find(AI);
2588 assert(OI != AllocaOriginMap.
end() && Origin);
2595 const Align ShadowAlign = getShadowAlign(InstAlignment);
2596 if (DFS.isZeroShadow(PrimitiveShadow)) {
2597 storeZeroPrimitiveShadow(
Addr,
Size, ShadowAlign, Pos);
2602 Value *ShadowAddr, *OriginAddr;
2603 std::tie(ShadowAddr, OriginAddr) =
2604 DFS.getShadowOriginAddress(
Addr, InstAlignment, Pos);
2606 const unsigned ShadowVecSize = 8;
2607 assert(ShadowVecSize * DFS.ShadowWidthBits <= 128 &&
2608 "Shadow vector is too large!");
2612 if (LeftSize >= ShadowVecSize) {
2616 for (
unsigned I = 0;
I != ShadowVecSize; ++
I) {
2618 ShadowVec, PrimitiveShadow,
2622 Value *CurShadowVecAddr =
2625 LeftSize -= ShadowVecSize;
2627 }
while (LeftSize >= ShadowVecSize);
2630 while (LeftSize > 0) {
2631 Value *CurShadowAddr =
2638 if (ShouldTrackOrigins) {
2639 storeOrigin(Pos,
Addr,
Size, PrimitiveShadow, Origin, OriginAddr,
2646 case AtomicOrdering::NotAtomic:
2647 return AtomicOrdering::NotAtomic;
2648 case AtomicOrdering::Unordered:
2649 case AtomicOrdering::Monotonic:
2650 case AtomicOrdering::Release:
2651 return AtomicOrdering::Release;
2652 case AtomicOrdering::Acquire:
2653 case AtomicOrdering::AcquireRelease:
2654 return AtomicOrdering::AcquireRelease;
2655 case AtomicOrdering::SequentiallyConsistent:
2656 return AtomicOrdering::SequentiallyConsistent;
2661void DFSanVisitor::visitStoreInst(
StoreInst &SI) {
2662 auto &
DL =
SI.getDataLayout();
2663 Value *Val =
SI.getValueOperand();
2676 const bool ShouldTrackOrigins =
2677 DFSF.DFS.shouldTrackOrigins() && !
SI.isAtomic();
2678 std::vector<Value *> Shadows;
2679 std::vector<Value *> Origins;
2682 SI.isAtomic() ? DFSF.DFS.getZeroShadow(Val) : DFSF.getShadow(Val);
2684 if (ShouldTrackOrigins) {
2685 Shadows.push_back(Shadow);
2686 Origins.push_back(DFSF.getOrigin(Val));
2689 Value *PrimitiveShadow;
2691 Value *PtrShadow = DFSF.getShadow(
SI.getPointerOperand());
2692 if (ShouldTrackOrigins) {
2693 Shadows.push_back(PtrShadow);
2694 Origins.push_back(DFSF.getOrigin(
SI.getPointerOperand()));
2696 PrimitiveShadow = DFSF.combineShadows(Shadow, PtrShadow,
SI.getIterator());
2698 PrimitiveShadow = DFSF.collapseToPrimitiveShadow(Shadow,
SI.getIterator());
2700 Value *Origin =
nullptr;
2701 if (ShouldTrackOrigins)
2702 Origin = DFSF.combineOrigins(Shadows, Origins,
SI.getIterator());
2703 DFSF.storePrimitiveShadowOrigin(
SI.getPointerOperand(),
Size,
SI.getAlign(),
2704 PrimitiveShadow, Origin,
SI.getIterator());
2709 IRB.
CreateCall(DFSF.DFS.DFSanStoreCallbackFn, {PrimitiveShadow, Addr});
2715 assert(isa<AtomicRMWInst>(
I) || isa<AtomicCmpXchgInst>(
I));
2717 Value *Val =
I.getOperand(1);
2718 const auto &
DL =
I.getDataLayout();
2727 const Align ShadowAlign = DFSF.getShadowAlign(InstAlignment);
2728 DFSF.storeZeroPrimitiveShadow(
Addr,
Size, ShadowAlign,
I.getIterator());
2729 DFSF.setShadow(&
I, DFSF.DFS.getZeroShadow(&
I));
2730 DFSF.setOrigin(&
I, DFSF.DFS.ZeroOrigin);
2734 visitCASOrRMW(
I.getAlign(),
I);
2741 visitCASOrRMW(
I.getAlign(),
I);
2748 visitInstOperands(UO);
2752 visitInstOperands(BO);
2755void DFSanVisitor::visitBitCastInst(
BitCastInst &BCI) {
2759 if (
auto *CI = dyn_cast<CallInst>(BCI.
getOperand(0)))
2762 visitInstOperands(BCI);
2765void DFSanVisitor::visitCastInst(
CastInst &CI) { visitInstOperands(CI); }
2767void DFSanVisitor::visitCmpInst(
CmpInst &CI) {
2768 visitInstOperands(CI);
2771 Value *CombinedShadow = DFSF.getShadow(&CI);
2773 IRB.
CreateCall(DFSF.DFS.DFSanCmpCallbackFn, CombinedShadow);
2790 DFSF.setShadow(&LPI, DFSF.DFS.getZeroShadow(&LPI));
2791 DFSF.setOrigin(&LPI, DFSF.DFS.ZeroOrigin);
2796 DFSF.isLookupTableConstant(
2798 visitInstOperands(GEPI);
2805 DFSF.setShadow(&GEPI, DFSF.getShadow(BasePointer));
2806 if (DFSF.DFS.shouldTrackOrigins())
2807 DFSF.setOrigin(&GEPI, DFSF.getOrigin(BasePointer));
2811 visitInstOperands(
I);
2815 visitInstOperands(
I);
2819 visitInstOperands(
I);
2824 Value *Agg =
I.getAggregateOperand();
2825 Value *AggShadow = DFSF.getShadow(Agg);
2827 DFSF.setShadow(&
I, ResShadow);
2828 visitInstOperandOrigins(
I);
2833 Value *AggShadow = DFSF.getShadow(
I.getAggregateOperand());
2834 Value *InsShadow = DFSF.getShadow(
I.getInsertedValueOperand());
2836 DFSF.setShadow(&
I, Res);
2837 visitInstOperandOrigins(
I);
2840void DFSanVisitor::visitAllocaInst(
AllocaInst &
I) {
2841 bool AllLoadsStores =
true;
2842 for (
User *U :
I.users()) {
2843 if (isa<LoadInst>(U))
2846 if (
StoreInst *SI = dyn_cast<StoreInst>(U)) {
2847 if (
SI->getPointerOperand() == &
I)
2851 AllLoadsStores =
false;
2854 if (AllLoadsStores) {
2856 DFSF.AllocaShadowMap[&
I] = IRB.
CreateAlloca(DFSF.DFS.PrimitiveShadowTy);
2857 if (DFSF.DFS.shouldTrackOrigins()) {
2858 DFSF.AllocaOriginMap[&
I] =
2862 DFSF.setShadow(&
I, DFSF.DFS.ZeroPrimitiveShadow);
2863 DFSF.setOrigin(&
I, DFSF.DFS.ZeroOrigin);
2866void DFSanVisitor::visitSelectInst(
SelectInst &
I) {
2867 Value *CondShadow = DFSF.getShadow(
I.getCondition());
2868 Value *TrueShadow = DFSF.getShadow(
I.getTrueValue());
2869 Value *FalseShadow = DFSF.getShadow(
I.getFalseValue());
2870 Value *ShadowSel =
nullptr;
2871 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
2872 std::vector<Value *> Shadows;
2873 std::vector<Value *> Origins;
2875 ShouldTrackOrigins ? DFSF.getOrigin(
I.getTrueValue()) :
nullptr;
2876 Value *FalseOrigin =
2877 ShouldTrackOrigins ? DFSF.getOrigin(
I.getFalseValue()) :
nullptr;
2879 DFSF.addConditionalCallbacksIfEnabled(
I,
I.getCondition());
2881 if (isa<VectorType>(
I.getCondition()->getType())) {
2882 ShadowSel = DFSF.combineShadowsThenConvert(
I.getType(), TrueShadow,
2883 FalseShadow,
I.getIterator());
2884 if (ShouldTrackOrigins) {
2885 Shadows.push_back(TrueShadow);
2886 Shadows.push_back(FalseShadow);
2887 Origins.push_back(TrueOrigin);
2888 Origins.push_back(FalseOrigin);
2891 if (TrueShadow == FalseShadow) {
2892 ShadowSel = TrueShadow;
2893 if (ShouldTrackOrigins) {
2894 Shadows.push_back(TrueShadow);
2895 Origins.push_back(TrueOrigin);
2899 "",
I.getIterator());
2900 if (ShouldTrackOrigins) {
2901 Shadows.push_back(ShadowSel);
2903 FalseOrigin,
"",
I.getIterator()));
2908 I.getType(), CondShadow,
2909 ShadowSel,
I.getIterator())
2911 if (ShouldTrackOrigins) {
2913 Shadows.push_back(CondShadow);
2914 Origins.push_back(DFSF.getOrigin(
I.getCondition()));
2916 DFSF.setOrigin(&
I, DFSF.combineOrigins(Shadows, Origins,
I.getIterator()));
2920void DFSanVisitor::visitMemSetInst(
MemSetInst &
I) {
2922 Value *ValShadow = DFSF.getShadow(
I.getValue());
2923 Value *ValOrigin = DFSF.DFS.shouldTrackOrigins()
2924 ? DFSF.getOrigin(
I.getValue())
2925 : DFSF.DFS.ZeroOrigin;
2927 {ValShadow, ValOrigin, I.getDest(),
2928 IRB.CreateZExtOrTrunc(I.getLength(), DFSF.DFS.IntptrTy)});
2936 if (DFSF.DFS.shouldTrackOrigins()) {
2938 DFSF.DFS.DFSanMemOriginTransferFn,
2939 {I.getArgOperand(0), I.getArgOperand(1),
2940 IRB.CreateIntCast(I.getArgOperand(2), DFSF.DFS.IntptrTy, false)});
2943 Value *DestShadow = DFSF.DFS.getShadowAddress(
I.getDest(),
I.getIterator());
2944 Value *SrcShadow = DFSF.DFS.getShadowAddress(
I.getSource(),
I.getIterator());
2946 IRB.
CreateMul(
I.getLength(), ConstantInt::get(
I.getLength()->getType(),
2947 DFSF.DFS.ShadowWidthBytes));
2948 auto *MTI = cast<MemTransferInst>(
2949 IRB.
CreateCall(
I.getFunctionType(),
I.getCalledOperand(),
2950 {DestShadow, SrcShadow, LenShadow, I.getVolatileCst()}));
2951 MTI->setDestAlignment(DFSF.getShadowAlign(
I.getDestAlign().valueOrOne()));
2952 MTI->setSourceAlignment(DFSF.getShadowAlign(
I.getSourceAlign().valueOrOne()));
2955 DFSF.DFS.DFSanMemTransferCallbackFn,
2956 {DestShadow, IRB.CreateZExtOrTrunc(I.getLength(), DFSF.DFS.IntptrTy)});
2960void DFSanVisitor::visitBranchInst(
BranchInst &BR) {
2961 if (!
BR.isConditional())
2964 DFSF.addConditionalCallbacksIfEnabled(BR,
BR.getCondition());
2967void DFSanVisitor::visitSwitchInst(
SwitchInst &SW) {
2968 DFSF.addConditionalCallbacksIfEnabled(SW, SW.
getCondition());
2973 if (
auto *
I = dyn_cast<BitCastInst>(RetVal)) {
2974 RetVal =
I->getOperand(0);
2976 if (
auto *
I = dyn_cast<CallInst>(RetVal)) {
2977 return I->isMustTailCall();
2982void DFSanVisitor::visitReturnInst(
ReturnInst &RI) {
2990 Type *RT = DFSF.F->getFunctionType()->getReturnType();
2991 unsigned Size = getDataLayout().getTypeAllocSize(DFSF.DFS.getShadowTy(RT));
2997 if (DFSF.DFS.shouldTrackOrigins()) {
3005 std::vector<Value *> &Args,
3012 for (
unsigned N = FT->getNumParams();
N != 0; ++
I, --
N)
3014 DFSF.collapseToPrimitiveShadow(DFSF.getShadow(*
I), CB.
getIterator()));
3017 if (FT->isVarArg()) {
3018 auto *LabelVATy = ArrayType::get(DFSF.DFS.PrimitiveShadowTy,
3019 CB.
arg_size() - FT->getNumParams());
3020 auto *LabelVAAlloca =
3021 new AllocaInst(LabelVATy, getDataLayout().getAllocaAddrSpace(),
3022 "labelva", DFSF.F->getEntryBlock().begin());
3024 for (
unsigned N = 0;
I != CB.
arg_end(); ++
I, ++
N) {
3027 DFSF.collapseToPrimitiveShadow(DFSF.getShadow(*
I), CB.
getIterator()),
3035 if (!FT->getReturnType()->isVoidTy()) {
3036 if (!DFSF.LabelReturnAlloca) {
3038 DFSF.DFS.PrimitiveShadowTy, getDataLayout().getAllocaAddrSpace(),
3039 "labelreturn", DFSF.F->getEntryBlock().begin());
3041 Args.push_back(DFSF.LabelReturnAlloca);
3046 std::vector<Value *> &Args,
3053 for (
unsigned N = FT->getNumParams();
N != 0; ++
I, --
N)
3054 Args.push_back(DFSF.getOrigin(*
I));
3057 if (FT->isVarArg()) {
3059 ArrayType::get(DFSF.DFS.OriginTy, CB.
arg_size() - FT->getNumParams());
3060 auto *OriginVAAlloca =
3061 new AllocaInst(OriginVATy, getDataLayout().getAllocaAddrSpace(),
3062 "originva", DFSF.F->getEntryBlock().begin());
3064 for (
unsigned N = 0;
I != CB.
arg_end(); ++
I, ++
N) {
3073 if (!FT->getReturnType()->isVoidTy()) {
3074 if (!DFSF.OriginReturnAlloca) {
3076 DFSF.DFS.OriginTy, getDataLayout().getAllocaAddrSpace(),
3077 "originreturn", DFSF.F->getEntryBlock().begin());
3079 Args.push_back(DFSF.OriginReturnAlloca);
3085 switch (DFSF.DFS.getWrapperKind(&
F)) {
3086 case DataFlowSanitizer::WK_Warning:
3088 IRB.
CreateCall(DFSF.DFS.DFSanUnimplementedFn,
3090 DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &
F);
3091 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3092 DFSF.setOrigin(&CB, DFSF.DFS.ZeroOrigin);
3094 case DataFlowSanitizer::WK_Discard:
3096 DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &
F);
3097 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3098 DFSF.setOrigin(&CB, DFSF.DFS.ZeroOrigin);
3100 case DataFlowSanitizer::WK_Functional:
3102 DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &
F);
3103 visitInstOperands(CB);
3105 case DataFlowSanitizer::WK_Custom:
3109 CallInst *CI = dyn_cast<CallInst>(&CB);
3113 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
3115 TransformedFunction CustomFn = DFSF.DFS.getCustomFunctionType(FT);
3116 std::string CustomFName = ShouldTrackOrigins ?
"__dfso_" :
"__dfsw_";
3117 CustomFName +=
F.getName();
3119 CustomFName, CustomFn.TransformedType);
3121 CustomFn->copyAttributesFrom(&
F);
3124 if (!FT->getReturnType()->isVoidTy()) {
3125 CustomFn->removeFnAttrs(DFSF.DFS.ReadOnlyNoneAttrs);
3129 std::vector<Value *>
Args;
3133 for (
unsigned N = FT->getNumParams();
N != 0; ++
I, --
N) {
3138 const unsigned ShadowArgStart =
Args.size();
3139 addShadowArguments(
F, CB, Args, IRB);
3142 const unsigned OriginArgStart =
Args.size();
3143 if (ShouldTrackOrigins)
3144 addOriginArguments(
F, CB, Args, IRB);
3157 for (
unsigned N = 0;
N < FT->getNumParams();
N++) {
3158 const unsigned ArgNo = ShadowArgStart +
N;
3160 DFSF.DFS.PrimitiveShadowTy)
3162 if (ShouldTrackOrigins) {
3163 const unsigned OriginArgNo = OriginArgStart +
N;
3171 if (!FT->getReturnType()->isVoidTy()) {
3173 IRB.
CreateLoad(DFSF.DFS.PrimitiveShadowTy, DFSF.LabelReturnAlloca);
3174 DFSF.setShadow(CustomCI,
3175 DFSF.expandFromPrimitiveShadow(
3176 FT->getReturnType(), LabelLoad, CB.
getIterator()));
3177 if (ShouldTrackOrigins) {
3179 IRB.
CreateLoad(DFSF.DFS.OriginTy, DFSF.OriginReturnAlloca);
3180 DFSF.setOrigin(CustomCI, OriginLoad);
3192 constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
3193 uint32_t OrderingTable[NumOrderings] = {};
3195 OrderingTable[(int)AtomicOrderingCABI::relaxed] =
3196 OrderingTable[(
int)AtomicOrderingCABI::acquire] =
3197 OrderingTable[(int)AtomicOrderingCABI::consume] =
3198 (
int)AtomicOrderingCABI::acquire;
3199 OrderingTable[(int)AtomicOrderingCABI::release] =
3200 OrderingTable[(
int)AtomicOrderingCABI::acq_rel] =
3201 (int)AtomicOrderingCABI::acq_rel;
3202 OrderingTable[(int)AtomicOrderingCABI::seq_cst] =
3203 (
int)AtomicOrderingCABI::seq_cst;
3208void DFSanVisitor::visitLibAtomicLoad(
CallBase &CB) {
3210 assert(isa<CallInst>(CB));
3219 Value *NewOrdering =
3224 NextIRB.SetCurrentDebugLocation(CB.
getDebugLoc());
3230 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3231 {DstPtr, SrcPtr, NextIRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3235 constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
3236 uint32_t OrderingTable[NumOrderings] = {};
3238 OrderingTable[(int)AtomicOrderingCABI::relaxed] =
3239 OrderingTable[(
int)AtomicOrderingCABI::release] =
3240 (int)AtomicOrderingCABI::release;
3241 OrderingTable[(int)AtomicOrderingCABI::consume] =
3242 OrderingTable[(
int)AtomicOrderingCABI::acquire] =
3243 OrderingTable[(int)AtomicOrderingCABI::acq_rel] =
3244 (
int)AtomicOrderingCABI::acq_rel;
3245 OrderingTable[(int)AtomicOrderingCABI::seq_cst] =
3246 (
int)AtomicOrderingCABI::seq_cst;
3251void DFSanVisitor::visitLibAtomicStore(
CallBase &CB) {
3259 Value *NewOrdering =
3267 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3268 {DstPtr, SrcPtr, IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3271void DFSanVisitor::visitLibAtomicExchange(
CallBase &CB) {
3287 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3288 {DstPtr, TargetPtr, IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3292 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3293 {TargetPtr, SrcPtr, IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3296void DFSanVisitor::visitLibAtomicCompareExchange(
CallBase &CB) {
3310 NextIRB.SetCurrentDebugLocation(CB.
getDebugLoc());
3312 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3316 NextIRB.CreateCall(DFSF.DFS.DFSanMemShadowOriginConditionalExchangeFn,
3317 {NextIRB.CreateIntCast(&CB, NextIRB.getInt8Ty(), false),
3318 TargetPtr, ExpectedPtr, DesiredPtr,
3319 NextIRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3322void DFSanVisitor::visitCallBase(
CallBase &CB) {
3325 visitInstOperands(CB);
3331 if (
F == DFSF.DFS.DFSanVarargWrapperFn.getCallee()->stripPointerCasts())
3335 if (DFSF.TLI.getLibFunc(CB, LF)) {
3340 case LibFunc_atomic_load:
3341 if (!isa<CallInst>(CB)) {
3342 llvm::errs() <<
"DFSAN -- cannot instrument invoke of libatomic load. "
3346 visitLibAtomicLoad(CB);
3348 case LibFunc_atomic_store:
3349 visitLibAtomicStore(CB);
3357 if (
F &&
F->hasName() && !
F->isVarArg()) {
3358 if (
F->getName() ==
"__atomic_exchange") {
3359 visitLibAtomicExchange(CB);
3362 if (
F->getName() ==
"__atomic_compare_exchange") {
3363 visitLibAtomicCompareExchange(CB);
3370 if (UnwrappedFnIt != DFSF.DFS.UnwrappedFnMap.end())
3371 if (visitWrappedCallBase(*UnwrappedFnIt->second, CB))
3376 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
3381 unsigned ArgOffset = 0;
3382 for (
unsigned I = 0,
N = FT->getNumParams();
I !=
N; ++
I) {
3383 if (ShouldTrackOrigins) {
3386 if (
I < DFSF.DFS.NumOfElementsInArgOrgTLS &&
3387 !DFSF.DFS.isZeroShadow(ArgShadow))
3389 DFSF.getArgOriginTLS(
I, IRB));
3393 DL.getTypeAllocSize(DFSF.DFS.getShadowTy(FT->getParamType(
I)));
3399 DFSF.getArgTLS(FT->getParamType(
I), ArgOffset, IRB),
3407 if (
II->getNormalDest()->getSinglePredecessor()) {
3408 Next = &
II->getNormalDest()->front();
3412 Next = &NewBB->
front();
3420 if (isa<CallInst>(CB) && cast<CallInst>(CB).isMustTailCall())
3425 unsigned Size =
DL.getTypeAllocSize(DFSF.DFS.getShadowTy(&CB));
3428 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3430 LoadInst *LI = NextIRB.CreateAlignedLoad(
3431 DFSF.DFS.getShadowTy(&CB), DFSF.getRetvalTLS(CB.
getType(), NextIRB),
3433 DFSF.SkipInsts.insert(LI);
3434 DFSF.setShadow(&CB, LI);
3435 DFSF.NonZeroChecks.push_back(LI);
3438 if (ShouldTrackOrigins) {
3439 LoadInst *LI = NextIRB.CreateLoad(DFSF.DFS.OriginTy,
3440 DFSF.getRetvalOriginTLS(),
"_dfsret_o");
3441 DFSF.SkipInsts.insert(LI);
3442 DFSF.setOrigin(&CB, LI);
3445 DFSF.addReachesFunctionCallbacksIfEnabled(NextIRB, CB, &CB);
3449void DFSanVisitor::visitPHINode(
PHINode &PN) {
3450 Type *ShadowTy = DFSF.DFS.getShadowTy(&PN);
3459 DFSF.setShadow(&PN, ShadowPN);
3462 if (DFSF.DFS.shouldTrackOrigins()) {
3468 DFSF.setOrigin(&PN, OriginPN);
3471 DFSF.PHIFixups.push_back({&PN, ShadowPN, OriginPN});
3484 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.
uint64_t IntrinsicInst * II
if(auto Err=PB.parsePassPipeline(MPM, Passes)) return wrap(std MPM run * Mod
FunctionAnalysisManager FAM
This header defines various interfaces for pass management in LLVM.
const SmallVectorImpl< MachineOperand > & Cond
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
StringSet - A set-like wrapper for the StringMap.
Defines the virtual file system interface vfs::FileSystem.
Class for arbitrary precision integers.
an instruction to allocate memory on the stack
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
This class represents an incoming formal argument to a Function.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
An instruction that atomically checks whether a specified value is in a memory location,...
an instruction that atomically reads a memory location, combines it with another value,...
AttributeSet getFnAttrs() const
The function attributes are returned.
static AttributeList get(LLVMContext &C, ArrayRef< std::pair< unsigned, Attribute > > Attrs)
Create an AttributeList with the specified parameters in it.
AttributeSet getRetAttrs() const
The attributes for the ret value are returned.
unsigned getNumAttrSets() const
AttributeSet getParamAttrs(unsigned ArgNo) const
The attributes for the argument or parameter at the given index are returned.
AttributeMask & addAttribute(Attribute::AttrKind Val)
Add an attribute to the mask.
static Attribute getWithMemoryEffects(LLVMContext &Context, MemoryEffects ME)
LLVM Basic Block Representation.
const Instruction & front() const
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
InstListType::iterator iterator
Instruction iterators...
This class represents a no-op cast from one type to another.
Conditional or Unconditional Branch instruction.
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
bool isInlineAsm() const
Check if this call is an inline asm statement.
void setCallingConv(CallingConv::ID CC)
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
CallingConv::ID getCallingConv() const
User::op_iterator arg_begin()
Return the iterator pointing to the beginning of the argument list.
Value * getCalledOperand() const
void setAttributes(AttributeList A)
Set the parameter attributes for this call.
void addRetAttr(Attribute::AttrKind Kind)
Adds the attribute to the return value.
Value * getArgOperand(unsigned i) const
void setArgOperand(unsigned i, Value *v)
User::op_iterator arg_end()
Return the iterator pointing to the end of the argument list.
FunctionType * getFunctionType() const
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
unsigned arg_size() const
AttributeList getAttributes() const
Return the parameter attributes for this call.
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
Adds the attribute to the indicated argument.
void setCalledFunction(Function *Fn)
Sets the function called, including updating the function type.
This class represents a function call, abstracting a target machine's calling convention.
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", 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)
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())
Constant * CreateGlobalStringPtr(StringRef Str, const Twine &Name="", unsigned AddressSpace=0, Module *M=nullptr, bool AddNull=true)
Same as CreateGlobalString, but return a pointer with "i8*" type instead of a pointer to array of i8.
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)
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)
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args=std::nullopt, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateXor(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateMul(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...
This instruction inserts a single (scalar) element into a VectorType value.
This instruction inserts a struct field of array element value into an aggregate value.
Base class for instruction visitors.
RetTy visitCmpInst(CmpInst &I)
RetTy visitExtractElementInst(ExtractElementInst &I)
RetTy visitCallBase(CallBase &I)
RetTy visitInsertValueInst(InsertValueInst &I)
RetTy visitShuffleVectorInst(ShuffleVectorInst &I)
RetTy visitLandingPadInst(LandingPadInst &I)
RetTy visitAtomicCmpXchgInst(AtomicCmpXchgInst &I)
RetTy visitBitCastInst(BitCastInst &I)
RetTy visitSwitchInst(SwitchInst &I)
RetTy visitPHINode(PHINode &I)
RetTy visitReturnInst(ReturnInst &I)
RetTy visitExtractValueInst(ExtractValueInst &I)
RetTy visitUnaryOperator(UnaryOperator &I)
RetTy visitStoreInst(StoreInst &I)
RetTy visitInsertElementInst(InsertElementInst &I)
RetTy visitAtomicRMWInst(AtomicRMWInst &I)
RetTy visitAllocaInst(AllocaInst &I)
RetTy visitBinaryOperator(BinaryOperator &I)
RetTy visitMemTransferInst(MemTransferInst &I)
RetTy visitMemSetInst(MemSetInst &I)
RetTy visitCastInst(CastInst &I)
RetTy visitBranchInst(BranchInst &I)
RetTy visitSelectInst(SelectInst &I)
RetTy visitGetElementPtrInst(GetElementPtrInst &I)
RetTy visitLoadInst(LoadInst &I)
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
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, 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.