Branch data Line data Source code
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 : : #define INITIAL_READ 1024
54 : :
55 : : #if BYTE_ORDER == LITTLE_ENDIAN
56 : : # 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 : 262 : addr_segndx (Dwfl *dwfl, size_t segment, GElf_Addr addr, bool next)
81 : : {
82 : 262 : int ndx = -1;
83 : 720 : do
84 : : {
85 [ + + ]: 720 : if (dwfl->lookup_segndx[segment] >= 0)
86 : 654 : ndx = dwfl->lookup_segndx[segment];
87 [ - + ]: 720 : if (++segment >= dwfl->lookup_elts - 1)
88 [ # # ]: 0 : return next ? ndx + 1 : ndx;
89 : : }
90 [ + + ]: 720 : while (dwfl->lookup_addr[segment] < addr);
91 : :
92 [ - + ]: 262 : if (next)
93 : : {
94 [ # # ]: 0 : while (dwfl->lookup_segndx[segment] < 0)
95 [ # # ]: 0 : if (++segment >= dwfl->lookup_elts - 1)
96 : 0 : return ndx + 1;
97 : : ndx = dwfl->lookup_segndx[segment];
98 : : }
99 : :
100 : : return ndx;
101 : : }
102 : :
103 : : /* Return whether there is SZ bytes available at PTR till END. */
104 : :
105 : : static bool
106 : 11512 : buf_has_data (const void *ptr, const void *end, size_t sz)
107 : : {
108 [ - + ]: 11512 : return ptr < end && (size_t) (end - ptr) >= sz;
109 : : }
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 : 11512 : buf_read_ulong (unsigned char ei_data, size_t sz,
116 : : const void **ptrp, const void *end, uint64_t *retp)
117 : : {
118 [ + - + - ]: 23024 : if (! buf_has_data (*ptrp, end, sz))
119 : : return false;
120 : :
121 : 11512 : union
122 : : {
123 : : uint64_t u64;
124 : : uint32_t u32;
125 : : } u;
126 : :
127 [ + + ]: 11512 : memcpy (&u, *ptrp, sz);
128 : 11512 : (*ptrp) += sz;
129 : :
130 [ + + ]: 11512 : if (retp == NULL)
131 : : return true;
132 : :
133 [ + + ]: 11252 : if (MY_ELFDATA != ei_data)
134 : : {
135 [ + - ]: 30 : if (sz == 4)
136 : 30 : CONVERT (u.u32);
137 : : else
138 : 0 : CONVERT (u.u64);
139 : : }
140 [ + + ]: 11252 : if (sz == 4)
141 : 114 : *retp = u.u32;
142 : : else
143 : 11138 : *retp = u.u64;
144 : : return true;
145 : : }
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 : 328 : 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 : : {
156 [ + + ]: 328 : if (note_file == NULL)
157 : : return NULL;
158 : :
159 : 260 : size_t sz;
160 [ - + + ]: 260 : switch (ei_class)
161 : : {
162 : : case ELFCLASS32:
163 : : sz = 4;
164 : : break;
165 : 242 : case ELFCLASS64:
166 : 242 : sz = 8;
167 : 242 : break;
168 : : default:
169 : : return NULL;
170 : : }
171 : :
172 : 260 : const void *ptr = note_file;
173 : 260 : const void *end = note_file + note_file_size;
174 : 260 : uint64_t count;
175 [ - + ]: 260 : if (! buf_read_ulong (ei_data, sz, &ptr, end, &count))
176 : : return NULL;
177 [ - + ]: 260 : if (! buf_read_ulong (ei_data, sz, &ptr, end, NULL)) // page_size
178 : : return NULL;
179 : :
180 : 260 : uint64_t maxcount = (size_t) (end - ptr) / (3 * sz);
181 [ - + ]: 260 : if (count > maxcount)
182 : : return NULL;
183 : :
184 : : /* Where file names are stored. */
185 : 260 : const char *fptr = ptr + 3 * count * sz;
186 : :
187 : 260 : ssize_t firstix = -1;
188 : 260 : ssize_t lastix = -1;
189 [ + + ]: 3766 : for (size_t mix = 0; mix < count; mix++)
190 : : {
191 : 3664 : uint64_t mstart, mend, moffset;
192 [ + - ]: 3664 : if (! buf_read_ulong (ei_data, sz, &ptr, fptr, &mstart)
193 [ + - ]: 3664 : || ! buf_read_ulong (ei_data, sz, &ptr, fptr, &mend)
194 [ - + ]: 3664 : || ! buf_read_ulong (ei_data, sz, &ptr, fptr, &moffset))
195 : 0 : return NULL;
196 [ + + + - ]: 3664 : if (mstart == module_start && moffset == 0)
197 : 204 : firstix = lastix = mix;
198 [ + + + + ]: 3664 : if (firstix != -1 && mstart < module_end)
199 : 762 : lastix = mix;
200 [ + + ]: 3664 : if (mend >= module_end)
201 : : break;
202 : : }
203 [ + + ]: 260 : if (firstix == -1)
204 : : return NULL;
205 : :
206 : : const char *retval = NULL;
207 [ + + ]: 2836 : for (ssize_t mix = 0; mix <= lastix; mix++)
208 : : {
209 : 2636 : const char *fnext = memchr (fptr, 0, (const char *) end - fptr);
210 [ - + ]: 2636 : if (fnext == NULL)
211 : : return NULL;
212 [ + + ]: 2636 : if (mix == firstix)
213 : 204 : retval = fptr;
214 [ + + + + ]: 2636 : if (firstix < mix && mix <= lastix && strcmp (fptr, retval) != 0)
215 : : return NULL;
216 : 2632 : fptr = fnext + 1;
217 : : }
218 : : return retval;
219 : : }
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 : 152 : invalid_elf (Elf *elf, bool disk_file_has_build_id,
228 : : struct elf_build_id *build_id)
229 : : {
230 [ + + + - ]: 152 : if (! disk_file_has_build_id && build_id->len > 0)
231 : : {
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 : : return true;
236 : : }
237 [ - + ]: 150 : if (disk_file_has_build_id && build_id->len > 0)
238 : : {
239 : 150 : const void *elf_build_id;
240 : 150 : ssize_t elf_build_id_len;
241 : :
242 : : /* If there is a build id in the elf file, check it. */
243 : 150 : elf_build_id_len = INTUSE(dwelf_elf_gnu_build_id) (elf, &elf_build_id);
244 [ + - ]: 150 : if (elf_build_id_len > 0)
245 : : {
246 [ + - ]: 150 : if (build_id->len != (size_t) elf_build_id_len
247 [ + + ]: 150 : || memcmp (build_id->memory, elf_build_id, build_id->len) != 0)
248 : 38 : return true;
249 : : }
250 : : }
251 : : return false;
252 : : }
253 : :
254 : : static void
255 : 1584 : finish_portion (struct read_state *read_state,
256 : : void **data, size_t *data_size)
257 : : {
258 [ + + + + ]: 1584 : if (*data_size != 0 && *data != NULL)
259 : 246 : (*read_state->memory_callback) (read_state->dwfl, -1, data, data_size,
260 : : 0, 0, read_state->memory_callback_arg);
261 : 1584 : }
262 : :
263 : : static inline bool
264 : 1280 : 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 : : {
269 : : /* Check whether we will have to read the segment data, or if it
270 : : can be returned from the existing buffer. */
271 [ + + ]: 1280 : if (filesz > *read_state->buffer_available
272 [ + + ]: 1222 : || 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 [ + + ]: 1028 : || (filesz == 0 && memchr (vaddr - start + *read_state->buffer, '\0',
276 : : (*read_state->buffer_available
277 [ - + ]: 70 : - (vaddr - start))) == NULL))
278 : : {
279 : 252 : *data = NULL;
280 : 252 : *data_size = filesz;
281 : 252 : return !(*read_state->memory_callback) (read_state->dwfl,
282 : : addr_segndx (read_state->dwfl,
283 : : segment, vaddr,
284 : : false),
285 : : data, data_size, vaddr, filesz,
286 : 252 : read_state->memory_callback_arg);
287 : : }
288 : :
289 : : /* We already have this whole note segment from our initial read. */
290 : 1028 : *data = vaddr - start + (*read_state->buffer);
291 : 1028 : *data_size = 0;
292 : 1028 : return false;
293 : : }
294 : :
295 : : int
296 : 1758 : 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 : : {
306 : 1758 : size_t segment = ndx;
307 : 1758 : struct read_state read_state;
308 : :
309 [ - + ]: 1758 : if (segment >= dwfl->lookup_elts)
310 : 0 : segment = dwfl->lookup_elts - 1;
311 : :
312 : : while (segment > 0
313 [ + + + + ]: 2198 : && (dwfl->lookup_segndx[segment] > ndx
314 [ + + ]: 2002 : || dwfl->lookup_segndx[segment] == -1))
315 : 440 : --segment;
316 : :
317 [ + + ]: 8216 : while (dwfl->lookup_segndx[segment] < ndx)
318 [ + - ]: 6458 : if (++segment == dwfl->lookup_elts)
319 : : return 0;
320 : :
321 : 1758 : GElf_Addr start = dwfl->lookup_addr[segment];
322 : :
323 : : /* First read in the file header and check its sanity. */
324 : :
325 : 1758 : void *buffer = NULL;
326 : 1758 : size_t buffer_available = INITIAL_READ;
327 : 1758 : Elf *elf = NULL;
328 : 1758 : int fd = -1;
329 : :
330 : 1758 : read_state.dwfl = dwfl;
331 : 1758 : read_state.memory_callback = memory_callback;
332 : 1758 : read_state.memory_callback_arg = memory_callback_arg;
333 : 1758 : read_state.buffer = &buffer;
334 : 1758 : 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 : 1758 : void *phdrsp = NULL;
339 : :
340 : : /* Collect the build ID bits here. */
341 : 1758 : struct elf_build_id build_id;
342 : 1758 : build_id.memory = NULL;
343 : 1758 : build_id.len = 0;
344 : 1758 : build_id.vaddr = 0;
345 : :
346 [ + + ]: 1758 : if (! (*memory_callback) (dwfl, ndx, &buffer, &buffer_available,
347 : : start, sizeof (Elf64_Ehdr), memory_callback_arg)
348 [ + + ]: 1478 : || memcmp (buffer, ELFMAG, SELFMAG) != 0)
349 : 1302 : goto out;
350 : :
351 : : /* Extract the information we need from the file header. */
352 : 456 : const unsigned char *e_ident;
353 : 456 : unsigned char ei_class;
354 : 456 : unsigned char ei_data;
355 : 456 : uint16_t e_type;
356 : 456 : union
357 : : {
358 : : Elf32_Ehdr e32;
359 : : Elf64_Ehdr e64;
360 : : } ehdr;
361 : 456 : GElf_Off phoff;
362 : 456 : uint_fast16_t phnum;
363 : 456 : uint_fast16_t phentsize;
364 : 456 : GElf_Off shdrs_end;
365 : 456 : Elf_Data xlatefrom =
366 : : {
367 : : .d_type = ELF_T_EHDR,
368 : : .d_buf = (void *) buffer,
369 : : .d_version = EV_CURRENT,
370 : : };
371 : 456 : Elf_Data xlateto =
372 : : {
373 : : .d_type = ELF_T_EHDR,
374 : : .d_buf = &ehdr,
375 : : .d_size = sizeof ehdr,
376 : : .d_version = EV_CURRENT,
377 : : };
378 : 456 : e_ident = ((const unsigned char *) buffer);
379 : 456 : ei_class = e_ident[EI_CLASS];
380 : 456 : 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 : 912 : size_t ehdr_align = (ei_class == ELFCLASS32
385 : : ? __alignof__ (Elf32_Ehdr)
386 [ + + ]: 456 : : __alignof__ (Elf64_Ehdr));
387 [ - + ]: 456 : if (((uintptr_t) buffer & (ehdr_align - 1)) != 0)
388 : : {
389 [ # # ]: 0 : memcpy (&ehdr, buffer,
390 : : (ei_class == ELFCLASS32
391 : : ? sizeof (Elf32_Ehdr)
392 : : : sizeof (Elf64_Ehdr)));
393 : 0 : xlatefrom.d_buf = &ehdr;
394 : : }
395 [ + + - ]: 456 : switch (ei_class)
396 : : {
397 : 62 : case ELFCLASS32:
398 : 62 : xlatefrom.d_size = sizeof (Elf32_Ehdr);
399 [ - + ]: 62 : if (elf32_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL)
400 : 0 : goto out;
401 : 62 : e_type = ehdr.e32.e_type;
402 : 62 : phoff = ehdr.e32.e_phoff;
403 : 62 : phnum = ehdr.e32.e_phnum;
404 : 62 : phentsize = ehdr.e32.e_phentsize;
405 [ - + ]: 62 : if (phentsize != sizeof (Elf32_Phdr))
406 : 0 : 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 : 62 : shdrs_end = ehdr.e32.e_shoff + ehdr.e32.e_shnum * sizeof (Elf32_Shdr);
413 : 62 : break;
414 : :
415 : 394 : case ELFCLASS64:
416 : 394 : xlatefrom.d_size = sizeof (Elf64_Ehdr);
417 [ - + ]: 394 : if (elf64_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL)
418 : 0 : goto out;
419 : 394 : e_type = ehdr.e64.e_type;
420 : 394 : phoff = ehdr.e64.e_phoff;
421 : 394 : phnum = ehdr.e64.e_phnum;
422 : 394 : phentsize = ehdr.e64.e_phentsize;
423 [ - + ]: 394 : if (phentsize != sizeof (Elf64_Phdr))
424 : 0 : goto out;
425 : : /* See the NOTE above for shdrs_end and ehdr.e32.e_shnum. */
426 : 394 : shdrs_end = ehdr.e64.e_shoff + ehdr.e64.e_shnum * sizeof (Elf64_Shdr);
427 : 394 : break;
428 : :
429 : 0 : default:
430 : 0 : goto out;
431 : : }
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 [ - + ]: 456 : if (phnum == 0)
438 : 0 : goto out;
439 : :
440 : 456 : xlatefrom.d_type = xlateto.d_type = ELF_T_PHDR;
441 : 456 : xlatefrom.d_size = phnum * phentsize;
442 : :
443 : 456 : void *ph_buffer = NULL;
444 : 456 : size_t ph_buffer_size = 0;
445 [ - + ]: 456 : if (read_portion (&read_state, &ph_buffer, &ph_buffer_size,
446 : : start, segment,
447 : : start + phoff, xlatefrom.d_size))
448 : 0 : goto out;
449 : :
450 : 456 : xlatefrom.d_buf = ph_buffer;
451 : :
452 : 456 : bool class32 = ei_class == ELFCLASS32;
453 [ + + ]: 456 : size_t phdr_size = class32 ? sizeof (Elf32_Phdr) : sizeof (Elf64_Phdr);
454 [ - + ]: 456 : if (unlikely (phnum > SIZE_MAX / phdr_size))
455 : 0 : goto out;
456 : 456 : const size_t phdrsp_bytes = phnum * phdr_size;
457 : 456 : phdrsp = malloc (phdrsp_bytes);
458 [ - + ]: 456 : if (unlikely (phdrsp == NULL))
459 : 0 : goto out;
460 : :
461 : 456 : xlateto.d_buf = phdrsp;
462 : 456 : 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 : 456 : size_t phdr_align = (class32
468 : : ? __alignof__ (Elf32_Phdr)
469 : : : __alignof__ (Elf64_Phdr));
470 [ - + ]: 456 : if (((uintptr_t) ph_buffer & (phdr_align - 1)) != 0)
471 : : {
472 : 0 : memcpy (phdrsp, ph_buffer, phdrsp_bytes);
473 : 0 : xlatefrom.d_buf = phdrsp;
474 : : }
475 : :
476 : : /* Track the bounds of the file visible in memory. */
477 : 456 : GElf_Off file_trimmed_end = 0; /* Proper p_vaddr + p_filesz end. */
478 : 456 : GElf_Off file_end = 0; /* Rounded up to effective page size. */
479 : 456 : GElf_Off contiguous = 0; /* Visible as contiguous file from START. */
480 : 456 : 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 : 456 : GElf_Addr bias = 0;
484 : 456 : bool found_bias = false;
485 : :
486 : : /* Collect the unbiased bounds of the module here. */
487 : 456 : GElf_Addr module_start = -1l;
488 : 456 : GElf_Addr module_end = 0;
489 : 456 : GElf_Addr module_address_sync = 0;
490 : :
491 : : /* If we see PT_DYNAMIC, record it here. */
492 : 456 : GElf_Addr dyn_vaddr = 0;
493 : 456 : GElf_Xword dyn_filesz = 0;
494 : :
495 : 456 : Elf32_Phdr *p32 = phdrsp;
496 : 456 : Elf64_Phdr *p64 = phdrsp;
497 [ + + ]: 456 : if ((ei_class == ELFCLASS32
498 [ + - ]: 62 : && elf32_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL)
499 [ + + ]: 456 : || (ei_class == ELFCLASS64
500 [ - + ]: 394 : && elf64_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL))
501 : : {
502 : : found_bias = false; /* Trigger error check */
503 : : }
504 : : else
505 : : {
506 : : /* Consider each of the program headers we've read from the image. */
507 [ + + ]: 3832 : for (uint_fast16_t i = 0; i < phnum; ++i)
508 : : {
509 : 3376 : bool is32 = (ei_class == ELFCLASS32);
510 [ + + ]: 3376 : GElf_Word type = is32 ? p32[i].p_type : p64[i].p_type;
511 [ + + ]: 3376 : GElf_Addr vaddr = is32 ? p32[i].p_vaddr : p64[i].p_vaddr;
512 [ + + ]: 3376 : GElf_Xword memsz = is32 ? p32[i].p_memsz : p64[i].p_memsz;
513 [ + + ]: 3376 : GElf_Off offset = is32 ? p32[i].p_offset : p64[i].p_offset;
514 [ + + ]: 3376 : GElf_Xword filesz = is32 ? p32[i].p_filesz : p64[i].p_filesz;
515 [ + + ]: 3376 : GElf_Xword align = is32 ? p32[i].p_align : p64[i].p_align;
516 : :
517 [ + + ]: 3376 : if (type == PT_DYNAMIC)
518 : : {
519 : : dyn_vaddr = vaddr;
520 : : dyn_filesz = filesz;
521 : : }
522 [ + + ]: 2968 : else if (type == PT_NOTE)
523 : : {
524 : : /* If we have already seen a build ID, we don't care any more. */
525 [ + - - + ]: 472 : if (build_id.memory != NULL || filesz == 0)
526 : 0 : 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 : 472 : const GElf_Addr note_vaddr = start + offset;
531 : 472 : void *data = NULL;
532 : 472 : size_t data_size = 0;
533 [ - + ]: 472 : if (read_portion (&read_state, &data, &data_size,
534 : : start, segment, note_vaddr, filesz))
535 : 0 : continue; /* Next header */
536 : :
537 [ - + ]: 472 : if (filesz > SIZE_MAX / sizeof (Elf32_Nhdr))
538 : 0 : continue;
539 : :
540 : 472 : assert (sizeof (Elf32_Nhdr) == sizeof (Elf64_Nhdr));
541 : :
542 : 472 : void *notes;
543 [ + + ]: 472 : if (ei_data == MY_ELFDATA
544 [ - + ]: 414 : && (uintptr_t) data == (align == 8
545 : 20 : ? NOTE_ALIGN8 ((uintptr_t) data)
546 [ + + ]: 414 : : NOTE_ALIGN4 ((uintptr_t) data)))
547 : : notes = data;
548 : : else
549 : : {
550 : 58 : const unsigned int xencoding = ehdr.e32.e_ident[EI_DATA];
551 : :
552 : 58 : if (filesz > SIZE_MAX / sizeof (Elf32_Nhdr))
553 : : continue;
554 : 58 : notes = malloc (filesz);
555 [ - + ]: 58 : if (unlikely (notes == NULL))
556 : 0 : continue; /* Next header */
557 : 116 : xlatefrom.d_type = xlateto.d_type = (align == 8
558 : : ? ELF_T_NHDR8
559 [ + - ]: 58 : : ELF_T_NHDR);
560 : 58 : xlatefrom.d_buf = (void *) data;
561 : 58 : xlatefrom.d_size = filesz;
562 : 58 : xlateto.d_buf = notes;
563 : 58 : 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 [ - + ]: 58 : if ((uintptr_t) data != (align == 8
569 : 0 : ? NOTE_ALIGN8 ((uintptr_t) data)
570 [ - + ]: 58 : : NOTE_ALIGN4 ((uintptr_t) data)))
571 : : {
572 : 0 : memcpy (notes, data, filesz);
573 : 0 : xlatefrom.d_buf = notes;
574 : : }
575 : :
576 [ - + ]: 58 : if (elf32_xlatetom (&xlateto, &xlatefrom, xencoding) == NULL)
577 : : {
578 : 0 : free (notes);
579 : 0 : finish_portion (&read_state, &data, &data_size);
580 : 0 : continue;
581 : : }
582 : : }
583 : :
584 : 472 : const GElf_Nhdr *nh = notes;
585 : 472 : size_t len = 0;
586 [ + - ]: 690 : while (filesz - len > sizeof (*nh))
587 : : {
588 : 690 : len += sizeof (*nh);
589 : :
590 : 690 : size_t namesz = nh->n_namesz;
591 [ + + ]: 690 : namesz = align == 8 ? NOTE_ALIGN8 (namesz) : NOTE_ALIGN4 (namesz);
592 [ + - + - ]: 690 : if (namesz > filesz - len || len + namesz < namesz)
593 : : break;
594 : :
595 : 690 : void *note_name = notes + len;
596 : 690 : len += namesz;
597 : :
598 : 690 : size_t descsz = nh->n_descsz;
599 [ + + ]: 690 : descsz = align == 8 ? NOTE_ALIGN8 (descsz) : NOTE_ALIGN4 (descsz);
600 [ + + + - ]: 690 : if (descsz > filesz - len || len + descsz < descsz)
601 : : break;
602 : :
603 : 670 : void *note_desc = notes + len;
604 : 670 : 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 : : #define MIN_BUILD_ID_BYTES 3
609 : : #define MAX_BUILD_ID_BYTES 64
610 [ + + ]: 670 : if (nh->n_type == NT_GNU_BUILD_ID
611 [ + - ]: 452 : && nh->n_descsz >= MIN_BUILD_ID_BYTES
612 [ + - ]: 452 : && nh->n_descsz <= MAX_BUILD_ID_BYTES
613 [ + - ]: 452 : && nh->n_namesz == sizeof "GNU"
614 [ + - ]: 452 : && !memcmp (note_name, "GNU", sizeof "GNU"))
615 : : {
616 : 452 : build_id.vaddr = (note_desc
617 : : - (const void *) notes
618 : 452 : + note_vaddr);
619 : 452 : build_id.len = nh->n_descsz;
620 : 452 : build_id.memory = malloc (build_id.len);
621 [ + - ]: 452 : if (likely (build_id.memory != NULL))
622 : 452 : memcpy (build_id.memory, note_desc, build_id.len);
623 : : break;
624 : : }
625 : :
626 : 218 : nh = (void *) notes + len;
627 : : }
628 : :
629 [ + + ]: 472 : if (notes != data)
630 : 58 : free (notes);
631 : 472 : finish_portion (&read_state, &data, &data_size);
632 : : }
633 [ + + ]: 2496 : else if (type == PT_LOAD)
634 : : {
635 : 1764 : align = (dwfl->segment_align > 1
636 [ - + ]: 882 : ? dwfl->segment_align : (align ?: 1));
637 : :
638 : 882 : GElf_Addr vaddr_end = (vaddr + memsz + align - 1) & -align;
639 : 1764 : GElf_Addr filesz_vaddr = (filesz < memsz
640 [ + + ]: 882 : ? vaddr + filesz : vaddr_end);
641 : 882 : GElf_Off filesz_offset = filesz_vaddr - vaddr + offset;
642 : :
643 [ + + ]: 882 : if (file_trimmed_end < offset + filesz)
644 : : {
645 : 860 : 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 : 860 : if (shdrs_end <= filesz_offset
652 [ + + ]: 860 : && shdrs_end > file_trimmed_end)
653 : : {
654 : 62 : filesz += shdrs_end - file_trimmed_end;
655 : 62 : file_trimmed_end = shdrs_end;
656 : : }
657 : : }
658 : :
659 : 882 : total_filesz += filesz;
660 : :
661 [ + + ]: 882 : if (file_end < filesz_offset)
662 : : {
663 : 836 : file_end = filesz_offset;
664 [ + + ]: 836 : if (filesz_vaddr - start == filesz_offset)
665 : 290 : contiguous = file_end;
666 : : }
667 : :
668 [ + + + - ]: 882 : if (!found_bias && (offset & -align) == 0
669 [ + - ]: 456 : && likely (filesz_offset >= phoff + phnum * phentsize))
670 : : {
671 : 456 : bias = start - vaddr;
672 : 456 : found_bias = true;
673 : : }
674 : :
675 [ + + ]: 882 : if ((vaddr & -align) < module_start)
676 : : {
677 : 456 : module_start = vaddr & -align;
678 : 456 : module_address_sync = vaddr + memsz;
679 : : }
680 : :
681 : 882 : if (module_end < vaddr_end)
682 : : module_end = vaddr_end;
683 : : }
684 : : }
685 : : }
686 : :
687 : 456 : 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 [ - + ]: 456 : if (unlikely (!found_bias))
692 : 0 : goto out;
693 : :
694 : : /* Now we know enough to report a module for sure: its bounds. */
695 : 456 : module_start += bias;
696 : 456 : module_end += bias;
697 : :
698 : 456 : dyn_vaddr += bias;
699 : :
700 : : /* NAME found from link map has precedence over DT_SONAME possibly read
701 : : below. */
702 : 456 : 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 [ + - ]: 456 : if (r_debug_info != NULL)
710 : 456 : for (const struct r_debug_info_module *module = r_debug_info->module;
711 [ + + ]: 1734 : module != NULL; module = module->next)
712 [ + + + + ]: 1640 : if (module_start <= module->l_ld && module->l_ld < module_end)
713 : : {
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 : 366 : GElf_Addr fixup = module->l_ld - dyn_vaddr;
718 [ + + ]: 366 : if ((fixup & (dwfl->segment_align - 1)) == 0
719 [ + - ]: 362 : && module_start + fixup <= module->l_ld
720 [ + - ]: 362 : && module->l_ld < module_end + fixup)
721 : : {
722 : 362 : module_start += fixup;
723 : 362 : module_end += fixup;
724 : 362 : dyn_vaddr += fixup;
725 : 362 : bias += fixup;
726 [ + + ]: 362 : if (module->name[0] != '\0')
727 : : {
728 : 288 : name = xbasename (module->name);
729 : 288 : name_is_final = true;
730 : : }
731 : : break;
732 : : }
733 : : }
734 : :
735 [ + - ]: 456 : if (r_debug_info != NULL)
736 : : {
737 : 456 : bool skip_this_module = false;
738 : 456 : for (struct r_debug_info_module *module = r_debug_info->module;
739 [ + + ]: 2908 : module != NULL; module = module->next)
740 [ + + + + ]: 2452 : if ((module_end > module->start && module_start < module->end)
741 [ + + ]: 2304 : || dyn_vaddr == module->l_ld)
742 : : {
743 [ + + ]: 372 : if (module->elf != NULL
744 [ + + ]: 140 : && invalid_elf (module->elf, module->disk_file_has_build_id,
745 : : &build_id))
746 : : {
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 [ + + - + ]: 38 : if (name != NULL && module->name[0] != '\0'
753 [ + + ]: 36 : && strcmp (xbasename (module->name), xbasename (name)) == 0)
754 : : {
755 : 32 : elf_end (module->elf);
756 : 32 : close (module->fd);
757 : 32 : module->elf = NULL;
758 : 32 : module->fd = -1;
759 : : }
760 : : }
761 [ + + ]: 334 : else if (module->elf != NULL)
762 : : {
763 : : /* This module has already been reported. */
764 : : skip_this_module = true;
765 : : }
766 : : else
767 : : {
768 : : /* Only report this module if we haven't already done so. */
769 [ + + ]: 886 : for (Dwfl_Module *mod = dwfl->modulelist; mod != NULL;
770 : 654 : mod = mod->next)
771 [ + + ]: 654 : if (mod->low_addr == module_start
772 [ - + ]: 26 : && mod->high_addr == module_end)
773 : 654 : skip_this_module = true;
774 : : }
775 : : }
776 [ + + ]: 456 : if (skip_this_module)
777 : 128 : goto out;
778 : : }
779 : :
780 : 328 : const char *file_note_name = handle_file_note (module_start, module_end,
781 : : ei_class, ei_data,
782 : : note_file, note_file_size);
783 [ + + ]: 328 : if (file_note_name)
784 : : {
785 : 200 : name = file_note_name;
786 : 200 : name_is_final = true;
787 : 200 : 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 [ + + + - ]: 200 : if (dwfl->sysroot && !executable)
792 : 8 : {
793 : : #ifdef HAVE_OPENAT2_RESOLVE_IN_ROOT
794 : 8 : int sysrootfd, err;
795 : :
796 : 8 : struct open_how how = {
797 : : .flags = O_RDONLY,
798 : : .resolve = RESOLVE_IN_ROOT,
799 : : };
800 : :
801 : 8 : sysrootfd = open (dwfl->sysroot, O_DIRECTORY|O_PATH);
802 [ - + ]: 8 : if (sysrootfd < 0)
803 : 0 : return -1;
804 : :
805 : 8 : fd = syscall (SYS_openat2, sysrootfd, name, &how, sizeof(how));
806 [ - + ]: 8 : err = fd < 0 ? -errno : 0;
807 : :
808 : 8 : close (sysrootfd);
809 : :
810 : : /* Fallback to regular open() if openat2 is not available. */
811 [ - + ]: 8 : if (fd < 0 && err == -ENOSYS)
812 : : #endif
813 : : {
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 : : {
820 : 0 : fd = open (n, O_RDONLY);
821 : 0 : free (n);
822 : : }
823 : : }
824 : : }
825 : : else
826 : 192 : fd = open (name, O_RDONLY);
827 : :
828 [ + + ]: 200 : if (fd >= 0)
829 : : {
830 : 12 : Dwfl_Error error = __libdw_open_file (&fd, &elf, true, false);
831 [ + - ]: 12 : if (error == DWFL_E_NOERROR)
832 : 12 : invalid = invalid_elf (elf, true /* disk_file_has_build_id */,
833 : : &build_id);
834 : : }
835 [ + - ]: 12 : if (invalid)
836 : : {
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 : 0 : close (fd);
841 : 0 : fd = -1;
842 : 0 : elf_end (elf);
843 : 0 : elf = NULL;
844 : : }
845 : : }
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 : 328 : GElf_Addr soname_stroff = 0;
854 : 328 : GElf_Addr dynstr_vaddr = 0;
855 : 328 : GElf_Xword dynstrsz = 0;
856 : 328 : bool execlike = false;
857 : 656 : const size_t dyn_entsize = (ei_class == ELFCLASS32
858 [ + + ]: 328 : ? sizeof (Elf32_Dyn) : sizeof (Elf64_Dyn));
859 : 328 : void *dyn_data = NULL;
860 : 328 : size_t dyn_data_size = 0;
861 [ + + - + ]: 328 : if (dyn_filesz != 0 && dyn_filesz % dyn_entsize == 0
862 [ + + ]: 280 : && ! read_portion (&read_state, &dyn_data, &dyn_data_size,
863 : : start, segment, dyn_vaddr, dyn_filesz))
864 : : {
865 [ + - ]: 274 : if ((dyn_filesz / dyn_entsize) == 0
866 [ - + ]: 274 : || dyn_filesz > (SIZE_MAX / dyn_entsize))
867 : 0 : goto out;
868 : 274 : void *dyns = malloc (dyn_filesz);
869 : 274 : Elf32_Dyn *d32 = dyns;
870 : 274 : Elf64_Dyn *d64 = dyns;
871 [ - + ]: 274 : if (unlikely (dyns == NULL))
872 : 0 : goto out;
873 : :
874 : 274 : xlatefrom.d_type = xlateto.d_type = ELF_T_DYN;
875 : 274 : xlatefrom.d_buf = (void *) dyn_data;
876 : 274 : xlatefrom.d_size = dyn_filesz;
877 : 274 : xlateto.d_buf = dyns;
878 : 274 : 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 : 274 : bool is32 = (ei_class == ELFCLASS32);
884 : 274 : size_t dyn_align = (is32
885 : : ? __alignof__ (Elf32_Dyn)
886 : : : __alignof__ (Elf64_Dyn));
887 [ - + ]: 274 : if (((uintptr_t) dyn_data & (dyn_align - 1)) != 0)
888 : : {
889 : 0 : memcpy (dyns, dyn_data, dyn_filesz);
890 : 0 : xlatefrom.d_buf = dyns;
891 : : }
892 : :
893 [ + + - + ]: 274 : if ((is32 && elf32_xlatetom (&xlateto, &xlatefrom, ei_data) != NULL)
894 [ - + ]: 238 : || (!is32 && elf64_xlatetom (&xlateto, &xlatefrom, ei_data) != NULL))
895 : : {
896 : 548 : size_t n = (is32
897 : : ? (dyn_filesz / sizeof (Elf32_Dyn))
898 [ + + ]: 274 : : (dyn_filesz / sizeof (Elf64_Dyn)));
899 [ + + ]: 3074 : for (size_t i = 0; i < n; ++i)
900 : : {
901 [ + + ]: 3052 : GElf_Sxword tag = is32 ? d32[i].d_tag : d64[i].d_tag;
902 [ + + ]: 3052 : GElf_Xword val = is32 ? d32[i].d_un.d_val : d64[i].d_un.d_val;
903 : :
904 [ + + ]: 3052 : if (tag == DT_DEBUG)
905 : : execlike = true;
906 [ + + + + ]: 3034 : else if (tag == DT_SONAME)
907 : : soname_stroff = val;
908 : : else if (tag == DT_STRTAB)
909 : : dynstr_vaddr = val;
910 : 2234 : else if (tag == DT_STRSZ)
911 : : dynstrsz = val;
912 : : else
913 : 2234 : continue;
914 : :
915 [ + + + + ]: 818 : if (soname_stroff != 0 && dynstr_vaddr != 0 && dynstrsz != 0)
916 : : break;
917 : : }
918 : : }
919 : 274 : free (dyns);
920 : : }
921 : 328 : 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 [ + + ]: 328 : if (name == NULL)
925 [ + + + + ]: 104 : name = e_type == ET_EXEC ? "[exe]" : execlike ? "[pie]" : "[dso]";
926 : :
927 : 328 : void *soname = NULL;
928 : 328 : size_t soname_size = 0;
929 [ + + + - ]: 328 : if (! name_is_final && dynstrsz != 0 && dynstr_vaddr != 0)
930 : : {
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 [ + + ]: 82 : if ((dynstr_vaddr < module_start || dynstr_vaddr >= module_end)
944 [ - + ]: 66 : && dynstr_vaddr + bias >= module_start
945 [ - + ]: 66 : && dynstr_vaddr + bias < module_end)
946 : 82 : dynstr_vaddr += bias;
947 : :
948 [ - + ]: 82 : if (unlikely (dynstr_vaddr + dynstrsz > module_end))
949 : 0 : dynstrsz = 0;
950 : :
951 : : /* Try to get the DT_SONAME string. */
952 [ + + - + ]: 82 : if (soname_stroff != 0 && soname_stroff + 1 < dynstrsz
953 [ - + ]: 72 : && ! read_portion (&read_state, &soname, &soname_size,
954 : : start, segment,
955 : : dynstr_vaddr + soname_stroff, 0))
956 : 72 : name = soname;
957 : : }
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 : 328 : Dwfl_Module *mod = INTUSE(dwfl_report_module) (dwfl, name,
963 : : module_start, module_end);
964 : :
965 : : // !execlike && ET_EXEC is PIE.
966 : : // execlike && !ET_EXEC is a static executable.
967 [ + - + + : 328 : if (mod != NULL && (execlike || ehdr.e32.e_type == ET_EXEC))
+ + ]
968 : 66 : mod->is_executable = true;
969 : :
970 [ - + + + ]: 328 : if (likely (mod != NULL) && build_id.memory != NULL
971 [ + - ]: 326 : && unlikely (INTUSE(dwfl_module_report_build_id) (mod,
972 : : build_id.memory,
973 : : build_id.len,
974 : : build_id.vaddr)))
975 : : {
976 : 0 : mod->gc = true;
977 : 0 : mod = NULL;
978 : : }
979 : :
980 : : /* At this point we do not need BUILD_ID or NAME any more.
981 : : They have been copied. */
982 : 328 : free (build_id.memory);
983 : 328 : build_id.memory = NULL;
984 : 328 : finish_portion (&read_state, &soname, &soname_size);
985 : :
986 [ - + ]: 328 : if (unlikely (mod == NULL))
987 : : {
988 : 0 : ndx = -1;
989 : 0 : goto out;
990 : : }
991 : : else
992 : 328 : 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 : 656 : const GElf_Off cost = (contiguous < file_trimmed_end ? total_filesz
998 [ + + ]: 328 : : buffer_available >= contiguous ? 0
999 [ + + ]: 24 : : contiguous - buffer_available);
1000 : 656 : const GElf_Off worthwhile = ((dynstr_vaddr == 0 || dynstrsz == 0) ? 0
1001 [ + + ]: 328 : : dynstr_vaddr + dynstrsz - start);
1002 : 328 : const GElf_Off whole = MAX (file_trimmed_end, shdrs_end);
1003 : :
1004 [ + + ]: 328 : if (elf == NULL
1005 [ + + ]: 316 : && (*read_eagerly) (MODCB_ARGS (mod), &buffer, &buffer_available,
1006 : : cost, worthwhile, whole, contiguous,
1007 : : read_eagerly_arg, &elf)
1008 [ + + ]: 90 : && elf == NULL)
1009 : : {
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 : 8 : if (file_trimmed_end > maxread)
1014 : : file_trimmed_end = maxread;
1015 : :
1016 : 8 : void *contents = calloc (1, file_trimmed_end);
1017 [ - + ]: 8 : if (unlikely (contents == NULL))
1018 : 0 : goto out;
1019 : :
1020 [ + + ]: 8 : if (contiguous < file_trimmed_end)
1021 : : {
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 [ + + ]: 46 : for (uint_fast16_t i = 0; i < phnum; ++i)
1025 : : {
1026 : 40 : bool is32 = (ei_class == ELFCLASS32);
1027 [ - + ]: 40 : GElf_Word type = is32 ? p32[i].p_type : p64[i].p_type;
1028 : :
1029 [ + + ]: 40 : if (type != PT_LOAD)
1030 : 30 : continue;
1031 : :
1032 [ - + ]: 10 : GElf_Addr vaddr = is32 ? p32[i].p_vaddr : p64[i].p_vaddr;
1033 [ - + ]: 10 : GElf_Off offset = is32 ? p32[i].p_offset : p64[i].p_offset;
1034 [ - + ]: 10 : 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 [ - + ]: 10 : if (offset >= file_trimmed_end)
1038 : 0 : continue;
1039 : :
1040 : 10 : void *into = contents + offset;
1041 : 10 : size_t read_size = MIN (filesz, file_trimmed_end - offset);
1042 : 10 : (*memory_callback) (dwfl, addr_segndx (dwfl, segment,
1043 : : vaddr + bias, false),
1044 : : &into, &read_size, vaddr + bias, read_size,
1045 : : memory_callback_arg);
1046 : : }
1047 : : }
1048 : : else
1049 : : {
1050 : : /* The whole file sits contiguous in memory,
1051 : : but the caller didn't want to just do it. */
1052 : :
1053 : 2 : const size_t have = MIN (buffer_available, file_trimmed_end);
1054 [ - + ]: 2 : memcpy (contents, buffer, have);
1055 : :
1056 [ - + ]: 2 : if (have < file_trimmed_end)
1057 : : {
1058 : 0 : void *into = contents + have;
1059 : 0 : size_t read_size = file_trimmed_end - have;
1060 : 0 : (*memory_callback) (dwfl,
1061 : : addr_segndx (dwfl, segment,
1062 : : start + have, false),
1063 : : &into, &read_size, start + have,
1064 : : read_size, memory_callback_arg);
1065 : : }
1066 : : }
1067 : :
1068 : 8 : elf = elf_memory (contents, file_trimmed_end);
1069 [ - + ]: 8 : if (unlikely (elf == NULL))
1070 : 0 : free (contents);
1071 : : else
1072 : 8 : elf->flags |= ELF_F_MALLOCED;
1073 : : }
1074 : :
1075 [ + + + + ]: 328 : if (elf != NULL && mod->main.elf == NULL)
1076 : : {
1077 : : /* Install the file in the module. */
1078 : 96 : mod->main.elf = elf;
1079 : 96 : mod->main.fd = fd;
1080 : 96 : elf = NULL;
1081 : 96 : fd = -1;
1082 : 96 : mod->main.vaddr = module_start - bias;
1083 : 96 : mod->main.address_sync = module_address_sync;
1084 : 96 : mod->main_bias = bias;
1085 : : }
1086 : :
1087 : 232 : out:
1088 [ + + ]: 1758 : if (build_id.memory != NULL)
1089 : 126 : free (build_id.memory);
1090 : 1758 : free (phdrsp);
1091 [ + + ]: 1758 : if (buffer != NULL)
1092 : 1396 : (*memory_callback) (dwfl, -1, &buffer, &buffer_available, 0, 0,
1093 : : memory_callback_arg);
1094 : :
1095 [ + + ]: 1758 : if (elf != NULL)
1096 : 6 : elf_end (elf);
1097 [ - + ]: 1758 : if (fd != -1)
1098 : 0 : close (fd);
1099 : : return ndx;
1100 : : }
|