Blame libdwfl/core-file.c

Packit 032894
/* Core file handling.
Packit 032894
   Copyright (C) 2008-2010, 2013, 2015 Red Hat, Inc.
Packit 032894
   This file is part of elfutils.
Packit 032894
Packit 032894
   This file is free software; you can redistribute it and/or modify
Packit 032894
   it under the terms of either
Packit 032894
Packit 032894
     * the GNU Lesser General Public License as published by the Free
Packit 032894
       Software Foundation; either version 3 of the License, or (at
Packit 032894
       your option) any later version
Packit 032894
Packit 032894
   or
Packit 032894
Packit 032894
     * the GNU General Public License as published by the Free
Packit 032894
       Software Foundation; either version 2 of the License, or (at
Packit 032894
       your option) any later version
Packit 032894
Packit 032894
   or both in parallel, as here.
Packit 032894
Packit 032894
   elfutils is distributed in the hope that it will be useful, but
Packit 032894
   WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 032894
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 032894
   General Public License for more details.
Packit 032894
Packit 032894
   You should have received copies of the GNU General Public License and
Packit 032894
   the GNU Lesser General Public License along with this program.  If
Packit 032894
   not, see <http://www.gnu.org/licenses/>.  */
Packit 032894
Packit 032894
#include <config.h>
Packit 032894
#include "../libelf/libelfP.h"	/* For NOTE_ALIGN.  */
Packit 032894
#undef	_
Packit 032894
#include "libdwflP.h"
Packit 032894
#include <gelf.h>
Packit 032894
Packit 032894
#include <unistd.h>
Packit 032894
#include <endian.h>
Packit 032894
#include <byteswap.h>
Packit 032894
#include "system.h"
Packit 032894
Packit 032894
Packit 032894
/* On failure return, we update *NEXT to point back at OFFSET.  */
Packit 032894
static inline Elf *
Packit 032894
do_fail (int error, off_t *next, off_t offset)
Packit 032894
{
Packit 032894
    if (next != NULL)
Packit 032894
      *next = offset;
Packit 032894
    //__libelf_seterrno (error);
Packit 032894
    __libdwfl_seterrno (DWFL_E (LIBELF, error));
Packit 032894
    return NULL;
Packit 032894
}
Packit 032894
Packit 032894
#define fail(error) do_fail (error, next, offset)
Packit 032894
Packit 032894
/* This is a prototype of what a new libelf interface might be.
Packit 032894
   This implementation is pessimal for non-mmap cases and should
Packit 032894
   be replaced by more diddling inside libelf internals.  */
