Handle ELF files with 65280 or more sections

If e_shnum or e_shstrndx are at least SHN_LORESERVE (0xff00) then an
escape value is used to indicate that the actual value is found in one
of section 0's fields.

Sponsored by:	DARPA, AFRL
This commit is contained in:
Ed Maste 2014-05-07 21:16:47 +00:00
parent adb7cfe32b
commit 97a9b0b123
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=265613

View File

@ -368,7 +368,7 @@ static u_int64_t elf_get_half(Elf32_Ehdr *e, void *base, elf_member_t member);
static u_int64_t elf_get_word(Elf32_Ehdr *e, void *base, elf_member_t member);
static u_int64_t elf_get_quad(Elf32_Ehdr *e, void *base, elf_member_t member);
static void elf_print_ehdr(Elf32_Ehdr *e);
static void elf_print_ehdr(Elf32_Ehdr *e, void *sh);
static void elf_print_phdr(Elf32_Ehdr *e, void *p);
static void elf_print_shdr(Elf32_Ehdr *e, void *sh);
static void elf_print_symtab(Elf32_Ehdr *e, void *sh, char *str);
@ -382,6 +382,33 @@ static void elf_print_note(Elf32_Ehdr *e, void *sh);
static void usage(void);
/*
* Helpers for ELF files with shnum or shstrndx values that don't fit in the
* ELF header. If the values are too large then an escape value is used to
* indicate that the actual value is found in one of section 0's fields.
*/
static uint64_t
elf_get_shnum(Elf32_Ehdr *e, void *sh)
{
uint64_t shnum;
shnum = elf_get_quarter(e, e, E_SHNUM);
if (shnum == 0)
shnum = elf_get_word(e, (char *)sh, SH_SIZE);
return shnum;
}
static uint64_t
elf_get_shstrndx(Elf32_Ehdr *e, void *sh)
{
uint64_t shstrndx;
shstrndx = elf_get_quarter(e, e, E_SHSTRNDX);
if (shstrndx == SHN_XINDEX)
shstrndx = elf_get_word(e, (char *)sh, SH_LINK);
return shstrndx;
}
int
main(int ac, char **av)
{
@ -467,10 +494,10 @@ main(int ac, char **av)
phentsize = elf_get_quarter(e, e, E_PHENTSIZE);
phnum = elf_get_quarter(e, e, E_PHNUM);
shentsize = elf_get_quarter(e, e, E_SHENTSIZE);
shnum = elf_get_quarter(e, e, E_SHNUM);
shstrndx = elf_get_quarter(e, e, E_SHSTRNDX);
p = (char *)e + phoff;
sh = (char *)e + shoff;
shnum = elf_get_shnum(e, sh);
shstrndx = elf_get_shstrndx(e, sh);
offset = elf_get_off(e, (char *)sh + shstrndx * shentsize, SH_OFFSET);
shstrtab = (char *)e + offset;
for (i = 0; (u_int64_t)i < shnum; i++) {
@ -482,7 +509,7 @@ main(int ac, char **av)
dynstr = (char *)e + offset;
}
if (flags & ED_EHDR)
elf_print_ehdr(e);
elf_print_ehdr(e, sh);
if (flags & ED_PHDR)
elf_print_phdr(e, p);
if (flags & ED_SHDR)
@ -556,7 +583,7 @@ main(int ac, char **av)
}
static void
elf_print_ehdr(Elf32_Ehdr *e)
elf_print_ehdr(Elf32_Ehdr *e, void *sh)
{
u_int64_t class;
u_int64_t data;
@ -589,8 +616,8 @@ elf_print_ehdr(Elf32_Ehdr *e)
phentsize = elf_get_quarter(e, e, E_PHENTSIZE);
phnum = elf_get_quarter(e, e, E_PHNUM);
shentsize = elf_get_quarter(e, e, E_SHENTSIZE);
shnum = elf_get_quarter(e, e, E_SHNUM);
shstrndx = elf_get_quarter(e, e, E_SHSTRNDX);
shnum = elf_get_shnum(e, sh);
shstrndx = elf_get_shstrndx(e, sh);
fprintf(out, "\nelf header:\n");
fprintf(out, "\n");
fprintf(out, "\te_ident: %s %s %s\n", ei_classes[class], ei_data[data],
@ -671,7 +698,7 @@ elf_print_shdr(Elf32_Ehdr *e, void *sh)
int i;
shentsize = elf_get_quarter(e, e, E_SHENTSIZE);
shnum = elf_get_quarter(e, e, E_SHNUM);
shnum = elf_get_shnum(e, sh);
fprintf(out, "\nsection header:\n");
for (i = 0; (u_int64_t)i < shnum; i++) {
v = (char *)sh + i * shentsize;