xref: /aosp_15_r20/external/elfutils/libdwfl/dwfl_module_getdwarf.c (revision 7304104da70ce23c86437a01be71edd1a2d7f37e)
1*7304104dSAndroid Build Coastguard Worker /* Find debugging and symbol information for a module in libdwfl.
2*7304104dSAndroid Build Coastguard Worker    Copyright (C) 2005-2012, 2014, 2015 Red Hat, Inc.
3*7304104dSAndroid Build Coastguard Worker    This file is part of elfutils.
4*7304104dSAndroid Build Coastguard Worker 
5*7304104dSAndroid Build Coastguard Worker    This file is free software; you can redistribute it and/or modify
6*7304104dSAndroid Build Coastguard Worker    it under the terms of either
7*7304104dSAndroid Build Coastguard Worker 
8*7304104dSAndroid Build Coastguard Worker      * the GNU Lesser General Public License as published by the Free
9*7304104dSAndroid Build Coastguard Worker        Software Foundation; either version 3 of the License, or (at
10*7304104dSAndroid Build Coastguard Worker        your option) any later version
11*7304104dSAndroid Build Coastguard Worker 
12*7304104dSAndroid Build Coastguard Worker    or
13*7304104dSAndroid Build Coastguard Worker 
14*7304104dSAndroid Build Coastguard Worker      * the GNU General Public License as published by the Free
15*7304104dSAndroid Build Coastguard Worker        Software Foundation; either version 2 of the License, or (at
16*7304104dSAndroid Build Coastguard Worker        your option) any later version
17*7304104dSAndroid Build Coastguard Worker 
18*7304104dSAndroid Build Coastguard Worker    or both in parallel, as here.
19*7304104dSAndroid Build Coastguard Worker 
20*7304104dSAndroid Build Coastguard Worker    elfutils is distributed in the hope that it will be useful, but
21*7304104dSAndroid Build Coastguard Worker    WITHOUT ANY WARRANTY; without even the implied warranty of
22*7304104dSAndroid Build Coastguard Worker    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23*7304104dSAndroid Build Coastguard Worker    General Public License for more details.
24*7304104dSAndroid Build Coastguard Worker 
25*7304104dSAndroid Build Coastguard Worker    You should have received copies of the GNU General Public License and
26*7304104dSAndroid Build Coastguard Worker    the GNU Lesser General Public License along with this program.  If
27*7304104dSAndroid Build Coastguard Worker    not, see <http://www.gnu.org/licenses/>.  */
28*7304104dSAndroid Build Coastguard Worker 
29*7304104dSAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
30*7304104dSAndroid Build Coastguard Worker # include <config.h>
31*7304104dSAndroid Build Coastguard Worker #endif
32*7304104dSAndroid Build Coastguard Worker 
33*7304104dSAndroid Build Coastguard Worker #include "libdwflP.h"
34*7304104dSAndroid Build Coastguard Worker #include <inttypes.h>
35*7304104dSAndroid Build Coastguard Worker #include <fcntl.h>
36*7304104dSAndroid Build Coastguard Worker #include <string.h>
37*7304104dSAndroid Build Coastguard Worker #include "libdwP.h"	/* DWARF_E_* values are here.  */
38*7304104dSAndroid Build Coastguard Worker #include "libelfP.h"
39*7304104dSAndroid Build Coastguard Worker #include "system.h"
40*7304104dSAndroid Build Coastguard Worker 
41*7304104dSAndroid Build Coastguard Worker static inline Dwfl_Error
open_elf_file(Elf ** elf,int * fd,char ** name)42*7304104dSAndroid Build Coastguard Worker open_elf_file (Elf **elf, int *fd, char **name)
43*7304104dSAndroid Build Coastguard Worker {
44*7304104dSAndroid Build Coastguard Worker   if (*elf == NULL)
45*7304104dSAndroid Build Coastguard Worker     {
46*7304104dSAndroid Build Coastguard Worker       /* CBFAIL uses errno if it's set, so clear it first in case we don't
47*7304104dSAndroid Build Coastguard Worker 	 set it with an open failure below.  */
48*7304104dSAndroid Build Coastguard Worker       errno = 0;
49*7304104dSAndroid Build Coastguard Worker 
50*7304104dSAndroid Build Coastguard Worker       /* If there was a pre-primed file name left that the callback left
51*7304104dSAndroid Build Coastguard Worker 	 behind, try to open that file name.  */
52*7304104dSAndroid Build Coastguard Worker       if (*fd < 0 && *name != NULL)
53*7304104dSAndroid Build Coastguard Worker 	*fd = TEMP_FAILURE_RETRY (open (*name, O_RDONLY));
54*7304104dSAndroid Build Coastguard Worker 
55*7304104dSAndroid Build Coastguard Worker       if (*fd < 0)
56*7304104dSAndroid Build Coastguard Worker 	return CBFAIL;
57*7304104dSAndroid Build Coastguard Worker 
58*7304104dSAndroid Build Coastguard Worker       return __libdw_open_file (fd, elf, true, false);
59*7304104dSAndroid Build Coastguard Worker     }
60*7304104dSAndroid Build Coastguard Worker   else if (unlikely (elf_kind (*elf) != ELF_K_ELF))
61*7304104dSAndroid Build Coastguard Worker     {
62*7304104dSAndroid Build Coastguard Worker       elf_end (*elf);
63*7304104dSAndroid Build Coastguard Worker       *elf = NULL;
64*7304104dSAndroid Build Coastguard Worker       close (*fd);
65*7304104dSAndroid Build Coastguard Worker       *fd = -1;
66*7304104dSAndroid Build Coastguard Worker       return DWFL_E_BADELF;
67*7304104dSAndroid Build Coastguard Worker     }
68*7304104dSAndroid Build Coastguard Worker 
69*7304104dSAndroid Build Coastguard Worker   /* Elf file already open and looks fine.  */
70*7304104dSAndroid Build Coastguard Worker   return DWFL_E_NOERROR;
71*7304104dSAndroid Build Coastguard Worker }
72*7304104dSAndroid Build Coastguard Worker 
73*7304104dSAndroid Build Coastguard Worker /* Open libelf FILE->fd and compute the load base of ELF as loaded in MOD.
74*7304104dSAndroid Build Coastguard Worker    When we return success, FILE->elf and FILE->vaddr are set up.  */
75*7304104dSAndroid Build Coastguard Worker static inline Dwfl_Error
open_elf(Dwfl_Module * mod,struct dwfl_file * file)76*7304104dSAndroid Build Coastguard Worker open_elf (Dwfl_Module *mod, struct dwfl_file *file)
77*7304104dSAndroid Build Coastguard Worker {
78*7304104dSAndroid Build Coastguard Worker   Dwfl_Error error = open_elf_file (&file->elf, &file->fd, &file->name);
79*7304104dSAndroid Build Coastguard Worker   if (error != DWFL_E_NOERROR)
80*7304104dSAndroid Build Coastguard Worker     return error;
81*7304104dSAndroid Build Coastguard Worker 
82*7304104dSAndroid Build Coastguard Worker   GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (file->elf, &ehdr_mem);
83*7304104dSAndroid Build Coastguard Worker   if (ehdr == NULL)
84*7304104dSAndroid Build Coastguard Worker     {
85*7304104dSAndroid Build Coastguard Worker     elf_error:
86*7304104dSAndroid Build Coastguard Worker       elf_end (file->elf);
87*7304104dSAndroid Build Coastguard Worker       file->elf = NULL;
88*7304104dSAndroid Build Coastguard Worker       close (file->fd);
89*7304104dSAndroid Build Coastguard Worker       file->fd = -1;
90*7304104dSAndroid Build Coastguard Worker       return DWFL_E (LIBELF, elf_errno ());
91*7304104dSAndroid Build Coastguard Worker     }
92*7304104dSAndroid Build Coastguard Worker 
93*7304104dSAndroid Build Coastguard Worker   if (ehdr->e_type != ET_REL)
94*7304104dSAndroid Build Coastguard Worker     {
95*7304104dSAndroid Build Coastguard Worker       /* In any non-ET_REL file, we compute the "synchronization address".
96*7304104dSAndroid Build Coastguard Worker 
97*7304104dSAndroid Build Coastguard Worker 	 We start with the address at the end of the first PT_LOAD
98*7304104dSAndroid Build Coastguard Worker 	 segment.  When prelink converts REL to RELA in an ET_DYN
99*7304104dSAndroid Build Coastguard Worker 	 file, it expands the space between the beginning of the
100*7304104dSAndroid Build Coastguard Worker 	 segment and the actual code/data addresses.  Since that
101*7304104dSAndroid Build Coastguard Worker 	 change wasn't made in the debug file, the distance from
102*7304104dSAndroid Build Coastguard Worker 	 p_vaddr to an address of interest (in an st_value or DWARF
103*7304104dSAndroid Build Coastguard Worker 	 data) now differs between the main and debug files.  The
104*7304104dSAndroid Build Coastguard Worker 	 distance from address_sync to an address of interest remains
105*7304104dSAndroid Build Coastguard Worker 	 consistent.
106*7304104dSAndroid Build Coastguard Worker 
107*7304104dSAndroid Build Coastguard Worker 	 If there are no section headers at all (full stripping), then
108*7304104dSAndroid Build Coastguard Worker 	 the end of the first segment is a valid synchronization address.
109*7304104dSAndroid Build Coastguard Worker 	 This cannot happen in a prelinked file, since prelink itself
110*7304104dSAndroid Build Coastguard Worker 	 relies on section headers for prelinking and for undoing it.
111*7304104dSAndroid Build Coastguard Worker 	 (If you do full stripping on a prelinked file, then you get what
112*7304104dSAndroid Build Coastguard Worker 	 you deserve--you can neither undo the prelinking, nor expect to
113*7304104dSAndroid Build Coastguard Worker 	 line it up with a debug file separated before prelinking.)
114*7304104dSAndroid Build Coastguard Worker 
115*7304104dSAndroid Build Coastguard Worker 	 However, when prelink processes an ET_EXEC file, it can do
116*7304104dSAndroid Build Coastguard Worker 	 something different.  There it juggles the "special" sections
117*7304104dSAndroid Build Coastguard Worker 	 (SHT_DYNSYM et al) to make space for the additional prelink
118*7304104dSAndroid Build Coastguard Worker 	 special sections.  Sometimes it will do this by moving a special
119*7304104dSAndroid Build Coastguard Worker 	 section like .dynstr after the real program sections in the first
120*7304104dSAndroid Build Coastguard Worker 	 PT_LOAD segment--i.e. to the end.  That changes the end address of
121*7304104dSAndroid Build Coastguard Worker 	 the segment, so it no longer lines up correctly and is not a valid
122*7304104dSAndroid Build Coastguard Worker 	 synchronization address to use.  Because of this, we need to apply
123*7304104dSAndroid Build Coastguard Worker 	 a different prelink-savvy means to discover the synchronization
124*7304104dSAndroid Build Coastguard Worker 	 address when there is a separate debug file and a prelinked main
125*7304104dSAndroid Build Coastguard Worker 	 file.  That is done in find_debuginfo, below.  */
126*7304104dSAndroid Build Coastguard Worker 
127*7304104dSAndroid Build Coastguard Worker       size_t phnum;
128*7304104dSAndroid Build Coastguard Worker       if (unlikely (elf_getphdrnum (file->elf, &phnum) != 0))
129*7304104dSAndroid Build Coastguard Worker 	goto elf_error;
130*7304104dSAndroid Build Coastguard Worker 
131*7304104dSAndroid Build Coastguard Worker       file->vaddr = file->address_sync = 0;
132*7304104dSAndroid Build Coastguard Worker       for (size_t i = 0; i < phnum; ++i)
133*7304104dSAndroid Build Coastguard Worker 	{
134*7304104dSAndroid Build Coastguard Worker 	  GElf_Phdr ph_mem;
135*7304104dSAndroid Build Coastguard Worker 	  GElf_Phdr *ph = gelf_getphdr (file->elf, i, &ph_mem);
136*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (ph == NULL))
137*7304104dSAndroid Build Coastguard Worker 	    goto elf_error;
138*7304104dSAndroid Build Coastguard Worker 	  if (ph->p_type == PT_LOAD)
139*7304104dSAndroid Build Coastguard Worker 	    {
140*7304104dSAndroid Build Coastguard Worker 	      file->vaddr = ph->p_vaddr & -ph->p_align;
141*7304104dSAndroid Build Coastguard Worker 	      file->address_sync = ph->p_vaddr + ph->p_memsz;
142*7304104dSAndroid Build Coastguard Worker 	      break;
143*7304104dSAndroid Build Coastguard Worker 	    }
144*7304104dSAndroid Build Coastguard Worker 	}
145*7304104dSAndroid Build Coastguard Worker     }
146*7304104dSAndroid Build Coastguard Worker 
147*7304104dSAndroid Build Coastguard Worker   /* We only want to set the module e_type explicitly once, derived from
148*7304104dSAndroid Build Coastguard Worker      the main ELF file.  (It might be changed for the kernel, because
149*7304104dSAndroid Build Coastguard Worker      that is special - see below.)  open_elf is always called first for
150*7304104dSAndroid Build Coastguard Worker      the main ELF file, because both find_dw and find_symtab call
151*7304104dSAndroid Build Coastguard Worker      __libdwfl_getelf first to open the main file.  So don't let debug
152*7304104dSAndroid Build Coastguard Worker      or aux files override the module e_type.  The kernel heuristic
153*7304104dSAndroid Build Coastguard Worker      below could otherwise trigger for non-kernel/non-main files, since
154*7304104dSAndroid Build Coastguard Worker      their phdrs might not match the actual load addresses.  */
155*7304104dSAndroid Build Coastguard Worker   if (file == &mod->main)
156*7304104dSAndroid Build Coastguard Worker     {
157*7304104dSAndroid Build Coastguard Worker       mod->e_type = ehdr->e_type;
158*7304104dSAndroid Build Coastguard Worker 
159*7304104dSAndroid Build Coastguard Worker       /* Relocatable Linux kernels are ET_EXEC but act like ET_DYN.  */
160*7304104dSAndroid Build Coastguard Worker       if (mod->e_type == ET_EXEC && file->vaddr != mod->low_addr)
161*7304104dSAndroid Build Coastguard Worker 	mod->e_type = ET_DYN;
162*7304104dSAndroid Build Coastguard Worker     }
163*7304104dSAndroid Build Coastguard Worker   else
164*7304104dSAndroid Build Coastguard Worker     assert (mod->main.elf != NULL);
165*7304104dSAndroid Build Coastguard Worker 
166*7304104dSAndroid Build Coastguard Worker   return DWFL_E_NOERROR;
167*7304104dSAndroid Build Coastguard Worker }
168*7304104dSAndroid Build Coastguard Worker 
169*7304104dSAndroid Build Coastguard Worker /* We have an authoritative build ID for this module MOD, so don't use
170*7304104dSAndroid Build Coastguard Worker    a file by name that doesn't match that ID.  */
171*7304104dSAndroid Build Coastguard Worker static void
mod_verify_build_id(Dwfl_Module * mod)172*7304104dSAndroid Build Coastguard Worker mod_verify_build_id (Dwfl_Module *mod)
173*7304104dSAndroid Build Coastguard Worker {
174*7304104dSAndroid Build Coastguard Worker   assert (mod->build_id_len > 0);
175*7304104dSAndroid Build Coastguard Worker 
176*7304104dSAndroid Build Coastguard Worker   switch (__builtin_expect (__libdwfl_find_build_id (mod, false,
177*7304104dSAndroid Build Coastguard Worker 						     mod->main.elf), 2))
178*7304104dSAndroid Build Coastguard Worker     {
179*7304104dSAndroid Build Coastguard Worker     case 2:
180*7304104dSAndroid Build Coastguard Worker       /* Build ID matches as it should. */
181*7304104dSAndroid Build Coastguard Worker       return;
182*7304104dSAndroid Build Coastguard Worker 
183*7304104dSAndroid Build Coastguard Worker     case -1:			/* ELF error.  */
184*7304104dSAndroid Build Coastguard Worker       mod->elferr = INTUSE(dwfl_errno) ();
185*7304104dSAndroid Build Coastguard Worker       break;
186*7304104dSAndroid Build Coastguard Worker 
187*7304104dSAndroid Build Coastguard Worker     case 0:			/* File has no build ID note.  */
188*7304104dSAndroid Build Coastguard Worker     case 1:			/* FIle has a build ID that does not match.  */
189*7304104dSAndroid Build Coastguard Worker       mod->elferr = DWFL_E_WRONG_ID_ELF;
190*7304104dSAndroid Build Coastguard Worker       break;
191*7304104dSAndroid Build Coastguard Worker 
192*7304104dSAndroid Build Coastguard Worker     default:
193*7304104dSAndroid Build Coastguard Worker       abort ();
194*7304104dSAndroid Build Coastguard Worker     }
195*7304104dSAndroid Build Coastguard Worker 
196*7304104dSAndroid Build Coastguard Worker   /* We get here when it was the right ELF file.  Clear it out.  */
197*7304104dSAndroid Build Coastguard Worker   elf_end (mod->main.elf);
198*7304104dSAndroid Build Coastguard Worker   mod->main.elf = NULL;
199*7304104dSAndroid Build Coastguard Worker   if (mod->main.fd >= 0)
200*7304104dSAndroid Build Coastguard Worker     {
201*7304104dSAndroid Build Coastguard Worker       close (mod->main.fd);
202*7304104dSAndroid Build Coastguard Worker       mod->main.fd = -1;
203*7304104dSAndroid Build Coastguard Worker     }
204*7304104dSAndroid Build Coastguard Worker }
205*7304104dSAndroid Build Coastguard Worker 
206*7304104dSAndroid Build Coastguard Worker /* Find the main ELF file for this module and open libelf on it.
207*7304104dSAndroid Build Coastguard Worker    When we return success, MOD->main.elf and MOD->main.bias are set up.  */
208*7304104dSAndroid Build Coastguard Worker void
209*7304104dSAndroid Build Coastguard Worker internal_function
__libdwfl_getelf(Dwfl_Module * mod)210*7304104dSAndroid Build Coastguard Worker __libdwfl_getelf (Dwfl_Module *mod)
211*7304104dSAndroid Build Coastguard Worker {
212*7304104dSAndroid Build Coastguard Worker   if (mod->main.elf != NULL	/* Already done.  */
213*7304104dSAndroid Build Coastguard Worker       || mod->elferr != DWFL_E_NOERROR)	/* Cached failure.  */
214*7304104dSAndroid Build Coastguard Worker     return;
215*7304104dSAndroid Build Coastguard Worker 
216*7304104dSAndroid Build Coastguard Worker   mod->main.fd = (*mod->dwfl->callbacks->find_elf) (MODCB_ARGS (mod),
217*7304104dSAndroid Build Coastguard Worker 						    &mod->main.name,
218*7304104dSAndroid Build Coastguard Worker 						    &mod->main.elf);
219*7304104dSAndroid Build Coastguard Worker   const bool fallback = mod->main.elf == NULL && mod->main.fd < 0;
220*7304104dSAndroid Build Coastguard Worker   mod->elferr = open_elf (mod, &mod->main);
221*7304104dSAndroid Build Coastguard Worker   if (mod->elferr != DWFL_E_NOERROR)
222*7304104dSAndroid Build Coastguard Worker     return;
223*7304104dSAndroid Build Coastguard Worker 
224*7304104dSAndroid Build Coastguard Worker   if (!mod->main.valid)
225*7304104dSAndroid Build Coastguard Worker     {
226*7304104dSAndroid Build Coastguard Worker       /* Clear any explicitly reported build ID, just in case it was wrong.
227*7304104dSAndroid Build Coastguard Worker 	 We'll fetch it from the file when asked.  */
228*7304104dSAndroid Build Coastguard Worker       free (mod->build_id_bits);
229*7304104dSAndroid Build Coastguard Worker       mod->build_id_bits = NULL;
230*7304104dSAndroid Build Coastguard Worker       mod->build_id_len = 0;
231*7304104dSAndroid Build Coastguard Worker     }
232*7304104dSAndroid Build Coastguard Worker   else if (fallback)
233*7304104dSAndroid Build Coastguard Worker     mod_verify_build_id (mod);
234*7304104dSAndroid Build Coastguard Worker 
235*7304104dSAndroid Build Coastguard Worker   mod->main_bias = mod->e_type == ET_REL ? 0 : mod->low_addr - mod->main.vaddr;
236*7304104dSAndroid Build Coastguard Worker }
237*7304104dSAndroid Build Coastguard Worker 
238*7304104dSAndroid Build Coastguard Worker static inline void
consider_shdr(GElf_Addr interp,GElf_Word sh_type,GElf_Xword sh_flags,GElf_Addr sh_addr,GElf_Xword sh_size,GElf_Addr * phighest)239*7304104dSAndroid Build Coastguard Worker consider_shdr (GElf_Addr interp,
240*7304104dSAndroid Build Coastguard Worker                GElf_Word sh_type,
241*7304104dSAndroid Build Coastguard Worker                GElf_Xword sh_flags,
242*7304104dSAndroid Build Coastguard Worker                GElf_Addr sh_addr,
243*7304104dSAndroid Build Coastguard Worker                GElf_Xword sh_size,
244*7304104dSAndroid Build Coastguard Worker                GElf_Addr *phighest)
245*7304104dSAndroid Build Coastguard Worker {
246*7304104dSAndroid Build Coastguard Worker   if ((sh_flags & SHF_ALLOC)
247*7304104dSAndroid Build Coastguard Worker       && ((sh_type == SHT_PROGBITS && sh_addr != interp)
248*7304104dSAndroid Build Coastguard Worker           || sh_type == SHT_NOBITS))
249*7304104dSAndroid Build Coastguard Worker     {
250*7304104dSAndroid Build Coastguard Worker       const GElf_Addr sh_end = sh_addr + sh_size;
251*7304104dSAndroid Build Coastguard Worker       if (sh_end > *phighest)
252*7304104dSAndroid Build Coastguard Worker         *phighest = sh_end;
253*7304104dSAndroid Build Coastguard Worker     }
254*7304104dSAndroid Build Coastguard Worker }
255*7304104dSAndroid Build Coastguard Worker 
256*7304104dSAndroid Build Coastguard Worker /* If the main file might have been prelinked, then we need to
257*7304104dSAndroid Build Coastguard Worker    discover the correct synchronization address between the main and
258*7304104dSAndroid Build Coastguard Worker    debug files.  Because of prelink's section juggling, we cannot rely
259*7304104dSAndroid Build Coastguard Worker    on the address_sync computed from PT_LOAD segments (see open_elf).
260*7304104dSAndroid Build Coastguard Worker 
261*7304104dSAndroid Build Coastguard Worker    We will attempt to discover a synchronization address based on the
262*7304104dSAndroid Build Coastguard Worker    section headers instead.  But finding a section address that is
263*7304104dSAndroid Build Coastguard Worker    safe to use requires identifying which sections are SHT_PROGBITS.
264*7304104dSAndroid Build Coastguard Worker    We can do that in the main file, but in the debug file all the
265*7304104dSAndroid Build Coastguard Worker    allocated sections have been transformed into SHT_NOBITS so we have
266*7304104dSAndroid Build Coastguard Worker    lost the means to match them up correctly.
267*7304104dSAndroid Build Coastguard Worker 
268*7304104dSAndroid Build Coastguard Worker    The only method left to us is to decode the .gnu.prelink_undo
269*7304104dSAndroid Build Coastguard Worker    section in the prelinked main file.  This shows what the sections
270*7304104dSAndroid Build Coastguard Worker    looked like before prelink juggled them--when they still had a
271*7304104dSAndroid Build Coastguard Worker    direct correspondence to the debug file.  */
272*7304104dSAndroid Build Coastguard Worker static Dwfl_Error
find_prelink_address_sync(Dwfl_Module * mod,struct dwfl_file * file)273*7304104dSAndroid Build Coastguard Worker find_prelink_address_sync (Dwfl_Module *mod, struct dwfl_file *file)
274*7304104dSAndroid Build Coastguard Worker {
275*7304104dSAndroid Build Coastguard Worker   /* The magic section is only identified by name.  */
276*7304104dSAndroid Build Coastguard Worker   size_t shstrndx;
277*7304104dSAndroid Build Coastguard Worker   if (elf_getshdrstrndx (mod->main.elf, &shstrndx) < 0)
278*7304104dSAndroid Build Coastguard Worker     return DWFL_E_LIBELF;
279*7304104dSAndroid Build Coastguard Worker 
280*7304104dSAndroid Build Coastguard Worker   Elf_Scn *scn = NULL;
281*7304104dSAndroid Build Coastguard Worker   while ((scn = elf_nextscn (mod->main.elf, scn)) != NULL)
282*7304104dSAndroid Build Coastguard Worker     {
283*7304104dSAndroid Build Coastguard Worker       GElf_Shdr shdr_mem;
284*7304104dSAndroid Build Coastguard Worker       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
285*7304104dSAndroid Build Coastguard Worker       if (unlikely (shdr == NULL))
286*7304104dSAndroid Build Coastguard Worker 	return DWFL_E_LIBELF;
287*7304104dSAndroid Build Coastguard Worker       if (shdr->sh_type == SHT_PROGBITS
288*7304104dSAndroid Build Coastguard Worker 	  && !(shdr->sh_flags & SHF_ALLOC)
289*7304104dSAndroid Build Coastguard Worker 	  && shdr->sh_name != 0)
290*7304104dSAndroid Build Coastguard Worker 	{
291*7304104dSAndroid Build Coastguard Worker 	  const char *secname = elf_strptr (mod->main.elf, shstrndx,
292*7304104dSAndroid Build Coastguard Worker 					    shdr->sh_name);
293*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (secname == NULL))
294*7304104dSAndroid Build Coastguard Worker 	    return DWFL_E_LIBELF;
295*7304104dSAndroid Build Coastguard Worker 	  if (!strcmp (secname, ".gnu.prelink_undo"))
296*7304104dSAndroid Build Coastguard Worker 	    break;
297*7304104dSAndroid Build Coastguard Worker 	}
298*7304104dSAndroid Build Coastguard Worker     }
299*7304104dSAndroid Build Coastguard Worker 
300*7304104dSAndroid Build Coastguard Worker   if (scn == NULL)
301*7304104dSAndroid Build Coastguard Worker     /* There was no .gnu.prelink_undo section.  */
302*7304104dSAndroid Build Coastguard Worker     return DWFL_E_NOERROR;
303*7304104dSAndroid Build Coastguard Worker 
304*7304104dSAndroid Build Coastguard Worker   Elf_Data *undodata = elf_rawdata (scn, NULL);
305*7304104dSAndroid Build Coastguard Worker   if (unlikely (undodata == NULL))
306*7304104dSAndroid Build Coastguard Worker     return DWFL_E_LIBELF;
307*7304104dSAndroid Build Coastguard Worker 
308*7304104dSAndroid Build Coastguard Worker   /* Decode the section.  It consists of the original ehdr, phdrs,
309*7304104dSAndroid Build Coastguard Worker      and shdrs (but omits section 0).  */
310*7304104dSAndroid Build Coastguard Worker 
311*7304104dSAndroid Build Coastguard Worker   union
312*7304104dSAndroid Build Coastguard Worker   {
313*7304104dSAndroid Build Coastguard Worker     Elf32_Ehdr e32;
314*7304104dSAndroid Build Coastguard Worker     Elf64_Ehdr e64;
315*7304104dSAndroid Build Coastguard Worker   } ehdr;
316*7304104dSAndroid Build Coastguard Worker   Elf_Data dst =
317*7304104dSAndroid Build Coastguard Worker     {
318*7304104dSAndroid Build Coastguard Worker       .d_buf = &ehdr,
319*7304104dSAndroid Build Coastguard Worker       .d_size = sizeof ehdr,
320*7304104dSAndroid Build Coastguard Worker       .d_type = ELF_T_EHDR,
321*7304104dSAndroid Build Coastguard Worker       .d_version = EV_CURRENT
322*7304104dSAndroid Build Coastguard Worker     };
323*7304104dSAndroid Build Coastguard Worker   Elf_Data src = *undodata;
324*7304104dSAndroid Build Coastguard Worker   src.d_size = gelf_fsize (mod->main.elf, ELF_T_EHDR, 1, EV_CURRENT);
325*7304104dSAndroid Build Coastguard Worker   src.d_type = ELF_T_EHDR;
326*7304104dSAndroid Build Coastguard Worker   if (unlikely (gelf_xlatetom (mod->main.elf, &dst, &src,
327*7304104dSAndroid Build Coastguard Worker 			       elf_getident (mod->main.elf, NULL)[EI_DATA])
328*7304104dSAndroid Build Coastguard Worker 		== NULL))
329*7304104dSAndroid Build Coastguard Worker     return DWFL_E_LIBELF;
330*7304104dSAndroid Build Coastguard Worker 
331*7304104dSAndroid Build Coastguard Worker   size_t shentsize = gelf_fsize (mod->main.elf, ELF_T_SHDR, 1, EV_CURRENT);
332*7304104dSAndroid Build Coastguard Worker   size_t phentsize = gelf_fsize (mod->main.elf, ELF_T_PHDR, 1, EV_CURRENT);
333*7304104dSAndroid Build Coastguard Worker 
334*7304104dSAndroid Build Coastguard Worker   uint_fast16_t phnum;
335*7304104dSAndroid Build Coastguard Worker   uint_fast16_t shnum;
336*7304104dSAndroid Build Coastguard Worker   if (ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32)
337*7304104dSAndroid Build Coastguard Worker     {
338*7304104dSAndroid Build Coastguard Worker       if (ehdr.e32.e_shentsize != shentsize
339*7304104dSAndroid Build Coastguard Worker 	  || ehdr.e32.e_phentsize != phentsize)
340*7304104dSAndroid Build Coastguard Worker 	return DWFL_E_BAD_PRELINK;
341*7304104dSAndroid Build Coastguard Worker       phnum = ehdr.e32.e_phnum;
342*7304104dSAndroid Build Coastguard Worker       shnum = ehdr.e32.e_shnum;
343*7304104dSAndroid Build Coastguard Worker     }
344*7304104dSAndroid Build Coastguard Worker   else
345*7304104dSAndroid Build Coastguard Worker     {
346*7304104dSAndroid Build Coastguard Worker       if (ehdr.e64.e_shentsize != shentsize
347*7304104dSAndroid Build Coastguard Worker 	  || ehdr.e64.e_phentsize != phentsize)
348*7304104dSAndroid Build Coastguard Worker 	return DWFL_E_BAD_PRELINK;
349*7304104dSAndroid Build Coastguard Worker       phnum = ehdr.e64.e_phnum;
350*7304104dSAndroid Build Coastguard Worker       shnum = ehdr.e64.e_shnum;
351*7304104dSAndroid Build Coastguard Worker     }
352*7304104dSAndroid Build Coastguard Worker 
353*7304104dSAndroid Build Coastguard Worker   /* Since prelink does not store the zeroth section header in the undo
354*7304104dSAndroid Build Coastguard Worker      section, it cannot support SHN_XINDEX encoding.  */
355*7304104dSAndroid Build Coastguard Worker   if (unlikely (shnum >= SHN_LORESERVE) || unlikely(shnum == 0)
356*7304104dSAndroid Build Coastguard Worker       || unlikely (undodata->d_size != (src.d_size
357*7304104dSAndroid Build Coastguard Worker 					+ phnum * phentsize
358*7304104dSAndroid Build Coastguard Worker 					+ (shnum - 1) * shentsize)))
359*7304104dSAndroid Build Coastguard Worker     return DWFL_E_BAD_PRELINK;
360*7304104dSAndroid Build Coastguard Worker 
361*7304104dSAndroid Build Coastguard Worker   --shnum;
362*7304104dSAndroid Build Coastguard Worker 
363*7304104dSAndroid Build Coastguard Worker   /* We look at the allocated SHT_PROGBITS (or SHT_NOBITS) sections.  (Most
364*7304104dSAndroid Build Coastguard Worker      every file will have some SHT_PROGBITS sections, but it's possible to
365*7304104dSAndroid Build Coastguard Worker      have one with nothing but .bss, i.e. SHT_NOBITS.)  The special sections
366*7304104dSAndroid Build Coastguard Worker      that can be moved around have different sh_type values--except for
367*7304104dSAndroid Build Coastguard Worker      .interp, the section that became the PT_INTERP segment.  So we exclude
368*7304104dSAndroid Build Coastguard Worker      the SHT_PROGBITS section whose address matches the PT_INTERP p_vaddr.
369*7304104dSAndroid Build Coastguard Worker      For this reason, we must examine the phdrs first to find PT_INTERP.  */
370*7304104dSAndroid Build Coastguard Worker 
371*7304104dSAndroid Build Coastguard Worker   GElf_Addr main_interp = 0;
372*7304104dSAndroid Build Coastguard Worker   {
373*7304104dSAndroid Build Coastguard Worker     size_t main_phnum;
374*7304104dSAndroid Build Coastguard Worker     if (unlikely (elf_getphdrnum (mod->main.elf, &main_phnum)))
375*7304104dSAndroid Build Coastguard Worker       return DWFL_E_LIBELF;
376*7304104dSAndroid Build Coastguard Worker     for (size_t i = 0; i < main_phnum; ++i)
377*7304104dSAndroid Build Coastguard Worker       {
378*7304104dSAndroid Build Coastguard Worker 	GElf_Phdr phdr;
379*7304104dSAndroid Build Coastguard Worker 	if (unlikely (gelf_getphdr (mod->main.elf, i, &phdr) == NULL))
380*7304104dSAndroid Build Coastguard Worker 	  return DWFL_E_LIBELF;
381*7304104dSAndroid Build Coastguard Worker 	if (phdr.p_type == PT_INTERP)
382*7304104dSAndroid Build Coastguard Worker 	  {
383*7304104dSAndroid Build Coastguard Worker 	    main_interp = phdr.p_vaddr;
384*7304104dSAndroid Build Coastguard Worker 	    break;
385*7304104dSAndroid Build Coastguard Worker 	  }
386*7304104dSAndroid Build Coastguard Worker       }
387*7304104dSAndroid Build Coastguard Worker   }
388*7304104dSAndroid Build Coastguard Worker 
389*7304104dSAndroid Build Coastguard Worker   src.d_buf += src.d_size;
390*7304104dSAndroid Build Coastguard Worker   src.d_type = ELF_T_PHDR;
391*7304104dSAndroid Build Coastguard Worker   src.d_size = phnum * phentsize;
392*7304104dSAndroid Build Coastguard Worker 
393*7304104dSAndroid Build Coastguard Worker   GElf_Addr undo_interp = 0;
394*7304104dSAndroid Build Coastguard Worker   bool class32 = ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32;
395*7304104dSAndroid Build Coastguard Worker   {
396*7304104dSAndroid Build Coastguard Worker     size_t phdr_size = class32 ? sizeof (Elf32_Phdr) : sizeof (Elf64_Phdr);
397*7304104dSAndroid Build Coastguard Worker     if (unlikely (phnum > SIZE_MAX / phdr_size))
398*7304104dSAndroid Build Coastguard Worker       return DWFL_E_NOMEM;
399*7304104dSAndroid Build Coastguard Worker     const size_t phdrs_bytes = phnum * phdr_size;
400*7304104dSAndroid Build Coastguard Worker     void *phdrs = malloc (phdrs_bytes);
401*7304104dSAndroid Build Coastguard Worker     if (unlikely (phdrs == NULL))
402*7304104dSAndroid Build Coastguard Worker       return DWFL_E_NOMEM;
403*7304104dSAndroid Build Coastguard Worker     dst.d_buf = phdrs;
404*7304104dSAndroid Build Coastguard Worker     dst.d_size = phdrs_bytes;
405*7304104dSAndroid Build Coastguard Worker     if (unlikely (gelf_xlatetom (mod->main.elf, &dst, &src,
406*7304104dSAndroid Build Coastguard Worker 				 ehdr.e32.e_ident[EI_DATA]) == NULL))
407*7304104dSAndroid Build Coastguard Worker       {
408*7304104dSAndroid Build Coastguard Worker 	free (phdrs);
409*7304104dSAndroid Build Coastguard Worker 	return DWFL_E_LIBELF;
410*7304104dSAndroid Build Coastguard Worker       }
411*7304104dSAndroid Build Coastguard Worker     if (class32)
412*7304104dSAndroid Build Coastguard Worker       {
413*7304104dSAndroid Build Coastguard Worker 	Elf32_Phdr (*p32)[phnum] = phdrs;
414*7304104dSAndroid Build Coastguard Worker 	for (uint_fast16_t i = 0; i < phnum; ++i)
415*7304104dSAndroid Build Coastguard Worker 	  if ((*p32)[i].p_type == PT_INTERP)
416*7304104dSAndroid Build Coastguard Worker 	    {
417*7304104dSAndroid Build Coastguard Worker 	      undo_interp = (*p32)[i].p_vaddr;
418*7304104dSAndroid Build Coastguard Worker 	      break;
419*7304104dSAndroid Build Coastguard Worker 	    }
420*7304104dSAndroid Build Coastguard Worker       }
421*7304104dSAndroid Build Coastguard Worker     else
422*7304104dSAndroid Build Coastguard Worker       {
423*7304104dSAndroid Build Coastguard Worker 	Elf64_Phdr (*p64)[phnum] = phdrs;
424*7304104dSAndroid Build Coastguard Worker 	for (uint_fast16_t i = 0; i < phnum; ++i)
425*7304104dSAndroid Build Coastguard Worker 	  if ((*p64)[i].p_type == PT_INTERP)
426*7304104dSAndroid Build Coastguard Worker 	    {
427*7304104dSAndroid Build Coastguard Worker 	      undo_interp = (*p64)[i].p_vaddr;
428*7304104dSAndroid Build Coastguard Worker 	      break;
429*7304104dSAndroid Build Coastguard Worker 	    }
430*7304104dSAndroid Build Coastguard Worker       }
431*7304104dSAndroid Build Coastguard Worker     free (phdrs);
432*7304104dSAndroid Build Coastguard Worker   }
433*7304104dSAndroid Build Coastguard Worker 
434*7304104dSAndroid Build Coastguard Worker   if (unlikely ((main_interp == 0) != (undo_interp == 0)))
435*7304104dSAndroid Build Coastguard Worker     return DWFL_E_BAD_PRELINK;
436*7304104dSAndroid Build Coastguard Worker 
437*7304104dSAndroid Build Coastguard Worker   src.d_buf += src.d_size;
438*7304104dSAndroid Build Coastguard Worker   src.d_type = ELF_T_SHDR;
439*7304104dSAndroid Build Coastguard Worker   src.d_size = gelf_fsize (mod->main.elf, ELF_T_SHDR, shnum, EV_CURRENT);
440*7304104dSAndroid Build Coastguard Worker 
441*7304104dSAndroid Build Coastguard Worker   size_t shdr_size = class32 ? sizeof (Elf32_Shdr) : sizeof (Elf64_Shdr);
442*7304104dSAndroid Build Coastguard Worker   if (unlikely (shnum > SIZE_MAX / shdr_size))
443*7304104dSAndroid Build Coastguard Worker     return DWFL_E_NOMEM;
444*7304104dSAndroid Build Coastguard Worker   const size_t shdrs_bytes = shnum * shdr_size;
445*7304104dSAndroid Build Coastguard Worker   void *shdrs = malloc (shdrs_bytes);
446*7304104dSAndroid Build Coastguard Worker   if (unlikely (shdrs == NULL))
447*7304104dSAndroid Build Coastguard Worker     return DWFL_E_NOMEM;
448*7304104dSAndroid Build Coastguard Worker   dst.d_buf = shdrs;
449*7304104dSAndroid Build Coastguard Worker   dst.d_size = shdrs_bytes;
450*7304104dSAndroid Build Coastguard Worker   if (unlikely (gelf_xlatetom (mod->main.elf, &dst, &src,
451*7304104dSAndroid Build Coastguard Worker 			       ehdr.e32.e_ident[EI_DATA]) == NULL))
452*7304104dSAndroid Build Coastguard Worker     {
453*7304104dSAndroid Build Coastguard Worker       free (shdrs);
454*7304104dSAndroid Build Coastguard Worker       return DWFL_E_LIBELF;
455*7304104dSAndroid Build Coastguard Worker     }
456*7304104dSAndroid Build Coastguard Worker 
457*7304104dSAndroid Build Coastguard Worker   /* Now we can look at the original section headers of the main file
458*7304104dSAndroid Build Coastguard Worker      before it was prelinked.  First we'll apply our method to the main
459*7304104dSAndroid Build Coastguard Worker      file sections as they are after prelinking, to calculate the
460*7304104dSAndroid Build Coastguard Worker      synchronization address of the main file.  Then we'll apply that
461*7304104dSAndroid Build Coastguard Worker      same method to the saved section headers, to calculate the matching
462*7304104dSAndroid Build Coastguard Worker      synchronization address of the debug file.
463*7304104dSAndroid Build Coastguard Worker 
464*7304104dSAndroid Build Coastguard Worker      The method is to consider SHF_ALLOC sections that are either
465*7304104dSAndroid Build Coastguard Worker      SHT_PROGBITS or SHT_NOBITS, excluding the section whose sh_addr
466*7304104dSAndroid Build Coastguard Worker      matches the PT_INTERP p_vaddr.  The special sections that can be
467*7304104dSAndroid Build Coastguard Worker      moved by prelink have other types, except for .interp (which
468*7304104dSAndroid Build Coastguard Worker      becomes PT_INTERP).  The "real" sections cannot move as such, but
469*7304104dSAndroid Build Coastguard Worker      .bss can be split into .dynbss and .bss, with the total memory
470*7304104dSAndroid Build Coastguard Worker      image remaining the same but being spread across the two sections.
471*7304104dSAndroid Build Coastguard Worker      So we consider the highest section end, which still matches up.  */
472*7304104dSAndroid Build Coastguard Worker 
473*7304104dSAndroid Build Coastguard Worker   GElf_Addr highest;
474*7304104dSAndroid Build Coastguard Worker 
475*7304104dSAndroid Build Coastguard Worker   highest = 0;
476*7304104dSAndroid Build Coastguard Worker   scn = NULL;
477*7304104dSAndroid Build Coastguard Worker   while ((scn = elf_nextscn (mod->main.elf, scn)) != NULL)
478*7304104dSAndroid Build Coastguard Worker     {
479*7304104dSAndroid Build Coastguard Worker       GElf_Shdr sh_mem;
480*7304104dSAndroid Build Coastguard Worker       GElf_Shdr *sh = gelf_getshdr (scn, &sh_mem);
481*7304104dSAndroid Build Coastguard Worker       if (unlikely (sh == NULL))
482*7304104dSAndroid Build Coastguard Worker 	{
483*7304104dSAndroid Build Coastguard Worker 	  free (shdrs);
484*7304104dSAndroid Build Coastguard Worker 	  return DWFL_E_LIBELF;
485*7304104dSAndroid Build Coastguard Worker 	}
486*7304104dSAndroid Build Coastguard Worker       consider_shdr (main_interp, sh->sh_type, sh->sh_flags,
487*7304104dSAndroid Build Coastguard Worker 		     sh->sh_addr, sh->sh_size, &highest);
488*7304104dSAndroid Build Coastguard Worker     }
489*7304104dSAndroid Build Coastguard Worker   if (highest > mod->main.vaddr)
490*7304104dSAndroid Build Coastguard Worker     {
491*7304104dSAndroid Build Coastguard Worker       mod->main.address_sync = highest;
492*7304104dSAndroid Build Coastguard Worker 
493*7304104dSAndroid Build Coastguard Worker       highest = 0;
494*7304104dSAndroid Build Coastguard Worker       if (class32)
495*7304104dSAndroid Build Coastguard Worker 	{
496*7304104dSAndroid Build Coastguard Worker 	  Elf32_Shdr (*s32)[shnum] = shdrs;
497*7304104dSAndroid Build Coastguard Worker 	  for (size_t i = 0; i < shnum; ++i)
498*7304104dSAndroid Build Coastguard Worker 	    consider_shdr (undo_interp, (*s32)[i].sh_type,
499*7304104dSAndroid Build Coastguard Worker 			   (*s32)[i].sh_flags, (*s32)[i].sh_addr,
500*7304104dSAndroid Build Coastguard Worker 			   (*s32)[i].sh_size, &highest);
501*7304104dSAndroid Build Coastguard Worker 	}
502*7304104dSAndroid Build Coastguard Worker       else
503*7304104dSAndroid Build Coastguard Worker 	{
504*7304104dSAndroid Build Coastguard Worker 	  Elf64_Shdr (*s64)[shnum] = shdrs;
505*7304104dSAndroid Build Coastguard Worker 	  for (size_t i = 0; i < shnum; ++i)
506*7304104dSAndroid Build Coastguard Worker 	    consider_shdr (undo_interp, (*s64)[i].sh_type,
507*7304104dSAndroid Build Coastguard Worker 			   (*s64)[i].sh_flags, (*s64)[i].sh_addr,
508*7304104dSAndroid Build Coastguard Worker 			   (*s64)[i].sh_size, &highest);
509*7304104dSAndroid Build Coastguard Worker 	}
510*7304104dSAndroid Build Coastguard Worker 
511*7304104dSAndroid Build Coastguard Worker       if (highest > file->vaddr)
512*7304104dSAndroid Build Coastguard Worker 	file->address_sync = highest;
513*7304104dSAndroid Build Coastguard Worker       else
514*7304104dSAndroid Build Coastguard Worker 	{
515*7304104dSAndroid Build Coastguard Worker 	  free (shdrs);
516*7304104dSAndroid Build Coastguard Worker 	  return DWFL_E_BAD_PRELINK;
517*7304104dSAndroid Build Coastguard Worker 	}
518*7304104dSAndroid Build Coastguard Worker     }
519*7304104dSAndroid Build Coastguard Worker 
520*7304104dSAndroid Build Coastguard Worker   free (shdrs);
521*7304104dSAndroid Build Coastguard Worker 
522*7304104dSAndroid Build Coastguard Worker   return DWFL_E_NOERROR;
523*7304104dSAndroid Build Coastguard Worker }
524*7304104dSAndroid Build Coastguard Worker 
525*7304104dSAndroid Build Coastguard Worker /* Find the separate debuginfo file for this module and open libelf on it.
526*7304104dSAndroid Build Coastguard Worker    When we return success, MOD->debug is set up.  */
527*7304104dSAndroid Build Coastguard Worker static Dwfl_Error
find_debuginfo(Dwfl_Module * mod)528*7304104dSAndroid Build Coastguard Worker find_debuginfo (Dwfl_Module *mod)
529*7304104dSAndroid Build Coastguard Worker {
530*7304104dSAndroid Build Coastguard Worker   if (mod->debug.elf != NULL)
531*7304104dSAndroid Build Coastguard Worker     return DWFL_E_NOERROR;
532*7304104dSAndroid Build Coastguard Worker 
533*7304104dSAndroid Build Coastguard Worker   GElf_Word debuglink_crc = 0;
534*7304104dSAndroid Build Coastguard Worker   const char *debuglink_file;
535*7304104dSAndroid Build Coastguard Worker   debuglink_file = INTUSE(dwelf_elf_gnu_debuglink) (mod->main.elf,
536*7304104dSAndroid Build Coastguard Worker 						    &debuglink_crc);
537*7304104dSAndroid Build Coastguard Worker 
538*7304104dSAndroid Build Coastguard Worker   mod->debug.fd = (*mod->dwfl->callbacks->find_debuginfo) (MODCB_ARGS (mod),
539*7304104dSAndroid Build Coastguard Worker 							   mod->main.name,
540*7304104dSAndroid Build Coastguard Worker 							   debuglink_file,
541*7304104dSAndroid Build Coastguard Worker 							   debuglink_crc,
542*7304104dSAndroid Build Coastguard Worker 							   &mod->debug.name);
543*7304104dSAndroid Build Coastguard Worker   Dwfl_Error result = open_elf (mod, &mod->debug);
544*7304104dSAndroid Build Coastguard Worker   if (result == DWFL_E_NOERROR && mod->debug.address_sync != 0)
545*7304104dSAndroid Build Coastguard Worker     result = find_prelink_address_sync (mod, &mod->debug);
546*7304104dSAndroid Build Coastguard Worker   return result;
547*7304104dSAndroid Build Coastguard Worker }
548*7304104dSAndroid Build Coastguard Worker 
549*7304104dSAndroid Build Coastguard Worker /* Try to find the alternative debug link for the given DWARF and set
550*7304104dSAndroid Build Coastguard Worker    it if found.  Only called when mod->dw is already setup but still
551*7304104dSAndroid Build Coastguard Worker    might need an alternative (dwz multi) debug file.  filename is either
552*7304104dSAndroid Build Coastguard Worker    the main or debug name from which the Dwarf was created. */
553*7304104dSAndroid Build Coastguard Worker static void
find_debug_altlink(Dwfl_Module * mod,const char * filename)554*7304104dSAndroid Build Coastguard Worker find_debug_altlink (Dwfl_Module *mod, const char *filename)
555*7304104dSAndroid Build Coastguard Worker {
556*7304104dSAndroid Build Coastguard Worker   assert (mod->dw != NULL);
557*7304104dSAndroid Build Coastguard Worker 
558*7304104dSAndroid Build Coastguard Worker   const char *altname;
559*7304104dSAndroid Build Coastguard Worker   const void *build_id;
560*7304104dSAndroid Build Coastguard Worker   ssize_t build_id_len = INTUSE(dwelf_dwarf_gnu_debugaltlink) (mod->dw,
561*7304104dSAndroid Build Coastguard Worker 							       &altname,
562*7304104dSAndroid Build Coastguard Worker 							       &build_id);
563*7304104dSAndroid Build Coastguard Worker 
564*7304104dSAndroid Build Coastguard Worker   if (build_id_len > 0)
565*7304104dSAndroid Build Coastguard Worker     {
566*7304104dSAndroid Build Coastguard Worker       /* We could store altfile in the module, but don't really need it.  */
567*7304104dSAndroid Build Coastguard Worker       char *altfile = NULL;
568*7304104dSAndroid Build Coastguard Worker       mod->alt_fd = (*mod->dwfl->callbacks->find_debuginfo) (MODCB_ARGS (mod),
569*7304104dSAndroid Build Coastguard Worker 							     filename,
570*7304104dSAndroid Build Coastguard Worker 							     altname,
571*7304104dSAndroid Build Coastguard Worker 							     0,
572*7304104dSAndroid Build Coastguard Worker 							     &altfile);
573*7304104dSAndroid Build Coastguard Worker 
574*7304104dSAndroid Build Coastguard Worker       /* The (internal) callbacks might just set mod->alt_elf directly
575*7304104dSAndroid Build Coastguard Worker 	 because they open the Elf anyway for sanity checking.
576*7304104dSAndroid Build Coastguard Worker 	 Otherwise open either the given file name or use the fd
577*7304104dSAndroid Build Coastguard Worker 	 returned.  */
578*7304104dSAndroid Build Coastguard Worker       Dwfl_Error error = open_elf_file (&mod->alt_elf, &mod->alt_fd,
579*7304104dSAndroid Build Coastguard Worker 					&altfile);
580*7304104dSAndroid Build Coastguard Worker       if (error == DWFL_E_NOERROR)
581*7304104dSAndroid Build Coastguard Worker 	{
582*7304104dSAndroid Build Coastguard Worker 	  mod->alt = INTUSE(dwarf_begin_elf) (mod->alt_elf,
583*7304104dSAndroid Build Coastguard Worker 					      DWARF_C_READ, NULL);
584*7304104dSAndroid Build Coastguard Worker 	  if (mod->alt == NULL)
585*7304104dSAndroid Build Coastguard Worker 	    {
586*7304104dSAndroid Build Coastguard Worker 	      elf_end (mod->alt_elf);
587*7304104dSAndroid Build Coastguard Worker 	      mod->alt_elf = NULL;
588*7304104dSAndroid Build Coastguard Worker 	      close (mod->alt_fd);
589*7304104dSAndroid Build Coastguard Worker 	      mod->alt_fd = -1;
590*7304104dSAndroid Build Coastguard Worker 	    }
591*7304104dSAndroid Build Coastguard Worker 	  else
592*7304104dSAndroid Build Coastguard Worker 	    dwarf_setalt (mod->dw, mod->alt);
593*7304104dSAndroid Build Coastguard Worker 	}
594*7304104dSAndroid Build Coastguard Worker 
595*7304104dSAndroid Build Coastguard Worker       free (altfile); /* See above, we don't really need it.  */
596*7304104dSAndroid Build Coastguard Worker     }
597*7304104dSAndroid Build Coastguard Worker }
598*7304104dSAndroid Build Coastguard Worker 
599*7304104dSAndroid Build Coastguard Worker /* Try to find a symbol table in FILE.
600*7304104dSAndroid Build Coastguard Worker    Returns DWFL_E_NOERROR if a proper one is found.
601*7304104dSAndroid Build Coastguard Worker    Returns DWFL_E_NO_SYMTAB if not, but still sets results for SHT_DYNSYM.  */
602*7304104dSAndroid Build Coastguard Worker static Dwfl_Error
load_symtab(struct dwfl_file * file,struct dwfl_file ** symfile,Elf_Scn ** symscn,Elf_Scn ** xndxscn,size_t * syments,int * first_global,GElf_Word * strshndx)603*7304104dSAndroid Build Coastguard Worker load_symtab (struct dwfl_file *file, struct dwfl_file **symfile,
604*7304104dSAndroid Build Coastguard Worker 	     Elf_Scn **symscn, Elf_Scn **xndxscn,
605*7304104dSAndroid Build Coastguard Worker 	     size_t *syments, int *first_global, GElf_Word *strshndx)
606*7304104dSAndroid Build Coastguard Worker {
607*7304104dSAndroid Build Coastguard Worker   bool symtab = false;
608*7304104dSAndroid Build Coastguard Worker   Elf_Scn *scn = NULL;
609*7304104dSAndroid Build Coastguard Worker   while ((scn = elf_nextscn (file->elf, scn)) != NULL)
610*7304104dSAndroid Build Coastguard Worker     {
611*7304104dSAndroid Build Coastguard Worker       GElf_Shdr shdr_mem, *shdr = gelf_getshdr (scn, &shdr_mem);
612*7304104dSAndroid Build Coastguard Worker       if (shdr != NULL)
613*7304104dSAndroid Build Coastguard Worker 	switch (shdr->sh_type)
614*7304104dSAndroid Build Coastguard Worker 	  {
615*7304104dSAndroid Build Coastguard Worker 	  case SHT_SYMTAB:
616*7304104dSAndroid Build Coastguard Worker 	    if (shdr->sh_entsize == 0)
617*7304104dSAndroid Build Coastguard Worker 	      break;
618*7304104dSAndroid Build Coastguard Worker 	    symtab = true;
619*7304104dSAndroid Build Coastguard Worker 	    *symscn = scn;
620*7304104dSAndroid Build Coastguard Worker 	    *symfile = file;
621*7304104dSAndroid Build Coastguard Worker 	    *strshndx = shdr->sh_link;
622*7304104dSAndroid Build Coastguard Worker 	    *syments = shdr->sh_size / shdr->sh_entsize;
623*7304104dSAndroid Build Coastguard Worker 	    *first_global = shdr->sh_info;
624*7304104dSAndroid Build Coastguard Worker 	    if (*xndxscn != NULL)
625*7304104dSAndroid Build Coastguard Worker 	      return DWFL_E_NOERROR;
626*7304104dSAndroid Build Coastguard Worker 	    break;
627*7304104dSAndroid Build Coastguard Worker 
628*7304104dSAndroid Build Coastguard Worker 	  case SHT_DYNSYM:
629*7304104dSAndroid Build Coastguard Worker 	    if (symtab)
630*7304104dSAndroid Build Coastguard Worker 	      break;
631*7304104dSAndroid Build Coastguard Worker 	    /* Use this if need be, but keep looking for SHT_SYMTAB.  */
632*7304104dSAndroid Build Coastguard Worker 	    if (shdr->sh_entsize == 0)
633*7304104dSAndroid Build Coastguard Worker 	      break;
634*7304104dSAndroid Build Coastguard Worker 	    *symscn = scn;
635*7304104dSAndroid Build Coastguard Worker 	    *symfile = file;
636*7304104dSAndroid Build Coastguard Worker 	    *strshndx = shdr->sh_link;
637*7304104dSAndroid Build Coastguard Worker 	    *syments = shdr->sh_size / shdr->sh_entsize;
638*7304104dSAndroid Build Coastguard Worker 	    *first_global = shdr->sh_info;
639*7304104dSAndroid Build Coastguard Worker 	    break;
640*7304104dSAndroid Build Coastguard Worker 
641*7304104dSAndroid Build Coastguard Worker 	  case SHT_SYMTAB_SHNDX:
642*7304104dSAndroid Build Coastguard Worker 	    *xndxscn = scn;
643*7304104dSAndroid Build Coastguard Worker 	    if (symtab)
644*7304104dSAndroid Build Coastguard Worker 	      return DWFL_E_NOERROR;
645*7304104dSAndroid Build Coastguard Worker 	    break;
646*7304104dSAndroid Build Coastguard Worker 
647*7304104dSAndroid Build Coastguard Worker 	  default:
648*7304104dSAndroid Build Coastguard Worker 	    break;
649*7304104dSAndroid Build Coastguard Worker 	  }
650*7304104dSAndroid Build Coastguard Worker     }
651*7304104dSAndroid Build Coastguard Worker 
652*7304104dSAndroid Build Coastguard Worker   if (symtab)
653*7304104dSAndroid Build Coastguard Worker     /* We found one, though no SHT_SYMTAB_SHNDX to go with it.  */
654*7304104dSAndroid Build Coastguard Worker     return DWFL_E_NOERROR;
655*7304104dSAndroid Build Coastguard Worker 
656*7304104dSAndroid Build Coastguard Worker   /* We found no SHT_SYMTAB, so any SHT_SYMTAB_SHNDX was bogus.
657*7304104dSAndroid Build Coastguard Worker      We might have found an SHT_DYNSYM and set *SYMSCN et al though.  */
658*7304104dSAndroid Build Coastguard Worker   *xndxscn = NULL;
659*7304104dSAndroid Build Coastguard Worker   return DWFL_E_NO_SYMTAB;
660*7304104dSAndroid Build Coastguard Worker }
661*7304104dSAndroid Build Coastguard Worker 
662*7304104dSAndroid Build Coastguard Worker 
663*7304104dSAndroid Build Coastguard Worker /* Translate addresses into file offsets.
664*7304104dSAndroid Build Coastguard Worker    OFFS[*] start out zero and remain zero if unresolved.  */
665*7304104dSAndroid Build Coastguard Worker static void
find_offsets(Elf * elf,GElf_Addr main_bias,size_t phnum,size_t n,GElf_Addr addrs[n],GElf_Off offs[n])666*7304104dSAndroid Build Coastguard Worker find_offsets (Elf *elf, GElf_Addr main_bias, size_t phnum, size_t n,
667*7304104dSAndroid Build Coastguard Worker 	      GElf_Addr addrs[n], GElf_Off offs[n])
668*7304104dSAndroid Build Coastguard Worker {
669*7304104dSAndroid Build Coastguard Worker   size_t unsolved = n;
670*7304104dSAndroid Build Coastguard Worker   for (size_t i = 0; i < phnum; ++i)
671*7304104dSAndroid Build Coastguard Worker     {
672*7304104dSAndroid Build Coastguard Worker       GElf_Phdr phdr_mem;
673*7304104dSAndroid Build Coastguard Worker       GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem);
674*7304104dSAndroid Build Coastguard Worker       if (phdr != NULL && phdr->p_type == PT_LOAD && phdr->p_memsz > 0)
675*7304104dSAndroid Build Coastguard Worker 	for (size_t j = 0; j < n; ++j)
676*7304104dSAndroid Build Coastguard Worker 	  if (offs[j] == 0
677*7304104dSAndroid Build Coastguard Worker 	      && addrs[j] >= phdr->p_vaddr + main_bias
678*7304104dSAndroid Build Coastguard Worker 	      && addrs[j] - (phdr->p_vaddr + main_bias) < phdr->p_filesz)
679*7304104dSAndroid Build Coastguard Worker 	    {
680*7304104dSAndroid Build Coastguard Worker 	      offs[j] = addrs[j] - (phdr->p_vaddr + main_bias) + phdr->p_offset;
681*7304104dSAndroid Build Coastguard Worker 	      if (--unsolved == 0)
682*7304104dSAndroid Build Coastguard Worker 		break;
683*7304104dSAndroid Build Coastguard Worker 	    }
684*7304104dSAndroid Build Coastguard Worker     }
685*7304104dSAndroid Build Coastguard Worker }
686*7304104dSAndroid Build Coastguard Worker 
687*7304104dSAndroid Build Coastguard Worker /* Various addresses we might want to pull from the dynamic segment.  */
688*7304104dSAndroid Build Coastguard Worker enum
689*7304104dSAndroid Build Coastguard Worker {
690*7304104dSAndroid Build Coastguard Worker   i_symtab,
691*7304104dSAndroid Build Coastguard Worker   i_strtab,
692*7304104dSAndroid Build Coastguard Worker   i_hash,
693*7304104dSAndroid Build Coastguard Worker   i_gnu_hash,
694*7304104dSAndroid Build Coastguard Worker   i_max
695*7304104dSAndroid Build Coastguard Worker };
696*7304104dSAndroid Build Coastguard Worker 
697*7304104dSAndroid Build Coastguard Worker /* Translate pointers into file offsets.  ADJUST is either zero
698*7304104dSAndroid Build Coastguard Worker    in case the dynamic segment wasn't adjusted or mod->main_bias.
699*7304104dSAndroid Build Coastguard Worker    Will set mod->symfile if the translated offsets can be used as
700*7304104dSAndroid Build Coastguard Worker    symbol table.  */
701*7304104dSAndroid Build Coastguard Worker static void
translate_offs(GElf_Addr adjust,Dwfl_Module * mod,size_t phnum,GElf_Addr addrs[i_max],GElf_Xword strsz,GElf_Ehdr * ehdr)702*7304104dSAndroid Build Coastguard Worker translate_offs (GElf_Addr adjust,
703*7304104dSAndroid Build Coastguard Worker                 Dwfl_Module *mod, size_t phnum,
704*7304104dSAndroid Build Coastguard Worker                 GElf_Addr addrs[i_max], GElf_Xword strsz,
705*7304104dSAndroid Build Coastguard Worker                 GElf_Ehdr *ehdr)
706*7304104dSAndroid Build Coastguard Worker {
707*7304104dSAndroid Build Coastguard Worker   GElf_Off offs[i_max] = { 0, };
708*7304104dSAndroid Build Coastguard Worker   find_offsets (mod->main.elf, adjust, phnum, i_max, addrs, offs);
709*7304104dSAndroid Build Coastguard Worker 
710*7304104dSAndroid Build Coastguard Worker   /* Figure out the size of the symbol table.  */
711*7304104dSAndroid Build Coastguard Worker   if (offs[i_hash] != 0)
712*7304104dSAndroid Build Coastguard Worker     {
713*7304104dSAndroid Build Coastguard Worker       /* In the original format, .hash says the size of .dynsym.  */
714*7304104dSAndroid Build Coastguard Worker 
715*7304104dSAndroid Build Coastguard Worker       size_t entsz = SH_ENTSIZE_HASH (ehdr);
716*7304104dSAndroid Build Coastguard Worker       Elf_Data *data = elf_getdata_rawchunk (mod->main.elf,
717*7304104dSAndroid Build Coastguard Worker 					     offs[i_hash] + entsz, entsz,
718*7304104dSAndroid Build Coastguard Worker 					     (entsz == 4
719*7304104dSAndroid Build Coastguard Worker 					      ? ELF_T_WORD : ELF_T_XWORD));
720*7304104dSAndroid Build Coastguard Worker       if (data != NULL)
721*7304104dSAndroid Build Coastguard Worker 	mod->syments = (entsz == 4
722*7304104dSAndroid Build Coastguard Worker 			? *(const GElf_Word *) data->d_buf
723*7304104dSAndroid Build Coastguard Worker 			: *(const GElf_Xword *) data->d_buf);
724*7304104dSAndroid Build Coastguard Worker     }
725*7304104dSAndroid Build Coastguard Worker   if (offs[i_gnu_hash] != 0 && mod->syments == 0)
726*7304104dSAndroid Build Coastguard Worker     {
727*7304104dSAndroid Build Coastguard Worker       /* In the new format, we can derive it with some work.  */
728*7304104dSAndroid Build Coastguard Worker 
729*7304104dSAndroid Build Coastguard Worker       const struct
730*7304104dSAndroid Build Coastguard Worker       {
731*7304104dSAndroid Build Coastguard Worker         Elf32_Word nbuckets;
732*7304104dSAndroid Build Coastguard Worker         Elf32_Word symndx;
733*7304104dSAndroid Build Coastguard Worker         Elf32_Word maskwords;
734*7304104dSAndroid Build Coastguard Worker         Elf32_Word shift2;
735*7304104dSAndroid Build Coastguard Worker       } *header;
736*7304104dSAndroid Build Coastguard Worker 
737*7304104dSAndroid Build Coastguard Worker       Elf_Data *data = elf_getdata_rawchunk (mod->main.elf, offs[i_gnu_hash],
738*7304104dSAndroid Build Coastguard Worker 					     sizeof *header, ELF_T_WORD);
739*7304104dSAndroid Build Coastguard Worker       if (data != NULL)
740*7304104dSAndroid Build Coastguard Worker         {
741*7304104dSAndroid Build Coastguard Worker           header = data->d_buf;
742*7304104dSAndroid Build Coastguard Worker           Elf32_Word nbuckets = header->nbuckets;
743*7304104dSAndroid Build Coastguard Worker           Elf32_Word symndx = header->symndx;
744*7304104dSAndroid Build Coastguard Worker           GElf_Off buckets_at = (offs[i_gnu_hash] + sizeof *header
745*7304104dSAndroid Build Coastguard Worker 				 + (gelf_getclass (mod->main.elf)
746*7304104dSAndroid Build Coastguard Worker 				    * sizeof (Elf32_Word)
747*7304104dSAndroid Build Coastguard Worker 				    * header->maskwords));
748*7304104dSAndroid Build Coastguard Worker 
749*7304104dSAndroid Build Coastguard Worker           // elf_getdata_rawchunk takes a size_t, make sure it
750*7304104dSAndroid Build Coastguard Worker           // doesn't overflow.
751*7304104dSAndroid Build Coastguard Worker #if SIZE_MAX <= UINT32_MAX
752*7304104dSAndroid Build Coastguard Worker           if (nbuckets > SIZE_MAX / sizeof (Elf32_Word))
753*7304104dSAndroid Build Coastguard Worker             data = NULL;
754*7304104dSAndroid Build Coastguard Worker           else
755*7304104dSAndroid Build Coastguard Worker #endif
756*7304104dSAndroid Build Coastguard Worker             data = elf_getdata_rawchunk (mod->main.elf, buckets_at,
757*7304104dSAndroid Build Coastguard Worker 					   nbuckets * sizeof (Elf32_Word),
758*7304104dSAndroid Build Coastguard Worker 					   ELF_T_WORD);
759*7304104dSAndroid Build Coastguard Worker 	  if (data != NULL && symndx < nbuckets)
760*7304104dSAndroid Build Coastguard Worker 	    {
761*7304104dSAndroid Build Coastguard Worker 	      const Elf32_Word *const buckets = data->d_buf;
762*7304104dSAndroid Build Coastguard Worker 	      Elf32_Word maxndx = symndx;
763*7304104dSAndroid Build Coastguard Worker 	      for (Elf32_Word bucket = 0; bucket < nbuckets; ++bucket)
764*7304104dSAndroid Build Coastguard Worker 		if (buckets[bucket] > maxndx)
765*7304104dSAndroid Build Coastguard Worker 		  maxndx = buckets[bucket];
766*7304104dSAndroid Build Coastguard Worker 
767*7304104dSAndroid Build Coastguard Worker 	      GElf_Off hasharr_at = (buckets_at
768*7304104dSAndroid Build Coastguard Worker 				     + nbuckets * sizeof (Elf32_Word));
769*7304104dSAndroid Build Coastguard Worker 	      hasharr_at += (maxndx - symndx) * sizeof (Elf32_Word);
770*7304104dSAndroid Build Coastguard Worker 	      do
771*7304104dSAndroid Build Coastguard Worker 		{
772*7304104dSAndroid Build Coastguard Worker 		  data = elf_getdata_rawchunk (mod->main.elf,
773*7304104dSAndroid Build Coastguard Worker 					       hasharr_at,
774*7304104dSAndroid Build Coastguard Worker 					       sizeof (Elf32_Word),
775*7304104dSAndroid Build Coastguard Worker 					       ELF_T_WORD);
776*7304104dSAndroid Build Coastguard Worker 		  if (data != NULL
777*7304104dSAndroid Build Coastguard Worker 		      && (*(const Elf32_Word *) data->d_buf & 1u))
778*7304104dSAndroid Build Coastguard Worker 		    {
779*7304104dSAndroid Build Coastguard Worker 		      mod->syments = maxndx + 1;
780*7304104dSAndroid Build Coastguard Worker 		      break;
781*7304104dSAndroid Build Coastguard Worker 		    }
782*7304104dSAndroid Build Coastguard Worker 		  ++maxndx;
783*7304104dSAndroid Build Coastguard Worker 		  hasharr_at += sizeof (Elf32_Word);
784*7304104dSAndroid Build Coastguard Worker 		}
785*7304104dSAndroid Build Coastguard Worker 	      while (data != NULL);
786*7304104dSAndroid Build Coastguard Worker 	    }
787*7304104dSAndroid Build Coastguard Worker 	}
788*7304104dSAndroid Build Coastguard Worker     }
789*7304104dSAndroid Build Coastguard Worker   if (offs[i_strtab] > offs[i_symtab] && mod->syments == 0)
790*7304104dSAndroid Build Coastguard Worker     mod->syments = ((offs[i_strtab] - offs[i_symtab])
791*7304104dSAndroid Build Coastguard Worker 		    / gelf_fsize (mod->main.elf,
792*7304104dSAndroid Build Coastguard Worker 				  ELF_T_SYM, 1, EV_CURRENT));
793*7304104dSAndroid Build Coastguard Worker 
794*7304104dSAndroid Build Coastguard Worker   if (mod->syments > 0)
795*7304104dSAndroid Build Coastguard Worker     {
796*7304104dSAndroid Build Coastguard Worker       mod->symdata = elf_getdata_rawchunk (mod->main.elf,
797*7304104dSAndroid Build Coastguard Worker 					   offs[i_symtab],
798*7304104dSAndroid Build Coastguard Worker 					   gelf_fsize (mod->main.elf,
799*7304104dSAndroid Build Coastguard Worker 						       ELF_T_SYM,
800*7304104dSAndroid Build Coastguard Worker 						       mod->syments,
801*7304104dSAndroid Build Coastguard Worker 						       EV_CURRENT),
802*7304104dSAndroid Build Coastguard Worker 						       ELF_T_SYM);
803*7304104dSAndroid Build Coastguard Worker       if (mod->symdata != NULL)
804*7304104dSAndroid Build Coastguard Worker 	{
805*7304104dSAndroid Build Coastguard Worker 	  mod->symstrdata = elf_getdata_rawchunk (mod->main.elf,
806*7304104dSAndroid Build Coastguard Worker 						  offs[i_strtab],
807*7304104dSAndroid Build Coastguard Worker 						  strsz,
808*7304104dSAndroid Build Coastguard Worker 						  ELF_T_BYTE);
809*7304104dSAndroid Build Coastguard Worker 	  if (mod->symstrdata == NULL)
810*7304104dSAndroid Build Coastguard Worker 	    mod->symdata = NULL;
811*7304104dSAndroid Build Coastguard Worker 	}
812*7304104dSAndroid Build Coastguard Worker       if (mod->symdata == NULL)
813*7304104dSAndroid Build Coastguard Worker 	mod->symerr = DWFL_E (LIBELF, elf_errno ());
814*7304104dSAndroid Build Coastguard Worker       else
815*7304104dSAndroid Build Coastguard Worker 	{
816*7304104dSAndroid Build Coastguard Worker 	  mod->symfile = &mod->main;
817*7304104dSAndroid Build Coastguard Worker 	  mod->symerr = DWFL_E_NOERROR;
818*7304104dSAndroid Build Coastguard Worker 	}
819*7304104dSAndroid Build Coastguard Worker     }
820*7304104dSAndroid Build Coastguard Worker }
821*7304104dSAndroid Build Coastguard Worker 
822*7304104dSAndroid Build Coastguard Worker /* Try to find a dynamic symbol table via phdrs.  */
823*7304104dSAndroid Build Coastguard Worker static void
find_dynsym(Dwfl_Module * mod)824*7304104dSAndroid Build Coastguard Worker find_dynsym (Dwfl_Module *mod)
825*7304104dSAndroid Build Coastguard Worker {
826*7304104dSAndroid Build Coastguard Worker   GElf_Ehdr ehdr_mem;
827*7304104dSAndroid Build Coastguard Worker   GElf_Ehdr *ehdr = gelf_getehdr (mod->main.elf, &ehdr_mem);
828*7304104dSAndroid Build Coastguard Worker 
829*7304104dSAndroid Build Coastguard Worker   size_t phnum;
830*7304104dSAndroid Build Coastguard Worker   if (unlikely (elf_getphdrnum (mod->main.elf, &phnum) != 0))
831*7304104dSAndroid Build Coastguard Worker     return;
832*7304104dSAndroid Build Coastguard Worker 
833*7304104dSAndroid Build Coastguard Worker   for (size_t i = 0; i < phnum; ++i)
834*7304104dSAndroid Build Coastguard Worker     {
835*7304104dSAndroid Build Coastguard Worker       GElf_Phdr phdr_mem;
836*7304104dSAndroid Build Coastguard Worker       GElf_Phdr *phdr = gelf_getphdr (mod->main.elf, i, &phdr_mem);
837*7304104dSAndroid Build Coastguard Worker       if (phdr == NULL)
838*7304104dSAndroid Build Coastguard Worker 	break;
839*7304104dSAndroid Build Coastguard Worker 
840*7304104dSAndroid Build Coastguard Worker       if (phdr->p_type == PT_DYNAMIC)
841*7304104dSAndroid Build Coastguard Worker 	{
842*7304104dSAndroid Build Coastguard Worker 	  /* Examine the dynamic section for the pointers we need.  */
843*7304104dSAndroid Build Coastguard Worker 
844*7304104dSAndroid Build Coastguard Worker 	  Elf_Data *data = elf_getdata_rawchunk (mod->main.elf,
845*7304104dSAndroid Build Coastguard Worker 						 phdr->p_offset, phdr->p_filesz,
846*7304104dSAndroid Build Coastguard Worker 						 ELF_T_DYN);
847*7304104dSAndroid Build Coastguard Worker 	  if (data == NULL)
848*7304104dSAndroid Build Coastguard Worker 	    continue;
849*7304104dSAndroid Build Coastguard Worker 
850*7304104dSAndroid Build Coastguard Worker 	  GElf_Addr addrs[i_max] = { 0, };
851*7304104dSAndroid Build Coastguard Worker 	  GElf_Xword strsz = 0;
852*7304104dSAndroid Build Coastguard Worker 	  size_t n = data->d_size / gelf_fsize (mod->main.elf,
853*7304104dSAndroid Build Coastguard Worker 						ELF_T_DYN, 1, EV_CURRENT);
854*7304104dSAndroid Build Coastguard Worker 	  for (size_t j = 0; j < n; ++j)
855*7304104dSAndroid Build Coastguard Worker 	    {
856*7304104dSAndroid Build Coastguard Worker 	      GElf_Dyn dyn_mem;
857*7304104dSAndroid Build Coastguard Worker 	      GElf_Dyn *dyn = gelf_getdyn (data, j, &dyn_mem);
858*7304104dSAndroid Build Coastguard Worker 	      if (dyn != NULL)
859*7304104dSAndroid Build Coastguard Worker 		switch (dyn->d_tag)
860*7304104dSAndroid Build Coastguard Worker 		  {
861*7304104dSAndroid Build Coastguard Worker 		  case DT_SYMTAB:
862*7304104dSAndroid Build Coastguard Worker 		    addrs[i_symtab] = dyn->d_un.d_ptr;
863*7304104dSAndroid Build Coastguard Worker 		    continue;
864*7304104dSAndroid Build Coastguard Worker 
865*7304104dSAndroid Build Coastguard Worker 		  case DT_HASH:
866*7304104dSAndroid Build Coastguard Worker 		    addrs[i_hash] = dyn->d_un.d_ptr;
867*7304104dSAndroid Build Coastguard Worker 		    continue;
868*7304104dSAndroid Build Coastguard Worker 
869*7304104dSAndroid Build Coastguard Worker 		  case DT_GNU_HASH:
870*7304104dSAndroid Build Coastguard Worker 		    addrs[i_gnu_hash] = dyn->d_un.d_ptr;
871*7304104dSAndroid Build Coastguard Worker 		    continue;
872*7304104dSAndroid Build Coastguard Worker 
873*7304104dSAndroid Build Coastguard Worker 		  case DT_STRTAB:
874*7304104dSAndroid Build Coastguard Worker 		    addrs[i_strtab] = dyn->d_un.d_ptr;
875*7304104dSAndroid Build Coastguard Worker 		    continue;
876*7304104dSAndroid Build Coastguard Worker 
877*7304104dSAndroid Build Coastguard Worker 		  case DT_STRSZ:
878*7304104dSAndroid Build Coastguard Worker 		    strsz = dyn->d_un.d_val;
879*7304104dSAndroid Build Coastguard Worker 		    continue;
880*7304104dSAndroid Build Coastguard Worker 
881*7304104dSAndroid Build Coastguard Worker 		  default:
882*7304104dSAndroid Build Coastguard Worker 		    continue;
883*7304104dSAndroid Build Coastguard Worker 
884*7304104dSAndroid Build Coastguard Worker 		  case DT_NULL:
885*7304104dSAndroid Build Coastguard Worker 		    break;
886*7304104dSAndroid Build Coastguard Worker 		  }
887*7304104dSAndroid Build Coastguard Worker 	      break;
888*7304104dSAndroid Build Coastguard Worker 	    }
889*7304104dSAndroid Build Coastguard Worker 
890*7304104dSAndroid Build Coastguard Worker 	  /* First try unadjusted, like ELF files from disk, vdso.
891*7304104dSAndroid Build Coastguard Worker 	     Then try for already adjusted dynamic section, like ELF
892*7304104dSAndroid Build Coastguard Worker 	     from remote memory.  */
893*7304104dSAndroid Build Coastguard Worker 	  translate_offs (0, mod, phnum, addrs, strsz, ehdr);
894*7304104dSAndroid Build Coastguard Worker 	  if (mod->symfile == NULL)
895*7304104dSAndroid Build Coastguard Worker 	    translate_offs (mod->main_bias, mod, phnum, addrs, strsz, ehdr);
896*7304104dSAndroid Build Coastguard Worker 
897*7304104dSAndroid Build Coastguard Worker 	  return;
898*7304104dSAndroid Build Coastguard Worker 	}
899*7304104dSAndroid Build Coastguard Worker     }
900*7304104dSAndroid Build Coastguard Worker }
901*7304104dSAndroid Build Coastguard Worker 
902*7304104dSAndroid Build Coastguard Worker 
903*7304104dSAndroid Build Coastguard Worker #if USE_LZMA
904*7304104dSAndroid Build Coastguard Worker /* Try to find the offset between the main file and .gnu_debugdata.  */
905*7304104dSAndroid Build Coastguard Worker static bool
find_aux_address_sync(Dwfl_Module * mod)906*7304104dSAndroid Build Coastguard Worker find_aux_address_sync (Dwfl_Module *mod)
907*7304104dSAndroid Build Coastguard Worker {
908*7304104dSAndroid Build Coastguard Worker   /* Don't trust the phdrs in the minisymtab elf file to be setup correctly.
909*7304104dSAndroid Build Coastguard Worker      The address_sync is equal to the main file it is embedded in at first.  */
910*7304104dSAndroid Build Coastguard Worker   mod->aux_sym.address_sync = mod->main.address_sync;
911*7304104dSAndroid Build Coastguard Worker 
912*7304104dSAndroid Build Coastguard Worker   /* Adjust address_sync for the difference in entry addresses, attempting to
913*7304104dSAndroid Build Coastguard Worker      account for ELF relocation changes after aux was split.  */
914*7304104dSAndroid Build Coastguard Worker   GElf_Ehdr ehdr_main, ehdr_aux;
915*7304104dSAndroid Build Coastguard Worker   if (unlikely (gelf_getehdr (mod->main.elf, &ehdr_main) == NULL)
916*7304104dSAndroid Build Coastguard Worker       || unlikely (gelf_getehdr (mod->aux_sym.elf, &ehdr_aux) == NULL))
917*7304104dSAndroid Build Coastguard Worker     return false;
918*7304104dSAndroid Build Coastguard Worker   mod->aux_sym.address_sync += ehdr_aux.e_entry - ehdr_main.e_entry;
919*7304104dSAndroid Build Coastguard Worker 
920*7304104dSAndroid Build Coastguard Worker   /* The shdrs are setup OK to make find_prelink_address_sync () do the right
921*7304104dSAndroid Build Coastguard Worker      thing, which is possibly more reliable, but it needs .gnu.prelink_undo.  */
922*7304104dSAndroid Build Coastguard Worker   if (mod->aux_sym.address_sync != 0)
923*7304104dSAndroid Build Coastguard Worker     return find_prelink_address_sync (mod, &mod->aux_sym) == DWFL_E_NOERROR;
924*7304104dSAndroid Build Coastguard Worker 
925*7304104dSAndroid Build Coastguard Worker   return true;
926*7304104dSAndroid Build Coastguard Worker }
927*7304104dSAndroid Build Coastguard Worker #endif
928*7304104dSAndroid Build Coastguard Worker 
929*7304104dSAndroid Build Coastguard Worker /* Try to find the auxiliary symbol table embedded in the main elf file
930*7304104dSAndroid Build Coastguard Worker    section .gnu_debugdata.  Only matters if the symbol information comes
931*7304104dSAndroid Build Coastguard Worker    from the main file dynsym.  No harm done if not found.  */
932*7304104dSAndroid Build Coastguard Worker static void
find_aux_sym(Dwfl_Module * mod,Elf_Scn ** aux_symscn,Elf_Scn ** aux_xndxscn,GElf_Word * aux_strshndx)933*7304104dSAndroid Build Coastguard Worker find_aux_sym (Dwfl_Module *mod __attribute__ ((unused)),
934*7304104dSAndroid Build Coastguard Worker 	      Elf_Scn **aux_symscn __attribute__ ((unused)),
935*7304104dSAndroid Build Coastguard Worker 	      Elf_Scn **aux_xndxscn __attribute__ ((unused)),
936*7304104dSAndroid Build Coastguard Worker 	      GElf_Word *aux_strshndx __attribute__ ((unused)))
937*7304104dSAndroid Build Coastguard Worker {
938*7304104dSAndroid Build Coastguard Worker   /* Since a .gnu_debugdata section is compressed using lzma don't do
939*7304104dSAndroid Build Coastguard Worker      anything unless we have support for that.  */
940*7304104dSAndroid Build Coastguard Worker #if USE_LZMA
941*7304104dSAndroid Build Coastguard Worker   Elf *elf = mod->main.elf;
942*7304104dSAndroid Build Coastguard Worker 
943*7304104dSAndroid Build Coastguard Worker   size_t shstrndx;
944*7304104dSAndroid Build Coastguard Worker   if (elf_getshdrstrndx (elf, &shstrndx) < 0)
945*7304104dSAndroid Build Coastguard Worker     return;
946*7304104dSAndroid Build Coastguard Worker 
947*7304104dSAndroid Build Coastguard Worker   Elf_Scn *scn = NULL;
948*7304104dSAndroid Build Coastguard Worker   while ((scn = elf_nextscn (elf, scn)) != NULL)
949*7304104dSAndroid Build Coastguard Worker     {
950*7304104dSAndroid Build Coastguard Worker       GElf_Shdr shdr_mem;
951*7304104dSAndroid Build Coastguard Worker       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
952*7304104dSAndroid Build Coastguard Worker       if (shdr == NULL)
953*7304104dSAndroid Build Coastguard Worker 	return;
954*7304104dSAndroid Build Coastguard Worker 
955*7304104dSAndroid Build Coastguard Worker       const char *name = elf_strptr (elf, shstrndx, shdr->sh_name);
956*7304104dSAndroid Build Coastguard Worker       if (name == NULL)
957*7304104dSAndroid Build Coastguard Worker 	return;
958*7304104dSAndroid Build Coastguard Worker 
959*7304104dSAndroid Build Coastguard Worker       if (!strcmp (name, ".gnu_debugdata"))
960*7304104dSAndroid Build Coastguard Worker 	break;
961*7304104dSAndroid Build Coastguard Worker     }
962*7304104dSAndroid Build Coastguard Worker 
963*7304104dSAndroid Build Coastguard Worker   if (scn == NULL)
964*7304104dSAndroid Build Coastguard Worker     return;
965*7304104dSAndroid Build Coastguard Worker 
966*7304104dSAndroid Build Coastguard Worker   /* Found the .gnu_debugdata section.  Uncompress the lzma image and
967*7304104dSAndroid Build Coastguard Worker      turn it into an ELF image.  */
968*7304104dSAndroid Build Coastguard Worker   Elf_Data *rawdata = elf_rawdata (scn, NULL);
969*7304104dSAndroid Build Coastguard Worker   if (rawdata == NULL)
970*7304104dSAndroid Build Coastguard Worker     return;
971*7304104dSAndroid Build Coastguard Worker 
972*7304104dSAndroid Build Coastguard Worker   Dwfl_Error error;
973*7304104dSAndroid Build Coastguard Worker   void *buffer = NULL;
974*7304104dSAndroid Build Coastguard Worker   size_t size = 0;
975*7304104dSAndroid Build Coastguard Worker   error = __libdw_unlzma (-1, 0, rawdata->d_buf, rawdata->d_size,
976*7304104dSAndroid Build Coastguard Worker 			  &buffer, &size);
977*7304104dSAndroid Build Coastguard Worker   if (error == DWFL_E_NOERROR)
978*7304104dSAndroid Build Coastguard Worker     {
979*7304104dSAndroid Build Coastguard Worker       if (unlikely (size == 0))
980*7304104dSAndroid Build Coastguard Worker 	free (buffer);
981*7304104dSAndroid Build Coastguard Worker       else
982*7304104dSAndroid Build Coastguard Worker 	{
983*7304104dSAndroid Build Coastguard Worker 	  mod->aux_sym.elf = elf_memory (buffer, size);
984*7304104dSAndroid Build Coastguard Worker 	  if (mod->aux_sym.elf == NULL)
985*7304104dSAndroid Build Coastguard Worker 	    free (buffer);
986*7304104dSAndroid Build Coastguard Worker 	  else
987*7304104dSAndroid Build Coastguard Worker 	    {
988*7304104dSAndroid Build Coastguard Worker 	      mod->aux_sym.fd = -1;
989*7304104dSAndroid Build Coastguard Worker 	      mod->aux_sym.elf->flags |= ELF_F_MALLOCED;
990*7304104dSAndroid Build Coastguard Worker 	      if (open_elf (mod, &mod->aux_sym) != DWFL_E_NOERROR)
991*7304104dSAndroid Build Coastguard Worker 		return;
992*7304104dSAndroid Build Coastguard Worker 	      if (! find_aux_address_sync (mod))
993*7304104dSAndroid Build Coastguard Worker 		{
994*7304104dSAndroid Build Coastguard Worker 		  elf_end (mod->aux_sym.elf);
995*7304104dSAndroid Build Coastguard Worker 		  mod->aux_sym.elf = NULL;
996*7304104dSAndroid Build Coastguard Worker 		  return;
997*7304104dSAndroid Build Coastguard Worker 		}
998*7304104dSAndroid Build Coastguard Worker 
999*7304104dSAndroid Build Coastguard Worker 	      /* So far, so good. Get minisymtab table data and cache it. */
1000*7304104dSAndroid Build Coastguard Worker 	      bool minisymtab = false;
1001*7304104dSAndroid Build Coastguard Worker 	      scn = NULL;
1002*7304104dSAndroid Build Coastguard Worker 	      while ((scn = elf_nextscn (mod->aux_sym.elf, scn)) != NULL)
1003*7304104dSAndroid Build Coastguard Worker 		{
1004*7304104dSAndroid Build Coastguard Worker 		  GElf_Shdr shdr_mem, *shdr = gelf_getshdr (scn, &shdr_mem);
1005*7304104dSAndroid Build Coastguard Worker 		  if (shdr != NULL)
1006*7304104dSAndroid Build Coastguard Worker 		    switch (shdr->sh_type)
1007*7304104dSAndroid Build Coastguard Worker 		      {
1008*7304104dSAndroid Build Coastguard Worker 		      case SHT_SYMTAB:
1009*7304104dSAndroid Build Coastguard Worker 			if (shdr->sh_entsize == 0)
1010*7304104dSAndroid Build Coastguard Worker 			  return;
1011*7304104dSAndroid Build Coastguard Worker 			minisymtab = true;
1012*7304104dSAndroid Build Coastguard Worker 			*aux_symscn = scn;
1013*7304104dSAndroid Build Coastguard Worker 			*aux_strshndx = shdr->sh_link;
1014*7304104dSAndroid Build Coastguard Worker 			mod->aux_syments = shdr->sh_size / shdr->sh_entsize;
1015*7304104dSAndroid Build Coastguard Worker 			mod->aux_first_global = shdr->sh_info;
1016*7304104dSAndroid Build Coastguard Worker 			if (*aux_xndxscn != NULL)
1017*7304104dSAndroid Build Coastguard Worker 			  return;
1018*7304104dSAndroid Build Coastguard Worker 			break;
1019*7304104dSAndroid Build Coastguard Worker 
1020*7304104dSAndroid Build Coastguard Worker 		      case SHT_SYMTAB_SHNDX:
1021*7304104dSAndroid Build Coastguard Worker 			*aux_xndxscn = scn;
1022*7304104dSAndroid Build Coastguard Worker 			if (minisymtab)
1023*7304104dSAndroid Build Coastguard Worker 			  return;
1024*7304104dSAndroid Build Coastguard Worker 			break;
1025*7304104dSAndroid Build Coastguard Worker 
1026*7304104dSAndroid Build Coastguard Worker 		      default:
1027*7304104dSAndroid Build Coastguard Worker 			break;
1028*7304104dSAndroid Build Coastguard Worker 		      }
1029*7304104dSAndroid Build Coastguard Worker 		}
1030*7304104dSAndroid Build Coastguard Worker 
1031*7304104dSAndroid Build Coastguard Worker 	      if (minisymtab)
1032*7304104dSAndroid Build Coastguard Worker 		/* We found one, though no SHT_SYMTAB_SHNDX to go with it.  */
1033*7304104dSAndroid Build Coastguard Worker 		return;
1034*7304104dSAndroid Build Coastguard Worker 
1035*7304104dSAndroid Build Coastguard Worker 	      /* We found no SHT_SYMTAB, so everything else is bogus.  */
1036*7304104dSAndroid Build Coastguard Worker 	      *aux_xndxscn = NULL;
1037*7304104dSAndroid Build Coastguard Worker 	      *aux_strshndx = 0;
1038*7304104dSAndroid Build Coastguard Worker 	      mod->aux_syments = 0;
1039*7304104dSAndroid Build Coastguard Worker 	      elf_end (mod->aux_sym.elf);
1040*7304104dSAndroid Build Coastguard Worker 	      mod->aux_sym.elf = NULL;
1041*7304104dSAndroid Build Coastguard Worker 	      return;
1042*7304104dSAndroid Build Coastguard Worker 	    }
1043*7304104dSAndroid Build Coastguard Worker 	}
1044*7304104dSAndroid Build Coastguard Worker     }
1045*7304104dSAndroid Build Coastguard Worker   else
1046*7304104dSAndroid Build Coastguard Worker     free (buffer);
1047*7304104dSAndroid Build Coastguard Worker #endif
1048*7304104dSAndroid Build Coastguard Worker }
1049*7304104dSAndroid Build Coastguard Worker 
1050*7304104dSAndroid Build Coastguard Worker /* Try to find a symbol table in either MOD->main.elf or MOD->debug.elf.  */
1051*7304104dSAndroid Build Coastguard Worker static void
find_symtab(Dwfl_Module * mod)1052*7304104dSAndroid Build Coastguard Worker find_symtab (Dwfl_Module *mod)
1053*7304104dSAndroid Build Coastguard Worker {
1054*7304104dSAndroid Build Coastguard Worker   if (mod->symdata != NULL || mod->aux_symdata != NULL	/* Already done.  */
1055*7304104dSAndroid Build Coastguard Worker       || mod->symerr != DWFL_E_NOERROR) /* Cached previous failure.  */
1056*7304104dSAndroid Build Coastguard Worker     return;
1057*7304104dSAndroid Build Coastguard Worker 
1058*7304104dSAndroid Build Coastguard Worker   __libdwfl_getelf (mod);
1059*7304104dSAndroid Build Coastguard Worker   mod->symerr = mod->elferr;
1060*7304104dSAndroid Build Coastguard Worker   if (mod->symerr != DWFL_E_NOERROR)
1061*7304104dSAndroid Build Coastguard Worker     return;
1062*7304104dSAndroid Build Coastguard Worker 
1063*7304104dSAndroid Build Coastguard Worker   /* First see if the main ELF file has the debugging information.  */
1064*7304104dSAndroid Build Coastguard Worker   Elf_Scn *symscn = NULL, *xndxscn = NULL;
1065*7304104dSAndroid Build Coastguard Worker   Elf_Scn *aux_symscn = NULL, *aux_xndxscn = NULL;
1066*7304104dSAndroid Build Coastguard Worker   GElf_Word strshndx, aux_strshndx = 0;
1067*7304104dSAndroid Build Coastguard Worker   mod->symerr = load_symtab (&mod->main, &mod->symfile, &symscn,
1068*7304104dSAndroid Build Coastguard Worker 			     &xndxscn, &mod->syments, &mod->first_global,
1069*7304104dSAndroid Build Coastguard Worker 			     &strshndx);
1070*7304104dSAndroid Build Coastguard Worker   switch (mod->symerr)
1071*7304104dSAndroid Build Coastguard Worker     {
1072*7304104dSAndroid Build Coastguard Worker     default:
1073*7304104dSAndroid Build Coastguard Worker       return;
1074*7304104dSAndroid Build Coastguard Worker 
1075*7304104dSAndroid Build Coastguard Worker     case DWFL_E_NOERROR:
1076*7304104dSAndroid Build Coastguard Worker       break;
1077*7304104dSAndroid Build Coastguard Worker 
1078*7304104dSAndroid Build Coastguard Worker     case DWFL_E_NO_SYMTAB:
1079*7304104dSAndroid Build Coastguard Worker       /* Now we have to look for a separate debuginfo file.  */
1080*7304104dSAndroid Build Coastguard Worker       mod->symerr = find_debuginfo (mod);
1081*7304104dSAndroid Build Coastguard Worker       switch (mod->symerr)
1082*7304104dSAndroid Build Coastguard Worker 	{
1083*7304104dSAndroid Build Coastguard Worker 	default:
1084*7304104dSAndroid Build Coastguard Worker 	  return;
1085*7304104dSAndroid Build Coastguard Worker 
1086*7304104dSAndroid Build Coastguard Worker 	case DWFL_E_NOERROR:
1087*7304104dSAndroid Build Coastguard Worker 	  mod->symerr = load_symtab (&mod->debug, &mod->symfile, &symscn,
1088*7304104dSAndroid Build Coastguard Worker 				     &xndxscn, &mod->syments,
1089*7304104dSAndroid Build Coastguard Worker 				     &mod->first_global, &strshndx);
1090*7304104dSAndroid Build Coastguard Worker 	  break;
1091*7304104dSAndroid Build Coastguard Worker 
1092*7304104dSAndroid Build Coastguard Worker 	case DWFL_E_CB:		/* The find_debuginfo hook failed.  */
1093*7304104dSAndroid Build Coastguard Worker 	  mod->symerr = DWFL_E_NO_SYMTAB;
1094*7304104dSAndroid Build Coastguard Worker 	  break;
1095*7304104dSAndroid Build Coastguard Worker 	}
1096*7304104dSAndroid Build Coastguard Worker 
1097*7304104dSAndroid Build Coastguard Worker       switch (mod->symerr)
1098*7304104dSAndroid Build Coastguard Worker 	{
1099*7304104dSAndroid Build Coastguard Worker 	default:
1100*7304104dSAndroid Build Coastguard Worker 	  return;
1101*7304104dSAndroid Build Coastguard Worker 
1102*7304104dSAndroid Build Coastguard Worker 	case DWFL_E_NOERROR:
1103*7304104dSAndroid Build Coastguard Worker 	  break;
1104*7304104dSAndroid Build Coastguard Worker 
1105*7304104dSAndroid Build Coastguard Worker 	case DWFL_E_NO_SYMTAB:
1106*7304104dSAndroid Build Coastguard Worker 	  /* There might be an auxiliary table.  */
1107*7304104dSAndroid Build Coastguard Worker 	  find_aux_sym (mod, &aux_symscn, &aux_xndxscn, &aux_strshndx);
1108*7304104dSAndroid Build Coastguard Worker 
1109*7304104dSAndroid Build Coastguard Worker 	  if (symscn != NULL)
1110*7304104dSAndroid Build Coastguard Worker 	    {
1111*7304104dSAndroid Build Coastguard Worker 	      /* We still have the dynamic symbol table.  */
1112*7304104dSAndroid Build Coastguard Worker 	      mod->symerr = DWFL_E_NOERROR;
1113*7304104dSAndroid Build Coastguard Worker 	      break;
1114*7304104dSAndroid Build Coastguard Worker 	    }
1115*7304104dSAndroid Build Coastguard Worker 
1116*7304104dSAndroid Build Coastguard Worker 	  if (aux_symscn != NULL)
1117*7304104dSAndroid Build Coastguard Worker 	    {
1118*7304104dSAndroid Build Coastguard Worker 	      /* We still have the auxiliary symbol table.  */
1119*7304104dSAndroid Build Coastguard Worker 	      mod->symerr = DWFL_E_NOERROR;
1120*7304104dSAndroid Build Coastguard Worker 	      goto aux_cache;
1121*7304104dSAndroid Build Coastguard Worker 	    }
1122*7304104dSAndroid Build Coastguard Worker 
1123*7304104dSAndroid Build Coastguard Worker 	  /* Last ditch, look for dynamic symbols without section headers.  */
1124*7304104dSAndroid Build Coastguard Worker 	  find_dynsym (mod);
1125*7304104dSAndroid Build Coastguard Worker 	  return;
1126*7304104dSAndroid Build Coastguard Worker 	}
1127*7304104dSAndroid Build Coastguard Worker       break;
1128*7304104dSAndroid Build Coastguard Worker     }
1129*7304104dSAndroid Build Coastguard Worker 
1130*7304104dSAndroid Build Coastguard Worker   /* This does some sanity checks on the string table section.  */
1131*7304104dSAndroid Build Coastguard Worker   if (elf_strptr (mod->symfile->elf, strshndx, 0) == NULL)
1132*7304104dSAndroid Build Coastguard Worker     {
1133*7304104dSAndroid Build Coastguard Worker     elferr:
1134*7304104dSAndroid Build Coastguard Worker       mod->symdata = NULL;
1135*7304104dSAndroid Build Coastguard Worker       mod->syments = 0;
1136*7304104dSAndroid Build Coastguard Worker       mod->first_global = 0;
1137*7304104dSAndroid Build Coastguard Worker       mod->symerr = DWFL_E (LIBELF, elf_errno ());
1138*7304104dSAndroid Build Coastguard Worker       goto aux_cleanup; /* This cleans up some more and tries find_dynsym.  */
1139*7304104dSAndroid Build Coastguard Worker     }
1140*7304104dSAndroid Build Coastguard Worker 
1141*7304104dSAndroid Build Coastguard Worker   /* Cache the data; MOD->syments and MOD->first_global were set
1142*7304104dSAndroid Build Coastguard Worker      above.  If any of the sections is compressed, uncompress it
1143*7304104dSAndroid Build Coastguard Worker      first.  Only the string data section could theoretically be
1144*7304104dSAndroid Build Coastguard Worker      compressed GNU style (as .zdebug_str).  Everything else only ELF
1145*7304104dSAndroid Build Coastguard Worker      gabi style (SHF_COMPRESSED).  */
1146*7304104dSAndroid Build Coastguard Worker 
1147*7304104dSAndroid Build Coastguard Worker   Elf_Scn *symstrscn = elf_getscn (mod->symfile->elf, strshndx);
1148*7304104dSAndroid Build Coastguard Worker   if (symstrscn == NULL)
1149*7304104dSAndroid Build Coastguard Worker     goto elferr;
1150*7304104dSAndroid Build Coastguard Worker 
1151*7304104dSAndroid Build Coastguard Worker   GElf_Shdr shdr_mem;
1152*7304104dSAndroid Build Coastguard Worker   GElf_Shdr *shdr = gelf_getshdr (symstrscn, &shdr_mem);
1153*7304104dSAndroid Build Coastguard Worker   if (shdr == NULL)
1154*7304104dSAndroid Build Coastguard Worker     goto elferr;
1155*7304104dSAndroid Build Coastguard Worker 
1156*7304104dSAndroid Build Coastguard Worker   size_t shstrndx;
1157*7304104dSAndroid Build Coastguard Worker   if (elf_getshdrstrndx (mod->symfile->elf, &shstrndx) < 0)
1158*7304104dSAndroid Build Coastguard Worker     goto elferr;
1159*7304104dSAndroid Build Coastguard Worker 
1160*7304104dSAndroid Build Coastguard Worker   const char *sname = elf_strptr (mod->symfile->elf, shstrndx, shdr->sh_name);
1161*7304104dSAndroid Build Coastguard Worker   if (sname == NULL)
1162*7304104dSAndroid Build Coastguard Worker     goto elferr;
1163*7304104dSAndroid Build Coastguard Worker 
1164*7304104dSAndroid Build Coastguard Worker   if (startswith (sname, ".zdebug"))
1165*7304104dSAndroid Build Coastguard Worker     /* Try to uncompress, but it might already have been, an error
1166*7304104dSAndroid Build Coastguard Worker        might just indicate, already uncompressed.  */
1167*7304104dSAndroid Build Coastguard Worker     elf_compress_gnu (symstrscn, 0, 0);
1168*7304104dSAndroid Build Coastguard Worker 
1169*7304104dSAndroid Build Coastguard Worker   if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
1170*7304104dSAndroid Build Coastguard Worker     if (elf_compress (symstrscn, 0, 0) < 0)
1171*7304104dSAndroid Build Coastguard Worker       goto elferr;
1172*7304104dSAndroid Build Coastguard Worker 
1173*7304104dSAndroid Build Coastguard Worker   mod->symstrdata = elf_getdata (symstrscn, NULL);
1174*7304104dSAndroid Build Coastguard Worker   if (mod->symstrdata == NULL || mod->symstrdata->d_buf == NULL)
1175*7304104dSAndroid Build Coastguard Worker     goto elferr;
1176*7304104dSAndroid Build Coastguard Worker 
1177*7304104dSAndroid Build Coastguard Worker   if (xndxscn == NULL)
1178*7304104dSAndroid Build Coastguard Worker     mod->symxndxdata = NULL;
1179*7304104dSAndroid Build Coastguard Worker   else
1180*7304104dSAndroid Build Coastguard Worker     {
1181*7304104dSAndroid Build Coastguard Worker       shdr = gelf_getshdr (xndxscn, &shdr_mem);
1182*7304104dSAndroid Build Coastguard Worker       if (shdr == NULL)
1183*7304104dSAndroid Build Coastguard Worker 	goto elferr;
1184*7304104dSAndroid Build Coastguard Worker 
1185*7304104dSAndroid Build Coastguard Worker       if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
1186*7304104dSAndroid Build Coastguard Worker 	if (elf_compress (xndxscn, 0, 0) < 0)
1187*7304104dSAndroid Build Coastguard Worker 	  goto elferr;
1188*7304104dSAndroid Build Coastguard Worker 
1189*7304104dSAndroid Build Coastguard Worker       mod->symxndxdata = elf_getdata (xndxscn, NULL);
1190*7304104dSAndroid Build Coastguard Worker       if (mod->symxndxdata == NULL || mod->symxndxdata->d_buf == NULL)
1191*7304104dSAndroid Build Coastguard Worker 	goto elferr;
1192*7304104dSAndroid Build Coastguard Worker     }
1193*7304104dSAndroid Build Coastguard Worker 
1194*7304104dSAndroid Build Coastguard Worker   shdr = gelf_getshdr (symscn, &shdr_mem);
1195*7304104dSAndroid Build Coastguard Worker   if (shdr == NULL)
1196*7304104dSAndroid Build Coastguard Worker     goto elferr;
1197*7304104dSAndroid Build Coastguard Worker 
1198*7304104dSAndroid Build Coastguard Worker   if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
1199*7304104dSAndroid Build Coastguard Worker     if (elf_compress (symscn, 0, 0) < 0)
1200*7304104dSAndroid Build Coastguard Worker       goto elferr;
1201*7304104dSAndroid Build Coastguard Worker 
1202*7304104dSAndroid Build Coastguard Worker   mod->symdata = elf_getdata (symscn, NULL);
1203*7304104dSAndroid Build Coastguard Worker   if (mod->symdata == NULL || mod->symdata->d_buf == NULL)
1204*7304104dSAndroid Build Coastguard Worker     goto elferr;
1205*7304104dSAndroid Build Coastguard Worker 
1206*7304104dSAndroid Build Coastguard Worker   // Sanity check number of symbols.
1207*7304104dSAndroid Build Coastguard Worker   shdr = gelf_getshdr (symscn, &shdr_mem);
1208*7304104dSAndroid Build Coastguard Worker   if (shdr == NULL || shdr->sh_entsize == 0
1209*7304104dSAndroid Build Coastguard Worker       || mod->syments > mod->symdata->d_size / shdr->sh_entsize
1210*7304104dSAndroid Build Coastguard Worker       || (size_t) mod->first_global > mod->syments)
1211*7304104dSAndroid Build Coastguard Worker     goto elferr;
1212*7304104dSAndroid Build Coastguard Worker 
1213*7304104dSAndroid Build Coastguard Worker   /* Cache any auxiliary symbol info, when it fails, just ignore aux_sym.  */
1214*7304104dSAndroid Build Coastguard Worker   if (aux_symscn != NULL)
1215*7304104dSAndroid Build Coastguard Worker     {
1216*7304104dSAndroid Build Coastguard Worker   aux_cache:
1217*7304104dSAndroid Build Coastguard Worker       /* This does some sanity checks on the string table section.  */
1218*7304104dSAndroid Build Coastguard Worker       if (elf_strptr (mod->aux_sym.elf, aux_strshndx, 0) == NULL)
1219*7304104dSAndroid Build Coastguard Worker 	{
1220*7304104dSAndroid Build Coastguard Worker 	aux_cleanup:
1221*7304104dSAndroid Build Coastguard Worker 	  mod->aux_syments = 0;
1222*7304104dSAndroid Build Coastguard Worker 	  elf_end (mod->aux_sym.elf);
1223*7304104dSAndroid Build Coastguard Worker 	  mod->aux_sym.elf = NULL;
1224*7304104dSAndroid Build Coastguard Worker 	  /* We thought we had something through shdrs, but it failed...
1225*7304104dSAndroid Build Coastguard Worker 	     Last ditch, look for dynamic symbols without section headers.  */
1226*7304104dSAndroid Build Coastguard Worker 	  find_dynsym (mod);
1227*7304104dSAndroid Build Coastguard Worker 	  return;
1228*7304104dSAndroid Build Coastguard Worker 	}
1229*7304104dSAndroid Build Coastguard Worker 
1230*7304104dSAndroid Build Coastguard Worker       Elf_Scn *aux_strscn = elf_getscn (mod->aux_sym.elf, aux_strshndx);
1231*7304104dSAndroid Build Coastguard Worker       if (aux_strscn == NULL)
1232*7304104dSAndroid Build Coastguard Worker 	goto elferr;
1233*7304104dSAndroid Build Coastguard Worker 
1234*7304104dSAndroid Build Coastguard Worker       shdr = gelf_getshdr (aux_strscn, &shdr_mem);
1235*7304104dSAndroid Build Coastguard Worker       if (shdr == NULL)
1236*7304104dSAndroid Build Coastguard Worker 	goto elferr;
1237*7304104dSAndroid Build Coastguard Worker 
1238*7304104dSAndroid Build Coastguard Worker       size_t aux_shstrndx;
1239*7304104dSAndroid Build Coastguard Worker       if (elf_getshdrstrndx (mod->aux_sym.elf, &aux_shstrndx) < 0)
1240*7304104dSAndroid Build Coastguard Worker 	goto elferr;
1241*7304104dSAndroid Build Coastguard Worker 
1242*7304104dSAndroid Build Coastguard Worker       sname = elf_strptr (mod->aux_sym.elf, aux_shstrndx,
1243*7304104dSAndroid Build Coastguard Worker 				      shdr->sh_name);
1244*7304104dSAndroid Build Coastguard Worker       if (sname == NULL)
1245*7304104dSAndroid Build Coastguard Worker 	goto elferr;
1246*7304104dSAndroid Build Coastguard Worker 
1247*7304104dSAndroid Build Coastguard Worker       if (startswith (sname, ".zdebug"))
1248*7304104dSAndroid Build Coastguard Worker 	/* Try to uncompress, but it might already have been, an error
1249*7304104dSAndroid Build Coastguard Worker 	   might just indicate, already uncompressed.  */
1250*7304104dSAndroid Build Coastguard Worker 	elf_compress_gnu (aux_strscn, 0, 0);
1251*7304104dSAndroid Build Coastguard Worker 
1252*7304104dSAndroid Build Coastguard Worker       if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
1253*7304104dSAndroid Build Coastguard Worker 	if (elf_compress (aux_strscn, 0, 0) < 0)
1254*7304104dSAndroid Build Coastguard Worker 	  goto elferr;
1255*7304104dSAndroid Build Coastguard Worker 
1256*7304104dSAndroid Build Coastguard Worker       mod->aux_symstrdata = elf_getdata (aux_strscn, NULL);
1257*7304104dSAndroid Build Coastguard Worker       if (mod->aux_symstrdata == NULL || mod->aux_symstrdata->d_buf == NULL)
1258*7304104dSAndroid Build Coastguard Worker 	goto aux_cleanup;
1259*7304104dSAndroid Build Coastguard Worker 
1260*7304104dSAndroid Build Coastguard Worker       if (aux_xndxscn == NULL)
1261*7304104dSAndroid Build Coastguard Worker 	mod->aux_symxndxdata = NULL;
1262*7304104dSAndroid Build Coastguard Worker       else
1263*7304104dSAndroid Build Coastguard Worker 	{
1264*7304104dSAndroid Build Coastguard Worker 	  shdr = gelf_getshdr (aux_xndxscn, &shdr_mem);
1265*7304104dSAndroid Build Coastguard Worker 	  if (shdr == NULL)
1266*7304104dSAndroid Build Coastguard Worker 	    goto elferr;
1267*7304104dSAndroid Build Coastguard Worker 
1268*7304104dSAndroid Build Coastguard Worker 	  if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
1269*7304104dSAndroid Build Coastguard Worker 	    if (elf_compress (aux_xndxscn, 0, 0) < 0)
1270*7304104dSAndroid Build Coastguard Worker 	      goto elferr;
1271*7304104dSAndroid Build Coastguard Worker 
1272*7304104dSAndroid Build Coastguard Worker 	  mod->aux_symxndxdata = elf_getdata (aux_xndxscn, NULL);
1273*7304104dSAndroid Build Coastguard Worker 	  if (mod->aux_symxndxdata == NULL
1274*7304104dSAndroid Build Coastguard Worker 	      || mod->aux_symxndxdata->d_buf == NULL)
1275*7304104dSAndroid Build Coastguard Worker 	    goto aux_cleanup;
1276*7304104dSAndroid Build Coastguard Worker 	}
1277*7304104dSAndroid Build Coastguard Worker 
1278*7304104dSAndroid Build Coastguard Worker       shdr = gelf_getshdr (aux_symscn, &shdr_mem);
1279*7304104dSAndroid Build Coastguard Worker       if (shdr == NULL)
1280*7304104dSAndroid Build Coastguard Worker 	goto elferr;
1281*7304104dSAndroid Build Coastguard Worker 
1282*7304104dSAndroid Build Coastguard Worker       if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
1283*7304104dSAndroid Build Coastguard Worker 	if (elf_compress (aux_symscn, 0, 0) < 0)
1284*7304104dSAndroid Build Coastguard Worker 	  goto elferr;
1285*7304104dSAndroid Build Coastguard Worker 
1286*7304104dSAndroid Build Coastguard Worker       mod->aux_symdata = elf_getdata (aux_symscn, NULL);
1287*7304104dSAndroid Build Coastguard Worker       if (mod->aux_symdata == NULL || mod->aux_symdata->d_buf == NULL)
1288*7304104dSAndroid Build Coastguard Worker 	goto aux_cleanup;
1289*7304104dSAndroid Build Coastguard Worker 
1290*7304104dSAndroid Build Coastguard Worker       // Sanity check number of aux symbols.
1291*7304104dSAndroid Build Coastguard Worker       shdr = gelf_getshdr (aux_symscn, &shdr_mem);
1292*7304104dSAndroid Build Coastguard Worker       if (mod->aux_syments > mod->aux_symdata->d_size / shdr->sh_entsize
1293*7304104dSAndroid Build Coastguard Worker 	  || (size_t) mod->aux_first_global > mod->aux_syments)
1294*7304104dSAndroid Build Coastguard Worker 	goto aux_cleanup;
1295*7304104dSAndroid Build Coastguard Worker     }
1296*7304104dSAndroid Build Coastguard Worker }
1297*7304104dSAndroid Build Coastguard Worker 
1298*7304104dSAndroid Build Coastguard Worker 
1299*7304104dSAndroid Build Coastguard Worker /* Try to open a libebl backend for MOD.  */
1300*7304104dSAndroid Build Coastguard Worker Dwfl_Error
1301*7304104dSAndroid Build Coastguard Worker internal_function
__libdwfl_module_getebl(Dwfl_Module * mod)1302*7304104dSAndroid Build Coastguard Worker __libdwfl_module_getebl (Dwfl_Module *mod)
1303*7304104dSAndroid Build Coastguard Worker {
1304*7304104dSAndroid Build Coastguard Worker   if (mod->ebl == NULL)
1305*7304104dSAndroid Build Coastguard Worker     {
1306*7304104dSAndroid Build Coastguard Worker       __libdwfl_getelf (mod);
1307*7304104dSAndroid Build Coastguard Worker       if (mod->elferr != DWFL_E_NOERROR)
1308*7304104dSAndroid Build Coastguard Worker 	return mod->elferr;
1309*7304104dSAndroid Build Coastguard Worker 
1310*7304104dSAndroid Build Coastguard Worker       mod->ebl = ebl_openbackend (mod->main.elf);
1311*7304104dSAndroid Build Coastguard Worker       if (mod->ebl == NULL)
1312*7304104dSAndroid Build Coastguard Worker 	return DWFL_E_LIBEBL;
1313*7304104dSAndroid Build Coastguard Worker     }
1314*7304104dSAndroid Build Coastguard Worker   return DWFL_E_NOERROR;
1315*7304104dSAndroid Build Coastguard Worker }
1316*7304104dSAndroid Build Coastguard Worker 
1317*7304104dSAndroid Build Coastguard Worker /* Try to start up libdw on DEBUGFILE.  */
1318*7304104dSAndroid Build Coastguard Worker static Dwfl_Error
load_dw(Dwfl_Module * mod,struct dwfl_file * debugfile)1319*7304104dSAndroid Build Coastguard Worker load_dw (Dwfl_Module *mod, struct dwfl_file *debugfile)
1320*7304104dSAndroid Build Coastguard Worker {
1321*7304104dSAndroid Build Coastguard Worker   if (mod->e_type == ET_REL && !debugfile->relocated)
1322*7304104dSAndroid Build Coastguard Worker     {
1323*7304104dSAndroid Build Coastguard Worker       const Dwfl_Callbacks *const cb = mod->dwfl->callbacks;
1324*7304104dSAndroid Build Coastguard Worker 
1325*7304104dSAndroid Build Coastguard Worker       /* The debugging sections have to be relocated.  */
1326*7304104dSAndroid Build Coastguard Worker       if (cb->section_address == NULL)
1327*7304104dSAndroid Build Coastguard Worker 	return DWFL_E_NOREL;
1328*7304104dSAndroid Build Coastguard Worker 
1329*7304104dSAndroid Build Coastguard Worker       Dwfl_Error error = __libdwfl_module_getebl (mod);
1330*7304104dSAndroid Build Coastguard Worker       if (error != DWFL_E_NOERROR)
1331*7304104dSAndroid Build Coastguard Worker 	return error;
1332*7304104dSAndroid Build Coastguard Worker 
1333*7304104dSAndroid Build Coastguard Worker       find_symtab (mod);
1334*7304104dSAndroid Build Coastguard Worker       Dwfl_Error result = mod->symerr;
1335*7304104dSAndroid Build Coastguard Worker       if (result == DWFL_E_NOERROR)
1336*7304104dSAndroid Build Coastguard Worker 	result = __libdwfl_relocate (mod, debugfile->elf, true);
1337*7304104dSAndroid Build Coastguard Worker       if (result != DWFL_E_NOERROR)
1338*7304104dSAndroid Build Coastguard Worker 	return result;
1339*7304104dSAndroid Build Coastguard Worker     }
1340*7304104dSAndroid Build Coastguard Worker 
1341*7304104dSAndroid Build Coastguard Worker   mod->dw = INTUSE(dwarf_begin_elf) (debugfile->elf, DWARF_C_READ, NULL);
1342*7304104dSAndroid Build Coastguard Worker   if (mod->dw == NULL)
1343*7304104dSAndroid Build Coastguard Worker     {
1344*7304104dSAndroid Build Coastguard Worker       int err = INTUSE(dwarf_errno) ();
1345*7304104dSAndroid Build Coastguard Worker       return err == DWARF_E_NO_DWARF ? DWFL_E_NO_DWARF : DWFL_E (LIBDW, err);
1346*7304104dSAndroid Build Coastguard Worker     }
1347*7304104dSAndroid Build Coastguard Worker 
1348*7304104dSAndroid Build Coastguard Worker   /* Do this after dwarf_begin_elf has a chance to process the fd.  */
1349*7304104dSAndroid Build Coastguard Worker   if (mod->e_type == ET_REL && !debugfile->relocated)
1350*7304104dSAndroid Build Coastguard Worker     {
1351*7304104dSAndroid Build Coastguard Worker       /* Don't keep the file descriptors around.  */
1352*7304104dSAndroid Build Coastguard Worker       if (mod->main.fd != -1 && elf_cntl (mod->main.elf, ELF_C_FDREAD) == 0)
1353*7304104dSAndroid Build Coastguard Worker 	{
1354*7304104dSAndroid Build Coastguard Worker 	  close (mod->main.fd);
1355*7304104dSAndroid Build Coastguard Worker 	  mod->main.fd = -1;
1356*7304104dSAndroid Build Coastguard Worker 	}
1357*7304104dSAndroid Build Coastguard Worker       if (debugfile->fd != -1 && elf_cntl (debugfile->elf, ELF_C_FDREAD) == 0)
1358*7304104dSAndroid Build Coastguard Worker 	{
1359*7304104dSAndroid Build Coastguard Worker 	  close (debugfile->fd);
1360*7304104dSAndroid Build Coastguard Worker 	  debugfile->fd = -1;
1361*7304104dSAndroid Build Coastguard Worker 	}
1362*7304104dSAndroid Build Coastguard Worker     }
1363*7304104dSAndroid Build Coastguard Worker 
1364*7304104dSAndroid Build Coastguard Worker   /* We might have already closed the fd when we asked dwarf_begin_elf to
1365*7304104dSAndroid Build Coastguard Worker      create an Dwarf.  Help out a little in case we need to find an alt,
1366*7304104dSAndroid Build Coastguard Worker      dwo, or dwp file later.  */
1367*7304104dSAndroid Build Coastguard Worker   if (mod->dw->elfpath == NULL && mod->elfpath != NULL
1368*7304104dSAndroid Build Coastguard Worker       && debugfile == &mod->main)
1369*7304104dSAndroid Build Coastguard Worker     {
1370*7304104dSAndroid Build Coastguard Worker       mod->dw->elfpath = strdup (mod->elfpath);
1371*7304104dSAndroid Build Coastguard Worker       __libdw_set_debugdir (mod->dw);
1372*7304104dSAndroid Build Coastguard Worker     }
1373*7304104dSAndroid Build Coastguard Worker 
1374*7304104dSAndroid Build Coastguard Worker   /* Until we have iterated through all CU's, we might do lazy lookups.  */
1375*7304104dSAndroid Build Coastguard Worker   mod->lazycu = 1;
1376*7304104dSAndroid Build Coastguard Worker 
1377*7304104dSAndroid Build Coastguard Worker   return DWFL_E_NOERROR;
1378*7304104dSAndroid Build Coastguard Worker }
1379*7304104dSAndroid Build Coastguard Worker 
1380*7304104dSAndroid Build Coastguard Worker /* Try to start up libdw on either the main file or the debuginfo file.  */
1381*7304104dSAndroid Build Coastguard Worker static void
find_dw(Dwfl_Module * mod)1382*7304104dSAndroid Build Coastguard Worker find_dw (Dwfl_Module *mod)
1383*7304104dSAndroid Build Coastguard Worker {
1384*7304104dSAndroid Build Coastguard Worker   if (mod->dw != NULL		/* Already done.  */
1385*7304104dSAndroid Build Coastguard Worker       || mod->dwerr != DWFL_E_NOERROR) /* Cached previous failure.  */
1386*7304104dSAndroid Build Coastguard Worker     return;
1387*7304104dSAndroid Build Coastguard Worker 
1388*7304104dSAndroid Build Coastguard Worker   __libdwfl_getelf (mod);
1389*7304104dSAndroid Build Coastguard Worker   mod->dwerr = mod->elferr;
1390*7304104dSAndroid Build Coastguard Worker   if (mod->dwerr != DWFL_E_NOERROR)
1391*7304104dSAndroid Build Coastguard Worker     return;
1392*7304104dSAndroid Build Coastguard Worker 
1393*7304104dSAndroid Build Coastguard Worker   /* First see if the main ELF file has the debugging information.  */
1394*7304104dSAndroid Build Coastguard Worker   mod->dwerr = load_dw (mod, &mod->main);
1395*7304104dSAndroid Build Coastguard Worker   switch (mod->dwerr)
1396*7304104dSAndroid Build Coastguard Worker     {
1397*7304104dSAndroid Build Coastguard Worker     case DWFL_E_NOERROR:
1398*7304104dSAndroid Build Coastguard Worker       mod->debug.elf = mod->main.elf;
1399*7304104dSAndroid Build Coastguard Worker       mod->debug.address_sync = mod->main.address_sync;
1400*7304104dSAndroid Build Coastguard Worker 
1401*7304104dSAndroid Build Coastguard Worker       /* The Dwarf might need an alt debug file, find that now after
1402*7304104dSAndroid Build Coastguard Worker 	 everything about the debug file has been setup (the
1403*7304104dSAndroid Build Coastguard Worker 	 find_debuginfo callback might need it).  */
1404*7304104dSAndroid Build Coastguard Worker       find_debug_altlink (mod, mod->main.name);
1405*7304104dSAndroid Build Coastguard Worker       return;
1406*7304104dSAndroid Build Coastguard Worker 
1407*7304104dSAndroid Build Coastguard Worker     case DWFL_E_NO_DWARF:
1408*7304104dSAndroid Build Coastguard Worker       break;
1409*7304104dSAndroid Build Coastguard Worker 
1410*7304104dSAndroid Build Coastguard Worker     default:
1411*7304104dSAndroid Build Coastguard Worker       goto canonicalize;
1412*7304104dSAndroid Build Coastguard Worker     }
1413*7304104dSAndroid Build Coastguard Worker 
1414*7304104dSAndroid Build Coastguard Worker   /* Now we have to look for a separate debuginfo file.  */
1415*7304104dSAndroid Build Coastguard Worker   mod->dwerr = find_debuginfo (mod);
1416*7304104dSAndroid Build Coastguard Worker   switch (mod->dwerr)
1417*7304104dSAndroid Build Coastguard Worker     {
1418*7304104dSAndroid Build Coastguard Worker     case DWFL_E_NOERROR:
1419*7304104dSAndroid Build Coastguard Worker       mod->dwerr = load_dw (mod, &mod->debug);
1420*7304104dSAndroid Build Coastguard Worker       if (mod->dwerr == DWFL_E_NOERROR)
1421*7304104dSAndroid Build Coastguard Worker 	{
1422*7304104dSAndroid Build Coastguard Worker 	  /* The Dwarf might need an alt debug file, find that now after
1423*7304104dSAndroid Build Coastguard Worker 	     everything about the debug file has been setup (the
1424*7304104dSAndroid Build Coastguard Worker 	     find_debuginfo callback might need it).  */
1425*7304104dSAndroid Build Coastguard Worker 	  find_debug_altlink (mod, mod->debug.name);
1426*7304104dSAndroid Build Coastguard Worker 	  return;
1427*7304104dSAndroid Build Coastguard Worker 	}
1428*7304104dSAndroid Build Coastguard Worker 
1429*7304104dSAndroid Build Coastguard Worker       break;
1430*7304104dSAndroid Build Coastguard Worker 
1431*7304104dSAndroid Build Coastguard Worker     case DWFL_E_CB:		/* The find_debuginfo hook failed.  */
1432*7304104dSAndroid Build Coastguard Worker       mod->dwerr = DWFL_E_NO_DWARF;
1433*7304104dSAndroid Build Coastguard Worker       return;
1434*7304104dSAndroid Build Coastguard Worker 
1435*7304104dSAndroid Build Coastguard Worker     default:
1436*7304104dSAndroid Build Coastguard Worker       break;
1437*7304104dSAndroid Build Coastguard Worker     }
1438*7304104dSAndroid Build Coastguard Worker 
1439*7304104dSAndroid Build Coastguard Worker  canonicalize:
1440*7304104dSAndroid Build Coastguard Worker   mod->dwerr = __libdwfl_canon_error (mod->dwerr);
1441*7304104dSAndroid Build Coastguard Worker }
1442*7304104dSAndroid Build Coastguard Worker 
1443*7304104dSAndroid Build Coastguard Worker Dwarf *
dwfl_module_getdwarf(Dwfl_Module * mod,Dwarf_Addr * bias)1444*7304104dSAndroid Build Coastguard Worker dwfl_module_getdwarf (Dwfl_Module *mod, Dwarf_Addr *bias)
1445*7304104dSAndroid Build Coastguard Worker {
1446*7304104dSAndroid Build Coastguard Worker   if (mod == NULL)
1447*7304104dSAndroid Build Coastguard Worker     return NULL;
1448*7304104dSAndroid Build Coastguard Worker 
1449*7304104dSAndroid Build Coastguard Worker   find_dw (mod);
1450*7304104dSAndroid Build Coastguard Worker   if (mod->dwerr == DWFL_E_NOERROR)
1451*7304104dSAndroid Build Coastguard Worker     {
1452*7304104dSAndroid Build Coastguard Worker       /* If dwfl_module_getelf was used previously, then partial apply
1453*7304104dSAndroid Build Coastguard Worker 	 relocation to miscellaneous sections in the debug file too.  */
1454*7304104dSAndroid Build Coastguard Worker       if (mod->e_type == ET_REL
1455*7304104dSAndroid Build Coastguard Worker 	  && mod->main.relocated && ! mod->debug.relocated)
1456*7304104dSAndroid Build Coastguard Worker 	{
1457*7304104dSAndroid Build Coastguard Worker 	  mod->debug.relocated = true;
1458*7304104dSAndroid Build Coastguard Worker 	  if (mod->debug.elf != mod->main.elf)
1459*7304104dSAndroid Build Coastguard Worker 	    (void) __libdwfl_relocate (mod, mod->debug.elf, false);
1460*7304104dSAndroid Build Coastguard Worker 	}
1461*7304104dSAndroid Build Coastguard Worker 
1462*7304104dSAndroid Build Coastguard Worker       *bias = dwfl_adjusted_dwarf_addr (mod, 0);
1463*7304104dSAndroid Build Coastguard Worker       return mod->dw;
1464*7304104dSAndroid Build Coastguard Worker     }
1465*7304104dSAndroid Build Coastguard Worker 
1466*7304104dSAndroid Build Coastguard Worker   __libdwfl_seterrno (mod->dwerr);
1467*7304104dSAndroid Build Coastguard Worker   return NULL;
1468*7304104dSAndroid Build Coastguard Worker }
INTDEF(dwfl_module_getdwarf)1469*7304104dSAndroid Build Coastguard Worker INTDEF (dwfl_module_getdwarf)
1470*7304104dSAndroid Build Coastguard Worker 
1471*7304104dSAndroid Build Coastguard Worker int
1472*7304104dSAndroid Build Coastguard Worker dwfl_module_getsymtab (Dwfl_Module *mod)
1473*7304104dSAndroid Build Coastguard Worker {
1474*7304104dSAndroid Build Coastguard Worker   if (mod == NULL)
1475*7304104dSAndroid Build Coastguard Worker     return -1;
1476*7304104dSAndroid Build Coastguard Worker 
1477*7304104dSAndroid Build Coastguard Worker   find_symtab (mod);
1478*7304104dSAndroid Build Coastguard Worker   if (mod->symerr == DWFL_E_NOERROR)
1479*7304104dSAndroid Build Coastguard Worker     /* We will skip the auxiliary zero entry if there is another one.  */
1480*7304104dSAndroid Build Coastguard Worker     return (mod->syments + mod->aux_syments
1481*7304104dSAndroid Build Coastguard Worker 	    - (mod->syments > 0 && mod->aux_syments > 0 ? 1 : 0));
1482*7304104dSAndroid Build Coastguard Worker 
1483*7304104dSAndroid Build Coastguard Worker   __libdwfl_seterrno (mod->symerr);
1484*7304104dSAndroid Build Coastguard Worker   return -1;
1485*7304104dSAndroid Build Coastguard Worker }
INTDEF(dwfl_module_getsymtab)1486*7304104dSAndroid Build Coastguard Worker INTDEF (dwfl_module_getsymtab)
1487*7304104dSAndroid Build Coastguard Worker 
1488*7304104dSAndroid Build Coastguard Worker int
1489*7304104dSAndroid Build Coastguard Worker dwfl_module_getsymtab_first_global (Dwfl_Module *mod)
1490*7304104dSAndroid Build Coastguard Worker {
1491*7304104dSAndroid Build Coastguard Worker   if (mod == NULL)
1492*7304104dSAndroid Build Coastguard Worker     return -1;
1493*7304104dSAndroid Build Coastguard Worker 
1494*7304104dSAndroid Build Coastguard Worker   find_symtab (mod);
1495*7304104dSAndroid Build Coastguard Worker   if (mod->symerr == DWFL_E_NOERROR)
1496*7304104dSAndroid Build Coastguard Worker     {
1497*7304104dSAndroid Build Coastguard Worker       /* All local symbols should come before all global symbols.  If
1498*7304104dSAndroid Build Coastguard Worker 	 we have an auxiliary table make sure all the main locals come
1499*7304104dSAndroid Build Coastguard Worker 	 first, then all aux locals, then all main globals and finally all
1500*7304104dSAndroid Build Coastguard Worker 	 aux globals.  And skip the auxiliary table zero undefined
1501*7304104dSAndroid Build Coastguard Worker 	 entry.  */
1502*7304104dSAndroid Build Coastguard Worker       int skip_aux_zero = (mod->syments > 0 && mod->aux_syments > 0) ? 1 : 0;
1503*7304104dSAndroid Build Coastguard Worker       return mod->first_global + mod->aux_first_global - skip_aux_zero;
1504*7304104dSAndroid Build Coastguard Worker     }
1505*7304104dSAndroid Build Coastguard Worker 
1506*7304104dSAndroid Build Coastguard Worker   __libdwfl_seterrno (mod->symerr);
1507*7304104dSAndroid Build Coastguard Worker   return -1;
1508*7304104dSAndroid Build Coastguard Worker }
1509*7304104dSAndroid Build Coastguard Worker INTDEF (dwfl_module_getsymtab_first_global)
1510