The current implementation of -fsanitize=function places two words (the prolog
signature and the RTTI proxy) at the function entry, which makes the feature
incompatible with Intel Indirect Branch Tracking (IBT) that needs an ENDBR instruction
at the function entry. To allow the combination, move the two words before the
function entry, similar to -fsanitize=kcfi.
Armv8.5 Branch Target Identification (BTI) has a similar requirement.
Note: for IBT and BTI, whether a function gets a marker instruction at the entry
generally cannot be assumed (it can be disabled by a function attribute or
stronger LTO optimizations).
It is extremely unlikely for two words preceding a function entry to be
inaccessible. One way to achieve this is by ensuring that a function is
aligned at a page boundary and making the preceding page unmapped or
unreadable. This is not reasonable for application or library code.
(Think: the first text section has crt* code not instrumented by
-fsanitize=function.)
We use 0xc105cafe for all targets. .long 0xc105cafe disassembles to invalid
instructions on all architectures I have tested, except Power where it is
lfs 8, -13570(5) (Load Floating-Point with a weird offset, unlikely to be used in real code).
For the removed function in AsmPrinter.cpp, remove an assert: mdconst::extract
already asserts non-nullness.
For compiler-rt/test/ubsan/TestCases/TypeCheck/Function/function.cpp,
when the function doesn't have prolog/epilog (-O1 and above), after moving the two words,
the address of the function equals the address of ret instruction,
so symbolizing the function will additionally get a non-zero column number.
Adjust the test to allow an optional column number.
.long 3238382334 .long .L__llvm_rtti_proxy-_Z1fv _Z1fv: // symbolizing here retrieves the line table entry from the second .loc .file 0 ... .loc 0 1 0 .cfi_startproc .loc 0 2 1 prologue_end retq
Is it worth making this target specific? Defaulting to 0xc105cafe for all targets, if that gets allocated in the future on any one target we can change it without having to test against all other targets.
For example on AArch64 this is is in the decoding space of SME instructions op0 = 0b1 op1 = 0b0000. This may get allocated in the future. Although admittedly it is likely to be very rare to find a use of a SME instruction at the end of a function to cause it to get misidentified.
I suspect most targets have an explicit undefined instruction, such as UDF in AArch64 which is 0x0000???? where ? can be any value. On Arm there two separate 4-byte encodings for Arm, Thumb of UDF.