56#define DEBUG_TYPE "alloc-token"
62STATISTIC(NumFunctionsModified,
"Functions modified");
63STATISTIC(NumAllocationsInstrumented,
"Allocations instrumented");
73 II &&
II->getIntrinsicID() == Intrinsic::alloc_token_id) {
92bool containsPointer(
const MDNode *MD) {
95 return CI->getValue().getBoolValue();
101 : MaxTokens(MaxTokens ? MaxTokens : TokenTy.
getBitMask()) {
108 return Val % MaxTokens;
115class IncrementMode :
public ModeBase {
117 using ModeBase::ModeBase;
120 return boundedToken(Counter++);
128class RandomMode :
public ModeBase {
131 std::unique_ptr<RandomNumberGenerator> RNG)
132 : ModeBase(TokenTy, MaxTokens), RNG(std::move(RNG)) {}
134 return boundedToken((*RNG)());
138 std::unique_ptr<RandomNumberGenerator> RNG;
144class TypeHashMode :
public ModeBase {
152 if (
MDNode *
N = getAllocTokenMetadata(CB)) {
159 remarkNoMetadata(CB, ORE);
165 static void remarkNoMetadata(
const CallBase &CB,
170 ore::NV CalleeNV(
"Callee", Callee ? Callee->getName() :
"<unknown>");
172 <<
"Call to '" << CalleeNV <<
"' in '" << FuncNV
173 <<
"' without source-level type token";
181class TypeHashPointerSplitMode :
public TypeHashMode {
183 using TypeHashMode::TypeHashMode;
186 if (
MDNode *
N = getAllocTokenMetadata(CB)) {
196 remarkNoMetadata(CB, ORE);
203class TypeFuncHashMode :
public TypeHashMode {
210 MDNode *
N = getAllocTokenMetadata(CB);
212 remarkNoMetadata(CB, ORE);
216 if (
N->getNumOperands() != 3) {
218 &CB,
"!alloc_token without function name is incompatible with mode " +
226 remarkNoMetadata(CB, ORE);
245 if (
auto *Val = IntModuleFlagOrNull(
"alloc-token-max"))
247 if (
auto *Val = IntModuleFlagOrNull(
"alloc-token-fast-abi"))
249 if (
auto *Val = IntModuleFlagOrNull(
"alloc-token-extended"))
264 : CLOpts(CLOpts),
Options(resolveOptions(CLOpts, std::move(Opts), M)),
277 CLOpts.alloc_token_fallback);
281 CLOpts.alloc_token_fallback);
286 CLOpts.alloc_token_fallback,
Options.Mode);
295 std::optional<LibFunc>
299 bool isInstrumentableLibFunc(LibFunc Func,
const CallBase &CB,
303 static bool ignoreInstrumentableLibFunc(LibFunc Func);
307 bool replaceAllocationCall(
CallBase *CB, LibFunc Func,
313 LibFunc OriginalFunc);
320 return std::visit([&](
auto &&
Mode) {
return Mode(CB, ORE); },
Mode);
323 const InstrumentationOptions &CLOpts;
331 std::variant<IncrementMode, RandomMode, TypeHashMode,
332 TypeHashPointerSplitMode, TypeFuncHashMode>
336bool AllocToken::instrumentFunction(
Function &
F) {
338 if (
F.hasFnAttribute(Attribute::Naked))
348 const bool InstrumentFunction =
349 F.hasFnAttribute(Attribute::SanitizeAllocToken) &&
350 !
F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation);
360 II &&
II->getIntrinsicID() == Intrinsic::alloc_token_id) {
365 if (!InstrumentFunction)
371 if (std::optional<LibFunc> Func = shouldInstrumentCall(*CB, *TLI))
376 if (AllocCalls.
empty() && IntrinsicInsts.
empty())
382 for (
auto &[CB, Func] : AllocCalls)
383 Modified |= replaceAllocationCall(CB, Func, ORE, *TLI);
385 for (
auto *
II : IntrinsicInsts) {
386 replaceIntrinsicInst(
II, ORE);
391 NumFunctionsModified++;
396std::optional<LibFunc>
397AllocToken::shouldInstrumentCall(
const CallBase &CB,
407 if (Func != NotLibFunc) {
408 if (isInstrumentableLibFunc(Func, CB, TLI))
417bool AllocToken::isInstrumentableLibFunc(LibFunc Func,
const CallBase &CB,
419 if (ignoreInstrumentableLibFunc(Func))
428 case LibFunc_posix_memalign:
429 case LibFunc_size_returning_new:
430 case LibFunc_size_returning_new_hot_cold:
431 case LibFunc_size_returning_new_aligned:
432 case LibFunc_size_returning_new_aligned_hot_cold:
437 case LibFunc_ZnwjRKSt9nothrow_t:
438 case LibFunc_ZnwjSt11align_val_t:
439 case LibFunc_ZnwjSt11align_val_tRKSt9nothrow_t:
441 case LibFunc_Znwm12__hot_cold_t:
442 case LibFunc_ZnwmRKSt9nothrow_t:
443 case LibFunc_ZnwmRKSt9nothrow_t12__hot_cold_t:
444 case LibFunc_ZnwmSt11align_val_t:
445 case LibFunc_ZnwmSt11align_val_t12__hot_cold_t:
446 case LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t:
447 case LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t12__hot_cold_t:
449 case LibFunc_ZnajRKSt9nothrow_t:
450 case LibFunc_ZnajSt11align_val_t:
451 case LibFunc_ZnajSt11align_val_tRKSt9nothrow_t:
453 case LibFunc_Znam12__hot_cold_t:
454 case LibFunc_ZnamRKSt9nothrow_t:
455 case LibFunc_ZnamRKSt9nothrow_t12__hot_cold_t:
456 case LibFunc_ZnamSt11align_val_t:
457 case LibFunc_ZnamSt11align_val_t12__hot_cold_t:
458 case LibFunc_ZnamSt11align_val_tRKSt9nothrow_t:
459 case LibFunc_ZnamSt11align_val_tRKSt9nothrow_t12__hot_cold_t:
460 return CLOpts.alloc_token_cover_replaceable_new;
467bool AllocToken::ignoreInstrumentableLibFunc(LibFunc Func) {
470 case LibFunc_dunder_strdup:
471 case LibFunc_strndup:
472 case LibFunc_dunder_strndup:
479bool AllocToken::replaceAllocationCall(
CallBase *CB, LibFunc Func,
484 FunctionCallee TokenAlloc = getTokenAllocFunction(*CB, TokenID, Func);
487 NumAllocationsInstrumented++;
506 II->getUnwindDest(), NewArgs);
508 NewCall = IRB.
CreateCall(TokenAlloc, NewArgs);
523 LibFunc OriginalFunc) {
524 std::optional<std::pair<LibFunc, uint64_t>>
Key;
525 if (OriginalFunc != NotLibFunc) {
526 Key = std::make_pair(OriginalFunc,
Options.FastABI ? TokenID : 0);
527 auto It = TokenAllocFunctions.find(*
Key);
528 if (It != TokenAllocFunctions.end())
536 if (OldFTy->isVarArg())
539 Type *RetTy = OldFTy->getReturnType();
541 std::string TokenAllocName = CLOpts.alloc_token_prefix.str();
543 TokenAllocName +=
utostr(TokenID) +
"_";
546 TokenAllocName += Callee->getName();
550 Mod.getOrInsertFunction(TokenAllocName, NewFTy, NewAttrs);
553 TokenAllocFunctions[*
Key] = TokenAlloc;
559 assert(
II->getIntrinsicID() == Intrinsic::alloc_token_id);
563 II->replaceAllUsesWith(V);
564 II->eraseFromParent();
573 AllocToken
Pass(InstrumentationOptions::Global, Options, M,
MAM);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Expand Atomic instructions
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file defines the DenseMap class.
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
print mir2vec MIR2Vec Vocabulary Printer Pass
uint64_t IntrinsicInst * II
if(auto Err=PB.parsePassPipeline(MPM, Passes)) return wrap(std MPM run * Mod
FunctionAnalysisManager FAM
ModuleAnalysisManager MAM
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
LLVM_ABI AllocTokenPass(AllocTokenOptions Opts={})
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
Represents analyses that only rely on functions' control flow.
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
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
void setAttributes(AttributeList A)
Set the attributes for this call.
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 setCalledFunction(Function *Fn)
Sets the function called, including updating the function type.
LLVM_ABI bool isTailCall() const
Tests if this call site is marked as a tail call.
void setTailCall(bool IsTc=true)
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
FunctionType * getFunctionType()
unsigned getNumParams() const
Return the number of fixed parameters this function type requires.
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
@ AvailableExternallyLinkage
Available for inspection, not emission.
InvokeInst * CreateInvoke(FunctionType *Ty, Value *Callee, BasicBlock *NormalDest, BasicBlock *UnwindDest, ArrayRef< Value * > Args, ArrayRef< OperandBundleDef > OpBundles, const Twine &Name="")
Create an invoke instruction.
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this Instruction.
LLVM_ABI void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())
Copy metadata from SrcInst to this instruction.
Class to represent integer types.
uint64_t getBitMask() const
Return a bitmask with ones set for all of the bits that can be set by an unsigned version of this typ...
A wrapper class for inspecting calls to intrinsic functions.
LLVM_ABI void emitError(const Instruction *I, const Twine &ErrorStr)
emitError - Emit an error message to the currently installed error handler with optional location inf...
const MDOperand & getOperand(unsigned I) const
unsigned getNumOperands() const
Return number of MDNode operands.
LLVM_ABI StringRef getString() const
A Module instance is used to store all the information related to an LLVM module.
Pass interface - Implemented by all 'passes'.
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 & preserveSet()
Mark an analysis set as preserved.
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
LibFunc getLibFunc(StringRef funcName) const
Searches for a particular function name.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVMContext & getContext() const
All values hold a context through their type.
const ParentTy * getParent() const
Pass manager infrastructure for declaring and invalidating analyses.
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract_or_null(Y &&MD)
Extract a Value from Metadata, allowing null.
DiagnosticInfoOptimizationBase::Argument NV
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI std::optional< uint64_t > getAllocToken(AllocTokenMode Mode, const AllocTokenMetadata &Metadata, uint64_t MaxTokens)
Calculates stable allocation token ID.
LLVM_ABI std::pair< StringRef, StringRef > getToken(StringRef Source, StringRef Delimiters=" \t\n\v\f\r")
getToken - This function extracts one token from source, ignoring any leading characters that appear ...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
std::string utostr(uint64_t X, bool isNeg=false)
auto dyn_cast_or_null(const Y &Val)
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
@ Mod
The access may modify the value stored in memory.
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI bool isAllocationFn(const Value *V, const TargetLibraryInfo *TLI)
Tests if a value is a call or invoke to a library function that allocates or reallocates memory (eith...
constexpr bool valueOr(BoolOrDefault X, bool Default)
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
AllocTokenMode
Modes for generating allocation token IDs.
@ TypeFuncHashPointerSplit
Like TypeFuncHash, but for MaxTokens > 1 the most significant bit of the ID space is set for types th...
@ TypeHash
Token ID based on allocated type hash.
@ Random
Simple mode that returns a statically-assigned random token ID.
@ Increment
Incrementally increasing token ID.
@ TypeFuncHash
Token ID based on allocated type hash and containing function name hash.
@ TypeHashPointerSplit
Token ID based on allocated type hash, where the top half ID-space is reserved for types that contain...
LLVM_ABI std::optional< AllocTokenMode > getAllocTokenModeFromString(StringRef Name)
Returns the AllocTokenMode from its canonical string name; if an invalid name was provided returns nu...
LLVM_ABI StringRef getAllocTokenModeAsString(AllocTokenMode Mode)
Returns the canonical string name for the given AllocTokenMode.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Implement std::hash so that hash_code can be used in STL containers.