Skip to content

[lld][ARM] Fix assertion when mixing ARM and Thumb objects #101985

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 4 commits into from
Aug 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 14 additions & 7 deletions lld/ELF/Arch/ARM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,10 +228,16 @@ static void writePltHeaderLong(uint8_t *buf) {
write32(buf + 16, gotPlt - l1 - 8);
}

// True if we should use Thumb PLTs, which currently require Thumb2, and are
// only used if the target does not have the ARM ISA.
static bool useThumbPLTs() {
return config->armHasThumb2ISA && !config->armHasArmISA;
}

// The default PLT header requires the .got.plt to be within 128 Mb of the
// .plt in the positive direction.
void ARM::writePltHeader(uint8_t *buf) const {
if (config->armThumbPLTs) {
if (useThumbPLTs()) {
// The instruction sequence for thumb:
//
// 0: b500 push {lr}
Expand Down Expand Up @@ -289,7 +295,7 @@ void ARM::writePltHeader(uint8_t *buf) const {
}

void ARM::addPltHeaderSymbols(InputSection &isec) const {
if (config->armThumbPLTs) {
if (useThumbPLTs()) {
addSyntheticLocal("$t", STT_NOTYPE, 0, 0, isec);
addSyntheticLocal("$d", STT_NOTYPE, 12, 0, isec);
} else {
Expand All @@ -315,7 +321,7 @@ static void writePltLong(uint8_t *buf, uint64_t gotPltEntryAddr,
void ARM::writePlt(uint8_t *buf, const Symbol &sym,
uint64_t pltEntryAddr) const {

if (!config->armThumbPLTs) {
if (!useThumbPLTs()) {
uint64_t offset = sym.getGotPltVA() - pltEntryAddr - 8;

// The PLT entry is similar to the example given in Appendix A of ELF for
Expand Down Expand Up @@ -367,7 +373,7 @@ void ARM::writePlt(uint8_t *buf, const Symbol &sym,
}

void ARM::addPltSymbols(InputSection &isec, uint64_t off) const {
if (config->armThumbPLTs) {
if (useThumbPLTs()) {
addSyntheticLocal("$t", STT_NOTYPE, off, 0, isec);
} else {
addSyntheticLocal("$a", STT_NOTYPE, off, 0, isec);
Expand All @@ -393,7 +399,7 @@ bool ARM::needsThunk(RelExpr expr, RelType type, const InputFile *file,
case R_ARM_JUMP24:
// Source is ARM, all PLT entries are ARM so no interworking required.
// Otherwise we need to interwork if STT_FUNC Symbol has bit 0 set (Thumb).
assert(!config->armThumbPLTs &&
assert(!useThumbPLTs() &&
"If the source is ARM, we should not need Thumb PLTs");
if (s.isFunc() && expr == R_PC && (s.getVA() & 1))
return true;
Expand All @@ -407,7 +413,8 @@ bool ARM::needsThunk(RelExpr expr, RelType type, const InputFile *file,
case R_ARM_THM_JUMP24:
// Source is Thumb, when all PLT entries are ARM interworking is required.
// Otherwise we need to interwork if STT_FUNC Symbol has bit 0 clear (ARM).
if ((expr == R_PLT_PC && !config->armThumbPLTs) || (s.isFunc() && (s.getVA() & 1) == 0))
if ((expr == R_PLT_PC && !useThumbPLTs()) ||
(s.isFunc() && (s.getVA() & 1) == 0))
return true;
[[fallthrough]];
case R_ARM_THM_CALL: {
Expand Down Expand Up @@ -675,7 +682,7 @@ void ARM::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
// PLT entries are always ARM state so we know we need to interwork.
assert(rel.sym); // R_ARM_THM_CALL is always reached via relocate().
bool bit0Thumb = val & 1;
bool useThumb = bit0Thumb || config->armThumbPLTs;
bool useThumb = bit0Thumb || useThumbPLTs();
bool isBlx = (read16(loc + 2) & 0x1000) == 0;
// lld 10.0 and before always used bit0Thumb when deciding to write a BLX
// even when type not STT_FUNC.
Expand Down
3 changes: 2 additions & 1 deletion lld/ELF/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,8 @@ struct Config {
bool allowMultipleDefinition;
bool fatLTOObjects;
bool androidPackDynRelocs = false;
bool armThumbPLTs = false;
bool armHasArmISA = false;
bool armHasThumb2ISA = false;
bool armHasBlx = false;
bool armHasMovtMovw = false;
bool armJ1J2BranchEncoding = false;
Expand Down
6 changes: 2 additions & 4 deletions lld/ELF/InputFiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,10 +200,8 @@ static void updateSupportedARMFeatures(const ARMAttributeParser &attributes) {
attributes.getAttributeValue(ARMBuildAttrs::ARM_ISA_use);
std::optional<unsigned> thumb =
attributes.getAttributeValue(ARMBuildAttrs::THUMB_ISA_use);
bool noArmISA = !armISA || *armISA == ARMBuildAttrs::Not_Allowed;
bool hasThumb2 = thumb && *thumb >= ARMBuildAttrs::AllowThumb32;
if (noArmISA && hasThumb2)
config->armThumbPLTs = true;
config->armHasArmISA |= armISA && *armISA >= ARMBuildAttrs::Allowed;
config->armHasThumb2ISA |= thumb && *thumb >= ARMBuildAttrs::AllowThumb32;
}

InputFile::InputFile(Kind k, MemoryBufferRef m)
Expand Down
44 changes: 44 additions & 0 deletions lld/test/ELF/arm-mixed-plts.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# REQUIRES: arm

# RUN: rm -rf %t && split-file %s %t
# RUN: llvm-mc -filetype=obj -arm-add-build-attributes -triple=armv7a-none-linux-gnueabi %t/a.s -o %t1.o
# RUN: llvm-mc -filetype=obj -arm-add-build-attributes -triple=armv7a-none-linux-gnueabi %t/b.s -o %t2.o
# RUN: ld.lld -shared %t1.o %t2.o -o %t.so
# RUN: llvm-objdump -d %t.so | FileCheck %s

## Check that, when the input is a mixture of objects which can and cannot use
## the ARM ISA, we use the default ARM PLT sequences.

# CHECK: <.plt>:
# CHECK-NEXT: e52de004 str lr, [sp, #-0x4]!
# CHECK-NEXT: e28fe600 add lr, pc, #0, #12
# CHECK-NEXT: e28eea20 add lr, lr, #32, #20
# CHECK-NEXT: e5bef084 ldr pc, [lr, #0x84]!
# CHECK-NEXT: d4 d4 d4 d4 .word 0xd4d4d4d4
# CHECK-NEXT: d4 d4 d4 d4 .word 0xd4d4d4d4
# CHECK-NEXT: d4 d4 d4 d4 .word 0xd4d4d4d4
# CHECK-NEXT: d4 d4 d4 d4 .word 0xd4d4d4d4
# CHECK-NEXT: e28fc600 add r12, pc, #0, #12
# CHECK-NEXT: e28cca20 add r12, r12, #32, #20
# CHECK-NEXT: e5bcf06c ldr pc, [r12, #0x6c]!
# CHECK-NEXT: d4 d4 d4 d4 .word 0xd4d4d4d4

#--- a.s
.globl foo
.type foo, %function
.globl bar
.type bar, %function

.thumb
foo:
bl bar
bx lr

#--- b.s
.eabi_attribute Tag_ARM_ISA_use, 0

.arm
.globl bar
.type bar, %function
bar:
bx lr
Loading