Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 27 Jun 2014 14:42:13 +0000 (UTC)
From:      Ed Maste <emaste@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r267958 - stable/10/usr.bin/elfdump
Message-ID:  <201406271442.s5REgDtg020988@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: emaste
Date: Fri Jun 27 14:42:13 2014
New Revision: 267958
URL: http://svnweb.freebsd.org/changeset/base/267958

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

Modified:
  stable/10/usr.bin/elfdump/elfdump.c

Modified: stable/10/usr.bin/elfdump/elfdump.c
==============================================================================
--- stable/10/usr.bin/elfdump/elfdump.c	Fri Jun 27 13:19:03 2014	(r267957)
+++ stable/10/usr.bin/elfdump/elfdump.c	Fri Jun 27 14:42:13 2014	(r267958)
@@ -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,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;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201406271442.s5REgDtg020988>