125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Report modules by examining dynamic linker data structures. 203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Copyright (C) 2008-2014 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 "libdwflP.h" 3103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include "../libdw/memory-access.h" 3203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include "system.h" 3325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 3425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <byteswap.h> 3525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <endian.h> 3603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include <fcntl.h> 3725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 3825b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* This element is always provided and always has a constant value. 3925b3c049e70834cf33790a28643ab058b507b35cBen Cheng This makes it an easy thing to scan for to discern the format. */ 4025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define PROBE_TYPE AT_PHENT 4125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define PROBE_VAL32 sizeof (Elf32_Phdr) 4225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define PROBE_VAL64 sizeof (Elf64_Phdr) 4325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 4425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 4525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Examine an auxv data block and determine its format. 4625b3c049e70834cf33790a28643ab058b507b35cBen Cheng Return true iff we figured it out. */ 4725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool 4825b3c049e70834cf33790a28643ab058b507b35cBen Chengauxv_format_probe (const void *auxv, size_t size, 4925b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint_fast8_t *elfclass, uint_fast8_t *elfdata) 5025b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 5125b3c049e70834cf33790a28643ab058b507b35cBen Cheng const union 5225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 5325b3c049e70834cf33790a28643ab058b507b35cBen Cheng char buf[size]; 5425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf32_auxv_t a32[size / sizeof (Elf32_auxv_t)]; 5525b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf64_auxv_t a64[size / sizeof (Elf64_auxv_t)]; 5625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } *u = auxv; 5725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 5825b3c049e70834cf33790a28643ab058b507b35cBen Cheng inline bool check64 (size_t i) 5925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 6003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* The AUXV pointer might not even be naturally aligned for 64-bit 6103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes data, because note payloads in a core file are not aligned. 6203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes But we assume the data is 32-bit aligned. */ 6303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 6403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes uint64_t type = read_8ubyte_unaligned_noncvt (&u->a64[i].a_type); 6503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes uint64_t val = read_8ubyte_unaligned_noncvt (&u->a64[i].a_un.a_val); 6603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 6703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (type == BE64 (PROBE_TYPE) 6803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes && val == BE64 (PROBE_VAL64)) 6925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 7025b3c049e70834cf33790a28643ab058b507b35cBen Cheng *elfdata = ELFDATA2MSB; 7125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return true; 7225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 7325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 7403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (type == LE64 (PROBE_TYPE) 7503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes && val == LE64 (PROBE_VAL64)) 7625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 7725b3c049e70834cf33790a28643ab058b507b35cBen Cheng *elfdata = ELFDATA2LSB; 7825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return true; 7925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 8025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 8125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return false; 8225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 8325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 8425b3c049e70834cf33790a28643ab058b507b35cBen Cheng inline bool check32 (size_t i) 8525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 8625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (u->a32[i].a_type == BE32 (PROBE_TYPE) 8725b3c049e70834cf33790a28643ab058b507b35cBen Cheng && u->a32[i].a_un.a_val == BE32 (PROBE_VAL32)) 8825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 8925b3c049e70834cf33790a28643ab058b507b35cBen Cheng *elfdata = ELFDATA2MSB; 9025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return true; 9125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 9225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 9325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (u->a32[i].a_type == LE32 (PROBE_TYPE) 9425b3c049e70834cf33790a28643ab058b507b35cBen Cheng && u->a32[i].a_un.a_val == LE32 (PROBE_VAL32)) 9525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 9625b3c049e70834cf33790a28643ab058b507b35cBen Cheng *elfdata = ELFDATA2LSB; 9725b3c049e70834cf33790a28643ab058b507b35cBen Cheng return true; 9825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 9925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 10025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return false; 10125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 10225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 10325b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (size_t i = 0; i < size / sizeof (Elf64_auxv_t); ++i) 10425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 10525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (check64 (i)) 10625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 10725b3c049e70834cf33790a28643ab058b507b35cBen Cheng *elfclass = ELFCLASS64; 10825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return true; 10925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 11025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 11125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (check32 (i * 2) || check32 (i * 2 + 1)) 11225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 11325b3c049e70834cf33790a28643ab058b507b35cBen Cheng *elfclass = ELFCLASS32; 11425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return true; 11525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 11625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 11725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 11825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return false; 11925b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 12025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 12125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* This is a Dwfl_Memory_Callback that wraps another memory callback. 12225b3c049e70834cf33790a28643ab058b507b35cBen Cheng If the underlying callback cannot fill the data, then this will 12325b3c049e70834cf33790a28643ab058b507b35cBen Cheng fall back to fetching data from module files. */ 12425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 12525b3c049e70834cf33790a28643ab058b507b35cBen Chengstruct integrated_memory_callback 12625b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 12725b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwfl_Memory_Callback *memory_callback; 12825b3c049e70834cf33790a28643ab058b507b35cBen Cheng void *memory_callback_arg; 12925b3c049e70834cf33790a28643ab058b507b35cBen Cheng void *buffer; 13025b3c049e70834cf33790a28643ab058b507b35cBen Cheng}; 13125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 13225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool 13325b3c049e70834cf33790a28643ab058b507b35cBen Chengintegrated_memory_callback (Dwfl *dwfl, int ndx, 13425b3c049e70834cf33790a28643ab058b507b35cBen Cheng void **buffer, size_t *buffer_available, 13525b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Addr vaddr, 13625b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t minread, 13725b3c049e70834cf33790a28643ab058b507b35cBen Cheng void *arg) 13825b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 13925b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct integrated_memory_callback *info = arg; 14025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 14125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ndx == -1) 14225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 14325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Called for cleanup. */ 14425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (info->buffer != NULL) 14525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 14625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* The last probe buffer came from the underlying callback. 14725b3c049e70834cf33790a28643ab058b507b35cBen Cheng Let it do its cleanup. */ 14825b3c049e70834cf33790a28643ab058b507b35cBen Cheng assert (*buffer == info->buffer); /* XXX */ 14925b3c049e70834cf33790a28643ab058b507b35cBen Cheng *buffer = info->buffer; 15025b3c049e70834cf33790a28643ab058b507b35cBen Cheng info->buffer = NULL; 15125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return (*info->memory_callback) (dwfl, ndx, buffer, buffer_available, 15225b3c049e70834cf33790a28643ab058b507b35cBen Cheng vaddr, minread, 15325b3c049e70834cf33790a28643ab058b507b35cBen Cheng info->memory_callback_arg); 15425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 15525b3c049e70834cf33790a28643ab058b507b35cBen Cheng *buffer = NULL; 15625b3c049e70834cf33790a28643ab058b507b35cBen Cheng *buffer_available = 0; 15725b3c049e70834cf33790a28643ab058b507b35cBen Cheng return false; 15825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 15925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 16025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*buffer != NULL) 16125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* For a final-read request, we only use the underlying callback. */ 16225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return (*info->memory_callback) (dwfl, ndx, buffer, buffer_available, 16325b3c049e70834cf33790a28643ab058b507b35cBen Cheng vaddr, minread, info->memory_callback_arg); 16425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 16525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Let the underlying callback try to fill this request. */ 16625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((*info->memory_callback) (dwfl, ndx, &info->buffer, buffer_available, 16725b3c049e70834cf33790a28643ab058b507b35cBen Cheng vaddr, minread, info->memory_callback_arg)) 16825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 16925b3c049e70834cf33790a28643ab058b507b35cBen Cheng *buffer = info->buffer; 17025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return true; 17125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 17225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 17325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Now look for module text covering this address. */ 17425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 17525b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwfl_Module *mod; 17625b3c049e70834cf33790a28643ab058b507b35cBen Cheng (void) INTUSE(dwfl_addrsegment) (dwfl, vaddr, &mod); 17725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (mod == NULL) 17825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return false; 17925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 18025b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwarf_Addr bias; 18125b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Scn *scn = INTUSE(dwfl_module_address_section) (mod, &vaddr, &bias); 18225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (scn == NULL)) 18325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 18425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#if 0 // XXX would have to handle ndx=-1 cleanup calls passed down. 18525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* If we have no sections we can try to fill it from the module file 18625b3c049e70834cf33790a28643ab058b507b35cBen Cheng based on its phdr mappings. */ 18725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (likely (mod->e_type != ET_REL) && mod->main.elf != NULL) 18825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return INTUSE(dwfl_elf_phdr_memory_callback) 18925b3c049e70834cf33790a28643ab058b507b35cBen Cheng (dwfl, 0, buffer, buffer_available, 19025b3c049e70834cf33790a28643ab058b507b35cBen Cheng vaddr - mod->main.bias, minread, mod->main.elf); 19125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#endif 19225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return false; 19325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 19425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 19525b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data *data = elf_rawdata (scn, NULL); 19625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (data == NULL)) 19725b3c049e70834cf33790a28643ab058b507b35cBen Cheng // XXX throw error? 19825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return false; 19925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 20025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (data->d_size < vaddr)) 20125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return false; 20225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 20325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Provide as much data as we have. */ 20425b3c049e70834cf33790a28643ab058b507b35cBen Cheng void *contents = data->d_buf + vaddr; 20525b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t avail = data->d_size - vaddr; 20625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (avail < minread)) 20725b3c049e70834cf33790a28643ab058b507b35cBen Cheng return false; 20825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 20925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* If probing for a string, make sure it's terminated. */ 21025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (minread == 0 && unlikely (memchr (contents, '\0', avail) == NULL)) 21125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return false; 21225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 21325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We have it! */ 21425b3c049e70834cf33790a28643ab058b507b35cBen Cheng *buffer = contents; 21525b3c049e70834cf33790a28643ab058b507b35cBen Cheng *buffer_available = avail; 21625b3c049e70834cf33790a28643ab058b507b35cBen Cheng return true; 21725b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 21825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 21925b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic size_t 22025b3c049e70834cf33790a28643ab058b507b35cBen Chengaddrsize (uint_fast8_t elfclass) 22125b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 22225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return elfclass * 4; 22325b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 22425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 22525b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Report a module for each struct link_map in the linked list at r_map 22603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes in the struct r_debug at R_DEBUG_VADDR. For r_debug_info description 22703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes see dwfl_link_map_report in libdwflP.h. If R_DEBUG_INFO is not NULL then no 22803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes modules get added to DWFL, caller has to add them from filled in 22903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes R_DEBUG_INFO. 23025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 23125b3c049e70834cf33790a28643ab058b507b35cBen Cheng For each link_map entry, if an existing module resides at its address, 23225b3c049e70834cf33790a28643ab058b507b35cBen Cheng this just modifies that module's name and suggested file name. If 23325b3c049e70834cf33790a28643ab058b507b35cBen Cheng no such module exists, this calls dwfl_report_elf on the l_name string. 23425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 23525b3c049e70834cf33790a28643ab058b507b35cBen Cheng Returns the number of modules found, or -1 for errors. */ 23625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 23725b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic int 23825b3c049e70834cf33790a28643ab058b507b35cBen Chengreport_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata, 23925b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwfl *dwfl, GElf_Addr r_debug_vaddr, 24025b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwfl_Memory_Callback *memory_callback, 24103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes void *memory_callback_arg, 24203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes struct r_debug_info *r_debug_info) 24325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 24425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Skip r_version, to aligned r_map field. */ 24525b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Addr read_vaddr = r_debug_vaddr + addrsize (elfclass); 24625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 24725b3c049e70834cf33790a28643ab058b507b35cBen Cheng void *buffer = NULL; 24825b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t buffer_available = 0; 24925b3c049e70834cf33790a28643ab058b507b35cBen Cheng inline int release_buffer (int result) 25025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 25125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (buffer != NULL) 25225b3c049e70834cf33790a28643ab058b507b35cBen Cheng (void) (*memory_callback) (dwfl, -1, &buffer, &buffer_available, 0, 0, 25325b3c049e70834cf33790a28643ab058b507b35cBen Cheng memory_callback_arg); 25425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return result; 25525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 25625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 25725b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Addr addrs[4]; 25825b3c049e70834cf33790a28643ab058b507b35cBen Cheng inline bool read_addrs (GElf_Addr vaddr, size_t n) 25925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 26025b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t nb = n * addrsize (elfclass); /* Address words -> bytes to read. */ 26125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 26225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Read a new buffer if the old one doesn't cover these words. */ 26325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (buffer == NULL 26425b3c049e70834cf33790a28643ab058b507b35cBen Cheng || vaddr < read_vaddr 26525b3c049e70834cf33790a28643ab058b507b35cBen Cheng || vaddr - read_vaddr + nb > buffer_available) 26625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 26725b3c049e70834cf33790a28643ab058b507b35cBen Cheng release_buffer (0); 26825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 26925b3c049e70834cf33790a28643ab058b507b35cBen Cheng read_vaddr = vaddr; 27025b3c049e70834cf33790a28643ab058b507b35cBen Cheng int segndx = INTUSE(dwfl_addrsegment) (dwfl, vaddr, NULL); 27125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (segndx < 0) 27225b3c049e70834cf33790a28643ab058b507b35cBen Cheng || unlikely (! (*memory_callback) (dwfl, segndx, 27325b3c049e70834cf33790a28643ab058b507b35cBen Cheng &buffer, &buffer_available, 27425b3c049e70834cf33790a28643ab058b507b35cBen Cheng vaddr, nb, memory_callback_arg))) 27525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return true; 27625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 27725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 27825b3c049e70834cf33790a28643ab058b507b35cBen Cheng const union 27925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 28025b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf32_Addr a32[n]; 28125b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf64_Addr a64[n]; 28225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } *in = vaddr - read_vaddr + buffer; 28325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 28425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elfclass == ELFCLASS32) 28525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 28625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elfdata == ELFDATA2MSB) 28725b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (size_t i = 0; i < n; ++i) 28825b3c049e70834cf33790a28643ab058b507b35cBen Cheng addrs[i] = BE32 (in->a32[i]); 28925b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 29025b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (size_t i = 0; i < n; ++i) 29125b3c049e70834cf33790a28643ab058b507b35cBen Cheng addrs[i] = LE32 (in->a32[i]); 29225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 29325b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 29425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 29525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elfdata == ELFDATA2MSB) 29625b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (size_t i = 0; i < n; ++i) 29725b3c049e70834cf33790a28643ab058b507b35cBen Cheng addrs[i] = BE64 (in->a64[i]); 29825b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 29925b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (size_t i = 0; i < n; ++i) 30025b3c049e70834cf33790a28643ab058b507b35cBen Cheng addrs[i] = LE64 (in->a64[i]); 30125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 30225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 30325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return false; 30425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 30525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 30625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (read_addrs (read_vaddr, 1))) 30725b3c049e70834cf33790a28643ab058b507b35cBen Cheng return release_buffer (-1); 30825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 30925b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Addr next = addrs[0]; 31025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 31125b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwfl_Module **lastmodp = &dwfl->modulelist; 31225b3c049e70834cf33790a28643ab058b507b35cBen Cheng int result = 0; 31325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 31425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* There can't be more elements in the link_map list than there are 31525b3c049e70834cf33790a28643ab058b507b35cBen Cheng segments. DWFL->lookup_elts is probably twice that number, so it 31625b3c049e70834cf33790a28643ab058b507b35cBen Cheng is certainly above the upper bound. If we iterate too many times, 31725b3c049e70834cf33790a28643ab058b507b35cBen Cheng there must be a loop in the pointers due to link_map clobberation. */ 31825b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t iterations = 0; 31925b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (next != 0 && ++iterations < dwfl->lookup_elts) 32025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 32125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (read_addrs (next, 4)) 32225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return release_buffer (-1); 32325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 32403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* Unused: l_addr is the difference between the address in memory 32503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes and the ELF file when the core was created. We need to 32603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes recalculate the difference below because the ELF file we use 32703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes might be differently pre-linked. */ 32803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes // GElf_Addr l_addr = addrs[0]; 32925b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Addr l_name = addrs[1]; 33025b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Addr l_ld = addrs[2]; 33125b3c049e70834cf33790a28643ab058b507b35cBen Cheng next = addrs[3]; 33225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 33325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* If a clobbered or truncated memory image has no useful pointer, 33425b3c049e70834cf33790a28643ab058b507b35cBen Cheng just skip this element. */ 33525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (l_ld == 0) 33625b3c049e70834cf33790a28643ab058b507b35cBen Cheng continue; 33725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 33825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Fetch the string at the l_name address. */ 33925b3c049e70834cf33790a28643ab058b507b35cBen Cheng const char *name = NULL; 34025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (buffer != NULL 34125b3c049e70834cf33790a28643ab058b507b35cBen Cheng && read_vaddr <= l_name 34225b3c049e70834cf33790a28643ab058b507b35cBen Cheng && l_name + 1 - read_vaddr < buffer_available 34325b3c049e70834cf33790a28643ab058b507b35cBen Cheng && memchr (l_name - read_vaddr + buffer, '\0', 34425b3c049e70834cf33790a28643ab058b507b35cBen Cheng buffer_available - (l_name - read_vaddr)) != NULL) 34525b3c049e70834cf33790a28643ab058b507b35cBen Cheng name = l_name - read_vaddr + buffer; 34625b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 34725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 34825b3c049e70834cf33790a28643ab058b507b35cBen Cheng release_buffer (0); 34925b3c049e70834cf33790a28643ab058b507b35cBen Cheng read_vaddr = l_name; 35025b3c049e70834cf33790a28643ab058b507b35cBen Cheng int segndx = INTUSE(dwfl_addrsegment) (dwfl, l_name, NULL); 35125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (likely (segndx >= 0) 35225b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (*memory_callback) (dwfl, segndx, 35325b3c049e70834cf33790a28643ab058b507b35cBen Cheng &buffer, &buffer_available, 35425b3c049e70834cf33790a28643ab058b507b35cBen Cheng l_name, 0, memory_callback_arg)) 35525b3c049e70834cf33790a28643ab058b507b35cBen Cheng name = buffer; 35625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 35725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 35825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (name != NULL && name[0] == '\0') 35925b3c049e70834cf33790a28643ab058b507b35cBen Cheng name = NULL; 36025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 36103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (iterations == 1 && dwfl->executable_for_core != NULL) 36203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes name = dwfl->executable_for_core; 36303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 36403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes struct r_debug_info_module *r_debug_info_module = NULL; 36503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (r_debug_info != NULL) 36625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 36703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* Save link map information about valid shared library (or 36803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes executable) which has not been found on disk. */ 36903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes const char *name1 = name == NULL ? "" : name; 37003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes r_debug_info_module = malloc (sizeof (*r_debug_info_module) 37103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes + strlen (name1) + 1); 37203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (r_debug_info_module == NULL) 37303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return release_buffer (result); 37403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes r_debug_info_module->fd = -1; 37503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes r_debug_info_module->elf = NULL; 37603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes r_debug_info_module->l_ld = l_ld; 37703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes r_debug_info_module->start = 0; 37803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes r_debug_info_module->end = 0; 37903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes r_debug_info_module->disk_file_has_build_id = false; 38003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes strcpy (r_debug_info_module->name, name1); 38103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes r_debug_info_module->next = r_debug_info->module; 38203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes r_debug_info->module = r_debug_info_module; 38303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 38403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 38503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwfl_Module *mod = NULL; 38603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (name != NULL) 38703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 38803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* This code is mostly inlined dwfl_report_elf. */ 38903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes // XXX hook for sysroot 39003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes int fd = open64 (name, O_RDONLY); 39103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (fd >= 0) 39225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 39303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Elf *elf; 39403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwfl_Error error = __libdw_open_file (&fd, &elf, true, false); 39503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes GElf_Addr elf_dynamic_vaddr; 39603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (error == DWFL_E_NOERROR 39703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes && __libdwfl_dynamic_vaddr_get (elf, &elf_dynamic_vaddr)) 39825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 39903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes const void *build_id_bits; 40003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes GElf_Addr build_id_elfaddr; 40103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes int build_id_len; 40203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes bool valid = true; 40303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 40403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (__libdwfl_find_elf_build_id (NULL, elf, &build_id_bits, 40503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes &build_id_elfaddr, 40603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes &build_id_len) > 0 40703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes && build_id_elfaddr != 0) 40803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 40903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (r_debug_info_module != NULL) 41003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes r_debug_info_module->disk_file_has_build_id = true; 41103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes GElf_Addr build_id_vaddr = (build_id_elfaddr 41203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes - elf_dynamic_vaddr + l_ld); 41303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 41403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes release_buffer (0); 41503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes int segndx = INTUSE(dwfl_addrsegment) (dwfl, 41603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes build_id_vaddr, 41703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes NULL); 41803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (! (*memory_callback) (dwfl, segndx, 41903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes &buffer, &buffer_available, 42003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes build_id_vaddr, build_id_len, 42103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes memory_callback_arg)) 42203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 42303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* File has valid build-id which cannot be read from 42403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes memory. This happens for core files without bit 4 42503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes (0x10) set in Linux /proc/PID/coredump_filter. */ 42603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 42703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes else 42803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 42903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (memcmp (build_id_bits, buffer, build_id_len) != 0) 43003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* File has valid build-id which does not match 43103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes the one in memory. */ 43203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes valid = false; 43303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes release_buffer (0); 43403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 43503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 43603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 43703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (valid) 43803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 43903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes // It is like l_addr but it handles differently prelinked 44003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes // files at core dumping vs. core loading time. 44103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes GElf_Addr base = l_ld - elf_dynamic_vaddr; 44203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (r_debug_info_module == NULL) 44303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 44403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes // XXX hook for sysroot 44503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes mod = __libdwfl_report_elf (dwfl, basename (name), 44603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes name, fd, elf, base, 44703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes true, true); 44803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (mod != NULL) 44903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 45003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes elf = NULL; 45103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes fd = -1; 45203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 45303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 45403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes else if (__libdwfl_elf_address_range (elf, base, true, 45503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes true, NULL, NULL, 45603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes &r_debug_info_module->start, 45703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes &r_debug_info_module->end, 45803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes NULL, NULL)) 45903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 46003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes r_debug_info_module->elf = elf; 46103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes r_debug_info_module->fd = fd; 46203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes elf = NULL; 46303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes fd = -1; 46403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 46503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 46603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (elf != NULL) 46703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes elf_end (elf); 46803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (fd != -1) 46903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes close (fd); 47025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 47125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 47225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 47325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 47425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (mod != NULL) 47525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 47625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ++result; 47725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 47825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Move this module to the end of the list, so that we end 47925b3c049e70834cf33790a28643ab058b507b35cBen Cheng up with a list in the same order as the link_map chain. */ 48025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (mod->next != NULL) 48125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 48225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*lastmodp != mod) 48325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 48425b3c049e70834cf33790a28643ab058b507b35cBen Cheng lastmodp = &dwfl->modulelist; 48525b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (*lastmodp != mod) 48625b3c049e70834cf33790a28643ab058b507b35cBen Cheng lastmodp = &(*lastmodp)->next; 48725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 48825b3c049e70834cf33790a28643ab058b507b35cBen Cheng *lastmodp = mod->next; 48925b3c049e70834cf33790a28643ab058b507b35cBen Cheng mod->next = NULL; 49025b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (*lastmodp != NULL) 49125b3c049e70834cf33790a28643ab058b507b35cBen Cheng lastmodp = &(*lastmodp)->next; 49225b3c049e70834cf33790a28643ab058b507b35cBen Cheng *lastmodp = mod; 49325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 49425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 49525b3c049e70834cf33790a28643ab058b507b35cBen Cheng lastmodp = &mod->next; 49625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 49725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 49825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 49925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return release_buffer (result); 50025b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 50125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 50225b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic GElf_Addr 50325b3c049e70834cf33790a28643ab058b507b35cBen Chengconsider_executable (Dwfl_Module *mod, GElf_Addr at_phdr, GElf_Addr at_entry, 50425b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint_fast8_t *elfclass, uint_fast8_t *elfdata, 50525b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwfl_Memory_Callback *memory_callback, 50625b3c049e70834cf33790a28643ab058b507b35cBen Cheng void *memory_callback_arg) 50725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 50825b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Ehdr ehdr; 50925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (unlikely (gelf_getehdr (mod->main.elf, &ehdr) == NULL)) 51025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 51125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 51225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (at_entry != 0) 51325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 51425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* If we have an AT_ENTRY value, reject this executable if 51525b3c049e70834cf33790a28643ab058b507b35cBen Cheng its entry point address could not have supplied that. */ 51625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 51725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr.e_entry == 0) 51825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 51925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 52025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (mod->e_type == ET_EXEC) 52125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 52225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr.e_entry != at_entry) 52325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 52425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 52525b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 52625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 52725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* It could be a PIE. */ 52825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 52925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 53025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 53125b3c049e70834cf33790a28643ab058b507b35cBen Cheng // XXX this could be saved in the file cache: phdr vaddr, DT_DEBUG d_val vaddr 53225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Find the vaddr of the DT_DEBUG's d_ptr. This is the memory 53325b3c049e70834cf33790a28643ab058b507b35cBen Cheng address where &r_debug was written at runtime. */ 53425b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Xword align = mod->dwfl->segment_align; 53525b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Addr d_val_vaddr = 0; 53603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes size_t phnum; 53703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (elf_getphdrnum (mod->main.elf, &phnum) != 0) 53803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return 0; 53903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 54003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes for (size_t i = 0; i < phnum; ++i) 54125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 54225b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Phdr phdr_mem; 54325b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Phdr *phdr = gelf_getphdr (mod->main.elf, i, &phdr_mem); 54425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (phdr == NULL) 54525b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 54625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 54725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (phdr->p_align > 1 && (align == 0 || phdr->p_align < align)) 54825b3c049e70834cf33790a28643ab058b507b35cBen Cheng align = phdr->p_align; 54925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 55025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (at_phdr != 0 55125b3c049e70834cf33790a28643ab058b507b35cBen Cheng && phdr->p_type == PT_LOAD 55225b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (phdr->p_offset & -align) == (ehdr.e_phoff & -align)) 55325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 55425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* This is the segment that would map the phdrs. 55525b3c049e70834cf33790a28643ab058b507b35cBen Cheng If we have an AT_PHDR value, reject this executable 55625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if its phdr mapping could not have supplied that. */ 55725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (mod->e_type == ET_EXEC) 55825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 55925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr.e_phoff - phdr->p_offset + phdr->p_vaddr != at_phdr) 56025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 56125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 56225b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 56325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 56425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* It could be a PIE. If the AT_PHDR value and our 56525b3c049e70834cf33790a28643ab058b507b35cBen Cheng phdr address don't match modulo ALIGN, then this 56625b3c049e70834cf33790a28643ab058b507b35cBen Cheng could not have been the right PIE. */ 56725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (((ehdr.e_phoff - phdr->p_offset + phdr->p_vaddr) & -align) 56825b3c049e70834cf33790a28643ab058b507b35cBen Cheng != (at_phdr & -align)) 56925b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 57025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 57125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Calculate the bias applied to the PIE's p_vaddr values. */ 57225b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Addr bias = (at_phdr - (ehdr.e_phoff - phdr->p_offset 57325b3c049e70834cf33790a28643ab058b507b35cBen Cheng + phdr->p_vaddr)); 57425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 57525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Final sanity check: if we have an AT_ENTRY value, 57625b3c049e70834cf33790a28643ab058b507b35cBen Cheng reject this PIE unless its biased e_entry matches. */ 57725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (at_entry != 0 && at_entry != ehdr.e_entry + bias) 57825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 57925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 58025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* If we're changing the module's address range, 58125b3c049e70834cf33790a28643ab058b507b35cBen Cheng we've just invalidated the module lookup table. */ 58225b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Addr mod_bias = dwfl_adjusted_address (mod, 0); 58325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (bias != mod_bias) 58425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 58525b3c049e70834cf33790a28643ab058b507b35cBen Cheng mod->low_addr -= mod_bias; 58625b3c049e70834cf33790a28643ab058b507b35cBen Cheng mod->high_addr -= mod_bias; 58725b3c049e70834cf33790a28643ab058b507b35cBen Cheng mod->low_addr += bias; 58825b3c049e70834cf33790a28643ab058b507b35cBen Cheng mod->high_addr += bias; 58925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 59025b3c049e70834cf33790a28643ab058b507b35cBen Cheng free (mod->dwfl->lookup_module); 59125b3c049e70834cf33790a28643ab058b507b35cBen Cheng mod->dwfl->lookup_module = NULL; 59225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 59325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 59425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 59525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 59625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (phdr->p_type == PT_DYNAMIC) 59725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 59825b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data *data = elf_getdata_rawchunk (mod->main.elf, phdr->p_offset, 59925b3c049e70834cf33790a28643ab058b507b35cBen Cheng phdr->p_filesz, ELF_T_DYN); 60025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (data == NULL) 60125b3c049e70834cf33790a28643ab058b507b35cBen Cheng continue; 60225b3c049e70834cf33790a28643ab058b507b35cBen Cheng const size_t entsize = gelf_fsize (mod->main.elf, 60325b3c049e70834cf33790a28643ab058b507b35cBen Cheng ELF_T_DYN, 1, EV_CURRENT); 60425b3c049e70834cf33790a28643ab058b507b35cBen Cheng const size_t n = data->d_size / entsize; 60525b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (size_t j = 0; j < n; ++j) 60625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 60725b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Dyn dyn_mem; 60825b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Dyn *dyn = gelf_getdyn (data, j, &dyn_mem); 60925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (dyn != NULL && dyn->d_tag == DT_DEBUG) 61025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 61125b3c049e70834cf33790a28643ab058b507b35cBen Cheng d_val_vaddr = phdr->p_vaddr + entsize * j + entsize / 2; 61225b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 61325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 61425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 61525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 61625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 61725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 61825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (d_val_vaddr != 0) 61925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 62025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Now we have the final address from which to read &r_debug. */ 62125b3c049e70834cf33790a28643ab058b507b35cBen Cheng d_val_vaddr = dwfl_adjusted_address (mod, d_val_vaddr); 62225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 62325b3c049e70834cf33790a28643ab058b507b35cBen Cheng void *buffer = NULL; 62425b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t buffer_available = addrsize (ehdr.e_ident[EI_CLASS]); 62525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 62625b3c049e70834cf33790a28643ab058b507b35cBen Cheng int segndx = INTUSE(dwfl_addrsegment) (mod->dwfl, d_val_vaddr, NULL); 62725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 62825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((*memory_callback) (mod->dwfl, segndx, 62925b3c049e70834cf33790a28643ab058b507b35cBen Cheng &buffer, &buffer_available, 63025b3c049e70834cf33790a28643ab058b507b35cBen Cheng d_val_vaddr, buffer_available, 63125b3c049e70834cf33790a28643ab058b507b35cBen Cheng memory_callback_arg)) 63225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 63325b3c049e70834cf33790a28643ab058b507b35cBen Cheng const union 63425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 63525b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf32_Addr a32; 63625b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf64_Addr a64; 63725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } *u = buffer; 63825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 63925b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Addr vaddr; 64025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (ehdr.e_ident[EI_CLASS] == ELFCLASS32) 64125b3c049e70834cf33790a28643ab058b507b35cBen Cheng vaddr = (ehdr.e_ident[EI_DATA] == ELFDATA2MSB 64225b3c049e70834cf33790a28643ab058b507b35cBen Cheng ? BE32 (u->a32) : LE32 (u->a32)); 64325b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 64425b3c049e70834cf33790a28643ab058b507b35cBen Cheng vaddr = (ehdr.e_ident[EI_DATA] == ELFDATA2MSB 64525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ? BE64 (u->a64) : LE64 (u->a64)); 64625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 64725b3c049e70834cf33790a28643ab058b507b35cBen Cheng (*memory_callback) (mod->dwfl, -1, &buffer, &buffer_available, 0, 0, 64825b3c049e70834cf33790a28643ab058b507b35cBen Cheng memory_callback_arg); 64925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 65025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*elfclass == ELFCLASSNONE) 65125b3c049e70834cf33790a28643ab058b507b35cBen Cheng *elfclass = ehdr.e_ident[EI_CLASS]; 65225b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (*elfclass != ehdr.e_ident[EI_CLASS]) 65325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 65425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 65525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (*elfdata == ELFDATANONE) 65625b3c049e70834cf33790a28643ab058b507b35cBen Cheng *elfdata = ehdr.e_ident[EI_DATA]; 65725b3c049e70834cf33790a28643ab058b507b35cBen Cheng else if (*elfdata != ehdr.e_ident[EI_DATA]) 65825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 65925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 66025b3c049e70834cf33790a28643ab058b507b35cBen Cheng return vaddr; 66125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 66225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 66325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 66425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 66525b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 66625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 66725b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Try to find an existing executable module with a DT_DEBUG. */ 66825b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic GElf_Addr 66925b3c049e70834cf33790a28643ab058b507b35cBen Chengfind_executable (Dwfl *dwfl, GElf_Addr at_phdr, GElf_Addr at_entry, 67025b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint_fast8_t *elfclass, uint_fast8_t *elfdata, 67125b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwfl_Memory_Callback *memory_callback, 67225b3c049e70834cf33790a28643ab058b507b35cBen Cheng void *memory_callback_arg) 67325b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 67425b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (Dwfl_Module *mod = dwfl->modulelist; mod != NULL; mod = mod->next) 67525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (mod->main.elf != NULL) 67625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 67725b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Addr r_debug_vaddr = consider_executable (mod, at_phdr, at_entry, 67825b3c049e70834cf33790a28643ab058b507b35cBen Cheng elfclass, elfdata, 67925b3c049e70834cf33790a28643ab058b507b35cBen Cheng memory_callback, 68025b3c049e70834cf33790a28643ab058b507b35cBen Cheng memory_callback_arg); 68125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (r_debug_vaddr != 0) 68225b3c049e70834cf33790a28643ab058b507b35cBen Cheng return r_debug_vaddr; 68325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 68425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 68525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 68625b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 68725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 68825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 68925b3c049e70834cf33790a28643ab058b507b35cBen Chengint 69025b3c049e70834cf33790a28643ab058b507b35cBen Chengdwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size, 69125b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwfl_Memory_Callback *memory_callback, 69203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes void *memory_callback_arg, 69303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes struct r_debug_info *r_debug_info) 69425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 69525b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Addr r_debug_vaddr = 0; 69625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 69725b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint_fast8_t elfclass = ELFCLASSNONE; 69825b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint_fast8_t elfdata = ELFDATANONE; 69925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (likely (auxv != NULL) 70025b3c049e70834cf33790a28643ab058b507b35cBen Cheng && likely (auxv_format_probe (auxv, auxv_size, &elfclass, &elfdata))) 70125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 70225b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Addr entry = 0; 70325b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Addr phdr = 0; 70425b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Xword phent = 0; 70525b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Xword phnum = 0; 70625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 70703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#define READ_AUXV32(ptr) read_4ubyte_unaligned_noncvt (ptr) 70803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#define READ_AUXV64(ptr) read_8ubyte_unaligned_noncvt (ptr) 70903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#define AUXV_SCAN(NN, BL) do \ 71003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { \ 71103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes const Elf##NN##_auxv_t *av = auxv; \ 71203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes for (size_t i = 0; i < auxv_size / sizeof av[0]; ++i) \ 71303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { \ 71403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes uint##NN##_t type = READ_AUXV##NN (&av[i].a_type); \ 71503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes uint##NN##_t val = BL##NN (READ_AUXV##NN (&av[i].a_un.a_val)); \ 71603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (type == BL##NN (AT_ENTRY)) \ 71703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes entry = val; \ 71803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes else if (type == BL##NN (AT_PHDR)) \ 71903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes phdr = val; \ 72003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes else if (type == BL##NN (AT_PHNUM)) \ 72103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes phnum = val; \ 72203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes else if (type == BL##NN (AT_PHENT)) \ 72303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes phent = val; \ 72403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes else if (type == BL##NN (AT_PAGESZ)) \ 72503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { \ 72603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (val > 1 \ 72703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes && (dwfl->segment_align == 0 \ 72803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes || val < dwfl->segment_align)) \ 72903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes dwfl->segment_align = val; \ 73003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } \ 73103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } \ 73203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } \ 73325b3c049e70834cf33790a28643ab058b507b35cBen Cheng while (0) 73425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 73525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elfclass == ELFCLASS32) 73625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 73725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elfdata == ELFDATA2MSB) 73825b3c049e70834cf33790a28643ab058b507b35cBen Cheng AUXV_SCAN (32, BE); 73925b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 74025b3c049e70834cf33790a28643ab058b507b35cBen Cheng AUXV_SCAN (32, LE); 74125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 74225b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 74325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 74425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elfdata == ELFDATA2MSB) 74525b3c049e70834cf33790a28643ab058b507b35cBen Cheng AUXV_SCAN (64, BE); 74625b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 74725b3c049e70834cf33790a28643ab058b507b35cBen Cheng AUXV_SCAN (64, LE); 74825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 74925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 75025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* If we found the phdr dimensions, search phdrs for PT_DYNAMIC. */ 75125b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Addr dyn_vaddr = 0; 75225b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Xword dyn_filesz = 0; 75325b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Addr dyn_bias = (GElf_Addr) -1; 75425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 75525b3c049e70834cf33790a28643ab058b507b35cBen Cheng inline bool consider_phdr (GElf_Word type, 75625b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Addr vaddr, GElf_Xword filesz) 75725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 75825b3c049e70834cf33790a28643ab058b507b35cBen Cheng switch (type) 75925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 76025b3c049e70834cf33790a28643ab058b507b35cBen Cheng case PT_PHDR: 76125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (dyn_bias == (GElf_Addr) -1 76225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Do a sanity check on the putative address. */ 76325b3c049e70834cf33790a28643ab058b507b35cBen Cheng && ((vaddr & (dwfl->segment_align - 1)) 76425b3c049e70834cf33790a28643ab058b507b35cBen Cheng == (phdr & (dwfl->segment_align - 1)))) 76525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 76625b3c049e70834cf33790a28643ab058b507b35cBen Cheng dyn_bias = phdr - vaddr; 76725b3c049e70834cf33790a28643ab058b507b35cBen Cheng return dyn_vaddr != 0; 76825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 76925b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 77025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 77125b3c049e70834cf33790a28643ab058b507b35cBen Cheng case PT_DYNAMIC: 77225b3c049e70834cf33790a28643ab058b507b35cBen Cheng dyn_vaddr = vaddr; 77325b3c049e70834cf33790a28643ab058b507b35cBen Cheng dyn_filesz = filesz; 77425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return dyn_bias != (GElf_Addr) -1; 77525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 77625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 77725b3c049e70834cf33790a28643ab058b507b35cBen Cheng return false; 77825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 77925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 78025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (phdr != 0 && phnum != 0) 78125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 78225b3c049e70834cf33790a28643ab058b507b35cBen Cheng Dwfl_Module *phdr_mod; 78325b3c049e70834cf33790a28643ab058b507b35cBen Cheng int phdr_segndx = INTUSE(dwfl_addrsegment) (dwfl, phdr, &phdr_mod); 78425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data in = 78525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 78625b3c049e70834cf33790a28643ab058b507b35cBen Cheng .d_type = ELF_T_PHDR, 78725b3c049e70834cf33790a28643ab058b507b35cBen Cheng .d_version = EV_CURRENT, 78825b3c049e70834cf33790a28643ab058b507b35cBen Cheng .d_size = phnum * phent, 78925b3c049e70834cf33790a28643ab058b507b35cBen Cheng .d_buf = NULL 79025b3c049e70834cf33790a28643ab058b507b35cBen Cheng }; 79103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes bool in_ok = (*memory_callback) (dwfl, phdr_segndx, &in.d_buf, 79203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes &in.d_size, phdr, phnum * phent, 79303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes memory_callback_arg); 79403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (! in_ok && dwfl->executable_for_core != NULL) 79503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 79603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* AUXV -> PHDR -> DYNAMIC 79703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Both AUXV and DYNAMIC should be always present in a core file. 79803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes PHDR may be missing in core file, try to read it from 79903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes EXECUTABLE_FOR_CORE to find where DYNAMIC is located in the 80003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes core file. */ 80103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 80203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes int fd = open (dwfl->executable_for_core, O_RDONLY); 80303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Elf *elf; 80403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwfl_Error error = DWFL_E_ERRNO; 80503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (fd != -1) 80603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes error = __libdw_open_file (&fd, &elf, true, false); 80703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (error != DWFL_E_NOERROR) 80803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 80903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes __libdwfl_seterrno (error); 81003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return false; 81103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 81203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (elf, &ehdr_mem); 81303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (ehdr == NULL) 81403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 81503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes elf_end (elf); 81603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes close (fd); 81703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes __libdwfl_seterrno (DWFL_E_LIBELF); 81803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return false; 81903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 82003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes size_t e_phnum; 82103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (elf_getphdrnum (elf, &e_phnum) != 0) 82203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 82303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes elf_end (elf); 82403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes close (fd); 82503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes __libdwfl_seterrno (DWFL_E_LIBELF); 82603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return false; 82703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 82803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (e_phnum != phnum || ehdr->e_phentsize != phent) 82903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 83003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes elf_end (elf); 83103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes close (fd); 83203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes __libdwfl_seterrno (DWFL_E_BADELF); 83303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return false; 83403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 83503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes off_t off = ehdr->e_phoff; 83603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes assert (in.d_buf == NULL); 83703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes assert (in.d_size == phnum * phent); 83803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes in.d_buf = malloc (in.d_size); 83903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (unlikely (in.d_buf == NULL)) 84003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 84103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes elf_end (elf); 84203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes close (fd); 84303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes __libdwfl_seterrno (DWFL_E_NOMEM); 84403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return false; 84503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 84603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes ssize_t nread = pread_retry (fd, in.d_buf, in.d_size, off); 84703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes elf_end (elf); 84803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes close (fd); 84903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (nread != (ssize_t) in.d_size) 85003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 85103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes free (in.d_buf); 85203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes __libdwfl_seterrno (DWFL_E_ERRNO); 85303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return false; 85403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 85503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes in_ok = true; 85603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 85703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (in_ok) 85825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 85925b3c049e70834cf33790a28643ab058b507b35cBen Cheng union 86025b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 86125b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf32_Phdr p32; 86225b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf64_Phdr p64; 86325b3c049e70834cf33790a28643ab058b507b35cBen Cheng char data[phnum * phent]; 86425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } buf; 86525b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data out = 86625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 86725b3c049e70834cf33790a28643ab058b507b35cBen Cheng .d_type = ELF_T_PHDR, 86825b3c049e70834cf33790a28643ab058b507b35cBen Cheng .d_version = EV_CURRENT, 86925b3c049e70834cf33790a28643ab058b507b35cBen Cheng .d_size = phnum * phent, 87025b3c049e70834cf33790a28643ab058b507b35cBen Cheng .d_buf = &buf 87125b3c049e70834cf33790a28643ab058b507b35cBen Cheng }; 87225b3c049e70834cf33790a28643ab058b507b35cBen Cheng in.d_size = out.d_size; 87325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (likely ((elfclass == ELFCLASS32 87425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ? elf32_xlatetom : elf64_xlatetom) 87525b3c049e70834cf33790a28643ab058b507b35cBen Cheng (&out, &in, elfdata) != NULL)) 87625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 87725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We are looking for PT_DYNAMIC. */ 87825b3c049e70834cf33790a28643ab058b507b35cBen Cheng const union 87925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 88025b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf32_Phdr p32[phnum]; 88125b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf64_Phdr p64[phnum]; 88225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } *u = (void *) &buf; 88325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elfclass == ELFCLASS32) 88425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 88525b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (size_t i = 0; i < phnum; ++i) 88625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (consider_phdr (u->p32[i].p_type, 88725b3c049e70834cf33790a28643ab058b507b35cBen Cheng u->p32[i].p_vaddr, 88825b3c049e70834cf33790a28643ab058b507b35cBen Cheng u->p32[i].p_filesz)) 88925b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 89025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 89125b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 89225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 89325b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (size_t i = 0; i < phnum; ++i) 89425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (consider_phdr (u->p64[i].p_type, 89525b3c049e70834cf33790a28643ab058b507b35cBen Cheng u->p64[i].p_vaddr, 89625b3c049e70834cf33790a28643ab058b507b35cBen Cheng u->p64[i].p_filesz)) 89725b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 89825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 89925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 90025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 90125b3c049e70834cf33790a28643ab058b507b35cBen Cheng (*memory_callback) (dwfl, -1, &in.d_buf, &in.d_size, 0, 0, 90225b3c049e70834cf33790a28643ab058b507b35cBen Cheng memory_callback_arg); 90325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 90425b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 90525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We could not read the executable's phdrs from the 90625b3c049e70834cf33790a28643ab058b507b35cBen Cheng memory image. If we have a presupplied executable, 90725b3c049e70834cf33790a28643ab058b507b35cBen Cheng we can still use the AT_PHDR and AT_ENTRY values to 90825b3c049e70834cf33790a28643ab058b507b35cBen Cheng verify it, and to adjust its bias if it's a PIE. 90925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 91025b3c049e70834cf33790a28643ab058b507b35cBen Cheng If there was an ET_EXEC module presupplied that contains 91125b3c049e70834cf33790a28643ab058b507b35cBen Cheng the AT_PHDR address, then we only consider that one. 91225b3c049e70834cf33790a28643ab058b507b35cBen Cheng We'll either accept it if its phdr location and e_entry 91325b3c049e70834cf33790a28643ab058b507b35cBen Cheng make sense or reject it if they don't. If there is no 91425b3c049e70834cf33790a28643ab058b507b35cBen Cheng presupplied ET_EXEC, then look for a presupplied module, 91525b3c049e70834cf33790a28643ab058b507b35cBen Cheng which might be a PIE (ET_DYN) that needs its bias adjusted. */ 91625b3c049e70834cf33790a28643ab058b507b35cBen Cheng r_debug_vaddr = ((phdr_mod == NULL 91725b3c049e70834cf33790a28643ab058b507b35cBen Cheng || phdr_mod->main.elf == NULL 91825b3c049e70834cf33790a28643ab058b507b35cBen Cheng || phdr_mod->e_type != ET_EXEC) 91925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ? find_executable (dwfl, phdr, entry, 92025b3c049e70834cf33790a28643ab058b507b35cBen Cheng &elfclass, &elfdata, 92125b3c049e70834cf33790a28643ab058b507b35cBen Cheng memory_callback, 92225b3c049e70834cf33790a28643ab058b507b35cBen Cheng memory_callback_arg) 92325b3c049e70834cf33790a28643ab058b507b35cBen Cheng : consider_executable (phdr_mod, phdr, entry, 92425b3c049e70834cf33790a28643ab058b507b35cBen Cheng &elfclass, &elfdata, 92525b3c049e70834cf33790a28643ab058b507b35cBen Cheng memory_callback, 92625b3c049e70834cf33790a28643ab058b507b35cBen Cheng memory_callback_arg)); 92725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 92825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 92925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* If we found PT_DYNAMIC, search it for DT_DEBUG. */ 93025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (dyn_filesz != 0) 93125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 93225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (dyn_bias != (GElf_Addr) -1) 93325b3c049e70834cf33790a28643ab058b507b35cBen Cheng dyn_vaddr += dyn_bias; 93425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 93525b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data in = 93625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 93725b3c049e70834cf33790a28643ab058b507b35cBen Cheng .d_type = ELF_T_DYN, 93825b3c049e70834cf33790a28643ab058b507b35cBen Cheng .d_version = EV_CURRENT, 93925b3c049e70834cf33790a28643ab058b507b35cBen Cheng .d_size = dyn_filesz, 94025b3c049e70834cf33790a28643ab058b507b35cBen Cheng .d_buf = NULL 94125b3c049e70834cf33790a28643ab058b507b35cBen Cheng }; 94225b3c049e70834cf33790a28643ab058b507b35cBen Cheng int dyn_segndx = dwfl_addrsegment (dwfl, dyn_vaddr, NULL); 94325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((*memory_callback) (dwfl, dyn_segndx, &in.d_buf, &in.d_size, 94425b3c049e70834cf33790a28643ab058b507b35cBen Cheng dyn_vaddr, dyn_filesz, memory_callback_arg)) 94525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 94625b3c049e70834cf33790a28643ab058b507b35cBen Cheng union 94725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 94825b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf32_Dyn d32; 94925b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf64_Dyn d64; 95025b3c049e70834cf33790a28643ab058b507b35cBen Cheng char data[dyn_filesz]; 95125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } buf; 95225b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data out = 95325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 95425b3c049e70834cf33790a28643ab058b507b35cBen Cheng .d_type = ELF_T_DYN, 95525b3c049e70834cf33790a28643ab058b507b35cBen Cheng .d_version = EV_CURRENT, 95625b3c049e70834cf33790a28643ab058b507b35cBen Cheng .d_size = dyn_filesz, 95725b3c049e70834cf33790a28643ab058b507b35cBen Cheng .d_buf = &buf 95825b3c049e70834cf33790a28643ab058b507b35cBen Cheng }; 95925b3c049e70834cf33790a28643ab058b507b35cBen Cheng in.d_size = out.d_size; 96025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (likely ((elfclass == ELFCLASS32 96125b3c049e70834cf33790a28643ab058b507b35cBen Cheng ? elf32_xlatetom : elf64_xlatetom) 96225b3c049e70834cf33790a28643ab058b507b35cBen Cheng (&out, &in, elfdata) != NULL)) 96325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 96425b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We are looking for DT_DEBUG. */ 96525b3c049e70834cf33790a28643ab058b507b35cBen Cheng const union 96625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 96725b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf32_Dyn d32[dyn_filesz / sizeof (Elf32_Dyn)]; 96825b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf64_Dyn d64[dyn_filesz / sizeof (Elf64_Dyn)]; 96925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } *u = (void *) &buf; 97025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elfclass == ELFCLASS32) 97125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 97225b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t n = dyn_filesz / sizeof (Elf32_Dyn); 97325b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (size_t i = 0; i < n; ++i) 97425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (u->d32[i].d_tag == DT_DEBUG) 97525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 97625b3c049e70834cf33790a28643ab058b507b35cBen Cheng r_debug_vaddr = u->d32[i].d_un.d_val; 97725b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 97825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 97925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 98025b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 98125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 98225b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t n = dyn_filesz / sizeof (Elf64_Dyn); 98325b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (size_t i = 0; i < n; ++i) 98425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (u->d64[i].d_tag == DT_DEBUG) 98525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 98625b3c049e70834cf33790a28643ab058b507b35cBen Cheng r_debug_vaddr = u->d64[i].d_un.d_val; 98725b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 98825b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 98925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 99025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 99125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 99225b3c049e70834cf33790a28643ab058b507b35cBen Cheng (*memory_callback) (dwfl, -1, &in.d_buf, &in.d_size, 0, 0, 99325b3c049e70834cf33790a28643ab058b507b35cBen Cheng memory_callback_arg); 99425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 99525b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 99625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 99725b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 99825b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We have to look for a presupplied executable file to determine 99925b3c049e70834cf33790a28643ab058b507b35cBen Cheng the vaddr of its dynamic section and DT_DEBUG therein. */ 100025b3c049e70834cf33790a28643ab058b507b35cBen Cheng r_debug_vaddr = find_executable (dwfl, 0, 0, &elfclass, &elfdata, 100125b3c049e70834cf33790a28643ab058b507b35cBen Cheng memory_callback, memory_callback_arg); 100225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 100325b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (r_debug_vaddr == 0) 100425b3c049e70834cf33790a28643ab058b507b35cBen Cheng return 0; 100525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 100625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* For following pointers from struct link_map, we will use an 100725b3c049e70834cf33790a28643ab058b507b35cBen Cheng integrated memory access callback that can consult module text 100825b3c049e70834cf33790a28643ab058b507b35cBen Cheng elided from the core file. This is necessary when the l_name 100925b3c049e70834cf33790a28643ab058b507b35cBen Cheng pointer for the dynamic linker's own entry is a pointer into the 101025b3c049e70834cf33790a28643ab058b507b35cBen Cheng executable's .interp section. */ 101125b3c049e70834cf33790a28643ab058b507b35cBen Cheng struct integrated_memory_callback mcb = 101225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 101325b3c049e70834cf33790a28643ab058b507b35cBen Cheng .memory_callback = memory_callback, 101425b3c049e70834cf33790a28643ab058b507b35cBen Cheng .memory_callback_arg = memory_callback_arg 101525b3c049e70834cf33790a28643ab058b507b35cBen Cheng }; 101625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 101725b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Now we can follow the dynamic linker's library list. */ 101825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return report_r_debug (elfclass, elfdata, dwfl, r_debug_vaddr, 101903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes &integrated_memory_callback, &mcb, r_debug_info); 102025b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 102125b3c049e70834cf33790a28643ab058b507b35cBen ChengINTDEF (dwfl_link_map_report) 1022