Coverage Report

Created: 2026-09-06 06:52

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