From mboxrd@z Thu Jan 1 00:00:00 1970 Content-Type: multipart/mixed; boundary="===============7957617514515200414==" MIME-Version: 1.0 From: Mark Wielaard To: elfutils-devel@lists.fedorahosted.org Subject: [PATCH] Use elf_getphdrnum instead of accessing ehdr->e_phnum directly. Date: Sat, 22 Nov 2014 23:15:21 +0100 Message-ID: <1416694521-19570-1-git-send-email-mjw@redhat.com> --===============7957617514515200414== Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable 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 --- 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 + + * 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 = * 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 , 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 =3D 0; i < ehdr->e_phnum; ++i) + size_t phnum; + if (elf_getphdrnum (elf, &phnum) !=3D 0) + return false; + + for (size_t i =3D 0; i < phnum; ++i) { GElf_Phdr phdr_mem; GElf_Phdr *phdr =3D gelf_getphdr (elf, i, &phdr_mem); @@ -127,7 +131,7 @@ ppc_check_special_symbol (Elf *elf, GElf_Ehdr *ehdr, co= nst 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 =3D=3D 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, co= nst 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 + + * link_map.c (consider_executable): Use elf_getphdrnum. + (dwfl_link_map_report): Likewise. + 2014-11-18 Mark Wielaard = * 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_ph= dr, GElf_Addr at_entry, address where &r_debug was written at runtime. */ GElf_Xword align =3D mod->dwfl->segment_align; GElf_Addr d_val_vaddr =3D 0; - for (uint_fast16_t i =3D 0; i < ehdr.e_phnum; ++i) + size_t phnum; + if (elf_getphdrnum (mod->main.elf, &phnum) !=3D 0) + return 0; + + for (size_t i =3D 0; i < phnum; ++i) { GElf_Phdr phdr_mem; GElf_Phdr *phdr =3D gelf_getphdr (mod->main.elf, i, &phdr_mem); @@ -813,7 +817,15 @@ dwfl_link_map_report (Dwfl *dwfl, const void *auxv, si= ze_t auxv_size, __libdwfl_seterrno (DWFL_E_LIBELF); return false; } - if (ehdr->e_phnum !=3D phnum || ehdr->e_phentsize !=3D phent) + size_t e_phnum; + if (elf_getphdrnum (elf, &e_phnum) !=3D 0) + { + elf_end (elf); + close (fd); + __libdwfl_seterrno (DWFL_E_LIBELF); + return false; + } + if (e_phnum !=3D phnum || ehdr->e_phentsize !=3D 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 + + * 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 = * 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 =3D=3D NULL ? false : ebl->bss_plt_p (ebl->elf, ehdr); + return ebl =3D=3D 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, GEl= f_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 __a= ttribute__ ((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_E= hdr *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 + + * 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 = * 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 =3D special_sections[s].type; if (IS_KNOWN_SPECIAL (s, ".plt", false) - && ebl_bss_plt_p (ebl, ehdr)) + && ebl_bss_plt_p (ebl)) good_type =3D 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 , 2005. = @@ -324,14 +324,20 @@ process_file (const char *fname, bool more_than_one) if (segments =3D=3D NULL) error (1, errno, gettext ("while reading ELF file")); = - for (int i =3D 0; i < ehdr->e_phnum; ++i) + size_t phnum; + if (elf_getphdrnum (elf, &phnum) !=3D 0) + error (1, 0, gettext ("cannot get program header count: %s"), + elf_errmsg (-1)); + + + for (size_t i =3D 0; i < phnum; ++i) { GElf_Phdr phdr_mem; GElf_Phdr *phdr =3D gelf_getphdr (elf, i, &phdr_mem); if (phdr =3D=3D 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 =3D 1; goto next; @@ -349,7 +355,7 @@ process_file (const char *fname, bool more_than_one) if (segments =3D=3D 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 =3D 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 =3D=3D 0) - phnum =3D 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 =3D=3D 0 || ehdr->e_phoff =3D=3D 0) + if (phnum =3D=3D 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 =3D gelf_getehdr (elf, &ehdr_mem); - if (ehdr =3D=3D NULL) + size_t phnum; + if (elf_getphdrnum (elf, &phnum) !=3D 0) INTERNAL_ERROR (fullname); = GElf_Off total =3D 0; bool first =3D true; - for (size_t cnt =3D 0; cnt < ehdr->e_phnum; ++cnt) + for (size_t cnt =3D 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, cons= t 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) !=3D 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)) =3D=3D 0) || (ehdr->e_type !=3D ET_REL - && unlikely (gelf_newphdr (newelf, ehdr->e_phnum) =3D=3D 0))) + && unlikely (gelf_newphdr (newelf, phnum) =3D=3D 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 !=3D ET_REL) - for (cnt =3D 0; cnt < ehdr->e_phnum; ++cnt) + for (cnt =3D 0; cnt < phnum; ++cnt) { GElf_Phdr phdr_mem; GElf_Phdr *phdr =3D gelf_getphdr (elf, cnt, &phdr_mem); @@ -537,7 +542,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const= char *fname, debugelf =3D elf_begin (debug_fd, ELF_C_WRITE_MMAP, NULL); if (unlikely (gelf_newehdr (debugelf, gelf_getclass (elf)) =3D=3D 0) || (ehdr->e_type !=3D ET_REL - && unlikely (gelf_newphdr (debugelf, ehdr->e_phnum) =3D=3D 0))) + && unlikely (gelf_newphdr (debugelf, phnum) =3D=3D 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 !=3D ET_REL) - for (cnt =3D 0; cnt < ehdr->e_phnum; ++cnt) + for (cnt =3D 0; cnt < phnum; ++cnt) { GElf_Phdr phdr_mem; GElf_Phdr *phdr =3D 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) =3D=3D 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 =3D 0; i < ehdr->e_phnum; ++i) + for (size_t i =3D 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 -- a= rguments 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) =3D=3D 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 =3D 0; i < stripped_ehdr->e_phnum; ++i) + for (size_t i =3D 0; i < phnum; ++i) { GElf_Phdr phdr_mem; GElf_Phdr *phdr =3D gelf_getphdr (stripped, i, &phdr_mem); @@ -1863,11 +1871,15 @@ handle_file (const char *output_file, bool create_d= irs, Elf *stripped, const GElf_Ehdr *stripped_ehdr, Elf *unstripped) { + size_t phnum; + ELF_CHECK (elf_getphdrnum (stripped, &phnum) =3D=3D 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 =3D 0; if (unstripped !=3D NULL) - for (uint_fast16_t i =3D 0; i < stripped_ehdr->e_phnum; ++i) + for (size_t i =3D 0; i < phnum; ++i) { GElf_Phdr phdr_mem; GElf_Phdr *phdr =3D gelf_getphdr (stripped, i, &phdr_mem); -- = 1.9.3 --===============7957617514515200414==--