LLVM 20.0.0git
Macros | Enumerations | Functions | Variables
HWAddressSanitizer.cpp File Reference

This file is a part of HWAddressSanitizer, an address basic correctness checker based on tagged addressing. More...

#include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Analysis/BlockFrequencyInfo.h"
#include "llvm/Analysis/DomTreeUpdater.h"
#include "llvm/Analysis/GlobalsModRef.h"
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
#include "llvm/Analysis/PostDominators.h"
#include "llvm/Analysis/ProfileSummaryInfo.h"
#include "llvm/Analysis/StackSafetyAnalysis.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Value.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/MD5.h"
#include "llvm/Support/RandomNumberGenerator.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/Triple.h"
#include "llvm/Transforms/Instrumentation/AddressSanitizerCommon.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Instrumentation.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Transforms/Utils/MemoryTaggingSupport.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"
#include "llvm/Transforms/Utils/PromoteMemToReg.h"
#include <optional>
#include <random>

Go to the source code of this file.

Macros

#define DEBUG_TYPE   "hwasan"
 

Enumerations

enum  RecordStackHistoryMode { none , instr , libcall }
 

Functions

 STATISTIC (NumTotalFuncs, "Number of total funcs")
 
 STATISTIC (NumInstrumentedFuncs, "Number of instrumented funcs")
 
 STATISTIC (NumNoProfileSummaryFuncs, "Number of funcs without PS")
 
static unsigned getPointerOperandIndex (Instruction *I)
 
static size_t TypeSizeToSizeIndex (uint32_t TypeSize)
 
static void emitRemark (const Function &F, OptimizationRemarkEmitter &ORE, bool Skip)
 

Variables

const char kHwasanModuleCtorName [] = "hwasan.module_ctor"
 
const char kHwasanNoteName [] = "hwasan.note"
 
const char kHwasanInitName [] = "__hwasan_init"
 
const char kHwasanPersonalityThunkName [] = "__hwasan_personality_thunk"
 
const char kHwasanShadowMemoryDynamicAddress []
 
static const size_t kNumberOfAccessSizes = 5
 
static const size_t kDefaultShadowScale = 4
 
static const unsigned kShadowBaseAlignment = 32
 
static cl::opt< std::string > ClMemoryAccessCallbackPrefix ("hwasan-memory-access-callback-prefix", cl::desc("Prefix for memory access callbacks"), cl::Hidden, cl::init("__hwasan_"))
 
static cl::opt< boolClKasanMemIntrinCallbackPrefix ("hwasan-kernel-mem-intrinsic-prefix", cl::desc("Use prefix for memory intrinsics in KASAN mode"), cl::Hidden, cl::init(false))
 
static cl::opt< boolClInstrumentWithCalls ("hwasan-instrument-with-calls", cl::desc("instrument reads and writes with callbacks"), cl::Hidden, cl::init(false))
 
static cl::opt< boolClInstrumentReads ("hwasan-instrument-reads", cl::desc("instrument read instructions"), cl::Hidden, cl::init(true))
 
static cl::opt< boolClInstrumentWrites ("hwasan-instrument-writes", cl::desc("instrument write instructions"), cl::Hidden, cl::init(true))
 
static cl::opt< boolClInstrumentAtomics ("hwasan-instrument-atomics", cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden, cl::init(true))
 
static cl::opt< boolClInstrumentByval ("hwasan-instrument-byval", cl::desc("instrument byval arguments"), cl::Hidden, cl::init(true))
 
static cl::opt< boolClRecover ("hwasan-recover", cl::desc("Enable recovery mode (continue-after-error)."), cl::Hidden, cl::init(false))
 
static cl::opt< boolClInstrumentStack ("hwasan-instrument-stack", cl::desc("instrument stack (allocas)"), cl::Hidden, cl::init(true))
 
static cl::opt< boolClUseStackSafety ("hwasan-use-stack-safety", cl::Hidden, cl::init(true), cl::Hidden, cl::desc("Use Stack Safety analysis results"), cl::Optional)
 
