Skip to content

Commit

Permalink
[ELF][S390X] Support more relocation types
Browse files Browse the repository at this point in the history
  • Loading branch information
rui314 committed Oct 14, 2022
1 parent 30dd63c commit f4ce278
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 16 deletions.
76 changes: 62 additions & 14 deletions elf/arch-s390x.cc
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,21 @@ namespace mold::elf {

using E = S390X;

static void write_low12(u8 *loc, u64 val) {
*(ub16 *)loc &= 0xf000;
*(ub16 *)loc |= val & 0x0fff;
}

static void write_mid20(u8 *loc, u64 val) {
*(ub32 *)loc &= 0xf000'00ff;
*(ub32 *)loc |= (bits(val, 11, 0) << 16) | (bits(val, 19, 12) << 8);
}

static void write_low24(u8 *loc, u64 val) {
*(ub32 *)loc &= 0xff00'0000;
*(ub32 *)loc |= val & 0x00ff'ffff;
}

template <>
void write_plt_header(Context<E> &ctx, u8 *buf) {
static u8 insn[] = {
Expand Down Expand Up @@ -133,28 +148,41 @@ void InputSection<E>::apply_reloc_alloc(Context<E> &ctx, u8 *base) {
*loc = S + A;
break;
case R_390_12:
*(ub16 *)loc &= 0xf000;
*(ub16 *)loc |= (S + A) & 0x0fff;
write_low12(loc, S + A);
break;
case R_390_16:
*(ub16 *)loc = S + A;
break;
case R_390_20:
write_mid20(loc, S + A);
break;
case R_390_32:
case R_390_PLT32:
*(ub32 *)loc = S + A;
break;
case R_390_PLT64:
*(ub64 *)loc = S + A;
break;
case R_390_PC12DBL:
case R_390_PLT12DBL:
write_low12(loc, (S + A - P) >> 1);
break;
case R_390_PC16:
*(ub16 *)loc = S + A - P;
break;
case R_390_PC32:
*(ub32 *)loc = S + A - P;
break;
case R_390_PC64:
*(ub64 *)loc = S + A - P;
break;
case R_390_PC16DBL:
case R_390_PLT16DBL:
*(ub16 *)loc = (S + A - P) >> 1;
break;
case R_390_PC32:
*(ub32 *)loc = S + A - P;
case R_390_PC24DBL:
case R_390_PLT24DBL:
write_low24(loc, (S + A - P) >> 1);
break;
case R_390_PC32DBL:
case R_390_PLT32DBL:
Expand All @@ -166,26 +194,36 @@ void InputSection<E>::apply_reloc_alloc(Context<E> &ctx, u8 *base) {
*(ub32 *)loc = (S + A - P) >> 1;
}
break;
case R_390_PC64:
*(ub64 *)loc = S + A - P;
break;
case R_390_GOT12:
*(ub16 *)loc &= 0xf000;
*(ub16 *)loc |= (G + A) & 0x0fff;
case R_390_GOTPLT12:
write_low12(loc, G + A);
break;
case R_390_GOT16:
case R_390_GOTPLT16:
*(ub16 *)loc = G + A;
break;
case R_390_GOT20:
case R_390_GOTPLT20:
write_mid20(loc, G + A);
break;
case R_390_GOT32:
case R_390_GOTPLT32:
*(ub32 *)loc = G + A;
break;
case R_390_GOT64:
case R_390_GOTPLT64:
*(ub64 *)loc = G + A;
break;
case R_390_GOTOFF16:
case R_390_PLTOFF16:
*(ub16 *)loc = S + A - GOT;
break;
case R_390_GOTOFF32:
case R_390_PLTOFF32:
*(ub32 *)loc = S + A - GOT;
break;
case R_390_GOTOFF64:
case R_390_PLTOFF64:
*(ub64 *)loc = S + A - GOT;
break;
case R_390_GOTPC:
Expand All @@ -203,12 +241,9 @@ void InputSection<E>::apply_reloc_alloc(Context<E> &ctx, u8 *base) {
case R_390_TLS_LE64:
*(ub64 *)loc = S + A - ctx.tp_addr;
break;
case R_390_TLS_GOTIE20: {
i64 val = sym.get_gottp_addr(ctx) + A - GOT;
*(ub32 *)loc &= 0xf000'00ff;
*(ub32 *)loc |= (bits(val, 11, 0) << 16) | (bits(val, 19, 12) << 8);
case R_390_TLS_GOTIE20:
write_mid20(loc, sym.get_gottp_addr(ctx) + A - GOT);
break;
}
case R_390_TLS_IEENT:
*(ub32 *)loc = (sym.get_gottp_addr(ctx) + A - P) >> 1;
break;
Expand Down Expand Up @@ -347,6 +382,7 @@ void InputSection<E>::scan_relocations(Context<E> &ctx) {
case R_390_8:
case R_390_12:
case R_390_16:
case R_390_20:
case R_390_32:
scan_rel(ctx, sym, rel, absrel_table);
break;
Expand All @@ -359,19 +395,31 @@ void InputSection<E>::scan_relocations(Context<E> &ctx) {
break;
case R_390_GOT12:
case R_390_GOT16:
case R_390_GOT20:
case R_390_GOT32:
case R_390_GOT64:
case R_390_GOTOFF16:
case R_390_GOTOFF32:
case R_390_GOTOFF64:
case R_390_GOTPLT12:
case R_390_GOTPLT16:
case R_390_GOTPLT20:
case R_390_GOTPLT32:
case R_390_GOTPLT64:
case R_390_GOTPC:
case R_390_GOTPCDBL:
case R_390_GOTENT:
sym.flags |= NEEDS_GOT;
break;
case R_390_PLT12DBL:
case R_390_PLT16DBL:
case R_390_PLT24DBL:
case R_390_PLT32:
case R_390_PLT32DBL:
case R_390_PLT64:
case R_390_PLTOFF16:
case R_390_PLTOFF32:
case R_390_PLTOFF64:
if (sym.is_imported)
sym.flags |= NEEDS_PLT;
break;
Expand Down
4 changes: 2 additions & 2 deletions elf/elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -1522,7 +1522,7 @@ static constexpr u32 R_390_COPY = 9;
static constexpr u32 R_390_GLOB_DAT = 10;
static constexpr u32 R_390_JMP_SLOT = 11;
static constexpr u32 R_390_RELATIVE = 12;
static constexpr u32 R_390_GOTOFF = 13;
static constexpr u32 R_390_GOTOFF32 = 13;
static constexpr u32 R_390_GOTPC = 14;
static constexpr u32 R_390_GOT16 = 15;
static constexpr u32 R_390_PC16 = 16;
Expand Down Expand Up @@ -1592,7 +1592,7 @@ inline std::string rel_to_string<S390X>(u32 r_type) {
case R_390_GLOB_DAT: return "R_390_GLOB_DAT";
case R_390_JMP_SLOT: return "R_390_JMP_SLOT";
case R_390_RELATIVE: return "R_390_RELATIVE";
case R_390_GOTOFF: return "R_390_GOTOFF";
case R_390_GOTOFF32: return "R_390_GOTOFF32";
case R_390_GOTPC: return "R_390_GOTPC";
case R_390_GOT16: return "R_390_GOT16";
case R_390_PC16: return "R_390_PC16";
Expand Down

0 comments on commit f4ce278

Please sign in to comment.