From 8d81cc8517f2c30bb3fb99cf2241b1ba35afdae0 Mon Sep 17 00:00:00 2001 From: Artem Savkov Date: Tue, 12 Jan 2021 17:15:45 +0100 Subject: [PATCH] kpatch-elf: symtab_shndx support Symbol indexes over 64k don't fit into st_shndx and are stored in extended symbol table. Make sure we properly handle these cases. It is not normally useful during kpatch builds but will come up if we start diffing linked objects. Signed-off-by: Artem Savkov Signed-off-by: Josh Poimboeuf --- kpatch-build/kpatch-elf.c | 19 +++++++++++++++---- kpatch-build/kpatch-elf.h | 1 + 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/kpatch-build/kpatch-elf.c b/kpatch-build/kpatch-elf.c index b9d46a3..c6ef6f1 100644 --- a/kpatch-build/kpatch-elf.c +++ b/kpatch-build/kpatch-elf.c @@ -263,6 +263,10 @@ void kpatch_create_section_list(struct kpatch_elf *kelf) sec->index = (unsigned int)elf_ndxscn(scn); + + if (sec->sh.sh_type == SHT_SYMTAB_SHNDX) + kelf->symtab_shndx = sec->data; + log_debug("ndx %02d, data %p, size %zu, name %s\n", sec->index, sec->data->d_buf, sec->data->d_size, sec->name); @@ -278,6 +282,7 @@ void kpatch_create_symbol_list(struct kpatch_elf *kelf) struct section *symtab; struct symbol *sym; unsigned int symbols_nr, index = 0; + Elf32_Word shndx; symtab = find_section_by_name(&kelf->sections, ".symtab"); if (!symtab) @@ -305,10 +310,16 @@ void kpatch_create_symbol_list(struct kpatch_elf *kelf) sym->type = GELF_ST_TYPE(sym->sym.st_info); sym->bind = GELF_ST_BIND(sym->sym.st_info); - if (sym->sym.st_shndx > SHN_UNDEF && - sym->sym.st_shndx < SHN_LORESERVE) { - sym->sec = find_section_by_index(&kelf->sections, - sym->sym.st_shndx); + shndx = sym->sym.st_shndx; + if (shndx == SHN_XINDEX && + !gelf_getsymshndx(symtab->data, kelf->symtab_shndx, sym->index, &sym->sym, &shndx)) + ERROR("couldn't find extended section index for symbol %s; idx=%d", + sym->name, sym->index); + + if ((sym->sym.st_shndx > SHN_UNDEF && + sym->sym.st_shndx < SHN_LORESERVE) || + sym->sym.st_shndx == SHN_XINDEX) { + sym->sec = find_section_by_index(&kelf->sections, shndx); if (!sym->sec) ERROR("couldn't find section for symbol %s\n", sym->name); diff --git a/kpatch-build/kpatch-elf.h b/kpatch-build/kpatch-elf.h index b3cec43..a593f9c 100644 --- a/kpatch-build/kpatch-elf.h +++ b/kpatch-build/kpatch-elf.h @@ -120,6 +120,7 @@ struct kpatch_elf { struct list_head sections; struct list_head symbols; struct list_head strings; + Elf_Data *symtab_shndx; int fd; };