125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Core file handling.
203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   Copyright (C) 2008-2010, 2013 Red Hat, Inc.
303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   This file is part of elfutils.
425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   This file is free software; you can redistribute it and/or modify
603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   it under the terms of either
725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes     * the GNU Lesser General Public License as published by the Free
903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes       Software Foundation; either version 3 of the License, or (at
1003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes       your option) any later version
1103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
1203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   or
1303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
1403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes     * the GNU General Public License as published by the Free
1503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes       Software Foundation; either version 2 of the License, or (at
1603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes       your option) any later version
1703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
1803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   or both in parallel, as here.
1903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
2003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   elfutils is distributed in the hope that it will be useful, but
2125b3c049e70834cf33790a28643ab058b507b35cBen Cheng   WITHOUT ANY WARRANTY; without even the implied warranty of
2225b3c049e70834cf33790a28643ab058b507b35cBen Cheng   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
2325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   General Public License for more details.
2425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
2503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   You should have received copies of the GNU General Public License and
2603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   the GNU Lesser General Public License along with this program.  If
2703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   not, see <http://www.gnu.org/licenses/>.  */
2825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
2925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <config.h>
3025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "../libelf/libelfP.h"	/* For NOTE_ALIGN.  */
3125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#undef	_
3225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "libdwflP.h"
3325b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <gelf.h>
3425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
3525b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <sys/param.h>
3625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <unistd.h>
3725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <endian.h>
3825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <byteswap.h>
3925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "system.h"
4025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
4125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
4225b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* This is a prototype of what a new libelf interface might be.
4325b3c049e70834cf33790a28643ab058b507b35cBen Cheng   This implementation is pessimal for non-mmap cases and should
4425b3c049e70834cf33790a28643ab058b507b35cBen Cheng   be replaced by more diddling inside libelf internals.  */
4525b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic Elf *
4625b3c049e70834cf33790a28643ab058b507b35cBen Chengelf_begin_rand (Elf *parent, loff_t offset, loff_t size, loff_t *next)
4725b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
4825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (parent == NULL)
4925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return NULL;
5025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
5125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* On failure return, we update *NEXT to point back at OFFSET.  */
5225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  inline Elf *fail (int error)
5325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  {
5425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    if (next != NULL)
5525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *next = offset;
5625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    //__libelf_seterrno (error);
5725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    __libdwfl_seterrno (DWFL_E (LIBELF, error));
5825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return NULL;
5925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  }
6025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
6125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  loff_t min = (parent->kind == ELF_K_ELF ?
6225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		(parent->class == ELFCLASS32
6325b3c049e70834cf33790a28643ab058b507b35cBen Cheng		 ? sizeof (Elf32_Ehdr) : sizeof (Elf64_Ehdr))
6425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		: parent->kind == ELF_K_AR ? SARMAG
6525b3c049e70834cf33790a28643ab058b507b35cBen Cheng		: 0);
6625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
6725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (offset < min)
6825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      || unlikely (offset >= (loff_t) parent->maximum_size))
6925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return fail (ELF_E_RANGE);
7025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
7125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* For an archive, fetch just the size field
7225b3c049e70834cf33790a28643ab058b507b35cBen Cheng     from the archive header to override SIZE.  */
7325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (parent->kind == ELF_K_AR)
7425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
7525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      struct ar_hdr h = { .ar_size = "" };
7625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
7725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (parent->maximum_size - offset < sizeof h))
7825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return fail (ELF_E_RANGE);
7925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
8025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (parent->map_address != NULL)
8125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	memcpy (h.ar_size, parent->map_address + parent->start_offset + offset,
8225b3c049e70834cf33790a28643ab058b507b35cBen Cheng		sizeof h.ar_size);
8325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else if (unlikely (pread_retry (parent->fildes,
8425b3c049e70834cf33790a28643ab058b507b35cBen Cheng				      h.ar_size, sizeof (h.ar_size),
8525b3c049e70834cf33790a28643ab058b507b35cBen Cheng				      parent->start_offset + offset
8625b3c049e70834cf33790a28643ab058b507b35cBen Cheng				      + offsetof (struct ar_hdr, ar_size))
8725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			 != sizeof (h.ar_size)))
8825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return fail (ELF_E_READ_ERROR);
8925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
9025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      offset += sizeof h;
9125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
9225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      char *endp;
9325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size = strtoll (h.ar_size, &endp, 10);
9425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (endp == h.ar_size)
9525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  || unlikely ((loff_t) parent->maximum_size - offset < size))
9625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	return fail (ELF_E_INVALID_ARCHIVE);
9725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
9825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
9925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely ((loff_t) parent->maximum_size - offset < size))
10025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return fail (ELF_E_RANGE);
10125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
10225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Even if we fail at this point, update *NEXT to point past the file.  */
10325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (next != NULL)
10425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    *next = offset + size;
10525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
10625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (offset == 0)
10725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      && unlikely (size == (loff_t) parent->maximum_size))
10825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return elf_clone (parent, parent->cmd);
10925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
11025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Note the image is guaranteed live only as long as PARENT
11125b3c049e70834cf33790a28643ab058b507b35cBen Cheng     lives.  Using elf_memory is quite suboptimal if the whole
11225b3c049e70834cf33790a28643ab058b507b35cBen Cheng     file is not mmap'd.  We really should have something like
11325b3c049e70834cf33790a28643ab058b507b35cBen Cheng     a generalization of the archive support.  */
11425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf_Data *data = elf_getdata_rawchunk (parent, offset, size, ELF_T_BYTE);
11525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (data == NULL)
11625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return NULL;
11725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  assert ((loff_t) data->d_size == size);
11825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return elf_memory (data->d_buf, size);
11925b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
12025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
12125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
12225b3c049e70834cf33790a28643ab058b507b35cBen Chengint
12325b3c049e70834cf33790a28643ab058b507b35cBen Chengdwfl_report_core_segments (Dwfl *dwfl, Elf *elf, size_t phnum, GElf_Phdr *notes)
12425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
12525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (dwfl == NULL))
12625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return -1;
12725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
12825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int result = 0;
12925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
13025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (notes != NULL)
13125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    notes->p_type = PT_NULL;
13225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
13325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  for (size_t ndx = 0; result >= 0 && ndx < phnum; ++ndx)
13425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
13525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Phdr phdr_mem;
13625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      GElf_Phdr *phdr = gelf_getphdr (elf, ndx, &phdr_mem);
13725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (unlikely (phdr == NULL))
13825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
13925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  __libdwfl_seterrno (DWFL_E_LIBELF);
14025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  return -1;
14125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
14225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      switch (phdr->p_type)
14325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
14425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case PT_LOAD:
14525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  result = dwfl_report_segment (dwfl, ndx, phdr, 0, NULL);
14625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
14725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
14825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	case PT_NOTE:
14925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (notes != NULL)
15025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
15125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      *notes = *phdr;
15225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      notes = NULL;
15325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
15425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  break;
15525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
15625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
15725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
15825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return result;
15925b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
16025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
16125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Never read more than this much without mmap.  */
16225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#define MAX_EAGER_COST	8192
16325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
16425b3c049e70834cf33790a28643ab058b507b35cBen Chengstatic bool
16525b3c049e70834cf33790a28643ab058b507b35cBen Chengcore_file_read_eagerly (Dwfl_Module *mod,
16625b3c049e70834cf33790a28643ab058b507b35cBen Cheng			void **userdata __attribute__ ((unused)),
16725b3c049e70834cf33790a28643ab058b507b35cBen Cheng			const char *name __attribute__ ((unused)),
16825b3c049e70834cf33790a28643ab058b507b35cBen Cheng			Dwarf_Addr start __attribute__ ((unused)),
16925b3c049e70834cf33790a28643ab058b507b35cBen Cheng			void **buffer, size_t *buffer_available,
17025b3c049e70834cf33790a28643ab058b507b35cBen Cheng			GElf_Off cost, GElf_Off worthwhile,
17125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			GElf_Off whole,
17225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			GElf_Off contiguous __attribute__ ((unused)),
17325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			void *arg, Elf **elfp)
17425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
17525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf *core = arg;
17625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
17725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (whole <= *buffer_available)
17825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
17925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* All there ever was, we already have on hand.  */
18025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
18125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (core->map_address == NULL)
18225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
18325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* We already malloc'd the buffer.  */
18425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  *elfp = elf_memory (*buffer, whole);
18525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (*elfp == NULL))
18625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    return false;
18725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
18825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  (*elfp)->flags |= ELF_F_MALLOCED;
18925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  *buffer = NULL;
19025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  *buffer_available = 0;
19125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  return true;
19225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
19325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
19425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* We can use the image inside the core file directly.  */
19525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *elfp = elf_begin_rand (core, *buffer - core->map_address, whole, NULL);
19625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *buffer = NULL;
19725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *buffer_available = 0;
19825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return *elfp != NULL;
19925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
20025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
20125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* We don't have the whole file.
20225b3c049e70834cf33790a28643ab058b507b35cBen Cheng     Figure out if this is better than nothing.  */
20325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
20425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (worthwhile == 0)
20525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    /* Caller doesn't think so.  */
20625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return false;
20725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
20825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /*
20925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    XXX would like to fall back to partial file via memory
21025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    when build id find_elf fails
21125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    also, link_map name may give file name from disk better than partial here
21225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    requires find_elf hook re-doing the magic to fall back if no file found
21325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  */
21425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
21525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (mod->build_id_len > 0)
21625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    /* There is a build ID that could help us find the whole file,
21725b3c049e70834cf33790a28643ab058b507b35cBen Cheng       which might be more useful than what we have.
21825b3c049e70834cf33790a28643ab058b507b35cBen Cheng       We'll just rely on that.  */
21925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return false;
22025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
22125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (core->map_address != NULL)
22225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    /* It's cheap to get, so get it.  */
22325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return true;
22425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
22525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Only use it if there isn't too much to be read.  */
22625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return cost <= MAX_EAGER_COST;
22725b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
22825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
22925b3c049e70834cf33790a28643ab058b507b35cBen Chengbool
23025b3c049e70834cf33790a28643ab058b507b35cBen Chengdwfl_elf_phdr_memory_callback (Dwfl *dwfl, int ndx,
23125b3c049e70834cf33790a28643ab058b507b35cBen Cheng			       void **buffer, size_t *buffer_available,
23225b3c049e70834cf33790a28643ab058b507b35cBen Cheng			       GElf_Addr vaddr,
23325b3c049e70834cf33790a28643ab058b507b35cBen Cheng			       size_t minread,
23425b3c049e70834cf33790a28643ab058b507b35cBen Cheng			       void *arg)
23525b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
23625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  Elf *elf = arg;
23725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
23825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (ndx == -1)
23925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
24025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* Called for cleanup.  */
24125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (elf->map_address == NULL)
24225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	free (*buffer);
24325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *buffer = NULL;
24425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *buffer_available = 0;
24525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return false;
24625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
24725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
24825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const GElf_Off align = dwfl->segment_align ?: 1;
24925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Phdr phdr;
25025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
25125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  do
25225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    if (unlikely (gelf_getphdr (elf, ndx++, &phdr) == NULL))
25325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return false;
25425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  while (phdr.p_type != PT_LOAD
25525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	 || ((phdr.p_vaddr + phdr.p_memsz + align - 1) & -align) <= vaddr);
25625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
25725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Off start = vaddr - phdr.p_vaddr + phdr.p_offset;
25825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Off end;
25925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Addr end_vaddr;
26025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
26125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  inline void update_end ()
26225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  {
26325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    end = (phdr.p_offset + phdr.p_filesz + align - 1) & -align;
26425b3c049e70834cf33790a28643ab058b507b35cBen Cheng    end_vaddr = (phdr.p_vaddr + phdr.p_memsz + align - 1) & -align;
26525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  }
26625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
26725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  update_end ();
26825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
26925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Use following contiguous segments to get towards SIZE.  */
27025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  inline bool more (size_t size)
27125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  {
27225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    while (end <= start || end - start < size)
27325b3c049e70834cf33790a28643ab058b507b35cBen Cheng      {
27425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	if (phdr.p_filesz < phdr.p_memsz)
27525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  /* This segment is truncated, so no following one helps us.  */
27625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  return false;
27725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
27825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	if (unlikely (gelf_getphdr (elf, ndx++, &phdr) == NULL))
27925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  return false;
28025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
28125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	if (phdr.p_type == PT_LOAD)
28225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  {
28325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    if (phdr.p_offset > end
28425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		|| phdr.p_vaddr > end_vaddr)
28525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      /* It's discontiguous!  */
28625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      return false;
28725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
28825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    update_end ();
28925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  }
29025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      }
29125b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return true;
29225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  }
29325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
29425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* We need at least this much.  */
29525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (! more (minread))
29625b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return false;
29725b3c049e70834cf33790a28643ab058b507b35cBen Cheng
29825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* See how much more we can get of what the caller wants.  */
29925b3c049e70834cf33790a28643ab058b507b35cBen Cheng  (void) more (*buffer_available);
30025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
30125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* If it's already on hand anyway, use as much as there is.  */
30225b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (elf->map_address != NULL)
30325b3c049e70834cf33790a28643ab058b507b35cBen Cheng    (void) more (elf->maximum_size - start);
30425b3c049e70834cf33790a28643ab058b507b35cBen Cheng
30525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Make sure we don't look past the end of the actual file,
30625b3c049e70834cf33790a28643ab058b507b35cBen Cheng     even if the headers tell us to.  */
30725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (end > elf->maximum_size))
30825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    end = elf->maximum_size;
30925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
31025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* If the file is too small, there is nothing at all to get.  */
31125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (start >= end))
31225b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return false;
31325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
31425b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (elf->map_address != NULL)
31525b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
31625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      void *contents = elf->map_address + elf->start_offset + start;
31725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      size_t size = end - start;
31825b3c049e70834cf33790a28643ab058b507b35cBen Cheng
31925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (minread == 0)		/* String mode.  */
32025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
32125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  const void *eos = memchr (contents, '\0', size);
32225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (eos == NULL) || unlikely (eos == contents))
32325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    return false;
32425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  size = eos + 1 - contents;
32525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
32625b3c049e70834cf33790a28643ab058b507b35cBen Cheng
32725b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (*buffer == NULL)
32825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
32925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  *buffer = contents;
33025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  *buffer_available = size;
33125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
33225b3c049e70834cf33790a28643ab058b507b35cBen Cheng      else
33325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
33425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  *buffer_available = MIN (size, *buffer_available);
33525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  memcpy (*buffer, contents, *buffer_available);
33625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
33725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
33825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  else
33925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
34025b3c049e70834cf33790a28643ab058b507b35cBen Cheng      void *into = *buffer;
34125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (*buffer == NULL)
34225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
34325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  *buffer_available = MIN (minread ?: 512,
34425b3c049e70834cf33790a28643ab058b507b35cBen Cheng				   MAX (4096, MIN (end - start,
34525b3c049e70834cf33790a28643ab058b507b35cBen Cheng						   *buffer_available)));
34625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  into = malloc (*buffer_available);
34725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (into == NULL))
34825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
34925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      __libdwfl_seterrno (DWFL_E_NOMEM);
35025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      return false;
35125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
35225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
35325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
35425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      ssize_t nread = pread_retry (elf->fildes, into, *buffer_available, start);
35525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (nread < (ssize_t) minread)
35625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
35725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (into != *buffer)
35825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    free (into);
35925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (nread < 0)
36025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    __libdwfl_seterrno (DWFL_E_ERRNO);
36125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  return false;
36225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
36325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
36425b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (minread == 0)		/* String mode.  */
36525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
36625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  const void *eos = memchr (into, '\0', nread);
36725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  if (unlikely (eos == NULL) || unlikely (eos == into))
36825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    {
36925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      if (*buffer == NULL)
37025b3c049e70834cf33790a28643ab058b507b35cBen Cheng		free (into);
37125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      return false;
37225b3c049e70834cf33790a28643ab058b507b35cBen Cheng	    }
37325b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  nread = eos + 1 - into;
37425b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
37525b3c049e70834cf33790a28643ab058b507b35cBen Cheng
37625b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (*buffer == NULL)
37725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	*buffer = into;
37825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      *buffer_available = nread;
37925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
38025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
38125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  return true;
38225b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
38325b3c049e70834cf33790a28643ab058b507b35cBen Cheng
38403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes/* Free the contents of R_DEBUG_INFO without the R_DEBUG_INFO memory itself.  */
38503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
38603333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic void
38703333823c75a1c1887e923828113a1b0fd12020cElliott Hughesclear_r_debug_info (struct r_debug_info *r_debug_info)
38803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
38903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  while (r_debug_info->module != NULL)
39003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
39103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      struct r_debug_info_module *module = r_debug_info->module;
39203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      r_debug_info->module = module->next;
39303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      elf_end (module->elf);
39403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (module->fd != -1)
39503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	close (module->fd);
39603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      free (module);
39703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
39803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
39903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
40003333823c75a1c1887e923828113a1b0fd12020cElliott Hughesbool
40103333823c75a1c1887e923828113a1b0fd12020cElliott Hughesinternal_function
40203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes__libdwfl_dynamic_vaddr_get (Elf *elf, GElf_Addr *vaddrp)
40303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
40403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  size_t phnum;
40503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (unlikely (elf_getphdrnum (elf, &phnum) != 0))
40603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    return false;
40703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  for (size_t i = 0; i < phnum; ++i)
40803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
40903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      GElf_Phdr phdr_mem;
41003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem);
41103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (unlikely (phdr == NULL))
41203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	return false;
41303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (phdr->p_type == PT_DYNAMIC)
41403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	{
41503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  *vaddrp = phdr->p_vaddr;
41603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  return true;
41703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	}
41803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
41903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return false;
42003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
42103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
42225b3c049e70834cf33790a28643ab058b507b35cBen Chengint
42303333823c75a1c1887e923828113a1b0fd12020cElliott Hughesdwfl_core_file_report (Dwfl *dwfl, Elf *elf, const char *executable)
42425b3c049e70834cf33790a28643ab058b507b35cBen Cheng{
42525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t phnum;
42625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (elf_getphdrnum (elf, &phnum) != 0))
42725b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
42825b3c049e70834cf33790a28643ab058b507b35cBen Cheng      __libdwfl_seterrno (DWFL_E_LIBELF);
42925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      return -1;
43025b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
43125b3c049e70834cf33790a28643ab058b507b35cBen Cheng
43203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  free (dwfl->executable_for_core);
43303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (executable == NULL)
43403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    dwfl->executable_for_core = NULL;
43503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  else
43603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
43703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      dwfl->executable_for_core = strdup (executable);
43803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (dwfl->executable_for_core == NULL)
43903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	{
44003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  __libdwfl_seterrno (DWFL_E_NOMEM);
44103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  return -1;
44203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	}
44303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
44403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
44525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* First report each PT_LOAD segment.  */
44625b3c049e70834cf33790a28643ab058b507b35cBen Cheng  GElf_Phdr notes_phdr;
44725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  int ndx = dwfl_report_core_segments (dwfl, elf, phnum, &notes_phdr);
44825b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (unlikely (ndx <= 0))
44925b3c049e70834cf33790a28643ab058b507b35cBen Cheng    return ndx;
45025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
45125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Next, we should follow the chain from DT_DEBUG.  */
45225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
45325b3c049e70834cf33790a28643ab058b507b35cBen Cheng  const void *auxv = NULL;
45403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  const void *note_file = NULL;
45525b3c049e70834cf33790a28643ab058b507b35cBen Cheng  size_t auxv_size = 0;
45603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  size_t note_file_size = 0;
45725b3c049e70834cf33790a28643ab058b507b35cBen Cheng  if (likely (notes_phdr.p_type == PT_NOTE))
45825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    {
45925b3c049e70834cf33790a28643ab058b507b35cBen Cheng      /* PT_NOTE -> NT_AUXV -> AT_PHDR -> PT_DYNAMIC -> DT_DEBUG */
46025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
46125b3c049e70834cf33790a28643ab058b507b35cBen Cheng      Elf_Data *notes = elf_getdata_rawchunk (elf,
46225b3c049e70834cf33790a28643ab058b507b35cBen Cheng					      notes_phdr.p_offset,
46325b3c049e70834cf33790a28643ab058b507b35cBen Cheng					      notes_phdr.p_filesz,
46425b3c049e70834cf33790a28643ab058b507b35cBen Cheng					      ELF_T_NHDR);
46525b3c049e70834cf33790a28643ab058b507b35cBen Cheng      if (likely (notes != NULL))
46625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	{
46725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  size_t pos = 0;
46825b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  GElf_Nhdr nhdr;
46925b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  size_t name_pos;
47025b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  size_t desc_pos;
47125b3c049e70834cf33790a28643ab058b507b35cBen Cheng	  while ((pos = gelf_getnote (notes, pos, &nhdr,
47225b3c049e70834cf33790a28643ab058b507b35cBen Cheng				      &name_pos, &desc_pos)) > 0)
47303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    if (nhdr.n_namesz == sizeof "CORE"
47425b3c049e70834cf33790a28643ab058b507b35cBen Cheng		&& !memcmp (notes->d_buf + name_pos, "CORE", sizeof "CORE"))
47525b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      {
47603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		if (nhdr.n_type == NT_AUXV)
47703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  {
47803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    auxv = notes->d_buf + desc_pos;
47903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    auxv_size = nhdr.n_descsz;
48003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  }
48103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		if (nhdr.n_type == NT_FILE)
48203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  {
48303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    note_file = notes->d_buf + desc_pos;
48403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		    note_file_size = nhdr.n_descsz;
48503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  }
48625b3c049e70834cf33790a28643ab058b507b35cBen Cheng	      }
48725b3c049e70834cf33790a28643ab058b507b35cBen Cheng	}
48825b3c049e70834cf33790a28643ab058b507b35cBen Cheng    }
48925b3c049e70834cf33790a28643ab058b507b35cBen Cheng
49025b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* Now we have NT_AUXV contents.  From here on this processing could be
49125b3c049e70834cf33790a28643ab058b507b35cBen Cheng     used for a live process with auxv read from /proc.  */
49225b3c049e70834cf33790a28643ab058b507b35cBen Cheng
49303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  struct r_debug_info r_debug_info;
49403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  memset (&r_debug_info, 0, sizeof r_debug_info);
49503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  int retval = dwfl_link_map_report (dwfl, auxv, auxv_size,
49603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes				     dwfl_elf_phdr_memory_callback, elf,
49703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes				     &r_debug_info);
49803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  int listed = retval > 0 ? retval : 0;
49903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
50003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  /* Now sniff segment contents for modules hinted by information gathered
50103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes     from DT_DEBUG.  */
50203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
50303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  ndx = 0;
50403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  do
50503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
50603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      int seg = dwfl_segment_report_module (dwfl, ndx, NULL,
50703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes					    &dwfl_elf_phdr_memory_callback, elf,
50803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes					    core_file_read_eagerly, elf,
50903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes					    note_file, note_file_size,
51003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes					    &r_debug_info);
51103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (unlikely (seg < 0))
51203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	{
51303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  clear_r_debug_info (&r_debug_info);
51403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  return seg;
51503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	}
51603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (seg > ndx)
51703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	{
51803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  ndx = seg;
51903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  ++listed;
52003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	}
52103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      else
52203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	++ndx;
52303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
52403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  while (ndx < (int) phnum);
52503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
52603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  /* Now report the modules from dwfl_link_map_report which were not filtered
52703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes     out by dwfl_segment_report_module.  */
52803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
52903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  Dwfl_Module **lastmodp = &dwfl->modulelist;
53003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  while (*lastmodp != NULL)
53103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    lastmodp = &(*lastmodp)->next;
53203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  for (struct r_debug_info_module *module = r_debug_info.module;
53303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes       module != NULL; module = module->next)
53403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
53503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (module->elf == NULL)
53603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	continue;
53703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      GElf_Addr file_dynamic_vaddr;
53803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (! __libdwfl_dynamic_vaddr_get (module->elf, &file_dynamic_vaddr))
53903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	continue;
54003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      Dwfl_Module *mod;
54103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      mod = __libdwfl_report_elf (dwfl, basename (module->name), module->name,
54203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes				  module->fd, module->elf,
54303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes				  module->l_ld - file_dynamic_vaddr,
54403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes				  true, true);
54503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (mod == NULL)
54603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	continue;
54703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      ++listed;
54803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      module->elf = NULL;
54903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      module->fd = -1;
55003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      /* Move this module to the end of the list, so that we end
55103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	 up with a list in the same order as the link_map chain.  */
55203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (mod->next != NULL)
55303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	{
55403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (*lastmodp != mod)
55503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    {
55603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      lastmodp = &dwfl->modulelist;
55703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      while (*lastmodp != mod)
55803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		lastmodp = &(*lastmodp)->next;
55903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    }
56003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  *lastmodp = mod->next;
56103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  mod->next = NULL;
56203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  while (*lastmodp != NULL)
56303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    lastmodp = &(*lastmodp)->next;
56403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  *lastmodp = mod;
56503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	}
56603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      lastmodp = &mod->next;
56703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
56803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
56903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  clear_r_debug_info (&r_debug_info);
57025b3c049e70834cf33790a28643ab058b507b35cBen Cheng
57125b3c049e70834cf33790a28643ab058b507b35cBen Cheng  /* We return the number of modules we found if we found any.
57225b3c049e70834cf33790a28643ab058b507b35cBen Cheng     If we found none, we return -1 instead of 0 if there was an
57303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes     error rather than just nothing found.  */
57403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return listed > 0 ? listed : retval;
57525b3c049e70834cf33790a28643ab058b507b35cBen Cheng}
57625b3c049e70834cf33790a28643ab058b507b35cBen ChengINTDEF (dwfl_core_file_report)
57703333823c75a1c1887e923828113a1b0fd12020cElliott HughesNEW_VERSION (dwfl_core_file_report, ELFUTILS_0.158)
57803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
57903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#ifdef SHARED
58003333823c75a1c1887e923828113a1b0fd12020cElliott Hughesint _compat_without_executable_dwfl_core_file_report (Dwfl *dwfl, Elf *elf);
58103333823c75a1c1887e923828113a1b0fd12020cElliott HughesCOMPAT_VERSION_NEWPROTO (dwfl_core_file_report, ELFUTILS_0.146,
58203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			 without_executable)
58303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
58403333823c75a1c1887e923828113a1b0fd12020cElliott Hughesint
58503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes_compat_without_executable_dwfl_core_file_report (Dwfl *dwfl, Elf *elf)
58603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
58703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return dwfl_core_file_report (dwfl, elf, NULL);
58803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
58903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#endif
590