Skip to content

Commit daf2085

Browse files
authored
[lld][AArch64] Fix getImplicitAddend in big-endian mode. (#107845)
In AArch64, the endianness of instruction encodings is always little, whereas the endianness of data swaps between LE and BE modes. So getImplicitAddend must use the right one of read32() and read32le(), for data and code respectively. It was using read32() throughout, causing instructions to be read as big-endian in BE mode, getting the wrong addend. Fixed, and updated the existing test to check both endiannesses. The expected results for data must be byte-swapped, but the ones for code need no adjustment.
1 parent 4687017 commit daf2085

File tree

2 files changed

+25
-12
lines changed

2 files changed

+25
-12
lines changed

lld/ELF/Arch/AArch64.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -268,13 +268,13 @@ int64_t AArch64::getImplicitAddend(const uint8_t *buf, RelType type) const {
268268
case R_AARCH64_MOVW_UABS_G2:
269269
case R_AARCH64_MOVW_UABS_G2_NC:
270270
case R_AARCH64_MOVW_UABS_G3:
271-
return SignExtend64<16>(getBits(read32(buf), 5, 20));
271+
return SignExtend64<16>(getBits(read32le(buf), 5, 20));
272272

273273
// R_AARCH64_TSTBR14 points at a TBZ or TBNZ instruction, which
274274
// has a 14-bit offset measured in instructions, i.e. shifted left
275275
// by 2.
276276
case R_AARCH64_TSTBR14:
277-
return SignExtend64<16>(getBits(read32(buf), 5, 18) << 2);
277+
return SignExtend64<16>(getBits(read32le(buf), 5, 18) << 2);
278278

279279
// R_AARCH64_CONDBR19 operates on the ordinary B.cond instruction,
280280
// which has a 19-bit offset measured in instructions.
@@ -285,13 +285,13 @@ int64_t AArch64::getImplicitAddend(const uint8_t *buf, RelType type) const {
285285
// R_AARCH64_CONDBR19.
286286
case R_AARCH64_CONDBR19:
287287
case R_AARCH64_LD_PREL_LO19:
288-
return SignExtend64<21>(getBits(read32(buf), 5, 23) << 2);
288+
return SignExtend64<21>(getBits(read32le(buf), 5, 23) << 2);
289289

290290
// R_AARCH64_ADD_ABS_LO12_NC operates on ADD (immediate). The
291291
// immediate can optionally be shifted left by 12 bits, but this
292292
// relocation is intended for the case where it is not.
293293
case R_AARCH64_ADD_ABS_LO12_NC:
294-
return SignExtend64<12>(getBits(read32(buf), 10, 21));
294+
return SignExtend64<12>(getBits(read32le(buf), 10, 21));
295295

296296
// R_AARCH64_ADR_PREL_LO21 operates on an ADR instruction, whose
297297
// 21-bit immediate is split between two bits high up in the word
@@ -305,14 +305,14 @@ int64_t AArch64::getImplicitAddend(const uint8_t *buf, RelType type) const {
305305
case R_AARCH64_ADR_PREL_LO21:
306306
case R_AARCH64_ADR_PREL_PG_HI21:
307307
case R_AARCH64_ADR_PREL_PG_HI21_NC:
308-
return SignExtend64<21>((getBits(read32(buf), 5, 23) << 2) |
309-
getBits(read32(buf), 29, 30));
308+
return SignExtend64<21>((getBits(read32le(buf), 5, 23) << 2) |
309+
getBits(read32le(buf), 29, 30));
310310

311311
// R_AARCH64_{JUMP,CALL}26 operate on B and BL, which have a
312312
// 26-bit offset measured in instructions.
313313
case R_AARCH64_JUMP26:
314314
case R_AARCH64_CALL26:
315-
return SignExtend64<28>(getBits(read32(buf), 0, 25) << 2);
315+
return SignExtend64<28>(getBits(read32le(buf), 0, 25) << 2);
316316

317317
default:
318318
internalLinkerError(getErrorLocation(buf),

lld/test/ELF/aarch64-reloc-implicit-addend.test

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,25 @@ REQUIRES: aarch64
1111
## .reloc directives containing no addend, this succeeds.
1212

1313
# RUN: rm -rf %t && split-file %s %t && cd %t
14+
1415
# RUN: llvm-mc -filetype=obj -triple=aarch64 relocs.s -o rela.o
1516
# RUN: obj2yaml rela.o -o rela.yaml
1617
# RUN: sed "s/\.rela/\.rel/;s/SHT_RELA/SHT_REL/" rela.yaml > rel.yaml
1718
# RUN: yaml2obj rel.yaml -o rel.o
1819
# RUN: llvm-mc -filetype=obj -triple=aarch64 symbols.s -o symbols.o
1920
# RUN: ld.lld rel.o symbols.o -o a.out --section-start=.data=0x100000 --section-start=.text=0x200000
20-
# RUN: llvm-objdump -s a.out | FileCheck %s --check-prefix=DATA
21+
# RUN: llvm-objdump -s a.out | FileCheck %s --check-prefix=DATALE
2122
# RUN: llvm-objdump -d a.out | FileCheck %s --check-prefix=CODE
2223

24+
# RUN: llvm-mc -filetype=obj -triple=aarch64_be relocs.s -o rela_be.o
25+
# RUN: obj2yaml rela_be.o -o rela_be.yaml
26+
# RUN: sed "s/\.rela/\.rel/;s/SHT_RELA/SHT_REL/" rela_be.yaml > rel_be.yaml
27+
# RUN: yaml2obj rel_be.yaml -o rel_be.o
28+
# RUN: llvm-mc -filetype=obj -triple=aarch64_be symbols.s -o symbols_be.o
29+
# RUN: ld.lld -EB rel_be.o symbols_be.o -o be.out --section-start=.data=0x100000 --section-start=.text=0x200000
30+
# RUN: llvm-objdump -s be.out | FileCheck %s --check-prefix=DATABE
31+
# RUN: llvm-objdump -d be.out | FileCheck %s --check-prefix=CODE
32+
2333
#--- symbols.s
2434

2535
// Source file containing the values of target symbols for the relocations. If
@@ -53,7 +63,8 @@ REQUIRES: aarch64
5363
// Source file containing the test instructions and their relocations, with the
5464
// FileCheck comments interleaved.
5565

56-
// DATA: Contents of section .data:
66+
// DATALE: Contents of section .data:
67+
// DATABE: Contents of section .data:
5768
.data
5869

5970
// First test absolute data relocations. For each one I show the expected
@@ -72,7 +83,8 @@ REQUIRES: aarch64
7283
.reloc ., R_AARCH64_ABS16, abs16
7384
.hword 0x1234
7485

75-
// DATA-NEXT: 100000 98badcfe efcdab89 a9cbbc9a cdab
86+
// DATALE-NEXT: 100000 98badcfe efcdab89 a9cbbc9a cdab
87+
// DATABE-NEXT: 100000 89abcdef fedcba98 9abccba9 abcd
7688

7789
.balign 16
7890

@@ -91,7 +103,8 @@ REQUIRES: aarch64
91103
.reloc ., R_AARCH64_PREL16, data
92104
.hword 0x1234
93105

94-
// DATA-NEXT: 100010 11436587 78563412 09433412 1812
106+
// DATALE-NEXT: 100010 11436587 78563412 09433412 1812
107+
// DATABE-NEXT: 100010 12345678 87654311 12344309 1218
95108

96109
// CODE: 0000000000200000 <_start>:
97110
.text
@@ -123,7 +136,7 @@ _start:
123136

124137
.reloc ., R_AARCH64_MOVW_UABS_G0_NC, big64
125138
movz x0, #0x1234
126-
// CODE-NEXT: 200010: d2823560 mov x0, #0x11ab
139+
// CODE-NEXT: 200010: d2823560 mov x0, #0x11ab
127140
.reloc ., R_AARCH64_MOVW_UABS_G1_NC, big64
128141
movk x0, #0x1234, lsl #16
129142
// CODE-NEXT: 200014: f2a00000 movk x0, #0x0, lsl #16

0 commit comments

Comments
 (0)