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