1d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath/* Recover relocatibility for addresses computed from debug information.
2e1873141a517738d8c50923e40525bb2ae6db68aPetr Machata   Copyright (C) 2005-2009, 2012 Red Hat, Inc.
3de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   This file is part of elfutils.
4d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath
5de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   This file is free software; you can redistribute it and/or modify
6de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   it under the terms of either
7d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath
8de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard     * the GNU Lesser General Public License as published by the Free
9de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       Software Foundation; either version 3 of the License, or (at
10de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       your option) any later version
11de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
12de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   or
13de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
14de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard     * the GNU General Public License as published by the Free
15de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       Software Foundation; either version 2 of the License, or (at
16de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard       your option) any later version
17de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
18de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   or both in parallel, as here.
19de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard
20de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   elfutils is distributed in the hope that it will be useful, but
21361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   WITHOUT ANY WARRANTY; without even the implied warranty of
22361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   General Public License for more details.
24361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper
25de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   You should have received copies of the GNU General Public License and
26de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   the GNU Lesser General Public License along with this program.  If
27de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard   not, see <http://www.gnu.org/licenses/>.  */
28d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath
29d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath#include "libdwflP.h"
30b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper#include <fcntl.h>
31d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath#include <unistd.h>
32d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath
33d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath/* Since dwfl_report_elf lays out the sections already, this will only be
34d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath   called when the section headers of the debuginfo file are being
35e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath   consulted instead, or for the section placed at 0.  With binutils
36e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath   strip-to-debug, the symbol table is in the debuginfo file and relocation
37e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath   looks there.  */
38d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrathint
39d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrathdwfl_offline_section_address (Dwfl_Module *mod,
40d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath			      void **userdata __attribute__ ((unused)),
41d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath			      const char *modname __attribute__ ((unused)),
42d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath			      Dwarf_Addr base __attribute__ ((unused)),
43d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath			      const char *secname __attribute__ ((unused)),
44d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath			      Elf32_Word shndx,
45d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath			      const GElf_Shdr *shdr __attribute__ ((unused)),
46d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath			      Dwarf_Addr *addr)
47d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath{
489aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath  assert (mod->e_type == ET_REL);
49d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath  assert (shdr->sh_addr == 0);
50d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath  assert (shdr->sh_flags & SHF_ALLOC);
5127304cb338070ef53ee3db61e3e50cd57efe243aMark Wielaard  assert (shndx != 0);
52d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath
53e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath  if (mod->debug.elf == NULL)
54e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath    /* We are only here because sh_addr is zero even though layout is complete.
55e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath       The first section in the first file under -e is placed at 0.  */
56e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath    return 0;
57e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath
589aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath  /* The section numbers might not match between the two files.
599aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath     The best we can rely on is the order of SHF_ALLOC sections.  */
609aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath
61b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  Elf_Scn *ourscn = elf_getscn (mod->debug.elf, shndx);
629aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath  Elf_Scn *scn = NULL;
639aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath  uint_fast32_t skip_alloc = 0;
64b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  while ((scn = elf_nextscn (mod->debug.elf, scn)) != ourscn)
659aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath    {
669aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath      assert (scn != NULL);
679aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath      GElf_Shdr shdr_mem;
689aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath      GElf_Shdr *sh = gelf_getshdr (scn, &shdr_mem);
699aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath      if (unlikely (sh == NULL))
709aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath	return -1;
719aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath      if (sh->sh_flags & SHF_ALLOC)
729aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath	++skip_alloc;
739aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath    }
749aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath
759aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath  scn = NULL;
769aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath  while ((scn = elf_nextscn (mod->main.elf, scn)) != NULL)
779aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath    {
789aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath      GElf_Shdr shdr_mem;
79b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      GElf_Shdr *main_shdr = gelf_getshdr (scn, &shdr_mem);
809aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath      if (unlikely (main_shdr == NULL))
819aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath	return -1;
829aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath      if ((main_shdr->sh_flags & SHF_ALLOC) && skip_alloc-- == 0)
839aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath	{
849aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath	  assert (main_shdr->sh_flags == shdr->sh_flags);
859aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath	  *addr = main_shdr->sh_addr;
869aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath	  return 0;
879aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath	}
889aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath    }
89aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper
909aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath  /* This should never happen.  */
919aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath  return -1;
92d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath}
93d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrathINTDEF (dwfl_offline_section_address)
94d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath
95b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper/* Forward declarations.  */
96b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepperstatic Dwfl_Module *process_elf (Dwfl *dwfl, const char *name,
97b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper				 const char *file_name, int fd, Elf *elf);
98b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepperstatic Dwfl_Module *process_archive (Dwfl *dwfl, const char *name,
99b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper				     const char *file_name, int fd, Elf *elf,
100b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper				     int (*predicate) (const char *module,
101b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper						       const char *file));
102b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
103e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath/* Report one module for an ELF file, or many for an archive.
104e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath   Always consumes ELF and FD.  */
105b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepperstatic Dwfl_Module *
106b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepperprocess_file (Dwfl *dwfl, const char *name, const char *file_name, int fd,
107b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	      Elf *elf, int (*predicate) (const char *module,
108b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper					  const char *file))
109d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath{
110b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  switch (elf_kind (elf))
111b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    {
112b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    default:
113b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    case ELF_K_NONE:
114b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      __libdwfl_seterrno (elf == NULL ? DWFL_E_LIBELF : DWFL_E_BADELF);
115b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      return NULL;
116b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
117b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    case ELF_K_ELF:
118b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      return process_elf (dwfl, name, file_name, fd, elf);
119b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
120b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    case ELF_K_AR:
121b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      return process_archive (dwfl, name, file_name, fd, elf, predicate);
122b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    }
123b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper}
124d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath
125e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath/* Report the open ELF file as a module.  Always consumes ELF and FD.  */
126b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepperstatic Dwfl_Module *
127b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepperprocess_elf (Dwfl *dwfl, const char *name, const char *file_name, int fd,
128b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	     Elf *elf)
129b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper{
130b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  Dwfl_Module *mod = __libdwfl_report_elf (dwfl, name, file_name, fd, elf,
131904aec2c2f62b729a536c2259274fdd440b0d923Jan Kratochvil					   dwfl->offline_next_address, true,
132904aec2c2f62b729a536c2259274fdd440b0d923Jan Kratochvil					   false);
133d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath  if (mod != NULL)
134d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath    {
135d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath      /* If this is an ET_EXEC file with fixed addresses, the address range
136d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath	 it consumed may or may not intersect with the arbitrary range we
137d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath	 will use for relocatable modules.  Make sure we always use a free
138687d7e9bd154a4b1f22b5e3ed7c6c904e421e871Roland McGrath	 range for the offline allocations.  If this module did use
139687d7e9bd154a4b1f22b5e3ed7c6c904e421e871Roland McGrath	 offline_next_address, it may have rounded it up for the module's
140687d7e9bd154a4b1f22b5e3ed7c6c904e421e871Roland McGrath	 alignment requirements.  */
141687d7e9bd154a4b1f22b5e3ed7c6c904e421e871Roland McGrath      if ((dwfl->offline_next_address >= mod->low_addr
142687d7e9bd154a4b1f22b5e3ed7c6c904e421e871Roland McGrath	   || mod->low_addr - dwfl->offline_next_address < OFFLINE_REDZONE)
143d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath	  && dwfl->offline_next_address < mod->high_addr + OFFLINE_REDZONE)
144d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath	dwfl->offline_next_address = mod->high_addr + OFFLINE_REDZONE;
145d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath
146d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath      /* Don't keep the file descriptor around.  */
147d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath      if (mod->main.fd != -1 && elf_cntl (mod->main.elf, ELF_C_FDREAD) == 0)
148d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath	{
149d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath	  close (mod->main.fd);
150d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath	  mod->main.fd = -1;
151d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath	}
152d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath    }
153d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath
154d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath  return mod;
155d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath}
156b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
157e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath/* Always consumes MEMBER.  Returns elf_next result on success.
158e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath   For errors returns ELF_C_NULL with *MOD set to null.  */
159e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrathstatic Elf_Cmd
160b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepperprocess_archive_member (Dwfl *dwfl, const char *name, const char *file_name,
161b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper			int (*predicate) (const char *module, const char *file),
162e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath			int fd, Elf *member, Dwfl_Module **mod)
163b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper{
164b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  const Elf_Arhdr *h = elf_getarhdr (member);
165b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  if (unlikely (h == NULL))
166b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    {
167b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      __libdwfl_seterrno (DWFL_E_LIBELF);
168e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath    fail:
169b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      elf_end (member);
170b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      *mod = NULL;
171e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath      return ELF_C_NULL;
172b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    }
173b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
174e1873141a517738d8c50923e40525bb2ae6db68aPetr Machata  if (!strcmp (h->ar_name, "/") || !strcmp (h->ar_name, "//")
175e1873141a517738d8c50923e40525bb2ae6db68aPetr Machata      || !strcmp (h->ar_name, "/SYM64/"))
176b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    {
177e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath    skip:;
178e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath      /* Skip this and go to the next.  */
179e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath      Elf_Cmd result = elf_next (member);
180b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      elf_end (member);
181e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath      return result;
182b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    }
183b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
184b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  char *member_name;
185b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  if (unlikely (asprintf (&member_name, "%s(%s)", file_name, h->ar_name) < 0))
186b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    {
187b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    nomem:
188b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      __libdwfl_seterrno (DWFL_E_NOMEM);
189b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      elf_end (member);
190b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      *mod = NULL;
191e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath      return ELF_C_NULL;
192b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    }
193b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
194b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  char *module_name = NULL;
195b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  if (name == NULL || name[0] == '\0')
196b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    name = h->ar_name;
197b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  else if (unlikely (asprintf (&module_name, "%s:%s", name, h->ar_name) < 0))
198b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    {
199b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      free (member_name);
200b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      goto nomem;
201b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    }
202b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  else
203b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    name = module_name;
204b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
205b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  if (predicate != NULL)
206b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    {
207b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      /* Let the predicate decide whether to use this one.  */
208b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      int want = (*predicate) (name, member_name);
209b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      if (want <= 0)
210b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	{
211b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	  free (member_name);
212b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	  free (module_name);
213b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	  if (unlikely (want < 0))
214b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	    {
215b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	      __libdwfl_seterrno (DWFL_E_CB);
216e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath	      goto fail;
217b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	    }
218e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath	  goto skip;
219b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	}
220b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    }
221b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
222e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath  /* We let __libdwfl_report_elf cache the fd in mod->main.fd,
223e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath     though it's the same fd for all the members.
224e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath     On module teardown we will close it only on the last Elf reference.  */
225e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath  *mod = process_file (dwfl, name, member_name, fd, member, predicate);
226b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  free (member_name);
227b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  free (module_name);
228e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath
229e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath  if (*mod == NULL)		/* process_file called elf_end.  */
230e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath    return ELF_C_NULL;
231e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath
232e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath  /* Advance the archive-reading offset for the next iteration.  */
233e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath  return elf_next (member);
234b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper}
235b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
236b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper/* Report each member of the archive as its own module.  */
237b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepperstatic Dwfl_Module *
238b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepperprocess_archive (Dwfl *dwfl, const char *name, const char *file_name, int fd,
239b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		 Elf *archive,
240b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		 int (*predicate) (const char *module, const char *file))
241b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
242b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper{
243b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  Dwfl_Module *mod = NULL;
244b28a894209451b93ba830f56e40871e44e9c7c28Roland McGrath  Elf *member = elf_begin (fd, ELF_C_READ_MMAP_PRIVATE, archive);
245b28a894209451b93ba830f56e40871e44e9c7c28Roland McGrath  if (unlikely (member == NULL)) /* Empty archive.  */
246b28a894209451b93ba830f56e40871e44e9c7c28Roland McGrath    {
247b28a894209451b93ba830f56e40871e44e9c7c28Roland McGrath      __libdwfl_seterrno (DWFL_E_BADELF);
248b28a894209451b93ba830f56e40871e44e9c7c28Roland McGrath      return NULL;
249b28a894209451b93ba830f56e40871e44e9c7c28Roland McGrath    }
250b28a894209451b93ba830f56e40871e44e9c7c28Roland McGrath
251e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath  while (process_archive_member (dwfl, name, file_name, predicate,
252b28a894209451b93ba830f56e40871e44e9c7c28Roland McGrath				 fd, member, &mod) != ELF_C_NULL)
253b28a894209451b93ba830f56e40871e44e9c7c28Roland McGrath    member = elf_begin (fd, ELF_C_READ_MMAP_PRIVATE, archive);
254e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath
255e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath  /* We can drop the archive Elf handle even if we're still using members
256e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath     in live modules.  When the last module's elf_end on a member returns
257e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath     zero, that module will close FD.  If no modules survived the predicate,
258e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath     we are all done with the file right here.  */
259b28a894209451b93ba830f56e40871e44e9c7c28Roland McGrath  if (mod != NULL		/* If no modules, caller will clean up.  */
260b28a894209451b93ba830f56e40871e44e9c7c28Roland McGrath      && elf_end (archive) == 0)
261b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    close (fd);
262e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath
263b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  return mod;
264b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper}
265b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
266b597dfad924980dede10d7c19d87900b6172e599Ulrich DrepperDwfl_Module *
267b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepperinternal_function
268b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper__libdwfl_report_offline (Dwfl *dwfl, const char *name,
269b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper			  const char *file_name, int fd, bool closefd,
270b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper			  int (*predicate) (const char *module,
271b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper					    const char *file))
272b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper{
273bca43152aa0bcb31b9442c407bf2b86379761c50Roland McGrath  Elf *elf;
274bca43152aa0bcb31b9442c407bf2b86379761c50Roland McGrath  Dwfl_Error error = __libdw_open_file (&fd, &elf, closefd, true);
275bca43152aa0bcb31b9442c407bf2b86379761c50Roland McGrath  if (error != DWFL_E_NOERROR)
276bca43152aa0bcb31b9442c407bf2b86379761c50Roland McGrath    {
277bca43152aa0bcb31b9442c407bf2b86379761c50Roland McGrath      __libdwfl_seterrno (error);
278bca43152aa0bcb31b9442c407bf2b86379761c50Roland McGrath      return NULL;
279bca43152aa0bcb31b9442c407bf2b86379761c50Roland McGrath    }
280b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  Dwfl_Module *mod = process_file (dwfl, name, file_name, fd, elf, predicate);
281b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  if (mod == NULL)
282b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    {
283b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      elf_end (elf);
284b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      if (closefd)
285b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	close (fd);
286b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    }
287b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  return mod;
288b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper}
289b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
290b597dfad924980dede10d7c19d87900b6172e599Ulrich DrepperDwfl_Module *
291b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepperdwfl_report_offline (Dwfl *dwfl, const char *name,
292b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		     const char *file_name, int fd)
293b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper{
294b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  if (dwfl == NULL)
295b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    return NULL;
296b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
297b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  bool closefd = false;
298b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  if (fd < 0)
299b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    {
300b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      closefd = true;
3013425454a10d307fae891fb667cf7969e945cde79Josh Stone      fd = open (file_name, O_RDONLY);
302b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      if (fd < 0)
303b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	{
304b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	  __libdwfl_seterrno (DWFL_E_ERRNO);
305b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	  return NULL;
306b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	}
307b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    }
308b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
309b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  return __libdwfl_report_offline (dwfl, name, file_name, fd, closefd, NULL);
310b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper}
311d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrathINTDEF (dwfl_report_offline)
312