Skip to content

Commit 28fe1d7

Browse files
samitolvanenPeter Zijlstra
authored andcommitted
objtool: use gelf_getsymshndx to handle >64k sections
Currently, objtool fails to load the correct section for symbols when the index is greater than SHN_LORESERVE. Use gelf_getsymshndx instead of gelf_getsym to handle >64k sections. Signed-off-by: Sami Tolvanen <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Reviewed-by: Kees Cook <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent ab3852a commit 28fe1d7

File tree

1 file changed

+17
-7
lines changed

1 file changed

+17
-7
lines changed

tools/objtool/elf.c

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -343,19 +343,25 @@ static int read_sections(struct elf *elf)
343343

344344
static int read_symbols(struct elf *elf)
345345
{
346-
struct section *symtab, *sec;
346+
struct section *symtab, *symtab_shndx, *sec;
347347
struct symbol *sym, *pfunc;
348348
struct list_head *entry;
349349
struct rb_node *pnode;
350350
int symbols_nr, i;
351351
char *coldstr;
352+
Elf_Data *shndx_data = NULL;
353+
Elf32_Word shndx;
352354

353355
symtab = find_section_by_name(elf, ".symtab");
354356
if (!symtab) {
355357
WARN("missing symbol table");
356358
return -1;
357359
}
358360

361+
symtab_shndx = find_section_by_name(elf, ".symtab_shndx");
362+
if (symtab_shndx)
363+
shndx_data = symtab_shndx->data;
364+
359365
symbols_nr = symtab->sh.sh_size / symtab->sh.sh_entsize;
360366

361367
for (i = 0; i < symbols_nr; i++) {
@@ -369,8 +375,9 @@ static int read_symbols(struct elf *elf)
369375

370376
sym->idx = i;
371377

372-
if (!gelf_getsym(symtab->data, i, &sym->sym)) {
373-
WARN_ELF("gelf_getsym");
378+
if (!gelf_getsymshndx(symtab->data, shndx_data, i, &sym->sym,
379+
&shndx)) {
380+
WARN_ELF("gelf_getsymshndx");
374381
goto err;
375382
}
376383

@@ -384,10 +391,13 @@ static int read_symbols(struct elf *elf)
384391
sym->type = GELF_ST_TYPE(sym->sym.st_info);
385392
sym->bind = GELF_ST_BIND(sym->sym.st_info);
386393

387-
if (sym->sym.st_shndx > SHN_UNDEF &&
388-
sym->sym.st_shndx < SHN_LORESERVE) {
389-
sym->sec = find_section_by_index(elf,
390-
sym->sym.st_shndx);
394+
if ((sym->sym.st_shndx > SHN_UNDEF &&
395+
sym->sym.st_shndx < SHN_LORESERVE) ||
396+
(shndx_data && sym->sym.st_shndx == SHN_XINDEX)) {
397+
if (sym->sym.st_shndx != SHN_XINDEX)
398+
shndx = sym->sym.st_shndx;
399+
400+
sym->sec = find_section_by_index(elf, shndx);
391401
if (!sym->sec) {
392402
WARN("couldn't find section for symbol %s",
393403
sym->name);

0 commit comments

Comments
 (0)