Coverage Report

Created: 2025-11-06 06:34

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/elfutils/libdwfl/dwfl_segment_report_module.c
Line
Count
Source
1
/* Sniff out modules from ELF headers visible in memory segments.
2
   Copyright (C) 2008-2012, 2014, 2015, 2018 Red Hat, Inc.
3
   Copyright (C) 2021 Mark J. Wielaard <mark@klomp.org>
4
   This file is part of elfutils.
5
6
   This file is free software; you can redistribute it and/or modify
7
   it under the terms of either
8
9
     * the GNU Lesser General Public License as published by the Free
10
       Software Foundation; either version 3 of the License, or (at
11
       your option) any later version
12
13
   or
14
15
     * the GNU General Public License as published by the Free
16
       Software Foundation; either version 2 of the License, or (at
17
       your option) any later version
18
19
   or both in parallel, as here.
20
21
   elfutils is distributed in the hope that it will be useful, but
22
   WITHOUT ANY WARRANTY; without even the implied warranty of
23
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24
   General Public License for more details.
25
26
   You should have received copies of the GNU General Public License and
27
   the GNU Lesser General Public License along with this program.  If
28
   not, see <http://www.gnu.org/licenses/>.  */
29
30
#include <config.h>
31
#include "libelfP.h"  /* For NOTE_ALIGN4 and NOTE_ALIGN8.  */
32
#include "libdwflP.h"
33
#include "common.h"
34
35
#include <elf.h>
36
#include <gelf.h>
37
#include <inttypes.h>
38
#include <fcntl.h>
39
40
#ifdef HAVE_OPENAT2_RESOLVE_IN_ROOT
41
#include <linux/openat2.h>
42
#include <sys/syscall.h>
43
#include <unistd.h>
44
#endif
45
46
#include <system.h>
47
48
49
/* A good size for the initial read from memory, if it's not too costly.
50
   This more than covers the phdrs and note segment in the average 64-bit
51
   binary.  */
52
53
373k
#define INITIAL_READ  1024
54
55
#if BYTE_ORDER == LITTLE_ENDIAN
56
586k
# define MY_ELFDATA ELFDATA2LSB
57
#else
58
# define MY_ELFDATA ELFDATA2MSB
59
#endif
60
61
struct elf_build_id
62
{
63
  void *memory;
64
  size_t len;
65
  GElf_Addr vaddr;
66
};
67
68
struct read_state
69
{
70
  Dwfl *dwfl;
71
  Dwfl_Memory_Callback *memory_callback;
72
  void *memory_callback_arg;
73
  void **buffer;
74
  size_t *buffer_available;
75
};
76
77
/* Return user segment index closest to ADDR but not above it.
78
   If NEXT, return the closest to ADDR but not below it.  */
79
static int
80
addr_segndx (Dwfl *dwfl, size_t segment, GElf_Addr addr, bool next)
81
197k
{
82
197k
  int ndx = -1;
83
197k
  do
84
2.06M
    {
85
2.06M
      if (dwfl->lookup_segndx[segment] >= 0)
86
1.00M
  ndx = dwfl->lookup_segndx[segment];
87
2.06M
      if (++segment >= dwfl->lookup_elts - 1)
88
85.2k
  return next ? ndx + 1 : ndx;
89
2.06M
    }
90
1.98M
  while (dwfl->lookup_addr[segment] < addr);
91
92
111k
  if (next)
93
0
    {
94
0
      while (dwfl->lookup_segndx[segment] < 0)
95
0
  if (++segment >= dwfl->lookup_elts - 1)
96
0
    return ndx + 1;
97
0
      ndx = dwfl->lookup_segndx[segment];
98
0
    }
99
100
111k
  return ndx;
101
111k
}
102
103
/* Return whether there is SZ bytes available at PTR till END.  */
104
105
static bool
106
buf_has_data (const void *ptr, const void *end, size_t sz)
107
488k
{
108
488k
  return ptr < end && (size_t) (end - ptr) >= sz;
109
488k
}
110
111
/* Read SZ bytes into *RETP from *PTRP (limited by END) in format EI_DATA.
112
   Function comes from src/readelf.c .  */
113
114
static bool
115
buf_read_ulong (unsigned char ei_data, size_t sz,
116
    const void **ptrp, const void *end, uint64_t *retp)
117
488k
{
118
488k
  if (! buf_has_data (*ptrp, end, sz))
119
449
    return false;
120
121
487k
  union
122
487k
  {
123
487k
    uint64_t u64;
124
487k
    uint32_t u32;
125
487k
  } u;
126
127
487k
  memcpy (&u, *ptrp, sz);
128
487k
  (*ptrp) += sz;
129
130
487k
  if (retp == NULL)
131
4.43k
    return true;
132
133
483k
  if (MY_ELFDATA != ei_data)
134
472k
    {
135
472k
      if (sz == 4)
136
469k
  CONVERT (u.u32);
137
2.52k
      else
138
2.52k
  CONVERT (u.u64);
139
472k
    }
140
483k
  if (sz == 4)
141
470k
    *retp = u.u32;
142
12.7k
  else
143
12.7k
    *retp = u.u64;
144
483k
  return true;
145
487k
}
146
147
/* Try to find matching entry for module from address MODULE_START to
148
   MODULE_END in NT_FILE note located at NOTE_FILE of NOTE_FILE_SIZE
149
   bytes in format EI_CLASS and EI_DATA.  */
150
151
static const char *
152
handle_file_note (GElf_Addr module_start, GElf_Addr module_end,
153
      unsigned char ei_class, unsigned char ei_data,
154
      const void *note_file, size_t note_file_size)
