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