Coverage Report

Created: 2026-09-07 06:08

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
#include <system.h>
41
42
43
/* A good size for the initial read from memory, if it's not too costly.
44
   This more than covers the phdrs and note segment in the average 64-bit
45
   binary.  */
46
47
234k
#define INITIAL_READ  1024
48
49
#if BYTE_ORDER == LITTLE_ENDIAN
50
120k
# define MY_ELFDATA ELFDATA2LSB
51
#else
52
# define MY_ELFDATA ELFDATA2MSB
53
#endif
54
55
struct elf_build_id
56
{
57
  void *memory;
58
  size_t len;
59
  GElf_Addr vaddr;
60
};
61
62
struct read_state
63
{
64
  Dwfl *dwfl;
65
  Dwfl_Memory_Callback *memory_callback;
66
  void *memory_callback_arg;
67
  void **buffer;
68
  size_t *buffer_available;
69
};
70
71
/* Return user segment index closest to ADDR but not above it.
72
   If NEXT, return the closest to ADDR but not below it.  */
73
static int
74
addr_segndx (Dwfl *dwfl, size_t segment, GElf_Addr addr, bool next)
75
18.1k
{
76
18.1k
  int ndx = -1;
77
18.1k
  do
78
243k
    {
79
243k
      if (dwfl->lookup_segndx[segment] >= 0)
80
129k
  ndx = dwfl->lookup_segndx[segment];
81
243k
      if (++segment >= dwfl->lookup_elts - 1)
82
9.19k
  return next ? ndx + 1 : ndx;
83
243k
    }
84
234k
  while (dwfl->lookup_addr[segment] < addr);
85
86
8.98k
  if (next)
87
1.34k
    {
88
2.92k
      while (dwfl->lookup_segndx[segment] < 0)
89
2.29k
  if (++segment >= dwfl->lookup_elts - 1)
90
702
    return ndx + 1;
91
639
      ndx = dwfl->lookup_segndx[segment];
92
639
    }
93
94
8.27k
  return ndx;
95
8.98k
}
96
97
/* Return whether there is SZ bytes available at PTR till END.  */
98
99
static bool
100
buf_has_data (const void *ptr, const void *end, size_t sz)
101
115k
{
102
115k
  return ptr < end && (size_t) (end - ptr) >= sz;
103
115k
}
104
105
/* Read SZ bytes into *RETP from *PTRP (limited by END) in format EI_DATA.
106
   Function comes from src/readelf.c .  */
107
108
static bool
109
buf_read_ulong (unsigned char ei_data, size_t sz,
110
    const void **ptrp, const void *end, uint64_t *retp)
111
115k
{
112
115k
  if (! buf_has_data (*ptrp, end, sz))
113
26
    return false;
114
115
115k
  union
116
115k
  {
117
115k
    uint64_t u64;
118
115k
    uint32_t u32;
119
115k
  } u;
120
121
115k
  memcpy (&u, *ptrp, sz);
122
115k
  (*ptrp) += sz;
123
124
115k
  if (retp == NULL)
125
715
    return true;
126
127
115k
  if (MY_ELFDATA != ei_data)
128
111k
    {
129
111k
      if (sz == 4)
130
111k
  CONVERT (u.u32);
131
118
      else
132
118
  CONVERT (u.u64);
133
111k
    }
134
115k
  if (sz == 4)
135
113k
    *retp = u.u32;
136
1.61k
  else
137
1.61k
    *retp = u.u64;
138
115k
  return true;
139
115k
}
140
141
/* Try to find matching entry for module from address MODULE_START to
142
   MODULE_END in NT_FILE note located at NOTE_FILE of NOTE_FILE_SIZE
143
   bytes in format EI_CLASS and EI_DATA.  */
144
145
static const char *
146
handle_file_note (GElf_Addr module_start, GElf_Addr module_end,
147
      unsigned char ei_class, unsigned char ei_data,
148
      const void *note_file, size_t note_file_size)
149
6.41k
{
150
6.41k
  if (note_file == NULL)
151
5.67k
    return NULL;
152
153
741
  size_t sz;
154
741
  switch (ei_class)
155
741
    {
156
456
    case ELFCLASS32:
157
456
      sz = 4;
158
456
      break;
159
285
    case ELFCLASS64:
160
285
      sz = 8;
161
285
      break;
162
0
    default:
163
0
      return NULL;
164
741
    }
165
166
741
  const void *ptr = note_file;
167
741
  const void *end = note_file + note_file_size;
168
741
  uint64_t count;
169
741
  if (! buf_read_ulong (ei_data, sz, &ptr, end, &count))
170
14
    return NULL;
171
727
  if (! buf_read_ulong (ei_data, sz, &ptr, end, NULL)) // page_size
172
12
    return NULL;
173
174
715
  uint64_t maxcount = (size_t) (end - ptr) / (3 * sz);
175
715
  if (count > maxcount)
176
132
    return NULL;
177
178
  /* Where file names are stored.  */
179
583
  const char *fptr = ptr + 3 * count * sz;
180
181
583
  ssize_t firstix = -1;
182
583
  ssize_t lastix = -1;
183
38.4k
  for (size_t mix = 0; mix < count; mix++)
184
38.1k
    {
185
38.1k
      uint64_t mstart, mend, moffset;
186
38.1k
      if (! buf_read_ulong (ei_data, sz, &ptr, fptr, &mstart)
187
38.1k
    || ! buf_read_ulong (ei_data, sz, &ptr, fptr, &mend)
188
38.1k
    || ! buf_read_ulong (ei_data, sz, &ptr, fptr, &moffset))
189
0
  return NULL;
190
38.1k
      if (mstart == module_start && moffset == 0)
191
841
  firstix = lastix = mix;
192
38.1k
      if (firstix != -1 && mstart < module_end)
193
34.4k
  lastix = mix;
194
38.1k
      if (mend >= module_end)
195
243
  break;
196
38.1k
    }
197
583
  if (firstix == -1)
198
309
    return NULL;
199
200
274
  const char *retval = NULL;
201
25.7k
  for (ssize_t mix = 0; mix <= lastix; mix++)
202
25.6k
    {
203
25.6k
      const char *fnext = memchr (fptr, 0, (const char *) end - fptr);
204
25.6k
      if (fnext == NULL)
205
63
  return NULL;
206
25.5k
      if (mix == firstix)
207
220
  retval = fptr;
208
25.5k
      if (firstix < mix && mix <= lastix && strcmp (fptr, retval) != 0)
209
132
  return NULL;
210
25.4k
      fptr = fnext + 1;
211
25.4k
    }
212
79
  return retval;
213
274
}
214
215
/* Return true iff we are certain ELF cannot match BUILD_ID of
216
   BUILD_ID_LEN bytes.  Pass DISK_FILE_HAS_BUILD_ID as false if it is
217
   certain ELF does not contain build-id (it is only a performance hit
218
   to pass it always as true).  */
