From ced6687b6e41d008874e6f82209d0cecb79913fa Mon Sep 17 00:00:00 2001 From: Petr Machata Date: Fri, 17 Jan 2014 17:00:12 +0100 Subject: [PATCH] robustify: Use gelf_fsize instead of relying on shdr->sh_entsize. Signed-off-by: Mark Wielaard --- libdwfl/ChangeLog | 5 +++++ libdwfl/relocate.c | 9 ++++++--- src/ChangeLog | 6 ++++++ src/readelf.c | 39 +++++++++++++++++++++++++++++---------- 4 files changed, 46 insertions(+), 13 deletions(-) diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog index 55980a572..e55b03b75 100644 --- a/libdwfl/ChangeLog +++ b/libdwfl/ChangeLog @@ -1,3 +1,8 @@ +2014-01-17 Petr Machata + + * relocate.c (relocate_section): Use gelf_fsize instead of relying + on shdr->sh_entsize. + 2014-01-05 Mark Wielaard * frame_unwind.c (handle_cfi): Only skip resetting return register diff --git a/libdwfl/relocate.c b/libdwfl/relocate.c index f8a5fcfa6..52b7b5eb1 100644 --- a/libdwfl/relocate.c +++ b/libdwfl/relocate.c @@ -1,5 +1,5 @@ /* Relocate debug information. - Copyright (C) 2005-2010 Red Hat, Inc. + Copyright (C) 2005-2011, 2014 Red Hat, Inc. This file is part of elfutils. This file is free software; you can redistribute it and/or modify @@ -456,7 +456,10 @@ relocate_section (Dwfl_Module *mod, Elf *relocated, const GElf_Ehdr *ehdr, } } - size_t nrels = shdr->sh_size / shdr->sh_entsize; + size_t sh_entsize + = gelf_fsize (relocated, shdr->sh_type == SHT_REL ? ELF_T_REL : ELF_T_RELA, + 1, EV_CURRENT); + size_t nrels = shdr->sh_size / sh_entsize; size_t complete = 0; if (shdr->sh_type == SHT_REL) for (size_t relidx = 0; !result && relidx < nrels; ++relidx) @@ -558,7 +561,7 @@ relocate_section (Dwfl_Module *mod, Elf *relocated, const GElf_Ehdr *ehdr, nrels = next; } - shdr->sh_size = reldata->d_size = nrels * shdr->sh_entsize; + shdr->sh_size = reldata->d_size = nrels * sh_entsize; gelf_update_shdr (scn, shdr); } diff --git a/src/ChangeLog b/src/ChangeLog index d085d754c..a3f56fb55 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,9 @@ +2014-01-17 Petr Machata + + * readelf.c (handle_dynamic, handle_relocs_rel) + (handle_relocs_rela, handle_versym, print_liblist): + Use gelf_fsize instead of relying on shdr->sh_entsize. + 2014-01-14 Mark Wielaard * readelf.c (print_debug_macro_section): Clear vendor array before diff --git a/src/readelf.c b/src/readelf.c index 39912243b..a63760875 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -1,5 +1,5 @@ /* Print information from ELF file in human-readable form. - Copyright (C) 1999-2013 Red Hat, Inc. + Copyright (C) 1999-2014 Red Hat, Inc. This file is part of elfutils. Written by Ulrich Drepper , 1999. @@ -1532,6 +1532,7 @@ handle_dynamic (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) Elf_Data *data; size_t cnt; size_t shstrndx; + size_t sh_entsize; /* Get the data of the section. */ data = elf_getdata (scn, NULL); @@ -1543,12 +1544,19 @@ handle_dynamic (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) error (EXIT_FAILURE, 0, gettext ("cannot get section header string table index")); + sh_entsize = gelf_fsize (ebl->elf, ELF_T_DYN, 1, EV_CURRENT); + + glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), &glink_mem); + if (glink == NULL) + error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %Zu"), + elf_ndxscn (scn)); + printf (ngettext ("\ \nDynamic segment contains %lu entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n", "\ \nDynamic segment contains %lu entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n", - shdr->sh_size / shdr->sh_entsize), - (unsigned long int) (shdr->sh_size / shdr->sh_entsize), + shdr->sh_size / sh_entsize), + (unsigned long int) (shdr->sh_size / sh_entsize), class == ELFCLASS32 ? 10 : 18, shdr->sh_addr, shdr->sh_offset, (int) shdr->sh_link, @@ -1557,7 +1565,7 @@ handle_dynamic (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) &glink)->sh_name)); fputs_unlocked (gettext (" Type Value\n"), stdout); - for (cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt) + for (cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt) { GElf_Dyn dynmem; GElf_Dyn *dyn = gelf_getdyn (data, cnt, &dynmem); @@ -1706,7 +1714,8 @@ static void handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr) { int class = gelf_getclass (ebl->elf); - int nentries = shdr->sh_size / shdr->sh_entsize; + size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_REL, 1, EV_CURRENT); + int nentries = shdr->sh_size / sh_entsize; /* Get the data of the section. */ Elf_Data *data = elf_getdata (scn, NULL); @@ -1892,7 +1901,8 @@ static void handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr) { int class = gelf_getclass (ebl->elf); - int nentries = shdr->sh_size / shdr->sh_entsize; + size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_RELA, 1, EV_CURRENT); + int nentries = shdr->sh_size / sh_entsize; /* Get the data of the section. */ Elf_Data *data = elf_getdata (scn, NULL); @@ -2736,16 +2746,24 @@ handle_versym (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) filename = NULL; } + GElf_Shdr glink_mem; + GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), + &glink_mem); + size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_HALF, 1, EV_CURRENT); + if (glink == NULL) + error (EXIT_FAILURE, 0, gettext ("invalid sh_link value in section %Zu"), + elf_ndxscn (scn)); + /* Print the header. */ GElf_Shdr glink; printf (ngettext ("\ \nVersion symbols section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'", "\ \nVersion symbols section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'", - shdr->sh_size / shdr->sh_entsize), + shdr->sh_size / sh_entsize), (unsigned int) elf_ndxscn (scn), elf_strptr (ebl->elf, shstrndx, shdr->sh_name), - (int) (shdr->sh_size / shdr->sh_entsize), + (int) (shdr->sh_size / sh_entsize), class == ELFCLASS32 ? 10 : 18, shdr->sh_addr, shdr->sh_offset, (unsigned int) shdr->sh_link, @@ -2754,7 +2772,7 @@ handle_versym (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) &glink)->sh_name)); /* Now we can finally look at the actual contents of this section. */ - for (unsigned int cnt = 0; cnt < shdr->sh_size / shdr->sh_entsize; ++cnt) + for (unsigned int cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt) { if (cnt % 2 == 0) printf ("\n %4d:", cnt); @@ -3078,7 +3096,8 @@ print_liblist (Ebl *ebl) if (shdr != NULL && shdr->sh_type == SHT_GNU_LIBLIST) { - int nentries = shdr->sh_size / shdr->sh_entsize; + size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_LIB, 1, EV_CURRENT); + int nentries = shdr->sh_size / sh_entsize; printf (ngettext ("\ \nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entry:\n", "\ -- 2.47.2