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