Skip to content

Commit

Permalink
Improve MIPS support
Browse files Browse the repository at this point in the history
  • Loading branch information
rui314 committed Aug 4, 2023
1 parent 5199414 commit 0df6063
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 21 deletions.
2 changes: 1 addition & 1 deletion elf/arch-alpha.cc
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ void AlphaGotSection::copy_buf(Context<E> &ctx) {

if (e.sym->is_imported) {
*buf = ctx.arg.apply_dynamic_relocs ? e.addend : 0;
*dynrel++ = ElfRel<E>(P, E::R_ABS, e.sym->get_dynsym_idx(ctx), e.addend);
*dynrel++ = ElfRel<E>(P, E::R_DYNAMIC, e.sym->get_dynsym_idx(ctx), e.addend);
} else {
*buf = e.sym->get_addr(ctx) + e.addend;
if (ctx.arg.pic && !e.sym->is_absolute())
Expand Down
29 changes: 18 additions & 11 deletions elf/arch-mips64.cc
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ void EhFrameSection<E>::apply_eh_reloc(Context<E> &ctx, const ElfRel<E> &rel,
case R_NONE:
break;
case R_MIPS_64:
assert(rel.r_type2 == R_NONE);
*(U64<E> *)loc = val;
break;
default:
Expand Down Expand Up @@ -84,11 +85,11 @@ void InputSection<E>::apply_reloc_alloc(Context<E> &ctx, u8 *base) {
Symbol<E> &sym = *file.symbols[rel.r_sym];
u8 *loc = base + rel.r_offset;

[[maybe_unused]] auto check = [&](i64 val, i64 lo, i64 hi) {
auto check = [&](i64 val, i64 lo, i64 hi) {
if (val < lo || hi <= val)
Error(ctx) << *this << ": relocation " << rel << " against "
<< sym << " out of range: " << val << " is not in ["
<< lo << ", " << hi << ")";
<< lo << ", " << hi << "); recompile with -mxgot";
};

auto write_combined = [&](u64 val) {
Expand All @@ -114,19 +115,25 @@ void InputSection<E>::apply_reloc_alloc(Context<E> &ctx, u8 *base) {
};

auto write_hi16 = [&](u64 val) {
check(val, -(1LL << 31), 1LL << 31);
if (rel.r_type2 == R_NONE && rel.r_type3 == R_NONE)
*(U32<E> *)loc |= ((val + BIAS) >> 16) & 0xffff;
else
write_combined(val);
};

auto write_lo16 = [&](u64 val) {
auto write_lo16_nc = [&](u64 val) {
if (rel.r_type2 == R_NONE && rel.r_type3 == R_NONE)
*(U32<E> *)loc |= val & 0xffff;
else
write_combined(val);
};

auto write_lo16 = [&](u64 val) {
check(val, -(1 << 15), 1 << 15);
write_lo16_nc(val);
};

u64 S = sym.get_addr(ctx);
u64 A = rel.r_addend;
u64 P = get_addr() + rel.r_offset;
Expand All @@ -139,9 +146,9 @@ void InputSection<E>::apply_reloc_alloc(Context<E> &ctx, u8 *base) {
break;
case R_MIPS_GPREL16:
if (sym.is_local(ctx))
write_lo16(S + A + GP0 - GP);
write_lo16_nc(S + A + GP0 - GP);
else
write_lo16(S + A - GP);
write_lo16_nc(S + A - GP);
break;
case R_MIPS_GPREL32:
write32(S + A + GP0 - GP);
Expand All @@ -165,15 +172,15 @@ void InputSection<E>::apply_reloc_alloc(Context<E> &ctx, u8 *base) {
write_lo16(ctx.extra.got->get_gotpage_got_addr(ctx, sym, A) - GP);
break;
case R_MIPS_GOT_OFST:
write_lo16(S + A - ctx.extra.got->get_gotpage_page_addr(ctx, sym, A));
write_lo16(0);
break;
case R_MIPS_JALR:
break;
case R_MIPS_TLS_TPREL_HI16:
write_hi16(S + A - ctx.tp_addr);
break;
case R_MIPS_TLS_TPREL_LO16:
write_lo16(S + A - ctx.tp_addr);
write_lo16_nc(S + A - ctx.tp_addr);
break;
case R_MIPS_TLS_GOTTPREL:
write_lo16(sym.get_gottp_addr(ctx) - GP);
Expand All @@ -182,13 +189,13 @@ void InputSection<E>::apply_reloc_alloc(Context<E> &ctx, u8 *base) {
write_hi16(S + A - ctx.dtp_addr);
break;
case R_MIPS_TLS_DTPREL_LO16:
write_lo16(S + A - ctx.dtp_addr);
write_lo16_nc(S + A - ctx.dtp_addr);
break;
case R_MIPS_TLS_GD:
write_lo16(sym.get_tlsgd_addr(ctx) + A - GP);
write_lo16(sym.get_tlsgd_addr(ctx) - GP);
break;
case R_MIPS_TLS_LDM:
write_lo16(ctx.got->get_tlsld_addr(ctx) + A - GP);
write_lo16(ctx.got->get_tlsld_addr(ctx) - GP);
break;
default:
unreachable();
Expand Down Expand Up @@ -356,7 +363,7 @@ MipsGotSection<E>::get_got_entries(Context<E> &ctx) const {
for (const SymbolAddend &ent : got_syms) {
// If a symbol is imported, let the dynamic linker to resolve it.
if (ent.sym->is_imported) {
add({0, E::R_GLOB_DAT, ent.sym});
add({0, E::R_DYNAMIC, ent.sym});
continue;
}

Expand Down
14 changes: 8 additions & 6 deletions elf/cmdline.cc
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ std::vector<std::string> parse_nonpositional_args(Context<E> &ctx) {
// It looks like the SPARC's dynamic linker takes both RELA's r_addend
// and the value at the relocated place. So we don't want to write
// values to relocated places.
if (is_sparc<E>)
if constexpr (is_sparc<E>)
ctx.arg.apply_dynamic_relocs = false;

auto read_arg = [&](std::string name) {
Expand Down Expand Up @@ -1216,12 +1216,14 @@ std::vector<std::string> parse_nonpositional_args(Context<E> &ctx) {
Fatal(ctx) << "-auxiliary may not be used without -shared";
}

if (!ctx.arg.apply_dynamic_relocs && !E::is_rela)
Fatal(ctx) << "--no-apply-dynamic-relocs may not be used on "
<< E::target_name;
if constexpr (!E::is_rela || is_mips<E>)
if (!ctx.arg.apply_dynamic_relocs)
Fatal(ctx) << "--no-apply-dynamic-relocs may not be used on "
<< E::target_name;

if (is_sparc<E> && ctx.arg.apply_dynamic_relocs)
Fatal(ctx) << "--apply-dynamic-relocs may not be used on SPARC64";
if constexpr (is_sparc<E>)
if (ctx.arg.apply_dynamic_relocs)
Fatal(ctx) << "--apply-dynamic-relocs may not be used on SPARC64";

if (!ctx.arg.section_start.empty() && !ctx.arg.section_order.empty())
Fatal(ctx) << "--section-start may not be used with --section-order";
Expand Down
22 changes: 20 additions & 2 deletions elf/elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -1866,6 +1866,7 @@ struct X86_64 {
static constexpr u32 R_GLOB_DAT = R_X86_64_GLOB_DAT;
static constexpr u32 R_JUMP_SLOT = R_X86_64_JUMP_SLOT;
static constexpr u32 R_ABS = R_X86_64_64;
static constexpr u32 R_DYNAMIC = R_X86_64_64;
static constexpr u32 R_RELATIVE = R_X86_64_RELATIVE;
static constexpr u32 R_IRELATIVE = R_X86_64_IRELATIVE;
static constexpr u32 R_DTPOFF = R_X86_64_DTPOFF64;
Expand All @@ -1889,6 +1890,7 @@ struct I386 {
static constexpr u32 R_GLOB_DAT = R_386_GLOB_DAT;
static constexpr u32 R_JUMP_SLOT = R_386_JUMP_SLOT;
static constexpr u32 R_ABS = R_386_32;
static constexpr u32 R_DYNAMIC = R_386_32;
static constexpr u32 R_RELATIVE = R_386_RELATIVE;
static constexpr u32 R_IRELATIVE = R_386_IRELATIVE;
static constexpr u32 R_DTPOFF = R_386_TLS_DTPOFF32;
Expand All @@ -1914,6 +1916,7 @@ struct ARM64 {
static constexpr u32 R_GLOB_DAT = R_AARCH64_GLOB_DAT;
static constexpr u32 R_JUMP_SLOT = R_AARCH64_JUMP_SLOT;
static constexpr u32 R_ABS = R_AARCH64_ABS64;
static constexpr u32 R_DYNAMIC = R_AARCH64_ABS64;
static constexpr u32 R_RELATIVE = R_AARCH64_RELATIVE;
static constexpr u32 R_IRELATIVE = R_AARCH64_IRELATIVE;
static constexpr u32 R_DTPOFF = R_AARCH64_TLS_DTPREL64;
Expand All @@ -1939,6 +1942,7 @@ struct ARM32 {
static constexpr u32 R_GLOB_DAT = R_ARM_GLOB_DAT;
static constexpr u32 R_JUMP_SLOT = R_ARM_JUMP_SLOT;
static constexpr u32 R_ABS = R_ARM_ABS32;
static constexpr u32 R_DYNAMIC = R_ARM_ABS32;
static constexpr u32 R_RELATIVE = R_ARM_RELATIVE;
static constexpr u32 R_IRELATIVE = R_ARM_IRELATIVE;
static constexpr u32 R_DTPOFF = R_ARM_TLS_DTPOFF32;
Expand All @@ -1962,6 +1966,7 @@ struct RV64LE {
static constexpr u32 R_GLOB_DAT = R_RISCV_64;
static constexpr u32 R_JUMP_SLOT = R_RISCV_JUMP_SLOT;
static constexpr u32 R_ABS = R_RISCV_64;
static constexpr u32 R_DYNAMIC = R_RISCV_64;
static constexpr u32 R_RELATIVE = R_RISCV_RELATIVE;
static constexpr u32 R_IRELATIVE = R_RISCV_IRELATIVE;
static constexpr u32 R_DTPOFF = R_RISCV_TLS_DTPREL64;
Expand All @@ -1984,6 +1989,7 @@ struct RV64BE {
static constexpr u32 R_GLOB_DAT = R_RISCV_64;
static constexpr u32 R_JUMP_SLOT = R_RISCV_JUMP_SLOT;
static constexpr u32 R_ABS = R_RISCV_64;
static constexpr u32 R_DYNAMIC = R_RISCV_64;
static constexpr u32 R_RELATIVE = R_RISCV_RELATIVE;
static constexpr u32 R_IRELATIVE = R_RISCV_IRELATIVE;
static constexpr u32 R_DTPOFF = R_RISCV_TLS_DTPREL64;
Expand All @@ -2006,6 +2012,7 @@ struct RV32LE {
static constexpr u32 R_GLOB_DAT = R_RISCV_32;
static constexpr u32 R_JUMP_SLOT = R_RISCV_JUMP_SLOT;
static constexpr u32 R_ABS = R_RISCV_32;
static constexpr u32 R_DYNAMIC = R_RISCV_32;
static constexpr u32 R_RELATIVE = R_RISCV_RELATIVE;
static constexpr u32 R_IRELATIVE = R_RISCV_IRELATIVE;
static constexpr u32 R_DTPOFF = R_RISCV_TLS_DTPREL32;
Expand All @@ -2028,6 +2035,7 @@ struct RV32BE {
static constexpr u32 R_GLOB_DAT = R_RISCV_32;
static constexpr u32 R_JUMP_SLOT = R_RISCV_JUMP_SLOT;
static constexpr u32 R_ABS = R_RISCV_32;
static constexpr u32 R_DYNAMIC = R_RISCV_32;
static constexpr u32 R_RELATIVE = R_RISCV_RELATIVE;
static constexpr u32 R_IRELATIVE = R_RISCV_IRELATIVE;
static constexpr u32 R_DTPOFF = R_RISCV_TLS_DTPREL32;
Expand All @@ -2052,6 +2060,7 @@ struct PPC32 {
static constexpr u32 R_GLOB_DAT = R_PPC_GLOB_DAT;
static constexpr u32 R_JUMP_SLOT = R_PPC_JMP_SLOT;
static constexpr u32 R_ABS = R_PPC_ADDR32;
static constexpr u32 R_DYNAMIC = R_PPC_ADDR32;
static constexpr u32 R_RELATIVE = R_PPC_RELATIVE;
static constexpr u32 R_IRELATIVE = R_PPC_IRELATIVE;
static constexpr u32 R_DTPOFF = R_PPC_DTPREL32;
Expand All @@ -2075,6 +2084,7 @@ struct PPC64V1 {
static constexpr u32 R_GLOB_DAT = R_PPC64_GLOB_DAT;
static constexpr u32 R_JUMP_SLOT = R_PPC64_JMP_SLOT;
static constexpr u32 R_ABS = R_PPC64_ADDR64;
static constexpr u32 R_DYNAMIC = R_PPC64_ADDR64;
static constexpr u32 R_RELATIVE = R_PPC64_RELATIVE;
static constexpr u32 R_IRELATIVE = R_PPC64_IRELATIVE;
static constexpr u32 R_DTPOFF = R_PPC64_DTPREL64;
Expand All @@ -2099,6 +2109,7 @@ struct PPC64V2 {
static constexpr u32 R_GLOB_DAT = R_PPC64_GLOB_DAT;
static constexpr u32 R_JUMP_SLOT = R_PPC64_JMP_SLOT;
static constexpr u32 R_ABS = R_PPC64_ADDR64;
static constexpr u32 R_DYNAMIC = R_PPC64_ADDR64;
static constexpr u32 R_RELATIVE = R_PPC64_RELATIVE;
static constexpr u32 R_IRELATIVE = R_PPC64_IRELATIVE;
static constexpr u32 R_DTPOFF = R_PPC64_DTPREL64;
Expand All @@ -2121,6 +2132,7 @@ struct S390X {
static constexpr u32 R_GLOB_DAT = R_390_GLOB_DAT;
static constexpr u32 R_JUMP_SLOT = R_390_JMP_SLOT;
static constexpr u32 R_ABS = R_390_64;
static constexpr u32 R_DYNAMIC = R_390_64;
static constexpr u32 R_RELATIVE = R_390_RELATIVE;
static constexpr u32 R_IRELATIVE = R_390_IRELATIVE;
static constexpr u32 R_DTPOFF = R_390_TLS_DTPOFF;
Expand All @@ -2143,6 +2155,7 @@ struct SPARC64 {
static constexpr u32 R_GLOB_DAT = R_SPARC_GLOB_DAT;
static constexpr u32 R_JUMP_SLOT = R_SPARC_JMP_SLOT;
static constexpr u32 R_ABS = R_SPARC_64;
static constexpr u32 R_DYNAMIC = R_SPARC_64;
static constexpr u32 R_RELATIVE = R_SPARC_RELATIVE;
static constexpr u32 R_IRELATIVE = R_SPARC_IRELATIVE;
static constexpr u32 R_DTPOFF = R_SPARC_TLS_DTPOFF64;
Expand All @@ -2165,6 +2178,7 @@ struct M68K {
static constexpr u32 R_GLOB_DAT = R_68K_GLOB_DAT;
static constexpr u32 R_JUMP_SLOT = R_68K_JMP_SLOT;
static constexpr u32 R_ABS = R_68K_32;
static constexpr u32 R_DYNAMIC = R_68K_32;
static constexpr u32 R_RELATIVE = R_68K_RELATIVE;
static constexpr u32 R_DTPOFF = R_68K_TLS_DTPREL32;
static constexpr u32 R_TPOFF = R_68K_TLS_TPREL32;
Expand All @@ -2186,6 +2200,7 @@ struct SH4 {
static constexpr u32 R_GLOB_DAT = R_SH_GLOB_DAT;
static constexpr u32 R_JUMP_SLOT = R_SH_JMP_SLOT;
static constexpr u32 R_ABS = R_SH_DIR32;
static constexpr u32 R_DYNAMIC = R_SH_DIR32;
static constexpr u32 R_RELATIVE = R_SH_RELATIVE;
static constexpr u32 R_DTPOFF = R_SH_TLS_DTPOFF32;
static constexpr u32 R_TPOFF = R_SH_TLS_TPOFF32;
Expand All @@ -2207,6 +2222,7 @@ struct ALPHA {
static constexpr u32 R_GLOB_DAT = R_ALPHA_GLOB_DAT;
static constexpr u32 R_JUMP_SLOT = R_ALPHA_JMP_SLOT;
static constexpr u32 R_ABS = R_ALPHA_REFQUAD;
static constexpr u32 R_DYNAMIC = R_ALPHA_REFQUAD;
static constexpr u32 R_RELATIVE = R_ALPHA_RELATIVE;
static constexpr u32 R_DTPOFF = R_ALPHA_DTPREL64;
static constexpr u32 R_TPOFF = R_ALPHA_TPREL64;
Expand All @@ -2227,7 +2243,8 @@ struct MIPS64LE {
static constexpr u32 R_COPY = R_MIPS_COPY;
static constexpr u32 R_GLOB_DAT = R_MIPS_GLOB_DAT;
static constexpr u32 R_JUMP_SLOT = R_MIPS_JUMP_SLOT;
static constexpr u32 R_ABS = R_MIPS_GLOB_DAT;
static constexpr u32 R_ABS = R_MIPS_64;
static constexpr u32 R_DYNAMIC = R_MIPS_REL32;
static constexpr u32 R_RELATIVE = R_MIPS_REL32;
static constexpr u32 R_DTPOFF = R_MIPS_TLS_DTPREL64;
static constexpr u32 R_TPOFF = R_MIPS_TLS_TPREL64;
Expand All @@ -2248,7 +2265,8 @@ struct MIPS64BE {
static constexpr u32 R_COPY = R_MIPS_COPY;
static constexpr u32 R_GLOB_DAT = R_MIPS_GLOB_DAT;
static constexpr u32 R_JUMP_SLOT = R_MIPS_JUMP_SLOT;
static constexpr u32 R_ABS = R_MIPS_GLOB_DAT;
static constexpr u32 R_ABS = R_MIPS_64;
static constexpr u32 R_DYNAMIC = R_MIPS_REL32;
static constexpr u32 R_RELATIVE = R_MIPS_REL32;
static constexpr u32 R_DTPOFF = R_MIPS_TLS_DTPREL64;
static constexpr u32 R_TPOFF = R_MIPS_TLS_TPREL64;
Expand Down
2 changes: 1 addition & 1 deletion elf/input-sections.cc
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ static void apply_absrel(Context<E> &ctx, InputSection<E> &isec,
bool writable = (isec.shdr().sh_flags & SHF_WRITE);

auto emit_abs_dynrel = [&] {
*dynrel++ = ElfRel<E>(P, E::R_ABS, sym.get_dynsym_idx(ctx), A);
*dynrel++ = ElfRel<E>(P, E::R_DYNAMIC, sym.get_dynsym_idx(ctx), A);
if (ctx.arg.apply_dynamic_relocs)
*(Word<E> *)loc = A;
};
Expand Down

0 comments on commit 0df6063

Please sign in to comment.