155
41.9k
{
156
41.9k
  if (note_file == NULL)
157
37.0k
    return NULL;
158
159
4.88k
  size_t sz;
160
4.88k
  switch (ei_class)
161
4.88k
    {
162
4.01k
    case ELFCLASS32:
163
4.01k
      sz = 4;
164
4.01k
      break;
165
870
    case ELFCLASS64:
166
870
      sz = 8;
167
870
      break;
168
0
    default:
169
0
      return NULL;
170
4.88k
    }
171
172
4.88k
  const void *ptr = note_file;
173
4.88k
  const void *end = note_file + note_file_size;
174
4.88k
  uint64_t count;
175
4.88k
  if (! buf_read_ulong (ei_data, sz, &ptr, end, &count))
176
195
    return NULL;
177
4.68k
  if (! buf_read_ulong (ei_data, sz, &ptr, end, NULL)) // page_size
178
254
    return NULL;
179
180
4.43k
  uint64_t maxcount = (size_t) (end - ptr) / (3 * sz);
181
4.43k
  if (count > maxcount)
182
646
    return NULL;
183
184
  /* Where file names are stored.  */
185
3.78k
  const char *fptr = ptr + 3 * count * sz;
186
187
3.78k
  ssize_t firstix = -1;
188
3.78k
  ssize_t lastix = -1;
189
162k
  for (size_t mix = 0; mix < count; mix++)
190
159k
    {
191
159k
      uint64_t mstart, mend, moffset;
192
159k
      if (! buf_read_ulong (ei_data, sz, &ptr, fptr, &mstart)
193
159k
    || ! buf_read_ulong (ei_data, sz, &ptr, fptr, &mend)
194
159k
    || ! buf_read_ulong (ei_data, sz, &ptr, fptr, &moffset))
195
0
  return NULL;
196
159k
      if (mstart == module_start && moffset == 0)
197
3.77k
  firstix = lastix = mix;
198
159k
      if (firstix != -1 && mstart < module_end)
199
140k
  lastix = mix;
200
159k
      if (mend >= module_end)
201
876
  break;
202
159k
    }
203
3.78k
  if (firstix == -1)
204
1.26k
    return NULL;
205
206
2.52k
  const char *retval = NULL;
207
83.5k
  for (ssize_t mix = 0; mix <= lastix; mix++)
208
81.9k
    {
209
81.9k
      const char *fnext = memchr (fptr, 0, (const char *) end - fptr);
210
81.9k
      if (fnext == NULL)
211
395
  return NULL;
212
81.5k
      if (mix == firstix)
213
2.14k
  retval = fptr;
214
81.5k
      if (firstix < mix && mix <= lastix && strcmp (fptr, retval) != 0)
215
460
  return NULL;
216
81.0k
      fptr = fnext + 1;
217
81.0k
    }
218
1.66k
  return retval;
219
2.52k
}
220
221
/* Return true iff we are certain ELF cannot match BUILD_ID of
222
   BUILD_ID_LEN bytes.  Pass DISK_FILE_HAS_BUILD_ID as false if it is
223
   certain ELF does not contain build-id (it is only a performance hit
224
   to pass it always as true).  */
225
226
static bool
227
invalid_elf (Elf *elf, bool disk_file_has_build_id,
228
             struct elf_build_id *build_id)
229
2.33k
{
230
2.33k
  if (! disk_file_has_build_id && build_id->len > 0)
231
0
    {
232
      /* Module found in segments with build-id is more reliable
233
   than a module found via DT_DEBUG on disk without any
234
   build-id.   */
235
0
      return true;
236
0
    }
237
2.33k
  if (disk_file_has_build_id && build_id->len > 0)
238
1.99k
    {
239
1.99k
      const void *elf_build_id;
240
1.99k
      ssize_t elf_build_id_len;
241
242
      /* If there is a build id in the elf file, check it.  */
243
1.99k
      elf_build_id_len = INTUSE(dwelf_elf_gnu_build_id) (elf, &elf_build_id);
244
1.99k
      if (elf_build_id_len > 0)
245
1.99k
  {
246
1.99k
    if (build_id->len != (size_t) elf_build_id_len
247
1.20k
        || memcmp (build_id->memory, elf_build_id, build_id->len) != 0)
248
1.99k
      return true;
249
1.99k
  }
250
1.99k
    }
251
340
  return false;
252
2.33k
}
253
254
static void
255
finish_portion (struct read_state *read_state,
256
    void **data, size_t *data_size)
257
232k
{
258
232k
  if (*data_size != 0 && *data != NULL)
259
4.11k
    (*read_state->memory_callback) (read_state->dwfl, -1, data, data_size,
260
4.11k
            0, 0, read_state->memory_callback_arg);
261
232k
}
262
263
static inline bool
264
read_portion (struct read_state *read_state,
265
        void **data, size_t *data_size,
266
        GElf_Addr start, size_t segment,
267
        GElf_Addr vaddr, size_t filesz)
268
308k
{
269
  /* Check whether we will have to read the segment data, or if it
270
     can be returned from the existing buffer.  */
271
308k
  if (filesz > *read_state->buffer_available
272
180k
      || vaddr - start > *read_state->buffer_available - filesz
273
      /* If we're in string mode, then don't consider the buffer we have
274
   sufficient unless it contains the terminator of the string.  */
275
162k
      || (filesz == 0 && memchr (vaddr - start + *read_state->buffer, '\0',
276
1.72k
         (*read_state->buffer_available
277
1.72k
          - (vaddr - start))) == NULL))
278
146k
    {
279
146k
      *data = NULL;
280
146k
      *data_size = filesz;
281
146k
      return !(*read_state->memory_callback) (read_state->dwfl,
282
146k
                addr_segndx (read_state->dwfl,
283
146k
                 segment, vaddr,
284
146k
                 false),
285
146k
                data, data_size, vaddr, filesz,
286
146k
                read_state->memory_callback_arg);
287
146k
    }
288
289
  /* We already have this whole note segment from our initial read.  */
290
162k
  *data = vaddr - start + (*read_state->buffer);
291
162k
  *data_size = 0;
292
162k
  return false;
293
308k
}
294
295
int
296
dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
297
          const char *executable,
298
          Dwfl_Memory_Callback *memory_callback,
299
          void *memory_callback_arg,
300
          Dwfl_Module_Callback *read_eagerly,
301
          void *read_eagerly_arg,
302
          size_t maxread,
303
          const void *note_file, size_t note_file_size,
304
          const struct r_debug_info *r_debug_info)
