Fix performance for GOT offset lookup via a lookup table. (#6555)

This commit is contained in:
Rot127 2026-06-24 03:30:00 +00:00 committed by GitHub
parent 53e8999271
commit 2478a95874
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 47 additions and 18 deletions

View file

@ -371,6 +371,8 @@ static bool init(ELFOBJ *bin, RzBinObjectLoadOptions *options) {
bin->bits = Elf_(rz_bin_elf_get_bits)(bin);
bin->imports = Elf_(rz_bin_elf_analyse_imports)(bin);
bin->got_sym_id_off = ht_uu_new();
rz_vector_free(sections);
return true;
@ -428,6 +430,8 @@ void Elf_(rz_bin_elf_free)(RZ_NULLABLE ELFOBJ *bin) {
rz_vector_free(bin->symbols);
rz_vector_free(bin->imports);
ht_uu_free(bin->got_sym_id_off);
free(bin->elfctx);
free(bin);
}

View file

@ -245,6 +245,8 @@ struct Elf_(rz_bin_elf_obj_t) {
RzVector /*<RzBinElfSymbol>*/ *symbols; // RzVector<RzBinElfSymbol>
RzVector /*<RzBinElfSymbol>*/ *imports; // RzVector<RzBinElfSymbol>
HtUU *got_sym_id_off; ///< symbol id to GOT offset map.
};
// elf.c

View file

@ -46,6 +46,9 @@ void elf_patch_relocs_elfobj_only(ELFOBJ *obj, RzBuffer *bin_buf, ut64 baseaddr)
rz_bin_reloc_target_builder_free(targets);
return;
}
fill_got_sym_id_off_map(obj);
RzBinElfReloc *reloc;
ut64 got_addr = get_got_addr(obj);
ut64 baddr = baseaddr;

View file

@ -643,25 +643,13 @@ static ut64 get_got_addr(ELFOBJ *bin) {
* the symbol has no indirection in the GOT.
*/
RZ_IPI ut64 Elf_(rz_bin_get_reloc_sym_offset_in_got)(RZ_NONNULL ELFOBJ *bin, ut64 sym_id) {
RzBinElfSection *got = Elf_(rz_bin_elf_get_section_with_name)(bin, ".got");
if (!got) {
got = Elf_(rz_bin_elf_get_section_with_name)(bin, ".got.plt");
if (!got) {
rz_return_val_if_fail(bin, UT64_MAX);
bool found = false;
ut64 offset = ht_uu_find(bin->got_sym_id_off, sym_id, &found);
if (!found) {
return UT64_MAX;
}
}
// Search all entries of the GOT for the matching symbol id.
RzBinElfReloc *reloc;
rz_bin_elf_foreach_relocs(bin, reloc) {
if (!RZ_BETWEEN(got->rva, reloc->vaddr, got->rva + got->size)) {
// Not a GOT entry.
continue;
}
if (sym_id == reloc->sym) {
return reloc->offset;
}
}
return UT64_MAX;
return offset;
}
static void patch_relocs_obj(ELFOBJ *bin, ut64 baddr, RzBuffer *patch_buf) {
@ -725,6 +713,37 @@ static void patch_relocs_obj(ELFOBJ *bin, ut64 baddr, RzBuffer *patch_buf) {
rz_buf_sparse_set_write_mode(bin->buf_patched, RZ_BUF_SPARSE_WRITE_MODE_THROUGH);
}
static void fill_got_sym_id_off_map(ELFOBJ *obj) {
RzBinElfReloc *reloc;
if (ht_uu_size(obj->got_sym_id_off) > 0) {
// Already loaded by another ELF plugin callback.
return;
}
// Fill symbol id -> GOT offset map.
RzBinElfSection *got = Elf_(rz_bin_elf_get_section_with_name)(obj, ".got");
if (got) {
rz_bin_elf_foreach_relocs(obj, reloc) {
if (!RZ_BETWEEN(got->rva, reloc->vaddr, got->rva + got->size)) {
// Not a GOT entry.
continue;
}
ht_uu_insert(obj->got_sym_id_off, reloc->sym, reloc->offset);
}
}
got = Elf_(rz_bin_elf_get_section_with_name)(obj, ".got.plt");
if (!got) {
return;
}
rz_bin_elf_foreach_relocs(obj, reloc) {
if (!RZ_BETWEEN(got->rva, reloc->vaddr, got->rva + got->size)) {
// Not a GOT entry.
continue;
}
ht_uu_insert(obj->got_sym_id_off, reloc->sym, reloc->offset);
}
}
static void patch_relocs(RzBinFile *bf, ELFOBJ *bin) {
rz_return_if_fail(bf && bin);
RzBinObject *obj = bf->o;
@ -744,6 +763,7 @@ static RzPVector /*<RzBinVirtualFile *>*/ *virtual_files(RzBinFile *bf) {
if (!obj) {
return r;
}
fill_got_sym_id_off_map(obj);
patch_relocs(bf, obj);
// virtual file for reloc targets (where the relocs will point into)
ut64 rtmsz = reloc_targets_vfile_size(bf, obj);