This is an archive of the discontinued LLVM Phabricator instance.

[AArch64][v8.5A] Add BTI to all function starts
ClosedPublic

Authored by pbarrio on Mar 26 2021, 6:52 AM.

Details

Summary

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.

Diff Detail

Event Timeline

pbarrio created this revision.Mar 26 2021, 6:52 AM
pbarrio requested review of this revision.Mar 26 2021, 6:52 AM
Herald added a project: Restricted Project. · View Herald TranscriptMar 26 2021, 6:52 AM

@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.

MaskRay added a comment.EditedMar 26 2021, 1:48 PM

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.

My guess is that this would only affect a small number of functions?

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.

My guess is that this would only affect a small number of functions?

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.

pbarrio updated this revision to Diff 334224.EditedMar 30 2021, 10:44 AM

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.

peter.smith accepted this revision.Apr 7 2021, 3:02 AM

This LGTM, although please give a few days for MaskRay to check the patchable functions case.

This revision is now accepted and ready to land.Apr 7 2021, 3:02 AM
pbarrio added a comment.EditedApr 9 2021, 2:39 AM

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.

MaskRay accepted this revision.Apr 9 2021, 4:55 PM

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.

pirama added a subscriber: pirama.Apr 13 2021, 2:27 PM
This revision was automatically updated to reflect the committed changes.
pbarrio marked an inline comment as done.Apr 16 2021, 3:36 AM