offline.c revision e4c22ea004c02a58f5db5eb53794275344c17958
1d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath/* Recover relocatibility for addresses computed from debug information.
2aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper   Copyright (C) 2005, 2006, 2007 Red Hat, Inc.
3361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   This file is part of Red Hat elfutils.
4d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath
5361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   Red Hat elfutils is free software; you can redistribute it and/or modify
6361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   it under the terms of the GNU General Public License as published by the
7361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   Free Software Foundation; version 2 of the License.
8d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath
9361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   Red Hat elfutils is distributed in the hope that it will be useful, but
10361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   WITHOUT ANY WARRANTY; without even the implied warranty of
11361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   General Public License for more details.
13361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper
14361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   You should have received a copy of the GNU General Public License along
15361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   with Red Hat elfutils; if not, write to the Free Software Foundation,
161e9ef50681e20ef14c2ba38aef37a71ff148be08Ulrich Drepper   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
17361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper
18361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   In addition, as a special exception, Red Hat, Inc. gives You the
19361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   additional right to link the code of Red Hat elfutils with code licensed
20361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   under any Open Source Initiative certified open source license
21361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   (http://www.opensource.org/licenses/index.php) which requires the
22361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   distribution of source code with any binary distribution and to
23361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   distribute linked combinations of the two.  Non-GPL Code permitted under
24361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   this exception must only link to the code of Red Hat elfutils through
25361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   those well defined interfaces identified in the file named EXCEPTION
26361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   found in the source code files (the "Approved Interfaces").  The files
27361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   of Non-GPL Code may instantiate templates or use macros or inline
28361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   functions from the Approved Interfaces without causing the resulting
29361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   work to be covered by the GNU General Public License.  Only Red Hat,
30361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   Inc. may make changes or additions to the list of Approved Interfaces.
31361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   Red Hat's grant of this exception is conditioned upon your not adding
32361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   any new exceptions.  If you wish to add a new Approved Interface or
33361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   exception, please contact Red Hat.  You must obey the GNU General Public
34361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   License in all respects for all of the Red Hat elfutils code and other
35361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   code used in conjunction with Red Hat elfutils except the Non-GPL Code
36361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   covered by this exception.  If you modify this file, you may extend this
37361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   exception to your version of the file, but you are not obligated to do
38361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   so.  If you do not wish to provide this exception without modification,
39361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   you must delete this exception statement from your version and license
40361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   this file solely under the GPL without exception.
41361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper
42361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   Red Hat elfutils is an included package of the Open Invention Network.
43361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   An included package of the Open Invention Network is a package for which
44361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   Open Invention Network licensees cross-license their patents.  No patent
45361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   license is granted, either expressly or impliedly, by designation as an
46361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   included package.  Should you wish to participate in the Open Invention
47361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   Network licensing program, please visit www.openinventionnetwork.com
48361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper   <http://www.openinventionnetwork.com>.  */
49d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath
50d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath#include "libdwflP.h"
51b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper#include <fcntl.h>
52d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath#include <unistd.h>
53d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath
54d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath/* Since dwfl_report_elf lays out the sections already, this will only be
55d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath   called when the section headers of the debuginfo file are being
56e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath   consulted instead, or for the section placed at 0.  With binutils
57e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath   strip-to-debug, the symbol table is in the debuginfo file and relocation
58e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath   looks there.  */
59d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrathint
60d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrathdwfl_offline_section_address (Dwfl_Module *mod,
61d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath			      void **userdata __attribute__ ((unused)),
62d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath			      const char *modname __attribute__ ((unused)),
63d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath			      Dwarf_Addr base __attribute__ ((unused)),
64d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath			      const char *secname __attribute__ ((unused)),
65d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath			      Elf32_Word shndx,
66d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath			      const GElf_Shdr *shdr __attribute__ ((unused)),
67d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath			      Dwarf_Addr *addr)
68d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath{
699aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath  assert (mod->e_type == ET_REL);
70d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath  assert (shdr->sh_addr == 0);
71d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath  assert (shdr->sh_flags & SHF_ALLOC);
72d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath
73e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath  if (mod->debug.elf == NULL)
74e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath    /* We are only here because sh_addr is zero even though layout is complete.
75e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath       The first section in the first file under -e is placed at 0.  */
76e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath    return 0;
77e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath
789aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath  /* The section numbers might not match between the two files.
799aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath     The best we can rely on is the order of SHF_ALLOC sections.  */
809aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath
81b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  Elf_Scn *ourscn = elf_getscn (mod->debug.elf, shndx);
829aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath  Elf_Scn *scn = NULL;
839aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath  uint_fast32_t skip_alloc = 0;
84b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  while ((scn = elf_nextscn (mod->debug.elf, scn)) != ourscn)
859aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath    {
869aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath      assert (scn != NULL);
879aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath      GElf_Shdr shdr_mem;
889aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath      GElf_Shdr *sh = gelf_getshdr (scn, &shdr_mem);
899aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath      if (unlikely (sh == NULL))
909aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath	return -1;
919aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath      if (sh->sh_flags & SHF_ALLOC)
929aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath	++skip_alloc;
939aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath    }
949aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath
959aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath  scn = NULL;
969aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath  while ((scn = elf_nextscn (mod->main.elf, scn)) != NULL)
979aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath    {
989aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath      GElf_Shdr shdr_mem;
99b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      GElf_Shdr *main_shdr = gelf_getshdr (scn, &shdr_mem);
1009aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath      if (unlikely (main_shdr == NULL))
1019aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath	return -1;
1029aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath      if ((main_shdr->sh_flags & SHF_ALLOC) && skip_alloc-- == 0)
1039aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath	{
1049aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath	  assert (main_shdr->sh_flags == shdr->sh_flags);
1059aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath	  *addr = main_shdr->sh_addr;
1069aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath	  return 0;
1079aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath	}
1089aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath    }
109aa915fd3d70b4cbe4581f9ec170d986c6ba35063Ulrich Drepper
1109aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath  /* This should never happen.  */
1119aa8ef7fbb5ada14b7c4585d6c1361aa5eab6f88Roland McGrath  return -1;
112d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath}
113d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrathINTDEF (dwfl_offline_section_address)
114d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath
115b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper/* Forward declarations.  */
116b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepperstatic Dwfl_Module *process_elf (Dwfl *dwfl, const char *name,
117b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper				 const char *file_name, int fd, Elf *elf);
118b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepperstatic Dwfl_Module *process_archive (Dwfl *dwfl, const char *name,
119b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper				     const char *file_name, int fd, Elf *elf,
120b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper				     int (*predicate) (const char *module,
121b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper						       const char *file));
122b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
123e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath/* Report one module for an ELF file, or many for an archive.
124e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath   Always consumes ELF and FD.  */
125b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepperstatic Dwfl_Module *
126b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepperprocess_file (Dwfl *dwfl, const char *name, const char *file_name, int fd,
127b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	      Elf *elf, int (*predicate) (const char *module,
128b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper					  const char *file))
129d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath{
130b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  switch (elf_kind (elf))
131b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    {
132b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    default:
133b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    case ELF_K_NONE:
134b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      __libdwfl_seterrno (elf == NULL ? DWFL_E_LIBELF : DWFL_E_BADELF);
135b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      return NULL;
136b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
137b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    case ELF_K_ELF:
138b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      return process_elf (dwfl, name, file_name, fd, elf);
139b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
140b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    case ELF_K_AR:
141b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      return process_archive (dwfl, name, file_name, fd, elf, predicate);
142b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    }
143b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper}
144d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath
145e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath/* Report the open ELF file as a module.  Always consumes ELF and FD.  */
146b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepperstatic Dwfl_Module *
147b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepperprocess_elf (Dwfl *dwfl, const char *name, const char *file_name, int fd,
148b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	     Elf *elf)
149b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper{
150b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  Dwfl_Module *mod = __libdwfl_report_elf (dwfl, name, file_name, fd, elf,
151b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper					   dwfl->offline_next_address);
152d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath  if (mod != NULL)
153d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath    {
154d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath      /* If this is an ET_EXEC file with fixed addresses, the address range
155d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath	 it consumed may or may not intersect with the arbitrary range we
156d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath	 will use for relocatable modules.  Make sure we always use a free
157687d7e9bd154a4b1f22b5e3ed7c6c904e421e871Roland McGrath	 range for the offline allocations.  If this module did use
158687d7e9bd154a4b1f22b5e3ed7c6c904e421e871Roland McGrath	 offline_next_address, it may have rounded it up for the module's
159687d7e9bd154a4b1f22b5e3ed7c6c904e421e871Roland McGrath	 alignment requirements.  */
160687d7e9bd154a4b1f22b5e3ed7c6c904e421e871Roland McGrath      if ((dwfl->offline_next_address >= mod->low_addr
161687d7e9bd154a4b1f22b5e3ed7c6c904e421e871Roland McGrath	   || mod->low_addr - dwfl->offline_next_address < OFFLINE_REDZONE)
162d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath	  && dwfl->offline_next_address < mod->high_addr + OFFLINE_REDZONE)
163d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath	dwfl->offline_next_address = mod->high_addr + OFFLINE_REDZONE;
164d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath
165d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath      /* Don't keep the file descriptor around.  */
166d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath      if (mod->main.fd != -1 && elf_cntl (mod->main.elf, ELF_C_FDREAD) == 0)
167d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath	{
168d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath	  close (mod->main.fd);
169d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath	  mod->main.fd = -1;
170d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath	}
171d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath    }
172d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath
173d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath  return mod;
174d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrath}
175b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
176e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath/* Always consumes MEMBER.  Returns elf_next result on success.
177e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath   For errors returns ELF_C_NULL with *MOD set to null.  */
178e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrathstatic Elf_Cmd
179b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepperprocess_archive_member (Dwfl *dwfl, const char *name, const char *file_name,
180b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper			int (*predicate) (const char *module, const char *file),
181e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath			int fd, Elf *member, Dwfl_Module **mod)
182b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper{
183b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  const Elf_Arhdr *h = elf_getarhdr (member);
184b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  if (unlikely (h == NULL))
185b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    {
186b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      __libdwfl_seterrno (DWFL_E_LIBELF);
187e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath    fail:
188b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      elf_end (member);
189b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      *mod = NULL;
190e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath      return ELF_C_NULL;
191b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    }
192b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
193b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  if (!strcmp (h->ar_name, "/") || !strcmp (h->ar_name, "//"))
194b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    {
195e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath    skip:;
196e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath      /* Skip this and go to the next.  */
197e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath      Elf_Cmd result = elf_next (member);
198b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      elf_end (member);
199e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath      return result;
200b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    }
201b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
202b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  char *member_name;
203b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  if (unlikely (asprintf (&member_name, "%s(%s)", file_name, h->ar_name) < 0))
204b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    {
205b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    nomem:
206b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      __libdwfl_seterrno (DWFL_E_NOMEM);
207b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      elf_end (member);
208b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      *mod = NULL;
209e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath      return ELF_C_NULL;
210b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    }
211b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
212b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  char *module_name = NULL;
213b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  if (name == NULL || name[0] == '\0')
214b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    name = h->ar_name;
215b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  else if (unlikely (asprintf (&module_name, "%s:%s", name, h->ar_name) < 0))
216b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    {
217b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      free (member_name);
218b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      goto nomem;
219b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    }
220b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  else
221b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    name = module_name;
222b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
223b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  if (predicate != NULL)
224b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    {
225b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      /* Let the predicate decide whether to use this one.  */
226b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      int want = (*predicate) (name, member_name);
227b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      if (want <= 0)
228b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	{
229b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	  free (member_name);
230b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	  free (module_name);
231b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	  if (unlikely (want < 0))
232b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	    {
233b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	      __libdwfl_seterrno (DWFL_E_CB);
234e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath	      goto fail;
235b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	    }
236e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath	  goto skip;
237b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	}
238b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    }
239b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
240e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath  /* We let __libdwfl_report_elf cache the fd in mod->main.fd,
241e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath     though it's the same fd for all the members.
242e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath     On module teardown we will close it only on the last Elf reference.  */
243e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath  *mod = process_file (dwfl, name, member_name, fd, member, predicate);
244b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  free (member_name);
245b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  free (module_name);
246e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath
247e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath  if (*mod == NULL)		/* process_file called elf_end.  */
248e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath    return ELF_C_NULL;
249e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath
250e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath  /* Advance the archive-reading offset for the next iteration.  */
251e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath  return elf_next (member);
252b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper}
253b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
254b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper/* Report each member of the archive as its own module.  */
255b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepperstatic Dwfl_Module *
256b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepperprocess_archive (Dwfl *dwfl, const char *name, const char *file_name, int fd,
257b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		 Elf *archive,
258b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		 int (*predicate) (const char *module, const char *file))
259b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
260b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper{
261b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  Dwfl_Module *mod = NULL;
262e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath  while (process_archive_member (dwfl, name, file_name, predicate,
263e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath				 fd, elf_begin (fd, ELF_C_READ_MMAP_PRIVATE,
264e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath						archive), &mod) != ELF_C_NULL)
265e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath    ;
266e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath
267e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath  /* We can drop the archive Elf handle even if we're still using members
268e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath     in live modules.  When the last module's elf_end on a member returns
269e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath     zero, that module will close FD.  If no modules survived the predicate,
270e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath     we are all done with the file right here.  */
271e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath  if (elf_end (archive) == 0)
272b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    close (fd);
273e4c22ea004c02a58f5db5eb53794275344c17958Roland McGrath
274b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  return mod;
275b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper}
276b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
277b597dfad924980dede10d7c19d87900b6172e599Ulrich DrepperDwfl_Module *
278b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepperinternal_function
279b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper__libdwfl_report_offline (Dwfl *dwfl, const char *name,
280b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper			  const char *file_name, int fd, bool closefd,
281b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper			  int (*predicate) (const char *module,
282b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper					    const char *file))
283b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper{
284b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  Elf *elf = elf_begin (fd, ELF_C_READ_MMAP_PRIVATE, NULL);
285b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  Dwfl_Module *mod = process_file (dwfl, name, file_name, fd, elf, predicate);
286b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  if (mod == NULL)
287b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    {
288b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      elf_end (elf);
289b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      if (closefd)
290b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	close (fd);
291b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    }
292b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  return mod;
293b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper}
294b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
295b597dfad924980dede10d7c19d87900b6172e599Ulrich DrepperDwfl_Module *
296b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepperdwfl_report_offline (Dwfl *dwfl, const char *name,
297b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper		     const char *file_name, int fd)
298b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper{
299b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  if (dwfl == NULL)
300b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    return NULL;
301b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
302b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  bool closefd = false;
303b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  if (fd < 0)
304b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    {
305b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      closefd = true;
306b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      fd = open64 (file_name, O_RDONLY);
307b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper      if (fd < 0)
308b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	{
309b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	  __libdwfl_seterrno (DWFL_E_ERRNO);
310b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	  return NULL;
311b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper	}
312b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper    }
313b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper
314b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper  return __libdwfl_report_offline (dwfl, name, file_name, fd, closefd, NULL);
315b597dfad924980dede10d7c19d87900b6172e599Ulrich Drepper}
316d17fac7e89666b47811581b10b5ca0d253a3a82dRoland McGrathINTDEF (dwfl_report_offline)
317