libdwfl: Make sure elf_getdata_rawchunk size_t doesn't overflow find_dynsym.
[platform/upstream/elfutils.git] / libdwfl / dwfl_module_getdwarf.c
1 /* Find debugging and symbol information for a module in libdwfl.
2    Copyright (C) 2005-2012, 2014 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
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 (open64 (*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
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
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
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 /* If the main file might have been prelinked, then we need to
235    discover the correct synchronization address between the main and
236    debug files.  Because of prelink's section juggling, we cannot rely
237    on the address_sync computed from PT_LOAD segments (see open_elf).
238
239    We will attempt to discover a synchronization address based on the
240    section headers instead.  But finding a section address that is
241    safe to use requires identifying which sections are SHT_PROGBITS.
242    We can do that in the main file, but in the debug file all the
243    allocated sections have been transformed into SHT_NOBITS so we have
244    lost the means to match them up correctly.
245
246    The only method left to us is to decode the .gnu.prelink_undo
247    section in the prelinked main file.  This shows what the sections
248    looked like before prelink juggled them--when they still had a
249    direct correspondence to the debug file.  */
250 static Dwfl_Error
251 find_prelink_address_sync (Dwfl_Module *mod, struct dwfl_file *file)
252 {
253   /* The magic section is only identified by name.  */
254   size_t shstrndx;
255   if (elf_getshdrstrndx (mod->main.elf, &shstrndx) < 0)
256     return DWFL_E_LIBELF;
257
258   Elf_Scn *scn = NULL;
259   while ((scn = elf_nextscn (mod->main.elf, scn)) != NULL)
260     {
261       GElf_Shdr shdr_mem;
262       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
263       if (unlikely (shdr == NULL))
264         return DWFL_E_LIBELF;
265       if (shdr->sh_type == SHT_PROGBITS
266           && !(shdr->sh_flags & SHF_ALLOC)
267           && shdr->sh_name != 0)
268         {
269           const char *secname = elf_strptr (mod->main.elf, shstrndx,
270                                             shdr->sh_name);
271           if (unlikely (secname == NULL))
272             return DWFL_E_LIBELF;
273           if (!strcmp (secname, ".gnu.prelink_undo"))
274             break;
275         }
276     }
277
278   if (scn == NULL)
279     /* There was no .gnu.prelink_undo section.  */
280     return DWFL_E_NOERROR;
281
282   Elf_Data *undodata = elf_rawdata (scn, NULL);
283   if (unlikely (undodata == NULL))
284     return DWFL_E_LIBELF;
285
286   /* Decode the section.  It consists of the original ehdr, phdrs,
287      and shdrs (but omits section 0).  */
288
289   union
290   {
291     Elf32_Ehdr e32;
292     Elf64_Ehdr e64;
293   } ehdr;
294   Elf_Data dst =
295     {
296       .d_buf = &ehdr,
297       .d_size = sizeof ehdr,
298       .d_type = ELF_T_EHDR,
299       .d_version = EV_CURRENT
300     };
301   Elf_Data src = *undodata;
302   src.d_size = gelf_fsize (mod->main.elf, ELF_T_EHDR, 1, EV_CURRENT);
303   src.d_type = ELF_T_EHDR;
304   if (unlikely (gelf_xlatetom (mod->main.elf, &dst, &src,
305                                elf_getident (mod->main.elf, NULL)[EI_DATA])
306                 == NULL))
307     return DWFL_E_LIBELF;
308
309   size_t shentsize = gelf_fsize (mod->main.elf, ELF_T_SHDR, 1, EV_CURRENT);
310   size_t phentsize = gelf_fsize (mod->main.elf, ELF_T_PHDR, 1, EV_CURRENT);
311
312   uint_fast16_t phnum;
313   uint_fast16_t shnum;
314   if (ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32)
315     {
316       if (ehdr.e32.e_shentsize != shentsize
317           || ehdr.e32.e_phentsize != phentsize)
318         return DWFL_E_BAD_PRELINK;
319       phnum = ehdr.e32.e_phnum;
320       shnum = ehdr.e32.e_shnum;
321     }
322   else
323     {
324       if (ehdr.e64.e_shentsize != shentsize
325           || ehdr.e64.e_phentsize != phentsize)
326         return DWFL_E_BAD_PRELINK;
327       phnum = ehdr.e64.e_phnum;
328       shnum = ehdr.e64.e_shnum;
329     }
330
331   /* Since prelink does not store the zeroth section header in the undo
332      section, it cannot support SHN_XINDEX encoding.  */
333   if (unlikely (shnum >= SHN_LORESERVE)
334       || unlikely (undodata->d_size != (src.d_size
335                                         + phnum * phentsize
336                                         + (shnum - 1) * shentsize)))
337     return DWFL_E_BAD_PRELINK;
338
339   /* We look at the allocated SHT_PROGBITS (or SHT_NOBITS) sections.  (Most
340      every file will have some SHT_PROGBITS sections, but it's possible to
341      have one with nothing but .bss, i.e. SHT_NOBITS.)  The special sections
342      that can be moved around have different sh_type values--except for
343      .interp, the section that became the PT_INTERP segment.  So we exclude
344      the SHT_PROGBITS section whose address matches the PT_INTERP p_vaddr.
345      For this reason, we must examine the phdrs first to find PT_INTERP.  */
346
347   GElf_Addr main_interp = 0;
348   {
349     size_t main_phnum;
350     if (unlikely (elf_getphdrnum (mod->main.elf, &main_phnum)))
351       return DWFL_E_LIBELF;
352     for (size_t i = 0; i < main_phnum; ++i)
353       {
354         GElf_Phdr phdr;
355         if (unlikely (gelf_getphdr (mod->main.elf, i, &phdr) == NULL))
356           return DWFL_E_LIBELF;
357         if (phdr.p_type == PT_INTERP)
358           {
359             main_interp = phdr.p_vaddr;
360             break;
361           }
362       }
363   }
364
365   src.d_buf += src.d_size;
366   src.d_type = ELF_T_PHDR;
367   src.d_size = phnum * phentsize;
368
369   GElf_Addr undo_interp = 0;
370   {
371     union
372     {
373       Elf32_Phdr p32[phnum];
374       Elf64_Phdr p64[phnum];
375     } phdr;
376     dst.d_buf = &phdr;
377     dst.d_size = sizeof phdr;
378     if (unlikely (gelf_xlatetom (mod->main.elf, &dst, &src,
379                                  ehdr.e32.e_ident[EI_DATA]) == NULL))
380       return DWFL_E_LIBELF;
381     if (ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32)
382       {
383         for (uint_fast16_t i = 0; i < phnum; ++i)
384           if (phdr.p32[i].p_type == PT_INTERP)
385             {
386               undo_interp = phdr.p32[i].p_vaddr;
387               break;
388             }
389       }
390     else
391       {
392         for (uint_fast16_t i = 0; i < phnum; ++i)
393           if (phdr.p64[i].p_type == PT_INTERP)
394             {
395               undo_interp = phdr.p64[i].p_vaddr;
396               break;
397             }
398       }
399   }
400
401   if (unlikely ((main_interp == 0) != (undo_interp == 0)))
402     return DWFL_E_BAD_PRELINK;
403
404   src.d_buf += src.d_size;
405   src.d_type = ELF_T_SHDR;
406   src.d_size = gelf_fsize (mod->main.elf, ELF_T_SHDR, shnum - 1, EV_CURRENT);
407
408   union
409   {
410     Elf32_Shdr s32[shnum - 1];
411     Elf64_Shdr s64[shnum - 1];
412   } shdr;
413   dst.d_buf = &shdr;
414   dst.d_size = sizeof shdr;
415   if (unlikely (gelf_xlatetom (mod->main.elf, &dst, &src,
416                                ehdr.e32.e_ident[EI_DATA]) == NULL))
417     return DWFL_E_LIBELF;
418
419   /* Now we can look at the original section headers of the main file
420      before it was prelinked.  First we'll apply our method to the main
421      file sections as they are after prelinking, to calculate the
422      synchronization address of the main file.  Then we'll apply that
423      same method to the saved section headers, to calculate the matching
424      synchronization address of the debug file.
425
426      The method is to consider SHF_ALLOC sections that are either
427      SHT_PROGBITS or SHT_NOBITS, excluding the section whose sh_addr
428      matches the PT_INTERP p_vaddr.  The special sections that can be
429      moved by prelink have other types, except for .interp (which
430      becomes PT_INTERP).  The "real" sections cannot move as such, but
431      .bss can be split into .dynbss and .bss, with the total memory
432      image remaining the same but being spread across the two sections.
433      So we consider the highest section end, which still matches up.  */
434
435   GElf_Addr highest;
436
437   inline void consider_shdr (GElf_Addr interp,
438                              GElf_Word sh_type,
439                              GElf_Xword sh_flags,
440                              GElf_Addr sh_addr,
441                              GElf_Xword sh_size)
442   {
443     if ((sh_flags & SHF_ALLOC)
444         && ((sh_type == SHT_PROGBITS && sh_addr != interp)
445             || sh_type == SHT_NOBITS))
446       {
447         const GElf_Addr sh_end = sh_addr + sh_size;
448         if (sh_end > highest)
449           highest = sh_end;
450       }
451   }
452
453   highest = 0;
454   scn = NULL;
455   while ((scn = elf_nextscn (mod->main.elf, scn)) != NULL)
456     {
457       GElf_Shdr sh_mem;
458       GElf_Shdr *sh = gelf_getshdr (scn, &sh_mem);
459       if (unlikely (sh == NULL))
460         return DWFL_E_LIBELF;
461       consider_shdr (main_interp, sh->sh_type, sh->sh_flags,
462                      sh->sh_addr, sh->sh_size);
463     }
464   if (highest > mod->main.vaddr)
465     {
466       mod->main.address_sync = highest;
467
468       highest = 0;
469       if (ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32)
470         for (size_t i = 0; i < shnum - 1; ++i)
471           consider_shdr (undo_interp, shdr.s32[i].sh_type, shdr.s32[i].sh_flags,
472                          shdr.s32[i].sh_addr, shdr.s32[i].sh_size);
473       else
474         for (size_t i = 0; i < shnum - 1; ++i)
475           consider_shdr (undo_interp, shdr.s64[i].sh_type, shdr.s64[i].sh_flags,
476                          shdr.s64[i].sh_addr, shdr.s64[i].sh_size);
477
478       if (highest > file->vaddr)
479         file->address_sync = highest;
480       else
481         return DWFL_E_BAD_PRELINK;
482     }
483
484   return DWFL_E_NOERROR;
485 }
486
487 /* Find the separate debuginfo file for this module and open libelf on it.
488    When we return success, MOD->debug is set up.  */
489 static Dwfl_Error
490 find_debuginfo (Dwfl_Module *mod)
491 {
492   if (mod->debug.elf != NULL)
493     return DWFL_E_NOERROR;
494
495   GElf_Word debuglink_crc = 0;
496   const char *debuglink_file;
497   debuglink_file = INTUSE(dwelf_elf_gnu_debuglink) (mod->main.elf,
498                                                     &debuglink_crc);
499
500   mod->debug.fd = (*mod->dwfl->callbacks->find_debuginfo) (MODCB_ARGS (mod),
501                                                            mod->main.name,
502                                                            debuglink_file,
503                                                            debuglink_crc,
504                                                            &mod->debug.name);
505   Dwfl_Error result = open_elf (mod, &mod->debug);
506   if (result == DWFL_E_NOERROR && mod->debug.address_sync != 0)
507     result = find_prelink_address_sync (mod, &mod->debug);
508   return result;
509 }
510
511 /* Try to find the alternative debug link for the given DWARF and set
512    it if found.  Only called when mod->dw is already setup but still
513    might need an alternative (dwz multi) debug file.  filename is either
514    the main or debug name from which the Dwarf was created. */
515 static void
516 find_debug_altlink (Dwfl_Module *mod, const char *filename)
517 {
518   assert (mod->dw != NULL);
519
520   const char *altname;
521   const void *build_id;
522   ssize_t build_id_len = INTUSE(dwelf_dwarf_gnu_debugaltlink) (mod->dw,
523                                                                &altname,
524                                                                &build_id);
525
526   if (build_id_len > 0)
527     {
528       /* We could store altfile in the module, but don't really need it.  */
529       char *altfile = NULL;
530       mod->alt_fd = (*mod->dwfl->callbacks->find_debuginfo) (MODCB_ARGS (mod),
531                                                              filename,
532                                                              altname,
533                                                              0,
534                                                              &altfile);
535
536       /* The (internal) callbacks might just set mod->alt_elf directly
537          because they open the Elf anyway for sanity checking.
538          Otherwise open either the given file name or use the fd
539          returned.  */
540       Dwfl_Error error = open_elf_file (&mod->alt_elf, &mod->alt_fd,
541                                         &altfile);
542       if (error == DWFL_E_NOERROR)
543         {
544           mod->alt = INTUSE(dwarf_begin_elf) (mod->alt_elf,
545                                               DWARF_C_READ, NULL);
546           if (mod->alt == NULL)
547             {
548               elf_end (mod->alt_elf);
549               mod->alt_elf = NULL;
550               close (mod->alt_fd);
551               mod->alt_fd = -1;
552             }
553           else
554             dwarf_setalt (mod->dw, mod->alt);
555         }
556
557       free (altfile); /* See above, we don't really need it.  */
558     }
559 }
560
561 /* Try to find a symbol table in FILE.
562    Returns DWFL_E_NOERROR if a proper one is found.
563    Returns DWFL_E_NO_SYMTAB if not, but still sets results for SHT_DYNSYM.  */
564 static Dwfl_Error
565 load_symtab (struct dwfl_file *file, struct dwfl_file **symfile,
566              Elf_Scn **symscn, Elf_Scn **xndxscn,
567              size_t *syments, int *first_global, GElf_Word *strshndx)
568 {
569   bool symtab = false;
570   Elf_Scn *scn = NULL;
571   while ((scn = elf_nextscn (file->elf, scn)) != NULL)
572     {
573       GElf_Shdr shdr_mem, *shdr = gelf_getshdr (scn, &shdr_mem);
574       if (shdr != NULL)
575         switch (shdr->sh_type)
576           {
577           case SHT_SYMTAB:
578             if (shdr->sh_entsize == 0)
579               break;
580             symtab = true;
581             *symscn = scn;
582             *symfile = file;
583             *strshndx = shdr->sh_link;
584             *syments = shdr->sh_size / shdr->sh_entsize;
585             *first_global = shdr->sh_info;
586             if (*xndxscn != NULL)
587               return DWFL_E_NOERROR;
588             break;
589
590           case SHT_DYNSYM:
591             if (symtab)
592               break;
593             /* Use this if need be, but keep looking for SHT_SYMTAB.  */
594             if (shdr->sh_entsize == 0)
595               break;
596             *symscn = scn;
597             *symfile = file;
598             *strshndx = shdr->sh_link;
599             *syments = shdr->sh_size / shdr->sh_entsize;
600             *first_global = shdr->sh_info;
601             break;
602
603           case SHT_SYMTAB_SHNDX:
604             *xndxscn = scn;
605             if (symtab)
606               return DWFL_E_NOERROR;
607             break;
608
609           default:
610             break;
611           }
612     }
613
614   if (symtab)
615     /* We found one, though no SHT_SYMTAB_SHNDX to go with it.  */
616     return DWFL_E_NOERROR;
617
618   /* We found no SHT_SYMTAB, so any SHT_SYMTAB_SHNDX was bogus.
619      We might have found an SHT_DYNSYM and set *SYMSCN et al though.  */
620   *xndxscn = NULL;
621   return DWFL_E_NO_SYMTAB;
622 }
623
624
625 /* Translate addresses into file offsets.
626    OFFS[*] start out zero and remain zero if unresolved.  */
627 static void
628 find_offsets (Elf *elf, GElf_Addr main_bias, size_t phnum, size_t n,
629               GElf_Addr addrs[n], GElf_Off offs[n])
630 {
631   size_t unsolved = n;
632   for (size_t i = 0; i < phnum; ++i)
633     {
634       GElf_Phdr phdr_mem;
635       GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem);
636       if (phdr != NULL && phdr->p_type == PT_LOAD && phdr->p_memsz > 0)
637         for (size_t j = 0; j < n; ++j)
638           if (offs[j] == 0
639               && addrs[j] >= phdr->p_vaddr + main_bias
640               && addrs[j] - (phdr->p_vaddr + main_bias) < phdr->p_filesz)
641             {
642               offs[j] = addrs[j] - (phdr->p_vaddr + main_bias) + phdr->p_offset;
643               if (--unsolved == 0)
644                 break;
645             }
646     }
647 }
648
649 /* Try to find a dynamic symbol table via phdrs.  */
650 static void
651 find_dynsym (Dwfl_Module *mod)
652 {
653   GElf_Ehdr ehdr_mem;
654   GElf_Ehdr *ehdr = gelf_getehdr (mod->main.elf, &ehdr_mem);
655
656   size_t phnum;
657   if (unlikely (elf_getphdrnum (mod->main.elf, &phnum) != 0))
658     return;
659
660   for (size_t i = 0; i < phnum; ++i)
661     {
662       GElf_Phdr phdr_mem;
663       GElf_Phdr *phdr = gelf_getphdr (mod->main.elf, i, &phdr_mem);
664       if (phdr == NULL)
665         break;
666
667       if (phdr->p_type == PT_DYNAMIC)
668         {
669           /* Examine the dynamic section for the pointers we need.  */
670
671           Elf_Data *data = elf_getdata_rawchunk (mod->main.elf,
672                                                  phdr->p_offset, phdr->p_filesz,
673                                                  ELF_T_DYN);
674           if (data == NULL)
675             continue;
676
677           enum
678             {
679               i_symtab,
680               i_strtab,
681               i_hash,
682               i_gnu_hash,
683               i_max
684             };
685           GElf_Addr addrs[i_max] = { 0, };
686           GElf_Xword strsz = 0;
687           size_t n = data->d_size / gelf_fsize (mod->main.elf,
688                                                 ELF_T_DYN, 1, EV_CURRENT);
689           for (size_t j = 0; j < n; ++j)
690             {
691               GElf_Dyn dyn_mem;
692               GElf_Dyn *dyn = gelf_getdyn (data, j, &dyn_mem);
693               if (dyn != NULL)
694                 switch (dyn->d_tag)
695                   {
696                   case DT_SYMTAB:
697                     addrs[i_symtab] = dyn->d_un.d_ptr;
698                     continue;
699
700                   case DT_HASH:
701                     addrs[i_hash] = dyn->d_un.d_ptr;
702                     continue;
703
704                   case DT_GNU_HASH:
705                     addrs[i_gnu_hash] = dyn->d_un.d_ptr;
706                     continue;
707
708                   case DT_STRTAB:
709                     addrs[i_strtab] = dyn->d_un.d_ptr;
710                     continue;
711
712                   case DT_STRSZ:
713                     strsz = dyn->d_un.d_val;
714                     continue;
715
716                   default:
717                     continue;
718
719                   case DT_NULL:
720                     break;
721                   }
722               break;
723             }
724
725           /* Translate pointers into file offsets.  ADJUST is either zero
726              in case the dynamic segment wasn't adjusted or mod->main_bias.  */
727           void translate_offs (GElf_Addr adjust)
728           {
729             GElf_Off offs[i_max] = { 0, };
730             find_offsets (mod->main.elf, adjust, phnum, i_max, addrs, offs);
731
732             /* Figure out the size of the symbol table.  */
733             if (offs[i_hash] != 0)
734               {
735                 /* In the original format, .hash says the size of .dynsym.  */
736
737                 size_t entsz = SH_ENTSIZE_HASH (ehdr);
738                 data = elf_getdata_rawchunk (mod->main.elf,
739                                              offs[i_hash] + entsz, entsz,
740                                              entsz == 4 ? ELF_T_WORD
741                                              : ELF_T_XWORD);
742                 if (data != NULL)
743                   mod->syments = (entsz == 4
744                                   ? *(const GElf_Word *) data->d_buf
745                                   : *(const GElf_Xword *) data->d_buf);
746               }
747             if (offs[i_gnu_hash] != 0 && mod->syments == 0)
748               {
749                 /* In the new format, we can derive it with some work.  */
750
751                 const struct
752                 {
753                   Elf32_Word nbuckets;
754                   Elf32_Word symndx;
755                   Elf32_Word maskwords;
756                   Elf32_Word shift2;
757                 } *header;
758
759                 data = elf_getdata_rawchunk (mod->main.elf, offs[i_gnu_hash],
760                                              sizeof *header, ELF_T_WORD);
761                 if (data != NULL)
762                   {
763                     header = data->d_buf;
764                     Elf32_Word nbuckets = header->nbuckets;
765                     Elf32_Word symndx = header->symndx;
766                     GElf_Off buckets_at = (offs[i_gnu_hash] + sizeof *header
767                                            + (gelf_getclass (mod->main.elf)
768                                               * sizeof (Elf32_Word)
769                                               * header->maskwords));
770
771                     // elf_getdata_rawchunk takes a size_t, make sure it
772                     // doesn't overflow.
773 #if SIZE_MAX <= UINT32_MAX
774                     if (nbuckets > SIZE_MAX / sizeof (Elf32_Word))
775                       data = NULL;
776                     else
777 #endif
778                       data
779                          = elf_getdata_rawchunk (mod->main.elf, buckets_at,
780                                                  nbuckets * sizeof (Elf32_Word),
781                                                  ELF_T_WORD);
782                     if (data != NULL && symndx < nbuckets)
783                       {
784                         const Elf32_Word *const buckets = data->d_buf;
785                         Elf32_Word maxndx = symndx;
786                         for (Elf32_Word bucket = 0; bucket < nbuckets; ++bucket)
787                           if (buckets[bucket] > maxndx)
788                             maxndx = buckets[bucket];
789
790                         GElf_Off hasharr_at = (buckets_at
791                                                + nbuckets * sizeof (Elf32_Word));
792                         hasharr_at += (maxndx - symndx) * sizeof (Elf32_Word);
793                         do
794                           {
795                             data = elf_getdata_rawchunk (mod->main.elf,
796                                                          hasharr_at,
797                                                          sizeof (Elf32_Word),
798                                                          ELF_T_WORD);
799                             if (data != NULL
800                                 && (*(const Elf32_Word *) data->d_buf & 1u))
801                               {
802                                 mod->syments = maxndx + 1;
803                                 break;
804                               }
805                             ++maxndx;
806                             hasharr_at += sizeof (Elf32_Word);
807                           } while (data != NULL);
808                       }
809                   }
810               }
811             if (offs[i_strtab] > offs[i_symtab] && mod->syments == 0)
812               mod->syments = ((offs[i_strtab] - offs[i_symtab])
813                               / gelf_fsize (mod->main.elf,
814                                             ELF_T_SYM, 1, EV_CURRENT));
815
816             if (mod->syments > 0)
817               {
818                 mod->symdata = elf_getdata_rawchunk (mod->main.elf,
819                                                      offs[i_symtab],
820                                                      gelf_fsize (mod->main.elf,
821                                                                  ELF_T_SYM,
822                                                                  mod->syments,
823                                                                  EV_CURRENT),
824                                                      ELF_T_SYM);
825                 if (mod->symdata != NULL)
826                   {
827                     mod->symstrdata = elf_getdata_rawchunk (mod->main.elf,
828                                                             offs[i_strtab],
829                                                             strsz,
830                                                             ELF_T_BYTE);
831                     if (mod->symstrdata == NULL)
832                       mod->symdata = NULL;
833                   }
834                 if (mod->symdata == NULL)
835                   mod->symerr = DWFL_E (LIBELF, elf_errno ());
836                 else
837                   {
838                     mod->symfile = &mod->main;
839                     mod->symerr = DWFL_E_NOERROR;
840                   }
841               }
842           }
843
844           /* First try unadjusted, like ELF files from disk, vdso.
845              Then try for already adjusted dynamic section, like ELF
846              from remote memory.  */
847           translate_offs (0);
848           if (mod->symfile == NULL)
849             translate_offs (mod->main_bias);
850
851           return;
852         }
853     }
854 }
855
856
857 #if USE_LZMA
858 /* Try to find the offset between the main file and .gnu_debugdata.  */
859 static bool
860 find_aux_address_sync (Dwfl_Module *mod)
861 {
862   /* Don't trust the phdrs in the minisymtab elf file to be setup correctly.
863      The address_sync is equal to the main file it is embedded in at first.  */
864   mod->aux_sym.address_sync = mod->main.address_sync;
865
866   /* Adjust address_sync for the difference in entry addresses, attempting to
867      account for ELF relocation changes after aux was split.  */
868   GElf_Ehdr ehdr_main, ehdr_aux;
869   if (unlikely (gelf_getehdr (mod->main.elf, &ehdr_main) == NULL)
870       || unlikely (gelf_getehdr (mod->aux_sym.elf, &ehdr_aux) == NULL))
871     return false;
872   mod->aux_sym.address_sync += ehdr_aux.e_entry - ehdr_main.e_entry;
873
874   /* The shdrs are setup OK to make find_prelink_address_sync () do the right
875      thing, which is possibly more reliable, but it needs .gnu.prelink_undo.  */
876   if (mod->aux_sym.address_sync != 0)
877     return find_prelink_address_sync (mod, &mod->aux_sym) == DWFL_E_NOERROR;
878
879   return true;
880 }
881 #endif
882
883 /* Try to find the auxiliary symbol table embedded in the main elf file
884    section .gnu_debugdata.  Only matters if the symbol information comes
885    from the main file dynsym.  No harm done if not found.  */
886 static void
887 find_aux_sym (Dwfl_Module *mod __attribute__ ((unused)),
888               Elf_Scn **aux_symscn __attribute__ ((unused)),
889               Elf_Scn **aux_xndxscn __attribute__ ((unused)),
890               GElf_Word *aux_strshndx __attribute__ ((unused)))
891 {
892   /* Since a .gnu_debugdata section is compressed using lzma don't do
893      anything unless we have support for that.  */
894 #if USE_LZMA
895   Elf *elf = mod->main.elf;
896
897   size_t shstrndx;
898   if (elf_getshdrstrndx (elf, &shstrndx) < 0)
899     return;
900
901   Elf_Scn *scn = NULL;
902   while ((scn = elf_nextscn (elf, scn)) != NULL)
903     {
904       GElf_Shdr shdr_mem;
905       GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
906       if (shdr == NULL)
907         return;
908
909       const char *name = elf_strptr (elf, shstrndx, shdr->sh_name);
910       if (name == NULL)
911         return;
912
913       if (!strcmp (name, ".gnu_debugdata"))
914         break;
915     }
916
917   if (scn == NULL)
918     return;
919
920   /* Found the .gnu_debugdata section.  Uncompress the lzma image and
921      turn it into an ELF image.  */
922   Elf_Data *rawdata = elf_rawdata (scn, NULL);
923   if (rawdata == NULL)
924     return;
925
926   Dwfl_Error error;
927   void *buffer = NULL;
928   size_t size = 0;
929   error = __libdw_unlzma (-1, 0, rawdata->d_buf, rawdata->d_size,
930                           &buffer, &size);
931   if (error == DWFL_E_NOERROR)
932     {
933       if (unlikely (size == 0))
934         free (buffer);
935       else
936         {
937           mod->aux_sym.elf = elf_memory (buffer, size);
938           if (mod->aux_sym.elf == NULL)
939             free (buffer);
940           else
941             {
942               mod->aux_sym.fd = -1;
943               mod->aux_sym.elf->flags |= ELF_F_MALLOCED;
944               if (open_elf (mod, &mod->aux_sym) != DWFL_E_NOERROR)
945                 return;
946               if (! find_aux_address_sync (mod))
947                 {
948                   elf_end (mod->aux_sym.elf);
949                   mod->aux_sym.elf = NULL;
950                   return;
951                 }
952
953               /* So far, so good. Get minisymtab table data and cache it. */
954               bool minisymtab = false;
955               scn = NULL;
956               while ((scn = elf_nextscn (mod->aux_sym.elf, scn)) != NULL)
957                 {
958                   GElf_Shdr shdr_mem, *shdr = gelf_getshdr (scn, &shdr_mem);
959                   if (shdr != NULL)
960                     switch (shdr->sh_type)
961                       {
962                       case SHT_SYMTAB:
963                         minisymtab = true;
964                         *aux_symscn = scn;
965                         *aux_strshndx = shdr->sh_link;
966                         mod->aux_syments = shdr->sh_size / shdr->sh_entsize;
967                         mod->aux_first_global = shdr->sh_info;
968                         if (*aux_xndxscn != NULL)
969                           return;
970                         break;
971
972                       case SHT_SYMTAB_SHNDX:
973                         *aux_xndxscn = scn;
974                         if (minisymtab)
975                           return;
976                         break;
977
978                       default:
979                         break;
980                       }
981                 }
982
983               if (minisymtab)
984                 /* We found one, though no SHT_SYMTAB_SHNDX to go with it.  */
985                 return;
986
987               /* We found no SHT_SYMTAB, so everything else is bogus.  */
988               *aux_xndxscn = NULL;
989               *aux_strshndx = 0;
990               mod->aux_syments = 0;
991               elf_end (mod->aux_sym.elf);
992               mod->aux_sym.elf = NULL;
993               return;
994             }
995         }
996     }
997   else
998     free (buffer);
999 #endif
1000 }
1001
1002 /* Try to find a symbol table in either MOD->main.elf or MOD->debug.elf.  */
1003 static void
1004 find_symtab (Dwfl_Module *mod)
1005 {
1006   if (mod->symdata != NULL || mod->aux_symdata != NULL  /* Already done.  */
1007       || mod->symerr != DWFL_E_NOERROR) /* Cached previous failure.  */
1008     return;
1009
1010   __libdwfl_getelf (mod);
1011   mod->symerr = mod->elferr;
1012   if (mod->symerr != DWFL_E_NOERROR)
1013     return;
1014
1015   /* First see if the main ELF file has the debugging information.  */
1016   Elf_Scn *symscn = NULL, *xndxscn = NULL;
1017   Elf_Scn *aux_symscn = NULL, *aux_xndxscn = NULL;
1018   GElf_Word strshndx, aux_strshndx = 0;
1019   mod->symerr = load_symtab (&mod->main, &mod->symfile, &symscn,
1020                              &xndxscn, &mod->syments, &mod->first_global,
1021                              &strshndx);
1022   switch (mod->symerr)
1023     {
1024     default:
1025       return;
1026
1027     case DWFL_E_NOERROR:
1028       break;
1029
1030     case DWFL_E_NO_SYMTAB:
1031       /* Now we have to look for a separate debuginfo file.  */
1032       mod->symerr = find_debuginfo (mod);
1033       switch (mod->symerr)
1034         {
1035         default:
1036           return;
1037
1038         case DWFL_E_NOERROR:
1039           mod->symerr = load_symtab (&mod->debug, &mod->symfile, &symscn,
1040                                      &xndxscn, &mod->syments,
1041                                      &mod->first_global, &strshndx);
1042           break;
1043
1044         case DWFL_E_CB:         /* The find_debuginfo hook failed.  */
1045           mod->symerr = DWFL_E_NO_SYMTAB;
1046           break;
1047         }
1048
1049       switch (mod->symerr)
1050         {
1051         default:
1052           return;
1053
1054         case DWFL_E_NOERROR:
1055           break;
1056
1057         case DWFL_E_NO_SYMTAB:
1058           /* There might be an auxiliary table.  */
1059           find_aux_sym (mod, &aux_symscn, &aux_xndxscn, &aux_strshndx);
1060
1061           if (symscn != NULL)
1062             {
1063               /* We still have the dynamic symbol table.  */
1064               mod->symerr = DWFL_E_NOERROR;
1065               break;
1066             }
1067
1068           if (aux_symscn != NULL)
1069             {
1070               /* We still have the auxiliary symbol table.  */
1071               mod->symerr = DWFL_E_NOERROR;
1072               goto aux_cache;
1073             }
1074
1075           /* Last ditch, look for dynamic symbols without section headers.  */
1076           find_dynsym (mod);
1077           return;
1078         }
1079       break;
1080     }
1081
1082   /* This does some sanity checks on the string table section.  */
1083   if (elf_strptr (mod->symfile->elf, strshndx, 0) == NULL)
1084     {
1085     elferr:
1086       mod->symerr = DWFL_E (LIBELF, elf_errno ());
1087       goto aux_cleanup;
1088     }
1089
1090   /* Cache the data; MOD->syments and MOD->first_global were set above.  */
1091
1092   mod->symstrdata = elf_getdata (elf_getscn (mod->symfile->elf, strshndx),
1093                                  NULL);
1094   if (mod->symstrdata == NULL || mod->symstrdata->d_buf == NULL)
1095     goto elferr;
1096
1097   if (xndxscn == NULL)
1098     mod->symxndxdata = NULL;
1099   else
1100     {
1101       mod->symxndxdata = elf_getdata (xndxscn, NULL);
1102       if (mod->symxndxdata == NULL || mod->symxndxdata->d_buf == NULL)
1103         goto elferr;
1104     }
1105
1106   mod->symdata = elf_getdata (symscn, NULL);
1107   if (mod->symdata == NULL || mod->symdata->d_buf == NULL)
1108     goto elferr;
1109
1110   // Sanity check number of symbols.
1111   GElf_Shdr shdr_mem, *shdr = gelf_getshdr (symscn, &shdr_mem);
1112   if (mod->syments > mod->symdata->d_size / shdr->sh_entsize
1113       || (size_t) mod->first_global > mod->syments)
1114     goto elferr;
1115
1116   /* Cache any auxiliary symbol info, when it fails, just ignore aux_sym.  */
1117   if (aux_symscn != NULL)
1118     {
1119   aux_cache:
1120       /* This does some sanity checks on the string table section.  */
1121       if (elf_strptr (mod->aux_sym.elf, aux_strshndx, 0) == NULL)
1122         {
1123         aux_cleanup:
1124           mod->aux_syments = 0;
1125           elf_end (mod->aux_sym.elf);
1126           mod->aux_sym.elf = NULL;
1127           return;
1128         }
1129
1130       mod->aux_symstrdata = elf_getdata (elf_getscn (mod->aux_sym.elf,
1131                                                      aux_strshndx),
1132                                          NULL);
1133       if (mod->aux_symstrdata == NULL || mod->aux_symstrdata->d_buf == NULL)
1134         goto aux_cleanup;
1135
1136       if (aux_xndxscn == NULL)
1137         mod->aux_symxndxdata = NULL;
1138       else
1139         {
1140           mod->aux_symxndxdata = elf_getdata (aux_xndxscn, NULL);
1141           if (mod->aux_symxndxdata == NULL
1142               || mod->aux_symxndxdata->d_buf == NULL)
1143             goto aux_cleanup;
1144         }
1145
1146       mod->aux_symdata = elf_getdata (aux_symscn, NULL);
1147       if (mod->aux_symdata == NULL || mod->aux_symdata->d_buf == NULL)
1148         goto aux_cleanup;
1149
1150       // Sanity check number of aux symbols.
1151       shdr = gelf_getshdr (aux_symscn, &shdr_mem);
1152       if (mod->aux_syments > mod->aux_symdata->d_size / shdr->sh_entsize
1153           || (size_t) mod->aux_first_global > mod->aux_syments)
1154         goto aux_cleanup;
1155     }
1156 }
1157
1158
1159 /* Try to open a libebl backend for MOD.  */
1160 Dwfl_Error
1161 internal_function
1162 __libdwfl_module_getebl (Dwfl_Module *mod)
1163 {
1164   if (mod->ebl == NULL)
1165     {
1166       __libdwfl_getelf (mod);
1167       if (mod->elferr != DWFL_E_NOERROR)
1168         return mod->elferr;
1169
1170       mod->ebl = ebl_openbackend (mod->main.elf);
1171       if (mod->ebl == NULL)
1172         return DWFL_E_LIBEBL;
1173     }
1174   return DWFL_E_NOERROR;
1175 }
1176
1177 /* Try to start up libdw on DEBUGFILE.  */
1178 static Dwfl_Error
1179 load_dw (Dwfl_Module *mod, struct dwfl_file *debugfile)
1180 {
1181   if (mod->e_type == ET_REL && !debugfile->relocated)
1182     {
1183       const Dwfl_Callbacks *const cb = mod->dwfl->callbacks;
1184
1185       /* The debugging sections have to be relocated.  */
1186       if (cb->section_address == NULL)
1187         return DWFL_E_NOREL;
1188
1189       Dwfl_Error error = __libdwfl_module_getebl (mod);
1190       if (error != DWFL_E_NOERROR)
1191         return error;
1192
1193       find_symtab (mod);
1194       Dwfl_Error result = mod->symerr;
1195       if (result == DWFL_E_NOERROR)
1196         result = __libdwfl_relocate (mod, debugfile->elf, true);
1197       if (result != DWFL_E_NOERROR)
1198         return result;
1199
1200       /* Don't keep the file descriptors around.  */
1201       if (mod->main.fd != -1 && elf_cntl (mod->main.elf, ELF_C_FDREAD) == 0)
1202         {
1203           close (mod->main.fd);
1204           mod->main.fd = -1;
1205         }
1206       if (debugfile->fd != -1 && elf_cntl (debugfile->elf, ELF_C_FDREAD) == 0)
1207         {
1208           close (debugfile->fd);
1209           debugfile->fd = -1;
1210         }
1211     }
1212
1213   mod->dw = INTUSE(dwarf_begin_elf) (debugfile->elf, DWARF_C_READ, NULL);
1214   if (mod->dw == NULL)
1215     {
1216       int err = INTUSE(dwarf_errno) ();
1217       return err == DWARF_E_NO_DWARF ? DWFL_E_NO_DWARF : DWFL_E (LIBDW, err);
1218     }
1219
1220   /* Until we have iterated through all CU's, we might do lazy lookups.  */
1221   mod->lazycu = 1;
1222
1223   return DWFL_E_NOERROR;
1224 }
1225
1226 /* Try to start up libdw on either the main file or the debuginfo file.  */
1227 static void
1228 find_dw (Dwfl_Module *mod)
1229 {
1230   if (mod->dw != NULL           /* Already done.  */
1231       || mod->dwerr != DWFL_E_NOERROR) /* Cached previous failure.  */
1232     return;
1233
1234   __libdwfl_getelf (mod);
1235   mod->dwerr = mod->elferr;
1236   if (mod->dwerr != DWFL_E_NOERROR)
1237     return;
1238
1239   /* First see if the main ELF file has the debugging information.  */
1240   mod->dwerr = load_dw (mod, &mod->main);
1241   switch (mod->dwerr)
1242     {
1243     case DWFL_E_NOERROR:
1244       mod->debug.elf = mod->main.elf;
1245       mod->debug.address_sync = mod->main.address_sync;
1246
1247       /* The Dwarf might need an alt debug file, find that now after
1248          everything about the debug file has been setup (the
1249          find_debuginfo callback might need it).  */
1250       find_debug_altlink (mod, mod->main.name);
1251       return;
1252
1253     case DWFL_E_NO_DWARF:
1254       break;
1255
1256     default:
1257       goto canonicalize;
1258     }
1259
1260   /* Now we have to look for a separate debuginfo file.  */
1261   mod->dwerr = find_debuginfo (mod);
1262   switch (mod->dwerr)
1263     {
1264     case DWFL_E_NOERROR:
1265       mod->dwerr = load_dw (mod, &mod->debug);
1266       if (mod->dwerr == DWFL_E_NOERROR)
1267         {
1268           /* The Dwarf might need an alt debug file, find that now after
1269              everything about the debug file has been setup (the
1270              find_debuginfo callback might need it).  */
1271           find_debug_altlink (mod, mod->debug.name);
1272           return;
1273         }
1274
1275       break;
1276
1277     case DWFL_E_CB:             /* The find_debuginfo hook failed.  */
1278       mod->dwerr = DWFL_E_NO_DWARF;
1279       return;
1280
1281     default:
1282       break;
1283     }
1284
1285  canonicalize:
1286   mod->dwerr = __libdwfl_canon_error (mod->dwerr);
1287 }
1288
1289 Dwarf *
1290 dwfl_module_getdwarf (Dwfl_Module *mod, Dwarf_Addr *bias)
1291 {
1292   if (mod == NULL)
1293     return NULL;
1294
1295   find_dw (mod);
1296   if (mod->dwerr == DWFL_E_NOERROR)
1297     {
1298       /* If dwfl_module_getelf was used previously, then partial apply
1299          relocation to miscellaneous sections in the debug file too.  */
1300       if (mod->e_type == ET_REL
1301           && mod->main.relocated && ! mod->debug.relocated)
1302         {
1303           mod->debug.relocated = true;
1304           if (mod->debug.elf != mod->main.elf)
1305             (void) __libdwfl_relocate (mod, mod->debug.elf, false);
1306         }
1307
1308       *bias = dwfl_adjusted_dwarf_addr (mod, 0);
1309       return mod->dw;
1310     }
1311
1312   __libdwfl_seterrno (mod->dwerr);
1313   return NULL;
1314 }
1315 INTDEF (dwfl_module_getdwarf)
1316
1317 int
1318 dwfl_module_getsymtab (Dwfl_Module *mod)
1319 {
1320   if (mod == NULL)
1321     return -1;
1322
1323   find_symtab (mod);
1324   if (mod->symerr == DWFL_E_NOERROR)
1325     /* We will skip the auxiliary zero entry if there is another one.  */
1326     return (mod->syments + mod->aux_syments
1327             - (mod->syments > 0 && mod->aux_syments > 0 ? 1 : 0));
1328
1329   __libdwfl_seterrno (mod->symerr);
1330   return -1;
1331 }
1332 INTDEF (dwfl_module_getsymtab)
1333
1334 int
1335 dwfl_module_getsymtab_first_global (Dwfl_Module *mod)
1336 {
1337   if (mod == NULL)
1338     return -1;
1339
1340   find_symtab (mod);
1341   if (mod->symerr == DWFL_E_NOERROR)
1342     {
1343       /* All local symbols should come before all global symbols.  If
1344          we have an auxiliary table make sure all the main locals come
1345          first, then all aux locals, then all main globals and finally all
1346          aux globals.  And skip the auxiliary table zero undefined
1347          entry.  */
1348       int skip_aux_zero = (mod->syments > 0 && mod->aux_syments > 0) ? 1 : 0;
1349       return mod->first_global + mod->aux_first_global - skip_aux_zero;
1350     }
1351
1352   __libdwfl_seterrno (mod->symerr);
1353   return -1;
1354 }
1355 INTDEF (dwfl_module_getsymtab_first_global)