-
Notifications
You must be signed in to change notification settings - Fork 15k
[PAC][ELF] Place AUTH constants in .data.rel.ro for position dependent code #150418
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 3 commits
a91b0ee
bf6186d
d85f8cf
1868cbe
cafc9df
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,6 +17,7 @@ | |
| #include "llvm/IR/DataLayout.h" | ||
| #include "llvm/IR/DerivedTypes.h" | ||
| #include "llvm/IR/Function.h" | ||
| #include "llvm/IR/GlobalValue.h" | ||
| #include "llvm/IR/GlobalVariable.h" | ||
| #include "llvm/IR/Mangler.h" | ||
| #include "llvm/IR/Module.h" | ||
|
|
@@ -226,6 +227,20 @@ void TargetLoweringObjectFile::emitPseudoProbeDescMetadata( | |
| } | ||
| } | ||
|
|
||
| static bool containsConstantPtrAuth(const Constant *C) { | ||
| if (isa<ConstantPtrAuth>(C)) | ||
| return true; | ||
|
|
||
| if (isa<BlockAddress>(C) || isa<GlobalValue>(C)) | ||
| return false; | ||
|
|
||
| for (const Value *Op : C->operands()) | ||
| if (containsConstantPtrAuth(cast<Constant>(Op))) | ||
| return true; | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| /// getKindForGlobal - This is a top-level target-independent classifier for | ||
| /// a global object. Given a global variable and information from the TM, this | ||
| /// function classifies the global in a target independent manner. This function | ||
|
|
@@ -333,9 +348,10 @@ SectionKind TargetLoweringObjectFile::getKindForGlobal(const GlobalObject *GO, | |
| // mergable section, because the linker doesn't take relocations into | ||
| // consideration when it tries to merge entries in the section. | ||
| Reloc::Model ReloModel = TM.getRelocationModel(); | ||
| if (ReloModel == Reloc::Static || ReloModel == Reloc::ROPI || | ||
| ReloModel == Reloc::RWPI || ReloModel == Reloc::ROPI_RWPI || | ||
| !C->needsDynamicRelocation()) | ||
| if ((ReloModel == Reloc::Static || ReloModel == Reloc::ROPI || | ||
| ReloModel == Reloc::RWPI || ReloModel == Reloc::ROPI_RWPI || | ||
| !C->needsDynamicRelocation()) && | ||
| !containsConstantPtrAuth(C)) | ||
| return SectionKind::getReadOnly(); | ||
|
Comment on lines
336
to
358
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [nit] Maybe it would be more readable to organize the checks along the lines // ...
} else {
// First of all, the dynamic linker always needs to fix PtrAuth relocations up.
if (containsPtrAuth(C))
return SectionKind::getReadOnlyWithRel();
// In static, ROPI and RWPI relocation models, the linker will resolve
// ...
if (ReloModel == ...)
return SectionKind::getReadOnly();
// Otherwise, the dynamic linker needs to fix it up, put it in the
// writable data.rel section.
return SectionKind::getReadOnlyWithRel();There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've always found it a bit confusing that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
@atrosinenko Applied your suggestion in cafc9df, thanks! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
@pcc While I like the idea of simplifying things and making naming less confusing, I'm not sure if such a change would make logic for all the users of We might think of such an improvement, but I guess this is out of scope of this PR and it's better not to combine actual bug fixes and refactoring. Can we postpone applying your suggestion? And could you please tell if there is any other feedback on this PR or this can be merged? Thanks! |
||
|
|
||
| // Otherwise, the dynamic linker needs to fix it up, put it in the | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| ; RUN: llc -mtriple aarch64-elf --relocation-model=static -mattr=+pauth < %s | FileCheck %s | ||
| ; RUN: llc -mtriple aarch64-elf --relocation-model=dynamic-no-pic -mattr=+pauth < %s | FileCheck %s | ||
|
|
||
| ;; A constant value, use .rodata | ||
| ; CHECK: .section .rodata,"a",@progbits | ||
| ; CHECK: .globl Const | ||
| ; CHECK: Const: | ||
| ; CHECK: .xword 37 | ||
|
|
||
| ;; An AUTH reloc is needed, use .data.rel.ro | ||
| ; CHECK: .section .data.rel.ro,"aw",@progbits | ||
| ; CHECK: .globl PtrAuthExtern | ||
| ; CHECK: PtrAuthExtern: | ||
| ; CHECK: .xword ConstExtern@AUTH(da,0) | ||
|
|
||
| ; CHECK: .globl PtrAuth | ||
| ; CHECK: PtrAuth: | ||
| ; CHECK: .xword Const@AUTH(da,0) | ||
|
|
||
| ; CHECK: .globl PtrAuthExternNested1 | ||
| ; CHECK: PtrAuthExternNested1: | ||
| ; CHECK: .xword ConstExtern@AUTH(da,0) | ||
|
|
||
| ;; The address could be filled statically, use .rodata | ||
| ; CHECK: .section .rodata,"a",@progbits | ||
| ; CHECK: .globl PtrAuthExternNested2 | ||
| ; CHECK: PtrAuthExternNested2: | ||
| ; CHECK: .xword PtrAuthExtern | ||
|
|
||
| ;; An AUTH reloc is needed, use .data.rel.ro | ||
| ; CHECK: .section .data.rel.ro,"aw",@progbits | ||
| ; CHECK: .globl PtrAuthNested1 | ||
| ; CHECK: PtrAuthNested1: | ||
| ; CHECK: .xword Const@AUTH(da,0) | ||
|
|
||
| ;; The address could be filled statically, use .rodata | ||
| ; CHECK: .section .rodata,"a",@progbits | ||
| ; CHECK: .globl PtrAuthNested2 | ||
| ; CHECK: PtrAuthNested2: | ||
| ; CHECK: .xword PtrAuth | ||
|
|
||
| @ConstExtern = external global i64 | ||
| @Const = constant i64 37 | ||
|
|
||
| @PtrAuthExtern = constant ptr ptrauth (ptr @ConstExtern, i32 2) | ||
| @PtrAuth = constant ptr ptrauth (ptr @Const, i32 2) | ||
|
|
||
| @PtrAuthExternNested1 = constant { ptr } { ptr ptrauth (ptr @ConstExtern, i32 2) } | ||
| @PtrAuthExternNested2 = constant { ptr } { ptr @PtrAuthExtern } | ||
| @PtrAuthNested1 = constant { ptr } { ptr ptrauth (ptr @Const, i32 2) } | ||
| @PtrAuthNested2 = constant { ptr } { ptr @PtrAuth } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIUC this would make
containsConstantPtrAuthreturn false for global variable like thiswhich is still "constant" (as a constant pointer to
global_var). This doesn't seem to hurt in case of this PR, but possibly a bit unexpected w.r.t. function name vs. its behavior.Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the other hand, I would expect
containsConstantPtrAuthto return false for@ptr_to_global_var = constant ptr @global_varno matter how@global_valueis defined - I guess recursively inspectingGlobalValues would makecontainsConstantPtrAuthincorrectly returntruein such cases. Thus, the original "issue" should be considered as a matter of comments or naming, if at all.