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