51#define DEBUG_TYPE "sanmd"
58constexpr uint32_t kVersionPtrSizeRel = (1u << 16);
59constexpr int kCtorDtorPriority = 2;
68 static const MetadataInfo Covered;
69 static const MetadataInfo Atomics;
73 explicit constexpr MetadataInfo(
StringRef FunctionPrefix,
75 : FunctionPrefix(FunctionPrefix), SectionSuffix(SectionSuffix) {}
77const MetadataInfo MetadataInfo::Covered{
79const MetadataInfo MetadataInfo::Atomics{
89STATISTIC(NumMetadataCovered,
"Metadata attached to covered functions");
90STATISTIC(NumMetadataAtomics,
"Metadata attached to atomics");
91STATISTIC(NumMetadataUAR,
"Metadata attached to UAR functions");
97transformOptionsFromCl(
const InstrumentationOptions &CLOpts,
99 Opts.
Covered |= CLOpts.sanitizer_metadata_covered;
100 Opts.Atomics |= CLOpts.sanitizer_metadata_atomics;
101 Opts.UAR |= CLOpts.sanitizer_metadata_uar;
102 return std::move(Opts);
105class SanitizerBinaryMetadata {
107 SanitizerBinaryMetadata(
const InstrumentationOptions &CLOpts,
Module &M,
109 std::unique_ptr<SpecialCaseList> Ignorelist)
110 : CLOpts(CLOpts),
Mod(M),
111 Options(transformOptionsFromCl(CLOpts, std::move(Opts))),
112 Ignorelist(std::move(Ignorelist)), TargetTriple(M.getTargetTriple()),
113 VersionStr(
utostr(getVersion())), IRB(M) {
115 assert(TargetTriple.isOSBinFormatELF() &&
"ELF only");
116 assert(!TargetTriple.isGPU() &&
"Device targets are not supported");
124 const auto CM =
Mod.getCodeModel();
126 Version |= kVersionPtrSizeRel;
130 void runOn(
Function &
F, MetadataInfoSet &MIS);
155 bool pretendAtomicAccess(
const Value *Addr);
157 const InstrumentationOptions &CLOpts;
160 std::unique_ptr<SpecialCaseList> Ignorelist;
161 const Triple TargetTriple;
162 const std::string VersionStr;
168bool SanitizerBinaryMetadata::run() {
184 const std::array<Type *, 3> InitTypes = {Int32Ty, PtrTy, PtrTy};
185 auto *Version = ConstantInt::get(Int32Ty, getVersion());
187 for (
const MetadataInfo *
MI : MIS) {
188 const std::array<
Value *, InitTypes.size()> InitArgs = {
190 getSectionMarker(getSectionStart(
MI->SectionSuffix), PtrTy),
191 getSectionMarker(getSectionEnd(
MI->SectionSuffix), PtrTy),
197 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)
212 Mod, StructorPrefix +
".module_dtor",
213 (
MI->FunctionPrefix +
"_del").str(), InitTypes, InitArgs,
215 CLOpts.sanitizer_metadata_weak_callbacks)
229 CtorComdatKey = Ctor;
230 DtorComdatKey = Dtor;
239void SanitizerBinaryMetadata::runOn(
Function &
F, MetadataInfoSet &MIS) {
243 if (
F.hasFnAttribute(Attribute::Naked))
245 if (
F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation))
247 if (Ignorelist && Ignorelist->inSection(
"metadata",
"fun",
F.getName()))
259 bool RequiresCovered =
false;
264 RequiresCovered |= runOn(
I, MIS, MDB, FeatureMask);
267 if (CLOpts.sanitizer_metadata_nosanitize_attr &&
268 F.hasFnAttribute(
"no_sanitize_thread"))
273 RequiresCovered =
true;
280 if (
Options.Covered || (FeatureMask && RequiresCovered)) {
281 NumMetadataCovered++;
282 const auto *
MI = &MetadataInfo::Covered;
287 F.setMetadata(LLVMContext::MD_pcsections,
292bool isUARSafeCall(CallInst *CI) {
300 return F && (
F->isIntrinsic() ||
F->doesNotReturn() ||
301 F->getName().starts_with(
"__asan_") ||
302 F->getName().starts_with(
"__hwsan_") ||
303 F->getName().starts_with(
"__ubsan_") ||
304 F->getName().starts_with(
"__msan_") ||
305 F->getName().starts_with(
"__tsan_"));
308bool hasUseAfterReturnUnsafeUses(
Value &V) {
309 for (User *U :
V.users()) {
311 if (
I->isLifetimeStartOrEnd() ||
I->isDroppable())
314 if (isUARSafeCall(CI))
321 if (
SI->getOperand(1) == &V)
325 if (!hasUseAfterReturnUnsafeUses(*GEPI))
328 if (!hasUseAfterReturnUnsafeUses(*BCI))
337bool useAfterReturnUnsafe(Instruction &
I) {
339 return hasUseAfterReturnUnsafeUses(
I);
344 return CI->
isTailCall() && !isUARSafeCall(CI);
348bool SanitizerBinaryMetadata::pretendAtomicAccess(
const Value *Addr) {
359 if (GV->hasSection()) {
360 const auto OF =
Mod.getTargetTriple().getObjectFormat();
363 if (GV->getSection().ends_with(ProfSec))
366 if (GV->getName().starts_with(
"__llvm_gcov") ||
367 GV->getName().starts_with(
"__llvm_gcda"))
374bool maybeSharedMutable(
const Value *Addr) {
385 if (GV->isConstant())
392bool SanitizerBinaryMetadata::runOn(Instruction &
I, MetadataInfoSet &MIS,
393 MDBuilder &MDB,
uint64_t &FeatureMask) {
395 bool RequiresCovered =
false;
401 if (useAfterReturnUnsafe(
I))
406 const Value *Addr =
nullptr;
408 Addr =
SI->getPointerOperand();
410 Addr = LI->getPointerOperand();
412 if (
I.mayReadOrWriteMemory() && maybeSharedMutable(Addr)) {
415 pretendAtomicAccess(Addr)) {
416 NumMetadataAtomics++;
417 InstMetadata.
push_back(&MetadataInfo::Atomics);
420 RequiresCovered =
true;
425 if (!InstMetadata.
empty()) {
426 MIS.insert_range(InstMetadata);
428 for (
const auto &
MI : InstMetadata)
433 return RequiresCovered;
437SanitizerBinaryMetadata::getSectionMarker(
const Twine &MarkerName,
Type *Ty) {
440 auto *Marker =
new GlobalVariable(
Mod, Ty,
false,
441 GlobalVariable::ExternalWeakLinkage,
442 nullptr, MarkerName);
447StringRef SanitizerBinaryMetadata::getSectionName(StringRef SectionSuffix) {
450 return StringPool.
save(SectionSuffix + VersionStr +
"!C");
453StringRef SanitizerBinaryMetadata::getSectionStart(StringRef SectionSuffix) {
458 return StringPool.
save(
"__start_" + SectionSuffix + VersionStr);
461StringRef SanitizerBinaryMetadata::getSectionEnd(StringRef SectionSuffix) {
462 return StringPool.
save(
"__stop_" + SectionSuffix + VersionStr);
472 VFS(VFS ?
std::
move(VFS) :
vfs::getRealFileSystem()),
473 IgnorelistFiles(
std::
move(IgnorelistFiles)) {}
477 std::unique_ptr<SpecialCaseList> Ignorelist;
478 if (!IgnorelistFiles.empty()) {
480 if (Ignorelist->inSection(
"metadata",
"src", M.getSourceFileName()))
484 SanitizerBinaryMetadata
Pass(InstrumentationOptions::Global, M, Options,
485 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),...
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.
LLVM_ABI void setComdat(Comdat *C)
void setLinkage(LinkageTypes LT)
@ HiddenVisibility
The GV is hidden.
void setVisibility(VisibilityTypes V)
@ 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.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
@ 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.
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.
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.