Skip to content

[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

Merged
merged 1 commit into from
Jan 11, 2024

Conversation

eleanor-arm
Copy link
Contributor

@eleanor-arm eleanor-arm commented Jan 8, 2024

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.

@llvmbot
Copy link
Member

llvmbot commented Jan 8, 2024

@llvm/pr-subscribers-lld-elf

Author: Eleanor Bonnici (eleanor-arm)

Changes

Full diff: https://github.com/llvm/llvm-project/pull/77304.diff

1 Files Affected:

  • (modified) lld/ELF/Relocations.cpp (+1-1)
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);

@llvmbot
Copy link
Member

llvmbot commented Jan 8, 2024

@llvm/pr-subscribers-lld

Author: Eleanor Bonnici (eleanor-arm)

Changes

Full diff: https://github.com/llvm/llvm-project/pull/77304.diff

1 Files Affected:

  • (modified) lld/ELF/Relocations.cpp (+1-1)
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);

Copy link

github-actions bot commented Jan 8, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@eleanor-arm
Copy link
Contributor Author

The bolt test results are not affected by this change.

Copy link
Collaborator

@smithp35 smithp35 left a 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.

@@ -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) {
Copy link
Collaborator

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

@eleanor-arm eleanor-arm force-pushed the pic branch 2 times, most recently from 8a310b6 to 6d756b9 Compare January 9, 2024 23:40
@eleanor-arm
Copy link
Contributor Author

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.

@@ -0,0 +1,13 @@
// REQUIRES: arm
Copy link
Member

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

Copy link
Contributor Author

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

@MaskRay
Copy link
Member

MaskRay commented Jan 10, 2024

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.

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 [ELF] tag. Some use a more verbose [lld][ELF].

@eleanor-arm eleanor-arm changed the title Allow Arm PC-relative relocations in pic or shared library [lld][ELF] Allow Arm PC-relative relocations in pic or shared library Jan 10, 2024
Copy link
Collaborator

@smithp35 smithp35 left a 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.

Copy link
Collaborator

@smithp35 smithp35 left a 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.

@jrtc27
Copy link
Collaborator

jrtc27 commented Jan 10, 2024

What "BSD" problem is this? (Semi-interested if it's FreeBSD)

@smithp35
Copy link
Collaborator

smithp35 commented Jan 10, 2024

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 .global _C_LABEL(cachebailout)

I'm hoping that .global can be replaced with .hidden or .protected so cachebailout can be visible inside the program, but not preemptible.

@jrtc27
Copy link
Collaborator

jrtc27 commented Jan 10, 2024

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 .global _C_LABEL(cachebailout)

I'm hoping that .global can be replaced with .hidden or .protected so cachebailout can be visible inside the program, but not preemptible.

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)

@MaskRay
Copy link
Member

MaskRay commented Jan 10, 2024

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.

Thanks for the comment. Linux kernel uses -shared -Bsymbolic to make defined symbols non-preemptible. Perhaps FreeBSD kernel uses something similar. Then placing R_ARM_PCA into isRelExpr should create no risk.

@@ -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
Copy link
Member

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.

@MaskRay
Copy link
Member

MaskRay commented Jan 10, 2024

Allow Arm PC-relative relocations in pic or shared library

PIC links include both -pie and -shared.
-shared is for shared libraries.
So "pic or shared library" is redundant.

Perhaps Allow ... in PIC links.

@jrtc27
Copy link
Collaborator

jrtc27 commented Jan 10, 2024

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.

Thanks for the comment. Linux kernel uses -shared -Bsymbolic to make defined symbols non-preemptible. Perhaps FreeBSD kernel uses something similar. Then placing R_ARM_PCA into isRelExpr should create no risk.

No -shared, and it uses -Bdynamic.

@eleanor-arm eleanor-arm changed the title [lld][ELF] Allow Arm PC-relative relocations in pic or shared library [lld][ELF] Allow Arm PC-relative relocations in PIC links Jan 11, 2024
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.
justinfargnoli pushed a commit to justinfargnoli/llvm-project that referenced this pull request Jan 28, 2024
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants