125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Core file handling. 203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Copyright (C) 2008-2010, 2013 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 <config.h> 3025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "../libelf/libelfP.h" /* For NOTE_ALIGN. */ 3125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#undef _ 3225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "libdwflP.h" 3325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <gelf.h> 3425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 3525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <sys/param.h> 3625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <unistd.h> 3725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <endian.h> 3825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <byteswap.h> 3925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "system.h" 4025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 4125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 4225b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* This is a prototype of what a new libelf interface might be. 4325b3c049e70834cf33790a28643ab058b507b35cBen Cheng This implementation is pessimal for non-mmap cases and should 4425b3c049e70834cf33790a28643ab058b507b35cBen Cheng be replaced by more diddling inside libelf internals. */ 4525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic Elf * 4625b3c049e70834cf33790a28643ab058b507b35cBen Chengelf_begin_rand (Elf *parent, loff_t offset, loff_t size, loff_t *next) 4725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 4825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (parent == NULL) 4925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 5025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 5125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* On failure return, we update *NEXT to point back at OFFSET. */ 5225b3c049e70834cf33790a28643ab058b507b35cBen Cheng inline Elf *fail (int error) 5325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 5425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (next != NULL) 5525b3c049e70834cf33790a28643ab058b507b35cBen Cheng *next = offset; 5625b3c049e70834cf33790a28643ab058b507b35cBen Cheng //__libelf_seterrno (error); 5725b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libdwfl_seterrno (DWFL_E (LIBELF, error)); 5825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 5925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 6025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 6125b3c049e70834cf33790a28643ab058b507b35cBen Cheng loff_t min = (parent->kind == ELF_K_ELF ? 6225b3c049e70834cf33790a28643ab058b507b35cBen Cheng (parent->class == ELFCLASS32 6325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ? sizeof (Elf32_Ehdr) : sizeof (Elf64_Ehdr)) 6425b3c049e70834cf33790a28643ab058b507b35cBen Cheng : parent->kind == ELF_K_AR ? SARMAG 6525b3c049e70834cf33790a28643ab058b507b35cBen Cheng : 0); 6625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 6725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (offset < min) 6825b3c049e70834cf33790a28643ab058b507b35cBen Cheng || unlikely (offset >= (loff_t) parent->maximum_size)) 6925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return fail (ELF_E_RANGE); 7025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 7125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* For an archive, fetch just the size field 7225b3c049e70834cf33790a28643ab058b507b35cBen Cheng from the archive header to override SIZE. */ 7325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (parent->kind == ELF_K_AR) 7425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 7525b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct ar_hdr h = { .ar_size = "" }; 7625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 7725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (parent->maximum_size - offset < sizeof h)) 7825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return fail (ELF_E_RANGE); 7925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 8025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (parent->map_address != NULL) 8125b3c049e70834cf33790a28643ab058b507b35cBen Cheng memcpy (h.ar_size, parent->map_address + parent->start_offset + offset, 8225b3c049e70834cf33790a28643ab058b507b35cBen Cheng sizeof h.ar_size); 8325b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (unlikely (pread_retry (parent->fildes, 8425b3c049e70834cf33790a28643ab058b507b35cBen Cheng h.ar_size, sizeof (h.ar_size), 8525b3c049e70834cf33790a28643ab058b507b35cBen Cheng parent->start_offset + offset 8625b3c049e70834cf33790a28643ab058b507b35cBen Cheng + offsetof (struct ar_hdr, ar_size)) 8725b3c049e70834cf33790a28643ab058b507b35cBen Cheng != sizeof (h.ar_size))) 8825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return fail (ELF_E_READ_ERROR); 8925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 9025b3c049e70834cf33790a28643ab058b507b35cBen Cheng offset += sizeof h; 9125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 9225b3c049e70834cf33790a28643ab058b507b35cBen Cheng char *endp; 9325b3c049e70834cf33790a28643ab058b507b35cBen Cheng size = strtoll (h.ar_size, &endp, 10); 9425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (endp == h.ar_size) 9525b3c049e70834cf33790a28643ab058b507b35cBen Cheng || unlikely ((loff_t) parent->maximum_size - offset < size)) 9625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return fail (ELF_E_INVALID_ARCHIVE); 9725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 9825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 9925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely ((loff_t) parent->maximum_size - offset < size)) 10025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return fail (ELF_E_RANGE); 10125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 10225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Even if we fail at this point, update *NEXT to point past the file. */ 10325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (next != NULL) 10425b3c049e70834cf33790a28643ab058b507b35cBen Cheng *next = offset + size; 10525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 10625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (offset == 0) 10725b3c049e70834cf33790a28643ab058b507b35cBen Cheng && unlikely (size == (loff_t) parent->maximum_size)) 10825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return elf_clone (parent, parent->cmd); 10925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 11025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Note the image is guaranteed live only as long as PARENT 11125b3c049e70834cf33790a28643ab058b507b35cBen Cheng lives. Using elf_memory is quite suboptimal if the whole 11225b3c049e70834cf33790a28643ab058b507b35cBen Cheng file is not mmap'd. We really should have something like 11325b3c049e70834cf33790a28643ab058b507b35cBen Cheng a generalization of the archive support. */ 11425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data *data = elf_getdata_rawchunk (parent, offset, size, ELF_T_BYTE); 11525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (data == NULL) 11625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 11725b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert ((loff_t) data->d_size == size); 11825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return elf_memory (data->d_buf, size); 11925b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 12025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 12125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 12225b3c049e70834cf33790a28643ab058b507b35cBen Chengint 12325b3c049e70834cf33790a28643ab058b507b35cBen Chengdwfl_report_core_segments (Dwfl *dwfl, Elf *elf, size_t phnum, GElf_Phdr *notes) 12425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 12525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (dwfl == NULL)) 12625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 12725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 12825b3c049e70834cf33790a28643ab058b507b35cBen Cheng int result = 0; 12925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 13025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (notes != NULL) 13125b3c049e70834cf33790a28643ab058b507b35cBen Cheng notes->p_type = PT_NULL; 13225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 13325b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (size_t ndx = 0; result >= 0 && ndx < phnum; ++ndx) 13425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 13525b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Phdr phdr_mem; 13625b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Phdr *phdr = gelf_getphdr (elf, ndx, &phdr_mem); 13725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (phdr == NULL)) 13825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 13925b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libdwfl_seterrno (DWFL_E_LIBELF); 14025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 14125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 14225b3c049e70834cf33790a28643ab058b507b35cBen Cheng switch (phdr->p_type) 14325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 14425b3c049e70834cf33790a28643ab058b507b35cBen Cheng case PT_LOAD: 14525b3c049e70834cf33790a28643ab058b507b35cBen Cheng result = dwfl_report_segment (dwfl, ndx, phdr, 0, NULL); 14625b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 14725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 14825b3c049e70834cf33790a28643ab058b507b35cBen Cheng case PT_NOTE: 14925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (notes != NULL) 15025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 15125b3c049e70834cf33790a28643ab058b507b35cBen Cheng *notes = *phdr; 15225b3c049e70834cf33790a28643ab058b507b35cBen Cheng notes = NULL; 15325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 15425b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 15525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 15625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 15725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 15825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return result; 15925b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 16025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 16125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Never read more than this much without mmap. */ 16225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define MAX_EAGER_COST 8192 16325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 16425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool 16525b3c049e70834cf33790a28643ab058b507b35cBen Chengcore_file_read_eagerly (Dwfl_Module *mod, 16625b3c049e70834cf33790a28643ab058b507b35cBen Cheng void **userdata __attribute__ ((unused)), 16725b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *name __attribute__ ((unused)), 16825b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwarf_Addr start __attribute__ ((unused)), 16925b3c049e70834cf33790a28643ab058b507b35cBen Cheng void **buffer, size_t *buffer_available, 17025b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Off cost, GElf_Off worthwhile, 17125b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Off whole, 17225b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Off contiguous __attribute__ ((unused)), 17325b3c049e70834cf33790a28643ab058b507b35cBen Cheng void *arg, Elf **elfp) 17425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 17525b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf *core = arg; 17625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 17725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (whole <= *buffer_available) 17825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 17925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* All there ever was, we already have on hand. */ 18025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 18125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (core->map_address == NULL) 18225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 18325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We already malloc'd the buffer. */ 18425b3c049e70834cf33790a28643ab058b507b35cBen Cheng *elfp = elf_memory (*buffer, whole); 18525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (*elfp == NULL)) 18625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return false; 18725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 18825b3c049e70834cf33790a28643ab058b507b35cBen Cheng (*elfp)->flags |= ELF_F_MALLOCED; 18925b3c049e70834cf33790a28643ab058b507b35cBen Cheng *buffer = NULL; 19025b3c049e70834cf33790a28643ab058b507b35cBen Cheng *buffer_available = 0; 19125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return true; 19225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 19325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 19425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We can use the image inside the core file directly. */ 19525b3c049e70834cf33790a28643ab058b507b35cBen Cheng *elfp = elf_begin_rand (core, *buffer - core->map_address, whole, NULL); 19625b3c049e70834cf33790a28643ab058b507b35cBen Cheng *buffer = NULL; 19725b3c049e70834cf33790a28643ab058b507b35cBen Cheng *buffer_available = 0; 19825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return *elfp != NULL; 19925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 20025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 20125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We don't have the whole file. 20225b3c049e70834cf33790a28643ab058b507b35cBen Cheng Figure out if this is better than nothing. */ 20325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 20425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (worthwhile == 0) 20525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Caller doesn't think so. */ 20625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return false; 20725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 20825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* 20925b3c049e70834cf33790a28643ab058b507b35cBen Cheng XXX would like to fall back to partial file via memory 21025b3c049e70834cf33790a28643ab058b507b35cBen Cheng when build id find_elf fails 21125b3c049e70834cf33790a28643ab058b507b35cBen Cheng also, link_map name may give file name from disk better than partial here 21225b3c049e70834cf33790a28643ab058b507b35cBen Cheng requires find_elf hook re-doing the magic to fall back if no file found 21325b3c049e70834cf33790a28643ab058b507b35cBen Cheng */ 21425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 21525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (mod->build_id_len > 0) 21625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* There is a build ID that could help us find the whole file, 21725b3c049e70834cf33790a28643ab058b507b35cBen Cheng which might be more useful than what we have. 21825b3c049e70834cf33790a28643ab058b507b35cBen Cheng We'll just rely on that. */ 21925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return false; 22025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 22125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (core->map_address != NULL) 22225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* It's cheap to get, so get it. */ 22325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return true; 22425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 22525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Only use it if there isn't too much to be read. */ 22625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return cost <= MAX_EAGER_COST; 22725b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 22825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 22925b3c049e70834cf33790a28643ab058b507b35cBen Chengbool 23025b3c049e70834cf33790a28643ab058b507b35cBen Chengdwfl_elf_phdr_memory_callback (Dwfl *dwfl, int ndx, 23125b3c049e70834cf33790a28643ab058b507b35cBen Cheng void **buffer, size_t *buffer_available, 23225b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Addr vaddr, 23325b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t minread, 23425b3c049e70834cf33790a28643ab058b507b35cBen Cheng void *arg) 23525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 23625b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf *elf = arg; 23725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 23825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ndx == -1) 23925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 24025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Called for cleanup. */ 24125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elf->map_address == NULL) 24225b3c049e70834cf33790a28643ab058b507b35cBen Cheng free (*buffer); 24325b3c049e70834cf33790a28643ab058b507b35cBen Cheng *buffer = NULL; 24425b3c049e70834cf33790a28643ab058b507b35cBen Cheng *buffer_available = 0; 24525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return false; 24625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 24725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 24825b3c049e70834cf33790a28643ab058b507b35cBen Cheng const GElf_Off align = dwfl->segment_align ?: 1; 24925b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Phdr phdr; 25025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 25125b3c049e70834cf33790a28643ab058b507b35cBen Cheng do 25225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (gelf_getphdr (elf, ndx++, &phdr) == NULL)) 25325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return false; 25425b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (phdr.p_type != PT_LOAD 25525b3c049e70834cf33790a28643ab058b507b35cBen Cheng || ((phdr.p_vaddr + phdr.p_memsz + align - 1) & -align) <= vaddr); 25625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 25725b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Off start = vaddr - phdr.p_vaddr + phdr.p_offset; 25825b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Off end; 25925b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Addr end_vaddr; 26025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 26125b3c049e70834cf33790a28643ab058b507b35cBen Cheng inline void update_end () 26225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 26325b3c049e70834cf33790a28643ab058b507b35cBen Cheng end = (phdr.p_offset + phdr.p_filesz + align - 1) & -align; 26425b3c049e70834cf33790a28643ab058b507b35cBen Cheng end_vaddr = (phdr.p_vaddr + phdr.p_memsz + align - 1) & -align; 26525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 26625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 26725b3c049e70834cf33790a28643ab058b507b35cBen Cheng update_end (); 26825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 26925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Use following contiguous segments to get towards SIZE. */ 27025b3c049e70834cf33790a28643ab058b507b35cBen Cheng inline bool more (size_t size) 27125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 27225b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (end <= start || end - start < size) 27325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 27425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (phdr.p_filesz < phdr.p_memsz) 27525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* This segment is truncated, so no following one helps us. */ 27625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return false; 27725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 27825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (gelf_getphdr (elf, ndx++, &phdr) == NULL)) 27925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return false; 28025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 28125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (phdr.p_type == PT_LOAD) 28225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 28325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (phdr.p_offset > end 28425b3c049e70834cf33790a28643ab058b507b35cBen Cheng || phdr.p_vaddr > end_vaddr) 28525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* It's discontiguous! */ 28625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return false; 28725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 28825b3c049e70834cf33790a28643ab058b507b35cBen Cheng update_end (); 28925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 29025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 29125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return true; 29225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 29325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 29425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We need at least this much. */ 29525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (! more (minread)) 29625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return false; 29725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 29825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* See how much more we can get of what the caller wants. */ 29925b3c049e70834cf33790a28643ab058b507b35cBen Cheng (void) more (*buffer_available); 30025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 30125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* If it's already on hand anyway, use as much as there is. */ 30225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elf->map_address != NULL) 30325b3c049e70834cf33790a28643ab058b507b35cBen Cheng (void) more (elf->maximum_size - start); 30425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 30525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Make sure we don't look past the end of the actual file, 30625b3c049e70834cf33790a28643ab058b507b35cBen Cheng even if the headers tell us to. */ 30725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (end > elf->maximum_size)) 30825b3c049e70834cf33790a28643ab058b507b35cBen Cheng end = elf->maximum_size; 30925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 31025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* If the file is too small, there is nothing at all to get. */ 31125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (start >= end)) 31225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return false; 31325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 31425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elf->map_address != NULL) 31525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 31625b3c049e70834cf33790a28643ab058b507b35cBen Cheng void *contents = elf->map_address + elf->start_offset + start; 31725b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t size = end - start; 31825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 31925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (minread == 0) /* String mode. */ 32025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 32125b3c049e70834cf33790a28643ab058b507b35cBen Cheng const void *eos = memchr (contents, '\0', size); 32225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (eos == NULL) || unlikely (eos == contents)) 32325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return false; 32425b3c049e70834cf33790a28643ab058b507b35cBen Cheng size = eos + 1 - contents; 32525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 32625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 32725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*buffer == NULL) 32825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 32925b3c049e70834cf33790a28643ab058b507b35cBen Cheng *buffer = contents; 33025b3c049e70834cf33790a28643ab058b507b35cBen Cheng *buffer_available = size; 33125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 33225b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 33325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 33425b3c049e70834cf33790a28643ab058b507b35cBen Cheng *buffer_available = MIN (size, *buffer_available); 33525b3c049e70834cf33790a28643ab058b507b35cBen Cheng memcpy (*buffer, contents, *buffer_available); 33625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 33725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 33825b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 33925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 34025b3c049e70834cf33790a28643ab058b507b35cBen Cheng void *into = *buffer; 34125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*buffer == NULL) 34225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 34325b3c049e70834cf33790a28643ab058b507b35cBen Cheng *buffer_available = MIN (minread ?: 512, 34425b3c049e70834cf33790a28643ab058b507b35cBen Cheng MAX (4096, MIN (end - start, 34525b3c049e70834cf33790a28643ab058b507b35cBen Cheng *buffer_available))); 34625b3c049e70834cf33790a28643ab058b507b35cBen Cheng into = malloc (*buffer_available); 34725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (into == NULL)) 34825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 34925b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libdwfl_seterrno (DWFL_E_NOMEM); 35025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return false; 35125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 35225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 35325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 35425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ssize_t nread = pread_retry (elf->fildes, into, *buffer_available, start); 35525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (nread < (ssize_t) minread) 35625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 35725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (into != *buffer) 35825b3c049e70834cf33790a28643ab058b507b35cBen Cheng free (into); 35925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (nread < 0) 36025b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libdwfl_seterrno (DWFL_E_ERRNO); 36125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return false; 36225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 36325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 36425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (minread == 0) /* String mode. */ 36525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 36625b3c049e70834cf33790a28643ab058b507b35cBen Cheng const void *eos = memchr (into, '\0', nread); 36725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (eos == NULL) || unlikely (eos == into)) 36825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 36925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*buffer == NULL) 37025b3c049e70834cf33790a28643ab058b507b35cBen Cheng free (into); 37125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return false; 37225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 37325b3c049e70834cf33790a28643ab058b507b35cBen Cheng nread = eos + 1 - into; 37425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 37525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 37625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*buffer == NULL) 37725b3c049e70834cf33790a28643ab058b507b35cBen Cheng *buffer = into; 37825b3c049e70834cf33790a28643ab058b507b35cBen Cheng *buffer_available = nread; 37925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 38025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 38125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return true; 38225b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 38325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 38403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes/* Free the contents of R_DEBUG_INFO without the R_DEBUG_INFO memory itself. */ 38503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 38603333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic void 38703333823c75a1c1887e923828113a1b0fd12020cElliott Hughesclear_r_debug_info (struct r_debug_info *r_debug_info) 38803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{ 38903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes while (r_debug_info->module != NULL) 39003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 39103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes struct r_debug_info_module *module = r_debug_info->module; 39203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes r_debug_info->module = module->next; 39303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes elf_end (module->elf); 39403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (module->fd != -1) 39503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes close (module->fd); 39603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes free (module); 39703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 39803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes} 39903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 40003333823c75a1c1887e923828113a1b0fd12020cElliott Hughesbool 40103333823c75a1c1887e923828113a1b0fd12020cElliott Hughesinternal_function 40203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes__libdwfl_dynamic_vaddr_get (Elf *elf, GElf_Addr *vaddrp) 40303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{ 40403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes size_t phnum; 40503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (unlikely (elf_getphdrnum (elf, &phnum) != 0)) 40603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return false; 40703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes for (size_t i = 0; i < phnum; ++i) 40803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 40903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes GElf_Phdr phdr_mem; 41003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem); 41103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (unlikely (phdr == NULL)) 41203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return false; 41303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (phdr->p_type == PT_DYNAMIC) 41403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 41503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes *vaddrp = phdr->p_vaddr; 41603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return true; 41703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 41803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 41903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return false; 42003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes} 42103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 42225b3c049e70834cf33790a28643ab058b507b35cBen Chengint 42303333823c75a1c1887e923828113a1b0fd12020cElliott Hughesdwfl_core_file_report (Dwfl *dwfl, Elf *elf, const char *executable) 42425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 42525b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t phnum; 42625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (elf_getphdrnum (elf, &phnum) != 0)) 42725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 42825b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libdwfl_seterrno (DWFL_E_LIBELF); 42925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return -1; 43025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 43125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 43203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes free (dwfl->executable_for_core); 43303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (executable == NULL) 43403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes dwfl->executable_for_core = NULL; 43503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes else 43603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 43703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes dwfl->executable_for_core = strdup (executable); 43803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (dwfl->executable_for_core == NULL) 43903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 44003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes __libdwfl_seterrno (DWFL_E_NOMEM); 44103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return -1; 44203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 44303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 44403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 44525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* First report each PT_LOAD segment. */ 44625b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Phdr notes_phdr; 44725b3c049e70834cf33790a28643ab058b507b35cBen Cheng int ndx = dwfl_report_core_segments (dwfl, elf, phnum, ¬es_phdr); 44825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (ndx <= 0)) 44925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return ndx; 45025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 45125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Next, we should follow the chain from DT_DEBUG. */ 45225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 45325b3c049e70834cf33790a28643ab058b507b35cBen Cheng const void *auxv = NULL; 45403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes const void *note_file = NULL; 45525b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t auxv_size = 0; 45603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes size_t note_file_size = 0; 45725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (likely (notes_phdr.p_type == PT_NOTE)) 45825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 45925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* PT_NOTE -> NT_AUXV -> AT_PHDR -> PT_DYNAMIC -> DT_DEBUG */ 46025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 46125b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data *notes = elf_getdata_rawchunk (elf, 46225b3c049e70834cf33790a28643ab058b507b35cBen Cheng notes_phdr.p_offset, 46325b3c049e70834cf33790a28643ab058b507b35cBen Cheng notes_phdr.p_filesz, 46425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ELF_T_NHDR); 46525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (likely (notes != NULL)) 46625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 46725b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t pos = 0; 46825b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Nhdr nhdr; 46925b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t name_pos; 47025b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t desc_pos; 47125b3c049e70834cf33790a28643ab058b507b35cBen Cheng while ((pos = gelf_getnote (notes, pos, &nhdr, 47225b3c049e70834cf33790a28643ab058b507b35cBen Cheng &name_pos, &desc_pos)) > 0) 47303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (nhdr.n_namesz == sizeof "CORE" 47425b3c049e70834cf33790a28643ab058b507b35cBen Cheng && !memcmp (notes->d_buf + name_pos, "CORE", sizeof "CORE")) 47525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 47603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (nhdr.n_type == NT_AUXV) 47703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 47803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes auxv = notes->d_buf + desc_pos; 47903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes auxv_size = nhdr.n_descsz; 48003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 48103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (nhdr.n_type == NT_FILE) 48203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 48303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes note_file = notes->d_buf + desc_pos; 48403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes note_file_size = nhdr.n_descsz; 48503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 48625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 48725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 48825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 48925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 49025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Now we have NT_AUXV contents. From here on this processing could be 49125b3c049e70834cf33790a28643ab058b507b35cBen Cheng used for a live process with auxv read from /proc. */ 49225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 49303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes struct r_debug_info r_debug_info; 49403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes memset (&r_debug_info, 0, sizeof r_debug_info); 49503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes int retval = dwfl_link_map_report (dwfl, auxv, auxv_size, 49603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes dwfl_elf_phdr_memory_callback, elf, 49703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes &r_debug_info); 49803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes int listed = retval > 0 ? retval : 0; 49903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 50003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* Now sniff segment contents for modules hinted by information gathered 50103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes from DT_DEBUG. */ 50203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 50303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes ndx = 0; 50403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes do 50503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 50603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes int seg = dwfl_segment_report_module (dwfl, ndx, NULL, 50703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes &dwfl_elf_phdr_memory_callback, elf, 50803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes core_file_read_eagerly, elf, 50903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes note_file, note_file_size, 51003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes &r_debug_info); 51103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (unlikely (seg < 0)) 51203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 51303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes clear_r_debug_info (&r_debug_info); 51403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return seg; 51503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 51603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (seg > ndx) 51703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 51803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes ndx = seg; 51903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes ++listed; 52003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 52103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes else 52203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes ++ndx; 52303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 52403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes while (ndx < (int) phnum); 52503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 52603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* Now report the modules from dwfl_link_map_report which were not filtered 52703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes out by dwfl_segment_report_module. */ 52803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 52903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwfl_Module **lastmodp = &dwfl->modulelist; 53003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes while (*lastmodp != NULL) 53103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes lastmodp = &(*lastmodp)->next; 53203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes for (struct r_debug_info_module *module = r_debug_info.module; 53303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes module != NULL; module = module->next) 53403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 53503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (module->elf == NULL) 53603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes continue; 53703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes GElf_Addr file_dynamic_vaddr; 53803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (! __libdwfl_dynamic_vaddr_get (module->elf, &file_dynamic_vaddr)) 53903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes continue; 54003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwfl_Module *mod; 54103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes mod = __libdwfl_report_elf (dwfl, basename (module->name), module->name, 54203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes module->fd, module->elf, 54303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes module->l_ld - file_dynamic_vaddr, 54403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes true, true); 54503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (mod == NULL) 54603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes continue; 54703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes ++listed; 54803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes module->elf = NULL; 54903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes module->fd = -1; 55003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* Move this module to the end of the list, so that we end 55103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes up with a list in the same order as the link_map chain. */ 55203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (mod->next != NULL) 55303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 55403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (*lastmodp != mod) 55503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 55603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes lastmodp = &dwfl->modulelist; 55703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes while (*lastmodp != mod) 55803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes lastmodp = &(*lastmodp)->next; 55903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 56003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes *lastmodp = mod->next; 56103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes mod->next = NULL; 56203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes while (*lastmodp != NULL) 56303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes lastmodp = &(*lastmodp)->next; 56403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes *lastmodp = mod; 56503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 56603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes lastmodp = &mod->next; 56703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 56803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 56903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes clear_r_debug_info (&r_debug_info); 57025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 57125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We return the number of modules we found if we found any. 57225b3c049e70834cf33790a28643ab058b507b35cBen Cheng If we found none, we return -1 instead of 0 if there was an 57303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes error rather than just nothing found. */ 57403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return listed > 0 ? listed : retval; 57525b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 57625b3c049e70834cf33790a28643ab058b507b35cBen ChengINTDEF (dwfl_core_file_report) 57703333823c75a1c1887e923828113a1b0fd12020cElliott HughesNEW_VERSION (dwfl_core_file_report, ELFUTILS_0.158) 57803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 57903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#ifdef SHARED 58003333823c75a1c1887e923828113a1b0fd12020cElliott Hughesint _compat_without_executable_dwfl_core_file_report (Dwfl *dwfl, Elf *elf); 58103333823c75a1c1887e923828113a1b0fd12020cElliott HughesCOMPAT_VERSION_NEWPROTO (dwfl_core_file_report, ELFUTILS_0.146, 58203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes without_executable) 58303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 58403333823c75a1c1887e923828113a1b0fd12020cElliott Hughesint 58503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes_compat_without_executable_dwfl_core_file_report (Dwfl *dwfl, Elf *elf) 58603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{ 58703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return dwfl_core_file_report (dwfl, elf, NULL); 58803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes} 58903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#endif 590