offline.c revision 904aec2c2f62b729a536c2259274fdd440b0d923
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);
51d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath
52e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath  if (mod->debug.elf == NULL)
53e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath    /* We are only here because sh_addr is zero even though layout is complete.
54e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath       The first section in the first file under -e is placed at 0.  */
55e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath    return 0;
56e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath
579aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath  /* The section numbers might not match between the two files.
589aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath     The best we can rely on is the order of SHF_ALLOC sections.  */
599aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath
60b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  Elf_Scn *ourscn = elf_getscn (mod->debug.elf, shndx);
619aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath  Elf_Scn *scn = NULL;
629aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath  uint_fast32_t skip_alloc = 0;
63b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  while ((scn = elf_nextscn (mod->debug.elf, scn)) != ourscn)
649aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath    {
659aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath      assert (scn != NULL);
669aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath      GElf_Shdr shdr_mem;
679aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath      GElf_Shdr *sh = gelf_getshdr (scn, &shdr_mem);
689aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath      if (unlikely (sh == NULL))
699aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath	return -1;
709aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath      if (sh->sh_flags & SHF_ALLOC)
719aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath	++skip_alloc;
729aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath    }
739aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath
749aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath  scn = NULL;
759aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath  while ((scn = elf_nextscn (mod->main.elf, scn)) != NULL)
769aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath    {
779aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath      GElf_Shdr shdr_mem;
78b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      GElf_Shdr *main_shdr = gelf_getshdr (scn, &shdr_mem);
799aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath      if (unlikely (main_shdr == NULL))
809aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath	return -1;
819aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath      if ((main_shdr->sh_flags & SHF_ALLOC) && skip_alloc-- == 0)
829aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath	{
839aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath	  assert (main_shdr->sh_flags == shdr->sh_flags);
849aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath	  *addr = main_shdr->sh_addr;
859aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath	  return 0;
869aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath	}
879aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath    }
88aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper
899aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath  /* This should never happen.  */
909aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath  return -1;
91d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath}
92d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrathINTDEF (dwfl_offline_section_address)
93d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath
94b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper/* Forward declarations.  */
95b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepperstatic Dwfl_Module *process_elf (Dwfl *dwfl, const char *name,
96b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper				 const char *file_name, int fd, Elf *elf);
97b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepperstatic Dwfl_Module *process_archive (Dwfl *dwfl, const char *name,
98b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper				     const char *file_name, int fd, Elf *elf,
99b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper				     int (*predicate) (const char *module,
100b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper						       const char *file));
101b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
102e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath/* Report one module for an ELF file, or many for an archive.
103e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath   Always consumes ELF and FD.  */
104b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepperstatic Dwfl_Module *
105b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepperprocess_file (Dwfl *dwfl, const char *name, const char *file_name, int fd,
106b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	      Elf *elf, int (*predicate) (const char *module,
107b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper					  const char *file))
108d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath{
109b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  switch (elf_kind (elf))
110b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    {
111b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    default:
112b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    case ELF_K_NONE:
113b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      __libdwfl_seterrno (elf == NULL ? DWFL_E_LIBELF : DWFL_E_BADELF);
114b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      return NULL;
115b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
116b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    case ELF_K_ELF:
117b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      return process_elf (dwfl, name, file_name, fd, elf);
118b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
119b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    case ELF_K_AR:
120b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      return process_archive (dwfl, name, file_name, fd, elf, predicate);
121b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    }
122b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper}
123d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath
124e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath/* Report the open ELF file as a module.  Always consumes ELF and FD.  */
125b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepperstatic Dwfl_Module *
126b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepperprocess_elf (Dwfl *dwfl, const char *name, const char *file_name, int fd,
127b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	     Elf *elf)
128b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper{
129b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  Dwfl_Module *mod = __libdwfl_report_elf (dwfl, name, file_name, fd, elf,
130904aec2c2f62b729a536c2259274fdd440b0d923Jan Kratochvil					   dwfl->offline_next_address, true,
131904aec2c2f62b729a536c2259274fdd440b0d923Jan Kratochvil					   false);
132d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath  if (mod != NULL)
133d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath    {
134d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath      /* If this is an ET_EXEC file with fixed addresses, the address range
135d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath	 it consumed may or may not intersect with the arbitrary range we
136d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath	 will use for relocatable modules.  Make sure we always use a free
137687d7e9bd154a4b1f22b5e3ed7c6c904e421e871Roland McGrath	 range for the offline allocations.  If this module did use
138687d7e9bd154a4b1f22b5e3ed7c6c904e421e871Roland McGrath	 offline_next_address, it may have rounded it up for the module's
139687d7e9bd154a4b1f22b5e3ed7c6c904e421e871Roland McGrath	 alignment requirements.  */
140687d7e9bd154a4b1f22b5e3ed7c6c904e421e871Roland McGrath      if ((dwfl->offline_next_address >= mod->low_addr
141687d7e9bd154a4b1f22b5e3ed7c6c904e421e871Roland McGrath	   || mod->low_addr - dwfl->offline_next_address < OFFLINE_REDZONE)
142d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath	  && dwfl->offline_next_address < mod->high_addr + OFFLINE_REDZONE)
143d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath	dwfl->offline_next_address = mod->high_addr + OFFLINE_REDZONE;
144d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath
145d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath      /* Don't keep the file descriptor around.  */
146d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath      if (mod->main.fd != -1 && elf_cntl (mod->main.elf, ELF_C_FDREAD) == 0)
147d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath	{
148d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath	  close (mod->main.fd);
149d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath	  mod->main.fd = -1;
150d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath	}
151d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath    }
152d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath
153d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath  return mod;
154d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath}
155b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
156e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath/* Always consumes MEMBER.  Returns elf_next result on success.
157e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath   For errors returns ELF_C_NULL with *MOD set to null.  */
158e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrathstatic Elf_Cmd
159b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepperprocess_archive_member (Dwfl *dwfl, const char *name, const char *file_name,
160b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper			int (*predicate) (const char *module, const char *file),
161e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath			int fd, Elf *member, Dwfl_Module **mod)
162b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper{
163b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  const Elf_Arhdr *h = elf_getarhdr (member);
164b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  if (unlikely (h == NULL))
165b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    {
166b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      __libdwfl_seterrno (DWFL_E_LIBELF);
167e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath    fail:
168b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      elf_end (member);
169b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      *mod = NULL;
170e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath      return ELF_C_NULL;
171b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    }
172b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
173e1873141a517738d8c50923e40525bb2ae6db68aPetr Machata  if (!strcmp (h->ar_name, "/") || !strcmp (h->ar_name, "//")
174e1873141a517738d8c50923e40525bb2ae6db68aPetr Machata      || !strcmp (h->ar_name, "/SYM64/"))
175b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    {
176e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath    skip:;
177e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath      /* Skip this and go to the next.  */
178e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath      Elf_Cmd result = elf_next (member);
179b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      elf_end (member);
180e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath      return result;
181b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    }
182b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
183b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  char *member_name;
184b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  if (unlikely (asprintf (&member_name, "%s(%s)", file_name, h->ar_name) < 0))
185b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    {
186b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    nomem:
187b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      __libdwfl_seterrno (DWFL_E_NOMEM);
188b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      elf_end (member);
189b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      *mod = NULL;
190e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath      return ELF_C_NULL;
191b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    }
192b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
193b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  char *module_name = NULL;
194b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  if (name == NULL || name[0] == '\0')
195b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    name = h->ar_name;
196b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  else if (unlikely (asprintf (&module_name, "%s:%s", name, h->ar_name) < 0))
197b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    {
198b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      free (member_name);
199b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      goto nomem;
200b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    }
201b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  else
202b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    name = module_name;
203b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
204b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  if (predicate != NULL)
205b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    {
206b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      /* Let the predicate decide whether to use this one.  */
207b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      int want = (*predicate) (name, member_name);
208b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      if (want <= 0)
209b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	{
210b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	  free (member_name);
211b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	  free (module_name);
212b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	  if (unlikely (want < 0))
213b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	    {
214b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	      __libdwfl_seterrno (DWFL_E_CB);
215e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath	      goto fail;
216b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	    }
217e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath	  goto skip;
218b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	}
219b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    }
220b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
221e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath  /* We let __libdwfl_report_elf cache the fd in mod->main.fd,
222e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath     though it's the same fd for all the members.
223e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath     On module teardown we will close it only on the last Elf reference.  */
224e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath  *mod = process_file (dwfl, name, member_name, fd, member, predicate);
225b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  free (member_name);
226b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  free (module_name);
227e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath
228e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath  if (*mod == NULL)		/* process_file called elf_end.  */
229e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath    return ELF_C_NULL;
230e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath
231e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath  /* Advance the archive-reading offset for the next iteration.  */
232e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath  return elf_next (member);
233b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper}
234b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
235b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper/* Report each member of the archive as its own module.  */
236b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepperstatic Dwfl_Module *
237b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepperprocess_archive (Dwfl *dwfl, const char *name, const char *file_name, int fd,
238b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		 Elf *archive,
239b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		 int (*predicate) (const char *module, const char *file))
240b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
241b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper{
242b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  Dwfl_Module *mod = NULL;
243b28a894209451b93ba830f56e40871e44e9c7c28Roland McGrath  Elf *member = elf_begin (fd, ELF_C_READ_MMAP_PRIVATE, archive);
244b28a894209451b93ba830f56e40871e44e9c7c28Roland McGrath  if (unlikely (member == NULL)) /* Empty archive.  */
245b28a894209451b93ba830f56e40871e44e9c7c28Roland McGrath    {
246b28a894209451b93ba830f56e40871e44e9c7c28Roland McGrath      __libdwfl_seterrno (DWFL_E_BADELF);
247b28a894209451b93ba830f56e40871e44e9c7c28Roland McGrath      return NULL;
248b28a894209451b93ba830f56e40871e44e9c7c28Roland McGrath    }
249b28a894209451b93ba830f56e40871e44e9c7c28Roland McGrath
250e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath  while (process_archive_member (dwfl, name, file_name, predicate,
251b28a894209451b93ba830f56e40871e44e9c7c28Roland McGrath				 fd, member, &mod) != ELF_C_NULL)
252b28a894209451b93ba830f56e40871e44e9c7c28Roland McGrath    member = elf_begin (fd, ELF_C_READ_MMAP_PRIVATE, archive);
253e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath
254e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath  /* We can drop the archive Elf handle even if we're still using members
255e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath     in live modules.  When the last module's elf_end on a member returns
256e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath     zero, that module will close FD.  If no modules survived the predicate,
257e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath     we are all done with the file right here.  */
258b28a894209451b93ba830f56e40871e44e9c7c28Roland McGrath  if (mod != NULL		/* If no modules, caller will clean up.  */
259b28a894209451b93ba830f56e40871e44e9c7c28Roland McGrath      && elf_end (archive) == 0)
260b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    close (fd);
261e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath
262b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  return mod;
263b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper}
264b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
265b597dfad924980dede10d7c19d87900b6172e599Ulrich DrepperDwfl_Module *
266b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepperinternal_function
267b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper__libdwfl_report_offline (Dwfl *dwfl, const char *name,
268b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper			  const char *file_name, int fd, bool closefd,
269b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper			  int (*predicate) (const char *module,
270b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper					    const char *file))
271b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper{
272bca43152aa0bcb31b9442c407bf2b86379761c50Roland McGrath  Elf *elf;
273bca43152aa0bcb31b9442c407bf2b86379761c50Roland McGrath  Dwfl_Error error = __libdw_open_file (&fd, &elf, closefd, true);
274bca43152aa0bcb31b9442c407bf2b86379761c50Roland McGrath  if (error != DWFL_E_NOERROR)
275bca43152aa0bcb31b9442c407bf2b86379761c50Roland McGrath    {
276bca43152aa0bcb31b9442c407bf2b86379761c50Roland McGrath      __libdwfl_seterrno (error);
277bca43152aa0bcb31b9442c407bf2b86379761c50Roland McGrath      return NULL;
278bca43152aa0bcb31b9442c407bf2b86379761c50Roland McGrath    }
279b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  Dwfl_Module *mod = process_file (dwfl, name, file_name, fd, elf, predicate);
280b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  if (mod == NULL)
281b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    {
282b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      elf_end (elf);
283b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      if (closefd)
284b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	close (fd);
285b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    }
286b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  return mod;
287b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper}
288b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
289b597dfad924980dede10d7c19d87900b6172e599Ulrich DrepperDwfl_Module *
290b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepperdwfl_report_offline (Dwfl *dwfl, const char *name,
291b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		     const char *file_name, int fd)
292b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper{
293b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  if (dwfl == NULL)
294b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    return NULL;
295b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
296b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  bool closefd = false;
297b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  if (fd < 0)
298b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    {
299b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      closefd = true;
300b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      fd = open64 (file_name, O_RDONLY);
301b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      if (fd < 0)
302b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	{
303b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	  __libdwfl_seterrno (DWFL_E_ERRNO);
304b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	  return NULL;
305b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	}
306b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    }
307b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
308b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  return __libdwfl_report_offline (dwfl, name, file_name, fd, closefd, NULL);
309b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper}
310d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrathINTDEF (dwfl_report_offline)
311