static cl::opt< size_t > ClMaxLifetimes ("hwasan-max-lifetimes-for-alloca", cl::Hidden, cl::init(3), cl::ReallyHidden, cl::desc("How many lifetime ends to handle for a single alloca."), cl::Optional)
 
static cl::opt< boolClUseAfterScope ("hwasan-use-after-scope", cl::desc("detect use after scope within function"), cl::Hidden, cl::init(true))
 
static cl::opt< boolClGenerateTagsWithCalls ("hwasan-generate-tags-with-calls", cl::desc("generate new tags with runtime library calls"), cl::Hidden, cl::init(false))
 
static cl::opt< boolClGlobals ("hwasan-globals", cl::desc("Instrument globals"), cl::Hidden, cl::init(false))
 
static cl::opt< int > ClMatchAllTag ("hwasan-match-all-tag", cl::desc("don't report bad accesses via pointers with this tag"), cl::Hidden, cl::init(-1))
 
static cl::opt< boolClEnableKhwasan ("hwasan-kernel", cl::desc("Enable KernelHWAddressSanitizer instrumentation"), cl::Hidden, cl::init(false))
 
static cl::opt< uint64_tClMappingOffset ("hwasan-mapping-offset", cl::desc("HWASan shadow mapping offset [EXPERIMENTAL]"), cl::Hidden)
 
static cl::opt< OffsetKind > ClMappingOffsetDynamic ("hwasan-mapping-offset-dynamic", cl::desc("HWASan shadow mapping dynamic offset location"), cl::Hidden, cl::values(clEnumValN(OffsetKind::kGlobal, "global", "Use global"), clEnumValN(OffsetKind::kIfunc, "ifunc", "Use ifunc global"), clEnumValN(OffsetKind::kTls, "tls", "Use TLS")))
 
static cl::opt< boolClFrameRecords ("hwasan-with-frame-record", cl::desc("Use ring buffer for stack allocations"), cl::Hidden)
 
static cl::opt< int > ClHotPercentileCutoff ("hwasan-percentile-cutoff-hot", cl::desc("Hot percentile cuttoff."))
 
static cl::opt< float > ClRandomSkipRate ("hwasan-random-rate", cl::desc("Probability value in the range [0.0, 1.0] " "to keep instrumentation of a function."))
 
static cl::opt< RecordStackHistoryModeClRecordStackHistory ("hwasan-record-stack-history", cl::desc("Record stack frames with tagged allocations in a thread-local " "ring buffer"), cl::values(clEnumVal(none, "Do not record stack ring history"), clEnumVal(instr, "Insert instructions into the prologue for " "storing into the stack ring buffer directly"), clEnumVal(libcall, "Add a call to __hwasan_add_frame_record for " "storing into the stack ring buffer")), cl::Hidden, cl::init(instr))
 
static cl::opt< boolClInstrumentMemIntrinsics ("hwasan-instrument-mem-intrinsics", cl::desc("instrument memory intrinsics"), cl::Hidden, cl::init(true))
 
static cl::opt< boolClInstrumentLandingPads ("hwasan-instrument-landing-pads", cl::desc("instrument landing pads"), cl::Hidden, cl::init(false))
 
static cl::opt< boolClUseShortGranules ("hwasan-use-short-granules", cl::desc("use short granules in allocas and outlined checks"), cl::Hidden, cl::init(false))
 
static cl::opt< boolClInstrumentPersonalityFunctions ("hwasan-instrument-personality-functions", cl::desc("instrument personality functions"), cl::Hidden)
 
static cl::opt< boolClInlineAllChecks ("hwasan-inline-all-checks", cl::desc("inline all checks"), cl::Hidden, cl::init(false))
 
static cl::opt< boolClInlineFastPathChecks ("hwasan-inline-fast-path-checks", cl::desc("inline all checks"), cl::Hidden, cl::init(false))
 