Packit 032894
static Elf *
Packit 032894
elf_begin_rand (Elf *parent, off_t offset, off_t size, off_t *next)
Packit 032894
{
Packit 032894
  if (parent == NULL)
Packit 032894
    return NULL;
Packit 032894
Packit 032894
  off_t min = (parent->kind == ELF_K_ELF ?
Packit 032894
		(parent->class == ELFCLASS32
Packit 032894
		 ? sizeof (Elf32_Ehdr) : sizeof (Elf64_Ehdr))
Packit 032894
		: parent->kind == ELF_K_AR ? SARMAG
Packit 032894
		: 0);
Packit 032894
Packit 032894
  if (unlikely (offset < min)
Packit 032894
      || unlikely (offset >= (off_t) parent->maximum_size))
Packit 032894
    return fail (ELF_E_RANGE);
Packit 032894
Packit 032894
  /* For an archive, fetch just the size field
Packit 032894
     from the archive header to override SIZE.  */
Packit 032894
  if (parent->kind == ELF_K_AR)
Packit 032894
    {
Packit 032894
      struct ar_hdr h = { .ar_size = "" };
Packit 032894
Packit 032894
      if (unlikely (parent->maximum_size - offset < sizeof h))
Packit 032894
	return fail (ELF_E_RANGE);
Packit 032894
Packit 032894
      if (parent->map_address != NULL)
Packit 032894
	memcpy (h.ar_size, parent->map_address + parent->start_offset + offset,
Packit 032894
		sizeof h.ar_size);
Packit 032894
      else if (unlikely (pread_retry (parent->fildes,
Packit 032894
				      h.ar_size, sizeof (h.ar_size),
Packit 032894
				      parent->start_offset + offset
Packit 032894
				      + offsetof (struct ar_hdr, ar_size))
Packit 032894
			 != sizeof (h.ar_size)))
Packit 032894
	return fail (ELF_E_READ_ERROR);
Packit 032894
Packit 032894
      offset += sizeof h;
Packit 032894
Packit 032894
      char *endp;
Packit 032894
      size = strtoll (h.ar_size, &endp, 10);
Packit 032894
      if (unlikely (endp == h.ar_size)
Packit 032894
	  || unlikely ((off_t) parent->maximum_size - offset < size))
Packit 032894
	return fail (ELF_E_INVALID_ARCHIVE);
Packit 032894
    }
Packit 032894
Packit 032894
  if (unlikely ((off_t) parent->maximum_size - offset < size))
Packit 032894
    return fail (ELF_E_RANGE);
Packit 032894
Packit 032894
  /* Even if we fail at this point, update *NEXT to point past the file.  */
Packit 032894
  if (next != NULL)
Packit 032894
    *next = offset + size;
Packit 032894
Packit 032894
  if (unlikely (offset == 0)
Packit 032894
      && unlikely (size == (off_t) parent->maximum_size))
Packit 032894
    return elf_clone (parent, parent->cmd);
Packit 032894
Packit 032894
  /* Note the image is guaranteed live only as long as PARENT
Packit 032894
     lives.  Using elf_memory is quite suboptimal if the whole
Packit 032894
     file is not mmap'd.  We really should have something like
Packit 032894
     a generalization of the archive support.  */
Packit 032894
  Elf_Data *data = elf_getdata_rawchunk (parent, offset, size, ELF_T_BYTE);
Packit 032894
  if (data == NULL)
Packit 032894
    return NULL;
Packit 032894
  assert ((off_t) data->d_size == size);
Packit 032894
  return elf_memory (data->d_buf, size);
Packit 032894
}
Packit 032894
Packit 032894
Packit 032894
int
Packit 032894
dwfl_report_core_segments (Dwfl *dwfl, Elf *elf, size_t phnum, GElf_Phdr *notes)
Packit 032894
{
Packit 032894
  if (unlikely (dwfl == NULL))
Packit 032894
    return -1;
Packit 032894
Packit 032894
  int result = 0;
Packit 032894
Packit 032894
  if (notes != NULL)
Packit 032894
    notes->p_type = PT_NULL;
Packit 032894
Packit 032894
  for (size_t ndx = 0; result >= 0 && ndx < phnum; ++ndx)
Packit 032894
    {
Packit 032894
      GElf_Phdr phdr_mem;
Packit 032894
      GElf_Phdr *phdr = gelf_getphdr (elf, ndx, &phdr_mem);
Packit 032894
      if (unlikely (phdr == NULL))
Packit 032894
	{
Packit 032894
	  __libdwfl_seterrno (DWFL_E_LIBELF);
Packit 032894
	  return -1;
Packit 032894
	}
Packit 032894
      switch (phdr->p_type)
Packit 032894
	{
Packit 032894
	case PT_LOAD:
Packit 032894
	  result = dwfl_report_segment (dwfl, ndx, phdr, 0, NULL);
Packit 032894
	  break;
Packit 032894
Packit 032894
	case PT_NOTE:
Packit 032894
	  if (notes != NULL)
Packit 032894
	    {
Packit 032894
	      *notes = *phdr;
Packit 032894
	      notes = NULL;
Packit 032894
	    }
Packit 032894
	  break;
Packit 032894
	}
Packit 032894
    }
Packit 032894
Packit 032894
  return result;
Packit 032894
}
Packit 032894
Packit 032894
/* Never read more than this much without mmap.  */
Packit 032894
#define MAX_EAGER_COST	8192
Packit 032894
Packit 032894
/* Dwfl_Module_Callback passed to and called by dwfl_segment_report_module
Packit 032894
   to read in a segment as ELF image directly if possible or indicate an
Packit 032894
   attempt must be made to read in the while segment right now.  */
Packit 032894
static bool
Packit 032894
core_file_read_eagerly (Dwfl_Module *mod,
Packit 032894
			void **userdata __attribute__ ((unused)),
Packit 032894
			const char *name __attribute__ ((unused)),
Packit 032894
			Dwarf_Addr start __attribute__ ((unused)),
Packit 032894
			void **buffer, size_t *buffer_available,
Packit 032894
			GElf_Off cost, GElf_Off worthwhile,
Packit 032894
			GElf_Off whole,
Packit 032894
			GElf_Off contiguous __attribute__ ((unused)),
Packit 032894
			void *arg, Elf **elfp)
