1b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Find debugging and symbol information for a module in libdwfl. 2903924f0541ae61edddee994437549f1db343047Mark Wielaard Copyright (C) 2005-2012, 2014, 2015 Red Hat, Inc. 3de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard This file is part of elfutils. 4b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 5de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard This file is free software; you can redistribute it and/or modify 6de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard it under the terms of either 7b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 8de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard * the GNU Lesser General Public License as published by the Free 9de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard Software Foundation; either version 3 of the License, or (at 10de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard your option) any later version 11de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard 12de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard or 13de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard 14de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard * the GNU General Public License as published by the Free 15de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard Software Foundation; either version 2 of the License, or (at 16de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard your option) any later version 17de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard 18de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard or both in parallel, as here. 19de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard 20de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard elfutils is distributed in the hope that it will be useful, but 21361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper WITHOUT ANY WARRANTY; without even the implied warranty of 22361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper General Public License for more details. 24361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper 25de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard You should have received copies of the GNU General Public License and 26de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard the GNU Lesser General Public License along with this program. If 27de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard not, see <http://www.gnu.org/licenses/>. */ 28b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 29b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include "libdwflP.h" 30920f03dcd3a6dd46b3d88c45be8dbfa0adc780ddFlorian Weimer#include <inttypes.h> 31b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <fcntl.h> 32b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <string.h> 33d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath#include <unistd.h> 34b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include "../libdw/libdwP.h" /* DWARF_E_* values are here. */ 355083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard#include "../libelf/libelfP.h" 36b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 37b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic inline Dwfl_Error 38df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaardopen_elf_file (Elf **elf, int *fd, char **name) 39b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{ 40df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard if (*elf == NULL) 41b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper { 42e07da4f30d2fabc6e2d4a4bfcc05e02091c99f0aRoland McGrath /* CBFAIL uses errno if it's set, so clear it first in case we don't 43e07da4f30d2fabc6e2d4a4bfcc05e02091c99f0aRoland McGrath set it with an open failure below. */ 44e07da4f30d2fabc6e2d4a4bfcc05e02091c99f0aRoland McGrath errno = 0; 45e07da4f30d2fabc6e2d4a4bfcc05e02091c99f0aRoland McGrath 46059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath /* If there was a pre-primed file name left that the callback left 47059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath behind, try to open that file name. */ 48df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard if (*fd < 0 && *name != NULL) 493425454a10d307fae891fb667cf7969e945cde79Josh Stone *fd = TEMP_FAILURE_RETRY (open (*name, O_RDONLY)); 50059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath 51df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard if (*fd < 0) 52b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper return CBFAIL; 53b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 54df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard return __libdw_open_file (fd, elf, true, false); 55b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper } 56df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard else if (unlikely (elf_kind (*elf) != ELF_K_ELF)) 57122f388b300a489b54829d80f5e5fffb3f743ab7Roland McGrath { 58df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard elf_end (*elf); 59df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard *elf = NULL; 60df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard close (*fd); 61df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard *fd = -1; 62122f388b300a489b54829d80f5e5fffb3f743ab7Roland McGrath return DWFL_E_BADELF; 63122f388b300a489b54829d80f5e5fffb3f743ab7Roland McGrath } 64122f388b300a489b54829d80f5e5fffb3f743ab7Roland McGrath 65df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard /* Elf file already open and looks fine. */ 66df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard return DWFL_E_NOERROR; 67df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard} 68df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard 69df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard/* Open libelf FILE->fd and compute the load base of ELF as loaded in MOD. 70df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard When we return success, FILE->elf and FILE->vaddr are set up. */ 71df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaardstatic inline Dwfl_Error 72df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaardopen_elf (Dwfl_Module *mod, struct dwfl_file *file) 73df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard{ 74df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard Dwfl_Error error = open_elf_file (&file->elf, &file->fd, &file->name); 75df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard if (error != DWFL_E_NOERROR) 76df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard return error; 77df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard 78b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (file->elf, &ehdr_mem); 79b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper if (ehdr == NULL) 806258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper { 816258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper elf_error: 82ed431ddb74331f24add8c6d932ebed129c4385d8Roland McGrath elf_end (file->elf); 83ed431ddb74331f24add8c6d932ebed129c4385d8Roland McGrath file->elf = NULL; 846258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper close (file->fd); 856258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper file->fd = -1; 86122f388b300a489b54829d80f5e5fffb3f743ab7Roland McGrath return DWFL_E (LIBELF, elf_errno ()); 876258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper } 88b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 8965cefbd0793c0f9e90a326d7bebf0a47c93294adJosh Stone if (ehdr->e_type != ET_REL) 90f95760aff004850544f83626404c134d6a07c630Roland McGrath { 912c7d0ddfb8a08b8c450d0d3a5e297ec5d624661dRoland McGrath /* In any non-ET_REL file, we compute the "synchronization address". 922c7d0ddfb8a08b8c450d0d3a5e297ec5d624661dRoland McGrath 932c7d0ddfb8a08b8c450d0d3a5e297ec5d624661dRoland McGrath We start with the address at the end of the first PT_LOAD 942c7d0ddfb8a08b8c450d0d3a5e297ec5d624661dRoland McGrath segment. When prelink converts REL to RELA in an ET_DYN 952c7d0ddfb8a08b8c450d0d3a5e297ec5d624661dRoland McGrath file, it expands the space between the beginning of the 962c7d0ddfb8a08b8c450d0d3a5e297ec5d624661dRoland McGrath segment and the actual code/data addresses. Since that 972c7d0ddfb8a08b8c450d0d3a5e297ec5d624661dRoland McGrath change wasn't made in the debug file, the distance from 982c7d0ddfb8a08b8c450d0d3a5e297ec5d624661dRoland McGrath p_vaddr to an address of interest (in an st_value or DWARF 992c7d0ddfb8a08b8c450d0d3a5e297ec5d624661dRoland McGrath data) now differs between the main and debug files. The 1002c7d0ddfb8a08b8c450d0d3a5e297ec5d624661dRoland McGrath distance from address_sync to an address of interest remains 1012c7d0ddfb8a08b8c450d0d3a5e297ec5d624661dRoland McGrath consistent. 1022c7d0ddfb8a08b8c450d0d3a5e297ec5d624661dRoland McGrath 1032c7d0ddfb8a08b8c450d0d3a5e297ec5d624661dRoland McGrath If there are no section headers at all (full stripping), then 1042c7d0ddfb8a08b8c450d0d3a5e297ec5d624661dRoland McGrath the end of the first segment is a valid synchronization address. 1052c7d0ddfb8a08b8c450d0d3a5e297ec5d624661dRoland McGrath This cannot happen in a prelinked file, since prelink itself 1062c7d0ddfb8a08b8c450d0d3a5e297ec5d624661dRoland McGrath relies on section headers for prelinking and for undoing it. 1072c7d0ddfb8a08b8c450d0d3a5e297ec5d624661dRoland McGrath (If you do full stripping on a prelinked file, then you get what 1082c7d0ddfb8a08b8c450d0d3a5e297ec5d624661dRoland McGrath you deserve--you can neither undo the prelinking, nor expect to 1092c7d0ddfb8a08b8c450d0d3a5e297ec5d624661dRoland McGrath line it up with a debug file separated before prelinking.) 1102c7d0ddfb8a08b8c450d0d3a5e297ec5d624661dRoland McGrath 1112c7d0ddfb8a08b8c450d0d3a5e297ec5d624661dRoland McGrath However, when prelink processes an ET_EXEC file, it can do 1122c7d0ddfb8a08b8c450d0d3a5e297ec5d624661dRoland McGrath something different. There it juggles the "special" sections 1132c7d0ddfb8a08b8c450d0d3a5e297ec5d624661dRoland McGrath (SHT_DYNSYM et al) to make space for the additional prelink 1142c7d0ddfb8a08b8c450d0d3a5e297ec5d624661dRoland McGrath special sections. Sometimes it will do this by moving a special 1155ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath section like .dynstr after the real program sections in the first 1165ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath PT_LOAD segment--i.e. to the end. That changes the end address of 1175ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath the segment, so it no longer lines up correctly and is not a valid 1185ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath synchronization address to use. Because of this, we need to apply 1195ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath a different prelink-savvy means to discover the synchronization 1205ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath address when there is a separate debug file and a prelinked main 1215ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath file. That is done in find_debuginfo, below. */ 1222c7d0ddfb8a08b8c450d0d3a5e297ec5d624661dRoland McGrath 123f95760aff004850544f83626404c134d6a07c630Roland McGrath size_t phnum; 124f95760aff004850544f83626404c134d6a07c630Roland McGrath if (unlikely (elf_getphdrnum (file->elf, &phnum) != 0)) 125f95760aff004850544f83626404c134d6a07c630Roland McGrath goto elf_error; 126f95760aff004850544f83626404c134d6a07c630Roland McGrath 1271743d7f010bead5e869d097e23ce840583913381Roland McGrath file->vaddr = file->address_sync = 0; 128f95760aff004850544f83626404c134d6a07c630Roland McGrath for (size_t i = 0; i < phnum; ++i) 129f95760aff004850544f83626404c134d6a07c630Roland McGrath { 130f95760aff004850544f83626404c134d6a07c630Roland McGrath GElf_Phdr ph_mem; 131f95760aff004850544f83626404c134d6a07c630Roland McGrath GElf_Phdr *ph = gelf_getphdr (file->elf, i, &ph_mem); 1321743d7f010bead5e869d097e23ce840583913381Roland McGrath if (unlikely (ph == NULL)) 133f95760aff004850544f83626404c134d6a07c630Roland McGrath goto elf_error; 1345ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath if (ph->p_type == PT_LOAD) 135f95760aff004850544f83626404c134d6a07c630Roland McGrath { 1365ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath file->vaddr = ph->p_vaddr & -ph->p_align; 1375ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath file->address_sync = ph->p_vaddr + ph->p_memsz; 1382c7d0ddfb8a08b8c450d0d3a5e297ec5d624661dRoland McGrath break; 139f95760aff004850544f83626404c134d6a07c630Roland McGrath } 140f95760aff004850544f83626404c134d6a07c630Roland McGrath } 141f95760aff004850544f83626404c134d6a07c630Roland McGrath } 142b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 14365cefbd0793c0f9e90a326d7bebf0a47c93294adJosh Stone /* We only want to set the module e_type explictly once, derived from 14465cefbd0793c0f9e90a326d7bebf0a47c93294adJosh Stone the main ELF file. (It might be changed for the kernel, because 14565cefbd0793c0f9e90a326d7bebf0a47c93294adJosh Stone that is special - see below.) open_elf is always called first for 14665cefbd0793c0f9e90a326d7bebf0a47c93294adJosh Stone the main ELF file, because both find_dw and find_symtab call 14765cefbd0793c0f9e90a326d7bebf0a47c93294adJosh Stone __libdwfl_getelf first to open the main file. So don't let debug 14865cefbd0793c0f9e90a326d7bebf0a47c93294adJosh Stone or aux files override the module e_type. The kernel heuristic 14965cefbd0793c0f9e90a326d7bebf0a47c93294adJosh Stone below could otherwise trigger for non-kernel/non-main files, since 15065cefbd0793c0f9e90a326d7bebf0a47c93294adJosh Stone their phdrs might not match the actual load addresses. */ 15165cefbd0793c0f9e90a326d7bebf0a47c93294adJosh Stone if (file == &mod->main) 15265cefbd0793c0f9e90a326d7bebf0a47c93294adJosh Stone { 15365cefbd0793c0f9e90a326d7bebf0a47c93294adJosh Stone mod->e_type = ehdr->e_type; 1546258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper 15565cefbd0793c0f9e90a326d7bebf0a47c93294adJosh Stone /* Relocatable Linux kernels are ET_EXEC but act like ET_DYN. */ 15665cefbd0793c0f9e90a326d7bebf0a47c93294adJosh Stone if (mod->e_type == ET_EXEC && file->vaddr != mod->low_addr) 15765cefbd0793c0f9e90a326d7bebf0a47c93294adJosh Stone mod->e_type = ET_DYN; 15865cefbd0793c0f9e90a326d7bebf0a47c93294adJosh Stone } 15965cefbd0793c0f9e90a326d7bebf0a47c93294adJosh Stone else 16065cefbd0793c0f9e90a326d7bebf0a47c93294adJosh Stone assert (mod->main.elf != NULL); 1616258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper 162b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper return DWFL_E_NOERROR; 163b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper} 164b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 1653fdcdcbcb424c45645aff1200adfb34450caf0b2Jan Kratochvil/* We have an authoritative build ID for this module MOD, so don't use 1663fdcdcbcb424c45645aff1200adfb34450caf0b2Jan Kratochvil a file by name that doesn't match that ID. */ 1673fdcdcbcb424c45645aff1200adfb34450caf0b2Jan Kratochvilstatic void 1683fdcdcbcb424c45645aff1200adfb34450caf0b2Jan Kratochvilmod_verify_build_id (Dwfl_Module *mod) 1693fdcdcbcb424c45645aff1200adfb34450caf0b2Jan Kratochvil{ 1703fdcdcbcb424c45645aff1200adfb34450caf0b2Jan Kratochvil assert (mod->build_id_len > 0); 1713fdcdcbcb424c45645aff1200adfb34450caf0b2Jan Kratochvil 1723fdcdcbcb424c45645aff1200adfb34450caf0b2Jan Kratochvil switch (__builtin_expect (__libdwfl_find_build_id (mod, false, 1733fdcdcbcb424c45645aff1200adfb34450caf0b2Jan Kratochvil mod->main.elf), 2)) 1743fdcdcbcb424c45645aff1200adfb34450caf0b2Jan Kratochvil { 1753fdcdcbcb424c45645aff1200adfb34450caf0b2Jan Kratochvil case 2: 1763fdcdcbcb424c45645aff1200adfb34450caf0b2Jan Kratochvil /* Build ID matches as it should. */ 1773fdcdcbcb424c45645aff1200adfb34450caf0b2Jan Kratochvil return; 1783fdcdcbcb424c45645aff1200adfb34450caf0b2Jan Kratochvil 1793fdcdcbcb424c45645aff1200adfb34450caf0b2Jan Kratochvil case -1: /* ELF error. */ 1803fdcdcbcb424c45645aff1200adfb34450caf0b2Jan Kratochvil mod->elferr = INTUSE(dwfl_errno) (); 1813fdcdcbcb424c45645aff1200adfb34450caf0b2Jan Kratochvil break; 1823fdcdcbcb424c45645aff1200adfb34450caf0b2Jan Kratochvil 1833fdcdcbcb424c45645aff1200adfb34450caf0b2Jan Kratochvil case 0: /* File has no build ID note. */ 1843fdcdcbcb424c45645aff1200adfb34450caf0b2Jan Kratochvil case 1: /* FIle has a build ID that does not match. */ 1853fdcdcbcb424c45645aff1200adfb34450caf0b2Jan Kratochvil mod->elferr = DWFL_E_WRONG_ID_ELF; 1863fdcdcbcb424c45645aff1200adfb34450caf0b2Jan Kratochvil break; 1873fdcdcbcb424c45645aff1200adfb34450caf0b2Jan Kratochvil 1883fdcdcbcb424c45645aff1200adfb34450caf0b2Jan Kratochvil default: 1893fdcdcbcb424c45645aff1200adfb34450caf0b2Jan Kratochvil abort (); 1903fdcdcbcb424c45645aff1200adfb34450caf0b2Jan Kratochvil } 1913fdcdcbcb424c45645aff1200adfb34450caf0b2Jan Kratochvil 1923fdcdcbcb424c45645aff1200adfb34450caf0b2Jan Kratochvil /* We get here when it was the right ELF file. Clear it out. */ 1933fdcdcbcb424c45645aff1200adfb34450caf0b2Jan Kratochvil elf_end (mod->main.elf); 1943fdcdcbcb424c45645aff1200adfb34450caf0b2Jan Kratochvil mod->main.elf = NULL; 1953fdcdcbcb424c45645aff1200adfb34450caf0b2Jan Kratochvil if (mod->main.fd >= 0) 1963fdcdcbcb424c45645aff1200adfb34450caf0b2Jan Kratochvil { 1973fdcdcbcb424c45645aff1200adfb34450caf0b2Jan Kratochvil close (mod->main.fd); 1983fdcdcbcb424c45645aff1200adfb34450caf0b2Jan Kratochvil mod->main.fd = -1; 1993fdcdcbcb424c45645aff1200adfb34450caf0b2Jan Kratochvil } 2003fdcdcbcb424c45645aff1200adfb34450caf0b2Jan Kratochvil} 2013fdcdcbcb424c45645aff1200adfb34450caf0b2Jan Kratochvil 202b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Find the main ELF file for this module and open libelf on it. 203b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper When we return success, MOD->main.elf and MOD->main.bias are set up. */ 204a605a3c8f354895f4cca56aca8f8aa468b506fdfRoland McGrathvoid 2051036157150672569a79d30c9b59cc7623e3e8e60Roland McGrathinternal_function 206a605a3c8f354895f4cca56aca8f8aa468b506fdfRoland McGrath__libdwfl_getelf (Dwfl_Module *mod) 207b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{ 208b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper if (mod->main.elf != NULL /* Already done. */ 209b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper || mod->elferr != DWFL_E_NOERROR) /* Cached failure. */ 210b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper return; 211b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 212b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper mod->main.fd = (*mod->dwfl->callbacks->find_elf) (MODCB_ARGS (mod), 213b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper &mod->main.name, 214b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper &mod->main.elf); 215ed431ddb74331f24add8c6d932ebed129c4385d8Roland McGrath const bool fallback = mod->main.elf == NULL && mod->main.fd < 0; 216b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper mod->elferr = open_elf (mod, &mod->main); 217ed431ddb74331f24add8c6d932ebed129c4385d8Roland McGrath if (mod->elferr != DWFL_E_NOERROR) 218ed431ddb74331f24add8c6d932ebed129c4385d8Roland McGrath return; 21959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath 220ed431ddb74331f24add8c6d932ebed129c4385d8Roland McGrath if (!mod->main.valid) 22159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath { 22259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath /* Clear any explicitly reported build ID, just in case it was wrong. 22359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath We'll fetch it from the file when asked. */ 224bfc01703fe30815b450526ebcfbb37ec9f5fe9c7Roland McGrath free (mod->build_id_bits); 225bfc01703fe30815b450526ebcfbb37ec9f5fe9c7Roland McGrath mod->build_id_bits = NULL; 22659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath mod->build_id_len = 0; 22759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath } 228ed431ddb74331f24add8c6d932ebed129c4385d8Roland McGrath else if (fallback) 2293fdcdcbcb424c45645aff1200adfb34450caf0b2Jan Kratochvil mod_verify_build_id (mod); 2301743d7f010bead5e869d097e23ce840583913381Roland McGrath 2311743d7f010bead5e869d097e23ce840583913381Roland McGrath mod->main_bias = mod->e_type == ET_REL ? 0 : mod->low_addr - mod->main.vaddr; 232b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper} 233b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 2344e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsiehstatic inline void 2354e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsiehconsider_shdr (GElf_Addr interp, 2364e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh GElf_Word sh_type, 2374e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh GElf_Xword sh_flags, 2384e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh GElf_Addr sh_addr, 2394e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh GElf_Xword sh_size, 2404e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh GElf_Addr *phighest) 2414e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh{ 2424e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh if ((sh_flags & SHF_ALLOC) 2434e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh && ((sh_type == SHT_PROGBITS && sh_addr != interp) 2444e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh || sh_type == SHT_NOBITS)) 2454e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh { 2464e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh const GElf_Addr sh_end = sh_addr + sh_size; 2474e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh if (sh_end > *phighest) 2484e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh *phighest = sh_end; 2494e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh } 2504e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh} 2514e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh 2525ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath/* If the main file might have been prelinked, then we need to 2535ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath discover the correct synchronization address between the main and 2545ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath debug files. Because of prelink's section juggling, we cannot rely 2555ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath on the address_sync computed from PT_LOAD segments (see open_elf). 2565ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath 2575ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath We will attempt to discover a synchronization address based on the 2585ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath section headers instead. But finding a section address that is 2595ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath safe to use requires identifying which sections are SHT_PROGBITS. 2605ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath We can do that in the main file, but in the debug file all the 2615ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath allocated sections have been transformed into SHT_NOBITS so we have 2625ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath lost the means to match them up correctly. 2635ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath 2645ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath The only method left to us is to decode the .gnu.prelink_undo 2655ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath section in the prelinked main file. This shows what the sections 2665ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath looked like before prelink juggled them--when they still had a 2675ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath direct correspondence to the debug file. */ 2685ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrathstatic Dwfl_Error 2695083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaardfind_prelink_address_sync (Dwfl_Module *mod, struct dwfl_file *file) 2705ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath{ 2715ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath /* The magic section is only identified by name. */ 2725ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath size_t shstrndx; 2735ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath if (elf_getshdrstrndx (mod->main.elf, &shstrndx) < 0) 2745ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath return DWFL_E_LIBELF; 2755ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath 2765ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath Elf_Scn *scn = NULL; 2775ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath while ((scn = elf_nextscn (mod->main.elf, scn)) != NULL) 2785ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath { 2795ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath GElf_Shdr shdr_mem; 2805ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 2815ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath if (unlikely (shdr == NULL)) 2825ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath return DWFL_E_LIBELF; 2835ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath if (shdr->sh_type == SHT_PROGBITS 2845ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath && !(shdr->sh_flags & SHF_ALLOC) 2855ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath && shdr->sh_name != 0) 2865ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath { 2875ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath const char *secname = elf_strptr (mod->main.elf, shstrndx, 2885ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath shdr->sh_name); 2895ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath if (unlikely (secname == NULL)) 2905ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath return DWFL_E_LIBELF; 2915ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath if (!strcmp (secname, ".gnu.prelink_undo")) 2925ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath break; 2935ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath } 2945ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath } 2955ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath 2965ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath if (scn == NULL) 2975ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath /* There was no .gnu.prelink_undo section. */ 2985ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath return DWFL_E_NOERROR; 2995ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath 3005ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath Elf_Data *undodata = elf_rawdata (scn, NULL); 3015ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath if (unlikely (undodata == NULL)) 3025ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath return DWFL_E_LIBELF; 3035ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath 3045ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath /* Decode the section. It consists of the original ehdr, phdrs, 3055ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath and shdrs (but omits section 0). */ 3065ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath 3075ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath union 3085ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath { 3095ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath Elf32_Ehdr e32; 3105ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath Elf64_Ehdr e64; 3115ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath } ehdr; 3125ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath Elf_Data dst = 3135ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath { 3145ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath .d_buf = &ehdr, 3155ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath .d_size = sizeof ehdr, 3165ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath .d_type = ELF_T_EHDR, 3175ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath .d_version = EV_CURRENT 3185ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath }; 3195ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath Elf_Data src = *undodata; 3205ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath src.d_size = gelf_fsize (mod->main.elf, ELF_T_EHDR, 1, EV_CURRENT); 3215ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath src.d_type = ELF_T_EHDR; 3225ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath if (unlikely (gelf_xlatetom (mod->main.elf, &dst, &src, 3235ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath elf_getident (mod->main.elf, NULL)[EI_DATA]) 3245ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath == NULL)) 3255ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath return DWFL_E_LIBELF; 3265ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath 3275ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath size_t shentsize = gelf_fsize (mod->main.elf, ELF_T_SHDR, 1, EV_CURRENT); 3285ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath size_t phentsize = gelf_fsize (mod->main.elf, ELF_T_PHDR, 1, EV_CURRENT); 3295ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath 3305ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath uint_fast16_t phnum; 3315ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath uint_fast16_t shnum; 3325ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath if (ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32) 3335ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath { 3345ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath if (ehdr.e32.e_shentsize != shentsize 3355ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath || ehdr.e32.e_phentsize != phentsize) 3365ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath return DWFL_E_BAD_PRELINK; 3375ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath phnum = ehdr.e32.e_phnum; 3385ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath shnum = ehdr.e32.e_shnum; 3395ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath } 3405ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath else 3415ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath { 3425ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath if (ehdr.e64.e_shentsize != shentsize 3435ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath || ehdr.e64.e_phentsize != phentsize) 3445ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath return DWFL_E_BAD_PRELINK; 3455ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath phnum = ehdr.e64.e_phnum; 3465ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath shnum = ehdr.e64.e_shnum; 3475ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath } 3485ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath 3495ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath /* Since prelink does not store the zeroth section header in the undo 3505ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath section, it cannot support SHN_XINDEX encoding. */ 3515ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath if (unlikely (shnum >= SHN_LORESERVE) 3525ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath || unlikely (undodata->d_size != (src.d_size 3535ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath + phnum * phentsize 3545ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath + (shnum - 1) * shentsize))) 3555ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath return DWFL_E_BAD_PRELINK; 3565ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath 3575ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath /* We look at the allocated SHT_PROGBITS (or SHT_NOBITS) sections. (Most 3585ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath every file will have some SHT_PROGBITS sections, but it's possible to 3595ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath have one with nothing but .bss, i.e. SHT_NOBITS.) The special sections 3605ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath that can be moved around have different sh_type values--except for 3615ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath .interp, the section that became the PT_INTERP segment. So we exclude 3625ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath the SHT_PROGBITS section whose address matches the PT_INTERP p_vaddr. 3635ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath For this reason, we must examine the phdrs first to find PT_INTERP. */ 3645ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath 3650ef402035d71bf68c818e7b070d4c6d9744f951dRoland McGrath GElf_Addr main_interp = 0; 3660ef402035d71bf68c818e7b070d4c6d9744f951dRoland McGrath { 3670ef402035d71bf68c818e7b070d4c6d9744f951dRoland McGrath size_t main_phnum; 3680ef402035d71bf68c818e7b070d4c6d9744f951dRoland McGrath if (unlikely (elf_getphdrnum (mod->main.elf, &main_phnum))) 3690ef402035d71bf68c818e7b070d4c6d9744f951dRoland McGrath return DWFL_E_LIBELF; 3700ef402035d71bf68c818e7b070d4c6d9744f951dRoland McGrath for (size_t i = 0; i < main_phnum; ++i) 3710ef402035d71bf68c818e7b070d4c6d9744f951dRoland McGrath { 3720ef402035d71bf68c818e7b070d4c6d9744f951dRoland McGrath GElf_Phdr phdr; 3730ef402035d71bf68c818e7b070d4c6d9744f951dRoland McGrath if (unlikely (gelf_getphdr (mod->main.elf, i, &phdr) == NULL)) 3740ef402035d71bf68c818e7b070d4c6d9744f951dRoland McGrath return DWFL_E_LIBELF; 3750ef402035d71bf68c818e7b070d4c6d9744f951dRoland McGrath if (phdr.p_type == PT_INTERP) 3760ef402035d71bf68c818e7b070d4c6d9744f951dRoland McGrath { 3770ef402035d71bf68c818e7b070d4c6d9744f951dRoland McGrath main_interp = phdr.p_vaddr; 3780ef402035d71bf68c818e7b070d4c6d9744f951dRoland McGrath break; 3790ef402035d71bf68c818e7b070d4c6d9744f951dRoland McGrath } 3800ef402035d71bf68c818e7b070d4c6d9744f951dRoland McGrath } 3810ef402035d71bf68c818e7b070d4c6d9744f951dRoland McGrath } 3820ef402035d71bf68c818e7b070d4c6d9744f951dRoland McGrath 3835ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath src.d_buf += src.d_size; 3845ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath src.d_type = ELF_T_PHDR; 3855ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath src.d_size = phnum * phentsize; 3865ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath 3870ef402035d71bf68c818e7b070d4c6d9744f951dRoland McGrath GElf_Addr undo_interp = 0; 38886ed7f7f53179d7a893329e6b9851dbb75aba405Mark Wielaard bool class32 = ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32; 3895ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath { 39086ed7f7f53179d7a893329e6b9851dbb75aba405Mark Wielaard size_t phdr_size = class32 ? sizeof (Elf32_Phdr) : sizeof (Elf64_Phdr); 39186ed7f7f53179d7a893329e6b9851dbb75aba405Mark Wielaard if (unlikely (phnum > SIZE_MAX / phdr_size)) 3927eff36d5daa6ebca5e6399638a7643af105ae5b0Chih-Hung Hsieh return DWFL_E_NOMEM; 39386ed7f7f53179d7a893329e6b9851dbb75aba405Mark Wielaard const size_t phdrs_bytes = phnum * phdr_size; 3947eff36d5daa6ebca5e6399638a7643af105ae5b0Chih-Hung Hsieh void *phdrs = malloc (phdrs_bytes); 395903924f0541ae61edddee994437549f1db343047Mark Wielaard if (unlikely (phdrs == NULL)) 396903924f0541ae61edddee994437549f1db343047Mark Wielaard return DWFL_E_NOMEM; 397903924f0541ae61edddee994437549f1db343047Mark Wielaard dst.d_buf = phdrs; 3987eff36d5daa6ebca5e6399638a7643af105ae5b0Chih-Hung Hsieh dst.d_size = phdrs_bytes; 3995ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath if (unlikely (gelf_xlatetom (mod->main.elf, &dst, &src, 4005ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath ehdr.e32.e_ident[EI_DATA]) == NULL)) 401903924f0541ae61edddee994437549f1db343047Mark Wielaard { 402903924f0541ae61edddee994437549f1db343047Mark Wielaard free (phdrs); 403903924f0541ae61edddee994437549f1db343047Mark Wielaard return DWFL_E_LIBELF; 404903924f0541ae61edddee994437549f1db343047Mark Wielaard } 40586ed7f7f53179d7a893329e6b9851dbb75aba405Mark Wielaard if (class32) 4065ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath { 40786ed7f7f53179d7a893329e6b9851dbb75aba405Mark Wielaard Elf32_Phdr (*p32)[phnum] = phdrs; 4085ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath for (uint_fast16_t i = 0; i < phnum; ++i) 4097eff36d5daa6ebca5e6399638a7643af105ae5b0Chih-Hung Hsieh if ((*p32)[i].p_type == PT_INTERP) 4105ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath { 4117eff36d5daa6ebca5e6399638a7643af105ae5b0Chih-Hung Hsieh undo_interp = (*p32)[i].p_vaddr; 4125ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath break; 4135ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath } 4145ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath } 4155ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath else 4165ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath { 41786ed7f7f53179d7a893329e6b9851dbb75aba405Mark Wielaard Elf64_Phdr (*p64)[phnum] = phdrs; 4185ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath for (uint_fast16_t i = 0; i < phnum; ++i) 4197eff36d5daa6ebca5e6399638a7643af105ae5b0Chih-Hung Hsieh if ((*p64)[i].p_type == PT_INTERP) 4205ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath { 4217eff36d5daa6ebca5e6399638a7643af105ae5b0Chih-Hung Hsieh undo_interp = (*p64)[i].p_vaddr; 4225ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath break; 4235ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath } 4245ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath } 425903924f0541ae61edddee994437549f1db343047Mark Wielaard free (phdrs); 4265ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath } 4275ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath 4280ef402035d71bf68c818e7b070d4c6d9744f951dRoland McGrath if (unlikely ((main_interp == 0) != (undo_interp == 0))) 4290ef402035d71bf68c818e7b070d4c6d9744f951dRoland McGrath return DWFL_E_BAD_PRELINK; 4300ef402035d71bf68c818e7b070d4c6d9744f951dRoland McGrath 4315ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath src.d_buf += src.d_size; 4325ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath src.d_type = ELF_T_SHDR; 4335ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath src.d_size = gelf_fsize (mod->main.elf, ELF_T_SHDR, shnum - 1, EV_CURRENT); 4345ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath 43586ed7f7f53179d7a893329e6b9851dbb75aba405Mark Wielaard size_t shdr_size = class32 ? sizeof (Elf32_Shdr) : sizeof (Elf64_Shdr); 43686ed7f7f53179d7a893329e6b9851dbb75aba405Mark Wielaard if (unlikely (shnum - 1 > SIZE_MAX / shdr_size)) 4377eff36d5daa6ebca5e6399638a7643af105ae5b0Chih-Hung Hsieh return DWFL_E_NOMEM; 43886ed7f7f53179d7a893329e6b9851dbb75aba405Mark Wielaard const size_t shdrs_bytes = (shnum - 1) * shdr_size; 4397eff36d5daa6ebca5e6399638a7643af105ae5b0Chih-Hung Hsieh void *shdrs = malloc (shdrs_bytes); 440903924f0541ae61edddee994437549f1db343047Mark Wielaard if (unlikely (shdrs == NULL)) 441903924f0541ae61edddee994437549f1db343047Mark Wielaard return DWFL_E_NOMEM; 442903924f0541ae61edddee994437549f1db343047Mark Wielaard dst.d_buf = shdrs; 4437eff36d5daa6ebca5e6399638a7643af105ae5b0Chih-Hung Hsieh dst.d_size = shdrs_bytes; 4445ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath if (unlikely (gelf_xlatetom (mod->main.elf, &dst, &src, 4455ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath ehdr.e32.e_ident[EI_DATA]) == NULL)) 446903924f0541ae61edddee994437549f1db343047Mark Wielaard { 447903924f0541ae61edddee994437549f1db343047Mark Wielaard free (shdrs); 448903924f0541ae61edddee994437549f1db343047Mark Wielaard return DWFL_E_LIBELF; 449903924f0541ae61edddee994437549f1db343047Mark Wielaard } 4505ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath 4515ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath /* Now we can look at the original section headers of the main file 4525ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath before it was prelinked. First we'll apply our method to the main 4535ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath file sections as they are after prelinking, to calculate the 4545ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath synchronization address of the main file. Then we'll apply that 4555ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath same method to the saved section headers, to calculate the matching 4563a44c9a73887acf982ea2752fa16ce66e42105b7Roland McGrath synchronization address of the debug file. 4573a44c9a73887acf982ea2752fa16ce66e42105b7Roland McGrath 4583a44c9a73887acf982ea2752fa16ce66e42105b7Roland McGrath The method is to consider SHF_ALLOC sections that are either 4593a44c9a73887acf982ea2752fa16ce66e42105b7Roland McGrath SHT_PROGBITS or SHT_NOBITS, excluding the section whose sh_addr 4603a44c9a73887acf982ea2752fa16ce66e42105b7Roland McGrath matches the PT_INTERP p_vaddr. The special sections that can be 4613a44c9a73887acf982ea2752fa16ce66e42105b7Roland McGrath moved by prelink have other types, except for .interp (which 4623a44c9a73887acf982ea2752fa16ce66e42105b7Roland McGrath becomes PT_INTERP). The "real" sections cannot move as such, but 4633a44c9a73887acf982ea2752fa16ce66e42105b7Roland McGrath .bss can be split into .dynbss and .bss, with the total memory 4643a44c9a73887acf982ea2752fa16ce66e42105b7Roland McGrath image remaining the same but being spread across the two sections. 4653a44c9a73887acf982ea2752fa16ce66e42105b7Roland McGrath So we consider the highest section end, which still matches up. */ 4665ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath 4675ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath GElf_Addr highest; 4685ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath 4695ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath highest = 0; 4705ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath scn = NULL; 4715ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath while ((scn = elf_nextscn (mod->main.elf, scn)) != NULL) 4725ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath { 4735ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath GElf_Shdr sh_mem; 4745ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath GElf_Shdr *sh = gelf_getshdr (scn, &sh_mem); 4755ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath if (unlikely (sh == NULL)) 476903924f0541ae61edddee994437549f1db343047Mark Wielaard { 477903924f0541ae61edddee994437549f1db343047Mark Wielaard free (shdrs); 478903924f0541ae61edddee994437549f1db343047Mark Wielaard return DWFL_E_LIBELF; 479903924f0541ae61edddee994437549f1db343047Mark Wielaard } 4803a44c9a73887acf982ea2752fa16ce66e42105b7Roland McGrath consider_shdr (main_interp, sh->sh_type, sh->sh_flags, 4814e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh sh->sh_addr, sh->sh_size, &highest); 4825ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath } 4835ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath if (highest > mod->main.vaddr) 4845ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath { 4855ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath mod->main.address_sync = highest; 4865ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath 4875ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath highest = 0; 48886ed7f7f53179d7a893329e6b9851dbb75aba405Mark Wielaard if (class32) 48986ed7f7f53179d7a893329e6b9851dbb75aba405Mark Wielaard { 49086ed7f7f53179d7a893329e6b9851dbb75aba405Mark Wielaard Elf32_Shdr (*s32)[shnum - 1] = shdrs; 49186ed7f7f53179d7a893329e6b9851dbb75aba405Mark Wielaard for (size_t i = 0; i < shnum - 1; ++i) 49286ed7f7f53179d7a893329e6b9851dbb75aba405Mark Wielaard consider_shdr (undo_interp, (*s32)[i].sh_type, 49386ed7f7f53179d7a893329e6b9851dbb75aba405Mark Wielaard (*s32)[i].sh_flags, (*s32)[i].sh_addr, 4944e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh (*s32)[i].sh_size, &highest); 49586ed7f7f53179d7a893329e6b9851dbb75aba405Mark Wielaard } 4965ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath else 49786ed7f7f53179d7a893329e6b9851dbb75aba405Mark Wielaard { 49886ed7f7f53179d7a893329e6b9851dbb75aba405Mark Wielaard Elf64_Shdr (*s64)[shnum - 1] = shdrs; 49986ed7f7f53179d7a893329e6b9851dbb75aba405Mark Wielaard for (size_t i = 0; i < shnum - 1; ++i) 50086ed7f7f53179d7a893329e6b9851dbb75aba405Mark Wielaard consider_shdr (undo_interp, (*s64)[i].sh_type, 50186ed7f7f53179d7a893329e6b9851dbb75aba405Mark Wielaard (*s64)[i].sh_flags, (*s64)[i].sh_addr, 5024e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh (*s64)[i].sh_size, &highest); 50386ed7f7f53179d7a893329e6b9851dbb75aba405Mark Wielaard } 5045ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath 5055083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard if (highest > file->vaddr) 5065083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard file->address_sync = highest; 5075ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath else 508903924f0541ae61edddee994437549f1db343047Mark Wielaard { 509903924f0541ae61edddee994437549f1db343047Mark Wielaard free (shdrs); 510903924f0541ae61edddee994437549f1db343047Mark Wielaard return DWFL_E_BAD_PRELINK; 511903924f0541ae61edddee994437549f1db343047Mark Wielaard } 5125ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath } 5135ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath 514903924f0541ae61edddee994437549f1db343047Mark Wielaard free (shdrs); 515903924f0541ae61edddee994437549f1db343047Mark Wielaard 5165ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath return DWFL_E_NOERROR; 5175ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath} 518c07fbb3ff74a8c7b4916ff8155060a35f4b08aaaUlrich Drepper 519c07fbb3ff74a8c7b4916ff8155060a35f4b08aaaUlrich Drepper/* Find the separate debuginfo file for this module and open libelf on it. 520c07fbb3ff74a8c7b4916ff8155060a35f4b08aaaUlrich Drepper When we return success, MOD->debug is set up. */ 521c07fbb3ff74a8c7b4916ff8155060a35f4b08aaaUlrich Drepperstatic Dwfl_Error 522c07fbb3ff74a8c7b4916ff8155060a35f4b08aaaUlrich Drepperfind_debuginfo (Dwfl_Module *mod) 523c07fbb3ff74a8c7b4916ff8155060a35f4b08aaaUlrich Drepper{ 524c07fbb3ff74a8c7b4916ff8155060a35f4b08aaaUlrich Drepper if (mod->debug.elf != NULL) 525c07fbb3ff74a8c7b4916ff8155060a35f4b08aaaUlrich Drepper return DWFL_E_NOERROR; 526c07fbb3ff74a8c7b4916ff8155060a35f4b08aaaUlrich Drepper 527c07fbb3ff74a8c7b4916ff8155060a35f4b08aaaUlrich Drepper GElf_Word debuglink_crc = 0; 5289380297e130e6ccc829c8d56d701fb539b27bb0fMark Wielaard const char *debuglink_file; 5299380297e130e6ccc829c8d56d701fb539b27bb0fMark Wielaard debuglink_file = INTUSE(dwelf_elf_gnu_debuglink) (mod->main.elf, 5309380297e130e6ccc829c8d56d701fb539b27bb0fMark Wielaard &debuglink_crc); 531b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 532b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper mod->debug.fd = (*mod->dwfl->callbacks->find_debuginfo) (MODCB_ARGS (mod), 533b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper mod->main.name, 534b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper debuglink_file, 535b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper debuglink_crc, 536b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper &mod->debug.name); 5375ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath Dwfl_Error result = open_elf (mod, &mod->debug); 5385ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath if (result == DWFL_E_NOERROR && mod->debug.address_sync != 0) 5395083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard result = find_prelink_address_sync (mod, &mod->debug); 5405ad466d544bdca479626d07d65288b2cc2638b4aRoland McGrath return result; 541b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper} 542b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 543df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard/* Try to find the alternative debug link for the given DWARF and set 544df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard it if found. Only called when mod->dw is already setup but still 545df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard might need an alternative (dwz multi) debug file. filename is either 546df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard the main or debug name from which the Dwarf was created. */ 547df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaardstatic void 548df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaardfind_debug_altlink (Dwfl_Module *mod, const char *filename) 549df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard{ 550df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard assert (mod->dw != NULL); 551df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard 552df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard const char *altname; 553df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard const void *build_id; 554df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard ssize_t build_id_len = INTUSE(dwelf_dwarf_gnu_debugaltlink) (mod->dw, 555df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard &altname, 556df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard &build_id); 557df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard 558df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard if (build_id_len > 0) 559df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard { 560df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard /* We could store altfile in the module, but don't really need it. */ 561df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard char *altfile = NULL; 562df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard mod->alt_fd = (*mod->dwfl->callbacks->find_debuginfo) (MODCB_ARGS (mod), 563df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard filename, 564df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard altname, 565df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard 0, 566df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard &altfile); 567df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard 568df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard /* The (internal) callbacks might just set mod->alt_elf directly 569df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard because they open the Elf anyway for sanity checking. 570df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard Otherwise open either the given file name or use the fd 571df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard returned. */ 572df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard Dwfl_Error error = open_elf_file (&mod->alt_elf, &mod->alt_fd, 573df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard &altfile); 574df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard if (error == DWFL_E_NOERROR) 575df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard { 576df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard mod->alt = INTUSE(dwarf_begin_elf) (mod->alt_elf, 577df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard DWARF_C_READ, NULL); 578df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard if (mod->alt == NULL) 579df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard { 580df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard elf_end (mod->alt_elf); 581df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard mod->alt_elf = NULL; 582df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard close (mod->alt_fd); 583df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard mod->alt_fd = -1; 584df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard } 585df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard else 586df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard dwarf_setalt (mod->dw, mod->alt); 587df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard } 588df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard 589df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard free (altfile); /* See above, we don't really need it. */ 590df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard } 591df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard} 592b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 593b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper/* Try to find a symbol table in FILE. 594b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper Returns DWFL_E_NOERROR if a proper one is found. 595b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper Returns DWFL_E_NO_SYMTAB if not, but still sets results for SHT_DYNSYM. */ 596b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic Dwfl_Error 597b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperload_symtab (struct dwfl_file *file, struct dwfl_file **symfile, 598b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper Elf_Scn **symscn, Elf_Scn **xndxscn, 599ef431cd30b8a1a6b12a8783516fc95da88a9a636Mark Wielaard size_t *syments, int *first_global, GElf_Word *strshndx) 600b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{ 601d11f9cbecac4a5ac3848a68597028d1924f3ff6bRoland McGrath bool symtab = false; 602b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper Elf_Scn *scn = NULL; 603b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper while ((scn = elf_nextscn (file->elf, scn)) != NULL) 604b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper { 605b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper GElf_Shdr shdr_mem, *shdr = gelf_getshdr (scn, &shdr_mem); 606b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper if (shdr != NULL) 607b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper switch (shdr->sh_type) 608b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper { 609b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper case SHT_SYMTAB: 610df5ad1681cfc5c27df853299c5d8bfea5448bccaMark Wielaard if (shdr->sh_entsize == 0) 611df5ad1681cfc5c27df853299c5d8bfea5448bccaMark Wielaard break; 612d11f9cbecac4a5ac3848a68597028d1924f3ff6bRoland McGrath symtab = true; 613b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *symscn = scn; 614b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *symfile = file; 615b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *strshndx = shdr->sh_link; 616b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *syments = shdr->sh_size / shdr->sh_entsize; 617ef431cd30b8a1a6b12a8783516fc95da88a9a636Mark Wielaard *first_global = shdr->sh_info; 618b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper if (*xndxscn != NULL) 619b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper return DWFL_E_NOERROR; 620b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper break; 621b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 622b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper case SHT_DYNSYM: 623d11f9cbecac4a5ac3848a68597028d1924f3ff6bRoland McGrath if (symtab) 624d11f9cbecac4a5ac3848a68597028d1924f3ff6bRoland McGrath break; 625b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper /* Use this if need be, but keep looking for SHT_SYMTAB. */ 626df5ad1681cfc5c27df853299c5d8bfea5448bccaMark Wielaard if (shdr->sh_entsize == 0) 627df5ad1681cfc5c27df853299c5d8bfea5448bccaMark Wielaard break; 628b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *symscn = scn; 629b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *symfile = file; 630b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *strshndx = shdr->sh_link; 631b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *syments = shdr->sh_size / shdr->sh_entsize; 6325083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard *first_global = shdr->sh_info; 633b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper break; 634b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 635b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper case SHT_SYMTAB_SHNDX: 636b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *xndxscn = scn; 637d11f9cbecac4a5ac3848a68597028d1924f3ff6bRoland McGrath if (symtab) 638b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper return DWFL_E_NOERROR; 639b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper break; 640b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 641b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper default: 642b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper break; 643b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper } 644b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper } 645b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper 646d11f9cbecac4a5ac3848a68597028d1924f3ff6bRoland McGrath if (symtab) 647b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper /* We found one, though no SHT_SYMTAB_SHNDX to go with it. */ 648b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper return DWFL_E_NOERROR; 649b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper 650b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper /* We found no SHT_SYMTAB, so any SHT_SYMTAB_SHNDX was bogus. 651b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper We might have found an SHT_DYNSYM and set *SYMSCN et al though. */ 652b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper *xndxscn = NULL; 653b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper return DWFL_E_NO_SYMTAB; 654b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper} 655b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 65659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath 65759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath/* Translate addresses into file offsets. 65859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath OFFS[*] start out zero and remain zero if unresolved. */ 65959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathstatic void 6600375056af003d7676fb852e09782a985f3a52b1aJan Kratochvilfind_offsets (Elf *elf, GElf_Addr main_bias, size_t phnum, size_t n, 66159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath GElf_Addr addrs[n], GElf_Off offs[n]) 66259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath{ 66359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath size_t unsolved = n; 664f95760aff004850544f83626404c134d6a07c630Roland McGrath for (size_t i = 0; i < phnum; ++i) 66559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath { 66659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath GElf_Phdr phdr_mem; 66759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem); 66859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath if (phdr != NULL && phdr->p_type == PT_LOAD && phdr->p_memsz > 0) 66959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath for (size_t j = 0; j < n; ++j) 67059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath if (offs[j] == 0 6710375056af003d7676fb852e09782a985f3a52b1aJan Kratochvil && addrs[j] >= phdr->p_vaddr + main_bias 6720375056af003d7676fb852e09782a985f3a52b1aJan Kratochvil && addrs[j] - (phdr->p_vaddr + main_bias) < phdr->p_filesz) 67359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath { 6740375056af003d7676fb852e09782a985f3a52b1aJan Kratochvil offs[j] = addrs[j] - (phdr->p_vaddr + main_bias) + phdr->p_offset; 67559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath if (--unsolved == 0) 67659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath break; 67759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath } 67859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath } 67959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath} 68059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath 6814e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh/* Various addresses we might want to pull from the dynamic segment. */ 6824e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsiehenum 6834e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh{ 6844e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh i_symtab, 6854e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh i_strtab, 6864e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh i_hash, 6874e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh i_gnu_hash, 6884e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh i_max 6894e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh}; 6904e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh 6914e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh/* Translate pointers into file offsets. ADJUST is either zero 6924e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh in case the dynamic segment wasn't adjusted or mod->main_bias. 6934e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh Will set mod->symfile if the translated offsets can be used as 6944e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh symbol table. */ 6954e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsiehstatic void 6964e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsiehtranslate_offs (GElf_Addr adjust, 6974e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh Dwfl_Module *mod, size_t phnum, 6984e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh GElf_Addr addrs[i_max], GElf_Xword strsz, 6994e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh GElf_Ehdr *ehdr) 7004e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh{ 7014e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh GElf_Off offs[i_max] = { 0, }; 7024e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh find_offsets (mod->main.elf, adjust, phnum, i_max, addrs, offs); 7034e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh 7044e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh /* Figure out the size of the symbol table. */ 7054e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh if (offs[i_hash] != 0) 7064e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh { 7074e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh /* In the original format, .hash says the size of .dynsym. */ 7084e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh 7094e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh size_t entsz = SH_ENTSIZE_HASH (ehdr); 7104e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh Elf_Data *data = elf_getdata_rawchunk (mod->main.elf, 7114e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh offs[i_hash] + entsz, entsz, 7124e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh (entsz == 4 7134e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh ? ELF_T_WORD : ELF_T_XWORD)); 7144e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh if (data != NULL) 7154e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh mod->syments = (entsz == 4 7164e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh ? *(const GElf_Word *) data->d_buf 7174e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh : *(const GElf_Xword *) data->d_buf); 7184e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh } 7194e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh if (offs[i_gnu_hash] != 0 && mod->syments == 0) 7204e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh { 7214e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh /* In the new format, we can derive it with some work. */ 7224e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh 7234e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh const struct 7244e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh { 7254e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh Elf32_Word nbuckets; 7264e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh Elf32_Word symndx; 7274e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh Elf32_Word maskwords; 7284e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh Elf32_Word shift2; 7294e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh } *header; 7304e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh 7314e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh Elf_Data *data = elf_getdata_rawchunk (mod->main.elf, offs[i_gnu_hash], 7324e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh sizeof *header, ELF_T_WORD); 7334e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh if (data != NULL) 7344e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh { 7354e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh header = data->d_buf; 7364e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh Elf32_Word nbuckets = header->nbuckets; 7374e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh Elf32_Word symndx = header->symndx; 7384e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh GElf_Off buckets_at = (offs[i_gnu_hash] + sizeof *header 7394e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh + (gelf_getclass (mod->main.elf) 7404e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh * sizeof (Elf32_Word) 7414e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh * header->maskwords)); 7424e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh 7434e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh // elf_getdata_rawchunk takes a size_t, make sure it 7444e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh // doesn't overflow. 7454e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh#if SIZE_MAX <= UINT32_MAX 7464e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh if (nbuckets > SIZE_MAX / sizeof (Elf32_Word)) 7474e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh data = NULL; 7484e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh else 7494e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh#endif 7504e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh data = elf_getdata_rawchunk (mod->main.elf, buckets_at, 7514e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh nbuckets * sizeof (Elf32_Word), 7524e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh ELF_T_WORD); 7534e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh if (data != NULL && symndx < nbuckets) 7544e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh { 7554e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh const Elf32_Word *const buckets = data->d_buf; 7564e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh Elf32_Word maxndx = symndx; 7574e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh for (Elf32_Word bucket = 0; bucket < nbuckets; ++bucket) 7584e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh if (buckets[bucket] > maxndx) 7594e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh maxndx = buckets[bucket]; 7604e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh 7614e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh GElf_Off hasharr_at = (buckets_at 7624e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh + nbuckets * sizeof (Elf32_Word)); 7634e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh hasharr_at += (maxndx - symndx) * sizeof (Elf32_Word); 7644e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh do 7654e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh { 7664e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh data = elf_getdata_rawchunk (mod->main.elf, 7674e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh hasharr_at, 7684e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh sizeof (Elf32_Word), 7694e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh ELF_T_WORD); 7704e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh if (data != NULL 7714e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh && (*(const Elf32_Word *) data->d_buf & 1u)) 7724e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh { 7734e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh mod->syments = maxndx + 1; 7744e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh break; 7754e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh } 7764e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh ++maxndx; 7774e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh hasharr_at += sizeof (Elf32_Word); 7784e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh } 7794e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh while (data != NULL); 7804e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh } 7814e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh } 7824e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh } 7834e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh if (offs[i_strtab] > offs[i_symtab] && mod->syments == 0) 7844e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh mod->syments = ((offs[i_strtab] - offs[i_symtab]) 7854e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh / gelf_fsize (mod->main.elf, 7864e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh ELF_T_SYM, 1, EV_CURRENT)); 7874e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh 7884e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh if (mod->syments > 0) 7894e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh { 7904e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh mod->symdata = elf_getdata_rawchunk (mod->main.elf, 7914e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh offs[i_symtab], 7924e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh gelf_fsize (mod->main.elf, 7934e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh ELF_T_SYM, 7944e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh mod->syments, 7954e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh EV_CURRENT), 7964e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh ELF_T_SYM); 7974e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh if (mod->symdata != NULL) 7984e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh { 7994e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh mod->symstrdata = elf_getdata_rawchunk (mod->main.elf, 8004e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh offs[i_strtab], 8014e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh strsz, 8024e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh ELF_T_BYTE); 8034e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh if (mod->symstrdata == NULL) 8044e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh mod->symdata = NULL; 8054e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh } 8064e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh if (mod->symdata == NULL) 8074e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh mod->symerr = DWFL_E (LIBELF, elf_errno ()); 8084e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh else 8094e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh { 8104e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh mod->symfile = &mod->main; 8114e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh mod->symerr = DWFL_E_NOERROR; 8124e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh } 8134e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh } 8144e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh} 8154e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh 81659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath/* Try to find a dynamic symbol table via phdrs. */ 81759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathstatic void 81859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrathfind_dynsym (Dwfl_Module *mod) 81959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath{ 82059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath GElf_Ehdr ehdr_mem; 82159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath GElf_Ehdr *ehdr = gelf_getehdr (mod->main.elf, &ehdr_mem); 82259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath 823f95760aff004850544f83626404c134d6a07c630Roland McGrath size_t phnum; 824f95760aff004850544f83626404c134d6a07c630Roland McGrath if (unlikely (elf_getphdrnum (mod->main.elf, &phnum) != 0)) 825f95760aff004850544f83626404c134d6a07c630Roland McGrath return; 826f95760aff004850544f83626404c134d6a07c630Roland McGrath 827f95760aff004850544f83626404c134d6a07c630Roland McGrath for (size_t i = 0; i < phnum; ++i) 82859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath { 82959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath GElf_Phdr phdr_mem; 83059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath GElf_Phdr *phdr = gelf_getphdr (mod->main.elf, i, &phdr_mem); 83159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath if (phdr == NULL) 83259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath break; 83359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath 83459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath if (phdr->p_type == PT_DYNAMIC) 83559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath { 83659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath /* Examine the dynamic section for the pointers we need. */ 83759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath 83859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath Elf_Data *data = elf_getdata_rawchunk (mod->main.elf, 83959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath phdr->p_offset, phdr->p_filesz, 84059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath ELF_T_DYN); 84159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath if (data == NULL) 84259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath continue; 84359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath 84459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath GElf_Addr addrs[i_max] = { 0, }; 84559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath GElf_Xword strsz = 0; 84659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath size_t n = data->d_size / gelf_fsize (mod->main.elf, 84759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath ELF_T_DYN, 1, EV_CURRENT); 84859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath for (size_t j = 0; j < n; ++j) 84959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath { 85059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath GElf_Dyn dyn_mem; 85159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath GElf_Dyn *dyn = gelf_getdyn (data, j, &dyn_mem); 85259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath if (dyn != NULL) 85359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath switch (dyn->d_tag) 85459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath { 85559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath case DT_SYMTAB: 85659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath addrs[i_symtab] = dyn->d_un.d_ptr; 85759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath continue; 85859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath 85959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath case DT_HASH: 86059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath addrs[i_hash] = dyn->d_un.d_ptr; 86159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath continue; 86259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath 86359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath case DT_GNU_HASH: 86459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath addrs[i_gnu_hash] = dyn->d_un.d_ptr; 86559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath continue; 86659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath 86759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath case DT_STRTAB: 86859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath addrs[i_strtab] = dyn->d_un.d_ptr; 86959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath continue; 87059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath 87159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath case DT_STRSZ: 87259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath strsz = dyn->d_un.d_val; 87359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath continue; 87459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath 87559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath default: 87659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath continue; 87759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath 87859ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath case DT_NULL: 87959ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath break; 88059ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath } 88159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath break; 88259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath } 88359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath 8845691f86722e9c24169622e64e8e8f5e6a24ad3b0Mark Wielaard /* First try unadjusted, like ELF files from disk, vdso. 8855691f86722e9c24169622e64e8e8f5e6a24ad3b0Mark Wielaard Then try for already adjusted dynamic section, like ELF 8865691f86722e9c24169622e64e8e8f5e6a24ad3b0Mark Wielaard from remote memory. */ 8874e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh translate_offs (0, mod, phnum, addrs, strsz, ehdr); 8885691f86722e9c24169622e64e8e8f5e6a24ad3b0Mark Wielaard if (mod->symfile == NULL) 8894e249605bb605b9bcc7e86e48d91247abd82ff5eChih-Hung Hsieh translate_offs (mod->main_bias, mod, phnum, addrs, strsz, ehdr); 8905691f86722e9c24169622e64e8e8f5e6a24ad3b0Mark Wielaard 8915691f86722e9c24169622e64e8e8f5e6a24ad3b0Mark Wielaard return; 89259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath } 89359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath } 89459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath} 89559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath 896db35c87a85aa651b8ea3ed19689c53cefc28e313Josh Stone 897db35c87a85aa651b8ea3ed19689c53cefc28e313Josh Stone#if USE_LZMA 898db35c87a85aa651b8ea3ed19689c53cefc28e313Josh Stone/* Try to find the offset between the main file and .gnu_debugdata. */ 899db35c87a85aa651b8ea3ed19689c53cefc28e313Josh Stonestatic bool 900db35c87a85aa651b8ea3ed19689c53cefc28e313Josh Stonefind_aux_address_sync (Dwfl_Module *mod) 901db35c87a85aa651b8ea3ed19689c53cefc28e313Josh Stone{ 902db35c87a85aa651b8ea3ed19689c53cefc28e313Josh Stone /* Don't trust the phdrs in the minisymtab elf file to be setup correctly. 903db35c87a85aa651b8ea3ed19689c53cefc28e313Josh Stone The address_sync is equal to the main file it is embedded in at first. */ 904db35c87a85aa651b8ea3ed19689c53cefc28e313Josh Stone mod->aux_sym.address_sync = mod->main.address_sync; 905db35c87a85aa651b8ea3ed19689c53cefc28e313Josh Stone 906db35c87a85aa651b8ea3ed19689c53cefc28e313Josh Stone /* Adjust address_sync for the difference in entry addresses, attempting to 907db35c87a85aa651b8ea3ed19689c53cefc28e313Josh Stone account for ELF relocation changes after aux was split. */ 908db35c87a85aa651b8ea3ed19689c53cefc28e313Josh Stone GElf_Ehdr ehdr_main, ehdr_aux; 909db35c87a85aa651b8ea3ed19689c53cefc28e313Josh Stone if (unlikely (gelf_getehdr (mod->main.elf, &ehdr_main) == NULL) 910db35c87a85aa651b8ea3ed19689c53cefc28e313Josh Stone || unlikely (gelf_getehdr (mod->aux_sym.elf, &ehdr_aux) == NULL)) 911db35c87a85aa651b8ea3ed19689c53cefc28e313Josh Stone return false; 912db35c87a85aa651b8ea3ed19689c53cefc28e313Josh Stone mod->aux_sym.address_sync += ehdr_aux.e_entry - ehdr_main.e_entry; 913db35c87a85aa651b8ea3ed19689c53cefc28e313Josh Stone 914db35c87a85aa651b8ea3ed19689c53cefc28e313Josh Stone /* The shdrs are setup OK to make find_prelink_address_sync () do the right 915db35c87a85aa651b8ea3ed19689c53cefc28e313Josh Stone thing, which is possibly more reliable, but it needs .gnu.prelink_undo. */ 916db35c87a85aa651b8ea3ed19689c53cefc28e313Josh Stone if (mod->aux_sym.address_sync != 0) 917db35c87a85aa651b8ea3ed19689c53cefc28e313Josh Stone return find_prelink_address_sync (mod, &mod->aux_sym) == DWFL_E_NOERROR; 918db35c87a85aa651b8ea3ed19689c53cefc28e313Josh Stone 919db35c87a85aa651b8ea3ed19689c53cefc28e313Josh Stone return true; 920db35c87a85aa651b8ea3ed19689c53cefc28e313Josh Stone} 921db35c87a85aa651b8ea3ed19689c53cefc28e313Josh Stone#endif 922db35c87a85aa651b8ea3ed19689c53cefc28e313Josh Stone 9235083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard/* Try to find the auxiliary symbol table embedded in the main elf file 9245083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard section .gnu_debugdata. Only matters if the symbol information comes 9255083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard from the main file dynsym. No harm done if not found. */ 9265083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaardstatic void 9275083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaardfind_aux_sym (Dwfl_Module *mod __attribute__ ((unused)), 9285083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard Elf_Scn **aux_symscn __attribute__ ((unused)), 9295083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard Elf_Scn **aux_xndxscn __attribute__ ((unused)), 9305083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard GElf_Word *aux_strshndx __attribute__ ((unused))) 9315083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard{ 9325083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard /* Since a .gnu_debugdata section is compressed using lzma don't do 9335083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard anything unless we have support for that. */ 9345083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard#if USE_LZMA 9355083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard Elf *elf = mod->main.elf; 9365083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard 9375083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard size_t shstrndx; 9385083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard if (elf_getshdrstrndx (elf, &shstrndx) < 0) 9395083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard return; 9405083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard 9415083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard Elf_Scn *scn = NULL; 9425083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard while ((scn = elf_nextscn (elf, scn)) != NULL) 9435083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard { 9445083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard GElf_Shdr shdr_mem; 9455083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem); 9465083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard if (shdr == NULL) 9475083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard return; 9485083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard 9495083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard const char *name = elf_strptr (elf, shstrndx, shdr->sh_name); 9505083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard if (name == NULL) 9515083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard return; 9525083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard 9535083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard if (!strcmp (name, ".gnu_debugdata")) 9545083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard break; 9555083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard } 9565083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard 9575083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard if (scn == NULL) 9585083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard return; 9595083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard 9605083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard /* Found the .gnu_debugdata section. Uncompress the lzma image and 9615083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard turn it into an ELF image. */ 9625083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard Elf_Data *rawdata = elf_rawdata (scn, NULL); 9635083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard if (rawdata == NULL) 9645083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard return; 9655083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard 9665083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard Dwfl_Error error; 9675083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard void *buffer = NULL; 9685083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard size_t size = 0; 9695083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard error = __libdw_unlzma (-1, 0, rawdata->d_buf, rawdata->d_size, 9705083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard &buffer, &size); 9715083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard if (error == DWFL_E_NOERROR) 9725083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard { 9735083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard if (unlikely (size == 0)) 9745083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard free (buffer); 9755083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard else 9765083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard { 9775083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard mod->aux_sym.elf = elf_memory (buffer, size); 9785083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard if (mod->aux_sym.elf == NULL) 9795083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard free (buffer); 9805083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard else 9815083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard { 9825083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard mod->aux_sym.fd = -1; 9835083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard mod->aux_sym.elf->flags |= ELF_F_MALLOCED; 9845083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard if (open_elf (mod, &mod->aux_sym) != DWFL_E_NOERROR) 9855083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard return; 986db35c87a85aa651b8ea3ed19689c53cefc28e313Josh Stone if (! find_aux_address_sync (mod)) 9875083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard { 988db35c87a85aa651b8ea3ed19689c53cefc28e313Josh Stone elf_end (mod->aux_sym.elf); 989db35c87a85aa651b8ea3ed19689c53cefc28e313Josh Stone mod->aux_sym.elf = NULL; 990db35c87a85aa651b8ea3ed19689c53cefc28e313Josh Stone return; 9915083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard } 9925083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard 9935083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard /* So far, so good. Get minisymtab table data and cache it. */ 9945083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard bool minisymtab = false; 9955083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard scn = NULL; 9965083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard while ((scn = elf_nextscn (mod->aux_sym.elf, scn)) != NULL) 9975083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard { 9985083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard GElf_Shdr shdr_mem, *shdr = gelf_getshdr (scn, &shdr_mem); 9995083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard if (shdr != NULL) 10005083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard switch (shdr->sh_type) 10015083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard { 10025083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard case SHT_SYMTAB: 10035083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard minisymtab = true; 10045083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard *aux_symscn = scn; 10055083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard *aux_strshndx = shdr->sh_link; 1006697bdca1d7d70ebdcae90759dd885258400e1951Mark Wielaard mod->aux_syments = shdr->sh_size / shdr->sh_entsize; 10075083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard mod->aux_first_global = shdr->sh_info; 10085083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard if (*aux_xndxscn != NULL) 10095083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard return; 10105083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard break; 10115083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard 10125083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard case SHT_SYMTAB_SHNDX: 10135083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard *aux_xndxscn = scn; 10145083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard if (minisymtab) 10155083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard return; 10165083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard break; 10175083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard 10185083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard default: 10195083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard break; 10205083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard } 10215083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard } 10225083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard 10235083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard if (minisymtab) 10245083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard /* We found one, though no SHT_SYMTAB_SHNDX to go with it. */ 10255083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard return; 10265083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard 10275083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard /* We found no SHT_SYMTAB, so everything else is bogus. */ 10285083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard *aux_xndxscn = NULL; 10295083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard *aux_strshndx = 0; 10305083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard mod->aux_syments = 0; 10315083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard elf_end (mod->aux_sym.elf); 10325083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard mod->aux_sym.elf = NULL; 10335083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard return; 10345083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard } 10355083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard } 10365083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard } 10375083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard else 10385083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard free (buffer); 10395083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard#endif 10405083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard} 10415083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard 1042b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Try to find a symbol table in either MOD->main.elf or MOD->debug.elf. */ 1043b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void 1044b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperfind_symtab (Dwfl_Module *mod) 1045b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{ 1046697bdca1d7d70ebdcae90759dd885258400e1951Mark Wielaard if (mod->symdata != NULL || mod->aux_symdata != NULL /* Already done. */ 1047b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper || mod->symerr != DWFL_E_NOERROR) /* Cached previous failure. */ 1048b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper return; 1049b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 1050a605a3c8f354895f4cca56aca8f8aa468b506fdfRoland McGrath __libdwfl_getelf (mod); 1051b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper mod->symerr = mod->elferr; 1052b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper if (mod->symerr != DWFL_E_NOERROR) 1053b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper return; 1054b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 1055b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper /* First see if the main ELF file has the debugging information. */ 1056b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper Elf_Scn *symscn = NULL, *xndxscn = NULL; 10575083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard Elf_Scn *aux_symscn = NULL, *aux_xndxscn = NULL; 10585083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard GElf_Word strshndx, aux_strshndx = 0; 1059b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper mod->symerr = load_symtab (&mod->main, &mod->symfile, &symscn, 1060ef431cd30b8a1a6b12a8783516fc95da88a9a636Mark Wielaard &xndxscn, &mod->syments, &mod->first_global, 1061ef431cd30b8a1a6b12a8783516fc95da88a9a636Mark Wielaard &strshndx); 1062b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper switch (mod->symerr) 1063b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper { 1064b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper default: 1065b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper return; 1066b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 1067b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper case DWFL_E_NOERROR: 1068b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper break; 1069b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 1070b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper case DWFL_E_NO_SYMTAB: 1071b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper /* Now we have to look for a separate debuginfo file. */ 1072b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper mod->symerr = find_debuginfo (mod); 1073b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper switch (mod->symerr) 1074b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper { 1075b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper default: 1076b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper return; 1077b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 1078b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper case DWFL_E_NOERROR: 1079b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper mod->symerr = load_symtab (&mod->debug, &mod->symfile, &symscn, 1080ef431cd30b8a1a6b12a8783516fc95da88a9a636Mark Wielaard &xndxscn, &mod->syments, 1081ef431cd30b8a1a6b12a8783516fc95da88a9a636Mark Wielaard &mod->first_global, &strshndx); 1082b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper break; 1083b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 1084b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper case DWFL_E_CB: /* The find_debuginfo hook failed. */ 1085b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper mod->symerr = DWFL_E_NO_SYMTAB; 1086b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper break; 1087b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper } 1088b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 1089b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper switch (mod->symerr) 1090b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper { 1091b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper default: 1092b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper return; 1093b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 1094b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper case DWFL_E_NOERROR: 1095b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper break; 1096b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 1097b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper case DWFL_E_NO_SYMTAB: 1098697bdca1d7d70ebdcae90759dd885258400e1951Mark Wielaard /* There might be an auxiliary table. */ 1099697bdca1d7d70ebdcae90759dd885258400e1951Mark Wielaard find_aux_sym (mod, &aux_symscn, &aux_xndxscn, &aux_strshndx); 1100697bdca1d7d70ebdcae90759dd885258400e1951Mark Wielaard 110159ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath if (symscn != NULL) 110259ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath { 110359ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath /* We still have the dynamic symbol table. */ 110459ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath mod->symerr = DWFL_E_NOERROR; 110559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath break; 110659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath } 110759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath 1108697bdca1d7d70ebdcae90759dd885258400e1951Mark Wielaard if (aux_symscn != NULL) 1109697bdca1d7d70ebdcae90759dd885258400e1951Mark Wielaard { 1110697bdca1d7d70ebdcae90759dd885258400e1951Mark Wielaard /* We still have the auxiliary symbol table. */ 1111697bdca1d7d70ebdcae90759dd885258400e1951Mark Wielaard mod->symerr = DWFL_E_NOERROR; 1112697bdca1d7d70ebdcae90759dd885258400e1951Mark Wielaard goto aux_cache; 1113697bdca1d7d70ebdcae90759dd885258400e1951Mark Wielaard } 1114697bdca1d7d70ebdcae90759dd885258400e1951Mark Wielaard 111559ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath /* Last ditch, look for dynamic symbols without section headers. */ 111659ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath find_dynsym (mod); 111759ea7f33f781e6e3f8c9d81d457e5d99eee8f1ceRoland McGrath return; 1118b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper } 1119b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper break; 1120b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper } 1121b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 1122b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper /* This does some sanity checks on the string table section. */ 1123b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper if (elf_strptr (mod->symfile->elf, strshndx, 0) == NULL) 1124b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper { 1125b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper elferr: 112696f7667a2e804465adc3d4cfbb17c022adfa40f0Mark Wielaard mod->symdata = NULL; 112796f7667a2e804465adc3d4cfbb17c022adfa40f0Mark Wielaard mod->syments = 0; 112896f7667a2e804465adc3d4cfbb17c022adfa40f0Mark Wielaard mod->first_global = 0; 1129b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper mod->symerr = DWFL_E (LIBELF, elf_errno ()); 1130544d008acdcd6417c70b1b42be52206a24599102Mark Wielaard goto aux_cleanup; /* This cleans up some more and tries find_dynsym. */ 1131b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper } 1132b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 1133d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard /* Cache the data; MOD->syments and MOD->first_global were set 1134d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard above. If any of the sections is compressed, uncompress it 1135d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard first. Only the string data setion could theoretically be 1136d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard compressed GNU style (as .zdebug_str). Everything else only ELF 1137d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard gabi style (SHF_COMPRESSED). */ 1138d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard 1139d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard Elf_Scn *symstrscn = elf_getscn (mod->symfile->elf, strshndx); 1140d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard if (symstrscn == NULL) 1141d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard goto elferr; 1142d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard 1143d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard GElf_Shdr shdr_mem; 1144d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard GElf_Shdr *shdr = gelf_getshdr (symstrscn, &shdr_mem); 1145d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard if (shdr == NULL) 1146d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard goto elferr; 1147d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard 1148d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard size_t shstrndx; 1149d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard if (elf_getshdrstrndx (mod->symfile->elf, &shstrndx) < 0) 1150d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard goto elferr; 1151d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard 1152d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard const char *sname = elf_strptr (mod->symfile->elf, shstrndx, shdr->sh_name); 1153d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard if (sname == NULL) 1154d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard goto elferr; 1155d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard 1156d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard if (strncmp (sname, ".zdebug", strlen (".zdebug")) == 0) 1157d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard /* Try to uncompress, but it might already have been, an error 1158d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard might just indicate, already uncompressed. */ 1159d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard elf_compress_gnu (symstrscn, 0, 0); 1160b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 1161d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard if ((shdr->sh_flags & SHF_COMPRESSED) != 0) 1162d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard if (elf_compress (symstrscn, 0, 0) < 0) 1163d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard goto elferr; 1164d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard 1165d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard mod->symstrdata = elf_getdata (symstrscn, NULL); 116686b0b13a0814f7283e04ddf766859a47e6b7bbb2Mark Wielaard if (mod->symstrdata == NULL || mod->symstrdata->d_buf == NULL) 1167b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper goto elferr; 1168b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 1169b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper if (xndxscn == NULL) 1170b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper mod->symxndxdata = NULL; 1171b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper else 1172b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper { 1173d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard shdr = gelf_getshdr (xndxscn, &shdr_mem); 1174d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard if (shdr == NULL) 1175d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard goto elferr; 1176d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard 1177d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard if ((shdr->sh_flags & SHF_COMPRESSED) != 0) 1178d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard if (elf_compress (xndxscn, 0, 0) < 0) 1179d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard goto elferr; 1180d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard 11813712b288d1407cf6551d359cdaacb31bbf2b2a75Roland McGrath mod->symxndxdata = elf_getdata (xndxscn, NULL); 118286b0b13a0814f7283e04ddf766859a47e6b7bbb2Mark Wielaard if (mod->symxndxdata == NULL || mod->symxndxdata->d_buf == NULL) 1183b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper goto elferr; 1184b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper } 1185b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 1186d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard shdr = gelf_getshdr (symscn, &shdr_mem); 1187d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard if (shdr == NULL) 1188d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard goto elferr; 1189d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard 1190d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard if ((shdr->sh_flags & SHF_COMPRESSED) != 0) 1191d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard if (elf_compress (symscn, 0, 0) < 0) 1192d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard goto elferr; 1193d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard 11943712b288d1407cf6551d359cdaacb31bbf2b2a75Roland McGrath mod->symdata = elf_getdata (symscn, NULL); 119586b0b13a0814f7283e04ddf766859a47e6b7bbb2Mark Wielaard if (mod->symdata == NULL || mod->symdata->d_buf == NULL) 119686b0b13a0814f7283e04ddf766859a47e6b7bbb2Mark Wielaard goto elferr; 119786b0b13a0814f7283e04ddf766859a47e6b7bbb2Mark Wielaard 119886b0b13a0814f7283e04ddf766859a47e6b7bbb2Mark Wielaard // Sanity check number of symbols. 1199d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard shdr = gelf_getshdr (symscn, &shdr_mem); 1200821e15c6ca716b17b3d3b678cfb17d12ef9bcf25Mark Wielaard if (shdr == NULL || shdr->sh_entsize == 0 1201821e15c6ca716b17b3d3b678cfb17d12ef9bcf25Mark Wielaard || mod->syments > mod->symdata->d_size / shdr->sh_entsize 120286b0b13a0814f7283e04ddf766859a47e6b7bbb2Mark Wielaard || (size_t) mod->first_global > mod->syments) 1203b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper goto elferr; 12045083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard 12055083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard /* Cache any auxiliary symbol info, when it fails, just ignore aux_sym. */ 12065083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard if (aux_symscn != NULL) 12075083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard { 1208697bdca1d7d70ebdcae90759dd885258400e1951Mark Wielaard aux_cache: 12095083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard /* This does some sanity checks on the string table section. */ 12105083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard if (elf_strptr (mod->aux_sym.elf, aux_strshndx, 0) == NULL) 12115083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard { 12125083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard aux_cleanup: 12135083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard mod->aux_syments = 0; 12145083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard elf_end (mod->aux_sym.elf); 12155083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard mod->aux_sym.elf = NULL; 1216544d008acdcd6417c70b1b42be52206a24599102Mark Wielaard /* We thought we had something through shdrs, but it failed... 1217544d008acdcd6417c70b1b42be52206a24599102Mark Wielaard Last ditch, look for dynamic symbols without section headers. */ 1218544d008acdcd6417c70b1b42be52206a24599102Mark Wielaard find_dynsym (mod); 12195083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard return; 12205083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard } 12215083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard 1222d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard Elf_Scn *aux_strscn = elf_getscn (mod->aux_sym.elf, aux_strshndx); 1223d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard if (aux_strscn == NULL) 1224d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard goto elferr; 1225d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard 1226d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard shdr = gelf_getshdr (aux_strscn, &shdr_mem); 1227d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard if (shdr == NULL) 1228d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard goto elferr; 1229d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard 1230d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard size_t aux_shstrndx; 1231d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard if (elf_getshdrstrndx (mod->aux_sym.elf, &aux_shstrndx) < 0) 1232d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard goto elferr; 1233d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard 1234d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard sname = elf_strptr (mod->aux_sym.elf, aux_shstrndx, 1235d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard shdr->sh_name); 1236d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard if (sname == NULL) 1237d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard goto elferr; 1238d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard 1239d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard if (strncmp (sname, ".zdebug", strlen (".zdebug")) == 0) 1240d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard /* Try to uncompress, but it might already have been, an error 1241d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard might just indicate, already uncompressed. */ 1242d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard elf_compress_gnu (aux_strscn, 0, 0); 1243d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard 1244d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard if ((shdr->sh_flags & SHF_COMPRESSED) != 0) 1245d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard if (elf_compress (aux_strscn, 0, 0) < 0) 1246d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard goto elferr; 1247d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard 1248d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard mod->aux_symstrdata = elf_getdata (aux_strscn, NULL); 124986b0b13a0814f7283e04ddf766859a47e6b7bbb2Mark Wielaard if (mod->aux_symstrdata == NULL || mod->aux_symstrdata->d_buf == NULL) 12505083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard goto aux_cleanup; 12515083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard 12525083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard if (aux_xndxscn == NULL) 12535083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard mod->aux_symxndxdata = NULL; 12545083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard else 12555083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard { 1256d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard shdr = gelf_getshdr (aux_xndxscn, &shdr_mem); 1257d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard if (shdr == NULL) 1258d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard goto elferr; 1259d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard 1260d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard if ((shdr->sh_flags & SHF_COMPRESSED) != 0) 1261d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard if (elf_compress (aux_xndxscn, 0, 0) < 0) 1262d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard goto elferr; 1263d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard 12642e73a8aec03499cda880db667e2570ebc0dd6810Mark Wielaard mod->aux_symxndxdata = elf_getdata (aux_xndxscn, NULL); 126586b0b13a0814f7283e04ddf766859a47e6b7bbb2Mark Wielaard if (mod->aux_symxndxdata == NULL 126686b0b13a0814f7283e04ddf766859a47e6b7bbb2Mark Wielaard || mod->aux_symxndxdata->d_buf == NULL) 12675083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard goto aux_cleanup; 12685083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard } 12695083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard 1270d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard shdr = gelf_getshdr (aux_symscn, &shdr_mem); 1271d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard if (shdr == NULL) 1272d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard goto elferr; 1273d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard 1274d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard if ((shdr->sh_flags & SHF_COMPRESSED) != 0) 1275d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard if (elf_compress (aux_symscn, 0, 0) < 0) 1276d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard goto elferr; 1277d22cb04967a2396514abf28cc43e70c037ee9cf2Mark Wielaard 12785083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard mod->aux_symdata = elf_getdata (aux_symscn, NULL); 127986b0b13a0814f7283e04ddf766859a47e6b7bbb2Mark Wielaard if (mod->aux_symdata == NULL || mod->aux_symdata->d_buf == NULL) 128086b0b13a0814f7283e04ddf766859a47e6b7bbb2Mark Wielaard goto aux_cleanup; 128186b0b13a0814f7283e04ddf766859a47e6b7bbb2Mark Wielaard 128286b0b13a0814f7283e04ddf766859a47e6b7bbb2Mark Wielaard // Sanity check number of aux symbols. 128386b0b13a0814f7283e04ddf766859a47e6b7bbb2Mark Wielaard shdr = gelf_getshdr (aux_symscn, &shdr_mem); 128486b0b13a0814f7283e04ddf766859a47e6b7bbb2Mark Wielaard if (mod->aux_syments > mod->aux_symdata->d_size / shdr->sh_entsize 128586b0b13a0814f7283e04ddf766859a47e6b7bbb2Mark Wielaard || (size_t) mod->aux_first_global > mod->aux_syments) 12865083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard goto aux_cleanup; 12875083a70d3b64946fa47ea5766943a15a3ecc6891Mark Wielaard } 1288b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper} 1289b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 1290b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 1291994b4899278199fc4d307780dac0ea50b238bc74Roland McGrath/* Try to open a libebl backend for MOD. */ 1292994b4899278199fc4d307780dac0ea50b238bc74Roland McGrathDwfl_Error 1293077c65f3be02e5d01b0c4dea3f6c854077d156fcUlrich Drepperinternal_function 1294994b4899278199fc4d307780dac0ea50b238bc74Roland McGrath__libdwfl_module_getebl (Dwfl_Module *mod) 1295994b4899278199fc4d307780dac0ea50b238bc74Roland McGrath{ 1296994b4899278199fc4d307780dac0ea50b238bc74Roland McGrath if (mod->ebl == NULL) 1297994b4899278199fc4d307780dac0ea50b238bc74Roland McGrath { 1298a605a3c8f354895f4cca56aca8f8aa468b506fdfRoland McGrath __libdwfl_getelf (mod); 1299994b4899278199fc4d307780dac0ea50b238bc74Roland McGrath if (mod->elferr != DWFL_E_NOERROR) 1300994b4899278199fc4d307780dac0ea50b238bc74Roland McGrath return mod->elferr; 1301994b4899278199fc4d307780dac0ea50b238bc74Roland McGrath 1302994b4899278199fc4d307780dac0ea50b238bc74Roland McGrath mod->ebl = ebl_openbackend (mod->main.elf); 1303994b4899278199fc4d307780dac0ea50b238bc74Roland McGrath if (mod->ebl == NULL) 1304994b4899278199fc4d307780dac0ea50b238bc74Roland McGrath return DWFL_E_LIBEBL; 1305994b4899278199fc4d307780dac0ea50b238bc74Roland McGrath } 1306994b4899278199fc4d307780dac0ea50b238bc74Roland McGrath return DWFL_E_NOERROR; 1307994b4899278199fc4d307780dac0ea50b238bc74Roland McGrath} 1308994b4899278199fc4d307780dac0ea50b238bc74Roland McGrath 1309b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Try to start up libdw on DEBUGFILE. */ 1310b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic Dwfl_Error 1311d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrathload_dw (Dwfl_Module *mod, struct dwfl_file *debugfile) 1312b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{ 1313059c83e5db89955913a39fe6705acca571c32c3fRoland McGrath if (mod->e_type == ET_REL && !debugfile->relocated) 1314b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper { 1315b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper const Dwfl_Callbacks *const cb = mod->dwfl->callbacks; 1316b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 1317b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper /* The debugging sections have to be relocated. */ 1318b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper if (cb->section_address == NULL) 1319b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper return DWFL_E_NOREL; 1320b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 1321994b4899278199fc4d307780dac0ea50b238bc74Roland McGrath Dwfl_Error error = __libdwfl_module_getebl (mod); 1322994b4899278199fc4d307780dac0ea50b238bc74Roland McGrath if (error != DWFL_E_NOERROR) 1323994b4899278199fc4d307780dac0ea50b238bc74Roland McGrath return error; 1324b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 1325b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper find_symtab (mod); 1326b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper Dwfl_Error result = mod->symerr; 1327b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper if (result == DWFL_E_NOERROR) 1328e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath result = __libdwfl_relocate (mod, debugfile->elf, true); 1329b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper if (result != DWFL_E_NOERROR) 1330b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper return result; 1331d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath 1332d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath /* Don't keep the file descriptors around. */ 1333d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath if (mod->main.fd != -1 && elf_cntl (mod->main.elf, ELF_C_FDREAD) == 0) 1334d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath { 1335d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath close (mod->main.fd); 1336d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath mod->main.fd = -1; 1337d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath } 1338d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath if (debugfile->fd != -1 && elf_cntl (debugfile->elf, ELF_C_FDREAD) == 0) 1339d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath { 1340d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath close (debugfile->fd); 1341d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath debugfile->fd = -1; 1342d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath } 1343b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper } 1344b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 1345d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath mod->dw = INTUSE(dwarf_begin_elf) (debugfile->elf, DWARF_C_READ, NULL); 1346b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper if (mod->dw == NULL) 1347b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper { 13484959bf89d92b59ba72bea5786d7b3f9b5564f750Roland McGrath int err = INTUSE(dwarf_errno) (); 1349b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper return err == DWARF_E_NO_DWARF ? DWFL_E_NO_DWARF : DWFL_E (LIBDW, err); 1350b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper } 1351b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 1352b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper /* Until we have iterated through all CU's, we might do lazy lookups. */ 1353b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper mod->lazycu = 1; 1354b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 1355b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper return DWFL_E_NOERROR; 1356b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper} 1357b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 1358b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Try to start up libdw on either the main file or the debuginfo file. */ 1359b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperstatic void 1360b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperfind_dw (Dwfl_Module *mod) 1361b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{ 1362b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper if (mod->dw != NULL /* Already done. */ 1363b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper || mod->dwerr != DWFL_E_NOERROR) /* Cached previous failure. */ 1364b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper return; 1365b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 1366a605a3c8f354895f4cca56aca8f8aa468b506fdfRoland McGrath __libdwfl_getelf (mod); 1367b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper mod->dwerr = mod->elferr; 1368b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper if (mod->dwerr != DWFL_E_NOERROR) 1369b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper return; 1370b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 1371b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper /* First see if the main ELF file has the debugging information. */ 1372d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath mod->dwerr = load_dw (mod, &mod->main); 1373b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper switch (mod->dwerr) 1374b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper { 1375b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper case DWFL_E_NOERROR: 1376b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper mod->debug.elf = mod->main.elf; 13771743d7f010bead5e869d097e23ce840583913381Roland McGrath mod->debug.address_sync = mod->main.address_sync; 1378df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard 1379df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard /* The Dwarf might need an alt debug file, find that now after 1380df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard everything about the debug file has been setup (the 1381df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard find_debuginfo callback might need it). */ 1382df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard find_debug_altlink (mod, mod->main.name); 1383b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper return; 1384b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 1385b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper case DWFL_E_NO_DWARF: 1386b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper break; 1387b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 1388b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper default: 1389b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper goto canonicalize; 1390b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper } 1391b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 1392b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper /* Now we have to look for a separate debuginfo file. */ 1393b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper mod->dwerr = find_debuginfo (mod); 1394b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper switch (mod->dwerr) 1395b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper { 1396b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper case DWFL_E_NOERROR: 1397d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath mod->dwerr = load_dw (mod, &mod->debug); 1398df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard if (mod->dwerr == DWFL_E_NOERROR) 1399df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard { 1400df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard /* The Dwarf might need an alt debug file, find that now after 1401df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard everything about the debug file has been setup (the 1402df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard find_debuginfo callback might need it). */ 1403df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard find_debug_altlink (mod, mod->debug.name); 1404df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard return; 1405df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard } 1406df85bf99021119fcbb2ced66dd69f1cceafb180cMark Wielaard 1407b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper break; 1408b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 1409b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper case DWFL_E_CB: /* The find_debuginfo hook failed. */ 1410b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper mod->dwerr = DWFL_E_NO_DWARF; 1411b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper return; 1412b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 1413b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper default: 1414b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper break; 1415b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper } 1416b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 1417b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper canonicalize: 1418b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper mod->dwerr = __libdwfl_canon_error (mod->dwerr); 1419b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper} 1420b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 1421b08d5a8fb42f4586d756068065186b5af7e48daUlrich DrepperDwarf * 1422b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperdwfl_module_getdwarf (Dwfl_Module *mod, Dwarf_Addr *bias) 1423b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{ 1424b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper if (mod == NULL) 1425b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper return NULL; 1426b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 1427b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper find_dw (mod); 1428b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper if (mod->dwerr == DWFL_E_NOERROR) 1429b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper { 1430e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath /* If dwfl_module_getelf was used previously, then partial apply 1431e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath relocation to miscellaneous sections in the debug file too. */ 1432e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath if (mod->e_type == ET_REL 1433e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath && mod->main.relocated && ! mod->debug.relocated) 1434e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath { 1435e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath mod->debug.relocated = true; 1436e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath if (mod->debug.elf != mod->main.elf) 1437e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath (void) __libdwfl_relocate (mod, mod->debug.elf, false); 1438e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath } 1439e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath 14401743d7f010bead5e869d097e23ce840583913381Roland McGrath *bias = dwfl_adjusted_dwarf_addr (mod, 0); 1441b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper return mod->dw; 1442b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper } 1443b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 1444b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper __libdwfl_seterrno (mod->dwerr); 1445b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper return NULL; 1446b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper} 1447b08d5a8fb42f4586d756068065186b5af7e48daUlrich DrepperINTDEF (dwfl_module_getdwarf) 1448b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 1449e1812e1d90090450e3d93be56a487e2f11affcedUlrich Drepperint 1450e1812e1d90090450e3d93be56a487e2f11affcedUlrich Drepperdwfl_module_getsymtab (Dwfl_Module *mod) 1451b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{ 1452b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper if (mod == NULL) 1453e1812e1d90090450e3d93be56a487e2f11affcedUlrich Drepper return -1; 1454b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 1455b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper find_symtab (mod); 1456e1812e1d90090450e3d93be56a487e2f11affcedUlrich Drepper if (mod->symerr == DWFL_E_NOERROR) 1457697bdca1d7d70ebdcae90759dd885258400e1951Mark Wielaard /* We will skip the auxiliary zero entry if there is another one. */ 1458697bdca1d7d70ebdcae90759dd885258400e1951Mark Wielaard return (mod->syments + mod->aux_syments 1459697bdca1d7d70ebdcae90759dd885258400e1951Mark Wielaard - (mod->syments > 0 && mod->aux_syments > 0 ? 1 : 0)); 1460b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 1461e1812e1d90090450e3d93be56a487e2f11affcedUlrich Drepper __libdwfl_seterrno (mod->symerr); 1462e1812e1d90090450e3d93be56a487e2f11affcedUlrich Drepper return -1; 1463b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper} 1464e1812e1d90090450e3d93be56a487e2f11affcedUlrich DrepperINTDEF (dwfl_module_getsymtab) 146514c2d9e614cb0e3fd50ad757eaba686b37699580Mark Wielaard 146614c2d9e614cb0e3fd50ad757eaba686b37699580Mark Wielaardint 146714c2d9e614cb0e3fd50ad757eaba686b37699580Mark Wielaarddwfl_module_getsymtab_first_global (Dwfl_Module *mod) 146814c2d9e614cb0e3fd50ad757eaba686b37699580Mark Wielaard{ 146914c2d9e614cb0e3fd50ad757eaba686b37699580Mark Wielaard if (mod == NULL) 147014c2d9e614cb0e3fd50ad757eaba686b37699580Mark Wielaard return -1; 147114c2d9e614cb0e3fd50ad757eaba686b37699580Mark Wielaard 147214c2d9e614cb0e3fd50ad757eaba686b37699580Mark Wielaard find_symtab (mod); 147314c2d9e614cb0e3fd50ad757eaba686b37699580Mark Wielaard if (mod->symerr == DWFL_E_NOERROR) 147414c2d9e614cb0e3fd50ad757eaba686b37699580Mark Wielaard { 147514c2d9e614cb0e3fd50ad757eaba686b37699580Mark Wielaard /* All local symbols should come before all global symbols. If 147614c2d9e614cb0e3fd50ad757eaba686b37699580Mark Wielaard we have an auxiliary table make sure all the main locals come 147714c2d9e614cb0e3fd50ad757eaba686b37699580Mark Wielaard first, then all aux locals, then all main globals and finally all 147814c2d9e614cb0e3fd50ad757eaba686b37699580Mark Wielaard aux globals. And skip the auxiliary table zero undefined 147914c2d9e614cb0e3fd50ad757eaba686b37699580Mark Wielaard entry. */ 148014c2d9e614cb0e3fd50ad757eaba686b37699580Mark Wielaard int skip_aux_zero = (mod->syments > 0 && mod->aux_syments > 0) ? 1 : 0; 148114c2d9e614cb0e3fd50ad757eaba686b37699580Mark Wielaard return mod->first_global + mod->aux_first_global - skip_aux_zero; 148214c2d9e614cb0e3fd50ad757eaba686b37699580Mark Wielaard } 148314c2d9e614cb0e3fd50ad757eaba686b37699580Mark Wielaard 148414c2d9e614cb0e3fd50ad757eaba686b37699580Mark Wielaard __libdwfl_seterrno (mod->symerr); 148514c2d9e614cb0e3fd50ad757eaba686b37699580Mark Wielaard return -1; 148614c2d9e614cb0e3fd50ad757eaba686b37699580Mark Wielaard} 148714c2d9e614cb0e3fd50ad757eaba686b37699580Mark WielaardINTDEF (dwfl_module_getsymtab_first_global) 1488