summaryrefslogtreecommitdiffstats
path: root/usr.bin/elfdump/elfdump.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/elfdump/elfdump.c')
-rw-r--r--usr.bin/elfdump/elfdump.c43
1 files changed, 35 insertions, 8 deletions
diff --git a/usr.bin/elfdump/elfdump.c b/usr.bin/elfdump/elfdump.c
index 23d1487..c86e6fc 100644
--- a/usr.bin/elfdump/elfdump.c
+++ b/usr.bin/elfdump/elfdump.c
@@ -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;
OpenPOWER on IntegriCloud