static cl::opt< boolClUsePageAliases ("hwasan-experimental-use-page-aliases", cl::desc("Use page aliasing in HWASan"), cl::Hidden, cl::init(false))
 

Detailed Description

This file is a part of HWAddressSanitizer, an address basic correctness checker based on tagged addressing.

Definition in file HWAddressSanitizer.cpp.

Macro Definition Documentation

◆ DEBUG_TYPE

#define DEBUG_TYPE   "hwasan"

Definition at line 71 of file HWAddressSanitizer.cpp.

Enumeration Type Documentation

◆ RecordStackHistoryMode

Enumerator
none 
instr 
libcall 

Definition at line 208 of file HWAddressSanitizer.cpp.

Function Documentation

◆ emitRemark()

static void emitRemark ( const Function F,
OptimizationRemarkEmitter ORE,
bool  Skip 
)
static

Definition at line 1560 of file HWAddressSanitizer.cpp.

References DEBUG_TYPE, llvm::OptimizationRemarkEmitter::emit(), and F.

◆ getPointerOperandIndex()

static unsigned getPointerOperandIndex ( Instruction I)
static

Definition at line 936 of file HWAddressSanitizer.cpp.

References I, and llvm::report_fatal_error().

◆ STATISTIC() [1/3]

STATISTIC ( NumInstrumentedFuncs  ,
"Number of instrumented funcs"   
)

◆ STATISTIC() [2/3]

STATISTIC ( NumNoProfileSummaryFuncs  ,
"Number of funcs without PS"   
)

◆ STATISTIC() [3/3]

STATISTIC ( NumTotalFuncs  ,
"Number of total funcs"   
)

◆ TypeSizeToSizeIndex()

static size_t TypeSizeToSizeIndex ( uint32_t  TypeSize)
static

Definition at line 949 of file HWAddressSanitizer.cpp.

References assert(), llvm::countr_zero(), and kNumberOfAccessSizes.

Variable Documentation

◆ ClEnableKhwasan

cl::opt< bool > ClEnableKhwasan("hwasan-kernel", cl::desc("Enable KernelHWAddressSanitizer instrumentation"), cl::Hidden, cl::init(false)) ( "hwasan-kernel"  ,
cl::desc("Enable KernelHWAddressSanitizer instrumentation")  ,
cl::Hidden  ,
cl::init(false)   
)
static

◆ ClFrameRecords

cl::opt< bool > ClFrameRecords("hwasan-with-frame-record", cl::desc("Use ring buffer for stack allocations"), cl::Hidden) ( "hwasan-with-frame-record"  ,
cl::desc("Use ring buffer for stack allocations")  ,
cl::Hidden   
)
static

◆ ClGenerateTagsWithCalls

cl::opt< bool > ClGenerateTagsWithCalls("hwasan-generate-tags-with-calls", cl::desc("generate new tags with runtime library calls"), cl::Hidden, cl::init(false)) ( "hwasan-generate-tags-with-calls"  ,
cl::desc("generate new tags with runtime library calls")  ,
cl::Hidden  ,
cl::init(false)   
)
static

◆ ClGlobals

cl::opt< bool > ClGlobals("hwasan-globals", cl::desc("Instrument globals"), cl::Hidden, cl::init(false)) ( "hwasan-globals"  ,
cl::desc("Instrument globals")  ,
cl::Hidden  ,
cl::init(false)   
)
static

◆ ClHotPercentileCutoff

cl::opt< int > ClHotPercentileCutoff("hwasan-percentile-cutoff-hot", cl::desc("Hot percentile cuttoff.")) ( "hwasan-percentile-cutoff-hot"  ,
cl::desc("Hot percentile cuttoff.")   
)
static

◆ ClInlineAllChecks

