Skip to content

Commit f4ce278

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

File tree

2 files changed

+64
-16
lines changed

2 files changed

+64
-16
lines changed

elf/arch-s390x.cc

Lines changed: 62 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,28 +148,41 @@ 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;
141155
break;
156+
case R_390_20:
157+
write_mid20(loc, S + A);
158+
break;
142159
case R_390_32:
143160
case R_390_PLT32:
144161
*(ub32 *)loc = S + A;
145162
break;
146163
case R_390_PLT64:
147164
*(ub64 *)loc = S + A;
148165
break;
166+
case R_390_PC12DBL:
167+
case R_390_PLT12DBL:
168+
write_low12(loc, (S + A - P) >> 1);
169+
break;
149170
case R_390_PC16:
150171
*(ub16 *)loc = S + A - P;
151172
break;
173+
case R_390_PC32:
174+
*(ub32 *)loc = S + A - P;
175+
break;
176+
case R_390_PC64:
177+
*(ub64 *)loc = S + A - P;
178+
break;
152179
case R_390_PC16DBL:
153180
case R_390_PLT16DBL:
154181
*(ub16 *)loc = (S + A - P) >> 1;
155182
break;
156-
case R_390_PC32:
157-
*(ub32 *)loc = S + A - P;
183+
case R_390_PC24DBL:
184+
case R_390_PLT24DBL:
185+
write_low24(loc, (S + A - P) >> 1);
158186
break;
159187
case R_390_PC32DBL:
160188
case R_390_PLT32DBL:
@@ -166,26 +194,36 @@ void InputSection<E>::apply_reloc_alloc(Context<E> &ctx, u8 *base) {
166194
*(ub32 *)loc = (S + A - P) >> 1;
167195
}
168196
break;
169-
case R_390_PC64:
170-
*(ub64 *)loc = S + A - P;
171-
break;
172197
case R_390_GOT12:
173-
*(ub16 *)loc &= 0xf000;
174-
*(ub16 *)loc |= (G + A) & 0x0fff;
198+
case R_390_GOTPLT12:
199+
write_low12(loc, G + A);
175200
break;
176201
case R_390_GOT16:
202+
case R_390_GOTPLT16:
177203
*(ub16 *)loc = G + A;
178204
break;
205+
case R_390_GOT20:
206+
case R_390_GOTPLT20:
207+
write_mid20(loc, G + A);
208+
break;
179209
case R_390_GOT32:
210+
case R_390_GOTPLT32:
180211
*(ub32 *)loc = G + A;
181212
break;
182213
case R_390_GOT64:
214+
case R_390_GOTPLT64:
183215
*(ub64 *)loc = G + A;
184216
break;
185217
case R_390_GOTOFF16:
218+
case R_390_PLTOFF16:
186219
*(ub16 *)loc = S + A - GOT;
187220
break;
221+
case R_390_GOTOFF32:
222+
case R_390_PLTOFF32:
223+
*(ub32 *)loc = S + A - GOT;
224+
break;
188225
case R_390_GOTOFF64:
226+
case R_390_PLTOFF64:
189227
*(ub64 *)loc = S + A - GOT;
190228
break;
191229
case R_390_GOTPC:
@@ -203,12 +241,9 @@ void InputSection<E>::apply_reloc_alloc(Context<E> &ctx, u8 *base) {
203241
case R_390_TLS_LE64:
204242
*(ub64 *)loc = S + A - ctx.tp_addr;
205243
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);
244+
case R_390_TLS_GOTIE20:
245+
write_mid20(loc, sym.get_gottp_addr(ctx) + A - GOT);
210246
break;
211-
}
212247
case R_390_TLS_IEENT:
213248
*(ub32 *)loc = (sym.get_gottp_addr(ctx) + A - P) >> 1;
214249
break;
@@ -347,6 +382,7 @@ void InputSection<E>::scan_relocations(Context<E> &ctx) {
347382
case R_390_8:
348383
case R_390_12:
349384
case R_390_16:
385+
case R_390_20:
350386
case R_390_32:
351387
scan_rel(ctx, sym, rel, absrel_table);
352388
break;
@@ -359,19 +395,31 @@ void InputSection<E>::scan_relocations(Context<E> &ctx) {
359395
break;
360396
case R_390_GOT12:
361397
case R_390_GOT16:
398+
case R_390_GOT20:
362399
case R_390_GOT32:
363400
case R_390_GOT64:
364401
case R_390_GOTOFF16:
402+
case R_390_GOTOFF32:
365403
case R_390_GOTOFF64:
404+
case R_390_GOTPLT12:
405+
case R_390_GOTPLT16:
406+
case R_390_GOTPLT20:
407+
case R_390_GOTPLT32:
408+
case R_390_GOTPLT64:
366409
case R_390_GOTPC:
367410
case R_390_GOTPCDBL:
368411
case R_390_GOTENT:
369412
sym.flags |= NEEDS_GOT;
370413
break;
414+
case R_390_PLT12DBL:
371415
case R_390_PLT16DBL:
416+
case R_390_PLT24DBL:
372417
case R_390_PLT32:
373418
case R_390_PLT32DBL:
374419
case R_390_PLT64:
420+
case R_390_PLTOFF16:
421+
case R_390_PLTOFF32:
422+
case R_390_PLTOFF64:
375423
if (sym.is_imported)
376424
sym.flags |= NEEDS_PLT;
377425
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)