Packit 032894
{
Packit 032894
  Elf *core = arg;
Packit 032894
Packit 032894
  /* The available buffer is often the whole segment when the core file
Packit 032894
     was mmap'd if used together with the dwfl_elf_phdr_memory_callback.
Packit 032894
     Which means that if it is complete we can just construct the whole
Packit 032894
     ELF image right now without having to read in anything more.  */
Packit 032894
  if (whole <= *buffer_available)
Packit 032894
    {
Packit 032894
      /* All there ever was, we already have on hand.  */
Packit 032894
Packit 032894
      if (core->map_address == NULL)
Packit 032894
	{
Packit 032894
	  /* We already malloc'd the buffer.  */
Packit 032894
	  *elfp = elf_memory (*buffer, whole);
Packit 032894
	  if (unlikely (*elfp == NULL))
Packit 032894
	    return false;
Packit 032894
Packit 032894
	  (*elfp)->flags |= ELF_F_MALLOCED;
Packit 032894
	  *buffer = NULL;
Packit 032894
	  *buffer_available = 0;
Packit 032894
	  return true;
Packit 032894
	}
Packit 032894
Packit 032894
      /* We can use the image inside the core file directly.  */
Packit 032894
      *elfp = elf_begin_rand (core, *buffer - core->map_address, whole, NULL);
Packit 032894
      *buffer = NULL;
Packit 032894
      *buffer_available = 0;
Packit 032894
      return *elfp != NULL;
Packit 032894
    }
Packit 032894
Packit 032894
  /* We don't have the whole file.  Which either means the core file
Packit 032894
     wasn't mmap'd, but needs to still be read in, or that the segment
Packit 032894
     is truncated.  Figure out if this is better than nothing.  */
Packit 032894
Packit 032894
  if (worthwhile == 0)
Packit 032894
    /* Caller doesn't think so.  */
Packit 032894
    return false;
Packit 032894
Packit 032894
  /*
Packit 032894
    XXX would like to fall back to partial file via memory
Packit 032894
    when build id find_elf fails
Packit 032894
    also, link_map name may give file name from disk better than partial here
Packit 032894
    requires find_elf hook re-doing the magic to fall back if no file found
Packit 032894
  */
Packit 032894
Packit 032894
  if (whole > MAX_EAGER_COST && mod->build_id_len > 0)
Packit 032894
    /* We can't cheaply read the whole file here, so we'd
Packit 032894
       be using a partial file.  But there is a build ID that could
Packit 032894
       help us find the whole file, which might be more useful than
Packit 032894
       what we have.  We'll just rely on that.  */
Packit 032894
    return false;
Packit 032894
Packit 032894
  /* The file is either small (most likely the vdso) or big and incomplete,
Packit 032894
     but we don't have a build-id.  */
Packit 032894
Packit 032894
  if (core->map_address != NULL)
Packit 032894
    /* It's cheap to get, so get it.  */
Packit 032894
    return true;
Packit 032894
Packit 032894
  /* Only use it if there isn't too much to be read.  */
Packit 032894
  return cost <= MAX_EAGER_COST;
Packit 032894
}
Packit 032894
Packit 032894
static inline void
Packit 032894
update_end (GElf_Phdr *pphdr, const GElf_Off align,
Packit 032894
            GElf_Off *pend, GElf_Addr *pend_vaddr)
Packit 032894
{
Packit 032894
  *pend = (pphdr->p_offset + pphdr->p_filesz + align - 1) & -align;
Packit 032894
  *pend_vaddr = (pphdr->p_vaddr + pphdr->p_memsz + align - 1) & -align;
Packit 032894
}
Packit 032894
Packit 032894
/* Use following contiguous segments to get towards SIZE.  */
Packit 032894
static inline bool
Packit 032894
do_more (size_t size, GElf_Phdr *pphdr, const GElf_Off align,
Packit 032894
         Elf *elf, GElf_Off start, int *pndx,
Packit 032894
         GElf_Off *pend, GElf_Addr *pend_vaddr)