219
220
static bool
221
invalid_elf (Elf *elf, bool disk_file_has_build_id,
222
             struct elf_build_id *build_id)
223
107
{
224
107
  if (! disk_file_has_build_id && build_id->len > 0)
225
0
    {
226
      /* Module found in segments with build-id is more reliable
227
   than a module found via DT_DEBUG on disk without any
228
   build-id.   */
229
0
      return true;
230
0
    }
231
107
  if (disk_file_has_build_id && build_id->len > 0)
232
107
    {
233
107
      const void *elf_build_id;
234
107
      ssize_t elf_build_id_len;
235
236
      /* If there is a build id in the elf file, check it.  */
237
107
      elf_build_id_len = INTUSE(dwelf_elf_gnu_build_id) (elf, &elf_build_id);
238
107
      if (elf_build_id_len > 0)
239
107
  {
240
107
    if (build_id->len != (size_t) elf_build_id_len
241
31
        || memcmp (build_id->memory, elf_build_id, build_id->len) != 0)
242
107
      return true;
243
107
  }
244
107
    }
245
0
  return false;
246
107
}
247
248
static void
249
finish_portion (struct read_state *read_state,
250
    void **data, size_t *data_size)
251
27.0k
{
252
27.0k
  if (*data_size != 0 && *data != NULL)
253
973
    (*read_state->memory_callback) (read_state->dwfl, -1, data, data_size,
254
973
            0, 0, read_state->memory_callback_arg);
255
27.0k
}
256
257
static inline bool
258
read_portion (struct read_state *read_state,
259
        void **data, size_t *data_size,
260
        GElf_Addr start, size_t segment,
261
        GElf_Addr vaddr, size_t filesz)
262
23.5k
{
263
  /* Check whether we will have to read the segment data, or if it
264
     can be returned from the existing buffer.  */
265
23.5k
  if (filesz > *read_state->buffer_available
266
17.1k
      || vaddr - start > *read_state->buffer_available - filesz
267
      /* If we're in string mode, then don't consider the buffer we have
268
   sufficient unless it contains the terminator of the string.  */
269
15.8k
      || (filesz == 0 && memchr (vaddr - start + *read_state->buffer, '\0',
270
200
         (*read_state->buffer_available
271
200
          - (vaddr - start))) == NULL))
272
7.82k
    {
273
7.82k
      *data = NULL;
274
7.82k
      *data_size = filesz;
275
7.82k
      return !(*read_state->memory_callback) (read_state->dwfl,
276
7.82k
                addr_segndx (read_state->dwfl,
277
7.82k
                 segment, vaddr,
278
7.82k
                 false),
279
7.82k
                data, data_size, vaddr, filesz,
280
7.82k
                read_state->memory_callback_arg);
281
7.82k
    }
282
283
  /* We already have this whole note segment from our initial read.  */
284
15.7k
  *data = vaddr - start + (*read_state->buffer);
285
15.7k
  *data_size = 0;
286
15.7k
  return false;
287
23.5k
}
288
289
int
290
dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
291
          Dwfl_Memory_Callback *memory_callback,
292
          void *memory_callback_arg,
293
          Dwfl_Module_Callback *read_eagerly,
294
          void *read_eagerly_arg,
295
          size_t maxread,
296
          const void *note_file, size_t note_file_size,
297
          const struct r_debug_info *r_debug_info)
