Change -fsanitize=function to place two words before the function entry
authorFangrui Song <i@maskray.me>
Fri, 19 May 2023 14:50:29 +0000 (07:50 -0700)
committerFangrui Song <i@maskray.me>
Fri, 19 May 2023 14:50:29 +0000 (07:50 -0700)
commitad31a2dcadfcd57a99bbd6d0050d2690fd84a883
treebc1d7991175e845c11f37e4aa26b8e85c8d25211
parentd933c895348b79a28cdb9e330e0ee5146bac5adf
Change -fsanitize=function to place two words before the function entry

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
```

Reviewed By: peter.smith

Differential Revision: https://reviews.llvm.org/D148665
clang/lib/CodeGen/CGExpr.cpp
clang/lib/CodeGen/TargetInfo.cpp
clang/lib/CodeGen/TargetInfo.h
clang/test/CodeGen/ubsan-function.cpp
clang/test/CodeGenCXX/catch-undef-behavior.cpp
clang/test/CodeGenCXX/ubsan-function-noexcept.cpp
compiler-rt/test/ubsan/TestCases/TypeCheck/Function/function.cpp
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
llvm/test/CodeGen/X86/func-sanitizer.ll
llvm/test/CodeGen/X86/patchable-function-entry-ibt.ll