Home | History | Annotate | Download | only in libdwfl
      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     if (next != NULL)
     46       *next = offset;
     47     //__libelf_seterrno (error);
     48     __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 elf_begin_rand (Elf *parent, off_t offset, off_t size, off_t *next)
     59 {
     60   if (parent == NULL)
     61     return NULL;
     62 
     63   off_t min = (parent->kind == ELF_K_ELF ?
     64 		(parent->class == ELFCLASS32
     65 		 ? sizeof (Elf32_Ehdr) : sizeof (Elf64_Ehdr))
     66 		: parent->kind == ELF_K_AR ? SARMAG
     67 		: 0);
     68 
     69   if (unlikely (offset < min)
     70       || unlikely (offset >= (off_t) parent->maximum_size))
     71     return fail (ELF_E_RANGE);
     72 
     73   /* For an archive, fetch just the size field
     74      from the archive header to override SIZE.  */
     75   if (parent->kind == ELF_K_AR)
     76     {
     77       struct ar_hdr h = { .ar_size = "" };
     78 
     79       if (unlikely (parent->maximum_size - offset < sizeof h))
     80 	return fail (ELF_E_RANGE);
     81 
     82       if (parent->map_address != NULL)
     83 	memcpy (h.ar_size, parent->map_address + parent->start_offset + offset,
     84 		sizeof h.ar_size);
     85       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 	return fail (ELF_E_READ_ERROR);
     91 
     92       offset += sizeof h;
     93 
     94       char *endp;
     95       size = strtoll (h.ar_size, &endp, 10);
     96       if (unlikely (endp == h.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
    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
    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
    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
    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
    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)
    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 (elf->map_address != NULL)
    336     {
    337       void *contents = elf->map_address + elf->start_offset + start;
    338       size_t size = end - start;
    339 
    340       if (minread == 0)		/* String mode.  */
    341 	{
    342 	  const void *eos = memchr (contents, '\0', size);
    343 	  if (unlikely (eos == NULL) || unlikely (eos == contents))
    344 	    return false;
    345 	  size = eos + 1 - contents;
    346 	}
    347 
    348       if (*buffer == NULL)
    349 	{
    350 	  *buffer = contents;
    351 	  *buffer_available = size;
    352 	}
    353       else
    354 	{
    355 	  *buffer_available = MIN (size, *buffer_available);
    356 	  memcpy (*buffer, contents, *buffer_available);
    357 	}
    358     }
    359   else
    360     {
    361       void *into = *buffer;
    362       if (*buffer == NULL)
    363 	{
    364 	  *buffer_available = MIN (minread ?: 512,
    365 				   MAX (4096, MIN (end - start,
    366 						   *buffer_available)));
    367 	  into = malloc (*buffer_available);
    368 	  if (unlikely (into == NULL))
    369 	    {
    370 	      __libdwfl_seterrno (DWFL_E_NOMEM);
    371 	      return false;
    372 	    }
    373 	}
    374 
    375       ssize_t nread = pread_retry (elf->fildes, into, *buffer_available, start);
    376       if (nread < (ssize_t) minread)
    377 	{
    378 	  if (into != *buffer)
    379 	    free (into);
    380 	  if (nread < 0)
    381 	    __libdwfl_seterrno (DWFL_E_ERRNO);
    382 	  return false;
    383 	}
    384 
    385       if (minread == 0)		/* String mode.  */
    386 	{
    387 	  const void *eos = memchr (into, '\0', nread);
    388 	  if (unlikely (eos == NULL) || unlikely (eos == into))
    389 	    {
    390 	      if (*buffer == NULL)
    391 		free (into);
    392 	      return false;
    393 	    }
    394 	  nread = eos + 1 - into;
    395 	}
    396 
    397       if (*buffer == NULL)
    398 	*buffer = into;
    399       *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 clear_r_debug_info (struct r_debug_info *r_debug_info)
    409 {
    410   while (r_debug_info->module != NULL)
    411     {
    412       struct r_debug_info_module *module = r_debug_info->module;
    413       r_debug_info->module = module->next;
    414       elf_end (module->elf);
    415       if (module->fd != -1)
    416 	close (module->fd);
    417       free (module);
    418     }
    419 }
    420 
    421 bool
    422 internal_function
    423 __libdwfl_dynamic_vaddr_get (Elf *elf, GElf_Addr *vaddrp)
    424 {
    425   size_t phnum;
    426   if (unlikely (elf_getphdrnum (elf, &phnum) != 0))
    427     return false;
    428   for (size_t i = 0; i < phnum; ++i)
    429     {
    430       GElf_Phdr phdr_mem;
    431       GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem);
    432       if (unlikely (phdr == NULL))
    433 	return false;
    434       if (phdr->p_type == PT_DYNAMIC)
    435 	{
    436 	  *vaddrp = phdr->p_vaddr;
    437 	  return true;
    438 	}
    439     }
    440   return false;
    441 }
    442 
    443 int
    444 dwfl_core_file_report (Dwfl *dwfl, Elf *elf, const char *executable)
    445 {
    446   size_t phnum;
    447   if (unlikely (elf_getphdrnum (elf, &phnum) != 0))
    448     {
    449       __libdwfl_seterrno (DWFL_E_LIBELF);
    450       return -1;
    451     }
    452 
    453   if (dwfl->user_core != NULL)
    454     free (dwfl->user_core->executable_for_core);
    455   if (executable == NULL)
    456     {
    457       if (dwfl->user_core != NULL)
    458 	dwfl->user_core->executable_for_core = NULL;
    459     }
    460   else
    461     {
    462       if (dwfl->user_core == NULL)
    463 	{
    464 	  dwfl->user_core = calloc (1, sizeof (struct Dwfl_User_Core));
    465 	  if (dwfl->user_core == NULL)
    466 	    {
    467 	      __libdwfl_seterrno (DWFL_E_NOMEM);
    468 	      return -1;
    469 	    }
    470 	  dwfl->user_core->fd = -1;
    471 	}
    472       dwfl->user_core->executable_for_core = strdup (executable);
    473       if (dwfl->user_core->executable_for_core == NULL)
    474 	{
    475 	  __libdwfl_seterrno (DWFL_E_NOMEM);
    476 	  return -1;
    477 	}
    478     }
    479 
    480   /* First report each PT_LOAD segment.  */
    481   GElf_Phdr notes_phdr;
    482   int ndx = dwfl_report_core_segments (dwfl, elf, phnum, &notes_phdr);
    483   if (unlikely (ndx <= 0))
    484     return ndx;
    485 
    486   /* Next, we should follow the chain from DT_DEBUG.  */
    487 
    488   const void *auxv = NULL;
    489   const void *note_file = NULL;
    490   size_t auxv_size = 0;
    491   size_t note_file_size = 0;
    492   if (likely (notes_phdr.p_type == PT_NOTE))
    493     {
    494       /* PT_NOTE -> NT_AUXV -> AT_PHDR -> PT_DYNAMIC -> DT_DEBUG */
    495 
    496       Elf_Data *notes = elf_getdata_rawchunk (elf,
    497 					      notes_phdr.p_offset,
    498 					      notes_phdr.p_filesz,
    499 					      (notes_phdr.p_align == 8
    500 					       ? ELF_T_NHDR8
    501 					       : ELF_T_NHDR));
    502       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 	  while ((pos = gelf_getnote (notes, pos, &nhdr,
    509 				      &name_pos, &desc_pos)) > 0)
    510 	    if (nhdr.n_namesz == sizeof "CORE"
    511 		&& !memcmp (notes->d_buf + name_pos, "CORE", sizeof "CORE"))
    512 	      {
    513 		if (nhdr.n_type == NT_AUXV)
    514 		  {
    515 		    auxv = notes->d_buf + desc_pos;
    516 		    auxv_size = nhdr.n_descsz;
    517 		  }
    518 		if (nhdr.n_type == NT_FILE)
    519 		  {
    520 		    note_file = notes->d_buf + desc_pos;
    521 		    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   memset (&r_debug_info, 0, sizeof r_debug_info);
    532   int retval = dwfl_link_map_report (dwfl, auxv, auxv_size,
    533 				     dwfl_elf_phdr_memory_callback, elf,
    534 				     &r_debug_info);
    535   int listed = retval > 0 ? retval : 0;
    536 
    537   /* Now sniff segment contents for modules hinted by information gathered
    538      from DT_DEBUG.  */
    539 
    540   ndx = 0;
    541   do
    542     {
    543       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       if (unlikely (seg < 0))
    549 	{
    550 	  clear_r_debug_info (&r_debug_info);
    551 	  return seg;
    552 	}
    553       if (seg > ndx)
    554 	{
    555 	  ndx = seg;
    556 	  ++listed;
    557 	}
    558       else
    559 	++ndx;
    560     }
    561   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   Dwfl_Module **lastmodp = &dwfl->modulelist;
    567   while (*lastmodp != NULL)
    568     lastmodp = &(*lastmodp)->next;
    569   for (struct r_debug_info_module *module = r_debug_info.module;
    570        module != NULL; module = module->next)
    571     {
    572       if (module->elf == NULL)
    573 	continue;
    574       GElf_Addr file_dynamic_vaddr;
    575       if (! __libdwfl_dynamic_vaddr_get (module->elf, &file_dynamic_vaddr))
    576 	continue;
    577       Dwfl_Module *mod;
    578       mod = __libdwfl_report_elf (dwfl, basename (module->name), module->name,
    579 				  module->fd, module->elf,
    580 				  module->l_ld - file_dynamic_vaddr,
    581 				  true, true);
    582       if (mod == NULL)
    583 	continue;
    584       ++listed;
    585       module->elf = NULL;
    586       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       if (mod->next != NULL)
    590 	{
    591 	  if (*lastmodp != mod)
    592 	    {
    593 	      lastmodp = &dwfl->modulelist;
    594 	      while (*lastmodp != mod)
    595 		lastmodp = &(*lastmodp)->next;
    596 	    }
    597 	  *lastmodp = mod->next;
    598 	  mod->next = NULL;
    599 	  while (*lastmodp != NULL)
    600 	    lastmodp = &(*lastmodp)->next;
    601 	  *lastmodp = mod;
    602 	}
    603       lastmodp = &mod->next;
    604     }
    605 
    606   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   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
    627