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