The existing BTI placement pass avoids inserting "BTI c" when the
function has local linkage and is only directly called. However,
even in this case, there is a (small) chance that the linker later
adds a hunk with an indirect call to the function, e.g. if the
function is placed in a separate section and moved far away from
its callers. Make sure to add BTI for these functions too.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
@MaskRay sorry to pull you into this review - feel free to ignore if you're not interested.
I'm removing one of your tests for patchable-function-entry, since my proposed changes mean all functions will start with BTI c. Just to double-check: is there any other scenario that you wanted to check with the removed test, other than a function with BTI j in the branche targets but no BTI c at the start of the function? Thanks!
This looks reasonable to me, while the linker moving a local function far away from its callers in the same object file is unlikely, it is at least theoretically possible with linker scripts or a symbol ordering file. My guess is that this would only affect a small number of functions?
llvm/lib/Target/AArch64/AArch64BranchTargets.cpp | ||
---|---|---|
89 | A linker is not permitted to add a thunk for the R_AARCH64_CONDBR19 relocation (A conditional branch), it may be possible to exclude the conditional branch in the check. My guess is that it won't be worth it as calling a function with a conditional branch is not likely to be generated by the compiler. |
I know that for generalization, sometimes specific tests can be removed. -fpatchable-function-entry is a bit special though, it can place NOPs before and after the function label. This property is relied upon by the Linux kernel dynamic ftrace.
Since the NOP insertion is a bit strange, not clearly covered by other tests, and testing it does not increase test time (we don't add new llc commands so no process startup overhead), I'd like patchable-function-entry-bti.ll to be kept.
I got some numbers on the NDK samples (https://github.com/android/ndk-samples). Of a total of 6746 functions, this patch inserts a landing pad for 22 additional functions, which is ~0.3% of them. I haven't done proper benchmarking since this is a bugfix rather than an optimization, but I agree that this patch should affect a small number of functions.
Thanks for the figures, that looks like we avoid a potential problem without much impact on the generated code.
For patchable functions are there any other cases where we wouldn't generate a BTI at the start of the function? If there is we may be alter the test so that it is still checking that the nop is still inserted. If there is no way to avoid a BTI then we may have to alter the expected result and the comment.
I've dug up https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92424 and https://reviews.llvm.org/D72215 for context.
Reintroduced the removed fpatchable-function-entry test, but modified so that it expects a landing pad at the beginning of the function.
After the changes, it seems @f1i tests the same thing as @f1, although I guess in a bigger function?
For patchable functions are there any other cases where we wouldn't generate a BTI at the start of the function? If there is we may be alter the test so that it is still checking that the nop is still inserted. If there is no way to avoid a BTI then we may have to alter the expected result and the comment.
I've dug up https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92424 and https://reviews.llvm.org/D72215 for context.
Thanks for the context! I don't think there is a way to generate a function without an initial landing pad ATM. The BTI placement pass will add a landing pad at the beginning of any BB that is the start of a function.
From a quick look at that GCC bug report, I think we should be fine now: the landing pads are place at the right point. If, at some point, the behaviour of LLVM changes again, I've reinstated the test that I initially removed, and hopefully it will shout.
This LGTM, although please give a few days for MaskRay to check the patchable functions case.
Sure thing, thank you for the review. @MaskRay please let me know if you want to further discuss the changes to the patchable-function-entry test, otherwise I will commit this sometime next week.
LGTM.
llvm/test/CodeGen/AArch64/patchable-function-entry-bti.ll | ||
---|---|---|
50–51 | The comment needs update. It should say that we add BTI c even if the function has the internal linkage. |
A linker is not permitted to add a thunk for the R_AARCH64_CONDBR19 relocation (A conditional branch), it may be possible to exclude the conditional branch in the check. My guess is that it won't be worth it as calling a function with a conditional branch is not likely to be generated by the compiler.