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