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