Skip to content

lld/AArch64: handle more relocation addends #87328

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 3 commits into from
Apr 11, 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
42 changes: 35 additions & 7 deletions lld/ELF/Arch/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,13 @@ struct AArch64Relaxer {
};
} // namespace

// Return the bits [Start, End] from Val shifted Start bits.
// For instance, getBits(0xF0, 4, 8) returns 0xF.
static uint64_t getBits(uint64_t val, int start, int end) {
uint64_t mask = ((uint64_t)1 << (end + 1 - start)) - 1;
return (val >> start) & mask;
}

AArch64::AArch64() {
copyRel = R_AARCH64_COPY;
relativeRel = R_AARCH64_RELATIVE;
Expand Down Expand Up @@ -219,6 +226,10 @@ int64_t AArch64::getImplicitAddend(const uint8_t *buf, RelType type) const {
case R_AARCH64_GLOB_DAT:
case R_AARCH64_JUMP_SLOT:
return 0;
case R_AARCH64_ABS16:
case R_AARCH64_PREL16:
return SignExtend64<16>(read16(buf));
case R_AARCH64_ABS32:
case R_AARCH64_PREL32:
return SignExtend64<32>(read32(buf));
case R_AARCH64_ABS64:
Expand All @@ -227,6 +238,30 @@ int64_t AArch64::getImplicitAddend(const uint8_t *buf, RelType type) const {
case R_AARCH64_IRELATIVE:
case R_AARCH64_TLS_TPREL64:
return read64(buf);
case R_AARCH64_MOVW_UABS_G0:
case R_AARCH64_MOVW_UABS_G0_NC:
return getBits(SignExtend64<16>(read16(buf)), 0, 15);
case R_AARCH64_MOVW_UABS_G1:
case R_AARCH64_MOVW_UABS_G1_NC:
return getBits(SignExtend64<32>(read32(buf)), 16, 31);
case R_AARCH64_MOVW_UABS_G2:
case R_AARCH64_MOVW_UABS_G2_NC:
return getBits(read64(buf), 32, 47);
case R_AARCH64_MOVW_UABS_G3:
return getBits(read64(buf), 48, 63);
case R_AARCH64_TSTBR14:
return getBits(SignExtend64<32>(read32(buf)), 2, 15);
case R_AARCH64_CONDBR19:
case R_AARCH64_LD_PREL_LO19:
return getBits(SignExtend64<32>(read32(buf)), 2, 20);
case R_AARCH64_ADD_ABS_LO12_NC:
return getBits(SignExtend64<16>(read16(buf)), 0, 11);
case R_AARCH64_ADR_PREL_PG_HI21:
case R_AARCH64_ADR_PREL_PG_HI21_NC:
return getBits(SignExtend64<32>(read32(buf)), 12, 32);
case R_AARCH64_JUMP26:
case R_AARCH64_CALL26:
return getBits(SignExtend64<32>(read32(buf)), 2, 27);
default:
internalLinkerError(getErrorLocation(buf),
"cannot read addend for relocation " + toString(type));
Expand Down Expand Up @@ -330,13 +365,6 @@ static void write32AArch64Addr(uint8_t *l, uint64_t imm) {
write32le(l, (read32le(l) & ~mask) | immLo | immHi);
}

// Return the bits [Start, End] from Val shifted Start bits.
// For instance, getBits(0xF0, 4, 8) returns 0xF.
static uint64_t getBits(uint64_t val, int start, int end) {
uint64_t mask = ((uint64_t)1 << (end + 1 - start)) - 1;
return (val >> start) & mask;
}

static void or32le(uint8_t *p, int32_t v) { write32le(p, read32le(p) | v); }

// Update the immediate field in a AARCH64 ldr, str, and add instruction.
Expand Down
15 changes: 13 additions & 2 deletions lld/test/ELF/aarch64-reloc-implicit-addend.test
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
## Test certain REL relocation types generated by legacy armasm.
# RUN: yaml2obj %s -o %t.o
# RUN: not ld.lld %t.o -o /dev/null 2>&1 | FileCheck %s
# RUN: ld.lld %t.o -o %t
# RUN: llvm-objdump -s %t | FileCheck %s

# CHECK-COUNT-17: internal linker error: cannot read addend
# CHECK: Contents of section .abs:
# CHECK-NEXT: [[#%x,]] 29002800 00002700 00000000 0000fcff ).(...'.........
# CHECK-NEXT: [[#%x,]] ffffffff ffff ......
# CHECK-NEXT: Contents of section .uabs:
# CHECK-NEXT: [[#%x,]] 40ffffff 40ffffff 20ffffff 20ffffff @...@... ... ...
# CHECK-NEXT: [[#%x,]] 00ffffff 00ffffff ........
# CHECK-NEXT: Contents of section .prel:
# CHECK-NEXT: [[#%x,]] 00ffffff fcfeffff f8feffff a0ffffff ................
# CHECK-NEXT: [[#%x,]] 0010009f 0010009f ........
# CHECK-NEXT: Contents of section .branch:
# CHECK-NEXT: [[#%x,]] f0ffffff f0ffffff fdffffff fcffff14 ................

---
!ELF
Expand Down