52#define DEBUG_TYPE "sanmd"
59constexpr uint32_t kVersionPtrSizeRel = (1u << 16);
60constexpr int kCtorDtorPriority = 2;
69 static const MetadataInfo Covered;
70 static const MetadataInfo Atomics;
74 explicit constexpr MetadataInfo(
StringRef FunctionPrefix,
76 : FunctionPrefix(FunctionPrefix), SectionSuffix(SectionSuffix) {}
78const MetadataInfo MetadataInfo::Covered{
80const MetadataInfo MetadataInfo::Atomics{
90STATISTIC(NumMetadataCovered,
"Metadata attached to covered functions");
91STATISTIC(NumMetadataAtomics,
"Metadata attached to atomics");
92STATISTIC(NumMetadataUAR,
"Metadata attached to UAR functions");
98transformOptionsFromCl(
const InstrumentationOptions &CLOpts,
100 Opts.
Covered |= CLOpts.sanitizer_metadata_covered;
101 Opts.Atomics |= CLOpts.sanitizer_metadata_atomics;
102 Opts.UAR |= CLOpts.sanitizer_metadata_uar;
103 return std::move(Opts);
106class SanitizerBinaryMetadata {
108 SanitizerBinaryMetadata(
const InstrumentationOptions &CLOpts,
Module &M,
110 std::unique_ptr<SpecialCaseList> Ignorelist)
111 : CLOpts(CLOpts),
Mod(M),
112 Options(transformOptionsFromCl(CLOpts, std::move(Opts))),
113 Ignorelist(std::move(Ignorelist)), TargetTriple(M.getTargetTriple()),
114 VersionStr(
utostr(getVersion())), IRB(M) {
116 assert(TargetTriple.isOSBinFormatELF() &&
"ELF only");
117 assert(!TargetTriple.isGPU() &&
"Device targets are not supported");
125 const auto CM =
Mod.getCodeModel();
127 Version |= kVersionPtrSizeRel;
131 void runOn(
Function &
F, MetadataInfoSet &MIS);
156 bool pretendAtomicAccess(
const Value *Addr);
158 const InstrumentationOptions &CLOpts;
161 std::unique_ptr<SpecialCaseList> Ignorelist;
162 const Triple TargetTriple;
163 const std::string VersionStr;
169bool SanitizerBinaryMetadata::run() {
185 const std::array<Type *, 3> InitTypes = {Int32Ty, PtrTy, PtrTy};
186 auto *Version = ConstantInt::get(Int32Ty, getVersion());
188 for (
const MetadataInfo *
MI : MIS) {
189 const std::array<
Value *, InitTypes.size()> InitArgs = {
191 getSectionMarker(getSectionStart(
MI->SectionSuffix), PtrTy),
192 getSectionMarker(getSectionEnd(
MI->SectionSuffix), PtrTy),
198 const std::string StructorPrefix = (
MI->FunctionPrefix + VersionStr).str();
205 Mod, StructorPrefix +
".module_ctor",
206 (
MI->FunctionPrefix +
"_add").str(), InitTypes, InitArgs,
208 CLOpts.sanitizer_metadata_weak_callbacks);
210 Mod, StructorPrefix +
".module_dtor",
211 (
MI->FunctionPrefix +
"_del").str(), InitTypes, InitArgs,
213 CLOpts.sanitizer_metadata_weak_callbacks);
215 TargetLibraryInfo::getExtAttrForI32Param(TargetTriple,
225 Ctor->setComdat(
Mod.getOrInsertComdat(Ctor->getName()));
226 Dtor->setComdat(
Mod.getOrInsertComdat(Dtor->getName()));
232 CtorComdatKey = Ctor;
233 DtorComdatKey = Dtor;
242void SanitizerBinaryMetadata::runOn(
Function &
F, MetadataInfoSet &MIS) {
246 if (
F.hasFnAttribute(Attribute::Naked))
248 if (
F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation))
250 if (Ignorelist && Ignorelist->inSection(
"metadata",
"fun",
F.getName()))
262 bool RequiresCovered =
false;
267 RequiresCovered |= runOn(
I, MIS, MDB, FeatureMask);
270 if (CLOpts.sanitizer_metadata_nosanitize_attr &&
271 F.hasFnAttribute(
"no_sanitize_thread"))
276 RequiresCovered =
true;
283 if (
Options.Covered || (FeatureMask && RequiresCovered)) {
284 NumMetadataCovered++;
285 const auto *
MI = &MetadataInfo::Covered;
290 F.setMetadata(LLVMContext::MD_pcsections,
295bool isUARSafeCall(CallInst *CI) {
303 return F && (
F->isIntrinsic() ||
F->doesNotReturn() ||
304 F->getName().starts_with(
"__asan_") ||
305 F->getName().starts_with(
"__hwsan_") ||
306 F->getName().starts_with(
"__ubsan_") ||
307 F->getName().starts_with(
"__msan_") ||
308 F->getName().starts_with(
"__tsan_"));
311bool hasUseAfterReturnUnsafeUses(
Value &V) {
312 for (User *U :
V.users()) {
314 if (
I->isLifetimeStartOrEnd() ||
I->isDroppable())
317 if (isUARSafeCall(CI))
324 if (
SI->getOperand(1) == &V)
328 if (!hasUseAfterReturnUnsafeUses(*GEPI))
331 if (!hasUseAfterReturnUnsafeUses(*BCI))
340bool useAfterReturnUnsafe(Instruction &
I) {
342 return hasUseAfterReturnUnsafeUses(
I);
347 return CI->
isTailCall() && !isUARSafeCall(CI);
351bool SanitizerBinaryMetadata::pretendAtomicAccess(
const Value *Addr) {
362 if (GV->hasSection()) {
363 const auto OF =
Mod.getTargetTriple().getObjectFormat();
366 if (GV->getSection().ends_with(ProfSec))
369 if (GV->getName().starts_with(
"__llvm_gcov") ||
370 GV->getName().starts_with(
"__llvm_gcda"))
377bool maybeSharedMutable(
const Value *Addr) {
388 if (GV->isConstant())
395bool SanitizerBinaryMetadata::runOn(Instruction &
I, MetadataInfoSet &MIS,
396 MDBuilder &MDB,
uint64_t &FeatureMask) {
398 bool RequiresCovered =
false;
404 if (useAfterReturnUnsafe(
I))
409 const Value *Addr =
nullptr;
411 Addr =
SI->getPointerOperand();
413 Addr = LI->getPointerOperand();
415 if (
I.mayReadOrWriteMemory() && maybeSharedMutable(Addr)) {
418 pretendAtomicAccess(Addr)) {
419 NumMetadataAtomics++;
420 InstMetadata.
push_back(&MetadataInfo::Atomics);
423 RequiresCovered =
true;
428 if (!InstMetadata.
empty()) {
429 MIS.insert_range(InstMetadata);
431 for (
const auto &
MI : InstMetadata)
436 return RequiresCovered;
440SanitizerBinaryMetadata::getSectionMarker(
const Twine &MarkerName,
Type *Ty) {
443 auto *Marker =
new GlobalVariable(
Mod, Ty,
false,
444 GlobalVariable::ExternalWeakLinkage,
445 nullptr, MarkerName);
450StringRef SanitizerBinaryMetadata::getSectionName(StringRef SectionSuffix) {
453 return StringPool.
save(SectionSuffix + VersionStr +
"!C");
456StringRef SanitizerBinaryMetadata::getSectionStart(StringRef SectionSuffix) {
461 return StringPool.
save(
"__start_" + SectionSuffix + VersionStr);
464StringRef SanitizerBinaryMetadata::getSectionEnd(StringRef SectionSuffix) {
465 return StringPool.
save(
"__stop_" + SectionSuffix + VersionStr);
475 VFS(VFS ?
std::
move(VFS) :
vfs::getRealFileSystem()),
476 IgnorelistFiles(
std::
move(IgnorelistFiles)) {}
480 std::unique_ptr<SpecialCaseList> Ignorelist;
481 if (!IgnorelistFiles.empty()) {
483 if (Ignorelist->inSection(
"metadata",
"src", M.getSourceFileName()))
488 SanitizerBinaryMetadata
Pass(CLOpts, M, Options, std::move(Ignorelist));
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the BumpPtrAllocator interface.
Module.h This file contains the declarations for the Module class.
print mir2vec MIR2Vec Vocabulary Printer Pass
if(auto Err=PB.parsePassPipeline(MPM, Passes)) return wrap(std MPM run * Mod
This file implements a set that has insertion order iteration characteristics.
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)
Defines the virtual file system interface vfs::FileSystem.
A container for analyses that lazily runs them and caches their results.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
AttrKind
This enumeration lists the attributes that can be associated with parameters, function results,...
@ None
No attributes have been set.
LLVM Basic Block Representation.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
This is an important base class in LLVM.
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
@ HiddenVisibility
The GV is hidden.
@ ExternalLinkage
Externally visible function.
@ AvailableExternallyLinkage
Available for inspection, not emission.
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
ConstantInt * getInt64(uint64_t C)
Get a constant 64-bit value.
PointerType * getPtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
A smart pointer to a reference-counted object that inherits from RefCountedBase or ThreadSafeRefCount...
LLVM_ABI MDNode * createPCSections(ArrayRef< PCSection > Sections)
Return metadata for PC sections.
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.
A vector that has set insertion semantics.
void push_back(const T &Elt)
static LLVM_ABI std::unique_ptr< SpecialCaseList > createOrDie(const std::vector< std::string > &Paths, llvm::vfs::FileSystem &FS)
Parses the special case list entries from files.
Represent a constant reference to a string, i.e.
Triple - Helper class for working with autoconf configuration names.
bool supportsCOMDAT() const
Tests whether the target supports comdat.
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.
Saves strings in the provided stable storage and returns a StringRef with a stable character pointer.
StringRef save(const char *S)
LLVM Value Representation.
LLVM_ABI const Value * stripInBoundsOffsets(function_ref< void(const Value *)> Func=[](const Value *) {}) const
Strip off pointer casts and inbounds GEPs.
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
static constexpr const StringLiteral & getSectionName(DebugSectionKind SectionKind)
Return the name of the section.
This is an optimization pass for GlobalISel generic memory operations.
const InstrumentationOptions & getInstrumentationOptions(const LLVMContext &C)
LLVM_ABI AllocaInst * findAllocaForValue(Value *V, bool OffsetZero=false)
Returns unique alloca where the value comes from, or nullptr.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
std::string utostr(uint64_t X, bool isNeg=false)
LLVM_ABI std::string getInstrProfSectionName(InstrProfSectKind IPSK, Triple::ObjectFormatType OF, bool AddSegmentInfo=true)
Return the name of the profile section corresponding to IPSK.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
constexpr uint64_t kSanitizerBinaryMetadataUAR
LLVM_ABI std::pair< Function *, FunctionCallee > createSanitizerCtorAndInitFunctions(Module &M, StringRef CtorName, StringRef InitName, ArrayRef< Type * > InitArgTypes, ArrayRef< Value * > InitArgs, StringRef VersionCheckName=StringRef(), bool Weak=false)
Creates sanitizer constructor function, and calls sanitizer's init function from it.
std::optional< SyncScope::ID > getAtomicSyncScopeID(const Instruction *I)
A helper function that returns an atomic operation's sync scope; returns std::nullopt if it is not an...
constexpr uint64_t kSanitizerBinaryMetadataAtomics
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
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...
constexpr char kSanitizerBinaryMetadataCoveredSection[]
@ Mod
The access may modify the value stored in memory.
LLVM_ABI bool PointerMayBeCaptured(const Value *V, bool ReturnCaptures, unsigned MaxUsesToExplore=0)
PointerMayBeCaptured - Return true if this pointer value may be captured by the enclosing function (w...
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI void appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data=nullptr)
Append F to the list of global ctors of module M with the given Priority.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
constexpr char kSanitizerBinaryMetadataAtomicsSection[]
BumpPtrAllocatorImpl<> BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
LLVM_ABI void appendToGlobalDtors(Module &M, Function *F, int Priority, Constant *Data=nullptr)
Same as appendToGlobalCtors(), but for global dtors.
Implement std::hash so that hash_code can be used in STL containers.