Line data Source code
1 : /* Core file handling.
2 : Copyright (C) 2008-2010, 2013, 2015 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_ALIGN. */
31 : #undef _
32 : #include "libdwflP.h"
33 : #include <gelf.h>
34 :
35 : #include <unistd.h>
36 : #include <endian.h>
37 : #include <byteswap.h>
38 : #include "system.h"
39 :
40 :
41 : /* On failure return, we update *NEXT to point back at OFFSET. */
42 : static inline Elf *
43 : do_fail (int error, off_t *next, off_t offset)
44 : {
45 0 : if (next != NULL)
46 0 : *next = offset;
47 : //__libelf_seterrno (error);
48 0 : __libdwfl_seterrno (DWFL_E (LIBELF, error));
49 : return NULL;
50 : }
51 :
52 : #define fail(error) do_fail (error, next, offset)
53 :
54 : /* This is a prototype of what a new libelf interface might be.
55 : This implementation is pessimal for non-mmap cases and should
56 : be replaced by more diddling inside libelf internals. */
57 : static Elf *
58 36 : elf_begin_rand (Elf *parent, off_t offset, off_t size, off_t *next)
59 : {
60 36 : if (parent == NULL)
61 : return NULL;
62 :
63 72 : off_t min = (parent->kind == ELF_K_ELF ?
64 36 : (parent->class == ELFCLASS32
65 : ? sizeof (Elf32_Ehdr) : sizeof (Elf64_Ehdr))
66 72 : : parent->kind == ELF_K_AR ? SARMAG
67 : : 0);
68 :
69 36 : if (unlikely (offset < min)
70 36 : || unlikely (offset >= (off_t) parent->maximum_size))
71 0 : return fail (ELF_E_RANGE);
72 :
73 : /* For an archive, fetch just the size field
74 : from the archive header to override SIZE. */
75 36 : if (parent->kind == ELF_K_AR)
76 : {
77 0 : struct ar_hdr h = { .ar_size = "" };
78 :
79 0 : if (unlikely (parent->maximum_size - offset < sizeof h))
80 0 : return fail (ELF_E_RANGE);
81 :
82 0 : if (parent->map_address != NULL)
83 0 : memcpy (h.ar_size, parent->map_address + parent->start_offset + offset,
84 : sizeof h.ar_size);
85 0 : else if (unlikely (pread_retry (parent->fildes,
86 : h.ar_size, sizeof (h.ar_size),
87 : parent->start_offset + offset
88 : + offsetof (struct ar_hdr, ar_size))
89 : != sizeof (h.ar_size)))
90 0 : return fail (ELF_E_READ_ERROR);
91 :
92 0 : offset += sizeof h;
93 :
94 : char *endp;
95 0 : size = strtoll (h.ar_size, &endp, 10);
96 0 : if (unlikely (endp == h.ar_size)
97 0 : || unlikely ((off_t) parent->maximum_size - offset < size))
98 0 : return fail (ELF_E_INVALID_ARCHIVE);
99 : }
100 :
101 36 : if (unlikely ((off_t) parent->maximum_size - offset < size))
102 0 : return fail (ELF_E_RANGE);
103 :
104 : /* Even if we fail at this point, update *NEXT to point past the file. */
105 36 : if (next != NULL)
106 0 : *next = offset + size;
107 :
108 36 : if (unlikely (offset == 0)
109 0 : && unlikely (size == (off_t) parent->maximum_size))
110 0 : 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 36 : Elf_Data *data = elf_getdata_rawchunk (parent, offset, size, ELF_T_BYTE);
117 36 : if (data == NULL)
118 : return NULL;
119 36 : assert ((off_t) data->d_size == size);
120 36 : return elf_memory (data->d_buf, size);
121 : }
122 :
123 :
124 : int
125 36 : dwfl_report_core_segments (Dwfl *dwfl, Elf *elf, size_t phnum, GElf_Phdr *notes)
126 : {
127 36 : if (unlikely (dwfl == NULL))
128 : return -1;
129 :
130 36 : int result = 0;
131 :
132 36 : if (notes != NULL)
133 36 : notes->p_type = PT_NULL;
134 :
135 721 : for (size_t ndx = 0; result >= 0 && ndx < phnum; ++ndx)
136 : {
137 : GElf_Phdr phdr_mem;
138 721 : GElf_Phdr *phdr = gelf_getphdr (elf, ndx, &phdr_mem);
139 721 : if (unlikely (phdr == NULL))
140 : {
141 0 : __libdwfl_seterrno (DWFL_E_LIBELF);
142 0 : return -1;
143 : }
144 721 : switch (phdr->p_type)
145 : {
146 685 : case PT_LOAD:
147 685 : result = dwfl_report_segment (dwfl, ndx, phdr, 0, NULL);
148 685 : break;
149 :
150 36 : case PT_NOTE:
151 36 : if (notes != NULL)
152 : {
153 36 : *notes = *phdr;
154 36 : 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
170 117 : 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 117 : 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 117 : if (whole <= *buffer_available)
187 : {
188 : /* All there ever was, we already have on hand. */
189 :
190 36 : if (core->map_address == NULL)
191 : {
192 : /* We already malloc'd the buffer. */
193 0 : *elfp = elf_memory (*buffer, whole);
194 0 : if (unlikely (*elfp == NULL))
195 : return false;
196 :
197 0 : (*elfp)->flags |= ELF_F_MALLOCED;
198 0 : *buffer = NULL;
199 0 : *buffer_available = 0;
200 0 : return true;
201 : }
202 :
203 : /* We can use the image inside the core file directly. */
204 36 : *elfp = elf_begin_rand (core, *buffer - core->map_address, whole, NULL);
205 36 : *buffer = NULL;
206 36 : *buffer_available = 0;
207 36 : 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 81 : 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 69 : 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 3 : 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 0 : return cost <= MAX_EAGER_COST;
241 : }
242 :
243 : static inline void
244 : update_end (GElf_Phdr *pphdr, const GElf_Off align,
245 : GElf_Off *pend, GElf_Addr *pend_vaddr)
246 : {
247 1275 : *pend = (pphdr->p_offset + pphdr->p_filesz + align - 1) & -align;
248 1275 : *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
253 2383 : 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 5192 : while (*pend <= start || *pend - start < size)
258 : {
259 1235 : if (pphdr->p_filesz < pphdr->p_memsz)
260 : /* This segment is truncated, so no following one helps us. */
261 : return false;
262 :
263 983 : if (unlikely (gelf_getphdr (elf, (*pndx)++, pphdr) == NULL))
264 : return false;
265 :
266 983 : if (pphdr->p_type == PT_LOAD)
267 : {
268 983 : if (pphdr->p_offset > *pend
269 983 : || 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
282 1576 : 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 1576 : Elf *elf = arg;
289 :
290 1576 : if (ndx == -1)
291 : {
292 : /* Called for cleanup. */
293 727 : if (elf->map_address == NULL)
294 0 : free (*buffer);
295 727 : *buffer = NULL;
296 727 : *buffer_available = 0;
297 727 : return false;
298 : }
299 :
300 849 : const GElf_Off align = dwfl->segment_align ?: 1;
301 : GElf_Phdr phdr;
302 :
303 : do
304 885 : if (unlikely (gelf_getphdr (elf, ndx++, &phdr) == NULL))
305 : return false;
306 885 : while (phdr.p_type != PT_LOAD
307 885 : || ((phdr.p_vaddr + phdr.p_memsz + align - 1) & -align) <= vaddr);
308 :
309 849 : GElf_Off start = vaddr - phdr.p_vaddr + phdr.p_offset;
310 : GElf_Off end;
311 : GElf_Addr end_vaddr;
312 :
313 849 : update_end (&phdr, align, &end, &end_vaddr);
314 :
315 : /* We need at least this much. */
316 849 : if (! more (minread))
317 : return false;
318 :
319 : /* See how much more we can get of what the caller wants. */
320 767 : (void) more (*buffer_available);
321 :
322 : /* If it's already on hand anyway, use as much as there is. */
323 767 : if (elf->map_address != NULL)
324 767 : (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 767 : if (unlikely (end > elf->maximum_size))
329 0 : end = elf->maximum_size;
330 :
331 : /* If the file is too small, there is nothing at all to get. */
332 767 : if (unlikely (start >= end))
333 : return false;
334 :
335 767 : if (elf->map_address != NULL)
336 : {
337 767 : void *contents = elf->map_address + elf->start_offset + start;
338 767 : size_t size = end - start;
339 :
340 767 : if (minread == 0) /* String mode. */
341 : {
342 73 : const void *eos = memchr (contents, '\0', size);
343 73 : if (unlikely (eos == NULL) || unlikely (eos == contents))
344 : return false;
345 73 : size = eos + 1 - contents;
346 : }
347 :
348 767 : if (*buffer == NULL)
349 : {
350 763 : *buffer = contents;
351 763 : *buffer_available = size;
352 : }
353 : else
354 : {
355 4 : *buffer_available = MIN (size, *buffer_available);
356 4 : memcpy (*buffer, contents, *buffer_available);
357 : }
358 : }
359 : else
360 : {
361 0 : void *into = *buffer;
362 0 : if (*buffer == NULL)
363 : {
364 0 : *buffer_available = MIN (minread ?: 512,
365 : MAX (4096, MIN (end - start,
366 : *buffer_available)));
367 0 : into = malloc (*buffer_available);
368 0 : if (unlikely (into == NULL))
369 : {
370 0 : __libdwfl_seterrno (DWFL_E_NOMEM);
371 0 : return false;
372 : }
373 : }
374 :
375 0 : ssize_t nread = pread_retry (elf->fildes, into, *buffer_available, start);
376 0 : if (nread < (ssize_t) minread)
377 : {
378 0 : if (into != *buffer)
379 0 : free (into);
380 0 : if (nread < 0)
381 0 : __libdwfl_seterrno (DWFL_E_ERRNO);
382 : return false;
383 : }
384 :
385 0 : if (minread == 0) /* String mode. */
386 : {
387 0 : const void *eos = memchr (into, '\0', nread);
388 0 : if (unlikely (eos == NULL) || unlikely (eos == into))
389 : {
390 0 : if (*buffer == NULL)
391 0 : free (into);
392 : return false;
393 : }
394 0 : nread = eos + 1 - into;
395 : }
396 :
397 0 : if (*buffer == NULL)
398 0 : *buffer = into;
399 0 : *buffer_available = nread;
400 : }
401 :
402 : return true;
403 : }
404 :
405 : /* Free the contents of R_DEBUG_INFO without the R_DEBUG_INFO memory itself. */
406 :
407 : static void
408 36 : clear_r_debug_info (struct r_debug_info *r_debug_info)
409 : {
410 190 : while (r_debug_info->module != NULL)
411 : {
412 118 : struct r_debug_info_module *module = r_debug_info->module;
413 118 : r_debug_info->module = module->next;
414 118 : elf_end (module->elf);
415 118 : if (module->fd != -1)
416 0 : close (module->fd);
417 118 : free (module);
418 : }
419 36 : }
420 :
421 : bool
422 : internal_function
423 64 : __libdwfl_dynamic_vaddr_get (Elf *elf, GElf_Addr *vaddrp)
424 : {
425 : size_t phnum;
426 64 : if (unlikely (elf_getphdrnum (elf, &phnum) != 0))
427 : return false;
428 608 : for (size_t i = 0; i < phnum; ++i)
429 : {
430 : GElf_Phdr phdr_mem;
431 336 : GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem);
432 336 : if (unlikely (phdr == NULL))
433 64 : return false;
434 336 : if (phdr->p_type == PT_DYNAMIC)
435 : {
436 64 : *vaddrp = phdr->p_vaddr;
437 64 : return true;
438 : }
439 : }
440 : return false;
441 : }
442 :
443 : int
444 36 : dwfl_core_file_report (Dwfl *dwfl, Elf *elf, const char *executable)
445 : {
446 : size_t phnum;
447 36 : if (unlikely (elf_getphdrnum (elf, &phnum) != 0))
448 : {
449 0 : __libdwfl_seterrno (DWFL_E_LIBELF);
450 0 : return -1;
451 : }
452 :
453 36 : if (dwfl->user_core != NULL)
454 0 : free (dwfl->user_core->executable_for_core);
455 36 : if (executable == NULL)
456 : {
457 4 : if (dwfl->user_core != NULL)
458 0 : dwfl->user_core->executable_for_core = NULL;
459 : }
460 : else
461 : {
462 32 : if (dwfl->user_core == NULL)
463 : {
464 32 : dwfl->user_core = calloc (1, sizeof (struct Dwfl_User_Core));
465 32 : if (dwfl->user_core == NULL)
466 : {
467 0 : __libdwfl_seterrno (DWFL_E_NOMEM);
468 0 : return -1;
469 : }
470 32 : dwfl->user_core->fd = -1;
471 : }
472 32 : dwfl->user_core->executable_for_core = strdup (executable);
473 32 : if (dwfl->user_core->executable_for_core == NULL)
474 : {
475 0 : __libdwfl_seterrno (DWFL_E_NOMEM);
476 0 : return -1;
477 : }
478 : }
479 :
480 : /* First report each PT_LOAD segment. */
481 : GElf_Phdr notes_phdr;
482 36 : int ndx = dwfl_report_core_segments (dwfl, elf, phnum, ¬es_phdr);
483 36 : if (unlikely (ndx <= 0))
484 : return ndx;
485 :
486 : /* Next, we should follow the chain from DT_DEBUG. */
487 :
488 36 : const void *auxv = NULL;
489 36 : const void *note_file = NULL;
490 36 : size_t auxv_size = 0;
491 36 : size_t note_file_size = 0;
492 36 : if (likely (notes_phdr.p_type == PT_NOTE))
493 : {
494 : /* PT_NOTE -> NT_AUXV -> AT_PHDR -> PT_DYNAMIC -> DT_DEBUG */
495 :
496 72 : Elf_Data *notes = elf_getdata_rawchunk (elf,
497 36 : notes_phdr.p_offset,
498 : notes_phdr.p_filesz,
499 36 : (notes_phdr.p_align == 8
500 : ? ELF_T_NHDR8
501 : : ELF_T_NHDR));
502 36 : if (likely (notes != NULL))
503 : {
504 : size_t pos = 0;
505 : GElf_Nhdr nhdr;
506 : size_t name_pos;
507 : size_t desc_pos;
508 289 : while ((pos = gelf_getnote (notes, pos, &nhdr,
509 : &name_pos, &desc_pos)) > 0)
510 253 : if (nhdr.n_namesz == sizeof "CORE"
511 204 : && !memcmp (notes->d_buf + name_pos, "CORE", sizeof "CORE"))
512 : {
513 204 : if (nhdr.n_type == NT_AUXV)
514 : {
515 36 : auxv = notes->d_buf + desc_pos;
516 36 : auxv_size = nhdr.n_descsz;
517 : }
518 204 : if (nhdr.n_type == NT_FILE)
519 : {
520 24 : note_file = notes->d_buf + desc_pos;
521 24 : note_file_size = nhdr.n_descsz;
522 : }
523 : }
524 : }
525 : }
526 :
527 : /* Now we have NT_AUXV contents. From here on this processing could be
528 : used for a live process with auxv read from /proc. */
529 :
530 : struct r_debug_info r_debug_info;
531 36 : memset (&r_debug_info, 0, sizeof r_debug_info);
532 36 : int retval = dwfl_link_map_report (dwfl, auxv, auxv_size,
533 : dwfl_elf_phdr_memory_callback, elf,
534 : &r_debug_info);
535 36 : int listed = retval > 0 ? retval : 0;
536 :
537 : /* Now sniff segment contents for modules hinted by information gathered
538 : from DT_DEBUG. */
539 :
540 36 : ndx = 0;
541 : do
542 : {
543 459 : int seg = dwfl_segment_report_module (dwfl, ndx, NULL,
544 : &dwfl_elf_phdr_memory_callback, elf,
545 : core_file_read_eagerly, elf,
546 : note_file, note_file_size,
547 : &r_debug_info);
548 459 : if (unlikely (seg < 0))
549 : {
550 0 : clear_r_debug_info (&r_debug_info);
551 0 : return seg;
552 : }
553 459 : if (seg > ndx)
554 : {
555 118 : ndx = seg;
556 118 : ++listed;
557 : }
558 : else
559 341 : ++ndx;
560 : }
561 459 : while (ndx < (int) phnum);
562 :
563 : /* Now report the modules from dwfl_link_map_report which were not filtered
564 : out by dwfl_segment_report_module. */
565 :
566 36 : Dwfl_Module **lastmodp = &dwfl->modulelist;
567 190 : while (*lastmodp != NULL)
568 118 : lastmodp = &(*lastmodp)->next;
569 190 : for (struct r_debug_info_module *module = r_debug_info.module;
570 118 : module != NULL; module = module->next)
571 : {
572 118 : if (module->elf == NULL)
573 184 : continue;
574 : GElf_Addr file_dynamic_vaddr;
575 26 : if (! __libdwfl_dynamic_vaddr_get (module->elf, &file_dynamic_vaddr))
576 0 : continue;
577 : Dwfl_Module *mod;
578 26 : mod = __libdwfl_report_elf (dwfl, basename (module->name), module->name,
579 : module->fd, module->elf,
580 26 : module->l_ld - file_dynamic_vaddr,
581 : true, true);
582 26 : if (mod == NULL)
583 0 : continue;
584 26 : ++listed;
585 26 : module->elf = NULL;
586 26 : module->fd = -1;
587 : /* Move this module to the end of the list, so that we end
588 : up with a list in the same order as the link_map chain. */
589 26 : if (mod->next != NULL)
590 : {
591 0 : if (*lastmodp != mod)
592 : {
593 : lastmodp = &dwfl->modulelist;
594 0 : while (*lastmodp != mod)
595 0 : lastmodp = &(*lastmodp)->next;
596 : }
597 0 : *lastmodp = mod->next;
598 0 : mod->next = NULL;
599 0 : while (*lastmodp != NULL)
600 0 : lastmodp = &(*lastmodp)->next;
601 0 : *lastmodp = mod;
602 : }
603 26 : lastmodp = &mod->next;
604 : }
605 :
606 36 : clear_r_debug_info (&r_debug_info);
607 :
608 : /* We return the number of modules we found if we found any.
609 : If we found none, we return -1 instead of 0 if there was an
610 : error rather than just nothing found. */
611 36 : return listed > 0 ? listed : retval;
612 : }
613 : INTDEF (dwfl_core_file_report)
614 : NEW_VERSION (dwfl_core_file_report, ELFUTILS_0.158)
615 :
616 : #ifdef SYMBOL_VERSIONING
617 : int _compat_without_executable_dwfl_core_file_report (Dwfl *dwfl, Elf *elf);
618 : COMPAT_VERSION_NEWPROTO (dwfl_core_file_report, ELFUTILS_0.146,
619 : without_executable)
620 :
621 : int
622 : _compat_without_executable_dwfl_core_file_report (Dwfl *dwfl, Elf *elf)
623 : {
624 : return dwfl_core_file_report (dwfl, elf, NULL);
625 : }
626 : #endif
|