Packit 032894
{
Packit 032894
  while (*pend <= start || *pend - start < size)
Packit 032894
    {
Packit 032894
      if (pphdr->p_filesz < pphdr->p_memsz)
Packit 032894
	/* This segment is truncated, so no following one helps us.  */
Packit 032894
	return false;
Packit 032894
Packit 032894
      if (unlikely (gelf_getphdr (elf, (*pndx)++, pphdr) == NULL))
Packit 032894
	return false;
Packit 032894
Packit 032894
      if (pphdr->p_type == PT_LOAD)
Packit 032894
	{
Packit 032894
	  if (pphdr->p_offset > *pend
Packit 032894
	      || pphdr->p_vaddr > *pend_vaddr)
Packit 032894
	    /* It's discontiguous!  */
Packit 032894
	    return false;
Packit 032894
Packit 032894
	  update_end (pphdr, align, pend, pend_vaddr);
Packit 032894
	}
Packit 032894
    }
Packit 032894
  return true;
Packit 032894
}
Packit 032894
Packit 032894
#define more(size) do_more (size, &phdr, align, elf, start, &ndx, &end, &end_vaddr)
Packit 032894
Packit 032894
bool
Packit 032894
dwfl_elf_phdr_memory_callback (Dwfl *dwfl, int ndx,
Packit 032894
			       void **buffer, size_t *buffer_available,
Packit 032894
			       GElf_Addr vaddr,
Packit 032894
			       size_t minread,
Packit 032894
			       void *arg)
