diff --git a/mold.h b/mold.h index fad3d912..d797ef85 100644 --- a/mold.h +++ b/mold.h @@ -90,6 +90,7 @@ struct SymbolAux { i32 tlsdesc_idx = -1; i32 plt_idx = -1; i32 pltgot_idx = -1; + i32 iplt_idx = -1; i32 dynsym_idx = -1; }; @@ -1487,6 +1488,12 @@ public: ctx.symbol_aux[aux_idx].pltgot_idx = idx; } + void set_iplt_idx(Context &ctx, i32 idx) const { + assert(aux_idx != -1); + assert(ctx.symbol_aux[aux_idx].iplt_idx < 0); + ctx.symbol_aux[aux_idx].iplt_idx = idx; + } + void set_dynsym_idx(Context &ctx, i32 idx) const { assert(aux_idx != -1); assert(ctx.symbol_aux[aux_idx].dynsym_idx < 0); @@ -1521,6 +1528,10 @@ public: return (aux_idx == -1) ? -1 : ctx.symbol_aux[aux_idx].pltgot_idx; } + i32 get_iplt_idx(Context &ctx) const { + return (aux_idx == -1) ? -1 : ctx.symbol_aux[aux_idx].iplt_idx; + } + i32 get_dynsym_idx(Context &ctx) const { return (aux_idx == -1) ? -1 : ctx.symbol_aux[aux_idx].dynsym_idx; } diff --git a/output_chunks.cc b/output_chunks.cc index 4a341047..8ec9e65b 100644 --- a/output_chunks.cc +++ b/output_chunks.cc @@ -745,7 +745,13 @@ void GotPltSection::copy_buf(Context &ctx) { template void GotIpltSection::copy_buf(Context &ctx) { - // TODO + typename E::word *buf = (typename E::word *)(ctx.buf + this->shdr.sh_offset); + + if (E::rel_type == SHT_REL) { + std::span *> syms = ctx.iplt->symbols; + for (i64 i = 0; i < syms.size(); i++) + buf[i] = syms[i]->input_section->get_addr() + syms[i]->value; + } } template @@ -770,12 +776,27 @@ void PltSection::add_symbol(Context &ctx, Symbol *sym) { template void IpltSection::add_symbol(Context &ctx, Symbol *sym) { - // TODO + sym->set_iplt_idx(ctx, this->shdr.sh_size / E::pltgot_size); + this->shdr.sh_size += E::pltgot_size; + symbols.push_back(sym); + + ctx.gotiplt->shdr.sh_size += E::got_size; } template void IpltSection::copy_buf(Context &ctx) { - // TODO + u8 *buf = ctx.buf + this->shdr.sh_offset; + + static const u8 data[] = { + 0xff, 0x25, 0, 0, 0, 0, // jmp *foo@IGOT + 0x66, 0x90, // nop + }; + + for (i64 i = 0; i < symbols.size(); i++) { + u8 *ent = buf + i * E::pltgot_size; + memcpy(ent, data, sizeof(data)); + *(u32 *)(ent + 2) = ctx.gotiplt->shdr.sh_addr + i * E::got_size - 6; + } } template