57#define DEBUG_TYPE "alloc-token"
63enum class TokenMode :
unsigned {
76 TypeHashPointerSplit = 3,
83 cl::init(TokenMode::TypeHashPointerSplit),
86 "Incrementally increasing token ID"),
88 "Statically-assigned random token ID"),
90 "Token ID based on allocated type hash"),
92 TokenMode::TypeHashPointerSplit,
"typehashpointersplit",
93 "Token ID based on allocated type hash, where the top half "
94 "ID-space is reserved for types that contain pointers and the "
95 "bottom half for types that do not contain pointers. ")));
98 cl::desc(
"The allocation function prefix"),
102 cl::desc(
"Maximum number of tokens (0 = no max)"),
106 ClFastABI(
"alloc-token-fast-abi",
107 cl::desc(
"The token ID is encoded in the function name"),
115 ClExtended(
"alloc-token-extended",
116 cl::desc(
"Extend coverage to custom allocation functions"),
123cl::opt<bool> ClCoverReplaceableNew(
"alloc-token-cover-replaceable-new",
124 cl::desc(
"Cover replaceable operator new"),
128 "alloc-token-fallback",
129 cl::desc(
"The default fallback token where none could be determined"),
134STATISTIC(NumFunctionsInstrumented,
"Functions instrumented");
135STATISTIC(NumAllocationsInstrumented,
"Allocations instrumented");
146 assert(Ret->getNumOperands() == 2 &&
"bad !alloc_token");
152bool containsPointer(
const MDNode *MD) {
155 return CI->getValue().getBoolValue();
161 : MaxTokens(MaxTokens ? MaxTokens : TokenTy.
getBitMask()) {
168 return Val % MaxTokens;
175class IncrementMode :
public ModeBase {
177 using ModeBase::ModeBase;
180 return boundedToken(Counter++);
188class RandomMode :
public ModeBase {
191 std::unique_ptr<RandomNumberGenerator> RNG)
192 : ModeBase(TokenTy, MaxTokens), RNG(std::move(RNG)) {}
194 return boundedToken((*RNG)());
198 std::unique_ptr<RandomNumberGenerator> RNG;
204class TypeHashMode :
public ModeBase {
206 using ModeBase::ModeBase;
209 const auto [
N,
H] = getHash(CB, ORE);
210 return N ? boundedToken(
H) :
H;
214 std::pair<MDNode *, uint64_t> getHash(
const CallBase &CB,
216 if (
MDNode *
N = getAllocTokenMetadata(CB)) {
221 remarkNoMetadata(CB, ORE);
222 return {
nullptr, ClFallbackToken};
226 static void remarkNoMetadata(
const CallBase &CB,
231 ore::NV CalleeNV(
"Callee", Callee ? Callee->getName() :
"<unknown>");
233 <<
"Call to '" << CalleeNV <<
"' in '" << FuncNV
234 <<
"' without source-level type token";
240class TypeHashPointerSplitMode :
public TypeHashMode {
242 using TypeHashMode::TypeHashMode;
247 const uint64_t HalfTokens = MaxTokens / 2;
248 const auto [
N,
H] = getHash(CB, ORE);
256 if (containsPointer(
N))
275 :
Options(transformOptionsFromCl(std::move(Opts))),
Mod(M),
277 Mode(IncrementMode(*IntPtrTy, *
Options.MaxTokens)) {
279 case TokenMode::Increment:
281 case TokenMode::Random:
282 Mode.emplace<RandomMode>(*IntPtrTy, *
Options.MaxTokens,
285 case TokenMode::TypeHash:
286 Mode.emplace<TypeHashMode>(*IntPtrTy, *
Options.MaxTokens);
288 case TokenMode::TypeHashPointerSplit:
289 Mode.emplace<TypeHashPointerSplitMode>(*IntPtrTy, *
Options.MaxTokens);
298 std::optional<LibFunc>
306 static bool ignoreInstrumentableLibFunc(
LibFunc Func);
320 return std::visit([&](
auto &&
Mode) {
return Mode(CB, ORE); },
Mode);
330 std::variant<IncrementMode, RandomMode, TypeHashMode,
331 TypeHashPointerSplitMode>
335bool AllocToken::instrumentFunction(
Function &
F) {
337 if (
F.hasFnAttribute(Attribute::Naked))
339 if (
F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation))
345 if (!
F.hasFnAttribute(Attribute::SanitizeAllocToken))
357 if (std::optional<LibFunc> Func = shouldInstrumentCall(*CB, TLI))
358 AllocCalls.emplace_back(CB, Func.value());
362 for (
auto &[CB, Func] : AllocCalls)
363 Modified |= replaceAllocationCall(CB, Func, ORE, TLI);
366 NumFunctionsInstrumented++;
370std::optional<LibFunc>
371AllocToken::shouldInstrumentCall(
const CallBase &CB,
382 if (isInstrumentableLibFunc(Func, CB, TLI))
384 }
else if (
Options.Extended && getAllocTokenMetadata(CB)) {
391bool AllocToken::isInstrumentableLibFunc(
LibFunc Func,
const CallBase &CB,
393 if (ignoreInstrumentableLibFunc(Func))
402 case LibFunc_posix_memalign:
403 case LibFunc_size_returning_new:
404 case LibFunc_size_returning_new_hot_cold:
405 case LibFunc_size_returning_new_aligned:
406 case LibFunc_size_returning_new_aligned_hot_cold:
411 case LibFunc_ZnwjRKSt9nothrow_t:
412 case LibFunc_ZnwjSt11align_val_t:
413 case LibFunc_ZnwjSt11align_val_tRKSt9nothrow_t:
415 case LibFunc_Znwm12__hot_cold_t:
416 case LibFunc_ZnwmRKSt9nothrow_t:
417 case LibFunc_ZnwmRKSt9nothrow_t12__hot_cold_t:
418 case LibFunc_ZnwmSt11align_val_t:
419 case LibFunc_ZnwmSt11align_val_t12__hot_cold_t:
420 case LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t:
421 case LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t12__hot_cold_t:
423 case LibFunc_ZnajRKSt9nothrow_t:
424 case LibFunc_ZnajSt11align_val_t:
425 case LibFunc_ZnajSt11align_val_tRKSt9nothrow_t:
427 case LibFunc_Znam12__hot_cold_t:
428 case LibFunc_ZnamRKSt9nothrow_t:
429 case LibFunc_ZnamRKSt9nothrow_t12__hot_cold_t:
430 case LibFunc_ZnamSt11align_val_t:
431 case LibFunc_ZnamSt11align_val_t12__hot_cold_t:
432 case LibFunc_ZnamSt11align_val_tRKSt9nothrow_t:
433 case LibFunc_ZnamSt11align_val_tRKSt9nothrow_t12__hot_cold_t:
434 return ClCoverReplaceableNew;
441bool AllocToken::ignoreInstrumentableLibFunc(
LibFunc Func) {
444 case LibFunc_dunder_strdup:
445 case LibFunc_strndup:
446 case LibFunc_dunder_strndup:
458 FunctionCallee TokenAlloc = getTokenAllocFunction(*CB, TokenID, Func);
461 NumAllocationsInstrumented++;
473 NewArgs.
push_back(ConstantInt::get(IntPtrTy, TokenID));
480 II->getUnwindDest(), NewArgs);
482 NewCall = IRB.
CreateCall(TokenAlloc, NewArgs);
498 std::optional<std::pair<LibFunc, uint64_t>>
Key;
500 Key = std::make_pair(OriginalFunc,
Options.FastABI ? TokenID : 0);
501 auto It = TokenAllocFunctions.find(*
Key);
502 if (It != TokenAllocFunctions.end())
510 if (OldFTy->isVarArg())
513 Type *RetTy = OldFTy->getReturnType();
515 std::string TokenAllocName = ClFuncPrefix;
517 TokenAllocName +=
utostr(TokenID) +
"_";
520 TokenAllocName += Callee->getName();
524 F->copyAttributesFrom(Callee);
527 TokenAllocFunctions[*
Key] = TokenAlloc;
537 AllocToken
Pass(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...
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
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 SmallPtrSet class.
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...
const MDOperand & getOperand(unsigned I) const
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.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
bool getLibFunc(StringRef funcName, LibFunc &F) const
Searches for a particular function name.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
const ParentTy * getParent() const
Pass manager infrastructure for declaring and invalidating analyses.
@ C
The default llvm calling convention, compatible with C.
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
DiagnosticInfoOptimizationBase::Argument NV
This is an optimization pass for GlobalISel generic memory operations.
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)
LLVM_ABI uint64_t getStableSipHash(StringRef Str)
Compute a stable 64-bit hash of the given string.
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...
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Implement std::hash so that hash_code can be used in STL containers.
std::optional< uint64_t > MaxTokens