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