Skip to content

Commit 11a9127

Browse files
committed
[ELF][S390X] Support more relocation types
1 parent 30dd63c commit 11a9127

File tree

2 files changed

+60
-16
lines changed

2 files changed

+60
-16
lines changed

elf/arch-s390x.cc

Lines changed: 58 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,21 @@ namespace mold::elf {
4141

4242
using E = S390X;
4343

44+
static void write_low12(u8 *loc, u64 val) {
45+
*(ub16 *)loc &= 0xf000;
46+
*(ub16 *)loc |= val & 0x0fff;
47+
}
48+
49+
static void write_mid20(u8 *loc, u64 val) {
50+
*(ub32 *)loc &= 0xf000'00ff;
51+
*(ub32 *)loc |= (bits(val, 11, 0) << 16) | (bits(val, 19, 12) << 8);
52+
}
53+
54+
static void write_low24(u8 *loc, u64 val) {
55+
*(ub32 *)loc &= 0xff00'0000;
56+
*(ub32 *)loc |= val & 0x00ff'ffff;
57+
}
58+
4459
template <>
4560
void write_plt_header(Context<E> &ctx, u8 *buf) {
4661
static u8 insn[] = {
@@ -133,8 +148,7 @@ void InputSection<E>::apply_reloc_alloc(Context<E> &ctx, u8 *base) {
133148
*loc = S + A;
134149
break;
135150
case R_390_12:
136-
*(ub16 *)loc &= 0xf000;
137-
*(ub16 *)loc |= (S + A) & 0x0fff;
151+
write_low12(loc, S + A);
138152
break;
139153
case R_390_16:
140154
*(ub16 *)loc = S + A;
@@ -146,15 +160,26 @@ void InputSection<E>::apply_reloc_alloc(Context<E> &ctx, u8 *base) {
146160
case R_390_PLT64:
147161
*(ub64 *)loc = S + A;
148162
break;
163+
case R_390_PC12DBL:
164+
case R_390_PLT12DBL:
165+
write_low12(loc, (S + A - P) >> 1);
166+
break;
149167
case R_390_PC16:
150168
*(ub16 *)loc = S + A - P;
151169
break;
170+
case R_390_PC32:
171+
*(ub32 *)loc = S + A - P;
172+
break;
173+
case R_390_PC64:
174+
*(ub64 *)loc = S + A - P;
175+
break;
152176
case R_390_PC16DBL:
153177
case R_390_PLT16DBL:
154178
*(ub16 *)loc = (S + A - P) >> 1;
155179
break;
156-
case R_390_PC32:
157-
*(ub32 *)loc = S + A - P;
180+
case R_390_PC24DBL:
181+
case R_390_PLT24DBL:
182+
write_low24(loc, (S + A - P) >> 1);
158183
break;
159184
case R_390_PC32DBL:
160185
case R_390_PLT32DBL:
@@ -166,26 +191,36 @@ void InputSection<E>::apply_reloc_alloc(Context<E> &ctx, u8 *base) {
166191
*(ub32 *)loc = (S + A - P) >> 1;
167192
}
168193
break;
169-
case R_390_PC64:
170-
*(ub64 *)loc = S + A - P;
171-
break;
172194
case R_390_GOT12:
173-
*(ub16 *)loc &= 0xf000;
174-
*(ub16 *)loc |= (G + A) & 0x0fff;
195+
case R_390_GOTPLT12:
196+
write_low12(loc, G + A);
175197
break;
176198
case R_390_GOT16:
199+
case R_390_GOTPLT16:
177200
*(ub16 *)loc = G + A;
178201
break;
202+
case R_390_GOT20:
203+
case R_390_GOTPLT20:
204+
write_mid20(loc, G + A);
205+
break;
179206
case R_390_GOT32:
207+
case R_390_GOTPLT32:
180208
*(ub32 *)loc = G + A;
181209
break;
182210
case R_390_GOT64:
211+
case R_390_GOTPLT64:
183212
*(ub64 *)loc = G + A;
184213
break;
185214
case R_390_GOTOFF16:
215+
case R_390_PLTOFF16:
186216
*(ub16 *)loc = S + A - GOT;
187217
break;
218+
case R_390_GOTOFF32:
219+
case R_390_PLTOFF32:
220+
*(ub32 *)loc = S + A - GOT;
221+
break;
188222
case R_390_GOTOFF64:
223+
case R_390_PLTOFF64:
189224
*(ub64 *)loc = S + A - GOT;
190225
break;
191226
case R_390_GOTPC:
@@ -203,12 +238,9 @@ void InputSection<E>::apply_reloc_alloc(Context<E> &ctx, u8 *base) {
203238
case R_390_TLS_LE64:
204239
*(ub64 *)loc = S + A - ctx.tp_addr;
205240
break;
206-
case R_390_TLS_GOTIE20: {
207-
i64 val = sym.get_gottp_addr(ctx) + A - GOT;
208-
*(ub32 *)loc &= 0xf000'00ff;
209-
*(ub32 *)loc |= (bits(val, 11, 0) << 16) | (bits(val, 19, 12) << 8);
241+
case R_390_TLS_GOTIE20:
242+
write_mid20(loc, sym.get_gottp_addr(ctx) + A - GOT);
210243
break;
211-
}
212244
case R_390_TLS_IEENT:
213245
*(ub32 *)loc = (sym.get_gottp_addr(ctx) + A - P) >> 1;
214246
break;
@@ -359,19 +391,31 @@ void InputSection<E>::scan_relocations(Context<E> &ctx) {
359391
break;
360392
case R_390_GOT12:
361393
case R_390_GOT16:
394+
case R_390_GOT20:
362395
case R_390_GOT32:
363396
case R_390_GOT64:
364397
case R_390_GOTOFF16:
398+
case R_390_GOTOFF32:
365399
case R_390_GOTOFF64:
400+
case R_390_GOTPLT12:
401+
case R_390_GOTPLT16:
402+
case R_390_GOTPLT20:
403+
case R_390_GOTPLT32:
404+
case R_390_GOTPLT64:
366405
case R_390_GOTPC:
367406
case R_390_GOTPCDBL:
368407
case R_390_GOTENT:
369408
sym.flags |= NEEDS_GOT;
370409
break;
410+
case R_390_PLT12DBL:
371411
case R_390_PLT16DBL:
412+
case R_390_PLT24DBL:
372413
case R_390_PLT32:
373414
case R_390_PLT32DBL:
374415
case R_390_PLT64:
416+
case R_390_PLTOFF16:
417+
case R_390_PLTOFF32:
418+
case R_390_PLTOFF64:
375419
if (sym.is_imported)
376420
sym.flags |= NEEDS_PLT;
377421
break;

elf/elf.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1522,7 +1522,7 @@ static constexpr u32 R_390_COPY = 9;
15221522
static constexpr u32 R_390_GLOB_DAT = 10;
15231523
static constexpr u32 R_390_JMP_SLOT = 11;
15241524
static constexpr u32 R_390_RELATIVE = 12;
1525-
static constexpr u32 R_390_GOTOFF = 13;
1525+
static constexpr u32 R_390_GOTOFF32 = 13;
15261526
static constexpr u32 R_390_GOTPC = 14;
15271527
static constexpr u32 R_390_GOT16 = 15;
15281528
static constexpr u32 R_390_PC16 = 16;
@@ -1592,7 +1592,7 @@ inline std::string rel_to_string<S390X>(u32 r_type) {
15921592
case R_390_GLOB_DAT: return "R_390_GLOB_DAT";
15931593
case R_390_JMP_SLOT: return "R_390_JMP_SLOT";
15941594
case R_390_RELATIVE: return "R_390_RELATIVE";
1595-
case R_390_GOTOFF: return "R_390_GOTOFF";
1595+
case R_390_GOTOFF32: return "R_390_GOTOFF32";
15961596
case R_390_GOTPC: return "R_390_GOTPC";
15971597
case R_390_GOT16: return "R_390_GOT16";
15981598
case R_390_PC16: return "R_390_PC16";

0 commit comments

Comments
 (0)