1cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Report modules by examining dynamic linker data structures. 2cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Copyright (C) 2008 Red Hat, Inc. 3cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng This file is part of Red Hat elfutils. 4cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 5cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Red Hat elfutils is free software; you can redistribute it and/or modify 6cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng it under the terms of the GNU General Public License as published by the 7cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Free Software Foundation; version 2 of the License. 8cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 9cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Red Hat elfutils is distributed in the hope that it will be useful, but 10cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng WITHOUT ANY WARRANTY; without even the implied warranty of 11cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng General Public License for more details. 13cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 14cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng You should have received a copy of the GNU General Public License along 15cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng with Red Hat elfutils; if not, write to the Free Software Foundation, 16cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. 17cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 18cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng In addition, as a special exception, Red Hat, Inc. gives You the 19cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng additional right to link the code of Red Hat elfutils with code licensed 20cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng under any Open Source Initiative certified open source license 21cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (http://www.opensource.org/licenses/index.php) which requires the 22cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng distribution of source code with any binary distribution and to 23cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng distribute linked combinations of the two. Non-GPL Code permitted under 24cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng this exception must only link to the code of Red Hat elfutils through 25cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng those well defined interfaces identified in the file named EXCEPTION 26cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng found in the source code files (the "Approved Interfaces"). The files 27cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng of Non-GPL Code may instantiate templates or use macros or inline 28cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng functions from the Approved Interfaces without causing the resulting 29cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng work to be covered by the GNU General Public License. Only Red Hat, 30cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Inc. may make changes or additions to the list of Approved Interfaces. 31cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Red Hat's grant of this exception is conditioned upon your not adding 32cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng any new exceptions. If you wish to add a new Approved Interface or 33cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng exception, please contact Red Hat. You must obey the GNU General Public 34cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng License in all respects for all of the Red Hat elfutils code and other 35cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng code used in conjunction with Red Hat elfutils except the Non-GPL Code 36cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng covered by this exception. If you modify this file, you may extend this 37cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng exception to your version of the file, but you are not obligated to do 38cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng so. If you do not wish to provide this exception without modification, 39cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng you must delete this exception statement from your version and license 40cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng this file solely under the GPL without exception. 41cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 42cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Red Hat elfutils is an included package of the Open Invention Network. 43cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng An included package of the Open Invention Network is a package for which 44cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Open Invention Network licensees cross-license their patents. No patent 45cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng license is granted, either expressly or impliedly, by designation as an 46cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng included package. Should you wish to participate in the Open Invention 47cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Network licensing program, please visit www.openinventionnetwork.com 48cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng <http://www.openinventionnetwork.com>. */ 49cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 50cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <config.h> 51cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include "libdwflP.h" 52cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 53cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <byteswap.h> 54cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <endian.h> 55cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 56cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* This element is always provided and always has a constant value. 57cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng This makes it an easy thing to scan for to discern the format. */ 58cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#define PROBE_TYPE AT_PHENT 59cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#define PROBE_VAL32 sizeof (Elf32_Phdr) 60cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#define PROBE_VAL64 sizeof (Elf64_Phdr) 61cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 62cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#if BYTE_ORDER == BIG_ENDIAN 63cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng# define BE32(x) (x) 64cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng# define BE64(x) (x) 65cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng# define LE32(x) bswap_32 (x) 66cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng# define LE64(x) bswap_64 (x) 67cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#else 68cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng# define LE32(x) (x) 69cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng# define LE64(x) (x) 70cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng# define BE32(x) bswap_32 (x) 71cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng# define BE64(x) bswap_64 (x) 72cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 73cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 74cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 75cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Examine an auxv data block and determine its format. 76cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Return true iff we figured it out. */ 77cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic bool 78cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengauxv_format_probe (const void *auxv, size_t size, 79cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint_fast8_t *elfclass, uint_fast8_t *elfdata) 80cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 81cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const union 82cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 83cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng char buf[size]; 84cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf32_auxv_t a32[size / sizeof (Elf32_auxv_t)]; 85cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf64_auxv_t a64[size / sizeof (Elf64_auxv_t)]; 86cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } *u = auxv; 87cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 88cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng inline bool check64 (size_t i) 89cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 90cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (u->a64[i].a_type == BE64 (PROBE_TYPE) 91cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && u->a64[i].a_un.a_val == BE64 (PROBE_VAL64)) 92cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 93cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *elfdata = ELFDATA2MSB; 94cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return true; 95cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 96cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 97cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (u->a64[i].a_type == LE64 (PROBE_TYPE) 98cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && u->a64[i].a_un.a_val == LE64 (PROBE_VAL64)) 99cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 100cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *elfdata = ELFDATA2LSB; 101cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return true; 102cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 103cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 104cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return false; 105cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 106cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 107cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng inline bool check32 (size_t i) 108cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 109cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (u->a32[i].a_type == BE32 (PROBE_TYPE) 110cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && u->a32[i].a_un.a_val == BE32 (PROBE_VAL32)) 111cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 112cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *elfdata = ELFDATA2MSB; 113cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return true; 114cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 115cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 116cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (u->a32[i].a_type == LE32 (PROBE_TYPE) 117cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && u->a32[i].a_un.a_val == LE32 (PROBE_VAL32)) 118cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 119cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *elfdata = ELFDATA2LSB; 120cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return true; 121cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 122cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 123cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return false; 124cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 125cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 126cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t i; 127cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (i = 0; i < size / sizeof (Elf64_auxv_t); ++i) 128cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 129cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (check64 (i)) 130cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 131cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *elfclass = ELFCLASS64; 132cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return true; 133cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 134cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 135cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (check32 (i)) 136cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 137cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *elfclass = ELFCLASS32; 138cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return true; 139cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 140cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 141cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (; i < size / sizeof (Elf64_auxv_t); ++i) 142cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (check32 (i)) 143cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 144cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *elfclass = ELFCLASS32; 145cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return true; 146cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 147cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 148cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return false; 149cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 150cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 151cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* This is a Dwfl_Memory_Callback that wraps another memory callback. 152cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng If the underlying callback cannot fill the data, then this will 153cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng fall back to fetching data from module files. */ 154cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 155cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstruct integrated_memory_callback 156cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 157cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Dwfl_Memory_Callback *memory_callback; 158cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng void *memory_callback_arg; 159cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng void *buffer; 160cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng}; 161cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 162cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic bool 163cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengintegrated_memory_callback (Dwfl *dwfl, int ndx, 164cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng void **buffer, size_t *buffer_available, 165cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Addr vaddr, 166cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t minread, 167cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng void *arg) 168cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 169cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct integrated_memory_callback *info = arg; 170cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 171cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (ndx == -1) 172cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 173cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Called for cleanup. */ 174cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (info->buffer != NULL) 175cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 176cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* The last probe buffer came from the underlying callback. 177cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Let it do its cleanup. */ 178cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (*buffer == info->buffer); /* XXX */ 179cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *buffer = info->buffer; 180cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng info->buffer = NULL; 181cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return (*info->memory_callback) (dwfl, ndx, buffer, buffer_available, 182cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng vaddr, minread, 183cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng info->memory_callback_arg); 184cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 185cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *buffer = NULL; 186cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *buffer_available = 0; 187cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return false; 188cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 189cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 190cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*buffer != NULL) 191cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* For a final-read request, we only use the underlying callback. */ 192cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return (*info->memory_callback) (dwfl, ndx, buffer, buffer_available, 193cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng vaddr, minread, info->memory_callback_arg); 194cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 195cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Let the underlying callback try to fill this request. */ 196cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((*info->memory_callback) (dwfl, ndx, &info->buffer, buffer_available, 197cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng vaddr, minread, info->memory_callback_arg)) 198cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 199cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *buffer = info->buffer; 200cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return true; 201cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 202cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 203cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Now look for module text covering this address. */ 204cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 205cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Dwfl_Module *mod; 206cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (void) INTUSE(dwfl_addrsegment) (dwfl, vaddr, &mod); 207cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (mod == NULL) 208cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return false; 209cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 210cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Dwarf_Addr bias; 211cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Scn *scn = INTUSE(dwfl_module_address_section) (mod, &vaddr, &bias); 212cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unlikely (scn == NULL)) 213cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 214cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#if 0 // XXX would have to handle ndx=-1 cleanup calls passed down. 215cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* If we have no sections we can try to fill it from the module file 216cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng based on its phdr mappings. */ 217cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (likely (mod->e_type != ET_REL) && mod->main.elf != NULL) 218cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return INTUSE(dwfl_elf_phdr_memory_callback) 219cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (dwfl, 0, buffer, buffer_available, 220cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng vaddr - mod->main.bias, minread, mod->main.elf); 221cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 222cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return false; 223cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 224cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 225cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *data = elf_rawdata (scn, NULL); 226cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unlikely (data == NULL)) 227cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng // XXX throw error? 228cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return false; 229cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 230cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unlikely (data->d_size < vaddr)) 231cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return false; 232cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 233cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Provide as much data as we have. */ 234cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng void *contents = data->d_buf + vaddr; 235cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t avail = data->d_size - vaddr; 236cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unlikely (avail < minread)) 237cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return false; 238cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 239cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* If probing for a string, make sure it's terminated. */ 240cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (minread == 0 && unlikely (memchr (contents, '\0', avail) == NULL)) 241cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return false; 242cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 243cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* We have it! */ 244cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *buffer = contents; 245cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *buffer_available = avail; 246cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return true; 247cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 248cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 249cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic size_t 250cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengaddrsize (uint_fast8_t elfclass) 251cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 252cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return elfclass * 4; 253cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 254cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 255cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Report a module for each struct link_map in the linked list at r_map 256cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng in the struct r_debug at R_DEBUG_VADDR. 257cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 258cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng For each link_map entry, if an existing module resides at its address, 259cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng this just modifies that module's name and suggested file name. If 260cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng no such module exists, this calls dwfl_report_elf on the l_name string. 261cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 262cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Returns the number of modules found, or -1 for errors. */ 263cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 264cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic int 265cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengreport_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata, 266cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Dwfl *dwfl, GElf_Addr r_debug_vaddr, 267cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Dwfl_Memory_Callback *memory_callback, 268cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng void *memory_callback_arg) 269cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 270cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Skip r_version, to aligned r_map field. */ 271cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Addr read_vaddr = r_debug_vaddr + addrsize (elfclass); 272cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 273cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng void *buffer = NULL; 274cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t buffer_available = 0; 275cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng inline int release_buffer (int result) 276cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 277cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (buffer != NULL) 278cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (void) (*memory_callback) (dwfl, -1, &buffer, &buffer_available, 0, 0, 279cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng memory_callback_arg); 280cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return result; 281cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 282cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 283cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Addr addrs[4]; 284cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng inline bool read_addrs (GElf_Addr vaddr, size_t n) 285cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 286cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t nb = n * addrsize (elfclass); /* Address words -> bytes to read. */ 287cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 288cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Read a new buffer if the old one doesn't cover these words. */ 289cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (buffer == NULL 290cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || vaddr < read_vaddr 291cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || vaddr - read_vaddr + nb > buffer_available) 292cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 293cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng release_buffer (0); 294cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 295cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng read_vaddr = vaddr; 296cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int segndx = INTUSE(dwfl_addrsegment) (dwfl, vaddr, NULL); 297cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unlikely (segndx < 0) 298cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || unlikely (! (*memory_callback) (dwfl, segndx, 299cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng &buffer, &buffer_available, 300cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng vaddr, nb, memory_callback_arg))) 301cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return true; 302cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 303cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 304cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const union 305cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 306cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf32_Addr a32[n]; 307cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf64_Addr a64[n]; 308cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } *in = vaddr - read_vaddr + buffer; 309cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 310cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (elfclass == ELFCLASS32) 311cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 312cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (elfdata == ELFDATA2MSB) 313cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t i = 0; i < n; ++i) 314cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng addrs[i] = BE32 (in->a32[i]); 315cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 316cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t i = 0; i < n; ++i) 317cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng addrs[i] = LE32 (in->a32[i]); 318cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 319cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 320cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 321cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (elfdata == ELFDATA2MSB) 322cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t i = 0; i < n; ++i) 323cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng addrs[i] = BE64 (in->a64[i]); 324cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 325cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t i = 0; i < n; ++i) 326cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng addrs[i] = LE64 (in->a64[i]); 327cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 328cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 329cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return false; 330cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 331cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 332cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unlikely (read_addrs (read_vaddr, 1))) 333cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return release_buffer (-1); 334cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 335cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Addr next = addrs[0]; 336cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 337cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Dwfl_Module **lastmodp = &dwfl->modulelist; 338cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int result = 0; 339cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while (next != 0) 340cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 341cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (read_addrs (next, 4)) 342cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return release_buffer (-1); 343cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 344cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Addr l_addr = addrs[0]; 345cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Addr l_name = addrs[1]; 346cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Addr l_ld = addrs[2]; 347cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng next = addrs[3]; 348cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 349cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Fetch the string at the l_name address. */ 350cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const char *name = NULL; 351cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (buffer != NULL 352cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && read_vaddr <= l_name 353cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && l_name + 1 - read_vaddr < buffer_available 354cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && memchr (l_name - read_vaddr + buffer, '\0', 355cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng buffer_available - (l_name - read_vaddr)) != NULL) 356cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng name = l_name - read_vaddr + buffer; 357cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 358cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 359cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng release_buffer (0); 360cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng read_vaddr = l_name; 361cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int segndx = INTUSE(dwfl_addrsegment) (dwfl, l_name, NULL); 362cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (likely (segndx >= 0) 363cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && (*memory_callback) (dwfl, segndx, 364cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng &buffer, &buffer_available, 365cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng l_name, 0, memory_callback_arg)) 366cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng name = buffer; 367cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 368cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 369cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (name != NULL && name[0] == '\0') 370cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng name = NULL; 371cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 372cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* If content-sniffing already reported a module covering 373cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng the same area, find that existing module to adjust. 374cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng The l_ld address is the only one we know for sure 375cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng to be within the module's own segments (its .dynamic). */ 376cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Dwfl_Module *mod; 377cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int segndx = INTUSE(dwfl_addrsegment) (dwfl, l_ld, &mod); 378cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unlikely (segndx < 0)) 379cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return release_buffer (-1); 380cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 381cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (mod != NULL) 382cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 383cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* We have a module. We can give it a better name from l_name. */ 384cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (name != NULL && mod->name[0] == '[') 385cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 386cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng char *newname = strdup (basename (name)); 387cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (newname != NULL) 388cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 389cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng free (mod->name); 390cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng mod->name = newname; 391cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 392cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 393cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 394cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (name == NULL && mod->name[0] == '/') 395cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng name = mod->name; 396cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 397cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* If we don't have a file for it already, we can pre-install 398cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng the full file name from l_name. Opening the file by this 399cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng name will be the fallback when no build ID match is found. 400cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng XXX hook for sysroot */ 401cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (name != NULL 402cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && mod->main.elf == NULL 403cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && mod->main.name == NULL) 404cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng mod->main.name = strdup (name); 405cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 406cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (name != NULL) 407cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 408cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* We have to find the file's phdrs to compute along with l_addr 409cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng what its runtime address boundaries are. */ 410cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 411cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng // XXX hook for sysroot 412cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng mod = INTUSE(dwfl_report_elf) (dwfl, basename (name), 413cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng name, -1, l_addr); 414cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 415cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 416cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (mod != NULL) 417cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 418cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ++result; 419cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 420cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Move this module to the end of the list, so that we end 421cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng up with a list in the same order as the link_map chain. */ 422cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (mod->next != NULL) 423cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 424cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*lastmodp != mod) 425cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 426cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng lastmodp = &dwfl->modulelist; 427cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while (*lastmodp != mod) 428cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng lastmodp = &(*lastmodp)->next; 429cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 430cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *lastmodp = mod->next; 431cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng mod->next = NULL; 432cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while (*lastmodp != NULL) 433cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng lastmodp = &(*lastmodp)->next; 434cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *lastmodp = mod; 435cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 436cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 437cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng lastmodp = &mod->next; 438cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 439cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 440cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 441cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return release_buffer (result); 442cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 443cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 444cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic GElf_Addr 445cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengconsider_executable (Dwfl_Module *mod, GElf_Addr at_phdr, GElf_Addr at_entry, 446cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint_fast8_t *elfclass, uint_fast8_t *elfdata, 447cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Dwfl_Memory_Callback *memory_callback, 448cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng void *memory_callback_arg) 449cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 450cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Ehdr ehdr; 451cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (unlikely (gelf_getehdr (mod->main.elf, &ehdr) == NULL)) 452cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 453cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 454cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (at_entry != 0) 455cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 456cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* If we have an AT_ENTRY value, reject this executable if 457cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng its entry point address could not have supplied that. */ 458cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 459cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (ehdr.e_entry == 0) 460cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 461cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 462cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (mod->e_type == ET_EXEC) 463cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 464cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (ehdr.e_entry != at_entry) 465cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 466cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 467cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 468cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 469cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* It could be a PIE. */ 470cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 471cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 472cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 473cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng // XXX this could be saved in the file cache: phdr vaddr, DT_DEBUG d_val vaddr 474cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Find the vaddr of the DT_DEBUG's d_ptr. This is the memory 475cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng address where &r_debug was written at runtime. */ 476cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Xword align = mod->dwfl->segment_align; 477cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Addr d_val_vaddr = 0; 478cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (uint_fast16_t i = 0; i < ehdr.e_phnum; ++i) 479cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 480cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Phdr phdr_mem; 481cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Phdr *phdr = gelf_getphdr (mod->main.elf, i, &phdr_mem); 482cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (phdr == NULL) 483cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 484cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 485cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (phdr->p_align > 1 && (align == 0 || phdr->p_align < align)) 486cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng align = phdr->p_align; 487cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 488cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (at_phdr != 0 489cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && phdr->p_type == PT_LOAD 490cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && (phdr->p_offset & -align) == (ehdr.e_phoff & -align)) 491cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 492cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* This is the segment that would map the phdrs. 493cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng If we have an AT_PHDR value, reject this executable 494cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if its phdr mapping could not have supplied that. */ 495cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (mod->e_type == ET_EXEC) 496cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 497cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (ehdr.e_phoff - phdr->p_offset + phdr->p_vaddr != at_phdr) 498cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 499cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 500cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 501cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 502cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* It could be a PIE. If the AT_PHDR value and our 503cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng phdr address don't match modulo ALIGN, then this 504cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng could not have been the right PIE. */ 505cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (((ehdr.e_phoff - phdr->p_offset + phdr->p_vaddr) & -align) 506cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng != (at_phdr & -align)) 507cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 508cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 509cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Calculate the bias applied to the PIE's p_vaddr values. */ 510cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Addr bias = (at_phdr - (ehdr.e_phoff - phdr->p_offset 511cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng + phdr->p_vaddr)); 512cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 513cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Final sanity check: if we have an AT_ENTRY value, 514cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng reject this PIE unless its biased e_entry matches. */ 515cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (at_entry != 0 && at_entry != ehdr.e_entry + bias) 516cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 517cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 518cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* If we're changing the module's address range, 519cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng we've just invalidated the module lookup table. */ 520cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (bias != mod->main.bias) 521cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 522cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng mod->low_addr -= mod->main.bias; 523cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng mod->high_addr -= mod->main.bias; 524cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng mod->main.bias = bias; 525cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng mod->low_addr += bias; 526cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng mod->high_addr += bias; 527cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 528cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng free (mod->dwfl->lookup_module); 529cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng mod->dwfl->lookup_module = NULL; 530cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 531cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 532cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 533cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 534cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (phdr->p_type == PT_DYNAMIC) 535cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 536cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data *data = elf_getdata_rawchunk (mod->main.elf, phdr->p_offset, 537cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng phdr->p_filesz, ELF_T_DYN); 538cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (data == NULL) 539cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng continue; 540cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const size_t entsize = gelf_fsize (mod->main.elf, 541cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ELF_T_DYN, 1, EV_CURRENT); 542cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const size_t n = data->d_size / entsize; 543cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t j = 0; j < n; ++j) 544cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 545cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Dyn dyn_mem; 546cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Dyn *dyn = gelf_getdyn (data, j, &dyn_mem); 547cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (dyn != NULL && dyn->d_tag == DT_DEBUG) 548cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 549cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng d_val_vaddr = phdr->p_vaddr + entsize * j + entsize / 2; 550cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 551cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 552cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 553cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 554cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 555cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 556cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (d_val_vaddr != 0) 557cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 558cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Now we have the final address from which to read &r_debug. */ 559cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng d_val_vaddr += mod->main.bias; 560cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 561cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng void *buffer = NULL; 562cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t buffer_available = addrsize (ehdr.e_ident[EI_CLASS]); 563cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 564cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Dwfl_Module *m; 565cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int segndx = INTUSE(dwfl_addrsegment) (mod->dwfl, d_val_vaddr, &m); 566cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng assert (m == mod); 567cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 568cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((*memory_callback) (mod->dwfl, segndx, 569cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng &buffer, &buffer_available, 570cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng d_val_vaddr, buffer_available, 571cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng memory_callback_arg)) 572cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 573cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const union 574cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 575cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf32_Addr a32; 576cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf64_Addr a64; 577cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } *u = buffer; 578cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 579cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Addr vaddr; 580cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (ehdr.e_ident[EI_CLASS] == ELFCLASS32) 581cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng vaddr = (ehdr.e_ident[EI_DATA] == ELFDATA2MSB 582cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ? BE32 (u->a32) : LE32 (u->a32)); 583cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 584cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng vaddr = (ehdr.e_ident[EI_DATA] == ELFDATA2MSB 585cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ? BE64 (u->a64) : LE64 (u->a64)); 586cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 587cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (*memory_callback) (mod->dwfl, -1, &buffer, &buffer_available, 0, 0, 588cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng memory_callback_arg); 589cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 590cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 591cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*elfclass == ELFCLASSNONE) 592cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *elfclass = ehdr.e_ident[EI_CLASS]; 593cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (*elfclass != ehdr.e_ident[EI_CLASS]) 594cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 595cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 596cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (*elfdata == ELFDATANONE) 597cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng *elfdata = ehdr.e_ident[EI_DATA]; 598cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (*elfdata != ehdr.e_ident[EI_DATA]) 599cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 600cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 601cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return vaddr; 602cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 603cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 604cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 605cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 606cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 607cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 608cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Try to find an existing executable module with a DT_DEBUG. */ 609cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic GElf_Addr 610cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengfind_executable (Dwfl *dwfl, GElf_Addr at_phdr, GElf_Addr at_entry, 611cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint_fast8_t *elfclass, uint_fast8_t *elfdata, 612cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Dwfl_Memory_Callback *memory_callback, 613cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng void *memory_callback_arg) 614cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 615cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (Dwfl_Module *mod = dwfl->modulelist; mod != NULL; mod = mod->next) 616cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (mod->main.elf != NULL) 617cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 618cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Addr r_debug_vaddr = consider_executable (mod, at_phdr, at_entry, 619cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng elfclass, elfdata, 620cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng memory_callback, 621cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng memory_callback_arg); 622cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (r_debug_vaddr != 0) 623cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return r_debug_vaddr; 624cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 625cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 626cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 627cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 628cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 629cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 630cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengint 631cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengdwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size, 632cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Dwfl_Memory_Callback *memory_callback, 633cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng void *memory_callback_arg) 634cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 635cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Addr r_debug_vaddr = 0; 636cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 637cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint_fast8_t elfclass = ELFCLASSNONE; 638cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng uint_fast8_t elfdata = ELFDATANONE; 639cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (likely (auxv != NULL) 640cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && likely (auxv_format_probe (auxv, auxv_size, &elfclass, &elfdata))) 641cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 642cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Addr entry = 0; 643cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Addr phdr = 0; 644cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Xword phent = 0; 645cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Xword phnum = 0; 646cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 647cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#define AUXV_SCAN(NN, BL) do \ 648cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { \ 649cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const Elf##NN##_auxv_t *av = auxv; \ 650cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t i = 0; i < auxv_size / sizeof av[0]; ++i) \ 651cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { \ 652cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf##NN##_Addr val = BL##NN (av[i].a_un.a_val); \ 653cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (av[i].a_type == BL##NN (AT_ENTRY)) \ 654cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng entry = val; \ 655cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (av[i].a_type == BL##NN (AT_PHDR)) \ 656cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng phdr = val; \ 657cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (av[i].a_type == BL##NN (AT_PHNUM)) \ 658cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng phnum = val; \ 659cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (av[i].a_type == BL##NN (AT_PHENT)) \ 660cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng phent = val; \ 661cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else if (av[i].a_type == BL##NN (AT_PAGESZ)) \ 662cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { \ 663cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (val > 1 \ 664cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng && (dwfl->segment_align == 0 \ 665cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || val < dwfl->segment_align)) \ 666cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng dwfl->segment_align = val; \ 667cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } \ 668cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } \ 669cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } \ 670cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while (0) 671cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 672cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (elfclass == ELFCLASS32) 673cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 674cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (elfdata == ELFDATA2MSB) 675cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng AUXV_SCAN (32, BE); 676cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 677cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng AUXV_SCAN (32, LE); 678cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 679cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 680cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 681cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (elfdata == ELFDATA2MSB) 682cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng AUXV_SCAN (64, BE); 683cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 684cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng AUXV_SCAN (64, LE); 685cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 686cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 687cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* If we found the phdr dimensions, search phdrs for PT_DYNAMIC. */ 688cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Addr dyn_vaddr = 0; 689cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng GElf_Xword dyn_filesz = 0; 690cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (phdr != 0 && phnum != 0) 691cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 692cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Dwfl_Module *phdr_mod; 693cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int phdr_segndx = INTUSE(dwfl_addrsegment) (dwfl, phdr, &phdr_mod); 694cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data in = 695cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 696cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .d_type = ELF_T_PHDR, 697cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .d_version = EV_CURRENT, 698cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .d_size = phnum * phent, 699cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .d_buf = NULL 700cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng }; 701cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((*memory_callback) (dwfl, phdr_segndx, &in.d_buf, &in.d_size, 702cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng phdr, phnum * phent, memory_callback_arg)) 703cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 704cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng union 705cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 706cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf32_Phdr p32; 707cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf64_Phdr p64; 708cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng char data[phnum * phent]; 709cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } buf; 710cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data out = 711cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 712cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .d_type = ELF_T_PHDR, 713cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .d_version = EV_CURRENT, 714cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .d_size = phnum * phent, 715cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .d_buf = &buf 716cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng }; 717cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng in.d_size = out.d_size; 718cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (likely ((elfclass == ELFCLASS32 719cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ? elf32_xlatetom : elf64_xlatetom) 720cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (&out, &in, elfdata) != NULL)) 721cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 722cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* We are looking for PT_DYNAMIC. */ 723cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const union 724cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 725cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf32_Phdr p32[phnum]; 726cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf64_Phdr p64[phnum]; 727cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } *u = (void *) &buf; 728cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (elfclass == ELFCLASS32) 729cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 730cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t i = 0; i < phnum; ++i) 731cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (u->p32[i].p_type == PT_DYNAMIC) 732cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 733cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng dyn_vaddr = u->p32[i].p_vaddr; 734cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng dyn_filesz = u->p32[i].p_filesz; 735cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 736cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 737cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 738cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 739cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 740cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t i = 0; i < phnum; ++i) 741cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (u->p64[i].p_type == PT_DYNAMIC) 742cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 743cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng dyn_vaddr = u->p64[i].p_vaddr; 744cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng dyn_filesz = u->p64[i].p_filesz; 745cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 746cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 747cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 748cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 749cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 750cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (*memory_callback) (dwfl, -1, &in.d_buf, &in.d_size, 0, 0, 751cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng memory_callback_arg); 752cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 753cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 754cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* We could not read the executable's phdrs from the 755cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng memory image. If we have a presupplied executable, 756cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng we can still use the AT_PHDR and AT_ENTRY values to 757cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng verify it, and to adjust its bias if it's a PIE. 758cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 759cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng If there was an ET_EXEC module presupplied that contains 760cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng the AT_PHDR address, then we only consider that one. 761cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng We'll either accept it if its phdr location and e_entry 762cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng make sense or reject it if they don't. If there is no 763cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng presupplied ET_EXEC, then look for a presupplied module, 764cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng which might be a PIE (ET_DYN) that needs its bias adjusted. */ 765cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng r_debug_vaddr = ((phdr_mod == NULL 766cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || phdr_mod->main.elf == NULL 767cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng || phdr_mod->e_type != ET_EXEC) 768cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ? find_executable (dwfl, phdr, entry, 769cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng &elfclass, &elfdata, 770cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng memory_callback, 771cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng memory_callback_arg) 772cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng : consider_executable (phdr_mod, phdr, entry, 773cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng &elfclass, &elfdata, 774cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng memory_callback, 775cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng memory_callback_arg)); 776cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 777cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 778cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* If we found PT_DYNAMIC, search it for DT_DEBUG. */ 779cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (dyn_filesz != 0) 780cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 781cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data in = 782cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 783cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .d_type = ELF_T_DYN, 784cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .d_version = EV_CURRENT, 785cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .d_size = dyn_filesz, 786cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .d_buf = NULL 787cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng }; 788cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int dyn_segndx = dwfl_addrsegment (dwfl, dyn_vaddr, NULL); 789cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if ((*memory_callback) (dwfl, dyn_segndx, &in.d_buf, &in.d_size, 790cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng dyn_vaddr, dyn_filesz, memory_callback_arg)) 791cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 792cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng union 793cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 794cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf32_Dyn d32; 795cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf64_Dyn d64; 796cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng char data[dyn_filesz]; 797cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } buf; 798cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf_Data out = 799cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 800cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .d_type = ELF_T_DYN, 801cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .d_version = EV_CURRENT, 802cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .d_size = dyn_filesz, 803cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .d_buf = &buf 804cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng }; 805cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng in.d_size = out.d_size; 806cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (likely ((elfclass == ELFCLASS32 807cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ? elf32_xlatetom : elf64_xlatetom) 808cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (&out, &in, elfdata) != NULL)) 809cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 810cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* We are looking for PT_DYNAMIC. */ 811cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng const union 812cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 813cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf32_Dyn d32[dyn_filesz / sizeof (Elf32_Dyn)]; 814cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Elf64_Dyn d64[dyn_filesz / sizeof (Elf64_Dyn)]; 815cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } *u = (void *) &buf; 816cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (elfclass == ELFCLASS32) 817cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 818cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t n = dyn_filesz / sizeof (Elf32_Dyn); 819cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t i = 0; i < n; ++i) 820cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (u->d32[i].d_tag == DT_DEBUG) 821cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 822cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng r_debug_vaddr = u->d32[i].d_un.d_val; 823cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 824cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 825cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 826cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 827cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 828cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng size_t n = dyn_filesz / sizeof (Elf64_Dyn); 829cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for (size_t i = 0; i < n; ++i) 830cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (u->d64[i].d_tag == DT_DEBUG) 831cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 832cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng r_debug_vaddr = u->d64[i].d_un.d_val; 833cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 834cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 835cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 836cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 837cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 838cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (*memory_callback) (dwfl, -1, &in.d_buf, &in.d_size, 0, 0, 839cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng memory_callback_arg); 840cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 841cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 842cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 843cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng else 844cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* We have to look for a presupplied executable file to determine 845cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng the vaddr of its dynamic section and DT_DEBUG therein. */ 846cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng r_debug_vaddr = find_executable (dwfl, 0, 0, &elfclass, &elfdata, 847cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng memory_callback, memory_callback_arg); 848cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 849cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (r_debug_vaddr == 0) 850cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 851cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 852cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* For following pointers from struct link_map, we will use an 853cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng integrated memory access callback that can consult module text 854cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng elided from the core file. This is necessary when the l_name 855cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng pointer for the dynamic linker's own entry is a pointer into the 856cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng executable's .interp section. */ 857cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct integrated_memory_callback mcb = 858cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 859cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .memory_callback = memory_callback, 860cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng .memory_callback_arg = memory_callback_arg 861cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng }; 862cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 863cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Now we can follow the dynamic linker's library list. */ 864cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return report_r_debug (elfclass, elfdata, dwfl, r_debug_vaddr, 865cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng &integrated_memory_callback, &mcb); 866cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 867cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben ChengINTDEF (dwfl_link_map_report) 868