mirror of
https://github.com/rui314/mold.git
synced 2024-11-10 10:57:55 +03:00
Refactor
This commit is contained in:
parent
f19c242901
commit
ed0996a590
@ -73,10 +73,8 @@ static void write_thm_mov_imm(u8 *loc, u32 val) {
|
||||
}
|
||||
|
||||
template <>
|
||||
void PltSection<E>::copy_buf(Context<E> &ctx) {
|
||||
u8 *buf = ctx.buf + this->shdr.sh_offset;
|
||||
|
||||
static const ul32 plt0[] = {
|
||||
void write_plt_header(Context<E> &ctx, u8 *buf) {
|
||||
static const ul32 insn[] = {
|
||||
0xe52d'e004, // push {lr}
|
||||
0xe59f'e004, // ldr lr, 2f
|
||||
0xe08f'e00e, // 1: add lr, pc, lr
|
||||
@ -87,39 +85,27 @@ void PltSection<E>::copy_buf(Context<E> &ctx) {
|
||||
0xe320'f000, // nop
|
||||
};
|
||||
|
||||
memcpy(buf, plt0, sizeof(plt0));
|
||||
*(ul32 *)(buf + 16) = ctx.gotplt->shdr.sh_addr - this->shdr.sh_addr - 16;
|
||||
memcpy(buf, insn, sizeof(insn));
|
||||
*(ul32 *)(buf + 16) = ctx.gotplt->shdr.sh_addr - ctx.plt->shdr.sh_addr - 16;
|
||||
}
|
||||
|
||||
for (Symbol<E> *sym : symbols) {
|
||||
static const ul32 plt[] = {
|
||||
0xe59f'c004, // 1: ldr ip, 2f
|
||||
0xe08c'c00f, // add ip, ip, pc
|
||||
0xe59c'f000, // ldr pc, [ip]
|
||||
0x0000'0000, // 2: .word sym@GOTPLT - 1b
|
||||
};
|
||||
static const ul32 plt_entry[] = {
|
||||
0xe59f'c004, // 1: ldr ip, 2f
|
||||
0xe08c'c00f, // add ip, ip, pc
|
||||
0xe59c'f000, // ldr pc, [ip]
|
||||
0x0000'0000, // 2: .word sym@GOT - 1b
|
||||
};
|
||||
|
||||
u8 *ent = buf + sizeof(plt0) + sym->get_plt_idx(ctx) * sizeof(plt);
|
||||
memcpy(ent, plt, sizeof(plt));
|
||||
*(ul32 *)(ent + 12) = sym->get_gotplt_addr(ctx) - sym->get_plt_addr(ctx) - 12;
|
||||
}
|
||||
template <>
|
||||
void write_plt_entry(Context<E> &ctx, u8 *buf, Symbol<E> &sym) {
|
||||
memcpy(buf, plt_entry, sizeof(plt_entry));
|
||||
*(ul32 *)(buf + 12) = sym.get_gotplt_addr(ctx) - sym.get_plt_addr(ctx) - 12;
|
||||
}
|
||||
|
||||
template <>
|
||||
void PltGotSection<E>::copy_buf(Context<E> &ctx) {
|
||||
u8 *buf = ctx.buf + this->shdr.sh_offset;
|
||||
|
||||
for (Symbol<E> *sym : symbols) {
|
||||
static const ul32 plt[] = {
|
||||
0xe59f'c004, // 1: ldr ip, 2f
|
||||
0xe08c'c00f, // add ip, ip, pc
|
||||
0xe59c'f000, // ldr pc, [ip]
|
||||
0x0000'0000, // 2: .word sym@GOT - 1b
|
||||
};
|
||||
|
||||
u8 *ent = buf + sym->get_pltgot_idx(ctx) * sizeof(plt);
|
||||
memcpy(ent, plt, sizeof(plt));
|
||||
*(ul32 *)(ent + 12) = sym->get_got_addr(ctx) - sym->get_plt_addr(ctx) - 12;
|
||||
}
|
||||
void write_pltgot_entry(Context<E> &ctx, u8 *buf, Symbol<E> &sym) {
|
||||
memcpy(buf, plt_entry, sizeof(plt_entry));
|
||||
*(ul32 *)(buf + 12) = sym.get_got_addr(ctx) - sym.get_plt_addr(ctx) - 12;
|
||||
}
|
||||
|
||||
// ARM does not use .eh_frame for exception handling. Instead, it uses
|
||||
|
@ -41,9 +41,9 @@ static u64 page(u64 val) {
|
||||
return val & 0xffff'ffff'ffff'f000;
|
||||
}
|
||||
|
||||
static void write_plt_header(Context<E> &ctx, u8 *buf) {
|
||||
// Write PLT header
|
||||
static const ul32 plt0[] = {
|
||||
template <>
|
||||
void write_plt_header(Context<E> &ctx, u8 *buf) {
|
||||
static const ul32 insn[] = {
|
||||
0xa9bf'7bf0, // stp x16, x30, [sp,#-16]!
|
||||
0x9000'0010, // adrp x16, .got.plt[2]
|
||||
0xf940'0211, // ldr x17, [x16, .got.plt[2]]
|
||||
@ -57,16 +57,15 @@ static void write_plt_header(Context<E> &ctx, u8 *buf) {
|
||||
u64 gotplt = ctx.gotplt->shdr.sh_addr + 16;
|
||||
u64 plt = ctx.plt->shdr.sh_addr;
|
||||
|
||||
memcpy(buf, plt0, sizeof(plt0));
|
||||
memcpy(buf, insn, sizeof(insn));
|
||||
write_adrp(buf + 4, page(gotplt) - page(plt + 4));
|
||||
*(ul32 *)(buf + 8) |= bits(gotplt, 11, 3) << 10;
|
||||
*(ul32 *)(buf + 12) |= (gotplt & 0xfff) << 10;
|
||||
}
|
||||
|
||||
static void write_plt_entry(Context<E> &ctx, u8 *buf, Symbol<E> &sym) {
|
||||
u8 *ent = buf + E::plt_hdr_size + sym.get_plt_idx(ctx) * E::plt_size;
|
||||
|
||||
static const ul32 data[] = {
|
||||
template <>
|
||||
void write_plt_entry(Context<E> &ctx, u8 *buf, Symbol<E> &sym) {
|
||||
static const ul32 insn[] = {
|
||||
0x9000'0010, // adrp x16, .got.plt[n]
|
||||
0xf940'0211, // ldr x17, [x16, .got.plt[n]]
|
||||
0x9100'0210, // add x16, x16, .got.plt[n]
|
||||
@ -76,41 +75,27 @@ static void write_plt_entry(Context<E> &ctx, u8 *buf, Symbol<E> &sym) {
|
||||
u64 gotplt = sym.get_gotplt_addr(ctx);
|
||||
u64 plt = sym.get_plt_addr(ctx);
|
||||
|
||||
memcpy(ent, data, sizeof(data));
|
||||
write_adrp(ent, page(gotplt) - page(plt));
|
||||
*(ul32 *)(ent + 4) |= bits(gotplt, 11, 3) << 10;
|
||||
*(ul32 *)(ent + 8) |= (gotplt & 0xfff) << 10;
|
||||
memcpy(buf, insn, sizeof(insn));
|
||||
write_adrp(buf, page(gotplt) - page(plt));
|
||||
*(ul32 *)(buf + 4) |= bits(gotplt, 11, 3) << 10;
|
||||
*(ul32 *)(buf + 8) |= (gotplt & 0xfff) << 10;
|
||||
}
|
||||
|
||||
template <>
|
||||
void PltSection<E>::copy_buf(Context<E> &ctx) {
|
||||
u8 *buf = ctx.buf + this->shdr.sh_offset;
|
||||
write_plt_header(ctx, buf);
|
||||
for (Symbol<E> *sym : symbols)
|
||||
write_plt_entry(ctx, buf, *sym);
|
||||
}
|
||||
void write_pltgot_entry(Context<E> &ctx, u8 *buf, Symbol<E> &sym) {
|
||||
static const ul32 insn[] = {
|
||||
0x9000'0010, // adrp x16, GOT[n]
|
||||
0xf940'0211, // ldr x17, [x16, GOT[n]]
|
||||
0xd61f'0220, // br x17
|
||||
0xd503'201f, // nop
|
||||
};
|
||||
|
||||
template <>
|
||||
void PltGotSection<E>::copy_buf(Context<E> &ctx) {
|
||||
u8 *buf = ctx.buf + this->shdr.sh_offset;
|
||||
u64 got = sym.get_got_addr(ctx);
|
||||
u64 plt = sym.get_plt_addr(ctx);
|
||||
|
||||
for (Symbol<E> *sym : symbols) {
|
||||
u8 *ent = buf + sym->get_pltgot_idx(ctx) * E::pltgot_size;
|
||||
|
||||
static const ul32 data[] = {
|
||||
0x9000'0010, // adrp x16, GOT[n]
|
||||
0xf940'0211, // ldr x17, [x16, GOT[n]]
|
||||
0xd61f'0220, // br x17
|
||||
0xd503'201f, // nop
|
||||
};
|
||||
|
||||
u64 got = sym->get_got_addr(ctx);
|
||||
u64 plt = sym->get_plt_addr(ctx);
|
||||
|
||||
memcpy(ent, data, sizeof(data));
|
||||
write_adrp(ent, page(got) - page(plt));
|
||||
*(ul32 *)(ent + 4) |= bits(got, 11, 3) << 10;
|
||||
}
|
||||
memcpy(buf, insn, sizeof(insn));
|
||||
write_adrp(buf, page(got) - page(plt));
|
||||
*(ul32 *)(buf + 4) |= bits(got, 11, 3) << 10;
|
||||
}
|
||||
|
||||
template <>
|
||||
|
@ -39,89 +39,69 @@ namespace mold::elf {
|
||||
|
||||
using E = I386;
|
||||
|
||||
static void write_plt_header(Context<E> &ctx, u8 *buf) {
|
||||
template <>
|
||||
void write_plt_header(Context<E> &ctx, u8 *buf) {
|
||||
if (ctx.arg.pic) {
|
||||
static const u8 plt0[] = {
|
||||
static const u8 insn[] = {
|
||||
0xff, 0xb3, 0, 0, 0, 0, // pushl GOTPLT+4(%ebx)
|
||||
0xff, 0xa3, 0, 0, 0, 0, // jmp *GOTPLT+8(%ebx)
|
||||
0x90, 0x90, 0x90, 0x90, // nop
|
||||
};
|
||||
memcpy(buf, plt0, sizeof(plt0));
|
||||
memcpy(buf, insn, sizeof(insn));
|
||||
*(ul32 *)(buf + 2) = ctx.gotplt->shdr.sh_addr - ctx.got->shdr.sh_addr + 4;
|
||||
*(ul32 *)(buf + 8) = ctx.gotplt->shdr.sh_addr - ctx.got->shdr.sh_addr + 8;
|
||||
} else {
|
||||
static const u8 plt0[] = {
|
||||
static const u8 insn[] = {
|
||||
0xff, 0x35, 0, 0, 0, 0, // pushl GOTPLT+4
|
||||
0xff, 0x25, 0, 0, 0, 0, // jmp *GOTPLT+8
|
||||
0x90, 0x90, 0x90, 0x90, // nop
|
||||
};
|
||||
memcpy(buf, plt0, sizeof(plt0));
|
||||
memcpy(buf, insn, sizeof(insn));
|
||||
*(ul32 *)(buf + 2) = ctx.gotplt->shdr.sh_addr + 4;
|
||||
*(ul32 *)(buf + 8) = ctx.gotplt->shdr.sh_addr + 8;
|
||||
}
|
||||
}
|
||||
|
||||
static void write_plt_entry(Context<E> &ctx, u8 *buf, Symbol<E> &sym,
|
||||
i64 idx) {
|
||||
u8 *ent = buf + E::plt_hdr_size + sym.get_plt_idx(ctx) * E::plt_size;
|
||||
|
||||
template <>
|
||||
void write_plt_entry(Context<E> &ctx, u8 *buf, Symbol<E> &sym) {
|
||||
if (ctx.arg.pic) {
|
||||
static const u8 data[] = {
|
||||
static const u8 insn[] = {
|
||||
0xff, 0xa3, 0, 0, 0, 0, // jmp *foo@GOT(%ebx)
|
||||
0x68, 0, 0, 0, 0, // pushl $reloc_offset
|
||||
0xe9, 0, 0, 0, 0, // jmp .PLT0@PC
|
||||
};
|
||||
memcpy(ent, data, sizeof(data));
|
||||
*(ul32 *)(ent + 2) = sym.get_gotplt_addr(ctx) - ctx.got->shdr.sh_addr;
|
||||
memcpy(buf, insn, sizeof(insn));
|
||||
*(ul32 *)(buf + 2) = sym.get_gotplt_addr(ctx) - ctx.got->shdr.sh_addr;
|
||||
} else {
|
||||
static const u8 data[] = {
|
||||
static const u8 insn[] = {
|
||||
0xff, 0x25, 0, 0, 0, 0, // jmp *foo@GOT
|
||||
0x68, 0, 0, 0, 0, // pushl $reloc_offset
|
||||
0xe9, 0, 0, 0, 0, // jmp .PLT0@PC
|
||||
};
|
||||
memcpy(ent, data, sizeof(data));
|
||||
*(ul32 *)(ent + 2) = sym.get_gotplt_addr(ctx);
|
||||
memcpy(buf, insn, sizeof(insn));
|
||||
*(ul32 *)(buf + 2) = sym.get_gotplt_addr(ctx);
|
||||
}
|
||||
|
||||
*(ul32 *)(ent + 7) = idx * sizeof(ElfRel<E>);
|
||||
*(ul32 *)(ent + 12) = ctx.plt->shdr.sh_addr - sym.get_plt_addr(ctx) - 16;
|
||||
*(ul32 *)(buf + 7) = sym.get_plt_idx(ctx) * sizeof(ElfRel<E>);
|
||||
*(ul32 *)(buf + 12) = ctx.plt->shdr.sh_addr - sym.get_plt_addr(ctx) - 16;
|
||||
}
|
||||
|
||||
template <>
|
||||
void PltSection<E>::copy_buf(Context<E> &ctx) {
|
||||
u8 *buf = ctx.buf + this->shdr.sh_offset;
|
||||
write_plt_header(ctx, buf);
|
||||
|
||||
for (i64 i = 0; i < symbols.size(); i++)
|
||||
write_plt_entry(ctx, buf, *symbols[i], i);
|
||||
}
|
||||
|
||||
template <>
|
||||
void PltGotSection<E>::copy_buf(Context<E> &ctx) {
|
||||
u8 *buf = ctx.buf + this->shdr.sh_offset;
|
||||
|
||||
void write_pltgot_entry(Context<E> &ctx, u8 *buf, Symbol<E> &sym) {
|
||||
if (ctx.arg.pic) {
|
||||
static const u8 data[] = {
|
||||
static const u8 insn[] = {
|
||||
0xff, 0xa3, 0, 0, 0, 0, // jmp *foo@GOT(%ebx)
|
||||
0x66, 0x90, // nop
|
||||
};
|
||||
|
||||
for (i64 i = 0; i < symbols.size(); i++) {
|
||||
u8 *ent = buf + i * sizeof(data);
|
||||
memcpy(ent, data, sizeof(data));
|
||||
*(ul32 *)(ent + 2) = symbols[i]->get_got_addr(ctx) - ctx.got->shdr.sh_addr;
|
||||
}
|
||||
memcpy(buf, insn, sizeof(insn));
|
||||
*(ul32 *)(buf + 2) = sym.get_got_addr(ctx) - ctx.got->shdr.sh_addr;
|
||||
} else {
|
||||
static const u8 data[] = {
|
||||
static const u8 insn[] = {
|
||||
0xff, 0x25, 0, 0, 0, 0, // jmp *foo@GOT
|
||||
0x66, 0x90, // nop
|
||||
};
|
||||
|
||||
for (i64 i = 0; i < symbols.size(); i++) {
|
||||
u8 *ent = buf + i * sizeof(data);
|
||||
memcpy(ent, data, sizeof(data));
|
||||
*(ul32 *)(ent + 2) = symbols[i]->get_got_addr(ctx);
|
||||
}
|
||||
memcpy(buf, insn, sizeof(insn));
|
||||
*(ul32 *)(buf + 2) = sym.get_got_addr(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,10 +76,8 @@ static u64 highesta(u64 x) { return (x + 0x8000) >> 48; }
|
||||
// written to .got.plt, thunks just skip .plt and directly jump to the
|
||||
// resolved addresses.
|
||||
template <>
|
||||
void PltSection<E>::copy_buf(Context<E> &ctx) {
|
||||
u8 *buf = ctx.buf + this->shdr.sh_offset;
|
||||
|
||||
static const ul32 plt0[] = {
|
||||
void write_plt_header(Context<E> &ctx, u8 *buf) {
|
||||
static const ul32 insn[] = {
|
||||
// Get PC
|
||||
0x7c08'02a6, // mflr r0
|
||||
0x429f'0005, // bcl 1f
|
||||
@ -101,40 +99,27 @@ void PltSection<E>::copy_buf(Context<E> &ctx) {
|
||||
0x0000'0000,
|
||||
};
|
||||
|
||||
static_assert(E::plt_hdr_size == sizeof(plt0));
|
||||
memcpy(buf, plt0, sizeof(plt0));
|
||||
memcpy(buf, insn, sizeof(insn));
|
||||
*(ul64 *)(buf + 52) = ctx.gotplt->shdr.sh_addr - ctx.plt->shdr.sh_addr - 8;
|
||||
|
||||
for (i64 i = 0; i < symbols.size(); i++) {
|
||||
i64 disp = E::plt_hdr_size + i * E::plt_size;
|
||||
*(ul32 *)(buf + disp) = 0x4b00'0000 | (-disp & 0x00ff'ffff); // bl plt0
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
void PltGotSection<E>::copy_buf(Context<E> &ctx) {
|
||||
u8 *buf = ctx.buf + this->shdr.sh_offset;
|
||||
void write_plt_entry(Context<E> &ctx, u8 *buf, Symbol<E> &sym) {
|
||||
// bl plt0
|
||||
*(ul32 *)buf = 0x4b00'0000;
|
||||
*(ul32 *)buf |= (ctx.plt->shdr.sh_addr -sym.get_plt_addr(ctx)) & 0x00ff'ffff;
|
||||
}
|
||||
|
||||
static const ul32 entry[] = {
|
||||
// Save %r2 to the caller's TOC save area
|
||||
0xf841'0018, // std r2, 24(r1)
|
||||
|
||||
// Set %r12 to this PLT entry's .got.plt value and jump there
|
||||
0x3d82'0000, // addis r12, r2, 0
|
||||
0xe98c'0000, // ld r12, 0(r12)
|
||||
0x7d89'03a6, // mtctr r12
|
||||
0x4e80'0420, // bctr
|
||||
};
|
||||
|
||||
for (Symbol<E> *sym : symbols) {
|
||||
u8 *ent = buf + sym->get_pltgot_idx(ctx) * E::pltgot_size;
|
||||
memcpy(ent, entry, sizeof(entry));
|
||||
|
||||
i64 val = sym->get_got_addr(ctx) - sym->get_plt_addr(ctx) - ctx.TOC->value;
|
||||
assert(val == sign_extend(val, 31));
|
||||
*(ul32 *)(ent + 4) |= higha(val);
|
||||
*(ul32 *)(ent + 8) |= lo(val);
|
||||
}
|
||||
template <>
|
||||
void write_pltgot_entry(Context<E> &ctx, u8 *buf, Symbol<E> &sym) {
|
||||
// Just like .plt, no one uses .got.plt at runtime because all calls
|
||||
// to .got.plt are made via range extension thunks and range extension
|
||||
// thunks directly calls the final destination by reading a .got entry.
|
||||
// Here, we just set a dummy instruction.
|
||||
//
|
||||
// I believe we can completely elimnate .got.plt, but saving 4 bytes
|
||||
// for each GOTPLT entry doesn't seem to be worth its complexity.
|
||||
*(ul32 *)buf = 0x6000'0000; // nop
|
||||
}
|
||||
|
||||
template <>
|
||||
|
@ -161,10 +161,8 @@ static void set_rs1(u8 *loc, u32 rs1) {
|
||||
}
|
||||
|
||||
template <typename E>
|
||||
static void write_plt_header(Context<E> &ctx) {
|
||||
u8 *buf = ctx.buf + ctx.plt->shdr.sh_offset;
|
||||
|
||||
static const ul32 plt0_64[] = {
|
||||
void write_plt_header(Context<E> &ctx, u8 *buf) {
|
||||
static const ul32 insn_64[] = {
|
||||
0x0000'0397, // auipc t2, %pcrel_hi(.got.plt)
|
||||
0x41c3'0333, // sub t1, t1, t3 # .plt entry + hdr + 12
|
||||
0x0003'be03, // ld t3, %pcrel_lo(1b)(t2) # _dl_runtime_resolve
|
||||
@ -175,7 +173,7 @@ static void write_plt_header(Context<E> &ctx) {
|
||||
0x000e'0067, // jr t3
|
||||
};
|
||||
|
||||
static const ul32 plt0_32[] = {
|
||||
static const ul32 insn_32[] = {
|
||||
0x0000'0397, // auipc t2, %pcrel_hi(.got.plt)
|
||||
0x41c3'0333, // sub t1, t1, t3 # .plt entry + hdr + 12
|
||||
0x0003'ae03, // lw t3, %pcrel_lo(1b)(t2) # _dl_runtime_resolve
|
||||
@ -186,14 +184,14 @@ static void write_plt_header(Context<E> &ctx) {
|
||||
0x000e'0067, // jr t3
|
||||
};
|
||||
|
||||
if constexpr (E::is_64)
|
||||
memcpy(buf, plt0_64, sizeof(plt0_64));
|
||||
else
|
||||
memcpy(buf, plt0_32, sizeof(plt0_32));
|
||||
|
||||
u64 gotplt = ctx.gotplt->shdr.sh_addr;
|
||||
u64 plt = ctx.plt->shdr.sh_addr;
|
||||
|
||||
if constexpr (E::is_64)
|
||||
memcpy(buf, insn_64, sizeof(insn_64));
|
||||
else
|
||||
memcpy(buf, insn_32, sizeof(insn_32));
|
||||
|
||||
write_utype(buf, gotplt - plt);
|
||||
write_itype(buf + 8, gotplt - plt);
|
||||
write_itype(buf + 16, gotplt - plt);
|
||||
@ -214,43 +212,29 @@ static const ul32 plt_entry_32[] = {
|
||||
};
|
||||
|
||||
template <typename E>
|
||||
void PltSection<E>::copy_buf(Context<E> &ctx) {
|
||||
u8 *buf = ctx.buf + ctx.plt->shdr.sh_offset;
|
||||
void write_plt_entry(Context<E> &ctx, u8 *buf, Symbol<E> &sym) {
|
||||
if constexpr (E::is_64)
|
||||
memcpy(buf, plt_entry_64, sizeof(plt_entry_64));
|
||||
else
|
||||
memcpy(buf, plt_entry_32, sizeof(plt_entry_32));
|
||||
|
||||
write_plt_header(ctx);
|
||||
|
||||
for (Symbol<E> *sym : symbols) {
|
||||
u8 *ent = buf + E::plt_hdr_size + sym->get_plt_idx(ctx) * E::plt_size;
|
||||
u64 gotplt = sym->get_gotplt_addr(ctx);
|
||||
u64 plt = sym->get_plt_addr(ctx);
|
||||
|
||||
if constexpr (E::is_64)
|
||||
memcpy(ent, plt_entry_64, sizeof(plt_entry_64));
|
||||
else
|
||||
memcpy(ent, plt_entry_32, sizeof(plt_entry_32));
|
||||
|
||||
write_utype(ent, gotplt - plt);
|
||||
write_itype(ent + 4, gotplt - plt);
|
||||
}
|
||||
u64 gotplt = sym.get_gotplt_addr(ctx);
|
||||
u64 plt = sym.get_plt_addr(ctx);
|
||||
write_utype(buf, gotplt - plt);
|
||||
write_itype(buf + 4, gotplt - plt);
|
||||
}
|
||||
|
||||
template <typename E>
|
||||
void PltGotSection<E>::copy_buf(Context<E> &ctx) {
|
||||
u8 *buf = ctx.buf + this->shdr.sh_offset;
|
||||
void write_pltgot_entry(Context<E> &ctx, u8 *buf, Symbol<E> &sym) {
|
||||
if constexpr (E::is_64)
|
||||
memcpy(buf, plt_entry_64, sizeof(plt_entry_64));
|
||||
else
|
||||
memcpy(buf, plt_entry_32, sizeof(plt_entry_32));
|
||||
|
||||
for (Symbol<E> *sym : symbols) {
|
||||
u8 *ent = buf + sym->get_pltgot_idx(ctx) * E::pltgot_size;
|
||||
u64 got = sym->get_got_addr(ctx);
|
||||
u64 plt = sym->get_plt_addr(ctx);
|
||||
|
||||
if constexpr (E::is_64)
|
||||
memcpy(ent, plt_entry_64, sizeof(plt_entry_64));
|
||||
else
|
||||
memcpy(ent, plt_entry_32, sizeof(plt_entry_32));
|
||||
|
||||
write_utype(ent, got - plt);
|
||||
write_itype(ent + 4, got - plt);
|
||||
}
|
||||
u64 got = sym.get_got_addr(ctx);
|
||||
u64 plt = sym.get_plt_addr(ctx);
|
||||
write_utype(buf, got - plt);
|
||||
write_itype(buf + 4, got - plt);
|
||||
}
|
||||
|
||||
template <typename E>
|
||||
@ -961,8 +945,9 @@ i64 riscv_resize_sections(Context<E> &ctx) {
|
||||
}
|
||||
|
||||
#define INSTANTIATE_RISCV(E) \
|
||||
template void PltSection<E>::copy_buf(Context<E> &); \
|
||||
template void PltGotSection<E>::copy_buf(Context<E> &); \
|
||||
template void write_plt_header(Context<E> &, u8 *); \
|
||||
template void write_plt_entry(Context<E> &, u8 *, Symbol<E> &); \
|
||||
template void write_pltgot_entry(Context<E> &, u8 *, Symbol<E> &); \
|
||||
template void \
|
||||
EhFrameSection<E>::apply_reloc(Context<E> &, const ElfRel<E> &, u64, u64); \
|
||||
template void InputSection<E>::apply_reloc_alloc(Context<E> &, u8 *); \
|
||||
|
@ -76,11 +76,13 @@ using E = SPARC64;
|
||||
// Self-modifying code is nowadays considered really bad from the security
|
||||
// point of view, though.
|
||||
template <>
|
||||
void PltSection<E>::copy_buf(Context<E> &ctx) {
|
||||
u8 *buf = ctx.buf + this->shdr.sh_offset;
|
||||
memset(buf, 0, this->shdr.sh_size);
|
||||
void write_plt_header(Context<E> &ctx, u8 *buf) {
|
||||
memset(buf, 0, E::plt_hdr_size);
|
||||
}
|
||||
|
||||
static ub32 plt[] = {
|
||||
template <>
|
||||
void write_plt_entry(Context<E> &ctx, u8 *buf, Symbol<E> &sym) {
|
||||
static ub32 insn[] = {
|
||||
0x0300'0000, // sethi (. - .PLT0), %g1
|
||||
0x3068'0000, // ba,a %xcc, .PLT1
|
||||
0x0100'0000, // nop
|
||||
@ -91,26 +93,17 @@ void PltSection<E>::copy_buf(Context<E> &ctx) {
|
||||
0x0100'0000, // nop
|
||||
};
|
||||
|
||||
static_assert(sizeof(plt) == E::plt_size);
|
||||
|
||||
u64 plt0 = ctx.plt->shdr.sh_addr;
|
||||
u64 plt1 = ctx.plt->shdr.sh_addr + E::plt_size;
|
||||
u64 entry = sym.get_plt_addr(ctx);
|
||||
|
||||
for (i64 i = 0; i < symbols.size(); i++) {
|
||||
ub32 *loc = (ub32 *)(buf + E::plt_hdr_size + i * E::plt_size);
|
||||
memcpy(loc, plt, sizeof(plt));
|
||||
|
||||
u64 ent_addr = symbols[i]->get_plt_addr(ctx);
|
||||
loc[0] |= bits(ent_addr - plt0, 21, 0);
|
||||
loc[1] |= bits(plt1 - ent_addr - 4, 20, 2);
|
||||
}
|
||||
memcpy(buf, insn, sizeof(insn));
|
||||
*(ub32 *)buf |= bits(entry - plt0, 21, 0);
|
||||
*(ub32 *)(buf + 4) |= bits(plt1 - entry - 4, 20, 2);
|
||||
}
|
||||
|
||||
template <>
|
||||
void PltGotSection<E>::copy_buf(Context<E> &ctx) {
|
||||
u8 *buf = ctx.buf + this->shdr.sh_offset;
|
||||
memset(buf, 0, this->shdr.sh_size);
|
||||
|
||||
void write_pltgot_entry(Context<E> &ctx, u8 *buf, Symbol<E> &sym) {
|
||||
static ub32 entry[] = {
|
||||
0x8a10'000f, // mov %o7, %g5
|
||||
0x4000'0002, // call . + 8
|
||||
@ -122,13 +115,8 @@ void PltGotSection<E>::copy_buf(Context<E> &ctx) {
|
||||
0x0000'0000,
|
||||
};
|
||||
|
||||
static_assert(sizeof(entry) == E::pltgot_size);
|
||||
|
||||
for (Symbol<E> *sym : symbols) {
|
||||
u8 *loc = buf + sym->get_pltgot_idx(ctx) * E::pltgot_size;
|
||||
memcpy(loc, entry, sizeof(entry));
|
||||
*(ub64 *)(loc + 24) = sym->get_got_addr(ctx) - sym->get_plt_addr(ctx) - 4;
|
||||
}
|
||||
memcpy(buf, entry, sizeof(entry));
|
||||
*(ub64 *)(buf + 24) = sym.get_got_addr(ctx) - sym.get_plt_addr(ctx) - 4;
|
||||
}
|
||||
|
||||
template <>
|
||||
|
@ -44,53 +44,47 @@ using E = X86_64;
|
||||
// Our PLT entry clobbers %r11, but that's fine because the resolver
|
||||
// function (_dl_runtime_resolve) clobbers %r11 anyway.
|
||||
template <>
|
||||
void PltSection<E>::copy_buf(Context<E> &ctx) {
|
||||
u8 *buf = ctx.buf + this->shdr.sh_offset;
|
||||
memset(buf, 0xcc, this->shdr.sh_size);
|
||||
|
||||
// Write PLT header
|
||||
static const u8 plt0[] = {
|
||||
void write_plt_header(Context<E> &ctx, u8 *buf) {
|
||||
static const u8 insn[] = {
|
||||
0xf3, 0x0f, 0x1e, 0xfa, // endbr64
|
||||
0x41, 0x53, // push %r11
|
||||
0xff, 0x35, 0, 0, 0, 0, // push GOTPLT+8(%rip)
|
||||
0xff, 0x25, 0, 0, 0, 0, // jmp *GOTPLT+16(%rip)
|
||||
0xcc, 0xcc, 0xcc, 0xcc, // (padding)
|
||||
0xcc, 0xcc, 0xcc, 0xcc, // (padding)
|
||||
0xcc, 0xcc, 0xcc, 0xcc, // (padding)
|
||||
0xcc, 0xcc, // (padding)
|
||||
};
|
||||
|
||||
memcpy(buf, plt0, sizeof(plt0));
|
||||
*(ul32 *)(buf + 8) = ctx.gotplt->shdr.sh_addr - this->shdr.sh_addr - 4;
|
||||
*(ul32 *)(buf + 14) = ctx.gotplt->shdr.sh_addr - this->shdr.sh_addr - 2;
|
||||
memcpy(buf, insn, sizeof(insn));
|
||||
*(ul32 *)(buf + 8) = ctx.gotplt->shdr.sh_addr - ctx.plt->shdr.sh_addr - 4;
|
||||
*(ul32 *)(buf + 14) = ctx.gotplt->shdr.sh_addr - ctx.plt->shdr.sh_addr - 2;
|
||||
}
|
||||
|
||||
// Write PLT entries
|
||||
static const u8 data[] = {
|
||||
template <>
|
||||
void write_plt_entry(Context<E> &ctx, u8 *buf, Symbol<E> &sym) {
|
||||
static const u8 insn[] = {
|
||||
0xf3, 0x0f, 0x1e, 0xfa, // endbr64
|
||||
0x41, 0xbb, 0, 0, 0, 0, // mov $index_in_relplt, %r11d
|
||||
0xff, 0x25, 0, 0, 0, 0, // jmp *foo@GOTPLT
|
||||
};
|
||||
|
||||
for (Symbol<E> *sym : symbols) {
|
||||
i64 idx = sym->get_plt_idx(ctx);
|
||||
u8 *ent = buf + E::plt_hdr_size + idx * E::plt_size;
|
||||
memcpy(ent, data, sizeof(data));
|
||||
*(ul32 *)(ent + 6) = idx;
|
||||
*(ul32 *)(ent + 12) = sym->get_gotplt_addr(ctx) - sym->get_plt_addr(ctx) - 16;
|
||||
}
|
||||
memcpy(buf, insn, sizeof(insn));
|
||||
*(ul32 *)(buf + 6) = sym.get_plt_idx(ctx);
|
||||
*(ul32 *)(buf + 12) = sym.get_gotplt_addr(ctx) - sym.get_plt_addr(ctx) - 16;
|
||||
}
|
||||
|
||||
template <>
|
||||
void PltGotSection<E>::copy_buf(Context<E> &ctx) {
|
||||
u8 *buf = ctx.buf + this->shdr.sh_offset;
|
||||
memset(buf, 0xcc, this->shdr.sh_size);
|
||||
|
||||
static const u8 data[] = {
|
||||
void write_pltgot_entry(Context<E> &ctx, u8 *buf, Symbol<E> &sym) {
|
||||
static const u8 insn[] = {
|
||||
0xf3, 0x0f, 0x1e, 0xfa, // endbr64
|
||||
0xff, 0x25, 0, 0, 0, 0, // jmp *foo@GOT
|
||||
0xcc, 0xcc, 0xcc, 0xcc, // (padding)
|
||||
0xcc, 0xcc, // (padding)
|
||||
};
|
||||
|
||||
for (Symbol<E> *sym : symbols) {
|
||||
u8 *ent = buf + sym->get_pltgot_idx(ctx) * E::pltgot_size;
|
||||
memcpy(ent, data, sizeof(data));
|
||||
*(ul32 *)(ent + 6) = sym->get_got_addr(ctx) - sym->get_plt_addr(ctx) - 10;
|
||||
}
|
||||
memcpy(buf, insn, sizeof(insn));
|
||||
*(ul32 *)(buf + 6) = sym.get_got_addr(ctx) - sym.get_plt_addr(ctx) - 10;
|
||||
}
|
||||
|
||||
template <>
|
||||
|
@ -2515,7 +2515,7 @@ struct PPC64V2 {
|
||||
static constexpr u32 e_machine = EM_PPC64;
|
||||
static constexpr u32 plt_hdr_size = 60;
|
||||
static constexpr u32 plt_size = 4;
|
||||
static constexpr u32 pltgot_size = 20;
|
||||
static constexpr u32 pltgot_size = 4;
|
||||
static constexpr u32 tls_dtv_offset = 0x8000;
|
||||
static constexpr u32 thunk_hdr_size = 0;
|
||||
static constexpr u32 thunk_size = 20;
|
||||
|
@ -332,6 +332,15 @@ i64 to_phdr_flags(Context<E> &ctx, Chunk<E> *chunk);
|
||||
template <typename E>
|
||||
bool is_relro(Context<E> &ctx, Chunk<E> *chunk);
|
||||
|
||||
template <typename E>
|
||||
void write_plt_header(Context<E> &ctx, u8 *buf);
|
||||
|
||||
template <typename E>
|
||||
void write_plt_entry(Context<E> &ctx, u8 *buf, Symbol<E> &sym);
|
||||
|
||||
template <typename E>
|
||||
void write_pltgot_entry(Context<E> &ctx, u8 *buf, Symbol<E> &sym);
|
||||
|
||||
typedef enum { HEADER, OUTPUT_SECTION, SYNTHETIC } ChunkKind;
|
||||
|
||||
// Chunk represents a contiguous region in an output file.
|
||||
|
@ -1401,6 +1401,15 @@ void PltSection<E>::add_symbol(Context<E> &ctx, Symbol<E> *sym) {
|
||||
ctx.dynsym->add_symbol(ctx, sym);
|
||||
}
|
||||
|
||||
template <typename E>
|
||||
void PltSection<E>::copy_buf(Context<E> &ctx) {
|
||||
u8 *buf = ctx.buf + ctx.plt->shdr.sh_offset;
|
||||
write_plt_header(ctx, buf);
|
||||
|
||||
for (i64 i = 0; i < symbols.size(); i++)
|
||||
write_plt_entry(ctx, buf + E::plt_hdr_size + i * E::plt_size, *symbols[i]);
|
||||
}
|
||||
|
||||
template <typename E>
|
||||
void PltSection<E>::compute_symtab_size(Context<E> &ctx) {
|
||||
if (ctx.arg.strip_all || ctx.arg.retain_symbols_file)
|
||||
@ -1447,6 +1456,13 @@ void PltGotSection<E>::add_symbol(Context<E> &ctx, Symbol<E> *sym) {
|
||||
symbols.push_back(sym);
|
||||
}
|
||||
|
||||
template <typename E>
|
||||
void PltGotSection<E>::copy_buf(Context<E> &ctx) {
|
||||
u8 *buf = ctx.buf + ctx.pltgot->shdr.sh_offset;
|
||||
for (i64 i = 0; i < symbols.size(); i++)
|
||||
write_pltgot_entry(ctx, buf + i * E::pltgot_size, *symbols[i]);
|
||||
}
|
||||
|
||||
template <typename E>
|
||||
void PltGotSection<E>::compute_symtab_size(Context<E> &ctx) {
|
||||
if (ctx.arg.strip_all || ctx.arg.retain_symbols_file)
|
||||
|
Loading…
Reference in New Issue
Block a user