This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Use elf_getphdrnum instead of accessing ehdr->e_phnum directly.


Using elf_getphdrnum lets us handle ELF files that use more than PN_XNUM
phdrs. And guards against some corrupt files.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
---
 backends/ChangeLog      |  7 +++++++
 backends/ppc64_symbol.c |  3 +--
 backends/ppc_symbol.c   | 16 ++++++++++------
 libdwfl/ChangeLog       |  5 +++++
 libdwfl/link_map.c      | 18 +++++++++++++++---
 libebl/ChangeLog        |  7 +++++++
 libebl/ebl-hooks.h      |  2 +-
 libebl/eblbsspltp.c     |  7 +++----
 libebl/eblopenbackend.c |  5 ++---
 libebl/libebl.h         |  2 +-
 src/ChangeLog           | 12 ++++++++++++
 src/elflint.c           |  2 +-
 src/findtextrel.c       | 14 ++++++++++----
 src/readelf.c           |  7 +------
 src/size.c              |  7 +++----
 src/strip.c             | 13 +++++++++----
 src/unstrip.c           | 26 +++++++++++++++++++-------
 17 files changed, 107 insertions(+), 46 deletions(-)

diff --git a/backends/ChangeLog b/backends/ChangeLog
index abd22bf..db1b129 100644
--- a/backends/ChangeLog
+++ b/backends/ChangeLog
@@ -1,3 +1,10 @@
+2014-11-22  Mark Wielaard  <mjw@redhat.com>
+
+	* ppc64_symbol.c (ppc64_bss_plt_p): Remove ehdr argument.
+	* ppc_symbol.c (find_dyn_got): Likewise. Use elf_getphdrnum.
+	(ppc_check_special_symbol): Call find_dyn_got without ehdr.
+	(ppc_bss_plt_p): Remove ehdr argument.
+
 2014-11-17  Mark Wielaard  <mjw@redhat.com>
 
 	* ppc64_init.c (ppc64_init): Check section name is not NULL.
