125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Recover relocatibility for addresses computed from debug information. 203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Copyright (C) 2005-2009, 2012 Red Hat, Inc. 303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes This file is part of elfutils. 425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes This file is free software; you can redistribute it and/or modify 603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes it under the terms of either 725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes * the GNU Lesser General Public License as published by the Free 903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Software Foundation; either version 3 of the License, or (at 1003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes your option) any later version 1103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 1203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes or 1303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 1403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes * the GNU General Public License as published by the Free 1503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Software Foundation; either version 2 of the License, or (at 1603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes your option) any later version 1703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 1803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes or both in parallel, as here. 1903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 2003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes elfutils is distributed in the hope that it will be useful, but 2125b3c049e70834cf33790a28643ab058b507b35cBen Cheng WITHOUT ANY WARRANTY; without even the implied warranty of 2225b3c049e70834cf33790a28643ab058b507b35cBen Cheng MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 2325b3c049e70834cf33790a28643ab058b507b35cBen Cheng General Public License for more details. 2425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 2503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes You should have received copies of the GNU General Public License and 2603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes the GNU Lesser General Public License along with this program. If 2703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes not, see <http://www.gnu.org/licenses/>. */ 2825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 2925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "libdwflP.h" 3025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <fcntl.h> 3125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <unistd.h> 3225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 3325b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Since dwfl_report_elf lays out the sections already, this will only be 3425b3c049e70834cf33790a28643ab058b507b35cBen Cheng called when the section headers of the debuginfo file are being 3525b3c049e70834cf33790a28643ab058b507b35cBen Cheng consulted instead, or for the section placed at 0. With binutils 3625b3c049e70834cf33790a28643ab058b507b35cBen Cheng strip-to-debug, the symbol table is in the debuginfo file and relocation 3725b3c049e70834cf33790a28643ab058b507b35cBen Cheng looks there. */ 3825b3c049e70834cf33790a28643ab058b507b35cBen Chengint 3925b3c049e70834cf33790a28643ab058b507b35cBen Chengdwfl_offline_section_address (Dwfl_Module *mod, 4025b3c049e70834cf33790a28643ab058b507b35cBen Cheng void **userdata __attribute__ ((unused)), 4125b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *modname __attribute__ ((unused)), 4225b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwarf_Addr base __attribute__ ((unused)), 4325b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *secname __attribute__ ((unused)), 4425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf32_Word shndx, 4525b3c049e70834cf33790a28643ab058b507b35cBen Cheng const GElf_Shdr *shdr __attribute__ ((unused)), 4625b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwarf_Addr *addr) 4725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 4825b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (mod->e_type == ET_REL); 4925b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (shdr->sh_addr == 0); 5025b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (shdr->sh_flags & SHF_ALLOC); 5103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes assert (shndx != 0); 5225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 5325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (mod->debug.elf == NULL) 5425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We are only here because sh_addr is zero even though layout is complete. 5525b3c049e70834cf33790a28643ab058b507b35cBen Cheng The first section in the first file under -e is placed at 0. */ 5625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 5725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 5825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* The section numbers might not match between the two files. 5925b3c049e70834cf33790a28643ab058b507b35cBen Cheng The best we can rely on is the order of SHF_ALLOC sections. */ 6025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 6125b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Scn *ourscn = elf_getscn (mod->debug.elf, shndx); 6225b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Scn *scn = NULL; 6325b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint_fast32_t skip_alloc = 0; 6425b3c049e70834cf33790a28643ab058b507b35cBen Cheng while ((scn = elf_nextscn (mod->debug.elf, scn)) != ourscn) 6525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 6625b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (scn != NULL); 6725b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr shdr_mem; 6825b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *sh = gelf_getshdr (scn, &shdr_mem); 6925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (sh == NULL)) 7025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 7125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (sh->sh_flags & SHF_ALLOC) 7225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ++skip_alloc; 7325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 7425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 7525b3c049e70834cf33790a28643ab058b507b35cBen Cheng scn = NULL; 7625b3c049e70834cf33790a28643ab058b507b35cBen Cheng while ((scn = elf_nextscn (mod->main.elf, scn)) != NULL) 7725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 7825b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr shdr_mem; 7925b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Shdr *main_shdr = gelf_getshdr (scn, &shdr_mem); 8025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (main_shdr == NULL)) 8125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 8225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((main_shdr->sh_flags & SHF_ALLOC) && skip_alloc-- == 0) 8325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 8425b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (main_shdr->sh_flags == shdr->sh_flags); 8525b3c049e70834cf33790a28643ab058b507b35cBen Cheng *addr = main_shdr->sh_addr; 8625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 8725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 8825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 8925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 9025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* This should never happen. */ 9125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 9225b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 9325b3c049e70834cf33790a28643ab058b507b35cBen ChengINTDEF (dwfl_offline_section_address) 9425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 9525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Forward declarations. */ 9625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic Dwfl_Module *process_elf (Dwfl *dwfl, const char *name, 9725b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *file_name, int fd, Elf *elf); 9825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic Dwfl_Module *process_archive (Dwfl *dwfl, const char *name, 9925b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *file_name, int fd, Elf *elf, 10025b3c049e70834cf33790a28643ab058b507b35cBen Cheng int (*predicate) (const char *module, 10125b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *file)); 10225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 10325b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Report one module for an ELF file, or many for an archive. 10425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Always consumes ELF and FD. */ 10525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic Dwfl_Module * 10625b3c049e70834cf33790a28643ab058b507b35cBen Chengprocess_file (Dwfl *dwfl, const char *name, const char *file_name, int fd, 10725b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf *elf, int (*predicate) (const char *module, 10825b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *file)) 10925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 11025b3c049e70834cf33790a28643ab058b507b35cBen Cheng switch (elf_kind (elf)) 11125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 11225b3c049e70834cf33790a28643ab058b507b35cBen Cheng default: 11325b3c049e70834cf33790a28643ab058b507b35cBen Cheng case ELF_K_NONE: 11425b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libdwfl_seterrno (elf == NULL ? DWFL_E_LIBELF : DWFL_E_BADELF); 11525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 11625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 11725b3c049e70834cf33790a28643ab058b507b35cBen Cheng case ELF_K_ELF: 11825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return process_elf (dwfl, name, file_name, fd, elf); 11925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 12025b3c049e70834cf33790a28643ab058b507b35cBen Cheng case ELF_K_AR: 12125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return process_archive (dwfl, name, file_name, fd, elf, predicate); 12225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 12325b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 12425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 12525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Report the open ELF file as a module. Always consumes ELF and FD. */ 12625b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic Dwfl_Module * 12725b3c049e70834cf33790a28643ab058b507b35cBen Chengprocess_elf (Dwfl *dwfl, const char *name, const char *file_name, int fd, 12825b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf *elf) 12925b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 13025b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwfl_Module *mod = __libdwfl_report_elf (dwfl, name, file_name, fd, elf, 13103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes dwfl->offline_next_address, true, 13203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes false); 13325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (mod != NULL) 13425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 13525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* If this is an ET_EXEC file with fixed addresses, the address range 13625b3c049e70834cf33790a28643ab058b507b35cBen Cheng it consumed may or may not intersect with the arbitrary range we 13725b3c049e70834cf33790a28643ab058b507b35cBen Cheng will use for relocatable modules. Make sure we always use a free 13825b3c049e70834cf33790a28643ab058b507b35cBen Cheng range for the offline allocations. If this module did use 13925b3c049e70834cf33790a28643ab058b507b35cBen Cheng offline_next_address, it may have rounded it up for the module's 14025b3c049e70834cf33790a28643ab058b507b35cBen Cheng alignment requirements. */ 14125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((dwfl->offline_next_address >= mod->low_addr 14225b3c049e70834cf33790a28643ab058b507b35cBen Cheng || mod->low_addr - dwfl->offline_next_address < OFFLINE_REDZONE) 14325b3c049e70834cf33790a28643ab058b507b35cBen Cheng && dwfl->offline_next_address < mod->high_addr + OFFLINE_REDZONE) 14425b3c049e70834cf33790a28643ab058b507b35cBen Cheng dwfl->offline_next_address = mod->high_addr + OFFLINE_REDZONE; 14525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 14625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Don't keep the file descriptor around. */ 14725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (mod->main.fd != -1 && elf_cntl (mod->main.elf, ELF_C_FDREAD) == 0) 14825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 14925b3c049e70834cf33790a28643ab058b507b35cBen Cheng close (mod->main.fd); 15025b3c049e70834cf33790a28643ab058b507b35cBen Cheng mod->main.fd = -1; 15125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 15225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 15325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 15425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return mod; 15525b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 15625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 15725b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Always consumes MEMBER. Returns elf_next result on success. 15825b3c049e70834cf33790a28643ab058b507b35cBen Cheng For errors returns ELF_C_NULL with *MOD set to null. */ 15925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic Elf_Cmd 16025b3c049e70834cf33790a28643ab058b507b35cBen Chengprocess_archive_member (Dwfl *dwfl, const char *name, const char *file_name, 16125b3c049e70834cf33790a28643ab058b507b35cBen Cheng int (*predicate) (const char *module, const char *file), 16225b3c049e70834cf33790a28643ab058b507b35cBen Cheng int fd, Elf *member, Dwfl_Module **mod) 16325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 16425b3c049e70834cf33790a28643ab058b507b35cBen Cheng const Elf_Arhdr *h = elf_getarhdr (member); 16525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (h == NULL)) 16625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 16725b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libdwfl_seterrno (DWFL_E_LIBELF); 16825b3c049e70834cf33790a28643ab058b507b35cBen Cheng fail: 16925b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf_end (member); 17025b3c049e70834cf33790a28643ab058b507b35cBen Cheng *mod = NULL; 17125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return ELF_C_NULL; 17225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 17325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 17403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (!strcmp (h->ar_name, "/") || !strcmp (h->ar_name, "//") 17503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes || !strcmp (h->ar_name, "/SYM64/")) 17625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 17725b3c049e70834cf33790a28643ab058b507b35cBen Cheng skip:; 17825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Skip this and go to the next. */ 17925b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Cmd result = elf_next (member); 18025b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf_end (member); 18125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return result; 18225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 18325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 18425b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *member_name; 18525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (asprintf (&member_name, "%s(%s)", file_name, h->ar_name) < 0)) 18625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 18725b3c049e70834cf33790a28643ab058b507b35cBen Cheng nomem: 18825b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libdwfl_seterrno (DWFL_E_NOMEM); 18925b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf_end (member); 19025b3c049e70834cf33790a28643ab058b507b35cBen Cheng *mod = NULL; 19125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return ELF_C_NULL; 19225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 19325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 19425b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *module_name = NULL; 19525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (name == NULL || name[0] == '\0') 19625b3c049e70834cf33790a28643ab058b507b35cBen Cheng name = h->ar_name; 19725b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (unlikely (asprintf (&module_name, "%s:%s", name, h->ar_name) < 0)) 19825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 19925b3c049e70834cf33790a28643ab058b507b35cBen Cheng free (member_name); 20025b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto nomem; 20125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 20225b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 20325b3c049e70834cf33790a28643ab058b507b35cBen Cheng name = module_name; 20425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 20525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (predicate != NULL) 20625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 20725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Let the predicate decide whether to use this one. */ 20825b3c049e70834cf33790a28643ab058b507b35cBen Cheng int want = (*predicate) (name, member_name); 20925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (want <= 0) 21025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 21125b3c049e70834cf33790a28643ab058b507b35cBen Cheng free (member_name); 21225b3c049e70834cf33790a28643ab058b507b35cBen Cheng free (module_name); 21325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (want < 0)) 21425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 21525b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libdwfl_seterrno (DWFL_E_CB); 21625b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto fail; 21725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 21825b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto skip; 21925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 22025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 22125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 22225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We let __libdwfl_report_elf cache the fd in mod->main.fd, 22325b3c049e70834cf33790a28643ab058b507b35cBen Cheng though it's the same fd for all the members. 22425b3c049e70834cf33790a28643ab058b507b35cBen Cheng On module teardown we will close it only on the last Elf reference. */ 22525b3c049e70834cf33790a28643ab058b507b35cBen Cheng *mod = process_file (dwfl, name, member_name, fd, member, predicate); 22625b3c049e70834cf33790a28643ab058b507b35cBen Cheng free (member_name); 22725b3c049e70834cf33790a28643ab058b507b35cBen Cheng free (module_name); 22825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 22925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*mod == NULL) /* process_file called elf_end. */ 23025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return ELF_C_NULL; 23125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 23225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Advance the archive-reading offset for the next iteration. */ 23325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return elf_next (member); 23425b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 23525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 23625b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Report each member of the archive as its own module. */ 23725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic Dwfl_Module * 23825b3c049e70834cf33790a28643ab058b507b35cBen Chengprocess_archive (Dwfl *dwfl, const char *name, const char *file_name, int fd, 23925b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf *archive, 24025b3c049e70834cf33790a28643ab058b507b35cBen Cheng int (*predicate) (const char *module, const char *file)) 24125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 24225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 24325b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwfl_Module *mod = NULL; 24425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf *member = elf_begin (fd, ELF_C_READ_MMAP_PRIVATE, archive); 24525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (member == NULL)) /* Empty archive. */ 24625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 24725b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libdwfl_seterrno (DWFL_E_BADELF); 24825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 24925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 25025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 25125b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (process_archive_member (dwfl, name, file_name, predicate, 25225b3c049e70834cf33790a28643ab058b507b35cBen Cheng fd, member, &mod) != ELF_C_NULL) 25325b3c049e70834cf33790a28643ab058b507b35cBen Cheng member = elf_begin (fd, ELF_C_READ_MMAP_PRIVATE, archive); 25425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 25525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We can drop the archive Elf handle even if we're still using members 25625b3c049e70834cf33790a28643ab058b507b35cBen Cheng in live modules. When the last module's elf_end on a member returns 25725b3c049e70834cf33790a28643ab058b507b35cBen Cheng zero, that module will close FD. If no modules survived the predicate, 25825b3c049e70834cf33790a28643ab058b507b35cBen Cheng we are all done with the file right here. */ 25925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (mod != NULL /* If no modules, caller will clean up. */ 26025b3c049e70834cf33790a28643ab058b507b35cBen Cheng && elf_end (archive) == 0) 26125b3c049e70834cf33790a28643ab058b507b35cBen Cheng close (fd); 26225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 26325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return mod; 26425b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 26525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 26625b3c049e70834cf33790a28643ab058b507b35cBen ChengDwfl_Module * 26725b3c049e70834cf33790a28643ab058b507b35cBen Chenginternal_function 26825b3c049e70834cf33790a28643ab058b507b35cBen Cheng__libdwfl_report_offline (Dwfl *dwfl, const char *name, 26925b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *file_name, int fd, bool closefd, 27025b3c049e70834cf33790a28643ab058b507b35cBen Cheng int (*predicate) (const char *module, 27125b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *file)) 27225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 27325b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf *elf; 27425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwfl_Error error = __libdw_open_file (&fd, &elf, closefd, true); 27525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (error != DWFL_E_NOERROR) 27625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 27725b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libdwfl_seterrno (error); 27825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 27925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 28025b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwfl_Module *mod = process_file (dwfl, name, file_name, fd, elf, predicate); 28125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (mod == NULL) 28225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 28325b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf_end (elf); 28425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (closefd) 28525b3c049e70834cf33790a28643ab058b507b35cBen Cheng close (fd); 28625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 28725b3c049e70834cf33790a28643ab058b507b35cBen Cheng return mod; 28825b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 28925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 29025b3c049e70834cf33790a28643ab058b507b35cBen ChengDwfl_Module * 29125b3c049e70834cf33790a28643ab058b507b35cBen Chengdwfl_report_offline (Dwfl *dwfl, const char *name, 29225b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *file_name, int fd) 29325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 29425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (dwfl == NULL) 29525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 29625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 29725b3c049e70834cf33790a28643ab058b507b35cBen Cheng bool closefd = false; 29825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (fd < 0) 29925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 30025b3c049e70834cf33790a28643ab058b507b35cBen Cheng closefd = true; 30125b3c049e70834cf33790a28643ab058b507b35cBen Cheng fd = open64 (file_name, O_RDONLY); 30225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (fd < 0) 30325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 30425b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libdwfl_seterrno (DWFL_E_ERRNO); 30525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 30625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 30725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 30825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 30925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return __libdwfl_report_offline (dwfl, name, file_name, fd, closefd, NULL); 31025b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 31125b3c049e70834cf33790a28643ab058b507b35cBen ChengINTDEF (dwfl_report_offline) 312