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.  */
45static Elf *
46elf_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
122int
123dwfl_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
164static bool
165core_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
229bool
230dwfl_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
386static void
387clear_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
400bool
401internal_function
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
422int
423dwfl_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}
576INTDEF (dwfl_core_file_report)
577NEW_VERSION (dwfl_core_file_report, ELFUTILS_0.158)
578
579#ifdef SHARED
580int _compat_without_executable_dwfl_core_file_report (Dwfl *dwfl, Elf *elf);
581COMPAT_VERSION_NEWPROTO (dwfl_core_file_report, ELFUTILS_0.146,
582			 without_executable)
583
584int
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