]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
Use elf_getphdrnum instead of accessing ehdr->e_phnum directly.
authorMark Wielaard <mjw@redhat.com>
Sat, 22 Nov 2014 22:08:48 +0000 (23:08 +0100)
committerMark Wielaard <mjw@redhat.com>
Wed, 26 Nov 2014 19:17:22 +0000 (20:17 +0100)
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>
17 files changed:
backends/ChangeLog
backends/ppc64_symbol.c
backends/ppc_symbol.c
libdwfl/ChangeLog
libdwfl/link_map.c
libebl/ChangeLog
libebl/ebl-hooks.h
libebl/eblbsspltp.c
libebl/eblopenbackend.c
libebl/libebl.h
src/ChangeLog
src/elflint.c
src/findtextrel.c
src/readelf.c
src/size.c
src/strip.c
src/unstrip.c

index abd22bf8896161d6b02bc4e40bb268f4885a1f4a..db1b12989f6c9b56af5f99597ce7526fced8fde0 100644 (file)
@@ -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.
index 5a020d8d065386e2e7c98dfb53f2545bef9f1eb3..0feddcee24a86caeebcbb74dae643d6ecdfb8b5c 100644 (file)
@@ -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;
 }
index 220f243e1f9ac433caa261c9999e90d360b12a01..c17ab37470624132902e1ede577cd9fd9b291fe2 100644 (file)
@@ -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);
 }
index 460f4e5fa174527ffd6af307e7b24ee341e446ff..5876fccdd0c8bf1a75ce9001b1f5a899b37a649e 100644 (file)
@@ -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,
index 272f89ba7f17285b6a0e5a8f9b081d2843f98142..eaf43b5751ba099c1f29afb1e07c0d45b826bc66 100644 (file)
@@ -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);
index b6a0e6323e3b3705858f2a009a3dc4c114f56bc6..5e635f2160b93c3d077efcd3f36c538cc73c89fd 100644 (file)
@@ -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.
index e1186f86f595b27e20890de8e18ddde1ce9950be..2e3144644a72f7352546f143cf8529a1bea3d056 100644 (file)
@@ -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.  */
index 080e7c5ce3a9c6a4bfdb684dd5e350f568b7d566..95a5d8afdad14496bf0aaa8cca7ce5b8ce9318ab 100644 (file)
@@ -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);
 }
index bd947599dd2b407dc75c76c6f2df60d45800130d..3a22f53df10fd56474a966d616ebf3ea52d0c40e 100644 (file)
@@ -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;
 }
index bb993bf0a124c01471a84dba6931d30150692b4c..7c3c76473d69e443de72fd3f0cb68cc33864cb23 100644 (file)
@@ -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);
index bab948a19d792a43a362c4937f60951b2d2a2d93..bace91d5736ce25d760bec6ad0c078da033e4be8 100644 (file)
@@ -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
index d6a477489426752a8d72eaf6498e03b6e2a4f6af..fbc78ede5282914b0db82a530791bfcbf6fbc366 100644 (file)
@@ -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.
index 9fd81633b41252e964210d5d69aae65ce05c63c5..264a06bd96eb7a5e9fd06c3cb78df8937b80a5a9 100644 (file)
@@ -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;
index 08de79891dd0ecef9a3935cef70967c49a7aeedd..3b1f035a850e74010db1a1fe6795a25f61cb92b0 100644 (file)
@@ -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;
 
index cb67999b4b9b4c3bf6fa5f9aca34575390564d28..0e7e41e490a14311383d201faabfcffd6d4d76d6 100644 (file)
@@ -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;
index c9a1d8dfc3afea9b640f60fa83722a1d59a2f30b..2b2179969e2b5f3ddda538c4f2ecf9c31a751ad0 100644 (file)
@@ -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);
index f6af45002a9174222fe25d26ae53e512895f6323..989ac5ff2848650cdff65c7fa6ab1b81c1706b81 100644 (file)
@@ -241,7 +241,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
 #define ELF_CHECK(call, msg)                                                 \
   do                                                                         \
     {                                                                        \
-      if (!(call))                                                           \
+      if (unlikely (!(call)))                                                \
        error (EXIT_FAILURE, 0, msg, elf_errmsg (-1));                        \
     } while (0)
 
@@ -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);