Functions can be added not just by the fronted and PAC/BTI attributes
should be added to those too. The new pass manages the attributes.
After this change the all runtime created functions like _clang_call_terminate
or constructor that is emitted by a sanitizer will be handled for PAC/BTI if applicable.
Details
Diff Detail
Event Timeline
Previous version of the patch handled only the functions that are created in clang. Sanitizers can't see the codegen options therefore they also disables BTI.
This version of the patch is less invasive in my opinion, effects only aarch64.
branch-target-enforcement(BTI) and sign-return-address(PAC) are added to all function that comes from clang frontend.
If the backend encounters with the function without BTI attribute but the module is compiled with BTI then it assumes it should be made BTI compatible.
That said, my comments are not of the "over my dead body" kind ;)
clang/lib/CodeGen/CGCall.cpp | ||
---|---|---|
1827 | I would really prefer to not set values "true" or "false" for the attribute: we don't really have tri-state logic there (absent/present-true/present-false), and those values just add some not-very useful string processing. | |
1830 | What do we get from setting the PACBTI state in the default function attributes? We still have | |
llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp | ||
200 | This should be "true", although the comment might turn out moot. If we somehow end up with a function, that does not have that attribute, we should clear the | |
201–202 | ... that kind of string processing, here and elsewhere. | |
llvm/lib/Target/AArch64/AArch64BranchTargets.cpp | ||
61–65 | Isn't there some redundancy with the two calls to getFnAttribute and to hasFnAttribute ? |
llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp | ||
---|---|---|
200 | Oh, I see, those are the cases of sanitizer functions, created at LLVM level, that don't have the attribute. |
Thanks for the comments, patch is improved
isStringAttribute() check removed, the attribute is always a string in this case or "null" so the check is not needed.
Function level the attribute is now only change when needed, so as the function level attribute is expected to be rare I hope the performance won't be impacted by the patch.
I kept the "tri-state" logic because of the emitted functions. Introducing a "branch-target-enforcement-disabled" attribute seems even more confusing for me.
clang/lib/CodeGen/CGCall.cpp | ||
---|---|---|
1827 | How about setting the attribute for LLVM created functions at the time of creation, just like Clang created functions | |
1830 | Sure, but that's duplication of code/logic, it's a source of countless issues "oh, here's the place I should fix that thing ... oh noes, turns out I have to fix ten more ... hope I've found all ..." ;) | |
llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp | ||
200 | Or, as mentioned in the other comment, check if it's possible to set the attribute at the time of creation (from module attributes?). Tri-state logic is added complexity, if it's necessary, it's necessary, but if it's not, better make it simpler. |
clang/lib/CodeGen/CGCall.cpp | ||
---|---|---|
1827 | Attributes are not always set in clang as I see: |
clang/lib/CodeGen/TargetInfo.cpp | ||
---|---|---|
5149–5152 | I'm going to rebase the patch. I add there a new attribute here "ignore-branch-target-enforcement" |
clang/lib/CodeGen/CGCall.cpp | ||
---|---|---|
1826–1827 | LangOptions has the following functions:
With these functions some of these lines can be significantly reduced. | |
1836 | Use getLangOpts(). isSignReturnAddressWithAKey() | |
clang/lib/CodeGen/CodeGenModule.cpp | ||
595 | Use new functions please. |
clang/lib/CodeGen/TargetInfo.cpp | ||
---|---|---|
5149–5152 | TBH, that's worse, IMHO. Ideally, I *think* we'd like *every* LLVM IR function that the backend sees, The module attributes are LLVM IR metadata, and AFAIK LLVM IR metadata is an optional extra, |
clang/lib/CodeGen/TargetInfo.cpp | ||
---|---|---|
5149–5152 | Which case are you trying to handle here? |
clang/lib/CodeGen/TargetInfo.cpp | ||
---|---|---|
5149–5152 | Chill: I think I have code that solve that for clang created functions, but functions created in llvm I don't have any idea. Tamas: yes, that is the case when module is compiled with bti but the function is not ( "none" or "pac-ret" and so on. ) |
Patch is refactored, the new pass smooth out the attribute issues.
This version fixes issues with _clang_call_terminate, sanitisers and the CFI.
New pass might need a new file, I'm not yet convinced myself.
This approach looks way too hackish to me with multiple opposing attributes ("sign-return-address" vs. "ignore-sign-return-address")
and some convoluted logic to resolve the contradiction.
Would it be better to add a new value to "sign-return-address" as "none"? I don't see any other alternative option, I'm open to any other idea.
FWIW GCC has a "sign-return-address" function attribute with a default value of "none". It is considered deprecated, however, in favour of "branch-protection"
FWIW GCC has a "sign-return-address" function attribute with a default value of "none". It is considered deprecated, however, in favour of "branch-protection"
This is just the internal representation, the function attribute in C/C++ source is the "branch-protection".
Old version of the patch used attribute value to represent the "ignore"/disabled state https://reviews.llvm.org/D75181?id=247201 so I have no idea what would be the right solution.
My original idea was to pass options to LLVM. I'll come up with a patch in a day or two (if it works) and then we'll see.
I would really prefer to not set values "true" or "false" for the attribute: we don't really have tri-state logic there (absent/present-true/present-false), and those values just add some not-very useful string processing.