298
403k
{
299
403k
  size_t segment = ndx;
300
403k
  struct read_state read_state;
301
302
403k
  if (segment >= dwfl->lookup_elts)
303
332k
    segment = dwfl->lookup_elts - 1;
304
305
23.4M
  while (segment > 0
306
23.3M
   && (dwfl->lookup_segndx[segment] > ndx
307
12.4M
       || dwfl->lookup_segndx[segment] == -1))
308
23.0M
    --segment;
309
310
8.58M
  while (dwfl->lookup_segndx[segment] < ndx)
311
8.35M
    if (++segment == dwfl->lookup_elts)
312
169k
      return 0;
313
314
234k
  GElf_Addr start = dwfl->lookup_addr[segment];
315
316
  /* First read in the file header and check its sanity.  */
317
318
234k
  void *buffer = NULL;
319
234k
  size_t buffer_available = INITIAL_READ;
320
234k
  Elf *elf = NULL;
321
234k
  int fd = -1;
322
323
234k
  read_state.dwfl = dwfl;
324
234k
  read_state.memory_callback = memory_callback;
325
234k
  read_state.memory_callback_arg = memory_callback_arg;
326
234k
  read_state.buffer = &buffer;
327
234k
  read_state.buffer_available = &buffer_available;
328
329
  /* We might have to reserve some memory for the phdrs.  Set to NULL
330
     here so we can always safely free it.  */
331
234k
  void *phdrsp = NULL;
332
333
  /* Collect the build ID bits here.  */
334
234k
  struct elf_build_id build_id;
335
234k
  build_id.memory = NULL;
336
234k
  build_id.len = 0;
337
234k
  build_id.vaddr = 0;
338
339
234k
  if (! (*memory_callback) (dwfl, ndx, &buffer, &buffer_available,
340
234k
          start, sizeof (Elf64_Ehdr), memory_callback_arg)
341
22.5k
      || memcmp (buffer, ELFMAG, SELFMAG) != 0)
342
220k
    goto out;
343
344
  /* Extract the information we need from the file header.  */
345
13.9k
  const unsigned char *e_ident;
346
13.9k
  unsigned char ei_class;
347
13.9k
  unsigned char ei_data;
348
13.9k
  uint16_t e_type;
349
13.9k
  union
350
13.9k
  {
351
13.9k
    Elf32_Ehdr e32;
352
13.9k
    Elf64_Ehdr e64;
353
13.9k
  } ehdr;
354
13.9k
  GElf_Off phoff;
355
13.9k
  uint_fast16_t phnum;
356
13.9k
  uint_fast16_t phentsize;
357
13.9k
  GElf_Off shdrs_end;
358
13.9k
  Elf_Data xlatefrom =
359
13.9k
    {
360
13.9k
      .d_type = ELF_T_EHDR,
361
13.9k
      .d_buf = (void *) buffer,
362
13.9k
      .d_version = EV_CURRENT,
363
13.9k
    };
364
13.9k
  Elf_Data xlateto =
365
13.9k
    {
366
13.9k
      .d_type = ELF_T_EHDR,
367
13.9k
      .d_buf = &ehdr,
368
13.9k
      .d_size = sizeof ehdr,
369
13.9k
      .d_version = EV_CURRENT,
370
13.9k
    };
371
13.9k
  e_ident = ((const unsigned char *) buffer);
372
13.9k
  ei_class = e_ident[EI_CLASS];
373
13.9k
  ei_data = e_ident[EI_DATA];
374
  /* buffer may be unaligned, in which case xlatetom would not work.
375
     xlatetom does work when the in and out d_buf are equal (but not
376
     for any other overlap).  */
377
13.9k
  size_t ehdr_align = (ei_class == ELFCLASS32
378
13.9k
           ? __alignof__ (Elf32_Ehdr)
379
13.9k
           : __alignof__ (Elf64_Ehdr));
380
13.9k
  if (((uintptr_t) buffer & (ehdr_align - 1)) != 0)
381
1.04k
    {
382
1.04k
      memcpy (&ehdr, buffer,
383
1.04k
        (ei_class == ELFCLASS32
384
1.04k
         ? sizeof (Elf32_Ehdr)
385
1.04k
         : sizeof (Elf64_Ehdr)));
386
1.04k
      xlatefrom.d_buf = &ehdr;
387
1.04k
    }
388
13.9k
  switch (ei_class)
389
13.9k
    {
390
8.65k
    case ELFCLASS32:
391
8.65k
      xlatefrom.d_size = sizeof (Elf32_Ehdr);
392
8.65k
      if (elf32_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL)
393
228
  goto out;
394
8.43k
      e_type = ehdr.e32.e_type;
395
8.43k
      phoff = ehdr.e32.e_phoff;
396
8.43k
      phnum = ehdr.e32.e_phnum;
397
8.43k
      phentsize = ehdr.e32.e_phentsize;
398
8.43k
      if (phentsize != sizeof (Elf32_Phdr))
399
2.13k
  goto out;
400
      /* NOTE if the number of sections is > 0xff00 then e_shnum
401
   is zero and the actual number would come from the section
402
   zero sh_size field. We ignore this here because getting shdrs
403
   is just a nice bonus (see below in the type == PT_LOAD case
404
   where we trim the last segment).  */
405
6.29k
      shdrs_end = ehdr.e32.e_shoff + ehdr.e32.e_shnum * sizeof (Elf32_Shdr);
406
6.29k
      break;
407
408
5.04k
    case ELFCLASS64:
409
5.04k
      xlatefrom.d_size = sizeof (Elf64_Ehdr);
410
5.04k
      if (elf64_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL)
411
206
  goto out;
412
4.83k
      e_type = ehdr.e64.e_type;
413
4.83k
      phoff = ehdr.e64.e_phoff;
414
4.83k
      phnum = ehdr.e64.e_phnum;
415
4.83k
      phentsize = ehdr.e64.e_phentsize;
416
4.83k
      if (phentsize != sizeof (Elf64_Phdr))
417
1.25k
  goto out;
418
      /* See the NOTE above for shdrs_end and ehdr.e32.e_shnum.  */
419
3.58k
      shdrs_end = ehdr.e64.e_shoff + ehdr.e64.e_shnum * sizeof (Elf64_Shdr);
420
3.58k
      break;
421
422
247
    default:
423
247
      goto out;
424
13.9k
    }
425
426
  /* The file header tells where to find the program headers.
427
     These are what we need to find the boundaries of the module.
428
     Without them, we don't have a module to report.  */
429
430
9.88k
  if (phnum == 0)
431
199
    goto out;
432
433
9.68k
  xlatefrom.d_type = xlateto.d_type = ELF_T_PHDR;
434
9.68k
  xlatefrom.d_size = phnum * phentsize;
435
436
9.68k
  void *ph_buffer = NULL;
437
9.68k
  size_t ph_buffer_size = 0;
438
9.68k
  if (read_portion (&read_state, &ph_buffer, &ph_buffer_size,
439
9.68k
        start, segment,
440
9.68k
        start + phoff, xlatefrom.d_size))
441
898
    goto out;
442
443
8.78k
  xlatefrom.d_buf = ph_buffer;
444
445
8.78k
  bool class32 = ei_class == ELFCLASS32;
446
8.78k
  size_t phdr_size = class32 ? sizeof (Elf32_Phdr) : sizeof (Elf64_Phdr);
447
8.78k
  if (unlikely (phnum > SIZE_MAX / phdr_size))
448
0
    goto out;
449
8.78k
  const size_t phdrsp_bytes = phnum * phdr_size;
450
8.78k
  phdrsp = malloc (phdrsp_bytes);
451
8.78k
  if (unlikely (phdrsp == NULL))
452
0
    goto out;
453
454
8.78k
  xlateto.d_buf = phdrsp;
455
8.78k
  xlateto.d_size = phdrsp_bytes;
456
457
  /* ph_ buffer may be unaligned, in which case xlatetom would not work.
458
     xlatetom does work when the in and out d_buf are equal (but not
459
     for any other overlap).  */
460
8.78k
  size_t phdr_align = (class32
461
8.78k
           ? __alignof__ (Elf32_Phdr)
462
8.78k
           : __alignof__ (Elf64_Phdr));
463
8.78k
  if (((uintptr_t) ph_buffer & (phdr_align - 1)) != 0)
464
5.68k
    {
465
5.68k
      memcpy (phdrsp, ph_buffer, phdrsp_bytes);
466
5.68k
      xlatefrom.d_buf = phdrsp;
467
5.68k
    }
468
469
  /* Track the bounds of the file visible in memory.  */
470
8.78k
  GElf_Off file_trimmed_end = 0; /* Proper p_vaddr + p_filesz end.  */
471
8.78k
  GElf_Off file_end = 0;   /* Rounded up to effective page size.  */
472
8.78k
  GElf_Off contiguous = 0;   /* Visible as contiguous file from START.  */
473
8.78k
  GElf_Off total_filesz = 0;   /* Total size of data to read.  */
474
475
  /* Collect the bias between START and the containing PT_LOAD's p_vaddr.  */
476
8.78k
  GElf_Addr bias = 0;
477
8.78k
  bool found_bias = false;
478
479
  /* Collect the unbiased bounds of the module here.  */
480
8.78k
  GElf_Addr module_start = -1l;
481
8.78k
  GElf_Addr module_end = 0;
482
8.78k
  GElf_Addr module_address_sync = 0;
483
484
  /* If we see PT_DYNAMIC, record it here.  */
485
8.78k
  GElf_Addr dyn_vaddr = 0;
486
8.78k
  GElf_Xword dyn_filesz = 0;
487
488
8.78k
  Elf32_Phdr *p32 = phdrsp;
489
8.78k
  Elf64_Phdr *p64 = phdrsp;
490
8.78k
  if ((ei_class == ELFCLASS32
491
5.35k
       && elf32_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL)
492
8.78k
      || (ei_class == ELFCLASS64
493
3.43k
          && elf64_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL))
494
0
    {
495
0
      found_bias = false; /* Trigger error check */
496
0
    }
497
8.78k
  else
498
8.78k
    {
499
      /* Consider each of the program headers we've read from the image.  */
500
811k
      for (uint_fast16_t i = 0; i < phnum; ++i)
501
802k
        {
502
802k
          bool is32 = (ei_class == ELFCLASS32);
503
802k
          GElf_Word type = is32 ? p32[i].p_type : p64[i].p_type;
504
802k
          GElf_Addr vaddr = is32 ? p32[i].p_vaddr : p64[i].p_vaddr;
505
802k
          GElf_Xword memsz = is32 ? p32[i].p_memsz : p64[i].p_memsz;
506
802k
          GElf_Off offset = is32 ? p32[i].p_offset : p64[i].p_offset;
507
802k
          GElf_Xword filesz = is32 ? p32[i].p_filesz : p64[i].p_filesz;
508
802k
          GElf_Xword align = is32 ? p32[i].p_align : p64[i].p_align;
509
510
802k
          if (type == PT_DYNAMIC)
511
3.87k
            {
512
3.87k
              dyn_vaddr = vaddr;
513
3.87k
              dyn_filesz = filesz;
514
3.87k
            }
515
798k
          else if (type == PT_NOTE)
516
11.8k
            {
517
              /* If we have already seen a build ID, we don't care any more.  */
518
11.8k
              if (build_id.memory != NULL || filesz == 0)
519
1.10k
                continue; /* Next header */
520
521
              /* We calculate from the p_offset of the note segment,
522
               because we don't yet know the bias for its p_vaddr.  */
523
10.7k
              const GElf_Addr note_vaddr = start + offset;
524
10.7k
              void *data = NULL;
525
10.7k
              size_t data_size = 0;
526
10.7k
              if (read_portion (&read_state, &data, &data_size,
527
10.7k
        start, segment, note_vaddr, filesz))
528
5.38k
                continue; /* Next header */
529
530
5.40k
        if (filesz > SIZE_MAX / sizeof (Elf32_Nhdr))
531
0
    continue;
532
533
5.40k
              assert (sizeof (Elf32_Nhdr) == sizeof (Elf64_Nhdr));
534
535
5.40k
              void *notes;
536
5.40k
              if (ei_data == MY_ELFDATA
537
2.80k
      && (uintptr_t) data == (align == 8
538
2.80k
            ? NOTE_ALIGN8 ((uintptr_t) data)
539
2.80k
            : NOTE_ALIGN4 ((uintptr_t) data)))
540
2.45k
                notes = data;
541
2.94k
              else
542
2.94k
                {
543
2.94k
                  const unsigned int xencoding = ehdr.e32.e_ident[EI_DATA];
544
545
2.94k
      if (filesz > SIZE_MAX / sizeof (Elf32_Nhdr))
546
0
        continue;
547
2.94k
                  notes = malloc (filesz);
548
2.94k
                  if (unlikely (notes == NULL))
549
0
                    continue; /* Next header */
550
2.94k
                  xlatefrom.d_type = xlateto.d_type = (align == 8
551
2.94k
                                                       ? ELF_T_NHDR8
552
2.94k
                   : ELF_T_NHDR);
553
2.94k
                  xlatefrom.d_buf = (void *) data;
554
2.94k
                  xlatefrom.d_size = filesz;
555
2.94k
                  xlateto.d_buf = notes;
556
2.94k
                  xlateto.d_size = filesz;
557
558
      /* data may be unaligned, in which case xlatetom would not work.
559
         xlatetom does work when the in and out d_buf are equal (but not
560
         for any other overlap).  */
561
2.94k
      if ((uintptr_t) data != (align == 8
562
2.94k
             ? NOTE_ALIGN8 ((uintptr_t) data)
563
2.94k
             : NOTE_ALIGN4 ((uintptr_t) data)))
564
587
        {
565
587
          memcpy (notes, data, filesz);
566
587
          xlatefrom.d_buf = notes;
567
587
        }
568
569
2.94k
                  if (elf32_xlatetom (&xlateto, &xlatefrom, xencoding) == NULL)
570
0
                    {
571
0
                      free (notes);
572
0
                      finish_portion (&read_state, &data, &data_size);
573
0
                      continue;
574
0
                    }
575
2.94k
                }
576
577
5.40k
              const GElf_Nhdr *nh = notes;
578
5.40k
              size_t len = 0;
579
16.8k
              while (filesz - len > sizeof (*nh))
580
14.4k
                {
581
14.4k
      len += sizeof (*nh);
582
583
14.4k
      size_t namesz = nh->n_namesz;
584
14.4k
      namesz = align == 8 ? NOTE_ALIGN8 (namesz) : NOTE_ALIGN4 (namesz);
585
14.4k
      if (namesz > filesz - len || len + namesz < namesz)
586
1.30k
        break;
587
588
13.1k
      void *note_name = notes + len;
589
13.1k
      len += namesz;
590
591
13.1k
      size_t descsz = nh->n_descsz;
592
13.1k
      descsz = align == 8 ? NOTE_ALIGN8 (descsz) : NOTE_ALIGN4 (descsz);
593
13.1k
      if (descsz > filesz - len || len + descsz < descsz)
594
860
        break;
595
596
12.2k
      void *note_desc = notes + len;
597
12.2k
      len += descsz;
598
599
      /* We don't handle very short or really large build-ids.  We need at
600
         at least 3 and allow for up to 64 (normally ids are 20 long).  */
601
13.5k
#define MIN_BUILD_ID_BYTES 3
602
13.4k
#define MAX_BUILD_ID_BYTES 64
603
12.2k
      if (nh->n_type == NT_GNU_BUILD_ID
604
1.27k
          && nh->n_descsz >= MIN_BUILD_ID_BYTES
605
1.14k
          && nh->n_descsz <= MAX_BUILD_ID_BYTES
606
918
          && nh->n_namesz == sizeof "GNU"
607
877
          && !memcmp (note_name, "GNU", sizeof "GNU"))
608
773
        {
609
773
          build_id.vaddr = (note_desc
610
773
          - (const void *) notes
611
773
          + note_vaddr);
612
773
          build_id.len = nh->n_descsz;
613
773
          build_id.memory = malloc (build_id.len);
614
773
          if (likely (build_id.memory != NULL))
615
773
      memcpy (build_id.memory, note_desc, build_id.len);
616
773
          break;
617
773
        }
618
619
11.4k
      nh = (void *) notes + len;
620
11.4k
    }
621
622
5.40k
              if (notes != data)
623
2.94k
                free (notes);
624
5.40k
              finish_portion (&read_state, &data, &data_size);
625
5.40k
            }
626
787k
          else if (type == PT_LOAD)
627
67.8k
            {
628
67.8k
              align = (dwfl->segment_align > 1
629
67.8k
                       ? dwfl->segment_align : (align ?: 1));
630
631
67.8k
              GElf_Addr vaddr_end = (vaddr + memsz + align - 1) & -align;
632
67.8k
              GElf_Addr filesz_vaddr = (filesz < memsz
633
67.8k
                                        ? vaddr + filesz : vaddr_end);
634
67.8k
              GElf_Off filesz_offset = filesz_vaddr - vaddr + offset;
635
636
67.8k
              if (file_trimmed_end < offset + filesz)
637
13.4k
                {
638
13.4k
                  file_trimmed_end = offset + filesz;
639
640
                  /* Trim the last segment so we don't bother with zeros
641
                     in the last page that are off the end of the file.
642
                     However, if the extra bit in that page includes the
643
                     section headers, keep them.  */
644
13.4k
                  if (shdrs_end <= filesz_offset
645
6.14k
                      && shdrs_end > file_trimmed_end)
646
242
                    {
647
242
                      filesz += shdrs_end - file_trimmed_end;
648
242
                      file_trimmed_end = shdrs_end;
649
242
                    }
650
13.4k
                }
651
652
67.8k
              total_filesz += filesz;
653
654
67.8k
              if (file_end < filesz_offset)
655
12.3k
                {
656
12.3k
                  file_end = filesz_offset;
657
12.3k
                  if (filesz_vaddr - start == filesz_offset)
658
6.91k
                    contiguous = file_end;
659
12.3k
                }
660
661
67.8k
              if (!found_bias && (offset & -align) == 0
662
9.59k
                  && likely (filesz_offset >= phoff + phnum * phentsize))
663
6.41k
                {
664
6.41k
                  bias = start - vaddr;
665
6.41k
                  found_bias = true;
666
6.41k
                }
667
668
67.8k
              if ((vaddr & -align) < module_start)
669
10.5k
                {
670
10.5k
                  module_start = vaddr & -align;
671
10.5k
                  module_address_sync = vaddr + memsz;
672
10.5k
                }
673
674
67.8k
              if (module_end < vaddr_end)
675
13.0k
                module_end = vaddr_end;
676
67.8k
            }
677
802k
        }
678
8.78k
    }
679
680
8.78k
  finish_portion (&read_state, &ph_buffer, &ph_buffer_size);
681
682
  /* We must have seen the segment covering offset 0, or else the ELF
683
     header we read at START was not produced by these program headers.  */
684
8.78k
  if (unlikely (!found_bias))
685
2.36k
    goto out;
686
687
  /* Now we know enough to report a module for sure: its bounds.  */
688
6.41k
  module_start += bias;
689
6.41k
  module_end += bias;
690
691
6.41k
  dyn_vaddr += bias;
692
693
  /* NAME found from link map has precedence over DT_SONAME possibly read
694
     below.  */
695
6.41k
  bool name_is_final = false;
696
697
  /* Try to match up DYN_VADDR against L_LD as found in link map.
698
     Segments sniffing may guess invalid address as the first read-only memory
699
     mapping may not be dumped to the core file (if ELF headers are not dumped)
700
     and the ELF header is dumped first with the read/write mapping of the same
701
     file at higher addresses.  */
702
6.41k
  if (r_debug_info != NULL)
703
6.41k
    for (const struct r_debug_info_module *module = r_debug_info->module;
704
18.9k
   module != NULL; module = module->next)
705
12.9k
      if (module_start <= module->l_ld && module->l_ld < module_end)
706
5.28k
  {
707
    /* L_LD read from link map must be right while DYN_VADDR is unsafe.
708
       Therefore subtract DYN_VADDR and add L_LD to get a possibly
709
       corrective displacement for all addresses computed so far.  */
710
5.28k
    GElf_Addr fixup = module->l_ld - dyn_vaddr;
711
5.28k
    if ((fixup & (dwfl->segment_align - 1)) == 0
712
1.88k
        && module_start + fixup <= module->l_ld
713
1.65k
        && module->l_ld < module_end + fixup)
714
441
      {
715
441
        module_start += fixup;
716
441
        module_end += fixup;
717
441
        dyn_vaddr += fixup;
718
441
        bias += fixup;
719
441
        if (module->name[0] != '\0')
720
201
    {
721
201
      name = basename (module->name);
722
201
      name_is_final = true;
723
201
    }
724
441
        break;
725
441
      }
726
5.28k
  }
727
728
6.41k
  if (r_debug_info != NULL)
729
6.41k
    {
730
6.41k
      bool skip_this_module = false;
731
6.41k
      for (struct r_debug_info_module *module = r_debug_info->module;
732
21.0k
     module != NULL; module = module->next)
733
14.6k
  if ((module_end > module->start && module_start < module->end)
734
14.5k
      || dyn_vaddr == module->l_ld)
735
1.59k
    {
736
1.59k
      if (module->elf != NULL
737
107
          && invalid_elf (module->elf, module->disk_file_has_build_id,
738
107
        &build_id))
739
107
        {
740
107
    elf_end (module->elf);
741
107
    close (module->fd);
742
107
    module->elf = NULL;
743
107
    module->fd = -1;
744
107
        }
745
1.59k
      if (module->elf != NULL)
746
0
        {
747
    /* Ignore this found module if it would conflict in address
748
       space with any already existing module of DWFL.  */
749
0
    skip_this_module = true;
750
0
        }
751
1.59k
    }
752
6.41k
      if (skip_this_module)
753
0
  goto out;
754
6.41k
    }
755
756
6.41k
  const char *file_note_name = handle_file_note (module_start, module_end,
757
6.41k
             ei_class, ei_data,
758
6.41k
             note_file, note_file_size);
759
6.41k
  if (file_note_name)
760
79
    {
761
79
      name = file_note_name;
762
79
      name_is_final = true;
763
79
      bool invalid = false;
764
79
      fd = open (name, O_RDONLY);
765
79
      if (fd >= 0)
766
8
  {
767
8
    Dwfl_Error error = __libdw_open_file (&fd, &elf, true, false);
768
8
    if (error == DWFL_E_NOERROR)
769
0
      invalid = invalid_elf (elf, true /* disk_file_has_build_id */,
770
0
                                   &build_id);
771
8
  }
772
79
      if (invalid)
773
0
  {
774
    /* The file was there, but the build_id didn't match.  We
775
       still want to report the module, but need to get the ELF
776
       some other way if possible.  */
777
0
    close (fd);
778
0
    fd = -1;
779
0
    elf_end (elf);
780
0
    elf = NULL;
781
0
  }
782
79
    }
783
784
  /* Our return value now says to skip the segments contained
785
     within the module.  */
786
6.41k
  ndx = addr_segndx (dwfl, segment, module_end, true);
787
788
  /* Examine its .dynamic section to get more interesting details.
789
     If it has DT_SONAME, we'll use that as the module name.
790
     If it has a DT_DEBUG, then it's actually a PIE rather than a DSO.
791
     We need its DT_STRTAB and DT_STRSZ to decipher DT_SONAME,
792
     and they also tell us the essential portion of the file
793
     for fetching symbols.  */
794
6.41k
  GElf_Addr soname_stroff = 0;
795
6.41k
  GElf_Addr dynstr_vaddr = 0;
796
6.41k
  GElf_Xword dynstrsz = 0;
797
6.41k
  bool execlike = false;
798
6.41k
  const size_t dyn_entsize = (ei_class == ELFCLASS32
799
6.41k
            ? sizeof (Elf32_Dyn) : sizeof (Elf64_Dyn));
800
6.41k
  void *dyn_data = NULL;
801
6.41k
  size_t dyn_data_size = 0;
802
6.41k
  if (dyn_filesz != 0 && dyn_filesz % dyn_entsize == 0
803
2.64k
      && ! read_portion (&read_state, &dyn_data, &dyn_data_size,
804
2.64k
       start, segment, dyn_vaddr, dyn_filesz))
805
2.28k
    {
806
2.28k
      if ((dyn_filesz / dyn_entsize) == 0
807
2.28k
    || dyn_filesz > (SIZE_MAX / dyn_entsize))
808
0
  goto out;
809
2.28k
      void *dyns = malloc (dyn_filesz);
810
2.28k
      Elf32_Dyn *d32 = dyns;
811
2.28k
      Elf64_Dyn *d64 = dyns;
812
2.28k
      if (unlikely (dyns == NULL))
813
0
  goto out;
814
815
2.28k
      xlatefrom.d_type = xlateto.d_type = ELF_T_DYN;
816
2.28k
      xlatefrom.d_buf = (void *) dyn_data;
817
2.28k
      xlatefrom.d_size = dyn_filesz;
818
2.28k
      xlateto.d_buf = dyns;
819
2.28k
      xlateto.d_size = dyn_filesz;
820
821
      /* dyn_data may be unaligned, in which case xlatetom would not work.
822
   xlatetom does work when the in and out d_buf are equal (but not
823
   for any other overlap).  */
824
2.28k
      bool is32 = (ei_class == ELFCLASS32);
825
2.28k
      size_t dyn_align = (is32
826
2.28k
        ? __alignof__ (Elf32_Dyn)
827
2.28k
        : __alignof__ (Elf64_Dyn));
828
2.28k
      if (((uintptr_t) dyn_data & (dyn_align - 1)) != 0)
829
1.56k
  {
830
1.56k
    memcpy (dyns, dyn_data, dyn_filesz);
831
1.56k
    xlatefrom.d_buf = dyns;
832
1.56k
  }
833
834
2.28k
      if ((is32 && elf32_xlatetom (&xlateto, &xlatefrom, ei_data) != NULL)
835
694
          || (!is32 && elf64_xlatetom (&xlateto, &xlatefrom, ei_data) != NULL))
836
2.28k
        {
837
2.28k
          size_t n = (is32
838
2.28k
          ? (dyn_filesz / sizeof (Elf32_Dyn))
839
2.28k
          : (dyn_filesz / sizeof (Elf64_Dyn)));
840
106k
          for (size_t i = 0; i < n; ++i)
841
105k
            {
842
105k
              GElf_Sxword tag = is32 ? d32[i].d_tag : d64[i].d_tag;
843
105k
              GElf_Xword val = is32 ? d32[i].d_un.d_val : d64[i].d_un.d_val;
844
845
105k
              if (tag == DT_DEBUG)
846
86
                execlike = true;
847
105k
              else if (tag == DT_SONAME)
848
896
                soname_stroff = val;
849
104k
              else if (tag == DT_STRTAB)
850
2.30k
                dynstr_vaddr = val;
851
101k
              else if (tag == DT_STRSZ)
852
2.18k
                dynstrsz = val;
853
99.7k
              else
854
99.7k
                continue;
855
856
5.46k
              if (soname_stroff != 0 && dynstr_vaddr != 0 && dynstrsz != 0)
857
784
                break;
858
5.46k
            }
859
2.28k
        }
860
2.28k
      free (dyns);
861
2.28k
    }
862
6.41k
  finish_portion (&read_state, &dyn_data, &dyn_data_size);
863
864
  /* We'll use the name passed in or a stupid default if not DT_SONAME.  */
865
6.41k
  if (name == NULL)
866
6.13k
    name = e_type == ET_EXEC ? "[exe]" : execlike ? "[pie]" : "[dso]";
867
868
6.41k
  void *soname = NULL;
869
6.41k
  size_t soname_size = 0;
870
6.41k
  if (! name_is_final && dynstrsz != 0 && dynstr_vaddr != 0)
871
1.95k
    {
872
      /* We know the bounds of the .dynstr section.
873
874
   The DYNSTR_VADDR pointer comes from the .dynamic section
875
   (DT_STRTAB, detected above).  Ordinarily the dynamic linker
876
   will have adjusted this pointer in place so it's now an
877
   absolute address.  But sometimes .dynamic is read-only (in
878
   vDSOs and odd architectures), and sometimes the adjustment
879
   just hasn't happened yet in the memory image we looked at.
880
   So treat DYNSTR_VADDR as an absolute address if it falls
881
   within the module bounds, or try applying the phdr bias
882
   when that adjusts it to fall within the module bounds.  */
883
884
1.95k
      if ((dynstr_vaddr < module_start || dynstr_vaddr >= module_end)
885
658
    && dynstr_vaddr + bias >= module_start
886
487
    && dynstr_vaddr + bias < module_end)
887
75
  dynstr_vaddr += bias;
888
889
1.95k
      if (unlikely (dynstr_vaddr + dynstrsz > module_end))
890
324
  dynstrsz = 0;
891
892
      /* Try to get the DT_SONAME string.  */
893
1.95k
      if (soname_stroff != 0 && soname_stroff + 1 < dynstrsz
894
443
    && ! read_portion (&read_state, &soname, &soname_size,
895
443
           start, segment,
896
443
           dynstr_vaddr + soname_stroff, 0))
897
242
  name = soname;
898
1.95k
    }
899
900
  /* Now that we have chosen the module's name and bounds, report it.
901
     If we found a build ID, report that too.  */
902
903
6.41k
  Dwfl_Module *mod = INTUSE(dwfl_report_module) (dwfl, name,
904
6.41k
             module_start, module_end);
905
906
  // !execlike && ET_EXEC is PIE.
907
  // execlike && !ET_EXEC is a static executable.
908
6.41k
  if (mod != NULL && (execlike || ehdr.e32.e_type == ET_EXEC))
909
673
    mod->is_executable = true;
910
911
6.41k
  if (likely (mod != NULL) && build_id.memory != NULL
912
567
      && unlikely (INTUSE(dwfl_module_report_build_id) (mod,
913
6.41k
              build_id.memory,
914
6.41k
              build_id.len,
915
6.41k
              build_id.vaddr)))
916
190
    {
917
190
      mod->gc = true;
918
190
      mod = NULL;
919
190
    }
920
921
  /* At this point we do not need BUILD_ID or NAME any more.
922
     They have been copied.  */
923
6.41k
  free (build_id.memory);
924
6.41k
  build_id.memory = NULL;
925
6.41k
  finish_portion (&read_state, &soname, &soname_size);
926
927
6.41k
  if (unlikely (mod == NULL))
928
190
    {
929
190
      ndx = -1;
930
190
      goto out;
931
190
    }
932
933
  /* We have reported the module.  Now let the caller decide whether we
934
     should read the whole thing in right now.  */
935
936
6.22k
  const GElf_Off cost = (contiguous < file_trimmed_end ? total_filesz
937
6.22k
       : buffer_available >= contiguous ? 0
938
2.30k
       : contiguous - buffer_available);
939
6.22k
  const GElf_Off worthwhile = ((dynstr_vaddr == 0 || dynstrsz == 0) ? 0
940
6.22k
             : dynstr_vaddr + dynstrsz - start);
941
6.22k
  const GElf_Off whole = MAX (file_trimmed_end, shdrs_end);
942
943
6.22k
  if (elf == NULL
944
6.22k
      && (*read_eagerly) (MODCB_ARGS (mod), &buffer, &buffer_available,
945
6.22k
        cost, worthwhile, whole, contiguous,
946
6.22k
        read_eagerly_arg, &elf)
947
1.79k
      && elf == NULL)
948
1.62k
    {
949
      /* The caller wants to read the whole file in right now, but hasn't
950
   done it for us.  Fill in a local image of the virtual file.  */
951
952
1.62k
      if (file_trimmed_end > maxread)
953
1.57k
  file_trimmed_end = maxread;
954
955
1.62k
      void *contents = calloc (1, file_trimmed_end);
956
1.62k
      if (unlikely (contents == NULL))
957
0
  goto out;
958
959
1.62k
      if (contiguous < file_trimmed_end)
960
797
  {
961
    /* We can't use the memory image verbatim as the file image.
962
       So we'll be reading into a local image of the virtual file.  */
963
60.8k
          for (uint_fast16_t i = 0; i < phnum; ++i)
964
60.0k
            {
965
60.0k
              bool is32 = (ei_class == ELFCLASS32);
966
60.0k
              GElf_Word type = is32 ? p32[i].p_type : p64[i].p_type;
967
968
60.0k
              if (type != PT_LOAD)
969
54.6k
                continue;
970
971
5.38k
              GElf_Addr vaddr = is32 ? p32[i].p_vaddr : p64[i].p_vaddr;
972
5.38k
              GElf_Off offset = is32 ? p32[i].p_offset : p64[i].p_offset;
973
5.38k
              GElf_Xword filesz = is32 ? p32[i].p_filesz : p64[i].p_filesz;
974
975
              /* Don't try to read beyond the actual end of file.  */
976
5.38k
              if (offset >= file_trimmed_end)
977
1.63k
                continue;
978
979
3.75k
              void *into = contents + offset;
980
3.75k
              size_t read_size = MIN (filesz, file_trimmed_end - offset);
981
3.75k
              (*memory_callback) (dwfl, addr_segndx (dwfl, segment,
982
3.75k
                                                     vaddr + bias, false),
983
3.75k
                                  &into, &read_size, vaddr + bias, read_size,
984
3.75k
                                  memory_callback_arg);
985
3.75k
            }
986
797
  }
987
823
      else
988
823
  {
989
    /* The whole file sits contiguous in memory,
990
       but the caller didn't want to just do it.  */
991
992
823
    const size_t have = MIN (buffer_available, file_trimmed_end);
993
823
    memcpy (contents, buffer, have);
994
995
823
    if (have < file_trimmed_end)
996
187
            {
997
187
        void *into = contents + have;
998
187
        size_t read_size = file_trimmed_end - have;
999
187
        (*memory_callback) (dwfl,
1000
187
          addr_segndx (dwfl, segment,
1001
187
                 start + have, false),
1002
187
          &into, &read_size, start + have,
1003
187
          read_size, memory_callback_arg);
1004
187
            }
1005
823
  }
1006
1007
1.62k
      elf = elf_memory (contents, file_trimmed_end);
1008
1.62k
      if (unlikely (elf == NULL))
1009
17
  free (contents);
1010
1.60k
      else
1011
1.60k
  elf->flags |= ELF_F_MALLOCED;
1012
1.62k
    }
1013
1014
6.22k
  if (elf != NULL && mod->main.elf == NULL)
1015
1.53k
    {
1016
      /* Install the file in the module.  */
1017
1.53k
      mod->main.elf = elf;
1018
1.53k
      mod->main.fd = fd;
1019
1.53k
      elf = NULL;
1020
1.53k
      fd = -1;
1021
1.53k
      mod->main.vaddr = module_start - bias;
1022
1.53k
      mod->main.address_sync = module_address_sync;
1023
1.53k
      mod->main_bias = bias;
1024
1.53k
    }
1025
1026
234k
out:
1027
234k
  if (build_id.memory != NULL)
1028
206
    free (build_id.memory);
1029
234k
  free (phdrsp);
1030
234k
  if (buffer != NULL)
1031
22.3k
    (*memory_callback) (dwfl, -1, &buffer, &buffer_available, 0, 0,
1032
22.3k
                        memory_callback_arg);
1033
1034
234k
  if (elf != NULL)
1035
244
    elf_end (elf);
1036
234k
  if (fd != -1)
1037
0
    close (fd);
1038
234k
  return ndx;
1039
6.22k
}