-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[lld][ELF] Allow Arm PC-relative relocations in PIC links #77304
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
Conversation
@llvm/pr-subscribers-lld-elf Author: Eleanor Bonnici (eleanor-arm) ChangesFull diff: https://github.com/llvm/llvm-project/pull/77304.diff 1 Files Affected:
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index 210b4d1eb1a7a6..6a7976f41320f1 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -210,7 +210,7 @@ bool lld::elf::needsGot(RelExpr expr) {
// True if this expression is of the form Sym - X, where X is a position in the
// file (PC, or GOT for example).
static bool isRelExpr(RelExpr expr) {
- return oneof<R_PC, R_GOTREL, R_GOTPLTREL, R_MIPS_GOTREL, R_PPC64_CALL,
+ return oneof<R_PC, R_GOTREL, R_GOTPLTREL, R_ARM_PCA, R_MIPS_GOTREL, R_PPC64_CALL,
R_PPC64_RELAX_TOC, R_AARCH64_PAGE_PC, R_RELAX_GOT_PC,
R_RISCV_PC_INDIRECT, R_PPC64_RELAX_GOT_PC, R_LOONGARCH_PAGE_PC>(
expr);
|
@llvm/pr-subscribers-lld Author: Eleanor Bonnici (eleanor-arm) ChangesFull diff: https://github.com/llvm/llvm-project/pull/77304.diff 1 Files Affected:
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index 210b4d1eb1a7a6..6a7976f41320f1 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -210,7 +210,7 @@ bool lld::elf::needsGot(RelExpr expr) {
// True if this expression is of the form Sym - X, where X is a position in the
// file (PC, or GOT for example).
static bool isRelExpr(RelExpr expr) {
- return oneof<R_PC, R_GOTREL, R_GOTPLTREL, R_MIPS_GOTREL, R_PPC64_CALL,
+ return oneof<R_PC, R_GOTREL, R_GOTPLTREL, R_ARM_PCA, R_MIPS_GOTREL, R_PPC64_CALL,
R_PPC64_RELAX_TOC, R_AARCH64_PAGE_PC, R_RELAX_GOT_PC,
R_RISCV_PC_INDIRECT, R_PPC64_RELAX_GOT_PC, R_LOONGARCH_PAGE_PC>(
expr);
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
The bolt test results are not affected by this change. |
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.
The addition of R_PC_A looks good to me.
Please could you add a test?
The tests are in lld/test/ELF . All the arm ones are prefixed with arm-
and must start with REQUIRES ARM (so that they are skipped if the ARM backend isn't present).
A suitable test that fails currently:
.text
.type _start, %function
.global _start
.arm
_start: adr r0, .Ldest
bx lr
.section .text.1, "ax", %progbits
.Ldest: .word 10
using:
llvm-mc --triple=armv7-a adr.s -filetype=obj -o adr.o
ld.lld adr.o --shared -o adr.so
ld.lld: error: relocation R_ARM_ALU_PC_G0 cannot be used against symbol '.Ldest'; recompile with -fPIC
>>> defined in adr.o
>>> referenced by adr.o:(.text+0x0)
After your change that error should disappear.
Please can you add a description for the commit message too. Something like.
The relocations that map to R_ARM_PCA are equivalent to R_PC they are PC-relative and safe to use in shared-libraries, but have a different relocation code as they are evaluated
differently. Now that LLVM may generate these relocations in object files they may occur in shared-libries or position-independent executables.
lld/ELF/Relocations.cpp
Outdated
@@ -504,8 +504,7 @@ int64_t RelocationScanner::computeMipsAddend(const RelTy &rel, RelExpr expr, | |||
} | |||
|
|||
// Custom error message if Sym is defined in a discarded section. | |||
template <class ELFT> | |||
static std::string maybeReportDiscarded(Undefined &sym) { | |||
template <class ELFT> static std::string maybeReportDiscarded(Undefined &sym) { |
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.
Looks like some clang-format changes to unchanged code have made it into the patch. If these are still worth doing can you split these up into a separate [NFC] change mentioning clang-format
8a310b6
to
6d756b9
Compare
Apologies for the force push, it would have been better to do a fixup but the original version is still visible here on the main page. |
lld/test/ELF/arm-adr-pic.s
Outdated
@@ -0,0 +1,13 @@ | |||
// REQUIRES: arm |
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.
Instead of a new file, you can reuse an existing file. You can add a -shared
RUN line to arm-adr.s
with a comment stating that `/// R_ARM_ALU_PC_G0 referencing a non-preemptible symbol can be used in PIC links.'
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.
Thanks, that's a good idea -> DONE
Some people don't prefer force pushes but it's not a problem for me :) For shorter patches perhaps it matter even less. The lld/ELF patches usually have a |
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.
Thanks for the updates. LGTM. Will be worth leaving some time to see if MaskRay has any additional comments.
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.
Mentioning this here in case this does not fix the BSD problem. LLD will still give an error message if the relocation is to a pre-emptible symbol (.global in a --shared link). Strictly speaking this is correct as the global can be preempted and the R_ARM_PCA won't generate a dynamic relocation, which could lead to problems if the symbol is preempted.
I'm hoping that if this is the case the BSD case can use hidden visibility for the symbol, which will make it non-pre-emptible.
Adding R_ARM_PCA to the expressions that always calculate static link time constants in https://github.com/llvm/llvm-project/blob/main/lld/ELF/Relocations.cpp#L972 would permit its use to globals in shared libraries, but would be at risk of bugs if the symbol were pre-empted.
What "BSD" problem is this? (Semi-interested if it's FreeBSD) |
Looks like it is FreeBSD. It was a report that the change to make ADR emit a relocation had broken a BSD program #73834 (comment) (link refers to https://reviews.freebsd.org/D2035) I think the problem will still occur (if this code can be put in a shared object) as the adr target is I'm hoping that .global can be replaced with |
That's code in the kernel, so not preemptible, though if the code is still wrong for other reasons it's not a problem to fix it to support newer toolchains, there's normally some amount of that across the tree on each LLVM bump. (And to answer a question I see in there: FreeBSD uses its vendored Clang+LLD by default, but can be configured to use an external toolchain, whether LLVM, GNU or, in theory (but not really tested) a mix) |
Thanks for the comment. Linux kernel uses |
lld/test/ELF/arm-adr.s
Outdated
@@ -1,6 +1,8 @@ | |||
// REQUIRES: arm | |||
// RUN: llvm-mc --triple=armv7a-none-eabi --arm-add-build-attributes -filetype=obj -o %t.o %s | |||
// RUN: ld.lld %t.o -o %t | |||
/// R_ARM_ALU_PC_G0 referencing a non-preemptible symbol can be used in PIC links. | |||
// RUN: ld.lld %t.o --shared -o %t.so |
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.
If we don't use the output, the convention is /dev/null
.
Sometimes inspecting the output is useful (https://maskray.me/blog/2021-08-08-toolchain-testing#the-test-checks-too-little), but this simple change may not be worth the trouble.
PIC links include both Perhaps |
No -shared, and it uses -Bdynamic. |
The relocations that map to R_ARM_PCA are equivalent to R_PC. They are PC-relative and safe to use in shared libraries, but have a different relocation code as they are evaluated differently. Now that LLVM may generate these relocations in object files, they may occur in shared libraries or position-independent executables.
The relocations that map to R_ARM_PCA are equivalent to R_PC. They are PC-relative and safe to use in shared libraries, but have a different relocation code as they are evaluated differently. Now that LLVM may generate these relocations in object files, they may occur in shared libraries or position-independent executables.
The relocations that map to R_ARM_PCA are equivalent to R_PC. They are
PC-relative and safe to use in shared libraries, but have a different
relocation code as they are evaluated differently. Now that LLVM may
generate these relocations in object files, they may occur in
shared libraries or position-independent executables.