1 /* Core file handling.
2 Copyright (C) 2008-2010, 2013, 2015 Red Hat, Inc.
3 Copyright (C) 2021 Mark J. Wielaard <[email protected]>
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_ALIGN. */
32 #include "libdwflP.h"
33 #include <gelf.h>
34
35 /* On failure return, we update *NEXT to point back at OFFSET. */
36 static inline Elf *
do_fail(int error,off_t * next,off_t offset)37 do_fail (int error, off_t *next, off_t offset)
38 {
39 if (next != NULL)
40 *next = offset;
41 //__libelf_seterrno (error);
42 __libdwfl_seterrno (DWFL_E (LIBELF, error));
43 return NULL;
44 }
45
46 #define fail(error) do_fail (error, next, offset)
47
48 /* This is a prototype of what a new libelf interface might be.
49 This implementation is pessimal for non-mmap cases and should
50 be replaced by more diddling inside libelf internals. */
51 static Elf *
elf_begin_rand(Elf * parent,off_t offset,off_t size,off_t * next)52 elf_begin_rand (Elf *parent, off_t offset, off_t size, off_t *next)
53 {
54 if (parent == NULL)
55 return NULL;
56
57 off_t min = (parent->kind == ELF_K_ELF ?
58 (parent->class == ELFCLASS32
59 ? sizeof (Elf32_Ehdr) : sizeof (Elf64_Ehdr))
60 : parent->kind == ELF_K_AR ? SARMAG
61 : 0);
62
63 if (unlikely (offset < min)
64 || unlikely (offset >= (off_t) parent->maximum_size))
65 return fail (ELF_E_RANGE);
66
67 /* For an archive, fetch just the size field
68 from the archive header to override SIZE. */
69 if (parent->kind == ELF_K_AR)
70 {
71 /* File size, in ASCII decimal, right-padded with ASCII spaces.
72 Max 10 characters. Not zero terminated. So make this ar_size
73 array one larger and explicitly zero terminate it. As needed
74 for strtoll. */
75 #define AR_SIZE_CHARS 10
76 char ar_size[AR_SIZE_CHARS + 1];
77 ar_size[AR_SIZE_CHARS] = '\0';
78
79 if (unlikely (parent->maximum_size - offset < sizeof (struct ar_hdr)))
80 return fail (ELF_E_RANGE);
81
82 if (parent->map_address != NULL)
83 memcpy (ar_size, parent->map_address + parent->start_offset + offset,
84 AR_SIZE_CHARS);
85 else if (unlikely (pread_retry (parent->fildes,
86 ar_size, AR_SIZE_CHARS,
87 parent->start_offset + offset
88 + offsetof (struct ar_hdr, ar_size))
89 != AR_SIZE_CHARS))
90 return fail (ELF_E_READ_ERROR);
91
92 offset += sizeof (struct ar_hdr);
93
94 char *endp;
95 size = strtoll (ar_size, &endp, 10);
96 if (unlikely (endp == ar_size)
97 || unlikely ((off_t) parent->maximum_size - offset < size))
98 return fail (ELF_E_INVALID_ARCHIVE);
99 }
100
101 if (unlikely ((off_t) parent->maximum_size - offset < size))
102 return fail (ELF_E_RANGE);
103
104 /* Even if we fail at this point, update *NEXT to point past the file. */
105 if (next != NULL)
106 *next = offset + size;
107
108 if (unlikely (offset == 0)
109 && unlikely (size == (off_t) parent->maximum_size))
110 return elf_clone (parent, parent->cmd);
111
112 /* Note the image is guaranteed live only as long as PARENT
113 lives. Using elf_memory is quite suboptimal if the whole
114 file is not mmap'd. We really should have something like
115 a generalization of the archive support. */
116 Elf_Data *data = elf_getdata_rawchunk (parent, offset, size, ELF_T_BYTE);
117 if (data == NULL)
118 return NULL;
119 assert ((off_t) data->d_size == size);
120 return elf_memory (data->d_buf, size);
121 }
122
123
124 int
dwfl_report_core_segments(Dwfl * dwfl,Elf * elf,size_t phnum,GElf_Phdr * notes)125 dwfl_report_core_segments (Dwfl *dwfl, Elf *elf, size_t phnum, GElf_Phdr *notes)
126 {
127 if (unlikely (dwfl == NULL))
128 return -1;
129
130 int result = 0;
131
132 if (notes != NULL)
133 notes->p_type = PT_NULL;
134
135 for (size_t ndx = 0; result >= 0 && ndx < phnum; ++ndx)
136 {
137 GElf_Phdr phdr_mem;
138 GElf_Phdr *phdr = gelf_getphdr (elf, ndx, &phdr_mem);
139 if (unlikely (phdr == NULL))
140 {
141 __libdwfl_seterrno (DWFL_E_LIBELF);
142 return -1;
143 }
144 switch (phdr->p_type)
145 {
146 case PT_LOAD:
147 result = dwfl_report_segment (dwfl, ndx, phdr, 0, NULL);
148 break;
149
150 case PT_NOTE:
151 if (notes != NULL)
152 {
153 *notes = *phdr;
154 notes = NULL;
155 }
156 break;
157 }
158 }
159
160 return result;
161 }
162
163 /* Never read more than this much without mmap. */
164 #define MAX_EAGER_COST 8192
165
166 /* Dwfl_Module_Callback passed to and called by dwfl_segment_report_module
167 to read in a segment as ELF image directly if possible or indicate an
168 attempt must be made to read in the while segment right now. */
169 static bool
core_file_read_eagerly(Dwfl_Module * mod,void ** userdata,const char * name,Dwarf_Addr start,void ** buffer,size_t * buffer_available,GElf_Off cost,GElf_Off worthwhile,GElf_Off whole,GElf_Off contiguous,void * arg,Elf ** elfp)170 core_file_read_eagerly (Dwfl_Module *mod,
171 void **userdata __attribute__ ((unused)),
172 const char *name __attribute__ ((unused)),
173 Dwarf_Addr start __attribute__ ((unused)),
174 void **buffer, size_t *buffer_available,
175 GElf_Off cost, GElf_Off worthwhile,
176 GElf_Off whole,
177 GElf_Off contiguous __attribute__ ((unused)),
178 void *arg, Elf **elfp)
179 {
180 Elf *core = arg;
181
182 /* The available buffer is often the whole segment when the core file
183 was mmap'd if used together with the dwfl_elf_phdr_memory_callback.
184 Which means that if it is complete we can just construct the whole
185 ELF image right now without having to read in anything more. */
186 if (whole <= *buffer_available)
187 {
188 /* All there ever was, we already have on hand. */
189
190 if (core->map_address == NULL)
191 {
192 /* We already malloc'd the buffer. */
193 *elfp = elf_memory (*buffer, whole);
194 if (unlikely (*elfp == NULL))
195 return false;
196
197 (*elfp)->flags |= ELF_F_MALLOCED;
198 *buffer = NULL;
199 *buffer_available = 0;
200 return true;
201 }
202
203 /* We can use the image inside the core file directly. */
204 *elfp = elf_begin_rand (core, *buffer - core->map_address, whole, NULL);
205 *buffer = NULL;
206 *buffer_available = 0;
207 return *elfp != NULL;
208 }
209
210 /* We don't have the whole file. Which either means the core file
211 wasn't mmap'd, but needs to still be read in, or that the segment
212 is truncated. Figure out if this is better than nothing. */
213
214 if (worthwhile == 0)
215 /* Caller doesn't think so. */
216 return false;
217
218 /*
219 XXX would like to fall back to partial file via memory
220 when build id find_elf fails
221 also, link_map name may give file name from disk better than partial here
222 requires find_elf hook re-doing the magic to fall back if no file found
223 */
224
225 if (whole > MAX_EAGER_COST && mod->build_id_len > 0)
226 /* We can't cheaply read the whole file here, so we'd
227 be using a partial file. But there is a build ID that could
228 help us find the whole file, which might be more useful than
229 what we have. We'll just rely on that. */
230 return false;
231
232 /* The file is either small (most likely the vdso) or big and incomplete,
233 but we don't have a build-id. */
234
235 if (core->map_address != NULL)
236 /* It's cheap to get, so get it. */
237 return true;
238
239 /* Only use it if there isn't too much to be read. */
240 return cost <= MAX_EAGER_COST;
241 }
242
243 static inline void
update_end(GElf_Phdr * pphdr,const GElf_Off align,GElf_Off * pend,GElf_Addr * pend_vaddr)244 update_end (GElf_Phdr *pphdr, const GElf_Off align,
245 GElf_Off *pend, GElf_Addr *pend_vaddr)
246 {
247 *pend = (pphdr->p_offset + pphdr->p_filesz + align - 1) & -align;
248 *pend_vaddr = (pphdr->p_vaddr + pphdr->p_memsz + align - 1) & -align;
249 }
250
251 /* Use following contiguous segments to get towards SIZE. */
252 static inline bool
do_more(size_t size,GElf_Phdr * pphdr,const GElf_Off align,Elf * elf,GElf_Off start,int * pndx,GElf_Off * pend,GElf_Addr * pend_vaddr)253 do_more (size_t size, GElf_Phdr *pphdr, const GElf_Off align,
254 Elf *elf, GElf_Off start, int *pndx,
255 GElf_Off *pend, GElf_Addr *pend_vaddr)
256 {
257 while (*pend <= start || *pend - start < size)
258 {
259 if (pphdr->p_filesz < pphdr->p_memsz)
260 /* This segment is truncated, so no following one helps us. */
261 return false;
262
263 if (unlikely (gelf_getphdr (elf, (*pndx)++, pphdr) == NULL))
264 return false;
265
266 if (pphdr->p_type == PT_LOAD)
267 {
268 if (pphdr->p_offset > *pend
269 || pphdr->p_vaddr > *pend_vaddr)
270 /* It's discontiguous! */
271 return false;
272
273 update_end (pphdr, align, pend, pend_vaddr);
274 }
275 }
276 return true;
277 }
278
279 #define more(size) do_more (size, &phdr, align, elf, start, &ndx, &end, &end_vaddr)
280
281 bool
dwfl_elf_phdr_memory_callback(Dwfl * dwfl,int ndx,void ** buffer,size_t * buffer_available,GElf_Addr vaddr,size_t minread,void * arg)282 dwfl_elf_phdr_memory_callback (Dwfl *dwfl, int ndx,
283 void **buffer, size_t *buffer_available,
284 GElf_Addr vaddr,
285 size_t minread,
286 void *arg)
287 {
288 Elf *elf = arg;
289
290 if (ndx == -1)
291 {
292 /* Called for cleanup. */
293 if (elf->map_address == NULL)
294 free (*buffer);
295 *buffer = NULL;
296 *buffer_available = 0;
297 return false;
298 }
299
300 const GElf_Off align = dwfl->segment_align ?: 1;
301 GElf_Phdr phdr;
302
303 do
304 if (unlikely (gelf_getphdr (elf, ndx++, &phdr) == NULL))
305 return false;
306 while (phdr.p_type != PT_LOAD
307 || ((phdr.p_vaddr + phdr.p_memsz + align - 1) & -align) <= vaddr);
308
309 GElf_Off start = vaddr - phdr.p_vaddr + phdr.p_offset;
310 GElf_Off end;
311 GElf_Addr end_vaddr;
312
313 update_end (&phdr, align, &end, &end_vaddr);
314
315 /* We need at least this much. */
316 if (! more (minread))
317 return false;
318
319 /* See how much more we can get of what the caller wants. */
320 (void) more (*buffer_available);
321
322 /* If it's already on hand anyway, use as much as there is. */
323 if (elf->map_address != NULL && start < elf->maximum_size)
324 (void) more (elf->maximum_size - start);
325
326 /* Make sure we don't look past the end of the actual file,
327 even if the headers tell us to. */
328 if (unlikely (end > elf->maximum_size))
329 end = elf->maximum_size;
330
331 /* If the file is too small, there is nothing at all to get. */
332 if (unlikely (start >= end))
333 return false;
334
335 if (end - start < minread)
336 return false;
337
338 if (elf->map_address != NULL)
339 {
340 void *contents = elf->map_address + elf->start_offset + start;
341 size_t size = end - start;
342
343 if (minread == 0) /* String mode. */
344 {
345 const void *eos = memchr (contents, '\0', size);
346 if (unlikely (eos == NULL) || unlikely (eos == contents))
347 return false;
348 size = eos + 1 - contents;
349 }
350
351 if (*buffer == NULL)
352 {
353 *buffer = contents;
354 *buffer_available = size;
355 }
356 else
357 {
358 *buffer_available = MIN (size, *buffer_available);
359 memcpy (*buffer, contents, *buffer_available);
360 }
361 }
362 else
363 {
364 void *into = *buffer;
365 if (*buffer == NULL)
366 {
367 *buffer_available = MIN (minread ?: 512,
368 MAX (4096, MIN (end - start,
369 *buffer_available)));
370 into = malloc (*buffer_available);
371 if (unlikely (into == NULL))
372 {
373 __libdwfl_seterrno (DWFL_E_NOMEM);
374 return false;
375 }
376 }
377
378 ssize_t nread = pread_retry (elf->fildes, into, *buffer_available, start);
379 if (nread < (ssize_t) minread)
380 {
381 if (into != *buffer)
382 free (into);
383 if (nread < 0)
384 __libdwfl_seterrno (DWFL_E_ERRNO);
385 return false;
386 }
387
388 if (minread == 0) /* String mode. */
389 {
390 const void *eos = memchr (into, '\0', nread);
391 if (unlikely (eos == NULL) || unlikely (eos == into))
392 {
393 if (*buffer == NULL)
394 free (into);
395 return false;
396 }
397 nread = eos + 1 - into;
398 }
399
400 if (*buffer == NULL)
401 *buffer = into;
402 *buffer_available = nread;
403 }
404
405 return true;
406 }
407
408 /* Free the contents of R_DEBUG_INFO without the R_DEBUG_INFO memory itself. */
409
410 static void
clear_r_debug_info(struct r_debug_info * r_debug_info)411 clear_r_debug_info (struct r_debug_info *r_debug_info)
412 {
413 while (r_debug_info->module != NULL)
414 {
415 struct r_debug_info_module *module = r_debug_info->module;
416 r_debug_info->module = module->next;
417 elf_end (module->elf);
418 if (module->fd != -1)
419 close (module->fd);
420 free (module);
421 }
422 }
423
424 bool
425 internal_function
__libdwfl_dynamic_vaddr_get(Elf * elf,GElf_Addr * vaddrp)426 __libdwfl_dynamic_vaddr_get (Elf *elf, GElf_Addr *vaddrp)
427 {
428 size_t phnum;
429 if (unlikely (elf_getphdrnum (elf, &phnum) != 0))
430 return false;
431 for (size_t i = 0; i < phnum; ++i)
432 {
433 GElf_Phdr phdr_mem;
434 GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem);
435 if (unlikely (phdr == NULL))
436 return false;
437 if (phdr->p_type == PT_DYNAMIC)
438 {
439 *vaddrp = phdr->p_vaddr;
440 return true;
441 }
442 }
443 return false;
444 }
445
446 NEW_VERSION (dwfl_core_file_report, ELFUTILS_0.158)
447 int
dwfl_core_file_report(Dwfl * dwfl,Elf * elf,const char * executable)448 dwfl_core_file_report (Dwfl *dwfl, Elf *elf, const char *executable)
449 {
450 size_t phnum;
451 if (unlikely (elf_getphdrnum (elf, &phnum) != 0))
452 {
453 __libdwfl_seterrno (DWFL_E_LIBELF);
454 return -1;
455 }
456
457 bool cleanup_user_core = false;
458 if (dwfl->user_core != NULL)
459 free (dwfl->user_core->executable_for_core);
460 if (executable == NULL)
461 {
462 if (dwfl->user_core != NULL)
463 dwfl->user_core->executable_for_core = NULL;
464 }
465 else
466 {
467 if (dwfl->user_core == NULL)
468 {
469 cleanup_user_core = true;
470 dwfl->user_core = calloc (1, sizeof (struct Dwfl_User_Core));
471 if (dwfl->user_core == NULL)
472 {
473 __libdwfl_seterrno (DWFL_E_NOMEM);
474 return -1;
475 }
476 dwfl->user_core->fd = -1;
477 }
478 dwfl->user_core->executable_for_core = strdup (executable);
479 if (dwfl->user_core->executable_for_core == NULL)
480 {
481 if (cleanup_user_core)
482 {
483 free (dwfl->user_core);
484 dwfl->user_core = NULL;
485 }
486 __libdwfl_seterrno (DWFL_E_NOMEM);
487 return -1;
488 }
489 }
490
491 /* First report each PT_LOAD segment. */
492 GElf_Phdr notes_phdr;
493 int ndx = dwfl_report_core_segments (dwfl, elf, phnum, ¬es_phdr);
494 if (unlikely (ndx <= 0))
495 {
496 if (cleanup_user_core)
497 {
498 free (dwfl->user_core->executable_for_core);
499 free (dwfl->user_core);
500 dwfl->user_core = NULL;
501 }
502 return ndx;
503 }
504
505 /* Next, we should follow the chain from DT_DEBUG. */
506
507 const void *auxv = NULL;
508 const void *note_file = NULL;
509 size_t auxv_size = 0;
510 size_t note_file_size = 0;
511 if (likely (notes_phdr.p_type == PT_NOTE))
512 {
513 /* PT_NOTE -> NT_AUXV -> AT_PHDR -> PT_DYNAMIC -> DT_DEBUG */
514
515 Elf_Data *notes = elf_getdata_rawchunk (elf,
516 notes_phdr.p_offset,
517 notes_phdr.p_filesz,
518 (notes_phdr.p_align == 8
519 ? ELF_T_NHDR8
520 : ELF_T_NHDR));
521 if (likely (notes != NULL))
522 {
523 size_t pos = 0;
524 GElf_Nhdr nhdr;
525 size_t name_pos;
526 size_t desc_pos;
527 while ((pos = gelf_getnote (notes, pos, &nhdr,
528 &name_pos, &desc_pos)) > 0)
529 if (nhdr.n_namesz == sizeof "CORE"
530 && !memcmp (notes->d_buf + name_pos, "CORE", sizeof "CORE"))
531 {
532 if (nhdr.n_type == NT_AUXV)
533 {
534 auxv = notes->d_buf + desc_pos;
535 auxv_size = nhdr.n_descsz;
536 }
537 if (nhdr.n_type == NT_FILE)
538 {
539 note_file = notes->d_buf + desc_pos;
540 note_file_size = nhdr.n_descsz;
541 }
542 }
543 }
544 }
545
546 /* Now we have NT_AUXV contents. From here on this processing could be
547 used for a live process with auxv read from /proc. */
548
549 struct r_debug_info r_debug_info;
550 memset (&r_debug_info, 0, sizeof r_debug_info);
551 int retval = dwfl_link_map_report (dwfl, auxv, auxv_size,
552 dwfl_elf_phdr_memory_callback, elf,
553 &r_debug_info);
554 int listed = retval > 0 ? retval : 0;
555
556 /* Now sniff segment contents for modules hinted by information gathered
557 from DT_DEBUG. */
558
559 ndx = 0;
560 do
561 {
562 int seg = dwfl_segment_report_module (dwfl, ndx, NULL,
563 &dwfl_elf_phdr_memory_callback, elf,
564 core_file_read_eagerly, elf,
565 elf->maximum_size,
566 note_file, note_file_size,
567 &r_debug_info);
568 if (unlikely (seg < 0))
569 {
570 clear_r_debug_info (&r_debug_info);
571 return seg;
572 }
573 if (seg > ndx)
574 {
575 ndx = seg;
576 ++listed;
577 }
578 else
579 ++ndx;
580 }
581 while (ndx < (int) phnum);
582
583 /* Now report the modules from dwfl_link_map_report which were not filtered
584 out by dwfl_segment_report_module. */
585
586 Dwfl_Module **lastmodp = &dwfl->modulelist;
587 while (*lastmodp != NULL)
588 lastmodp = &(*lastmodp)->next;
589 for (struct r_debug_info_module *module = r_debug_info.module;
590 module != NULL; module = module->next)
591 {
592 if (module->elf == NULL)
593 continue;
594 GElf_Addr file_dynamic_vaddr;
595 if (! __libdwfl_dynamic_vaddr_get (module->elf, &file_dynamic_vaddr))
596 continue;
597 Dwfl_Module *mod;
598 mod = __libdwfl_report_elf (dwfl, xbasename (module->name), module->name,
599 module->fd, module->elf,
600 module->l_ld - file_dynamic_vaddr,
601 true, true);
602 if (mod == NULL)
603 continue;
604 ++listed;
605 module->elf = NULL;
606 module->fd = -1;
607 /* Move this module to the end of the list, so that we end
608 up with a list in the same order as the link_map chain. */
609 if (mod->next != NULL)
610 {
611 if (*lastmodp != mod)
612 {
613 lastmodp = &dwfl->modulelist;
614 while (*lastmodp != mod)
615 lastmodp = &(*lastmodp)->next;
616 }
617 *lastmodp = mod->next;
618 mod->next = NULL;
619 while (*lastmodp != NULL)
620 lastmodp = &(*lastmodp)->next;
621 *lastmodp = mod;
622 }
623 lastmodp = &mod->next;
624 }
625
626 clear_r_debug_info (&r_debug_info);
627
628 /* We return the number of modules we found if we found any.
629 If we found none, we return -1 instead of 0 if there was an
630 error rather than just nothing found. */
631 return listed > 0 ? listed : retval;
632 }
633 NEW_INTDEF (dwfl_core_file_report)
634
635 #ifdef SYMBOL_VERSIONING
636 int _compat_without_executable_dwfl_core_file_report (Dwfl *dwfl, Elf *elf);
637 COMPAT_VERSION_NEWPROTO (dwfl_core_file_report, ELFUTILS_0.146,
638 without_executable)
639
640 int
_compat_without_executable_dwfl_core_file_report(Dwfl * dwfl,Elf * elf)641 _compat_without_executable_dwfl_core_file_report (Dwfl *dwfl, Elf *elf)
642 {
643 return dwfl_core_file_report (dwfl, elf, NULL);
644 }
645 #endif
646