* [PATCH] Use elf_getphdrnum instead of accessing ehdr->e_phnum directly.
@ 2014-11-22 22:15 Mark Wielaard
0 siblings, 0 replies; only message in thread
From: Mark Wielaard @ 2014-11-22 22:15 UTC (permalink / raw)
To: elfutils-devel
[-- Attachment #1: Type: text/plain, Size: 17560 bytes --]
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
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2014-11-22 22:15 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-11-22 22:15 [PATCH] Use elf_getphdrnum instead of accessing ehdr->e_phnum directly Mark Wielaard
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).