From b47d290a36509e26e145f6d3eb2e6590ec6c554d Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Mon, 1 Jun 2009 07:38:32 -0700 Subject: Add support for IRELATIVE relocations. That's the second part of the IFUNC support. So far x86 and x86-64 only. --- backends/ChangeLog | 5 ++ backends/i386_reloc.def | 3 +- backends/x86_64_reloc.def | 3 +- libelf/ChangeLog | 4 ++ libelf/elf.h | 6 +- src/ChangeLog | 8 +++ src/readelf.c | 143 ++++++++++++++++++++++++++++++++++++---------- 7 files changed, 139 insertions(+), 33 deletions(-) diff --git a/backends/ChangeLog b/backends/ChangeLog index c764f9ef..a1aa351f 100644 --- a/backends/ChangeLog +++ b/backends/ChangeLog @@ -1,3 +1,8 @@ +2009-06-01 Ulrich Drepper + + * i386_reloc.def: Add IRELATIVE entry. + * x86_64_reloc.def: Likewise. + 2009-04-16 Roland McGrath * arm_regs.c (arm_register_info): Handle VFP registers. diff --git a/backends/i386_reloc.def b/backends/i386_reloc.def index bc1b835d..1befd1b6 100644 --- a/backends/i386_reloc.def +++ b/backends/i386_reloc.def @@ -1,5 +1,5 @@ /* List the relocation types for i386. -*- C -*- - Copyright (C) 2000, 2001, 2002, 2003, 2005 Red Hat, Inc. + Copyright (C) 2000, 2001, 2002, 2003, 2005, 2009 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -64,3 +64,4 @@ RELOC_TYPE (TLS_TPOFF32, EXEC|DYN) RELOC_TYPE (TLS_GOTDESC, REL) RELOC_TYPE (TLS_DESC_CALL, REL) RELOC_TYPE (TLS_DESC, EXEC) +RELOC_TYPE (IRELATIVE, EXEC|DYN) diff --git a/backends/x86_64_reloc.def b/backends/x86_64_reloc.def index e6c5a84b..5d70f47c 100644 --- a/backends/x86_64_reloc.def +++ b/backends/x86_64_reloc.def @@ -1,5 +1,5 @@ /* List the relocation types for x86-64. -*- C -*- - Copyright (C) 2000, 2001, 2002, 2003, 2005 Red Hat, Inc. + Copyright (C) 2000, 2001, 2002, 2003, 2005, 2009 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -49,3 +49,4 @@ RELOC_TYPE (TLSLD, REL) RELOC_TYPE (DTPOFF32, REL) RELOC_TYPE (GOTTPOFF, REL) RELOC_TYPE (TPOFF32, REL) +RELOC_TYPE (IRELATIVE, EXEC|DYN) diff --git a/libelf/ChangeLog b/libelf/ChangeLog index bfc3ee5f..2fd5381b 100644 --- a/libelf/ChangeLog +++ b/libelf/ChangeLog @@ -1,3 +1,7 @@ +2009-06-01 Ulrich Drepper + + * elf.h: Update from glibc. + 2009-04-14 Roland McGrath * elf.h: Update from glibc. diff --git a/libelf/elf.h b/libelf/elf.h index 062ef00f..8fdf74b0 100644 --- a/libelf/elf.h +++ b/libelf/elf.h @@ -1177,8 +1177,9 @@ typedef struct pointer to code and to argument, returning the TLS offset for the symbol. */ +#define R_386_IRELATIVE 42 /* Adjust indirectly by program base */ /* Keep this the last entry. */ -#define R_386_NUM 42 +#define R_386_NUM 43 /* SUN SPARC specific definitions. */ @@ -2625,8 +2626,9 @@ typedef Elf32_Addr Elf32_Conflict; #define R_X86_64_TLSDESC_CALL 35 /* Marker for call through TLS descriptor. */ #define R_X86_64_TLSDESC 36 /* TLS descriptor. */ +#define R_X86_64_IRELATIVE 37 /* Adjust indirectly by program base */ -#define R_X86_64_NUM 37 +#define R_X86_64_NUM 38 /* AM33 relocations. */ diff --git a/src/ChangeLog b/src/ChangeLog index f6fd86f3..01a2414a 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,11 @@ +2009-06-01 Ulrich Drepper + + * readelf.c (print_relocs): Expect ELF header argument and pass on + to handle_relocs_rel* functions. Adjust caller. + (handle_relocs_rel): Add ELF header argument. Add special case for + the IRELATIVE relocations in statically linked executables. + (handle_relocs_rela): Likewise. + 2009-04-29 Ulrich Drepper * elflint.c (check_symtab): Add tests of st_other field. diff --git a/src/readelf.c b/src/readelf.c index 1c790650..9ce46042 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -211,9 +211,11 @@ static void print_shdr (Ebl *ebl, GElf_Ehdr *ehdr); static void print_phdr (Ebl *ebl, GElf_Ehdr *ehdr); static void print_scngrp (Ebl *ebl); static void print_dynamic (Ebl *ebl, GElf_Ehdr *ehdr); -static void print_relocs (Ebl *ebl); -static void handle_relocs_rel (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr); -static void handle_relocs_rela (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr); +static void print_relocs (Ebl *ebl, GElf_Ehdr *ehdr); +static void handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, + GElf_Shdr *shdr); +static void handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, + GElf_Shdr *shdr); static void print_symtab (Ebl *ebl, int type); static void handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr); static void print_verinfo (Ebl *ebl); @@ -652,7 +654,7 @@ process_elf_file (Dwfl_Module *dwflmod, int fd) if (print_dynamic_table) print_dynamic (ebl, ehdr); if (print_relocations) - print_relocs (pure_ebl); + print_relocs (pure_ebl, ehdr); if (print_histogram) handle_hash (ebl); if (print_symbol_table) @@ -1449,7 +1451,7 @@ print_dynamic (Ebl *ebl, GElf_Ehdr *ehdr) /* Print relocations. */ static void -print_relocs (Ebl *ebl) +print_relocs (Ebl *ebl, GElf_Ehdr *ehdr) { /* Find all relocation sections and handle them. */ Elf_Scn *scn = NULL; @@ -1463,9 +1465,9 @@ print_relocs (Ebl *ebl) if (likely (shdr != NULL)) { if (shdr->sh_type == SHT_REL) - handle_relocs_rel (ebl, scn, shdr); + handle_relocs_rel (ebl, ehdr, scn, shdr); else if (shdr->sh_type == SHT_RELA) - handle_relocs_rela (ebl, scn, shdr); + handle_relocs_rela (ebl, ehdr, scn, shdr); } } } @@ -1473,7 +1475,7 @@ print_relocs (Ebl *ebl) /* Handle a relocation section. */ static void -handle_relocs_rel (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) +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; @@ -1545,6 +1547,7 @@ handle_relocs_rel (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) Offset Type Value Name\n"), stdout); + int is_statically_linked = 0; for (int cnt = 0; cnt < nentries; ++cnt) { GElf_Rel relmem; @@ -1558,16 +1561,56 @@ handle_relocs_rel (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) GELF_R_SYM (rel->r_info), &symmem, &xndx); if (unlikely (sym == NULL)) - printf (" %#0*" PRIx64 " %-20s <%s %ld>\n", - class == ELFCLASS32 ? 10 : 18, rel->r_offset, - ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) - /* Avoid the leading R_ which isn't carrying any - information. */ - ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), - buf, sizeof (buf)) + 2 - : gettext (""), - gettext ("INVALID SYMBOL"), - (long int) GELF_R_SYM (rel->r_info)); + { + /* As a special case we have to handle relocations in static + executables. This only happens for IRELATIVE relocations + (so far). There is no symbol table. */ + if (is_statically_linked == 0) + { + /* Find the program header and look for a PT_INTERP entry. */ + is_statically_linked = -1; + if (ehdr->e_type == ET_EXEC) + { + is_statically_linked = 1; + + for (size_t inner = 0; inner < ehdr->e_phnum; ++inner) + { + GElf_Phdr phdr_mem; + GElf_Phdr *phdr = gelf_getphdr (ebl->elf, inner, + &phdr_mem); + if (phdr != NULL && phdr->p_type == PT_INTERP) + { + is_statically_linked = -1; + break; + } + } + } + } + + if (is_statically_linked > 0 && shdr->sh_link == 0) + printf ("\ + %#0*" PRIx64 " %-20s %*s %s\n", + class == ELFCLASS32 ? 10 : 18, rel->r_offset, + ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) + /* Avoid the leading R_ which isn't carrying any + information. */ + ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), + buf, sizeof (buf)) + 2 + : gettext (""), + class == ELFCLASS32 ? 10 : 18, "", + elf_strptr (ebl->elf, shstrndx, destshdr->sh_name)); + else + printf (" %#0*" PRIx64 " %-20s <%s %ld>\n", + class == ELFCLASS32 ? 10 : 18, rel->r_offset, + ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) + /* Avoid the leading R_ which isn't carrying any + information. */ + ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), + buf, sizeof (buf)) + 2 + : gettext (""), + gettext ("INVALID SYMBOL"), + (long int) GELF_R_SYM (rel->r_info)); + } else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION) printf (" %#0*" PRIx64 " %-20s %#0*" PRIx64 " %s\n", class == ELFCLASS32 ? 10 : 18, rel->r_offset, @@ -1618,7 +1661,7 @@ handle_relocs_rel (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) /* Handle a relocation section. */ static void -handle_relocs_rela (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) +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; @@ -1676,6 +1719,7 @@ handle_relocs_rela (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) Offset Type Value Addend Name\n"), stdout); + int is_statically_linked = 0; for (int cnt = 0; cnt < nentries; ++cnt) { GElf_Rela relmem; @@ -1690,16 +1734,57 @@ handle_relocs_rela (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) &symmem, &xndx); if (unlikely (sym == NULL)) - printf (" %#0*" PRIx64 " %-15s <%s %ld>\n", - class == ELFCLASS32 ? 10 : 18, rel->r_offset, - ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) - /* Avoid the leading R_ which isn't carrying any - information. */ - ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), - buf, sizeof (buf)) + 2 - : gettext (""), - gettext ("INVALID SYMBOL"), - (long int) GELF_R_SYM (rel->r_info)); + { + /* As a special case we have to handle relocations in static + executables. This only happens for IRELATIVE relocations + (so far). There is no symbol table. */ + if (is_statically_linked == 0) + { + /* Find the program header and look for a PT_INTERP entry. */ + is_statically_linked = -1; + if (ehdr->e_type == ET_EXEC) + { + is_statically_linked = 1; + + for (size_t inner = 0; inner < ehdr->e_phnum; ++inner) + { + GElf_Phdr phdr_mem; + GElf_Phdr *phdr = gelf_getphdr (ebl->elf, inner, + &phdr_mem); + if (phdr != NULL && phdr->p_type == PT_INTERP) + { + is_statically_linked = -1; + break; + } + } + } + } + + if (is_statically_linked > 0 && shdr->sh_link == 0) + printf ("\ + %#0*" PRIx64 " %-15s %*s %#6" PRIx64 " %s\n", + class == ELFCLASS32 ? 10 : 18, rel->r_offset, + ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) + /* Avoid the leading R_ which isn't carrying any + information. */ + ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), + buf, sizeof (buf)) + 2 + : gettext (""), + class == ELFCLASS32 ? 10 : 18, "", + rel->r_addend, + elf_strptr (ebl->elf, shstrndx, destshdr->sh_name)); + else + printf (" %#0*" PRIx64 " %-15s <%s %ld>\n", + class == ELFCLASS32 ? 10 : 18, rel->r_offset, + ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info)) + /* Avoid the leading R_ which isn't carrying any + information. */ + ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info), + buf, sizeof (buf)) + 2 + : gettext (""), + gettext ("INVALID SYMBOL"), + (long int) GELF_R_SYM (rel->r_info)); + } else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION) printf ("\ %#0*" PRIx64 " %-15s %#0*" PRIx64 " %+6" PRId64 " %s\n", -- cgit v1.2.1 From f189493154d0041deced00e6a99cc5426dc9d260 Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Sat, 13 Jun 2009 15:55:42 -0700 Subject: Add aliases for elf_getshnum and elf_getshstrndx. Sun in their implementation messed up the semantics of these functions. To get back to source code compatibility they asked for a solution. We simply add aliases for the two affected functions, named elf_getshdrnum and elf_getshdrstrndx. The semantics remains the same. Users of the old interfaces receive a warning for now. In future we might make it impossible to link programs which request the old interfaces (binary compatibility will of course be maintained). --- NEWS | 6 ++ configure.ac | 2 +- libdwfl/ChangeLog | 6 ++ libdwfl/derelocate.c | 2 +- libdwfl/dwfl_module_getdwarf.c | 2 +- libdwfl/relocate.c | 6 +- libelf/ChangeLog | 17 ++++ libelf/Makefile.am | 2 +- libelf/elf32_checksum.c | 4 +- libelf/elf32_getshdr.c | 4 +- libelf/elf_getshdrnum.c | 111 ++++++++++++++++++++++ libelf/elf_getshdrstrndx.c | 205 +++++++++++++++++++++++++++++++++++++++++ libelf/elf_getshnum.c | 109 ---------------------- libelf/elf_getshstrndx.c | 203 ---------------------------------------- libelf/libelf.h | 16 +++- libelf/libelf.map | 5 + libelf/libelfP.h | 9 +- src/ChangeLog | 11 +++ src/ld.h | 4 +- src/ldgeneric.c | 12 +-- src/nm.c | 6 +- src/objdump.c | 2 +- src/readelf.c | 38 ++++---- src/size.c | 4 +- src/strip.c | 4 +- src/unstrip.c | 10 +- 26 files changed, 430 insertions(+), 370 deletions(-) create mode 100644 libelf/elf_getshdrnum.c create mode 100644 libelf/elf_getshdrstrndx.c delete mode 100644 libelf/elf_getshnum.c delete mode 100644 libelf/elf_getshstrndx.c diff --git a/NEWS b/NEWS index c0f60bca..e3106f71 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,9 @@ +Version 0.142: + +libelf: Add elf_getshdrnum alias for elf_getshnum and elf_getshdrstrndx alias + for elf_getshstrndx and deprecate original names. Sun screwed up + their implementation and asked for a solution. + Version 0.141: libebl: sparc backend fixes; diff --git a/configure.ac b/configure.ac index 4931530c..4d7ec1e6 100644 --- a/configure.ac +++ b/configure.ac @@ -16,7 +16,7 @@ dnl You should have received a copy of the GNU General Public License dnl along with this program; if not, write to the Free Software Foundation, dnl Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. dnl -AC_INIT([Red Hat elfutils],[0.141],[http://bugzilla.redhat.com/bugzilla/], +AC_INIT([Red Hat elfutils],[0.142],[http://bugzilla.redhat.com/bugzilla/], [elfutils]) AC_CONFIG_AUX_DIR([config]) diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog index 8f51ca73..97e888f0 100644 --- a/libdwfl/ChangeLog +++ b/libdwfl/ChangeLog @@ -1,3 +1,9 @@ +2009-06-13 Ulrich Drepper + + * derelocate.c: Don't use deprecated libelf functions. + * dwfl_module_getdwarf.c: Likewise. + * relocate.c: Likewise. + 2009-04-23 Ulrich Drepper * dwfl_module_build_id.c: Define versioned symbols only if SHARED is diff --git a/libdwfl/derelocate.c b/libdwfl/derelocate.c index c300f84b..56ba25af 100644 --- a/libdwfl/derelocate.c +++ b/libdwfl/derelocate.c @@ -94,7 +94,7 @@ cache_sections (Dwfl_Module *mod) size_t nrefs = 0; size_t shstrndx; - if (unlikely (elf_getshstrndx (mod->main.elf, &shstrndx) < 0)) + if (unlikely (elf_getshdrstrndx (mod->main.elf, &shstrndx) < 0)) { elf_error: __libdwfl_seterrno (DWFL_E_LIBELF); diff --git a/libdwfl/dwfl_module_getdwarf.c b/libdwfl/dwfl_module_getdwarf.c index 06cb4917..f48fabe7 100644 --- a/libdwfl/dwfl_module_getdwarf.c +++ b/libdwfl/dwfl_module_getdwarf.c @@ -148,7 +148,7 @@ static const char * find_debuglink (Elf *elf, GElf_Word *crc) { size_t shstrndx; - if (elf_getshstrndx (elf, &shstrndx) < 0) + if (elf_getshdrstrndx (elf, &shstrndx) < 0) return NULL; Elf_Scn *scn = NULL; diff --git a/libdwfl/relocate.c b/libdwfl/relocate.c index 2c0f3010..a31fe152 100644 --- a/libdwfl/relocate.c +++ b/libdwfl/relocate.c @@ -72,7 +72,7 @@ __libdwfl_relocate_value (Dwfl_Module *mod, Elf *elf, size_t *shstrndx, address and update the section header. */ if (*shstrndx == SHN_UNDEF - && unlikely (elf_getshstrndx (elf, shstrndx) < 0)) + && unlikely (elf_getshdrstrndx (elf, shstrndx) < 0)) return DWFL_E_LIBELF; const char *name = elf_strptr (elf, *shstrndx, refshdr->sh_name); @@ -582,7 +582,7 @@ __libdwfl_relocate (Dwfl_Module *mod, Elf *debugfile, bool debug) return DWFL_E_LIBELF; size_t d_shstrndx; - if (elf_getshstrndx (debugfile, &d_shstrndx) < 0) + if (elf_getshdrstrndx (debugfile, &d_shstrndx) < 0) return DWFL_E_LIBELF; RELOC_SYMTAB_CACHE (reloc_symtab); @@ -626,7 +626,7 @@ __libdwfl_relocate_section (Dwfl_Module *mod, Elf *relocated, RELOC_SYMTAB_CACHE (reloc_symtab); size_t shstrndx; - if (elf_getshstrndx (relocated, &shstrndx) < 0) + if (elf_getshdrstrndx (relocated, &shstrndx) < 0) return DWFL_E_LIBELF; return (__libdwfl_module_getebl (mod) diff --git a/libelf/ChangeLog b/libelf/ChangeLog index 2fd5381b..a0163db1 100644 --- a/libelf/ChangeLog +++ b/libelf/ChangeLog @@ -1,3 +1,20 @@ +2009-06-13 Ulrich Drepper + + * Makefile.am (libelf_a_SOURCES): Replace elf_getshnum.c and + elf_getshstrndx.c with elf_getshdrnum.c and elf_getshdrstrndx.c. + * elf_getshnum.c: Renamed to... + * elf_getshdrnum.c: ...this. Rename function and add old name as + alias. Likewise for internal functions with derived names. + * elf_getshstrndx.c: Renamed to... + * elf_getshdrstrndx.c: ...this. Rename function and add old name as + alias. Likewise for internal functions with derived names. + * libelf.h: Add prototypes for new names. Make old names as + deprecated. + * libelfP.h: Rename internal function prototypes. + * libelf.map: Export for names. + * elf32_checksum.c: Don't use deprecated functions. + * elf32_getshdr.c: Likewise. + 2009-06-01 Ulrich Drepper * elf.h: Update from glibc. diff --git a/libelf/Makefile.am b/libelf/Makefile.am index 84b01a86..fbb19a63 100644 --- a/libelf/Makefile.am +++ b/libelf/Makefile.am @@ -91,7 +91,7 @@ libelf_a_SOURCES = elf_version.c elf_hash.c elf_error.c elf_fill.c \ gelf_update_versym.c gelf_update_verneed.c \ gelf_update_vernaux.c gelf_update_verdef.c \ gelf_update_verdaux.c \ - elf_getshnum.c elf_getshstrndx.c \ + elf_getshdrnum.c elf_getshdrstrndx.c \ gelf_checksum.c elf32_checksum.c elf64_checksum.c \ libelf_crc32.c libelf_next_prime.c \ elf_clone.c \ diff --git a/libelf/elf32_checksum.c b/libelf/elf32_checksum.c index 32b4a02d..ad040b80 100644 --- a/libelf/elf32_checksum.c +++ b/libelf/elf32_checksum.c @@ -1,5 +1,5 @@ /* Compute simple checksum from permanent parts of the ELF file. - Copyright (C) 2002, 2003, 2004, 2005 Red Hat, Inc. + Copyright (C) 2002, 2003, 2004, 2005, 2009 Red Hat, Inc. This file is part of Red Hat elfutils. Written by Ulrich Drepper , 2002. @@ -90,7 +90,7 @@ elfw2(LIBELFBITS,checksum) (elf) return -1l; /* Find the section header string table. */ - if (INTUSE(elf_getshstrndx) (elf, &shstrndx) < 0) + if (INTUSE(elf_getshdrstrndx) (elf, &shstrndx) < 0) { /* This can only happen if the ELF handle is not for real. */ __libelf_seterrno (ELF_E_INVALID_HANDLE); diff --git a/libelf/elf32_getshdr.c b/libelf/elf32_getshdr.c index 91f5b3a1..8d650d9f 100644 --- a/libelf/elf32_getshdr.c +++ b/libelf/elf32_getshdr.c @@ -1,5 +1,5 @@ /* Return section header. - Copyright (C) 1998, 1999, 2000, 2001, 2002, 2005, 2007 Red Hat, Inc. + Copyright (C) 1998, 1999, 2000, 2001, 2002, 2005, 2007, 2009 Red Hat, Inc. This file is part of Red Hat elfutils. Written by Ulrich Drepper , 1998. @@ -81,7 +81,7 @@ load_shdr_wrlock (Elf_Scn *scn) goto out; size_t shnum; - if (__elf_getshnum_rdlock (elf, &shnum) != 0) + if (__elf_getshdrnum_rdlock (elf, &shnum) != 0) goto out; size_t size = shnum * sizeof (ElfW2(LIBELFBITS,Shdr)); diff --git a/libelf/elf_getshdrnum.c b/libelf/elf_getshdrnum.c new file mode 100644 index 00000000..ed1149bb --- /dev/null +++ b/libelf/elf_getshdrnum.c @@ -0,0 +1,111 @@ +/* Return number of sections in the ELF file. + Copyright (C) 2002, 2009 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper , 2002. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include + +#include "libelfP.h" + + +int +__elf_getshdrnum_rdlock (elf, dst) + Elf *elf; + size_t *dst; +{ + int result = 0; + int idx; + + if (elf == NULL) + return -1; + + if (unlikely (elf->kind != ELF_K_ELF)) + { + __libelf_seterrno (ELF_E_INVALID_HANDLE); + return -1; + } + + idx = elf->state.elf.scns_last->cnt; + if (idx != 0 + || (elf->state.elf.scns_last + != (elf->class == ELFCLASS32 + || (offsetof (Elf, state.elf32.scns) + == offsetof (Elf, state.elf64.scns)) + ? &elf->state.elf32.scns : &elf->state.elf64.scns))) + /* There is at least one section. */ + *dst = 1 + elf->state.elf.scns_last->data[idx - 1].index; + else + *dst = 0; + + return result; +} + +int +elf_getshdrnum (elf, dst) + Elf *elf; + size_t *dst; +{ + int result; + + if (elf == NULL) + return -1; + + rwlock_rdlock (elf->lock); + result = __elf_getshdrnum_rdlock (elf, dst); + rwlock_unlock (elf->lock); + + return result; +} +/* Alias for the deprecated name. */ +strong_alias (elf_getshdrnum, elf_getshnum) diff --git a/libelf/elf_getshdrstrndx.c b/libelf/elf_getshdrstrndx.c new file mode 100644 index 00000000..5e89b343 --- /dev/null +++ b/libelf/elf_getshdrstrndx.c @@ -0,0 +1,205 @@ +/* Return section index of section header string table. + Copyright (C) 2002, 2005, 2009 Red Hat, Inc. + This file is part of Red Hat elfutils. + Written by Ulrich Drepper , 2002. + + Red Hat elfutils is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by the + Free Software Foundation; version 2 of the License. + + Red Hat elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with Red Hat elfutils; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. + + In addition, as a special exception, Red Hat, Inc. gives You the + additional right to link the code of Red Hat elfutils with code licensed + under any Open Source Initiative certified open source license + (http://www.opensource.org/licenses/index.php) which requires the + distribution of source code with any binary distribution and to + distribute linked combinations of the two. Non-GPL Code permitted under + this exception must only link to the code of Red Hat elfutils through + those well defined interfaces identified in the file named EXCEPTION + found in the source code files (the "Approved Interfaces"). The files + of Non-GPL Code may instantiate templates or use macros or inline + functions from the Approved Interfaces without causing the resulting + work to be covered by the GNU General Public License. Only Red Hat, + Inc. may make changes or additions to the list of Approved Interfaces. + Red Hat's grant of this exception is conditioned upon your not adding + any new exceptions. If you wish to add a new Approved Interface or + exception, please contact Red Hat. You must obey the GNU General Public + License in all respects for all of the Red Hat elfutils code and other + code used in conjunction with Red Hat elfutils except the Non-GPL Code + covered by this exception. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do + so. If you do not wish to provide this exception without modification, + you must delete this exception statement from your version and license + this file solely under the GPL without exception. + + Red Hat elfutils is an included package of the Open Invention Network. + An included package of the Open Invention Network is a package for which + Open Invention Network licensees cross-license their patents. No patent + license is granted, either expressly or impliedly, by designation as an + included package. Should you wish to participate in the Open Invention + Network licensing program, please visit www.openinventionnetwork.com + . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include + +#include +#include "libelfP.h" +#include "common.h" + + +int +elf_getshdrstrndx (elf, dst) + Elf *elf; + size_t *dst; +{ + int result = 0; + + if (elf == NULL) + return -1; + + if (unlikely (elf->kind != ELF_K_ELF)) + { + __libelf_seterrno (ELF_E_INVALID_HANDLE); + return -1; + } + + rwlock_rdlock (elf->lock); + + /* We rely here on the fact that the `elf' element is a common prefix + of `elf32' and `elf64'. */ + assert (offsetof (struct Elf, state.elf.ehdr) + == offsetof (struct Elf, state.elf32.ehdr)); + assert (sizeof (elf->state.elf.ehdr) + == sizeof (elf->state.elf32.ehdr)); + assert (offsetof (struct Elf, state.elf.ehdr) + == offsetof (struct Elf, state.elf64.ehdr)); + assert (sizeof (elf->state.elf.ehdr) + == sizeof (elf->state.elf64.ehdr)); + + if (unlikely (elf->state.elf.ehdr == NULL)) + { + __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR); + result = -1; + } + else + { + Elf32_Word num; + + num = (elf->class == ELFCLASS32 + ? elf->state.elf32.ehdr->e_shstrndx + : elf->state.elf64.ehdr->e_shstrndx); + + /* Determine whether the index is too big to fit in the ELF + header. */ + if (unlikely (num == SHN_XINDEX)) + { + /* Yes. Search the zeroth section header. */ + if (elf->class == ELFCLASS32) + { + size_t offset; + + if (elf->state.elf32.scns.data[0].shdr.e32 != NULL) + { + num = elf->state.elf32.scns.data[0].shdr.e32->sh_link; + goto success; + } + + offset = elf->state.elf32.ehdr->e_shoff; + + if (elf->map_address != NULL + && elf->state.elf32.ehdr->e_ident[EI_DATA] == MY_ELFDATA + && (ALLOW_UNALIGNED + || (((size_t) ((char *) elf->map_address + offset)) + & (__alignof__ (Elf32_Shdr) - 1)) == 0)) + /* We can directly access the memory. */ + num = ((Elf32_Shdr *) (elf->map_address + offset))->sh_link; + else + { + /* We avoid reading in all the section headers. Just read + the first one. */ + Elf32_Shdr shdr_mem; + + if (unlikely (pread_retry (elf->fildes, &shdr_mem, + sizeof (Elf32_Shdr), offset) + != sizeof (Elf32_Shdr))) + { + /* We must be able to read this ELF section header. */ + __libelf_seterrno (ELF_E_INVALID_FILE); + result = -1; + goto out; + } + + if (elf->state.elf32.ehdr->e_ident[EI_DATA] != MY_ELFDATA) + CONVERT (shdr_mem.sh_link); + num = shdr_mem.sh_link; + } + } + else + { + if (elf->state.elf64.scns.data[0].shdr.e64 != NULL) + { + num = elf->state.elf64.scns.data[0].shdr.e64->sh_link; + goto success; + } + + size_t offset = elf->state.elf64.ehdr->e_shoff; + + if (elf->map_address != NULL + && elf->state.elf64.ehdr->e_ident[EI_DATA] == MY_ELFDATA + && (ALLOW_UNALIGNED + || (((size_t) ((char *) elf->map_address + offset)) + & (__alignof__ (Elf64_Shdr) - 1)) == 0)) + /* We can directly access the memory. */ + num = ((Elf64_Shdr *) (elf->map_address + offset))->sh_link; + else + { + /* We avoid reading in all the section headers. Just read + the first one. */ + Elf64_Shdr shdr_mem; + + if (unlikely (pread_retry (elf->fildes, &shdr_mem, + sizeof (Elf64_Shdr), offset) + != sizeof (Elf64_Shdr))) + { + /* We must be able to read this ELF section header. */ + __libelf_seterrno (ELF_E_INVALID_FILE); + result = -1; + goto out; + } + + if (elf->state.elf64.ehdr->e_ident[EI_DATA] != MY_ELFDATA) + CONVERT (shdr_mem.sh_link); + num = shdr_mem.sh_link; + } + } + } + + /* Store the result. */ + success: + *dst = num; + } + + out: + rwlock_unlock (elf->lock); + + return result; +} +INTDEF(elf_getshdrstrndx) +/* Alias for the deprecated name. */ +strong_alias (elf_getshdrstrndx, elf_getshstrndx) diff --git a/libelf/elf_getshnum.c b/libelf/elf_getshnum.c deleted file mode 100644 index 3c65ef4c..00000000 --- a/libelf/elf_getshnum.c +++ /dev/null @@ -1,109 +0,0 @@ -/* Return number of sections in the ELF file. - Copyright (C) 2002 Red Hat, Inc. - This file is part of Red Hat elfutils. - Written by Ulrich Drepper , 2002. - - Red Hat elfutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by the - Free Software Foundation; version 2 of the License. - - Red Hat elfutils is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License along - with Red Hat elfutils; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. - - In addition, as a special exception, Red Hat, Inc. gives You the - additional right to link the code of Red Hat elfutils with code licensed - under any Open Source Initiative certified open source license - (http://www.opensource.org/licenses/index.php) which requires the - distribution of source code with any binary distribution and to - distribute linked combinations of the two. Non-GPL Code permitted under - this exception must only link to the code of Red Hat elfutils through - those well defined interfaces identified in the file named EXCEPTION - found in the source code files (the "Approved Interfaces"). The files - of Non-GPL Code may instantiate templates or use macros or inline - functions from the Approved Interfaces without causing the resulting - work to be covered by the GNU General Public License. Only Red Hat, - Inc. may make changes or additions to the list of Approved Interfaces. - Red Hat's grant of this exception is conditioned upon your not adding - any new exceptions. If you wish to add a new Approved Interface or - exception, please contact Red Hat. You must obey the GNU General Public - License in all respects for all of the Red Hat elfutils code and other - code used in conjunction with Red Hat elfutils except the Non-GPL Code - covered by this exception. If you modify this file, you may extend this - exception to your version of the file, but you are not obligated to do - so. If you do not wish to provide this exception without modification, - you must delete this exception statement from your version and license - this file solely under the GPL without exception. - - Red Hat elfutils is an included package of the Open Invention Network. - An included package of the Open Invention Network is a package for which - Open Invention Network licensees cross-license their patents. No patent - license is granted, either expressly or impliedly, by designation as an - included package. Should you wish to participate in the Open Invention - Network licensing program, please visit www.openinventionnetwork.com - . */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include -#include - -#include "libelfP.h" - - -int -__elf_getshnum_rdlock (elf, dst) - Elf *elf; - size_t *dst; -{ - int result = 0; - int idx; - - if (elf == NULL) - return -1; - - if (unlikely (elf->kind != ELF_K_ELF)) - { - __libelf_seterrno (ELF_E_INVALID_HANDLE); - return -1; - } - - idx = elf->state.elf.scns_last->cnt; - if (idx != 0 - || (elf->state.elf.scns_last - != (elf->class == ELFCLASS32 - || (offsetof (Elf, state.elf32.scns) - == offsetof (Elf, state.elf64.scns)) - ? &elf->state.elf32.scns : &elf->state.elf64.scns))) - /* There is at least one section. */ - *dst = 1 + elf->state.elf.scns_last->data[idx - 1].index; - else - *dst = 0; - - return result; -} - -int -elf_getshnum (elf, dst) - Elf *elf; - size_t *dst; -{ - int result; - - if (elf == NULL) - return -1; - - rwlock_rdlock (elf->lock); - result = __elf_getshnum_rdlock (elf, dst); - rwlock_unlock (elf->lock); - - return result; -} diff --git a/libelf/elf_getshstrndx.c b/libelf/elf_getshstrndx.c deleted file mode 100644 index 52516a8e..00000000 --- a/libelf/elf_getshstrndx.c +++ /dev/null @@ -1,203 +0,0 @@ -/* Return section index of section header string table. - Copyright (C) 2002, 2005 Red Hat, Inc. - This file is part of Red Hat elfutils. - Written by Ulrich Drepper , 2002. - - Red Hat elfutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by the - Free Software Foundation; version 2 of the License. - - Red Hat elfutils is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License along - with Red Hat elfutils; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. - - In addition, as a special exception, Red Hat, Inc. gives You the - additional right to link the code of Red Hat elfutils with code licensed - under any Open Source Initiative certified open source license - (http://www.opensource.org/licenses/index.php) which requires the - distribution of source code with any binary distribution and to - distribute linked combinations of the two. Non-GPL Code permitted under - this exception must only link to the code of Red Hat elfutils through - those well defined interfaces identified in the file named EXCEPTION - found in the source code files (the "Approved Interfaces"). The files - of Non-GPL Code may instantiate templates or use macros or inline - functions from the Approved Interfaces without causing the resulting - work to be covered by the GNU General Public License. Only Red Hat, - Inc. may make changes or additions to the list of Approved Interfaces. - Red Hat's grant of this exception is conditioned upon your not adding - any new exceptions. If you wish to add a new Approved Interface or - exception, please contact Red Hat. You must obey the GNU General Public - License in all respects for all of the Red Hat elfutils code and other - code used in conjunction with Red Hat elfutils except the Non-GPL Code - covered by this exception. If you modify this file, you may extend this - exception to your version of the file, but you are not obligated to do - so. If you do not wish to provide this exception without modification, - you must delete this exception statement from your version and license - this file solely under the GPL without exception. - - Red Hat elfutils is an included package of the Open Invention Network. - An included package of the Open Invention Network is a package for which - Open Invention Network licensees cross-license their patents. No patent - license is granted, either expressly or impliedly, by designation as an - included package. Should you wish to participate in the Open Invention - Network licensing program, please visit www.openinventionnetwork.com - . */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include -#include -#include -#include - -#include -#include "libelfP.h" -#include "common.h" - - -int -elf_getshstrndx (elf, dst) - Elf *elf; - size_t *dst; -{ - int result = 0; - - if (elf == NULL) - return -1; - - if (unlikely (elf->kind != ELF_K_ELF)) - { - __libelf_seterrno (ELF_E_INVALID_HANDLE); - return -1; - } - - rwlock_rdlock (elf->lock); - - /* We rely here on the fact that the `elf' element is a common prefix - of `elf32' and `elf64'. */ - assert (offsetof (struct Elf, state.elf.ehdr) - == offsetof (struct Elf, state.elf32.ehdr)); - assert (sizeof (elf->state.elf.ehdr) - == sizeof (elf->state.elf32.ehdr)); - assert (offsetof (struct Elf, state.elf.ehdr) - == offsetof (struct Elf, state.elf64.ehdr)); - assert (sizeof (elf->state.elf.ehdr) - == sizeof (elf->state.elf64.ehdr)); - - if (unlikely (elf->state.elf.ehdr == NULL)) - { - __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR); - result = -1; - } - else - { - Elf32_Word num; - - num = (elf->class == ELFCLASS32 - ? elf->state.elf32.ehdr->e_shstrndx - : elf->state.elf64.ehdr->e_shstrndx); - - /* Determine whether the index is too big to fit in the ELF - header. */ - if (unlikely (num == SHN_XINDEX)) - { - /* Yes. Search the zeroth section header. */ - if (elf->class == ELFCLASS32) - { - size_t offset; - - if (elf->state.elf32.scns.data[0].shdr.e32 != NULL) - { - num = elf->state.elf32.scns.data[0].shdr.e32->sh_link; - goto success; - } - - offset = elf->state.elf32.ehdr->e_shoff; - - if (elf->map_address != NULL - && elf->state.elf32.ehdr->e_ident[EI_DATA] == MY_ELFDATA - && (ALLOW_UNALIGNED - || (((size_t) ((char *) elf->map_address + offset)) - & (__alignof__ (Elf32_Shdr) - 1)) == 0)) - /* We can directly access the memory. */ - num = ((Elf32_Shdr *) (elf->map_address + offset))->sh_link; - else - { - /* We avoid reading in all the section headers. Just read - the first one. */ - Elf32_Shdr shdr_mem; - - if (unlikely (pread_retry (elf->fildes, &shdr_mem, - sizeof (Elf32_Shdr), offset) - != sizeof (Elf32_Shdr))) - { - /* We must be able to read this ELF section header. */ - __libelf_seterrno (ELF_E_INVALID_FILE); - result = -1; - goto out; - } - - if (elf->state.elf32.ehdr->e_ident[EI_DATA] != MY_ELFDATA) - CONVERT (shdr_mem.sh_link); - num = shdr_mem.sh_link; - } - } - else - { - if (elf->state.elf64.scns.data[0].shdr.e64 != NULL) - { - num = elf->state.elf64.scns.data[0].shdr.e64->sh_link; - goto success; - } - - size_t offset = elf->state.elf64.ehdr->e_shoff; - - if (elf->map_address != NULL - && elf->state.elf64.ehdr->e_ident[EI_DATA] == MY_ELFDATA - && (ALLOW_UNALIGNED - || (((size_t) ((char *) elf->map_address + offset)) - & (__alignof__ (Elf64_Shdr) - 1)) == 0)) - /* We can directly access the memory. */ - num = ((Elf64_Shdr *) (elf->map_address + offset))->sh_link; - else - { - /* We avoid reading in all the section headers. Just read - the first one. */ - Elf64_Shdr shdr_mem; - - if (unlikely (pread_retry (elf->fildes, &shdr_mem, - sizeof (Elf64_Shdr), offset) - != sizeof (Elf64_Shdr))) - { - /* We must be able to read this ELF section header. */ - __libelf_seterrno (ELF_E_INVALID_FILE); - result = -1; - goto out; - } - - if (elf->state.elf64.ehdr->e_ident[EI_DATA] != MY_ELFDATA) - CONVERT (shdr_mem.sh_link); - num = shdr_mem.sh_link; - } - } - } - - /* Store the result. */ - success: - *dst = num; - } - - out: - rwlock_unlock (elf->lock); - - return result; -} -INTDEF(elf_getshstrndx) diff --git a/libelf/libelf.h b/libelf/libelf.h index dea0d838..16c7a7a2 100644 --- a/libelf/libelf.h +++ b/libelf/libelf.h @@ -1,5 +1,5 @@ /* Interface for libelf. - Copyright (C) 1998, 1999, 2000, 2002, 2004, 2005, 2006, 2007 Red Hat, Inc. + Copyright (C) 1998-2000, 2002, 2004-2007, 2009 Red Hat, Inc. This file is part of Red Hat elfutils. Red Hat elfutils is free software; you can redistribute it and/or modify @@ -256,14 +256,24 @@ extern int elf_scnshndx (Elf_Scn *__scn); sections than can be represented in the e_shnum field of the ELF header the information from the sh_size field in the zeroth section header is used. */ -extern int elf_getshnum (Elf *__elf, size_t *__dst); +extern int elf_getshdrnum (Elf *__elf, size_t *__dst); +/* Sun messed up the implementation of 'elf_getshnum' in their implementation. + It was agreed to make the same functionality available under a different + name and obsolete the old name. */ +extern int elf_getshnum (Elf *__elf, size_t *__dst) + __attribute__ ((__deprecated__)); /* Get the section index of the section header string table in the ELF file. If the index cannot be represented in the e_shnum field of the ELF header the information from the sh_link field in the zeroth section header is used. */ -extern int elf_getshstrndx (Elf *__elf, size_t *__dst); +extern int elf_getshdrstrndx (Elf *__elf, size_t *__dst); +/* Sun messed up the implementation of 'elf_getshnum' in their implementation. + It was agreed to make the same functionality available under a different + name and obsolete the old name. */ +extern int elf_getshstrndx (Elf *__elf, size_t *__dst) + __attribute__ ((__deprecated__)); /* Retrieve section header of ELFCLASS32 binary. */ diff --git a/libelf/libelf.map b/libelf/libelf.map index c2537774..e0f40eb8 100644 --- a/libelf/libelf.map +++ b/libelf/libelf.map @@ -128,3 +128,8 @@ ELFUTILS_1.4 { global: elf_scnshndx; } ELFUTILS_1.3; + +ELFUTILS_1.5 { + global: + elf_getshdrnum; elf_getshdrstrndx; +} ELFUTILS_1.4; diff --git a/libelf/libelfP.h b/libelf/libelfP.h index 818f42ac..47d7c2c5 100644 --- a/libelf/libelfP.h +++ b/libelf/libelfP.h @@ -533,11 +533,12 @@ extern Elf32_Phdr *__elf32_newphdr_internal (Elf *__elf, size_t __cnt) extern Elf64_Phdr *__elf64_newphdr_internal (Elf *__elf, size_t __cnt) attribute_hidden; extern Elf_Scn *__elf32_offscn_internal (Elf *__elf, Elf32_Off __offset) - attribute_hidden; + attribute_hidden; extern Elf_Scn *__elf64_offscn_internal (Elf *__elf, Elf64_Off __offset) - attribute_hidden; -extern int __elf_getshnum_rdlock (Elf *__elf, size_t *__dst) internal_function; -extern int __elf_getshstrndx_internal (Elf *__elf, size_t *__dst) + attribute_hidden; +extern int __elf_getshdrnum_rdlock (Elf *__elf, size_t *__dst) + internal_function; +extern int __elf_getshdrstrndx_internal (Elf *__elf, size_t *__dst) attribute_hidden; extern Elf32_Shdr *__elf32_getshdr_rdlock (Elf_Scn *__scn) internal_function; extern Elf64_Shdr *__elf64_getshdr_rdlock (Elf_Scn *__scn) internal_function; diff --git a/src/ChangeLog b/src/ChangeLog index 01a2414a..f74b31d5 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,14 @@ +2009-06-13 Ulrich Drepper + + * ldgeneric.c: Don't use deprecated libelf functions. + * nm.c: Likewise. + * objdump.c: Likewise. + * readelf.c: Likewise. + * size.c: Likewise. + * strip.c: Likewise. + * unstrip.c: Likewise. + * ld.h: Fix up comment. + 2009-06-01 Ulrich Drepper * readelf.c (print_relocs): Expect ELF header argument and pass on diff --git a/src/ld.h b/src/ld.h index 535f7cd2..72d5b27b 100644 --- a/src/ld.h +++ b/src/ld.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001, 2002, 2003, 2005, 2006, 2008 Red Hat, Inc. +/* Copyright (C) 2001, 2002, 2003, 2005, 2006, 2008, 2009 Red Hat, Inc. This file is part of Red Hat elfutils. Written by Ulrich Drepper , 2001. @@ -146,7 +146,7 @@ struct usedfiles separate field and not the e_shstrndx field in the ELF header since in case of a file with more than 64000 sections the index might be stored in the section header of section zero. The - elf_getshstrndx() function can find the value but it is too + elf_getshdrstrndx() function can find the value but it is too costly to repeat this call over and over. */ size_t shstrndx; diff --git a/src/ldgeneric.c b/src/ldgeneric.c index 8df2a57e..b2ea2f90 100644 --- a/src/ldgeneric.c +++ b/src/ldgeneric.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008 Red Hat, Inc. +/* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008, 2009 Red Hat, Inc. This file is part of Red Hat elfutils. Written by Ulrich Drepper , 2001. @@ -656,7 +656,7 @@ check_definition (const XElf_Sym *sym, size_t shndx, size_t symidx, Elf32_Word xndx; size_t shnum; - if (elf_getshnum (fileinfo->elf, &shnum) < 0) + if (elf_getshdrnum (fileinfo->elf, &shnum) < 0) error (EXIT_FAILURE, 0, gettext ("cannot determine number of sections: %s"), elf_errmsg (-1)); @@ -1117,7 +1117,7 @@ add_relocatable_file (struct usedfiles *fileinfo, GElf_Word secttype) assert (fileinfo->elf != NULL); /* Allocate memory for the sections. */ - if (unlikely (elf_getshnum (fileinfo->elf, &scncnt) < 0)) + if (unlikely (elf_getshdrnum (fileinfo->elf, &scncnt) < 0)) error (EXIT_FAILURE, 0, gettext ("cannot determine number of sections: %s"), elf_errmsg (-1)); @@ -1619,7 +1619,7 @@ add_relocatable_file (struct usedfiles *fileinfo, GElf_Word secttype) #ifndef NDEBUG size_t shnum; - assert (elf_getshnum (fileinfo->elf, &shnum) == 0); + assert (elf_getshdrnum (fileinfo->elf, &shnum) == 0); assert (shndx < shnum); #endif @@ -2038,7 +2038,7 @@ file_process2 (struct usedfiles *fileinfo) } /* Determine the section header string table section index. */ - if (unlikely (elf_getshstrndx (fileinfo->elf, &fileinfo->shstrndx) + if (unlikely (elf_getshdrstrndx (fileinfo->elf, &fileinfo->shstrndx) < 0)) { fprintf (stderr, gettext ("\ @@ -4148,7 +4148,7 @@ compute_hash_sum (void (*hashfct) (const void *, size_t, void *), void *ctx) { /* The call cannot fail. */ size_t shstrndx; - (void) elf_getshstrndx (ld_state.outelf, &shstrndx); + (void) elf_getshdrstrndx (ld_state.outelf, &shstrndx); const char *ident = elf_getident (ld_state.outelf, NULL); bool same_byte_order = ((ident[EI_DATA] == ELFDATA2LSB diff --git a/src/nm.c b/src/nm.c index 8833948a..01519a5a 100644 --- a/src/nm.c +++ b/src/nm.c @@ -724,7 +724,7 @@ show_symbols_sysv (Ebl *ebl, GElf_Word strndx, int longest_where) { size_t shnum; - if (elf_getshnum (ebl->elf, &shnum) < 0) + if (elf_getshdrnum (ebl->elf, &shnum) < 0) INTERNAL_ERROR (fullname); bool scnnames_malloced = shnum * sizeof (const char *) > 128 * 1024; @@ -735,7 +735,7 @@ show_symbols_sysv (Ebl *ebl, GElf_Word strndx, scnnames = (const char **) alloca (sizeof (const char *) * shnum); /* Get the section header string table index. */ size_t shstrndx; - if (elf_getshstrndx (ebl->elf, &shstrndx) < 0) + if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0) error (EXIT_FAILURE, 0, gettext ("cannot get section header string table index")); @@ -997,7 +997,7 @@ show_symbols (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, Elf_Scn *xndxscn, { /* Get the section header string table index. */ size_t shstrndx; - if (elf_getshstrndx (ebl->elf, &shstrndx) < 0) + if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0) error (EXIT_FAILURE, 0, gettext ("cannot get section header string table index")); diff --git a/src/objdump.c b/src/objdump.c index af8abf78..1234c794 100644 --- a/src/objdump.c +++ b/src/objdump.c @@ -739,7 +739,7 @@ handle_elf (Elf *elf, const char *prefix, const char *fname, /* Get the section header string table index. */ size_t shstrndx; - if (elf_getshstrndx (ebl->elf, &shstrndx) < 0) + if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0) error (EXIT_FAILURE, 0, gettext ("cannot get section header string table index")); diff --git a/src/readelf.c b/src/readelf.c index 9ce46042..ca9772e4 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -608,7 +608,7 @@ process_elf_file (Dwfl_Module *dwflmod, int fd) } /* Determine the number of sections. */ - if (unlikely (elf_getshnum (ebl->elf, &shnum) < 0)) + if (unlikely (elf_getshdrnum (ebl->elf, &shnum) < 0)) error (EXIT_FAILURE, 0, gettext ("cannot determine number of sections: %s"), elf_errmsg (-1)); @@ -847,7 +847,7 @@ There are %d section headers, starting at offset %#" PRIx64 ":\n\ ehdr->e_shnum, ehdr->e_shoff); /* Get the section header string table index. */ - if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0)) + if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)) error (EXIT_FAILURE, 0, gettext ("cannot get section header string table index")); @@ -990,7 +990,7 @@ print_phdr (Ebl *ebl, GElf_Ehdr *ehdr) /* Get the section header string table index. */ size_t shstrndx; - if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0)) + if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)) error (EXIT_FAILURE, 0, gettext ("cannot get section header string table index")); @@ -1131,7 +1131,7 @@ handle_scngrp (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) /* Get the section header string table index. */ size_t shstrndx; - if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0)) + if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)) error (EXIT_FAILURE, 0, gettext ("cannot get section header string table index")); @@ -1313,7 +1313,7 @@ handle_dynamic (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) return; /* Get the section header string table index. */ - if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0)) + if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)) error (EXIT_FAILURE, 0, gettext ("cannot get section header string table index")); @@ -1511,7 +1511,7 @@ handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr) /* Get the section header string table index. */ size_t shstrndx; - if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0)) + if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)) error (EXIT_FAILURE, 0, gettext ("cannot get section header string table index")); @@ -1697,7 +1697,7 @@ handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr) /* Get the section header string table index. */ size_t shstrndx; - if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0)) + if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)) error (EXIT_FAILURE, 0, gettext ("cannot get section header string table index")); @@ -1907,7 +1907,7 @@ handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) /* Get the section header string table index. */ size_t shstrndx; - if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0)) + if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)) error (EXIT_FAILURE, 0, gettext ("cannot get section header string table index")); @@ -2161,7 +2161,7 @@ handle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) /* Get the section header string table index. */ size_t shstrndx; - if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0)) + if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)) error (EXIT_FAILURE, 0, gettext ("cannot get section header string table index")); @@ -2227,7 +2227,7 @@ handle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) /* Get the section header string table index. */ size_t shstrndx; - if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0)) + if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)) error (EXIT_FAILURE, 0, gettext ("cannot get section header string table index")); @@ -2305,7 +2305,7 @@ handle_versym (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr) /* Get the section header string table index. */ size_t shstrndx; - if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0)) + if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)) error (EXIT_FAILURE, 0, gettext ("cannot get section header string table index")); @@ -2802,7 +2802,7 @@ handle_hash (Ebl *ebl) { /* Get the section header string table index. */ size_t shstrndx; - if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0)) + if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)) error (EXIT_FAILURE, 0, gettext ("cannot get section header string table index")); @@ -2838,7 +2838,7 @@ print_liblist (Ebl *ebl) /* Get the section header string table index. */ size_t shstrndx; - if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0)) + if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)) error (EXIT_FAILURE, 0, gettext ("cannot get section header string table index")); @@ -2900,7 +2900,7 @@ print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr) /* Get the section header string table index. */ size_t shstrndx; - if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0)) + if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)) error (EXIT_FAILURE, 0, gettext ("cannot get section header string table index")); @@ -4687,7 +4687,7 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, { size_t shstrndx; /* We know this call will succeed since it did in the caller. */ - (void) elf_getshstrndx (ebl->elf, &shstrndx); + (void) elf_getshdrstrndx (ebl->elf, &shstrndx); const char *scnname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name); Elf_Data *data = elf_rawdata (scn, NULL); @@ -6392,7 +6392,7 @@ print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr) /* Get the section header string table index. */ size_t shstrndx; - if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0)) + if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)) error (EXIT_FAILURE, 0, gettext ("cannot get section header string table index")); @@ -7258,7 +7258,7 @@ handle_notes (Ebl *ebl, GElf_Ehdr *ehdr) { /* Get the section header string table index. */ size_t shstrndx; - if (elf_getshstrndx (ebl->elf, &shstrndx) < 0) + if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0) error (EXIT_FAILURE, 0, gettext ("cannot get section header string table index")); @@ -7403,7 +7403,7 @@ for_each_section_argument (Elf *elf, const struct section_argument *list, { /* Get the section header string table index. */ size_t shstrndx; - if (elf_getshstrndx (elf, &shstrndx) < 0) + if (elf_getshdrstrndx (elf, &shstrndx) < 0) error (EXIT_FAILURE, 0, gettext ("cannot get section header string table index")); @@ -7472,7 +7472,7 @@ print_strings (Ebl *ebl) { /* Get the section header string table index. */ size_t shstrndx; - if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0)) + if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)) error (EXIT_FAILURE, 0, gettext ("cannot get section header string table index")); diff --git a/src/size.c b/src/size.c index 4698c350..d3dc1fe5 100644 --- a/src/size.c +++ b/src/size.c @@ -420,7 +420,7 @@ show_sysv (Elf *elf, const char *prefix, const char *fname, /* Get the section header string table index. */ size_t shstrndx; - if (unlikely (elf_getshstrndx (elf, &shstrndx) < 0)) + if (unlikely (elf_getshdrstrndx (elf, &shstrndx) < 0)) error (EXIT_FAILURE, 0, gettext ("cannot get section header string table index")); @@ -494,7 +494,7 @@ show_sysv_one_line (Elf *elf) { /* Get the section header string table index. */ size_t shstrndx; - if (unlikely (elf_getshstrndx (elf, &shstrndx) < 0)) + if (unlikely (elf_getshdrstrndx (elf, &shstrndx) < 0)) error (EXIT_FAILURE, 0, gettext ("cannot get section header string table index")); diff --git a/src/strip.c b/src/strip.c index d788ebf2..32cf0d70 100644 --- a/src/strip.c +++ b/src/strip.c @@ -477,7 +477,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, INTERNAL_ERROR (fname); /* Get the section header string table index. */ - if (unlikely (elf_getshstrndx (elf, &shstrndx) < 0)) + if (unlikely (elf_getshdrstrndx (elf, &shstrndx) < 0)) error (EXIT_FAILURE, 0, gettext ("cannot get section header string table index")); @@ -537,7 +537,7 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname, /* Number of sections. */ size_t shnum; - if (unlikely (elf_getshnum (elf, &shnum) < 0)) + if (unlikely (elf_getshdrnum (elf, &shnum) < 0)) { error (0, 0, gettext ("cannot determine number of sections: %s"), elf_errmsg (-1)); diff --git a/src/unstrip.c b/src/unstrip.c index 97b73c6f..284607b3 100644 --- a/src/unstrip.c +++ b/src/unstrip.c @@ -1218,19 +1218,19 @@ copy_elided_sections (Elf *unstripped, Elf *stripped, const GElf_Ehdr *stripped_ehdr, GElf_Addr bias) { size_t unstripped_shstrndx; - ELF_CHECK (elf_getshstrndx (unstripped, &unstripped_shstrndx) == 0, + ELF_CHECK (elf_getshdrstrndx (unstripped, &unstripped_shstrndx) == 0, _("cannot get section header string table section index: %s")); size_t stripped_shstrndx; - ELF_CHECK (elf_getshstrndx (stripped, &stripped_shstrndx) == 0, + ELF_CHECK (elf_getshdrstrndx (stripped, &stripped_shstrndx) == 0, _("cannot get section header string table section index: %s")); size_t unstripped_shnum; - ELF_CHECK (elf_getshnum (unstripped, &unstripped_shnum) == 0, + ELF_CHECK (elf_getshdrnum (unstripped, &unstripped_shnum) == 0, _("cannot get section count: %s")); size_t stripped_shnum; - ELF_CHECK (elf_getshnum (stripped, &stripped_shnum) == 0, + ELF_CHECK (elf_getshdrnum (stripped, &stripped_shnum) == 0, _("cannot get section count: %s")); /* Cache the stripped file's section details. */ @@ -1461,7 +1461,7 @@ copy_elided_sections (Elf *unstripped, Elf *stripped, strtab); /* Get the updated section count. */ - ELF_CHECK (elf_getshnum (unstripped, &unstripped_shnum) == 0, + ELF_CHECK (elf_getshdrnum (unstripped, &unstripped_shnum) == 0, _("cannot get section count: %s")); bool placed[unstripped_shnum - 1]; -- cgit v1.2.1 From 99d2372b25d1231d786b70278478c7a112f2b27c Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Sun, 14 Jun 2009 20:19:45 -0700 Subject: Squashed commit of the following: commit 77abb31cb8d55980ef92260917a7ecdd228b1a44 Author: Petr Machata Date: Mon Jun 8 15:46:16 2009 +0200 Fix a bug in offset checking commit b794eac4f8d3e08101b5d2924523b1259bbc1b17 Author: Petr Machata Date: Wed Jun 3 16:00:01 2009 +0200 Cosmetic, get rid of defining several variables per line commit a23938fe35d515a3d75a51f6204771f3cf6c9ec4 Author: Petr Machata Date: Wed Jun 3 15:50:03 2009 +0200 Restructure the code to decrease the binary size commit 7c301e3d4e8584dfb3174855fb6af3d5791dfeed Author: Petr Machata Date: Mon Jun 1 19:43:28 2009 +0200 Shuffle a couple pieces of code around to make the code smaller commit 6325323482c2a3e17409d32c7feec9461be26614 Merge: 83ac53d... e94b1b2... Author: Petr Machata Date: Fri May 22 08:49:07 2009 +0200 Merge branch 'master' of ssh://pmachata@git.fedorahosted.org/git/elfutils into pmachata/reader_hooks Conflicts: libdw/ChangeLog commit 83ac53db400945c074e77ec9904efe550903a0e2 Author: Petr Machata Date: Fri May 22 08:40:25 2009 +0200 Call reloc hook with the original address, not incremented commit f1996388745566abc1ca1c1700b3b7eded208575 Author: Petr Machata Date: Wed May 6 16:53:03 2009 +0200 Rewrite boundary checking logic so that it's immune to arithmetic overflow * ... also get rid of some code redundancy. commit 0c1df732822d83548edd0d005f3450281ed1701b Author: Petr Machata Date: Wed May 6 16:25:09 2009 +0200 __libdw_read_offset* take extra argument for header size checks * also presence of debug data and buffer is checked in __libdw_in_section commit 6fb192e360f842cacb34a90c03cd0524cccc3dec Author: Petr Machata Date: Wed May 6 15:51:20 2009 +0200 Check for presence of data before loading the offset commit a2e7612b165d83dd241225f87075fa4f58d18781 Author: Petr Machata Date: Wed May 6 15:04:16 2009 +0200 Cosmetic changes commit 8b1aad2c2f6c8dc02b3e704e4f386c1827e385cb Author: Petr Machata Date: Tue May 5 15:34:13 2009 +0200 Improve reader hook functions a bit * ... so that they are closer match to what's need on call sites commit 3854b7fbab2fe331711365f94a295af82164d0d2 Author: Petr Machata Date: Tue May 5 14:33:50 2009 +0200 Fixes in use of reader hooks in __libdw_formptr and dwarf_formudata * and a bit more commit 335075596b6acef6e59919155e2b087e690a572d Author: Petr Machata Date: Tue May 5 14:32:39 2009 +0200 Rename __libdw_read_udata_addr to __libdw_formptr commit 8273a2adaf8cb2ee203926af2849e4f96f8a6eaf Author: Petr Machata Date: Tue May 5 02:53:40 2009 +0200 Introduce __libdw_read_udata_address * the use in dwarf_ranges is iffy, there's a functionality mismatch. Need to find some better way commit 1c897f4abde1530038d332f4fc03a596a24f6aaf Author: Petr Machata Date: Mon May 4 18:09:13 2009 +0200 ChangeLog entries for previous commit commit 90d7c39454468b91c0fd6514a4e8d821222d6adb Author: Petr Machata Date: Mon May 4 18:07:54 2009 +0200 Fix bugs, introduce __libdw_read_begin_end_pair_inc commit 9b3923f5b69a3e56590769435c4693f057acdc1f Merge: 6200ba6... 589b3d3... Author: Petr Machata Date: Mon May 4 12:22:21 2009 +0200 Merge branch 'master' of ssh://pmachata@git.fedorahosted.org/git/elfutils into pmachata/reader_hooks commit 6200ba62aa9ea3cb9318f73a27181907a528dbe4 Author: Petr Machata Date: Wed Apr 29 15:31:28 2009 +0200 dwarf_getlocation_addr uses read hooks commit ecbb8cdd8b500e37dc34fc246b912f704fe31ca4 Author: Petr Machata Date: Wed Apr 29 15:16:09 2009 +0200 dwarf_ranges and dwarf_formref use read hooks commit cb8f67b29a896c2660c10aa1028a9dbb377553e9 Author: Petr Machata Date: Tue Apr 28 18:39:04 2009 +0200 Convert several new functions to use read hooks commit b130453eb16a8cf042915e312cc5f189b8b92c01 Author: Petr Machata Date: Tue Apr 28 18:38:27 2009 +0200 Add length read hooks commit bd885ff694817b965231d99f1ab867947998e734 Author: Petr Machata Date: Tue Apr 28 18:36:17 2009 +0200 Constify read hook arguments commit 66fe03f1e489a88b89a15c9e13f9bd33db2729b1 Author: Petr Machata Date: Tue Apr 28 16:11:05 2009 +0200 Change type of return value of offset read hooks to Dwarf_Off commit 22b36e00cc228f5a966f84ca3323e5d652923ce8 Merge: 5b3534b... a7cb532... Author: Petr Machata Date: Mon Apr 27 19:05:25 2009 +0200 Merge branch 'master' of ssh://pmachata@git.fedorahosted.org/git/elfutils into pmachata/reader_hooks commit 5b3534b62cbd45fe4f11dd1be3e492237938cce0 Author: Petr Machata Date: Mon Apr 27 18:53:06 2009 +0200 Rewrites in read hooks * Have the checking and reading logic itself in the header so that it gets optimized out/inlined. Call external relocating hook from there, there will presumably be more work to do, and we presumably don't want to keep this in the header. commit 9e265d71d0eb900e76d6fdb0196ef4fc6507f3a7 Merge: 1783089... 300f3a4... Author: Petr Machata Date: Thu Apr 23 17:45:25 2009 +0200 Merge branch 'master' of ssh://pmachata@git.fedorahosted.org/git/elfutils into pmachata/reader_hooks commit 1783089b184ddea2081bbe5ac4e80420cb6b0803 Author: Petr Machata Date: Thu Apr 23 17:44:48 2009 +0200 Use the new reader hooks in several places commit 11c3d97a5b40ea15edf324092b03da3050610d01 Author: Petr Machata Date: Thu Apr 23 17:40:03 2009 +0200 Introduce reader hooks --- libdw/ChangeLog | 34 +++++++++++ libdw/dwarf_formaddr.c | 8 +-- libdw/dwarf_formref_die.c | 7 +-- libdw/dwarf_formstring.c | 12 +--- libdw/dwarf_formudata.c | 53 ++++++++++++++-- libdw/dwarf_getaranges.c | 27 ++++----- libdw/dwarf_getlocation.c | 94 ++++++++++------------------- libdw/dwarf_getpubnames.c | 15 ++--- libdw/dwarf_getsrclines.c | 27 ++++----- libdw/dwarf_nextcu.c | 15 +++-- libdw/dwarf_ranges.c | 105 +++++++++++++++++++++----------- libdw/libdwP.h | 150 ++++++++++++++++++++++++++++++++++++++++++++++ 12 files changed, 377 insertions(+), 170 deletions(-) diff --git a/libdw/ChangeLog b/libdw/ChangeLog index 0e317d7c..525bb329 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,3 +1,37 @@ +2009-05-05 Petr Machata + + * libdwP.h (__libdw_formptr): Declare new function. + * dwarf_formudata.c: Implement it here. + * dwarf_getlocation.c (dwarf_getlocation_addr): + Call it instead of hand-rolled offset handling code. + * dwarf_getsrclines.c (dwarf_getsrclines): Likewise. + * dwarf_ranges.c (dwarf_ranges): Likewise. + +2009-05-04 Petr Machata + + * libdwP.h (__libdw_read_begin_end_pair_inc): Declare new function. + * dwarf_ranges.c: Implement it here. + (dwarf_ranges): Call it. + * dwarf_getlocation.c (dwarf_getlocation_addr): Call it also here. + +2009-04-23 Petr Machata + + * dwarf_formaddr.c (dwarf_formaddr): Call __libdw_read_* instead + of read_*ubyte_unaligned. + * dwarf_formref_die.c (dwarf_formref_die): Likewise. + * dwarf_formstring.c (dwarf_formstring): Likewise. + * dwarf_formudate.c (dwarf_formudata): Likewise. + * dwarf_getaranges.c (dwarf_getaranges): Likewise. + * dwarf_getlocation.c (dwarf_getlocation_addr): Likewise. + * dwarf_getpubnames.c (get_offsets): Likewise. + * dwarf_nextcu.c (dwarf_nextcu): Likewise. + +2009-04-23 Petr Machata + + * libdwP.h (__libdw_read_addr_inc, __libdw_read_off_inc, + __libdw_read_addr, __libdw_read_off): Add four new internal + functions. + 2009-05-07 Roland McGrath * dwarf_getmacros.c (dwarf_getmacros): Use absolute section offset in diff --git a/libdw/dwarf_formaddr.c b/libdw/dwarf_formaddr.c index dcb58d43..9938be7e 100644 --- a/libdw/dwarf_formaddr.c +++ b/libdw/dwarf_formaddr.c @@ -70,10 +70,10 @@ dwarf_formaddr (attr, return_addr) return -1; } - if (attr->cu->address_size == 8) - *return_addr = read_8ubyte_unaligned (attr->cu->dbg, attr->valp); - else - *return_addr = read_4ubyte_unaligned (attr->cu->dbg, attr->valp); + if (__libdw_read_address (attr->cu->dbg, + IDX_debug_info, attr->valp, + attr->cu->address_size, return_addr)) + return -1; return 0; } diff --git a/libdw/dwarf_formref_die.c b/libdw/dwarf_formref_die.c index 90a4b2d3..a004a0fd 100644 --- a/libdw/dwarf_formref_die.c +++ b/libdw/dwarf_formref_die.c @@ -72,10 +72,9 @@ dwarf_formref_die (attr, die_mem) ? attr->cu->address_size : attr->cu->offset_size); - if (ref_size == 8) - offset = read_8ubyte_unaligned (attr->cu->dbg, attr->valp); - else - offset = read_4ubyte_unaligned (attr->cu->dbg, attr->valp); + if (__libdw_read_offset (attr->cu->dbg, IDX_debug_info, attr->valp, + ref_size, &offset, IDX_debug_info, 0)) + return NULL; } else { diff --git a/libdw/dwarf_formstring.c b/libdw/dwarf_formstring.c index 790831ea..f95d31b8 100644 --- a/libdw/dwarf_formstring.c +++ b/libdw/dwarf_formstring.c @@ -74,20 +74,14 @@ dwarf_formstring (attrp) if (unlikely (attrp->form != DW_FORM_strp) || dbg->sectiondata[IDX_debug_str] == NULL) { - invalid_error: __libdw_seterrno (DWARF_E_NO_STRING); return NULL; } uint64_t off; - // XXX We need better boundary checks. - if (attrp->cu->offset_size == 8) - off = read_8ubyte_unaligned (dbg, attrp->valp); - else - off = read_4ubyte_unaligned (dbg, attrp->valp); - - if (off >= dbg->sectiondata[IDX_debug_str]->d_size) - goto invalid_error; + if (__libdw_read_offset (dbg, IDX_debug_info, attrp->valp, + attrp->cu->offset_size, &off, IDX_debug_str, 1)) + return NULL; return (const char *) dbg->sectiondata[IDX_debug_str]->d_buf + off; } diff --git a/libdw/dwarf_formudata.c b/libdw/dwarf_formudata.c index b5c40bb5..04f04aae 100644 --- a/libdw/dwarf_formudata.c +++ b/libdw/dwarf_formudata.c @@ -55,6 +55,51 @@ #include #include "libdwP.h" +internal_function unsigned char * +__libdw_formptr (Dwarf_Attribute *attr, int sec_index, + int err_nodata, unsigned char **endpp, + Dwarf_Off *offsetp) +{ + if (attr == NULL) + return NULL; + + const Elf_Data *d = attr->cu->dbg->sectiondata[sec_index]; + if (unlikely (d == NULL)) + { + __libdw_seterrno (err_nodata); + return NULL; + } + + Dwarf_Word offset; + switch (attr->form) + { + case DW_FORM_data4: + case DW_FORM_data8: + if (__libdw_read_offset (attr->cu->dbg, IDX_debug_info, attr->valp, + attr->form == DW_FORM_data4 ? 4 : 8, + &offset, sec_index, 0)) + return NULL; + break; + + default: + if (INTUSE(dwarf_formudata) (attr, &offset)) + return NULL; + }; + + unsigned char *readp = d->d_buf + offset; + unsigned char *endp = d->d_buf + d->d_size; + if (unlikely (readp >= endp)) + { + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return NULL; + } + + if (endpp != NULL) + *endpp = endp; + if (offsetp != NULL) + *offsetp = offset; + return readp; +} int dwarf_formudata (attr, return_uval) @@ -77,11 +122,11 @@ dwarf_formudata (attr, return_uval) break; case DW_FORM_data4: - *return_uval = read_4ubyte_unaligned (attr->cu->dbg, attr->valp); - break; - case DW_FORM_data8: - *return_uval = read_8ubyte_unaligned (attr->cu->dbg, attr->valp); + if (__libdw_read_address (attr->cu->dbg, IDX_debug_info, attr->valp, + attr->form == DW_FORM_data4 ? 4 : 8, + return_uval)) + return -1; break; case DW_FORM_sdata: diff --git a/libdw/dwarf_getaranges.c b/libdw/dwarf_getaranges.c index 96e99620..74f04ea5 100644 --- a/libdw/dwarf_getaranges.c +++ b/libdw/dwarf_getaranges.c @@ -149,14 +149,10 @@ dwarf_getaranges (dbg, aranges, naranges) } Dwarf_Word offset; - if (length_bytes == 4) - offset = read_4ubyte_unaligned_inc (dbg, readp); - else - offset = read_8ubyte_unaligned_inc (dbg, readp); - - /* Sanity-check the offset. */ - if (offset + 4 > dbg->sectiondata[IDX_debug_info]->d_size) - goto invalid; + if (__libdw_read_offset_inc (dbg, + IDX_debug_aranges, (unsigned char **)&readp, + length_bytes, &offset, IDX_debug_info, 4)) + return -1; unsigned int address_size = *readp++; if (address_size != 4 && address_size != 8) @@ -175,16 +171,15 @@ dwarf_getaranges (dbg, aranges, naranges) Dwarf_Word range_address; Dwarf_Word range_length; + if (__libdw_read_address_inc (dbg, IDX_debug_aranges, + (unsigned char **)&readp, + address_size, &range_address)) + return -1; + if (address_size == 4) - { - range_address = read_4ubyte_unaligned_inc (dbg, readp); - range_length = read_4ubyte_unaligned_inc (dbg, readp); - } + range_length = read_4ubyte_unaligned_inc (dbg, readp); else - { - range_address = read_8ubyte_unaligned_inc (dbg, readp); - range_length = read_8ubyte_unaligned_inc (dbg, readp); - } + range_length = read_8ubyte_unaligned_inc (dbg, readp); /* Two zero values mark the end. */ if (range_address == 0 && range_length == 0) diff --git a/libdw/dwarf_getlocation.c b/libdw/dwarf_getlocation.c index f680aa96..f829e72b 100644 --- a/libdw/dwarf_getlocation.c +++ b/libdw/dwarf_getlocation.c @@ -113,7 +113,7 @@ loc_compare (const void *p1, const void *p2) static int getlocation (struct Dwarf_CU *cu, const Dwarf_Block *block, - Dwarf_Op **llbuf, size_t *listlen) + Dwarf_Op **llbuf, size_t *listlen, int sec_index) { Dwarf *dbg = cu->dbg; @@ -151,24 +151,9 @@ getlocation (struct Dwarf_CU *cu, const Dwarf_Block *block, { case DW_OP_addr: /* Address, depends on address size of CU. */ - if (cu->address_size == 4) - { - if (unlikely (data + 4 > end_data)) - { - invalid: - __libdw_seterrno (DWARF_E_INVALID_DWARF); - return -1; - } - - newloc->number = read_4ubyte_unaligned_inc (dbg, data); - } - else - { - if (unlikely (data + 8 > end_data)) - goto invalid; - - newloc->number = read_8ubyte_unaligned_inc (dbg, data); - } + if (__libdw_read_address_inc (dbg, sec_index, (unsigned char **)&data, + cu->address_size, &newloc->number)) + return -1; break; case DW_OP_deref: @@ -211,7 +196,11 @@ getlocation (struct Dwarf_CU *cu, const Dwarf_Block *block, case DW_OP_deref_size: case DW_OP_xderef_size: if (unlikely (data >= end_data)) - goto invalid; + { + invalid: + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return -1; + } newloc->number = *data++; break; @@ -352,7 +341,7 @@ dwarf_getlocation (attr, llbuf, listlen) if (INTUSE(dwarf_formblock) (attr, &block) != 0) return -1; - return getlocation (attr->cu, &block, llbuf, listlen); + return getlocation (attr->cu, &block, llbuf, listlen, IDX_debug_info); } int @@ -376,7 +365,8 @@ dwarf_getlocation_addr (attr, address, llbufs, listlens, maxlocs) if (maxlocs == 0) return 0; if (llbufs != NULL && - getlocation (attr->cu, &block, &llbufs[0], &listlens[0]) != 0) + getlocation (attr->cu, &block, &llbufs[0], &listlens[0], + IDX_debug_info) != 0) return -1; return listlens[0] == 0 ? 0 : 1; } @@ -388,25 +378,17 @@ dwarf_getlocation_addr (attr, address, llbufs, listlens, maxlocs) return -1; } - /* Must have the form data4 or data8 which act as an offset. */ - Dwarf_Word offset; - if (unlikely (INTUSE(dwarf_formudata) (attr, &offset) != 0)) + unsigned char *endp; + unsigned char *readp = __libdw_formptr (attr, IDX_debug_loc, + DWARF_E_NO_LOCLIST, &endp, NULL); + if (readp == NULL) return -1; - const Elf_Data *d = attr->cu->dbg->sectiondata[IDX_debug_loc]; - if (unlikely (d == NULL)) - { - __libdw_seterrno (DWARF_E_NO_LOCLIST); - return -1; - } - Dwarf_Addr base = (Dwarf_Addr) -1; - unsigned char *readp = d->d_buf + offset; size_t got = 0; while (got < maxlocs) { - if ((unsigned char *) d->d_buf + d->d_size - readp - < attr->cu->address_size * 2) + if (endp - readp < attr->cu->address_size * 2) { invalid: __libdw_seterrno (DWARF_E_INVALID_DWARF); @@ -415,42 +397,25 @@ dwarf_getlocation_addr (attr, address, llbufs, listlens, maxlocs) Dwarf_Addr begin; Dwarf_Addr end; - if (attr->cu->address_size == 8) - { - begin = read_8ubyte_unaligned_inc (attr->cu->dbg, readp); - end = read_8ubyte_unaligned_inc (attr->cu->dbg, readp); - - if (begin == (Elf64_Addr) -1l) /* Base address entry. */ - { - base = end; - if (unlikely (base == (Dwarf_Addr) -1)) - goto invalid; - continue; - } - } - else - { - begin = read_4ubyte_unaligned_inc (attr->cu->dbg, readp); - end = read_4ubyte_unaligned_inc (attr->cu->dbg, readp); - - if (begin == (Elf32_Addr) -1) /* Base address entry. */ - { - base = end; - continue; - } - } - if (begin == 0 && end == 0) /* End of list entry. */ + int status + = __libdw_read_begin_end_pair_inc (attr->cu->dbg, IDX_debug_loc, + &readp, attr->cu->address_size, + &begin, &end, &base); + if (status == 2) /* End of list entry. */ break; + else if (status == 1) /* Base address selected. */ + continue; + else if (status < 0) + return status; - if ((unsigned char *) d->d_buf + d->d_size - readp < 2) + if (endp - readp < 2) goto invalid; /* We have a location expression. */ block.length = read_2ubyte_unaligned_inc (attr->cu->dbg, readp); block.data = readp; - if ((unsigned char *) d->d_buf + d->d_size - readp - < (ptrdiff_t) block.length) + if (endp - readp < (ptrdiff_t) block.length) goto invalid; readp += block.length; @@ -486,7 +451,8 @@ dwarf_getlocation_addr (attr, address, llbufs, listlens, maxlocs) /* This one matches the address. */ if (llbufs != NULL && unlikely (getlocation (attr->cu, &block, - &llbufs[got], &listlens[got]) != 0)) + &llbufs[got], &listlens[got], + IDX_debug_loc) != 0)) return -1; ++got; } diff --git a/libdw/dwarf_getpubnames.c b/libdw/dwarf_getpubnames.c index 1b054e26..5560a758 100644 --- a/libdw/dwarf_getpubnames.c +++ b/libdw/dwarf_getpubnames.c @@ -102,7 +102,6 @@ get_offsets (Dwarf *dbg) else if (unlikely (len >= DWARF3_LENGTH_MIN_ESCAPE_CODE && len <= DWARF3_LENGTH_MAX_ESCAPE_CODE)) { - invalid_dwarf: __libdw_seterrno (DWARF_E_INVALID_DWARF); goto err_return; } @@ -124,18 +123,12 @@ get_offsets (Dwarf *dbg) } /* Get the CU offset. */ - if (len_bytes == 4) - mem[cnt].cu_offset = read_4ubyte_unaligned (dbg, readp + 2); - else - mem[cnt].cu_offset = read_8ubyte_unaligned (dbg, readp + 2); + if (__libdw_read_offset (dbg, IDX_debug_pubnames, readp + 2, len_bytes, + &mem[cnt].cu_offset, IDX_debug_info, 3)) + /* Error has been already set in reader. */ + goto err_return; /* Determine the size of the CU header. */ - if (unlikely (dbg->sectiondata[IDX_debug_info] == NULL - || dbg->sectiondata[IDX_debug_info]->d_buf == NULL - || (mem[cnt].cu_offset + 3 - >= dbg->sectiondata[IDX_debug_info]->d_size))) - goto invalid_dwarf; - unsigned char *infop = ((unsigned char *) dbg->sectiondata[IDX_debug_info]->d_buf + mem[cnt].cu_offset); diff --git a/libdw/dwarf_getsrclines.c b/libdw/dwarf_getsrclines.c index fe0e67d6..efd0459f 100644 --- a/libdw/dwarf_getsrclines.c +++ b/libdw/dwarf_getsrclines.c @@ -135,20 +135,13 @@ dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines, size_t *nlines) /* Get the offset into the .debug_line section. NB: this call also checks whether the previous dwarf_attr call failed. */ - Dwarf_Word offset; - if (INTUSE(dwarf_formudata) (stmt_list, &offset) != 0) + const unsigned char *lineendp; + const unsigned char *linep + = __libdw_formptr (stmt_list, IDX_debug_line, DWARF_E_NO_DEBUG_LINE, + (unsigned char **) &lineendp, NULL); + if (linep == NULL) goto out; - Dwarf *dbg = cu->dbg; - if (dbg->sectiondata[IDX_debug_line] == NULL) - { - __libdw_seterrno (DWARF_E_NO_DEBUG_LINE); - goto out; - } - const uint8_t *linep = dbg->sectiondata[IDX_debug_line]->d_buf + offset; - const uint8_t *lineendp = (dbg->sectiondata[IDX_debug_line]->d_buf - + dbg->sectiondata[IDX_debug_line]->d_size); - /* Get the compilation directory. */ Dwarf_Attribute compdir_attr_mem; Dwarf_Attribute *compdir_attr = INTUSE(dwarf_attr) (cudie, @@ -162,6 +155,8 @@ dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines, size_t *nlines) __libdw_seterrno (DWARF_E_INVALID_DEBUG_LINE); goto out; } + + Dwarf *dbg = cu->dbg; Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep); unsigned int length = 4; if (unlikely (unit_length == DWARF3_LENGTH_64_BIT)) @@ -429,10 +424,10 @@ dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines, size_t *nlines) /* The value is an address. The size is defined as apporiate for the target machine. We use the address size field from the CU header. */ - if (cu->address_size == 4) - address = read_4ubyte_unaligned_inc (dbg, linep); - else - address = read_8ubyte_unaligned_inc (dbg, linep); + if (__libdw_read_address_inc (dbg, IDX_debug_line, + (unsigned char **)&linep, + cu->address_size, &address)) + goto out; break; case DW_LNE_define_file: diff --git a/libdw/dwarf_nextcu.c b/libdw/dwarf_nextcu.c index 9e5a96bc..66cde78a 100644 --- a/libdw/dwarf_nextcu.c +++ b/libdw/dwarf_nextcu.c @@ -84,7 +84,8 @@ dwarf_nextcu (dwarf, off, next_off, header_sizep, abbrev_offsetp, /* This points into the .debug_info section to the beginning of the CU entry. */ - char *bytes = (char *) dwarf->sectiondata[IDX_debug_info]->d_buf + off; + unsigned char *data = dwarf->sectiondata[IDX_debug_info]->d_buf; + unsigned char *bytes = data + off; /* The format of the CU header is described in dwarf2p1 7.5.1: @@ -144,10 +145,10 @@ dwarf_nextcu (dwarf, off, next_off, header_sizep, abbrev_offsetp, /* Get offset in .debug_abbrev. Note that the size of the entry depends on whether this is a 32-bit or 64-bit DWARF definition. */ uint64_t abbrev_offset; - if (offset_size == 4) - abbrev_offset = read_4ubyte_unaligned_inc (dwarf, bytes); - else - abbrev_offset = read_8ubyte_unaligned_inc (dwarf, bytes); + if (__libdw_read_offset_inc (dwarf, IDX_debug_info, &bytes, offset_size, + &abbrev_offset, IDX_debug_abbrev, 0)) + return -1; + if (abbrev_offsetp != NULL) *abbrev_offsetp = abbrev_offset; @@ -162,9 +163,7 @@ dwarf_nextcu (dwarf, off, next_off, header_sizep, abbrev_offsetp, /* Store the header length. */ if (header_sizep != NULL) - *header_sizep = (bytes - - ((char *) dwarf->sectiondata[IDX_debug_info]->d_buf - + off)); + *header_sizep = bytes - (data + off); /* See definition of DIE_OFFSET_FROM_CU_OFFSET macro for an explanation of the trick in this expression. */ diff --git a/libdw/dwarf_ranges.c b/libdw/dwarf_ranges.c index 1eef617b..50fb6ba2 100644 --- a/libdw/dwarf_ranges.c +++ b/libdw/dwarf_ranges.c @@ -55,6 +55,52 @@ #include #include +/* Read up begin/end pair and increment read pointer. + - If it's normal range record, set up `*beginp' and `*endp' and return 0. + - If it's base address selection record, set up `*basep' and return 1. + - If it's end of rangelist, don't set anything and return 2 + - If an error occurs, don't set anything and return -1. */ +internal_function int +__libdw_read_begin_end_pair_inc (Dwarf *dbg, int sec_index, + unsigned char **addrp, int width, + Dwarf_Addr *beginp, Dwarf_Addr *endp, + Dwarf_Addr *basep) +{ + Dwarf_Addr escape = (width == 8 ? (Elf64_Addr) -1 + : (Elf64_Addr) (Elf32_Addr) -1); + Dwarf_Addr begin; + Dwarf_Addr end; + + unsigned char *addr = *addrp; + bool begin_relocated = READ_AND_RELOCATE (__libdw_relocate_address, begin); + bool end_relocated = READ_AND_RELOCATE (__libdw_relocate_address, end); + *addrp = addr; + + /* Unrelocated escape for begin means base address selection. */ + if (begin == escape && !begin_relocated) + { + if (unlikely (end == escape)) + { + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return -1; + } + + if (basep != NULL) + *basep = end; + return 1; + } + + /* Unrelocated pair of zeroes means end of range list. */ + if (begin == 0 && end == 0 && !begin_relocated && !end_relocated) + return 2; + + /* Don't check for begin_relocated == end_relocated. Serve the data + to the client even though it may be buggy. */ + *beginp = begin; + *endp = end; + + return 0; +} ptrdiff_t dwarf_ranges (Dwarf_Die *die, ptrdiff_t offset, Dwarf_Addr *basep, @@ -80,11 +126,12 @@ dwarf_ranges (Dwarf_Die *die, ptrdiff_t offset, Dwarf_Addr *basep, const Elf_Data *d = die->cu->dbg->sectiondata[IDX_debug_ranges]; if (d == NULL && offset != 0) { - no_ranges: __libdw_seterrno (DWARF_E_NO_DEBUG_RANGES); return -1; } + unsigned char *readp; + unsigned char *readendp; if (offset == 0) { Dwarf_Attribute attr_mem; @@ -94,14 +141,12 @@ dwarf_ranges (Dwarf_Die *die, ptrdiff_t offset, Dwarf_Addr *basep, /* No PC attributes in this DIE at all, so an empty range list. */ return 0; - /* Must have the form data4 or data8 which act as an offset. */ Dwarf_Word start_offset; - if (INTUSE(dwarf_formudata) (attr, &start_offset) != 0) + if ((readp = __libdw_formptr (attr, IDX_debug_ranges, + DWARF_E_NO_DEBUG_RANGES, + &readendp, &start_offset)) == NULL) return -1; - if (d == NULL) - goto no_ranges; - offset = start_offset; assert ((Dwarf_Word) offset == start_offset); @@ -127,45 +172,37 @@ dwarf_ranges (Dwarf_Die *die, ptrdiff_t offset, Dwarf_Addr *basep, return -1; } } - else if (offset < 0 || (size_t) offset >= d->d_size) + else { - __libdw_seterrno (DWARF_E_INVALID_OFFSET); - return -1l; - } + if (__libdw_offset_in_section (die->cu->dbg, + IDX_debug_ranges, offset, 1)) + return -1l; - unsigned char *readp = d->d_buf + offset; + readp = d->d_buf + offset; + readendp = d->d_buf + d->d_size; + } next: - if ((unsigned char *) d->d_buf + d->d_size - readp - < die->cu->address_size * 2) + if (readendp - readp < die->cu->address_size * 2) goto invalid; Dwarf_Addr begin; Dwarf_Addr end; - if (die->cu->address_size == 8) - { - begin = read_8ubyte_unaligned_inc (die->cu->dbg, readp); - end = read_8ubyte_unaligned_inc (die->cu->dbg, readp); - if (begin == (uint64_t) -1l) /* Base address entry. */ - { - *basep = end; - goto next; - } - } - else + + switch (__libdw_read_begin_end_pair_inc (die->cu->dbg, IDX_debug_ranges, + &readp, die->cu->address_size, + &begin, &end, basep)) { - begin = read_4ubyte_unaligned_inc (die->cu->dbg, readp); - end = read_4ubyte_unaligned_inc (die->cu->dbg, readp); - if (begin == (uint32_t) -1) /* Base address entry. */ - { - *basep = end; - goto next; - } + case 0: + break; + case 1: + goto next; + case 2: + return 0; + default: + return -1l; } - if (begin == 0 && end == 0) /* End of list entry. */ - return 0; - /* We have an address range entry. */ *startp = *basep + begin; *endp = *basep + end; diff --git a/libdw/libdwP.h b/libdw/libdwP.h index 1d5a9b27..97a2e042 100644 --- a/libdw/libdwP.h +++ b/libdw/libdwP.h @@ -419,6 +419,156 @@ extern int __libdw_visit_scopes (unsigned int depth, extern int __dwarf_errno_internal (void); +/* Reader hooks. */ + +/* Relocation hooks return -1 on error (in that case the error code + must already have been set), 0 if there is no relocation and 1 if a + relocation was present.*/ + +static inline int +__libdw_relocate_address (Dwarf *dbg __attribute__ ((unused)), + int sec_index __attribute__ ((unused)), + const void *addr __attribute__ ((unused)), + int width __attribute__ ((unused)), + Dwarf_Addr *val __attribute__ ((unused))) +{ + return 0; +} + +static inline int +__libdw_relocate_offset (Dwarf *dbg __attribute__ ((unused)), + int sec_index __attribute__ ((unused)), + const void *addr __attribute__ ((unused)), + int width __attribute__ ((unused)), + Dwarf_Off *val __attribute__ ((unused))) +{ + return 0; +} + +static inline Elf_Data * +__libdw_checked_get_data (Dwarf *dbg, int sec_index) +{ + Elf_Data *data = dbg->sectiondata[sec_index]; + if (unlikely (data == NULL) + || unlikely (data->d_buf == NULL)) + { + __libdw_seterrno (DWARF_E_INVALID_DWARF); + return NULL; + } + return data; +} + +static inline int +__libdw_offset_in_section (Dwarf *dbg, int sec_index, + Dwarf_Off offset, size_t size) +{ + Elf_Data *data = __libdw_checked_get_data (dbg, sec_index); + if (data == NULL) + return -1; + if (unlikely (offset > data->d_size) + || unlikely (data->d_size - offset < size)) + { + __libdw_seterrno (DWARF_E_INVALID_OFFSET); + return -1; + } + + return 0; +} + +static inline bool +__libdw_in_section (Dwarf *dbg, int sec_index, + const void *addr, size_t size) +{ + Elf_Data *data = __libdw_checked_get_data (dbg, sec_index); + if (data == NULL) + return false; + if (unlikely (addr < data->d_buf) + || unlikely (data->d_size - (addr - data->d_buf) < size)) + { + __libdw_seterrno (DWARF_E_INVALID_OFFSET); + return false; + } + + return true; +} + +#define READ_AND_RELOCATE(RELOC_HOOK, VAL) \ + ({ \ + if (!__libdw_in_section (dbg, sec_index, addr, width)) \ + return -1; \ + \ + const unsigned char *orig_addr = addr; \ + if (width == 4) \ + VAL = read_4ubyte_unaligned_inc (dbg, addr); \ + else \ + VAL = read_8ubyte_unaligned_inc (dbg, addr); \ + \ + int status = RELOC_HOOK (dbg, sec_index, orig_addr, width, &VAL); \ + if (status < 0) \ + return status; \ + status > 0; \ + }) + +static inline int +__libdw_read_address_inc (Dwarf *dbg, + int sec_index, unsigned char **addrp, + int width, Dwarf_Addr *ret) +{ + unsigned char *addr = *addrp; + READ_AND_RELOCATE (__libdw_relocate_address, (*ret)); + *addrp = addr; + return 0; +} + +static inline int +__libdw_read_address (Dwarf *dbg, + int sec_index, const unsigned char *addr, + int width, Dwarf_Addr *ret) +{ + READ_AND_RELOCATE (__libdw_relocate_address, (*ret)); + return 0; +} + +static inline int +__libdw_read_offset_inc (Dwarf *dbg, + int sec_index, unsigned char **addrp, + int width, Dwarf_Off *ret, int sec_ret, + size_t size) +{ + unsigned char *addr = *addrp; + READ_AND_RELOCATE (__libdw_relocate_offset, (*ret)); + *addrp = addr; + return __libdw_offset_in_section (dbg, sec_ret, *ret, size); +} + +static inline int +__libdw_read_offset (Dwarf *dbg, + int sec_index, const unsigned char *addr, + int width, Dwarf_Off *ret, int sec_ret, + size_t size) +{ + READ_AND_RELOCATE (__libdw_relocate_offset, (*ret)); + return __libdw_offset_in_section (dbg, sec_ret, *ret, size); +} + +/* Read up begin/end pair and increment read pointer. + - If it's normal range record, set up *BEGINP and *ENDP and return 0. + - If it's base address selection record, set up *BASEP and return 1. + - If it's end of rangelist, don't set anything and return 2 + - If an error occurs, don't set anything and return <0. */ +int __libdw_read_begin_end_pair_inc (Dwarf *dbg, int sec_index, + unsigned char **addr, int width, + Dwarf_Addr *beginp, Dwarf_Addr *endp, + Dwarf_Addr *basep) + internal_function; + +unsigned char * __libdw_formptr (Dwarf_Attribute *attr, int sec_index, + int err_nodata, unsigned char **endpp, + Dwarf_Off *offsetp) + internal_function; + + + /* Aliases to avoid PLTs. */ INTDECL (dwarf_attr) INTDECL (dwarf_attr_integrate) -- cgit v1.2.1