305
495k
{
306
495k
  size_t segment = ndx;
307
495k
  struct read_state read_state;
308
309
495k
  if (segment >= dwfl->lookup_elts)
310
421k
    segment = dwfl->lookup_elts - 1;
311
312
22.6M
  while (segment > 0
313
22.5M
   && (dwfl->lookup_segndx[segment] > ndx
314
12.3M
       || dwfl->lookup_segndx[segment] == -1))
315
22.1M
    --segment;
316
317
19.5M
  while (dwfl->lookup_segndx[segment] < ndx)
318
19.1M
    if (++segment == dwfl->lookup_elts)
319
121k
      return 0;
320
321
373k
  GElf_Addr start = dwfl->lookup_addr[segment];
322
323
  /* First read in the file header and check its sanity.  */
324
325
373k
  void *buffer = NULL;
326
373k
  size_t buffer_available = INITIAL_READ;
327
373k
  Elf *elf = NULL;
328
373k
  int fd = -1;
329
330
373k
  read_state.dwfl = dwfl;
331
373k
  read_state.memory_callback = memory_callback;
332
373k
  read_state.memory_callback_arg = memory_callback_arg;
333
373k
  read_state.buffer = &buffer;
334
373k
  read_state.buffer_available = &buffer_available;
335
336
  /* We might have to reserve some memory for the phdrs.  Set to NULL
337
     here so we can always safely free it.  */
338
373k
  void *phdrsp = NULL;
339
340
  /* Collect the build ID bits here.  */
341
373k
  struct elf_build_id build_id;
342
373k
  build_id.memory = NULL;
343
373k
  build_id.len = 0;
344
373k
  build_id.vaddr = 0;
345
346
373k
  if (! (*memory_callback) (dwfl, ndx, &buffer, &buffer_available,
347
373k
          start, sizeof (Elf64_Ehdr), memory_callback_arg)
348
72.2k
      || memcmp (buffer, ELFMAG, SELFMAG) != 0)
349
323k
    goto out;
350
351
  /* Extract the information we need from the file header.  */
352
49.9k
  const unsigned char *e_ident;
353
49.9k
  unsigned char ei_class;
354
49.9k
  unsigned char ei_data;
355
49.9k
  uint16_t e_type;
356
49.9k
  union
357
49.9k
  {
358
49.9k
    Elf32_Ehdr e32;
359
49.9k
    Elf64_Ehdr e64;
360
49.9k
  } ehdr;
361
49.9k
  GElf_Off phoff;
362
49.9k
  uint_fast16_t phnum;
363
49.9k
  uint_fast16_t phentsize;
364
49.9k
  GElf_Off shdrs_end;
365
49.9k
  Elf_Data xlatefrom =
366
49.9k
    {
367
49.9k
      .d_type = ELF_T_EHDR,
368
49.9k
      .d_buf = (void *) buffer,
369
49.9k
      .d_version = EV_CURRENT,
370
49.9k
    };
371
49.9k
  Elf_Data xlateto =
372
49.9k
    {
373
49.9k
      .d_type = ELF_T_EHDR,
374
49.9k
      .d_buf = &ehdr,
375
49.9k
      .d_size = sizeof ehdr,
376
49.9k
      .d_version = EV_CURRENT,
377
49.9k
    };
378
49.9k
  e_ident = ((const unsigned char *) buffer);
379
49.9k
  ei_class = e_ident[EI_CLASS];
380
49.9k
  ei_data = e_ident[EI_DATA];
381
  /* buffer may be unaligned, in which case xlatetom would not work.
382
     xlatetom does work when the in and out d_buf are equal (but not
383
     for any other overlap).  */
384
49.9k
  size_t ehdr_align = (ei_class == ELFCLASS32
385
49.9k
           ? __alignof__ (Elf32_Ehdr)
386
49.9k
           : __alignof__ (Elf64_Ehdr));
387
49.9k
  if (((uintptr_t) buffer & (ehdr_align - 1)) != 0)
388
7.75k
    {
389
7.75k
      memcpy (&ehdr, buffer,
390
7.75k
        (ei_class == ELFCLASS32
391
7.75k
         ? sizeof (Elf32_Ehdr)
392
7.75k
         : sizeof (Elf64_Ehdr)));
393
7.75k
      xlatefrom.d_buf = &ehdr;
394
7.75k
    }
395
49.9k
  switch (ei_class)
396
49.9k
    {
397
34.7k
    case ELFCLASS32:
398
34.7k
      xlatefrom.d_size = sizeof (Elf32_Ehdr);
399
34.7k
      if (elf32_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL)
400
210
  goto out;
401
34.5k
      e_type = ehdr.e32.e_type;
402
34.5k
      phoff = ehdr.e32.e_phoff;
403
34.5k
      phnum = ehdr.e32.e_phnum;
404
34.5k
      phentsize = ehdr.e32.e_phentsize;
405
34.5k
      if (phentsize != sizeof (Elf32_Phdr))
406
1.86k
  goto out;
407
      /* NOTE if the number of sections is > 0xff00 then e_shnum
408
   is zero and the actual number would come from the section
409
   zero sh_size field. We ignore this here because getting shdrs
410
   is just a nice bonus (see below in the type == PT_LOAD case
411
   where we trim the last segment).  */
412
32.7k
      shdrs_end = ehdr.e32.e_shoff + ehdr.e32.e_shnum * sizeof (Elf32_Shdr);
413
32.7k
      break;
414
415
14.9k
    case ELFCLASS64:
416
14.9k
      xlatefrom.d_size = sizeof (Elf64_Ehdr);
417
14.9k
      if (elf64_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL)
418
207
  goto out;
419
14.7k
      e_type = ehdr.e64.e_type;
420
14.7k
      phoff = ehdr.e64.e_phoff;
421
14.7k
      phnum = ehdr.e64.e_phnum;
422
14.7k
      phentsize = ehdr.e64.e_phentsize;
423
14.7k
      if (phentsize != sizeof (Elf64_Phdr))
424
390
  goto out;
425
      /* See the NOTE above for shdrs_end and ehdr.e32.e_shnum.  */
426
14.3k
      shdrs_end = ehdr.e64.e_shoff + ehdr.e64.e_shnum * sizeof (Elf64_Shdr);
427
14.3k
      break;
428
429
205
    default:
430
205
      goto out;
431
49.9k
    }
432
433
  /* The file header tells where to find the program headers.
434
     These are what we need to find the boundaries of the module.
435
     Without them, we don't have a module to report.  */
436
437
47.0k
  if (phnum == 0)
438
194
    goto out;
439
440
46.8k
  xlatefrom.d_type = xlateto.d_type = ELF_T_PHDR;
441
46.8k
  xlatefrom.d_size = phnum * phentsize;
442
443
46.8k
  void *ph_buffer = NULL;
444
46.8k
  size_t ph_buffer_size = 0;
445
46.8k
  if (read_portion (&read_state, &ph_buffer, &ph_buffer_size,
446
46.8k
        start, segment,
447
46.8k
        start + phoff, xlatefrom.d_size))
448
1.67k
    goto out;
449
450
45.1k
  xlatefrom.d_buf = ph_buffer;
451
452
45.1k
  bool class32 = ei_class == ELFCLASS32;
453
45.1k
  size_t phdr_size = class32 ? sizeof (Elf32_Phdr) : sizeof (Elf64_Phdr);
454
45.1k
  if (unlikely (phnum > SIZE_MAX / phdr_size))
455
0
    goto out;
456
45.1k
  const size_t phdrsp_bytes = phnum * phdr_size;
457
45.1k
  phdrsp = malloc (phdrsp_bytes);
458
45.1k
  if (unlikely (phdrsp == NULL))
459
0
    goto out;
460
461
45.1k
  xlateto.d_buf = phdrsp;
462
45.1k
  xlateto.d_size = phdrsp_bytes;
463
464
  /* ph_ buffer may be unaligned, in which case xlatetom would not work.
465
     xlatetom does work when the in and out d_buf are equal (but not
466
     for any other overlap).  */
467
45.1k
  size_t phdr_align = (class32
468
45.1k
           ? __alignof__ (Elf32_Phdr)
469
45.1k
           : __alignof__ (Elf64_Phdr));
470
45.1k
  if (((uintptr_t) ph_buffer & (phdr_align - 1)) != 0)
471
34.2k
    {
472
34.2k
      memcpy (phdrsp, ph_buffer, phdrsp_bytes);
473
34.2k
      xlatefrom.d_buf = phdrsp;
474
34.2k
    }
475
476
  /* Track the bounds of the file visible in memory.  */
477
45.1k
  GElf_Off file_trimmed_end = 0; /* Proper p_vaddr + p_filesz end.  */
478
45.1k
  GElf_Off file_end = 0;   /* Rounded up to effective page size.  */
479
45.1k
  GElf_Off contiguous = 0;   /* Visible as contiguous file from START.  */
480
45.1k
  GElf_Off total_filesz = 0;   /* Total size of data to read.  */
481
482
  /* Collect the bias between START and the containing PT_LOAD's p_vaddr.  */
483
45.1k
  GElf_Addr bias = 0;
484
45.1k
  bool found_bias = false;
485
486
  /* Collect the unbiased bounds of the module here.  */
487
45.1k
  GElf_Addr module_start = -1l;
488
45.1k
  GElf_Addr module_end = 0;
489
45.1k
  GElf_Addr module_address_sync = 0;
490
491
  /* If we see PT_DYNAMIC, record it here.  */
492
45.1k
  GElf_Addr dyn_vaddr = 0;
493
45.1k
  GElf_Xword dyn_filesz = 0;
494
495
45.1k
  Elf32_Phdr *p32 = phdrsp;
496
45.1k
  Elf64_Phdr *p64 = phdrsp;
497
45.1k
  if ((ei_class == ELFCLASS32
498
31.2k
       && elf32_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL)
499
45.1k
      || (ei_class == ELFCLASS64
500
13.9k
          && elf64_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL))
501
0
    {
502
0
      found_bias = false; /* Trigger error check */
503
0
    }
504
45.1k
  else
505
45.1k
    {
506
      /* Consider each of the program headers we've read from the image.  */
507
64.5M
      for (uint_fast16_t i = 0; i < phnum; ++i)
508
64.5M
        {
509
64.5M
          bool is32 = (ei_class == ELFCLASS32);
510
64.5M
          GElf_Word type = is32 ? p32[i].p_type : p64[i].p_type;
511
64.5M
          GElf_Addr vaddr = is32 ? p32[i].p_vaddr : p64[i].p_vaddr;
512
64.5M
          GElf_Xword memsz = is32 ? p32[i].p_memsz : p64[i].p_memsz;
513
64.5M
          GElf_Off offset = is32 ? p32[i].p_offset : p64[i].p_offset;
514
64.5M
          GElf_Xword filesz = is32 ? p32[i].p_filesz : p64[i].p_filesz;
515
64.5M
          GElf_Xword align = is32 ? p32[i].p_align : p64[i].p_align;
516
517
64.5M
          if (type == PT_DYNAMIC)
518
210k
            {
519
210k
              dyn_vaddr = vaddr;
520
210k
              dyn_filesz = filesz;
521
210k
            }
522
64.3M
          else if (type == PT_NOTE)
523
297k
            {
524
              /* If we have already seen a build ID, we don't care any more.  */
525
297k
              if (build_id.memory != NULL || filesz == 0)
526
62.0k
                continue; /* Next header */
527
528
              /* We calculate from the p_offset of the note segment,
529
               because we don't yet know the bias for its p_vaddr.  */
530
235k
              const GElf_Addr note_vaddr = start + offset;
531
235k
              void *data = NULL;
532
235k
              size_t data_size = 0;
533
235k
              if (read_portion (&read_state, &data, &data_size,
534
235k
        start, segment, note_vaddr, filesz))
535
132k
                continue; /* Next header */
536
537
103k
        if (filesz > SIZE_MAX / sizeof (Elf32_Nhdr))
538
0
    continue;
539
540
103k
              assert (sizeof (Elf32_Nhdr) == sizeof (Elf64_Nhdr));
541
542
103k
              void *notes;
543
103k
              if (ei_data == MY_ELFDATA
544
47.9k
      && (uintptr_t) data == (align == 8
545
47.9k
            ? NOTE_ALIGN8 ((uintptr_t) data)
546
47.9k
            : NOTE_ALIGN4 ((uintptr_t) data)))
547
34.5k
                notes = data;
548
68.9k
              else
549
68.9k
                {
550
68.9k
                  const unsigned int xencoding = ehdr.e32.e_ident[EI_DATA];
551
552
68.9k
      if (filesz > SIZE_MAX / sizeof (Elf32_Nhdr))
553
0
        continue;
554
68.9k
                  notes = malloc (filesz);
555
68.9k
                  if (unlikely (notes == NULL))
556
0
                    continue; /* Next header */
557
68.9k
                  xlatefrom.d_type = xlateto.d_type = (align == 8
558
68.9k
                                                       ? ELF_T_NHDR8
559
68.9k
                   : ELF_T_NHDR);
560
68.9k
                  xlatefrom.d_buf = (void *) data;
561
68.9k
                  xlatefrom.d_size = filesz;
562
68.9k
                  xlateto.d_buf = notes;
563
68.9k
                  xlateto.d_size = filesz;
564
565
      /* data may be unaligned, in which case xlatetom would not work.
566
         xlatetom does work when the in and out d_buf are equal (but not
567
         for any other overlap).  */
568
68.9k
      if ((uintptr_t) data != (align == 8
569
68.9k
             ? NOTE_ALIGN8 ((uintptr_t) data)
570
68.9k
             : NOTE_ALIGN4 ((uintptr_t) data)))
571
18.1k
        {
572
18.1k
          memcpy (notes, data, filesz);
573
18.1k
          xlatefrom.d_buf = notes;
574
18.1k
        }
575
576
68.9k
                  if (elf32_xlatetom (&xlateto, &xlatefrom, xencoding) == NULL)
577
0
                    {
578
0
                      free (notes);
579
0
                      finish_portion (&read_state, &data, &data_size);
580
0
                      continue;
581
0
                    }
582
68.9k
                }
583
584
103k
              const GElf_Nhdr *nh = notes;
585
103k
              size_t len = 0;
586
152k
              while (filesz - len > sizeof (*nh))
587
97.5k
                {
588
97.5k
      len += sizeof (*nh);
589
590
97.5k
      size_t namesz = nh->n_namesz;
591
97.5k
      namesz = align == 8 ? NOTE_ALIGN8 (namesz) : NOTE_ALIGN4 (namesz);
592
97.5k
      if (namesz > filesz - len || len + namesz < namesz)
593
38.5k
        break;
594
595
58.9k
      void *note_name = notes + len;
596
58.9k
      len += namesz;
597
598
58.9k
      size_t descsz = nh->n_descsz;
599
58.9k
      descsz = align == 8 ? NOTE_ALIGN8 (descsz) : NOTE_ALIGN4 (descsz);
600
58.9k
      if (descsz > filesz - len || len + descsz < descsz)
601
6.64k
        break;
602
603
52.3k
      void *note_desc = notes + len;
604
52.3k
      len += descsz;
605
606
      /* We don't handle very short or really large build-ids.  We need at
607
         at least 3 and allow for up to 64 (normally ids are 20 long).  */
608
57.1k
#define MIN_BUILD_ID_BYTES 3
609
56.7k
#define MAX_BUILD_ID_BYTES 64
610
52.3k
      if (nh->n_type == NT_GNU_BUILD_ID
611
4.86k
          && nh->n_descsz >= MIN_BUILD_ID_BYTES
612
4.44k
          && nh->n_descsz <= MAX_BUILD_ID_BYTES
613
3.94k
          && nh->n_namesz == sizeof "GNU"
614
3.49k
          && !memcmp (note_name, "GNU", sizeof "GNU"))
615
3.02k
        {
616
3.02k
          build_id.vaddr = (note_desc
617
3.02k
          - (const void *) notes
618
3.02k
          + note_vaddr);
619
3.02k
          build_id.len = nh->n_descsz;
620
3.02k
          build_id.memory = malloc (build_id.len);
621
3.02k
          if (likely (build_id.memory != NULL))
622
3.02k
      memcpy (build_id.memory, note_desc, build_id.len);
623
3.02k
          break;
624
3.02k
        }
625
626
49.3k
      nh = (void *) notes + len;
627
49.3k
    }
628
629
103k
              if (notes != data)
630
68.9k
                free (notes);
631
103k
              finish_portion (&read_state, &data, &data_size);
632
103k
            }
633
64.0M
          else if (type == PT_LOAD)
634
1.97M
            {
635
1.97M
              align = (dwfl->segment_align > 1
636
1.97M
                       ? dwfl->segment_align : (align ?: 1));
637
638
1.97M
              GElf_Addr vaddr_end = (vaddr + memsz + align - 1) & -align;
639
1.97M
              GElf_Addr filesz_vaddr = (filesz < memsz
640
1.97M
                                        ? vaddr + filesz : vaddr_end);
641
1.97M
              GElf_Off filesz_offset = filesz_vaddr - vaddr + offset;
642
643
1.97M
              if (file_trimmed_end < offset + filesz)
644
91.3k
                {
645
91.3k
                  file_trimmed_end = offset + filesz;
646
647
                  /* Trim the last segment so we don't bother with zeros
648
                     in the last page that are off the end of the file.
649
                     However, if the extra bit in that page includes the
650
                     section headers, keep them.  */
651
91.3k
                  if (shdrs_end <= filesz_offset
652
45.8k
                      && shdrs_end > file_trimmed_end)
653
1.14k
                    {
654
1.14k
                      filesz += shdrs_end - file_trimmed_end;
655
1.14k
                      file_trimmed_end = shdrs_end;
656
1.14k
                    }
657
91.3k
                }
658
659
1.97M
              total_filesz += filesz;
660
661
1.97M
              if (file_end < filesz_offset)
662
100k
                {
663
100k
                  file_end = filesz_offset;
664
100k
                  if (filesz_vaddr - start == filesz_offset)
665
26.8k
                    contiguous = file_end;
666
100k
                }
667
668
1.97M
              if (!found_bias && (offset & -align) == 0
669
55.8k
                  && likely (filesz_offset >= phoff + phnum * phentsize))
670
43.4k
                {
671
43.4k
                  bias = start - vaddr;
672
43.4k
                  found_bias = true;
673
43.4k
                }
674
675
1.97M
              if ((vaddr & -align) < module_start)
676
57.8k
                {
677
57.8k
                  module_start = vaddr & -align;
678
57.8k
                  module_address_sync = vaddr + memsz;
679
57.8k
                }
680
681
1.97M
              if (module_end < vaddr_end)
682
99.4k
                module_end = vaddr_end;
683
1.97M
            }
684
64.5M
        }
685
45.1k
    }
686
687
45.1k
  finish_portion (&read_state, &ph_buffer, &ph_buffer_size);
688
689
  /* We must have seen the segment covering offset 0, or else the ELF
690
     header we read at START was not produced by these program headers.  */
691
45.1k
  if (unlikely (!found_bias))
692
1.73k
    goto out;
693
694
  /* Now we know enough to report a module for sure: its bounds.  */
695
43.4k
  module_start += bias;
696
43.4k
  module_end += bias;
697
698
43.4k
  dyn_vaddr += bias;
699
700
  /* NAME found from link map has precedence over DT_SONAME possibly read
701
     below.  */
702
43.4k
  bool name_is_final = false;
703
704
  /* Try to match up DYN_VADDR against L_LD as found in link map.
705
     Segments sniffing may guess invalid address as the first read-only memory
706
     mapping may not be dumped to the core file (if ELF headers are not dumped)
707
     and the ELF header is dumped first with the read/write mapping of the same
708
     file at higher addresses.  */
709
43.4k
  if (r_debug_info != NULL)
710
43.4k
    for (const struct r_debug_info_module *module = r_debug_info->module;
711
146k
   module != NULL; module = module->next)
712
105k
      if (module_start <= module->l_ld && module->l_ld < module_end)
713
8.53k
  {
714
    /* L_LD read from link map must be right while DYN_VADDR is unsafe.
715
       Therefore subtract DYN_VADDR and add L_LD to get a possibly
716
       corrective displacement for all addresses computed so far.  */
717
8.53k
    GElf_Addr fixup = module->l_ld - dyn_vaddr;
718
8.53k
    if ((fixup & (dwfl->segment_align - 1)) == 0
719
3.73k
        && module_start + fixup <= module->l_ld
720
2.34k
        && module->l_ld < module_end + fixup)
721
1.99k
      {
722
1.99k
        module_start += fixup;
723
1.99k
        module_end += fixup;
724
1.99k
        dyn_vaddr += fixup;
725
1.99k
        bias += fixup;
726
1.99k
        if (module->name[0] != '\0')
727
1.06k
    {
728
1.06k
      name = xbasename (module->name);
729
1.06k
      name_is_final = true;
730
1.06k
    }
731
1.99k
        break;
732
1.99k
      }
733
8.53k
  }
734
735
43.4k
  if (r_debug_info != NULL)
736
43.4k
    {
737
43.4k
      bool skip_this_module = false;
738
43.4k
      for (struct r_debug_info_module *module = r_debug_info->module;
739
161k
     module != NULL; module = module->next)
740
118k
  if ((module_end > module->start && module_start < module->end)
741
117k
      || dyn_vaddr == module->l_ld)
742
14.5k
    {
743
14.5k
      if (module->elf != NULL
744
1.25k
          && invalid_elf (module->elf, module->disk_file_has_build_id,
745
1.25k
        &build_id))
746
1.24k
        {
747
    /* If MODULE's build-id doesn't match the disk file's
748
       build-id, close ELF only if MODULE and ELF refer to
749
       different builds of files with the same name.  This
750
       prevents premature closure of the correct ELF in cases
751
       where segments of a module are non-contiguous in memory.  */
752
1.24k
    if (name != NULL && module->name[0] != '\0'
753
523
        && strcmp (xbasename (module->name), xbasename (name)) == 0)
754
94
      {
755
94
        elf_end (module->elf);
756
94
        close (module->fd);
757
94
        module->elf = NULL;
758
94
        module->fd = -1;
759
94
      }
760
1.24k
        }
761
13.2k
      else if (module->elf != NULL)
762
5
        {
763
    /* This module has already been reported.  */
764
5
    skip_this_module = true;
765
5
        }
766
13.2k
      else
767
13.2k
        {
768
    /* Only report this module if we haven't already done so.  */
769
26.6k
    for (Dwfl_Module *mod = dwfl->modulelist; mod != NULL;
770
13.3k
         mod = mod->next)
771
13.3k
      if (mod->low_addr == module_start
772
12.4k
          && mod->high_addr == module_end)
773
10.3k
        skip_this_module = true;
774
13.2k
        }
775
14.5k
    }
776
43.4k
      if (skip_this_module)
777
1.46k
  goto out;
778
43.4k
    }
779
780
41.9k
  const char *file_note_name = handle_file_note (module_start, module_end,
781
41.9k
             ei_class, ei_data,
782
41.9k
             note_file, note_file_size);
783
41.9k
  if (file_note_name)
784
1.66k
    {
785
1.66k
      name = file_note_name;
786
1.66k
      name_is_final = true;
787
1.66k
      bool invalid = false;
788
789
      /* We were not handed specific executable hence try to look for it in
790
   sysroot if it is set.  */
791
1.66k
      if (dwfl->sysroot && !executable)
792
0
  {
793
#ifdef HAVE_OPENAT2_RESOLVE_IN_ROOT
794
    int sysrootfd, err;
795
796
    struct open_how how = {
797
      .flags = O_RDONLY,
798
      .resolve = RESOLVE_IN_ROOT,
799
    };
800
801
    sysrootfd = open (dwfl->sysroot, O_DIRECTORY|O_PATH);
802
    if (sysrootfd < 0)
803
      return -1;
804
805
    fd = syscall (SYS_openat2, sysrootfd, name, &how, sizeof(how));
806
    err = fd < 0 ? -errno : 0;
807
808
    close (sysrootfd);
809
810
    /* Fallback to regular open() if openat2 is not available. */
811
    if (fd < 0 && err == -ENOSYS)
812
#endif
813
0
      {
814
0
        int r;
815
0
        char *n;
816
817
0
        r = asprintf (&n, "%s%s", dwfl->sysroot, name);
818
0
        if (r > 0)
819
0
    {
820
0
      fd = open (n, O_RDONLY);
821
0
      free (n);
822
0
    }
823
0
      }
824
0
  }
825
1.66k
      else
826
1.66k
    fd = open (name, O_RDONLY);
827
828
1.66k
      if (fd >= 0)
829
1.27k
  {
830
1.27k
    Dwfl_Error error = __libdw_open_file (&fd, &elf, true, false);
831
1.27k
    if (error == DWFL_E_NOERROR)
832
1.07k
      invalid = invalid_elf (elf, true /* disk_file_has_build_id */,
833
1.07k
                                   &build_id);
834
1.27k
  }
835
1.66k
      if (invalid)
836
744
  {
837
    /* The file was there, but the build_id didn't match.  We
838
       still want to report the module, but need to get the ELF
839
       some other way if possible.  */
840
744
    close (fd);
841
744
    fd = -1;
842
744
    elf_end (elf);
843
744
    elf = NULL;
844
744
  }
845
1.66k
    }
846
847
  /* Examine its .dynamic section to get more interesting details.
848
     If it has DT_SONAME, we'll use that as the module name.
849
     If it has a DT_DEBUG, then it's actually a PIE rather than a DSO.
850
     We need its DT_STRTAB and DT_STRSZ to decipher DT_SONAME,
851
     and they also tell us the essential portion of the file
852
     for fetching symbols.  */
853
41.9k
  GElf_Addr soname_stroff = 0;
854
41.9k
  GElf_Addr dynstr_vaddr = 0;
855
41.9k
  GElf_Xword dynstrsz = 0;
856
41.9k
  bool execlike = false;
857
41.9k
  const size_t dyn_entsize = (ei_class == ELFCLASS32
858
41.9k
            ? sizeof (Elf32_Dyn) : sizeof (Elf64_Dyn));
859
41.9k
  void *dyn_data = NULL;
860
41.9k
  size_t dyn_data_size = 0;
861
41.9k
  if (dyn_filesz != 0 && dyn_filesz % dyn_entsize == 0
862
22.0k
      && ! read_portion (&read_state, &dyn_data, &dyn_data_size,
863
22.0k
       start, segment, dyn_vaddr, dyn_filesz))
864
15.6k
    {
865
15.6k
      if ((dyn_filesz / dyn_entsize) == 0
866
15.6k
    || dyn_filesz > (SIZE_MAX / dyn_entsize))
867
0
  goto out;
868
15.6k
      void *dyns = malloc (dyn_filesz);
869
15.6k
      Elf32_Dyn *d32 = dyns;
870
15.6k
      Elf64_Dyn *d64 = dyns;
871
15.6k
      if (unlikely (dyns == NULL))
872
0
  goto out;
873
874
15.6k
      xlatefrom.d_type = xlateto.d_type = ELF_T_DYN;
875
15.6k
      xlatefrom.d_buf = (void *) dyn_data;
876
15.6k
      xlatefrom.d_size = dyn_filesz;
877
15.6k
      xlateto.d_buf = dyns;
878
15.6k
      xlateto.d_size = dyn_filesz;
879
880
      /* dyn_data may be unaligned, in which case xlatetom would not work.
881
   xlatetom does work when the in and out d_buf are equal (but not
882
   for any other overlap).  */
883
15.6k
      bool is32 = (ei_class == ELFCLASS32);
884
15.6k
      size_t dyn_align = (is32
885
15.6k
        ? __alignof__ (Elf32_Dyn)
886
15.6k
        : __alignof__ (Elf64_Dyn));
887
15.6k
      if (((uintptr_t) dyn_data & (dyn_align - 1)) != 0)
888
9.83k
  {
889
9.83k
    memcpy (dyns, dyn_data, dyn_filesz);
890
9.83k
    xlatefrom.d_buf = dyns;
891
9.83k
  }
892
893
15.6k
      if ((is32 && elf32_xlatetom (&xlateto, &xlatefrom, ei_data) != NULL)
894
2.33k
          || (!is32 && elf64_xlatetom (&xlateto, &xlatefrom, ei_data) != NULL))
895
15.6k
        {
896
15.6k
          size_t n = (is32
897
15.6k
          ? (dyn_filesz / sizeof (Elf32_Dyn))
898
15.6k
          : (dyn_filesz / sizeof (Elf64_Dyn)));
899
5.85M
          for (size_t i = 0; i < n; ++i)
900
5.84M
            {
901
5.84M
              GElf_Sxword tag = is32 ? d32[i].d_tag : d64[i].d_tag;
902
5.84M
              GElf_Xword val = is32 ? d32[i].d_un.d_val : d64[i].d_un.d_val;
903
904
5.84M
              if (tag == DT_DEBUG)
905
6.49k
                execlike = true;
906
5.83M
              else if (tag == DT_SONAME)
907
5.57k
                soname_stroff = val;
908
5.83M
              else if (tag == DT_STRTAB)
909
27.8k
                dynstr_vaddr = val;
910
5.80M
              else if (tag == DT_STRSZ)
911
18.2k
                dynstrsz = val;
912
5.78M
              else
913
5.78M
                continue;
914
915
58.1k
              if (soname_stroff != 0 && dynstr_vaddr != 0 && dynstrsz != 0)
916
4.56k
                break;
917
58.1k
            }
918
15.6k
        }
919
15.6k
      free (dyns);
920
15.6k
    }
921
41.9k
  finish_portion (&read_state, &dyn_data, &dyn_data_size);
922
923
  /* We'll use the name passed in or a stupid default if not DT_SONAME.  */
924
41.9k
  if (name == NULL)
925
40.0k
    name = e_type == ET_EXEC ? "[exe]" : execlike ? "[pie]" : "[dso]";
926
927
41.9k
  void *soname = NULL;
928
41.9k
  size_t soname_size = 0;
929
41.9k
  if (! name_is_final && dynstrsz != 0 && dynstr_vaddr != 0)
930
11.4k
    {
931
      /* We know the bounds of the .dynstr section.
932
933
   The DYNSTR_VADDR pointer comes from the .dynamic section
934
   (DT_STRTAB, detected above).  Ordinarily the dynamic linker
935
   will have adjusted this pointer in place so it's now an
936
   absolute address.  But sometimes .dynamic is read-only (in
937
   vDSOs and odd architectures), and sometimes the adjustment
938
   just hasn't happened yet in the memory image we looked at.
939
   So treat DYNSTR_VADDR as an absolute address if it falls
940
   within the module bounds, or try applying the phdr bias
941
   when that adjusts it to fall within the module bounds.  */
942
943
11.4k
      if ((dynstr_vaddr < module_start || dynstr_vaddr >= module_end)
944
5.65k
    && dynstr_vaddr + bias >= module_start
945
4.46k
    && dynstr_vaddr + bias < module_end)
946
2.97k
  dynstr_vaddr += bias;
947
948
11.4k
      if (unlikely (dynstr_vaddr + dynstrsz > module_end))
949
721
  dynstrsz = 0;
950
951
      /* Try to get the DT_SONAME string.  */
952
11.4k
      if (soname_stroff != 0 && soname_stroff + 1 < dynstrsz
953
3.46k
    && ! read_portion (&read_state, &soname, &soname_size,
954
3.46k
           start, segment,
955
3.46k
           dynstr_vaddr + soname_stroff, 0))
956
1.79k
  name = soname;
957
11.4k
    }
958
959
  /* Now that we have chosen the module's name and bounds, report it.
960
     If we found a build ID, report that too.  */
961
962
41.9k
  Dwfl_Module *mod = INTUSE(dwfl_report_module) (dwfl, name,
963
41.9k
             module_start, module_end);
964
965
  // !execlike && ET_EXEC is PIE.
966
  // execlike && !ET_EXEC is a static executable.
967
41.9k
  if (mod != NULL && (execlike || ehdr.e32.e_type == ET_EXEC))
968
4.64k
    mod->is_executable = true;
969
970
41.9k
  if (likely (mod != NULL) && build_id.memory != NULL
971
2.78k
      && unlikely (INTUSE(dwfl_module_report_build_id) (mod,
972
41.9k
              build_id.memory,
973
41.9k
              build_id.len,
974
41.9k
              build_id.vaddr)))
975
271
    {
976
271
      mod->gc = true;
977
271
      mod = NULL;
978
271
    }
979
980
  /* At this point we do not need BUILD_ID or NAME any more.
981
     They have been copied.  */
982
41.9k
  free (build_id.memory);
983
41.9k
  build_id.memory = NULL;
984
41.9k
  finish_portion (&read_state, &soname, &soname_size);
985
986
41.9k
  if (unlikely (mod == NULL))
987
271
    {
988
271
      ndx = -1;
989
271
      goto out;
990
271
    }
991
41.6k
  else
992
41.6k
    ndx++;
993
994
  /* We have reported the module.  Now let the caller decide whether we
995
     should read the whole thing in right now.  */
996
997
41.6k
  const GElf_Off cost = (contiguous < file_trimmed_end ? total_filesz
998
41.6k
       : buffer_available >= contiguous ? 0
999
10.8k
       : contiguous - buffer_available);
1000
41.6k
  const GElf_Off worthwhile = ((dynstr_vaddr == 0 || dynstrsz == 0) ? 0
1001
41.6k
             : dynstr_vaddr + dynstrsz - start);
1002
41.6k
  const GElf_Off whole = MAX (file_trimmed_end, shdrs_end);
1003
1004
41.6k
  if (elf == NULL
1005
41.3k
      && (*read_eagerly) (MODCB_ARGS (mod), &buffer, &buffer_available,
1006
41.3k
        cost, worthwhile, whole, contiguous,
1007
41.3k
        read_eagerly_arg, &elf)
1008
12.5k
      && elf == NULL)
1009
10.4k
    {
1010
      /* The caller wants to read the whole file in right now, but hasn't
1011
   done it for us.  Fill in a local image of the virtual file.  */
1012
1013
10.4k
      if (file_trimmed_end > maxread)
1014
9.77k
  file_trimmed_end = maxread;
1015
1016
10.4k
      void *contents = calloc (1, file_trimmed_end);
1017
10.4k
      if (unlikely (contents == NULL))
1018
0
  goto out;
1019
1020
10.4k
      if (contiguous < file_trimmed_end)
1021
5.97k
  {
1022
    /* We can't use the memory image verbatim as the file image.
1023
       So we'll be reading into a local image of the virtual file.  */
1024
4.78M
          for (uint_fast16_t i = 0; i < phnum; ++i)
1025
4.77M
            {
1026
4.77M
              bool is32 = (ei_class == ELFCLASS32);
1027
4.77M
              GElf_Word type = is32 ? p32[i].p_type : p64[i].p_type;
1028
1029
4.77M
              if (type != PT_LOAD)
1030
4.68M
                continue;
1031
1032
93.4k
              GElf_Addr vaddr = is32 ? p32[i].p_vaddr : p64[i].p_vaddr;
1033
93.4k
              GElf_Off offset = is32 ? p32[i].p_offset : p64[i].p_offset;
1034
93.4k
              GElf_Xword filesz = is32 ? p32[i].p_filesz : p64[i].p_filesz;
1035
1036
              /* Don't try to read beyond the actual end of file.  */
1037
93.4k
              if (offset >= file_trimmed_end)
1038
43.5k
                continue;
1039
1040
49.8k
              void *into = contents + offset;
1041
49.8k
              size_t read_size = MIN (filesz, file_trimmed_end - offset);
1042
49.8k
              (*memory_callback) (dwfl, addr_segndx (dwfl, segment,
1043
49.8k
                                                     vaddr + bias, false),
1044
49.8k
                                  &into, &read_size, vaddr + bias, read_size,
1045
49.8k
                                  memory_callback_arg);
1046
49.8k
            }
1047
5.97k
  }
1048
4.48k
      else
1049
4.48k
  {
1050
    /* The whole file sits contiguous in memory,
1051
       but the caller didn't want to just do it.  */
1052
1053
4.48k
    const size_t have = MIN (buffer_available, file_trimmed_end);
1054
4.48k
    memcpy (contents, buffer, have);
1055
1056
4.48k
    if (have < file_trimmed_end)
1057
1.20k
            {
1058
1.20k
        void *into = contents + have;
1059
1.20k
        size_t read_size = file_trimmed_end - have;
1060
1.20k
        (*memory_callback) (dwfl,
1061
1.20k
          addr_segndx (dwfl, segment,
1062
1.20k
                 start + have, false),
1063
1.20k
          &into, &read_size, start + have,
1064
1.20k
          read_size, memory_callback_arg);
1065
1.20k
            }
1066
4.48k
  }
1067
1068
10.4k
      elf = elf_memory (contents, file_trimmed_end);
1069
10.4k
      if (unlikely (elf == NULL))
1070
517
  free (contents);
1071
9.94k
      else
1072
9.94k
  elf->flags |= ELF_F_MALLOCED;
1073
10.4k
    }
1074
1075
41.6k
  if (elf != NULL && mod->main.elf == NULL)
1076
1.89k
    {
1077
      /* Install the file in the module.  */
1078
1.89k
      mod->main.elf = elf;
1079
1.89k
      mod->main.fd = fd;
1080
1.89k
      elf = NULL;
1081
1.89k
      fd = -1;
1082
1.89k
      mod->main.vaddr = module_start - bias;
1083
1.89k
      mod->main.address_sync = module_address_sync;
1084
1.89k
      mod->main_bias = bias;
1085
1.89k
    }
1086
1087
373k
out:
1088
373k
  if (build_id.memory != NULL)
1089
244
    free (build_id.memory);
1090
373k
  free (phdrsp);
1091
373k
  if (buffer != NULL)
1092
69.5k
    (*memory_callback) (dwfl, -1, &buffer, &buffer_available, 0, 0,
1093
69.5k
                        memory_callback_arg);
1094
1095
373k
  if (elf != NULL)
1096
10.4k
    elf_end (elf);
1097
373k
  if (fd != -1)
1098
325
    close (fd);
1099
373k
  return ndx;
1100
41.6k
}