Author: emaste
Date: Wed May  7 21:16:47 2014
New Revision: 265613
URL: http://svnweb.freebsd.org/changeset/base/265613

Log:
  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

Modified:
  head/usr.bin/elfdump/elfdump.c

Modified: head/usr.bin/elfdump/elfdump.c
==============================================================================
--- head/usr.bin/elfdump/elfdump.c      Wed May  7 21:01:35 2014        
(r265612)
+++ head/usr.bin/elfdump/elfdump.c      Wed May  7 21:16:47 2014        
(r265613)
@@ -368,7 +368,7 @@ static u_int64_t elf_get_half(Elf32_Ehdr
 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
 
 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;
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to