Skip to content

Commit a5c1174

Browse files
MQ-mengqingAmi-zhang
authored andcommitted
[lld][LoongArch] Support the R_LARCH_{ADD,SUB}_ULEB128 relocation types (llvm#81133)
For a label difference like `.uleb128 A-B`, MC generates a pair of R_LARCH_{ADD,SUB}_ULEB128 if A-B cannot be folded as a constant. GNU assembler generates a pair of relocations in more cases (when A or B is in a code section with linker relaxation). It is similar to RISCV. R_LARCH_{ADD,SUB}_ULEB128 relocations are created by Clang and GCC in `.gcc_except_table` and other debug sections with linker relaxation enabled. On LoongArch, first read the buf and count the available space. Then add or sub the value. Finally truncate the expected value and fill it into the available space. (cherry picked from commit eaa9ef6) Change-Id: Ic49d34146e47eeeabbbba00ef70b76a13322d80e
1 parent f51ee6c commit a5c1174

File tree

2 files changed

+121
-0
lines changed

2 files changed

+121
-0
lines changed

lld/ELF/Arch/LoongArch.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "Symbols.h"
1212
#include "SyntheticSections.h"
1313
#include "Target.h"
14+
#include "llvm/Support/LEB128.h"
1415

1516
using namespace llvm;
1617
using namespace llvm::object;
@@ -210,6 +211,16 @@ static bool isJirl(uint32_t insn) {
210211
return (insn & 0xfc000000) == JIRL;
211212
}
212213

214+
static void handleUleb128(uint8_t *loc, uint64_t val) {
215+
const uint32_t maxcount = 1 + 64 / 7;
216+
uint32_t count;
217+
uint64_t orig = decodeULEB128(loc, &count);
218+
if (count > maxcount)
219+
errorOrWarn(getErrorLocation(loc) + "extra space for uleb128");
220+
uint64_t mask = count < maxcount ? (1ULL << 7 * count) - 1 : -1ULL;
221+
encodeULEB128((orig + val) & mask, loc, count);
222+
}
223+
213224
LoongArch::LoongArch() {
214225
// The LoongArch ISA itself does not have a limit on page sizes. According to
215226
// the ISA manual, the PS (page size) field in MTLB entries and CSR.STLBPS is
@@ -451,11 +462,13 @@ RelExpr LoongArch::getRelExpr(const RelType type, const Symbol &s,
451462
case R_LARCH_ADD16:
452463
case R_LARCH_ADD32:
453464
case R_LARCH_ADD64:
465+
case R_LARCH_ADD_ULEB128:
454466
case R_LARCH_SUB6:
455467
case R_LARCH_SUB8:
456468
case R_LARCH_SUB16:
457469
case R_LARCH_SUB32:
458470
case R_LARCH_SUB64:
471+
case R_LARCH_SUB_ULEB128:
459472
// The LoongArch add/sub relocs behave like the RISCV counterparts; reuse
460473
// the RelExpr to avoid code duplication.
461474
return R_RISCV_ADD;
@@ -670,6 +683,9 @@ void LoongArch::relocate(uint8_t *loc, const Relocation &rel,
670683
case R_LARCH_ADD64:
671684
write64le(loc, read64le(loc) + val);
672685
return;
686+
case R_LARCH_ADD_ULEB128:
687+
handleUleb128(loc, val);
688+
return;
673689
case R_LARCH_SUB6:
674690
*loc = (*loc & 0xc0) | ((*loc - val) & 0x3f);
675691
return;
@@ -685,6 +701,9 @@ void LoongArch::relocate(uint8_t *loc, const Relocation &rel,
685701
case R_LARCH_SUB64:
686702
write64le(loc, read64le(loc) - val);
687703
return;
704+
case R_LARCH_SUB_ULEB128:
705+
handleUleb128(loc, -val);
706+
return;
688707

689708
case R_LARCH_MARK_LA:
690709
case R_LARCH_MARK_PCREL:

lld/test/ELF/loongarch-reloc-leb128.s

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
# REQUIRES: loongarch
2+
# RUN: rm -rf %t && split-file %s %t && cd %t
3+
4+
# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=+relax a.s -o a.o
5+
# RUN: llvm-readobj -r -x .gcc_except_table -x .debug_rnglists -x .debug_loclists a.o | FileCheck %s --check-prefix=REL
6+
# RUN: ld.lld -shared --gc-sections a.o -o a.so
7+
# RUN: llvm-readelf -x .gcc_except_table -x .debug_rnglists -x .debug_loclists a.so | FileCheck %s
8+
9+
# RUN: llvm-mc --filetype=obj --triple=loongarch32 --mattr=+relax a.s -o a32.o
10+
# RUN: llvm-readobj -r -x .gcc_except_table -x .debug_rnglists -x .debug_loclists a32.o | FileCheck %s --check-prefix=REL
11+
# RUN: ld.lld -shared --gc-sections a32.o -o a32.so
12+
# RUN: llvm-readelf -x .gcc_except_table -x .debug_rnglists -x .debug_loclists a32.so | FileCheck %s
13+
14+
# RUN: llvm-mc --filetype=obj --triple=loongarch32 --mattr=+relax extraspace.s -o extraspace32.o
15+
# RUN: llvm-mc --filetype=obj --triple=loongarch64 --mattr=+relax extraspace.s -o extraspace64.o
16+
# RUN: not ld.lld -shared extraspace32.o 2>&1 | FileCheck %s --check-prefix=ERROR
17+
# RUN: not ld.lld -shared extraspace64.o 2>&1 | FileCheck %s --check-prefix=ERROR
18+
# ERROR: error: extraspace{{.*}}.o:(.rodata+0x0): extra space for uleb128
19+
20+
#--- a.s
21+
.cfi_startproc
22+
.cfi_lsda 0x1b,.LLSDA0
23+
.cfi_endproc
24+
25+
.section .text.w,"axR"
26+
break 0; break 0; break 0; w1:
27+
.p2align 4 # 4 bytes after relaxation
28+
w2: break 0
29+
30+
.section .text.x,"ax"
31+
break 0; break 0; break 0; x1:
32+
.p2align 4 # 4 bytes after relaxation
33+
x2: break 0
34+
35+
.section .gcc_except_table,"a"
36+
.LLSDA0:
37+
.uleb128 w2-w1+116 # initial value: 0x0080
38+
.uleb128 w1-w2+141 # initial value: 0x0080
39+
.uleb128 w2-w1+16372 # initial value: 0x008080
40+
.uleb128 w1-w2+16397 # initial value: 0x008080
41+
.uleb128 w2-w1+2097140 # initial value: 0x00808080
42+
.uleb128 w1-w2+2097165 # initial value: 0x00808080
43+
44+
.section .debug_rnglists
45+
.uleb128 w2-w1+116 # initial value: 0x0080
46+
.uleb128 w1-w2+141 # initial value: 0x0080
47+
.uleb128 w2-w1+16372 # initial value: 0x008080
48+
.uleb128 w1-w2+16397 # initial value: 0x008080
49+
.uleb128 w2-w1+2097140 # initial value: 0x00808080
50+
.uleb128 w1-w2+2097165 # initial value: 0x00808080
51+
52+
.section .debug_loclists
53+
.uleb128 x2-x1 # references discarded symbols
54+
55+
# REL: Section ({{.*}}) .rela.debug_rnglists {
56+
# REL-NEXT: 0x0 R_LARCH_ADD_ULEB128 w2 0x74
57+
# REL-NEXT: 0x0 R_LARCH_SUB_ULEB128 w1 0x0
58+
# REL-NEXT: 0x2 R_LARCH_ADD_ULEB128 w1 0x8D
59+
# REL-NEXT: 0x2 R_LARCH_SUB_ULEB128 w2 0x0
60+
# REL-NEXT: 0x4 R_LARCH_ADD_ULEB128 w2 0x3FF4
61+
# REL-NEXT: 0x4 R_LARCH_SUB_ULEB128 w1 0x0
62+
# REL-NEXT: 0x7 R_LARCH_ADD_ULEB128 w1 0x400D
63+
# REL-NEXT: 0x7 R_LARCH_SUB_ULEB128 w2 0x0
64+
# REL-NEXT: 0xA R_LARCH_ADD_ULEB128 w2 0x1FFFF4
65+
# REL-NEXT: 0xA R_LARCH_SUB_ULEB128 w1 0x0
66+
# REL-NEXT: 0xE R_LARCH_ADD_ULEB128 w1 0x20000D
67+
# REL-NEXT: 0xE R_LARCH_SUB_ULEB128 w2 0x0
68+
# REL-NEXT: }
69+
# REL: Section ({{.*}}) .rela.debug_loclists {
70+
# REL-NEXT: 0x0 R_LARCH_ADD_ULEB128 x2 0x0
71+
# REL-NEXT: 0x0 R_LARCH_SUB_ULEB128 x1 0x0
72+
# REL-NEXT: }
73+
74+
# REL: Hex dump of section '.gcc_except_table':
75+
# REL-NEXT: 0x00000000 80008000 80800080 80008080 80008080 .
76+
# REL-NEXT: 0x00000010 8000 .
77+
# REL: Hex dump of section '.debug_rnglists':
78+
# REL-NEXT: 0x00000000 80008000 80800080 80008080 80008080 .
79+
# REL-NEXT: 0x00000010 8000 .
80+
# REL: Hex dump of section '.debug_loclists':
81+
# REL-NEXT: 0x00000000 00 .
82+
83+
# CHECK: Hex dump of section '.gcc_except_table':
84+
# CHECK-NEXT: 0x[[#%x,]] f8008901 f8ff0089 8001f8ff ff008980 .
85+
# CHECK-NEXT: 0x[[#%x,]] 8001 .
86+
# CHECK: Hex dump of section '.debug_rnglists':
87+
# CHECK-NEXT: 0x00000000 f8008901 f8ff0089 8001f8ff ff008980 .
88+
# CHECK-NEXT: 0x00000010 8001 .
89+
# CHECK: Hex dump of section '.debug_loclists':
90+
# CHECK-NEXT: 0x00000000 0c .
91+
92+
#--- extraspace.s
93+
.text
94+
w1:
95+
la.pcrel $t0, w1
96+
w2:
97+
98+
.rodata
99+
.reloc ., R_LARCH_ADD_ULEB128, w2
100+
.reloc ., R_LARCH_SUB_ULEB128, w1
101+
.fill 10, 1, 0x80
102+
.byte 0

0 commit comments

Comments
 (0)