Packit 032894
{
Packit 032894
  Elf *elf = arg;
Packit 032894
Packit 032894
  if (ndx == -1)
Packit 032894
    {
Packit 032894
      /* Called for cleanup.  */
Packit 032894
      if (elf->map_address == NULL)
Packit 032894
	free (*buffer);
Packit 032894
      *buffer = NULL;
Packit 032894
      *buffer_available = 0;
Packit 032894
      return false;
Packit 032894
    }
Packit 032894
Packit 032894
  const GElf_Off align = dwfl->segment_align ?: 1;
Packit 032894
  GElf_Phdr phdr;
Packit 032894
Packit 032894
  do
Packit 032894
    if (unlikely (gelf_getphdr (elf, ndx++, &phdr) == NULL))
Packit 032894
      return false;
Packit 032894
  while (phdr.p_type != PT_LOAD
Packit 032894
	 || ((phdr.p_vaddr + phdr.p_memsz + align - 1) & -align) <= vaddr);
Packit 032894
Packit 032894
  GElf_Off start = vaddr - phdr.p_vaddr + phdr.p_offset;
Packit 032894
  GElf_Off end;
Packit 032894
  GElf_Addr end_vaddr;
Packit 032894
Packit 032894
  update_end (&phdr, align, &end, &end_vaddr);
Packit 032894
Packit 032894
  /* We need at least this much.  */
Packit 032894
  if (! more (minread))
Packit 032894
    return false;
Packit 032894
Packit 032894
  /* See how much more we can get of what the caller wants.  */
Packit 032894
  (void) more (*buffer_available);
Packit 032894
Packit 032894
  /* If it's already on hand anyway, use as much as there is.  */
Packit 032894
  if (elf->map_address != NULL)
Packit 032894
    (void) more (elf->maximum_size - start);
Packit 032894
Packit 032894
  /* Make sure we don't look past the end of the actual file,
Packit 032894
     even if the headers tell us to.  */
Packit 032894
  if (unlikely (end > elf->maximum_size))
Packit 032894
    end = elf->maximum_size;
Packit 032894
Packit 032894
  /* If the file is too small, there is nothing at all to get.  */
Packit 032894
  if (unlikely (start >= end))
Packit 032894
    return false;
Packit 032894
Packit 032894
  if (elf->map_address != NULL)
Packit 032894
    {
Packit 032894
      void *contents = elf->map_address + elf->start_offset + start;
Packit 032894
      size_t size = end - start;
Packit 032894
Packit 032894
      if (minread == 0)		/* String mode.  */
Packit 032894
	{
Packit 032894
	  const void *eos = memchr (contents, '\0', size);
Packit 032894
	  if (unlikely (eos == NULL) || unlikely (eos == contents))
Packit 032894
	    return false;
Packit 032894
	  size = eos + 1 - contents;
Packit 032894
	}
Packit 032894
Packit 032894
      if (*buffer == NULL)
Packit 032894
	{
Packit 032894
	  *buffer = contents;
Packit 032894
	  *buffer_available = size;
Packit 032894
	}
Packit 032894
      else
Packit 032894
	{
Packit 032894
	  *buffer_available = MIN (size, *buffer_available);
Packit 032894
	  memcpy (*buffer, contents, *buffer_available);
Packit 032894
	}
Packit 032894
    }
Packit 032894
  else
Packit 032894
    {
Packit 032894
      void *into = *buffer;
Packit 032894
      if (*buffer == NULL)
Packit 032894
	{
Packit 032894
	  *buffer_available = MIN (minread ?: 512,
Packit 032894
				   MAX (4096, MIN (end - start,
Packit 032894
						   *buffer_available)));
Packit 032894
	  into = malloc (*buffer_available);
Packit 032894
	  if (unlikely (into == NULL))
Packit 032894
	    {
Packit 032894
	      __libdwfl_seterrno (DWFL_E_NOMEM);
Packit 032894
	      return false;
Packit 032894
	    }
Packit 032894
	}
Packit 032894
Packit 032894
      ssize_t nread = pread_retry (elf->fildes, into, *buffer_available, start);
Packit 032894
      if (nread < (ssize_t) minread)
Packit 032894
	{
Packit 032894
	  if (into != *buffer)
Packit 032894
	    free (into);
Packit 032894
	  if (nread < 0)
Packit 032894
	    __libdwfl_seterrno (DWFL_E_ERRNO);
Packit 032894
	  return false;
Packit 032894
	}
Packit 032894
Packit 032894
      if (minread == 0)		/* String mode.  */
Packit 032894
	{
Packit 032894
	  const void *eos = memchr (into, '\0', nread);
Packit 032894
	  if (unlikely (eos == NULL) || unlikely (eos == into))
Packit 032894
	    {
Packit 032894
	      if (*buffer == NULL)
Packit 032894
		free (into);
Packit 032894
	      return false;
Packit 032894
	    }
Packit 032894
	  nread = eos + 1 - into;
Packit 032894
	}
Packit 032894
Packit 032894
      if (*buffer == NULL)
Packit 032894
	*buffer = into;
Packit 032894
      *buffer_available = nread;
Packit 032894
    }
Packit 032894
Packit 032894
  return true;
Packit 032894
}
Packit 032894
Packit 032894
/* Free the contents of R_DEBUG_INFO without the R_DEBUG_INFO memory itself.  */
Packit 032894
Packit 032894
static void
Packit 032894
clear_r_debug_info (struct r_debug_info *r_debug_info)
Packit 032894
{
Packit 032894
  while (r_debug_info->module != NULL)
Packit 032894
    {
Packit 032894
      struct r_debug_info_module *module = r_debug_info->module;
Packit 032894
      r_debug_info->module = module->next;
Packit 032894
      elf_end (module->elf);
Packit 032894
      if (module->fd != -1)
Packit 032894
	close (module->fd);
Packit 032894
      free (module);
Packit 032894
    }
Packit 032894
}
Packit 032894
Packit 032894
bool
Packit 032894
internal_function
Packit 032894
__libdwfl_dynamic_vaddr_get (Elf *elf, GElf_Addr *vaddrp)
Packit 032894
{
Packit 032894
  size_t phnum;
Packit 032894
  if (unlikely (elf_getphdrnum (elf, &phnum) != 0))
Packit 032894
    return false;
Packit 032894
  for (size_t i = 0; i < phnum; ++i)
Packit 032894
    {
Packit 032894
      GElf_Phdr phdr_mem;
Packit 032894
      GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem);
Packit 032894
      if (unlikely (phdr == NULL))
Packit 032894
	return false;
Packit 032894
      if (phdr->p_type == PT_DYNAMIC)
Packit 032894
	{
Packit 032894
	  *vaddrp = phdr->p_vaddr;
Packit 032894
	  return true;
Packit 032894
	}
Packit 032894
    }
Packit 032894
  return false;
