summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoremaste <emaste@FreeBSD.org>2014-06-27 14:42:13 +0000
committeremaste <emaste@FreeBSD.org>2014-06-27 14:42:13 +0000
commitc17570f4b122b08e9ad6dc2c7a694d42444fe19f (patch)
treef411bea37e85cc154635941b43b179ab998f1e90
parent4dd240dde070d23287ceb79acd8bc4c76a1ac96b (diff)
downloadFreeBSD-src-c17570f4b122b08e9ad6dc2c7a694d42444fe19f.zip
FreeBSD-src-c17570f4b122b08e9ad6dc2c7a694d42444fe19f.tar.gz
MFC r265613, r267649: 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. Don't dump core when the ELF file has no section headers. The ELF core files created by gcore are among those.
-rw-r--r--usr.bin/elfdump/elfdump.c68
1 files changed, 55 insertions, 13 deletions
diff --git a/usr.bin/elfdump/elfdump.c b/usr.bin/elfdump/elfdump.c
index 23d1487..2f1461e 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,12 +494,20 @@ 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;
- offset = elf_get_off(e, (char *)sh + shstrndx * shentsize, SH_OFFSET);
- shstrtab = (char *)e + offset;
+ if (shoff > 0) {
+ 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;
+ } else {
+ sh = NULL;
+ shnum = 0;
+ shstrndx = 0;
+ shstrtab = NULL;
+ }
for (i = 0; (u_int64_t)i < shnum; i++) {
name = elf_get_word(e, (char *)sh + i * shentsize, SH_NAME);
offset = elf_get_off(e, (char *)sh + i * shentsize, SH_OFFSET);
@@ -482,7 +517,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 +591,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 +624,6 @@ 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);
fprintf(out, "\nelf header:\n");
fprintf(out, "\n");
fprintf(out, "\te_ident: %s %s %s\n", ei_classes[class], ei_data[data],
@@ -606,8 +639,12 @@ elf_print_ehdr(Elf32_Ehdr *e)
fprintf(out, "\te_phentsize: %jd\n", (intmax_t)phentsize);
fprintf(out, "\te_phnum: %jd\n", (intmax_t)phnum);
fprintf(out, "\te_shentsize: %jd\n", (intmax_t)shentsize);
- fprintf(out, "\te_shnum: %jd\n", (intmax_t)shnum);
- fprintf(out, "\te_shstrndx: %jd\n", (intmax_t)shstrndx);
+ if (sh != NULL) {
+ shnum = elf_get_shnum(e, sh);
+ shstrndx = elf_get_shstrndx(e, sh);
+ fprintf(out, "\te_shnum: %jd\n", (intmax_t)shnum);
+ fprintf(out, "\te_shstrndx: %jd\n", (intmax_t)shstrndx);
+ }
}
static void
@@ -670,8 +707,13 @@ elf_print_shdr(Elf32_Ehdr *e, void *sh)
void *v;
int i;
+ if (sh == NULL) {
+ fprintf(out, "\nNo section headers\n");
+ return;
+ }
+
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