Skip to content

Commit bb9310a

Browse files
MQ-mengqingMingcongBai
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)
1 parent 4a67591 commit bb9310a

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;
@@ -153,6 +154,16 @@ static bool isJirl(uint32_t insn) {
153154
return (insn & 0xfc000000) == JIRL;
154155
}
155156

157+
static void handleUleb128(uint8_t *loc, uint64_t val) {
158+
const uint32_t maxcount = 1 + 64 / 7;
159+
uint32_t count;
160+
uint64_t orig = decodeULEB128(loc, &count);
161+
if (count > maxcount)
162+
errorOrWarn(getErrorLocation(loc) + "extra space for uleb128");
163+
uint64_t mask = count < maxcount ? (1ULL << 7 * count) - 1 : -1ULL;
164+
encodeULEB128((orig + val) & mask, loc, count);
165+
}
166+
156167
LoongArch::LoongArch() {
157168
// The LoongArch ISA itself does not have a limit on page sizes. According to
158169
// the ISA manual, the PS (page size) field in MTLB entries and CSR.STLBPS is
@@ -394,11 +405,13 @@ RelExpr LoongArch::getRelExpr(const RelType type, const Symbol &s,
394405
case R_LARCH_ADD16:
395406
case R_LARCH_ADD32:
396407
case R_LARCH_ADD64:
408+
case R_LARCH_ADD_ULEB128:
397409
case R_LARCH_SUB6:
398410
case R_LARCH_SUB8:
399411
case R_LARCH_SUB16:
400412
case R_LARCH_SUB32:
401413
case R_LARCH_SUB64:
414+
case R_LARCH_SUB_ULEB128:
402415
// The LoongArch add/sub relocs behave like the RISCV counterparts; reuse
403416
// the RelExpr to avoid code duplication.
404417
return R_RISCV_ADD;
@@ -633,6 +646,9 @@ void LoongArch::relocate(uint8_t *loc, const Relocation &rel,
633646
case R_LARCH_ADD64:
634647
write64le(loc, read64le(loc) + val);
635648
return;
649+
case R_LARCH_ADD_ULEB128:
650+
handleUleb128(loc, val);
651+
return;
636652
case R_LARCH_SUB6:
637653
*loc = (*loc & 0xc0) | ((*loc - val) & 0x3f);
638654
return;
@@ -648,6 +664,9 @@ void LoongArch::relocate(uint8_t *loc, const Relocation &rel,
648664
case R_LARCH_SUB64:
649665
write64le(loc, read64le(loc) - val);
650666
return;
667+
case R_LARCH_SUB_ULEB128:
668+
handleUleb128(loc, -val);
669+
return;
651670

652671
case R_LARCH_MARK_LA:
653672
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 00 .
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)