cl::opt< bool > ClInlineAllChecks("hwasan-inline-all-checks", cl::desc("inline all checks"), cl::Hidden, cl::init(false)) ( "hwasan-inline-all-checks"  ,
cl::desc("inline all checks")  ,
cl::Hidden  ,
cl::init(false)   
)
static

◆ ClInlineFastPathChecks

cl::opt< bool > ClInlineFastPathChecks("hwasan-inline-fast-path-checks", cl::desc("inline all checks"), cl::Hidden, cl::init(false)) ( "hwasan-inline-fast-path-checks"  ,
cl::desc("inline all checks")  ,
cl::Hidden  ,
cl::init(false)   
)
static

◆ ClInstrumentAtomics

cl::opt< bool > ClInstrumentAtomics("hwasan-instrument-atomics", cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden, cl::init(true)) ( "hwasan-instrument-atomics"  ,
cl::desc("instrument atomic instructions (rmw, cmpxchg)")  ,
cl::Hidden  ,
cl::init(true  
)
static

◆ ClInstrumentByval

cl::opt< bool > ClInstrumentByval("hwasan-instrument-byval", cl::desc("instrument byval arguments"), cl::Hidden, cl::init(true)) ( "hwasan-instrument-byval"  ,
cl::desc("instrument byval arguments")  ,
cl::Hidden  ,
cl::init(true  
)
static

◆ ClInstrumentLandingPads

cl::opt< bool > ClInstrumentLandingPads("hwasan-instrument-landing-pads", cl::desc("instrument landing pads"), cl::Hidden, cl::init(false)) ( "hwasan-instrument-landing-pads"  ,
cl::desc("instrument landing pads")  ,
cl::Hidden  ,
cl::init(false)   
)
static

◆ ClInstrumentMemIntrinsics

cl::opt< bool > ClInstrumentMemIntrinsics("hwasan-instrument-mem-intrinsics", cl::desc("instrument memory intrinsics"), cl::Hidden, cl::init(true)) ( "hwasan-instrument-mem-intrinsics"  ,
cl::desc("instrument memory intrinsics")  ,
cl::Hidden  ,
cl::init(true  
)
static

◆ ClInstrumentPersonalityFunctions

cl::opt< bool > ClInstrumentPersonalityFunctions("hwasan-instrument-personality-functions", cl::desc("instrument personality functions"), cl::Hidden) ( "hwasan-instrument-personality-functions"  ,
cl::desc("instrument personality functions")  ,
cl::Hidden   
)
static

◆ ClInstrumentReads

cl::opt< bool > ClInstrumentReads("hwasan-instrument-reads", cl::desc("instrument read instructions"), cl::Hidden, cl::init(true)) ( "hwasan-instrument-reads"  ,
cl::desc("instrument read instructions")  ,
cl::Hidden  ,
cl::init(true  
)
static

◆ ClInstrumentStack

cl::opt< bool > ClInstrumentStack("hwasan-instrument-stack", cl::desc("instrument stack (allocas)"), cl::Hidden, cl::init(true)) ( "hwasan-instrument-stack"  ,
cl::desc("instrument stack (allocas)")  ,
cl::Hidden  ,
cl::init(true  
)
static

◆ ClInstrumentWithCalls

cl::opt< bool > ClInstrumentWithCalls("hwasan-instrument-with-calls", cl::desc("instrument reads and writes with callbacks"), cl::Hidden, cl::init(false)) ( "hwasan-instrument-with-calls"  ,
cl::desc("instrument reads and writes with callbacks")  ,
cl::Hidden  ,
cl::init(false)   
)
static

◆ ClInstrumentWrites

cl::opt< bool > ClInstrumentWrites("hwasan-instrument-writes", cl::desc("instrument write instructions"), cl::Hidden, cl::init(true)) ( "hwasan-instrument-writes"  ,
cl::desc("instrument write instructions")  ,
cl::Hidden  ,
cl::init(true  
)
static

◆ ClKasanMemIntrinCallbackPrefix

cl::opt< bool > ClKasanMemIntrinCallbackPrefix("hwasan-kernel-mem-intrinsic-prefix", cl::desc("Use prefix for memory intrinsics in KASAN mode"), cl::Hidden, cl::init(false)) ( "hwasan-kernel-mem-intrinsic-prefix"  ,
cl::desc("Use prefix for memory intrinsics in KASAN mode")  ,
cl::Hidden  ,
cl::init(false)   
)
static

◆ ClMappingOffset

cl::opt< uint64_t > ClMappingOffset("hwasan-mapping-offset", cl::desc("HWASan shadow mapping offset [EXPERIMENTAL]"), cl::Hidden) ( "hwasan-mapping-offset"  ,
cl::desc("HWASan shadow mapping offset [EXPERIMENTAL]")  ,
cl::Hidden   
)
static

◆ ClMappingOffsetDynamic

cl::opt< OffsetKind > ClMappingOffsetDynamic("hwasan-mapping-offset-dynamic", cl::desc("HWASan shadow mapping dynamic offset location"), cl::Hidden, cl::values(clEnumValN(OffsetKind::kGlobal, "global", "Use global"), clEnumValN(OffsetKind::kIfunc, "ifunc", "Use ifunc global"), clEnumValN(OffsetKind::kTls, "tls", "Use TLS"))) ( "hwasan-mapping-offset-dynamic"  ,
cl::desc("HWASan shadow mapping dynamic offset location")  ,
cl::Hidden  ,
cl::values(clEnumValN(OffsetKind::kGlobal, "global", "Use global"), clEnumValN(OffsetKind::kIfunc, "ifunc", "Use ifunc global"), clEnumValN(OffsetKind::kTls, "tls", "Use TLS"))   
)
static

◆ ClMatchAllTag

cl::opt< int > ClMatchAllTag("hwasan-match-all-tag", cl::desc("don't report bad accesses via pointers with this tag"), cl::Hidden, cl::init(-1)) ( "hwasan-match-all-tag"  ,
cl::desc("don't report bad accesses via pointers with this tag")  ,
cl::Hidden  ,
cl::init(-1)   
)
static

◆ ClMaxLifetimes

cl::opt< size_t > ClMaxLifetimes("hwasan-max-lifetimes-for-alloca", cl::Hidden, cl::init(3), cl::ReallyHidden, cl::desc("How many lifetime ends to handle for a single alloca."), cl::Optional) ( "hwasan-max-lifetimes-for-alloca"  ,
cl::Hidden  ,
cl::init(3)  ,
cl::ReallyHidden  ,
cl::desc("How many lifetime ends to handle for a single alloca.")  ,
cl::Optional   
)
static

◆ ClMemoryAccessCallbackPrefix

cl::opt< std::string > ClMemoryAccessCallbackPrefix("hwasan-memory-access-callback-prefix", cl::desc("Prefix for memory access callbacks"), cl::Hidden, cl::init("__hwasan_")) ( "hwasan-memory-access-callback-prefix"  ,
cl::desc("Prefix for memory access callbacks")  ,
cl::Hidden  ,
cl::init("__hwasan_")   
)
static

◆ ClRandomSkipRate

cl::opt< float > ClRandomSkipRate("hwasan-random-rate", cl::desc("Probability value in the range [0.0, 1.0] " "to keep instrumentation of a function.")) ( "hwasan-random-rate"  ,
cl::desc("Probability value in the range [0.0, 1.0] " "to keep instrumentation of a function.")   
)
static

◆ ClRecordStackHistory

cl::opt< RecordStackHistoryMode > ClRecordStackHistory("hwasan-record-stack-history", cl::desc("Record stack frames with tagged allocations in a thread-local " "ring buffer"), cl::values(clEnumVal(none, "Do not record stack ring history"), clEnumVal(instr, "Insert instructions into the prologue for " "storing into the stack ring buffer directly"), clEnumVal(libcall, "Add a call to __hwasan_add_frame_record for " "storing into the stack ring buffer")), cl::Hidden, cl::init(instr)) ( "hwasan-record-stack-history"  ,
cl::desc("Record stack frames with tagged allocations in a thread-local " "ring buffer")  ,
cl::values(clEnumVal(none, "Do not record stack ring history"), clEnumVal(instr, "Insert instructions into the prologue for " "storing into the stack ring buffer directly"), clEnumVal(libcall, "Add a call to __hwasan_add_frame_record for " "storing into the stack ring buffer"))  ,
cl::Hidden  ,
cl::init(instr  
)
static

◆ ClRecover

cl::opt< bool > ClRecover("hwasan-recover", cl::desc("Enable recovery mode (continue-after-error)."), cl::Hidden, cl::init(false)) ( "hwasan-recover"  ,
cl::desc("Enable recovery mode (continue-after-error).")  ,
cl::Hidden  ,
cl::init(false)   
)
static

◆ ClUseAfterScope

cl::opt< bool > ClUseAfterScope("hwasan-use-after-scope", cl::desc("detect use after scope within function"), cl::Hidden, cl::init(true)) ( "hwasan-use-after-scope"  ,
cl::desc("detect use after scope within function")  ,
cl::Hidden  ,
cl::init(true  
)
static

◆ ClUsePageAliases

cl::opt< bool > ClUsePageAliases("hwasan-experimental-use-page-aliases", cl::desc("Use page aliasing in HWASan"), cl::Hidden, cl::init(false)) ( "hwasan-experimental-use-page-aliases"  ,
cl::desc("Use page aliasing in HWASan")  ,
cl::Hidden  ,
cl::init(false)   
)
static

◆ ClUseShortGranules

cl::opt< bool > ClUseShortGranules("hwasan-use-short-granules", cl::desc("use short granules in allocas and outlined checks"), cl::Hidden, cl::init(false)) ( "hwasan-use-short-granules"  ,
cl::desc("use short granules in allocas and outlined checks")  ,
cl::Hidden  ,
cl::init(false)   
)
static

◆ ClUseStackSafety

cl::opt< bool > ClUseStackSafety("hwasan-use-stack-safety", cl::Hidden, cl::init(true), cl::Hidden, cl::desc("Use Stack Safety analysis results"), cl::Optional) ( "hwasan-use-stack-safety"  ,
cl::Hidden  ,
cl::init(true ,
cl::Hidden  ,
cl::desc("Use Stack Safety analysis results")  ,
cl::Optional   
)
static

◆ kDefaultShadowScale

const size_t kDefaultShadowScale = 4
static

Definition at line 84 of file HWAddressSanitizer.cpp.

◆ kHwasanInitName

const char kHwasanInitName[] = "__hwasan_init"

Definition at line 75 of file HWAddressSanitizer.cpp.

◆ kHwasanModuleCtorName

const char kHwasanModuleCtorName[] = "hwasan.module_ctor"

Definition at line 73 of file HWAddressSanitizer.cpp.

◆ kHwasanNoteName

const char kHwasanNoteName[] = "hwasan.note"

Definition at line 74 of file HWAddressSanitizer.cpp.

◆ kHwasanPersonalityThunkName

const char kHwasanPersonalityThunkName[] = "__hwasan_personality_thunk"

Definition at line 76 of file HWAddressSanitizer.cpp.

◆ kHwasanShadowMemoryDynamicAddress

const char kHwasanShadowMemoryDynamicAddress[]
Initial value:
=
"__hwasan_shadow_memory_dynamic_address"

Definition at line 78 of file HWAddressSanitizer.cpp.

◆ kNumberOfAccessSizes

const size_t kNumberOfAccessSizes = 5
static

Definition at line 82 of file HWAddressSanitizer.cpp.

◆ kShadowBaseAlignment

const unsigned kShadowBaseAlignment = 32
static

Definition at line 86 of file HWAddressSanitizer.cpp.