diff --git a/backends/ppc64_symbol.c b/backends/ppc64_symbol.c
index 5a020d8..0feddce 100644
--- a/backends/ppc64_symbol.c
+++ b/backends/ppc64_symbol.c
@@ -108,8 +108,7 @@ ppc64_check_special_symbol (Elf *elf, GElf_Ehdr *ehdr,
 
 /* Check if backend uses a bss PLT in this file.  */
 bool
-ppc64_bss_plt_p (Elf *elf __attribute__ ((unused)),
-		 GElf_Ehdr *ehdr __attribute__ ((unused)))
+ppc64_bss_plt_p (Elf *elf __attribute__ ((unused)))
 {
   return true;
 }
diff --git a/backends/ppc_symbol.c b/backends/ppc_symbol.c
index 220f243..c17ab37 100644
--- a/backends/ppc_symbol.c
+++ b/backends/ppc_symbol.c
@@ -1,5 +1,5 @@
 /* PPC specific symbolic name handling.
-   Copyright (C) 2004, 2005, 2007 Red Hat, Inc.
+   Copyright (C) 2004, 2005, 2007, 2014 Red Hat, Inc.
    This file is part of elfutils.
    Written by Ulrich Drepper <drepper@redhat.com>, 2004.
 
@@ -81,9 +81,13 @@ ppc_dynamic_tag_check (int64_t tag)
 
 /* Look for DT_PPC_GOT.  */
 static bool
-find_dyn_got (Elf *elf, GElf_Ehdr *ehdr, GElf_Addr *addr)
+find_dyn_got (Elf *elf, GElf_Addr *addr)
 {
-  for (int i = 0; i < ehdr->e_phnum; ++i)
+  size_t phnum;
+  if (elf_getphdrnum (elf, &phnum) != 0)
+    return false;
+
+  for (size_t i = 0; i < phnum; ++i)
     {
       GElf_Phdr phdr_mem;
       GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem);
@@ -127,7 +131,7 @@ ppc_check_special_symbol (Elf *elf, GElf_Ehdr *ehdr, const GElf_Sym *sym,
     {
       /* In -msecure-plt mode, DT_PPC_GOT is present and must match.  */
       GElf_Addr gotaddr;
-      if (find_dyn_got (elf, ehdr, &gotaddr))
+      if (find_dyn_got (elf, &gotaddr))
 	return sym->st_value == gotaddr;
 
       /* In -mbss-plt mode, any place in the section is valid.  */
@@ -154,8 +158,8 @@ ppc_check_special_symbol (Elf *elf, GElf_Ehdr *ehdr, const GElf_Sym *sym,
 
 /* Check if backend uses a bss PLT in this file.  */
 bool
-ppc_bss_plt_p (Elf *elf, GElf_Ehdr *ehdr)
+ppc_bss_plt_p (Elf *elf)
 {
   GElf_Addr addr;
-  return ! find_dyn_got (elf, ehdr, &addr);
+  return ! find_dyn_got (elf, &addr);
 }
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index 460f4e5..5876fcc 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,8 @@
+2014-11-22  Mark Wielaard  <mjw@redhat.com>
+
+	* link_map.c (consider_executable): Use elf_getphdrnum.
+	(dwfl_link_map_report): Likewise.
+
 2014-11-18  Mark Wielaard  <mjw@redhat.com>
 
 	* dwfl_module_getdwarf.c (find_symtab): Sanity check the data buffer,
diff --git a/libdwfl/link_map.c b/libdwfl/link_map.c
index 272f89b..eaf43b5 100644
--- a/libdwfl/link_map.c
+++ b/libdwfl/link_map.c
@@ -1,5 +1,5 @@
 /* Report modules by examining dynamic linker data structures.
-   Copyright (C) 2008-2013 Red Hat, Inc.
+   Copyright (C) 2008-2014 Red Hat, Inc.
    This file is part of elfutils.
 
    This file is free software; you can redistribute it and/or modify
@@ -533,7 +533,11 @@ consider_executable (Dwfl_Module *mod, GElf_Addr at_phdr, GElf_Addr at_entry,
      address where &r_debug was written at runtime.  */
   GElf_Xword align = mod->dwfl->segment_align;
   GElf_Addr d_val_vaddr = 0;
-  for (uint_fast16_t i = 0; i < ehdr.e_phnum; ++i)
+  size_t phnum;
+  if (elf_getphdrnum (mod->main.elf, &phnum) != 0)
+    return 0;
+
+  for (size_t i = 0; i < phnum; ++i)
     {
       GElf_Phdr phdr_mem;
       GElf_Phdr *phdr = gelf_getphdr (mod->main.elf, i, &phdr_mem);
@@ -813,7 +817,15 @@ dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size,
 		  __libdwfl_seterrno (DWFL_E_LIBELF);
 		  return false;
 		}
-	      if (ehdr->e_phnum != phnum || ehdr->e_phentsize != phent)
+	      size_t e_phnum;
+	      if (elf_getphdrnum (elf, &e_phnum) != 0)
+		{
+		  elf_end (elf);
+		  close (fd);
+		  __libdwfl_seterrno (DWFL_E_LIBELF);
+		  return false;
+		}
+	      if (e_phnum != phnum || ehdr->e_phentsize != phent)
 		{
 		  elf_end (elf);
 		  close (fd);
diff --git a/libebl/ChangeLog b/libebl/ChangeLog
index b6a0e63..5e635f2 100644
--- a/libebl/ChangeLog
+++ b/libebl/ChangeLog
@@ -1,3 +1,10 @@
+2014-11-22  Mark Wielaard  <mjw@redhat.com>
+
+	* ebl-hooks.h (bss_plt_p): Remove ehdr argument.
+	* eblbsspltp.c (ebl_bss_plt_p): Likewise.
+	* eblopenbackend.c (default_bss_plt_p): Likewise.
+	* libebl.h (ebl_bss_plt_p): Likewise.
+
 2014-11-17  Mark Wielaard  <mjw@redhat.com>
 
 	* ebldebugscnp.c (ebl_debugscn_p): Check name is not NULL.
diff --git a/libebl/ebl-hooks.h b/libebl/ebl-hooks.h
index e1186f8..2e31446 100644
--- a/libebl/ebl-hooks.h
+++ b/libebl/ebl-hooks.h
@@ -132,7 +132,7 @@ bool EBLHOOK(check_special_symbol) (Elf *, GElf_Ehdr *, const GElf_Sym *,
 bool EBLHOOK(check_st_other_bits) (unsigned char st_other);
 
 /* Check if backend uses a bss PLT in this file.  */
-bool EBLHOOK(bss_plt_p) (Elf *, GElf_Ehdr *);
+bool EBLHOOK(bss_plt_p) (Elf *);
 
 /* Return location expression to find return value given the
    DW_AT_type DIE of a DW_TAG_subprogram DIE.  */
diff --git a/libebl/eblbsspltp.c b/libebl/eblbsspltp.c
index 080e7c5..95a5d8a 100644
--- a/libebl/eblbsspltp.c
+++ b/libebl/eblbsspltp.c
@@ -1,5 +1,5 @@
 /* Check if backend uses a bss PLT.
-   Copyright (C) 2005 Red Hat, Inc.
+   Copyright (C) 2005, 2014 Red Hat, Inc.
    This file is part of elfutils.
 
    This file is free software; you can redistribute it and/or modify
@@ -35,9 +35,8 @@
 
 
 bool
-ebl_bss_plt_p (ebl, ehdr)
+ebl_bss_plt_p (ebl)
      Ebl *ebl;
-     GElf_Ehdr *ehdr;
 {
-  return ebl == NULL ? false : ebl->bss_plt_p (ebl->elf, ehdr);
+  return ebl == NULL ? false : ebl->bss_plt_p (ebl->elf);
 }
diff --git a/libebl/eblopenbackend.c b/libebl/eblopenbackend.c
index bd94759..3a22f53 100644
--- a/libebl/eblopenbackend.c
+++ b/libebl/eblopenbackend.c
@@ -186,7 +186,7 @@ static bool default_check_special_symbol (Elf *elf, GElf_Ehdr *ehdr,
 static bool default_check_st_other_bits (unsigned char st_other);
 static bool default_check_special_section (Ebl *, int,
 					   const GElf_Shdr *, const char *);
-static bool default_bss_plt_p (Elf *elf, GElf_Ehdr *ehdr);
+static bool default_bss_plt_p (Elf *elf);
 static int default_return_value_location (Dwarf_Die *functypedie,
 					  const Dwarf_Op **locops);
 static ssize_t default_register_info (Ebl *ebl,
@@ -693,8 +693,7 @@ default_check_st_other_bits (unsigned char st_other __attribute__ ((unused)))
 
 
 static bool
-default_bss_plt_p (Elf *elf __attribute__ ((unused)),
-		   GElf_Ehdr *ehdr __attribute__ ((unused)))
+default_bss_plt_p (Elf *elf __attribute__ ((unused)))
 {
   return false;
 }
diff --git a/libebl/libebl.h b/libebl/libebl.h
index bb993bf..7c3c764 100644
--- a/libebl/libebl.h
+++ b/libebl/libebl.h
@@ -201,7 +201,7 @@ extern bool ebl_section_strip_p (Ebl *ebl, const GElf_Ehdr *ehdr,
 				 bool remove_comment, bool only_remove_debug);
 
 /* Check if backend uses a bss PLT in this file.  */
-extern bool ebl_bss_plt_p (Ebl *ebl, GElf_Ehdr *ehdr);
+extern bool ebl_bss_plt_p (Ebl *ebl);
 
 /* Return size of entry in SysV-style hash table.  */
 extern int ebl_sysvhash_entrysize (Ebl *ebl);
diff --git a/src/ChangeLog b/src/ChangeLog
index bab948a..bace91d 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,15 @@
+2014-11-22  Mark Wielaard  <mjw@redhat.com>
+
+	* elflint.c (check_sections): Call ebl_bss_plt_p without ehdr.
+	* findtextrel.c (process_file): Use elf_getphdrnum.
+	* readelf.c (process_elf_file): Remove redundant ehdr->e_phoff check.
+	(print_phdr): Check phnum.
+	* size.c (show_segments): Use elf_getphdrnum.
+	* strip.c (handle_elf): Likewise.
+	* unstrip.c (copy_elf): Likewise.
+	(copy_elided_sections): Likewise.
+	(handle_file): Likewise.
+
 2014-11-18  Mark Wielaard  <mjw@redhat.com>
 
 	* readelf.c (print_cfa_program): Fix sanity check of DW_FORM_block
diff --git a/src/elflint.c b/src/elflint.c
index d6a4774..fbc78ed 100644
--- a/src/elflint.c
+++ b/src/elflint.c
@@ -3532,7 +3532,7 @@ cannot get section header for section [%2zu] '%s': %s\n"),
 
 		GElf_Word good_type = special_sections[s].type;
 		if (IS_KNOWN_SPECIAL (s, ".plt", false)
-		    && ebl_bss_plt_p (ebl, ehdr))
+		    && ebl_bss_plt_p (ebl))
 		  good_type = SHT_NOBITS;
 
 		/* In a debuginfo file, any normal section can be SHT_NOBITS.
diff --git a/src/findtextrel.c b/src/findtextrel.c
index 9fd8163..264a06b 100644
--- a/src/findtextrel.c
+++ b/src/findtextrel.c
@@ -1,5 +1,5 @@
 /* Locate source files or functions which caused text relocations.
-   Copyright (C) 2005-2010, 2012 Red Hat, Inc.
+   Copyright (C) 2005-2010, 2012, 2014 Red Hat, Inc.
    This file is part of elfutils.
    Written by Ulrich Drepper <drepper@redhat.com>, 2005.
 
@@ -324,14 +324,20 @@ process_file (const char *fname, bool more_than_one)
   if (segments == NULL)
     error (1, errno, gettext ("while reading ELF file"));
 
-  for (int i = 0; i < ehdr->e_phnum; ++i)
+  size_t phnum;
+  if (elf_getphdrnum (elf, &phnum) != 0)
+    error (1, 0, gettext ("cannot get program header count: %s"),
+           elf_errmsg (-1));
+
+
+  for (size_t i = 0; i < phnum; ++i)
     {
       GElf_Phdr phdr_mem;
       GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem);
       if (phdr == NULL)
 	{
 	  error (0, 0,
-		 gettext ("cannot get program header index at offset %d: %s"),
+		 gettext ("cannot get program header index at offset %zd: %s"),
 		 i, elf_errmsg (-1));
 	  result = 1;
 	  goto next;
@@ -349,7 +355,7 @@ process_file (const char *fname, bool more_than_one)
 	      if (segments == NULL)
 		{
 		  error (0, 0, gettext ("\
-cannot get program header index at offset %d: %s"),
+cannot get program header index at offset %zd: %s"),
 			 i, elf_errmsg (-1));
 		  result = 1;
 		  goto next;
diff --git a/src/readelf.c b/src/readelf.c
index 08de798..3b1f035 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -835,11 +835,6 @@ process_elf_file (Dwfl_Module *dwflmod, int fd)
 	   gettext ("cannot determine number of program headers: %s"),
 	   elf_errmsg (-1));
 
-  /* If there isn't actually a program header then set phnum to zero.
-     Don't do any extra work.  gelf_getphdr will always return NULL.  */
-  if (ehdr->e_phoff == 0)
-    phnum = 0;
-
   /* For an ET_REL file, libdwfl has adjusted the in-core shdrs
      and may have applied relocation to some sections.
      So we need to get a fresh Elf handle on the file to display those.  */
@@ -1162,7 +1157,7 @@ There are %d section headers, starting at offset %#" PRIx64 ":\n\
 static void
 print_phdr (Ebl *ebl, GElf_Ehdr *ehdr)
 {
-  if (ehdr->e_phnum == 0 || ehdr->e_phoff == 0)
+  if (phnum == 0)
     /* No program header, this is OK in relocatable objects.  */
     return;
 
diff --git a/src/size.c b/src/size.c
index cb67999..0e7e41e 100644
--- a/src/size.c
+++ b/src/size.c
@@ -600,14 +600,13 @@ show_bsd_totals (void)
 static void
 show_segments (Elf *elf, const char *fullname)
 {
-  GElf_Ehdr ehdr_mem;
-  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
-  if (ehdr == NULL)
+  size_t phnum;
+  if (elf_getphdrnum (elf, &phnum) != 0)
     INTERNAL_ERROR (fullname);
 
   GElf_Off total = 0;
   bool first = true;
-  for (size_t cnt = 0; cnt < ehdr->e_phnum; ++cnt)
+  for (size_t cnt = 0; cnt < phnum; ++cnt)
     {
       GElf_Phdr phdr_mem;
       GElf_Phdr *phdr;
diff --git a/src/strip.c b/src/strip.c
index c9a1d8d..2b21799 100644
--- a/src/strip.c
+++ b/src/strip.c
@@ -502,6 +502,11 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
     error (EXIT_FAILURE, 0,
 	   gettext ("cannot get section header string table index"));
 
+  /* Get the number of phdrs in the old file.  */
+  size_t phnum;
+  if (elf_getphdrnum (elf, &phnum) != 0)
+    error (EXIT_FAILURE, 0, gettext ("cannot get number of phdrs"));
+
   /* We now create a new ELF descriptor for the same file.  We
      construct it almost exactly in the same way with some information
      dropped.  */
@@ -513,7 +518,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
 
   if (unlikely (gelf_newehdr (newelf, gelf_getclass (elf)) == 0)
       || (ehdr->e_type != ET_REL
-	  && unlikely (gelf_newphdr (newelf, ehdr->e_phnum) == 0)))
+	  && unlikely (gelf_newphdr (newelf, phnum) == 0)))
     {
       error (0, 0, gettext ("cannot create new file '%s': %s"),
 	     output_fname, elf_errmsg (-1));
@@ -522,7 +527,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
 
   /* Copy over the old program header if needed.  */
   if (ehdr->e_type != ET_REL)
-    for (cnt = 0; cnt < ehdr->e_phnum; ++cnt)
+    for (cnt = 0; cnt < phnum; ++cnt)
       {
 	GElf_Phdr phdr_mem;
 	GElf_Phdr *phdr = gelf_getphdr (elf, cnt, &phdr_mem);
@@ -537,7 +542,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
       debugelf = elf_begin (debug_fd, ELF_C_WRITE_MMAP, NULL);
       if (unlikely (gelf_newehdr (debugelf, gelf_getclass (elf)) == 0)
 	  || (ehdr->e_type != ET_REL
-	      && unlikely (gelf_newphdr (debugelf, ehdr->e_phnum) == 0)))
+	      && unlikely (gelf_newphdr (debugelf, phnum) == 0)))
 	{
 	  error (0, 0, gettext ("cannot create new file '%s': %s"),
 		 debug_fname, elf_errmsg (-1));
@@ -546,7 +551,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
 
       /* Copy over the old program header if needed.  */
       if (ehdr->e_type != ET_REL)
-	for (cnt = 0; cnt < ehdr->e_phnum; ++cnt)
+	for (cnt = 0; cnt < phnum; ++cnt)
 	  {
 	    GElf_Phdr phdr_mem;
 	    GElf_Phdr *phdr = gelf_getphdr (elf, cnt, &phdr_mem);
diff --git a/src/unstrip.c b/src/unstrip.c
index f6af450..85d5a7e 100644
--- a/src/unstrip.c
+++ b/src/unstrip.c
@@ -257,13 +257,17 @@ copy_elf (Elf *outelf, Elf *inelf)
   ELF_CHECK (gelf_update_ehdr (outelf, ehdr),
 	     _("cannot copy ELF header: %s"));
 
-  if (ehdr->e_phnum > 0)
+  size_t phnum;
+  ELF_CHECK (elf_getphdrnum (inelf, &phnum) == 0,
+	     _("cannot get number of program headers: %s"));
+
+  if (phnum > 0)
     {
-      ELF_CHECK (gelf_newphdr (outelf, ehdr->e_phnum),
+      ELF_CHECK (gelf_newphdr (outelf, phnum),
 		 _("cannot create program headers: %s"));
 
       GElf_Phdr phdr_mem;
-      for (uint_fast16_t i = 0; i < ehdr->e_phnum; ++i)
+      for (size_t i = 0; i < phnum; ++i)
 	ELF_CHECK (gelf_update_phdr (outelf, i,
 				     gelf_getphdr (inelf, i, &phdr_mem)),
 		   _("cannot copy program header: %s"));
@@ -1823,12 +1827,16 @@ more sections in stripped file than debug file -- arguments reversed?"));
     }
   while (skip_reloc);
 
-  if (stripped_ehdr->e_phnum > 0)
-    ELF_CHECK (gelf_newphdr (unstripped, stripped_ehdr->e_phnum),
+  size_t phnum;
+  ELF_CHECK (elf_getphdrnum (stripped, &phnum) == 0,
+	     _("cannot get number of program headers: %s"));
+
+  if (phnum > 0)
+    ELF_CHECK (gelf_newphdr (unstripped, phnum),
 	       _("cannot create program headers: %s"));
 
   /* Copy each program header from the stripped file.  */
-  for (uint_fast16_t i = 0; i < stripped_ehdr->e_phnum; ++i)
+  for (size_t i = 0; i < phnum; ++i)
     {
       GElf_Phdr phdr_mem;
       GElf_Phdr *phdr = gelf_getphdr (stripped, i, &phdr_mem);
@@ -1863,11 +1871,15 @@ handle_file (const char *output_file, bool create_dirs,
 	     Elf *stripped, const GElf_Ehdr *stripped_ehdr,
 	     Elf *unstripped)
 {
+  size_t phnum;
+  ELF_CHECK (elf_getphdrnum (stripped, &phnum) == 0,
+	     _("cannot get number of program headers: %s"));
+
   /* Determine the address bias between the debuginfo file and the main
      file, which may have been modified by prelinking.  */
   GElf_Addr bias = 0;
   if (unstripped != NULL)
-    for (uint_fast16_t i = 0; i < stripped_ehdr->e_phnum; ++i)
+    for (size_t i = 0; i < phnum; ++i)
       {
 	GElf_Phdr phdr_mem;
 	GElf_Phdr *phdr = gelf_getphdr (stripped, i, &phdr_mem);
-- 
1.9.3


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]