Packit 032894
}
Packit 032894
Packit 032894
int
Packit 032894
dwfl_core_file_report (Dwfl *dwfl, Elf *elf, const char *executable)
Packit 032894
{
Packit 032894
  size_t phnum;
Packit 032894
  if (unlikely (elf_getphdrnum (elf, &phnum) != 0))
Packit 032894
    {
Packit 032894
      __libdwfl_seterrno (DWFL_E_LIBELF);
Packit 032894
      return -1;
Packit 032894
    }
Packit 032894
Packit 032894
  if (dwfl->user_core != NULL)
Packit 032894
    free (dwfl->user_core->executable_for_core);
Packit 032894
  if (executable == NULL)
Packit 032894
    {
Packit 032894
      if (dwfl->user_core != NULL)
Packit 032894
	dwfl->user_core->executable_for_core = NULL;
Packit 032894
    }
Packit 032894
  else
Packit 032894
    {
Packit 032894
      if (dwfl->user_core == NULL)
Packit 032894
	{
Packit 032894
	  dwfl->user_core = calloc (1, sizeof (struct Dwfl_User_Core));
Packit 032894
	  if (dwfl->user_core == NULL)
Packit 032894
	    {
Packit 032894
	      __libdwfl_seterrno (DWFL_E_NOMEM);
Packit 032894
	      return -1;
Packit 032894
	    }
Packit 032894
	  dwfl->user_core->fd = -1;
Packit 032894
	}
Packit 032894
      dwfl->user_core->executable_for_core = strdup (executable);
Packit 032894
      if (dwfl->user_core->executable_for_core == NULL)
Packit 032894
	{
Packit 032894
	  __libdwfl_seterrno (DWFL_E_NOMEM);
Packit 032894
	  return -1;
Packit 032894
	}
Packit 032894
    }
Packit 032894
Packit 032894
  /* First report each PT_LOAD segment.  */
Packit 032894
  GElf_Phdr notes_phdr;
Packit 032894
  int ndx = dwfl_report_core_segments (dwfl, elf, phnum, &notes_phdr);
Packit 032894
  if (unlikely (ndx <= 0))
Packit 032894
    return ndx;
Packit 032894
Packit 032894
  /* Next, we should follow the chain from DT_DEBUG.  */
Packit 032894
Packit 032894
  const void *auxv = NULL;
Packit 032894
  const void *note_file = NULL;
Packit 032894
  size_t auxv_size = 0;
Packit 032894
  size_t note_file_size = 0;
Packit 032894
  if (likely (notes_phdr.p_type == PT_NOTE))
Packit 032894
    {
Packit 032894
      /* PT_NOTE -> NT_AUXV -> AT_PHDR -> PT_DYNAMIC -> DT_DEBUG */
Packit 032894
Packit 032894
      Elf_Data *notes = elf_getdata_rawchunk (elf,
Packit 032894
					      notes_phdr.p_offset,
Packit 032894
					      notes_phdr.p_filesz,
Packit 032894
					      (notes_phdr.p_align == 8
Packit 032894
					       ? ELF_T_NHDR8
Packit 032894
					       : ELF_T_NHDR));
Packit 032894
      if (likely (notes != NULL))
Packit 032894
	{
Packit 032894
	  size_t pos = 0;
Packit 032894
	  GElf_Nhdr nhdr;
Packit 032894
	  size_t name_pos;
Packit 032894
	  size_t desc_pos;
Packit 032894
	  while ((pos = gelf_getnote (notes, pos, &nhdr,
Packit 032894
				      &name_pos, &desc_pos)) > 0)
Packit 032894
	    if (nhdr.n_namesz == sizeof "CORE"
Packit 032894
		&& !memcmp (notes->d_buf + name_pos, "CORE", sizeof "CORE"))
Packit 032894
	      {
Packit 032894
		if (nhdr.n_type == NT_AUXV)
Packit 032894
		  {
Packit 032894
		    auxv = notes->d_buf + desc_pos;
Packit 032894
		    auxv_size = nhdr.n_descsz;
Packit 032894
		  }
Packit 032894
		if (nhdr.n_type == NT_FILE)
Packit 032894
		  {
Packit 032894
		    note_file = notes->d_buf + desc_pos;
Packit 032894
		    note_file_size = nhdr.n_descsz;
Packit 032894
		  }
Packit 032894
	      }
Packit 032894
	}
Packit 032894
    }
Packit 032894
Packit 032894
  /* Now we have NT_AUXV contents.  From here on this processing could be
Packit 032894
     used for a live process with auxv read from /proc.  */
Packit 032894
Packit 032894
  struct r_debug_info r_debug_info;
Packit 032894
  memset (&r_debug_info, 0, sizeof r_debug_info);
Packit 032894
  int retval = dwfl_link_map_report (dwfl, auxv, auxv_size,
Packit 032894
				     dwfl_elf_phdr_memory_callback, elf,
Packit 032894
				     &r_debug_info);
Packit 032894
  int listed = retval > 0 ? retval : 0;
Packit 032894
Packit 032894
  /* Now sniff segment contents for modules hinted by information gathered
Packit 032894
     from DT_DEBUG.  */
Packit 032894
Packit 032894
  ndx = 0;
Packit 032894
  do
Packit 032894
    {
Packit 032894
      int seg = dwfl_segment_report_module (dwfl, ndx, NULL,
Packit 032894
					    &dwfl_elf_phdr_memory_callback, elf,
Packit 032894
					    core_file_read_eagerly, elf,
Packit 032894
					    note_file, note_file_size,
Packit 032894
					    &r_debug_info);
Packit 032894
      if (unlikely (seg < 0))
Packit 032894
	{
Packit 032894
	  clear_r_debug_info (&r_debug_info);
Packit 032894
	  return seg;
Packit 032894
	}
Packit 032894
      if (seg > ndx)
Packit 032894
	{
Packit 032894
	  ndx = seg;
Packit 032894
	  ++listed;
Packit 032894
	}
Packit 032894
      else
Packit 032894
	++ndx;
Packit 032894
    }
Packit 032894
  while (ndx < (int) phnum);
Packit 032894
Packit 032894
  /* Now report the modules from dwfl_link_map_report which were not filtered
Packit 032894
     out by dwfl_segment_report_module.  */
Packit 032894
Packit 032894
  Dwfl_Module **lastmodp = &dwfl->modulelist;
Packit 032894
  while (*lastmodp != NULL)
Packit 032894
    lastmodp = &(*lastmodp)->next;
Packit 032894
  for (struct r_debug_info_module *module = r_debug_info.module;
Packit 032894
       module != NULL; module = module->next)
Packit 032894
    {
Packit 032894
      if (module->elf == NULL)
Packit 032894
	continue;
Packit 032894
      GElf_Addr file_dynamic_vaddr;
Packit 032894
      if (! __libdwfl_dynamic_vaddr_get (module->elf, &file_dynamic_vaddr))
Packit 032894
	continue;
Packit 032894
      Dwfl_Module *mod;
Packit 032894
      mod = __libdwfl_report_elf (dwfl, basename (module->name), module->name,
Packit 032894
				  module->fd, module->elf,
Packit 032894
				  module->l_ld - file_dynamic_vaddr,
Packit 032894
				  true, true);
Packit 032894
      if (mod == NULL)
Packit 032894
	continue;
Packit 032894
      ++listed;
Packit 032894
      module->elf = NULL;
Packit 032894
      module->fd = -1;
Packit 032894
      /* Move this module to the end of the list, so that we end
Packit 032894
	 up with a list in the same order as the link_map chain.  */
Packit 032894
      if (mod->next != NULL)
Packit 032894
	{
Packit 032894
	  if (*lastmodp != mod)
Packit 032894
	    {
Packit 032894
	      lastmodp = &dwfl->modulelist;
Packit 032894
	      while (*lastmodp != mod)
Packit 032894
		lastmodp = &(*lastmodp)->next;
Packit 032894
	    }
Packit 032894
	  *lastmodp = mod->next;
Packit 032894
	  mod->next = NULL;
Packit 032894
	  while (*lastmodp != NULL)
Packit 032894
	    lastmodp = &(*lastmodp)->next;
Packit 032894
	  *lastmodp = mod;
Packit 032894
	}
Packit 032894
      lastmodp = &mod->next;
Packit 032894
    }
Packit 032894
Packit 032894
  clear_r_debug_info (&r_debug_info);
Packit 032894
Packit 032894
  /* We return the number of modules we found if we found any.
Packit 032894
     If we found none, we return -1 instead of 0 if there was an
Packit 032894
     error rather than just nothing found.  */
Packit 032894
  return listed > 0 ? listed : retval;
Packit 032894
}
Packit 032894
INTDEF (dwfl_core_file_report)
Packit 032894
NEW_VERSION (dwfl_core_file_report, ELFUTILS_0.158)
Packit 032894
Packit 032894
#ifdef SYMBOL_VERSIONING
Packit 032894
int _compat_without_executable_dwfl_core_file_report (Dwfl *dwfl, Elf *elf);
Packit 032894
COMPAT_VERSION_NEWPROTO (dwfl_core_file_report, ELFUTILS_0.146,
Packit 032894
			 without_executable)
Packit 032894
Packit 032894
int
Packit 032894
_compat_without_executable_dwfl_core_file_report (Dwfl *dwfl, Elf *elf)
Packit 032894
{
Packit 032894
  return dwfl_core_file_report (dwfl, elf, NULL);
Packit 032894
}
Packit 032894
#endif