xref: /aosp_15_r20/external/elfutils/libdwfl/offline.c (revision 7304104da70ce23c86437a01be71edd1a2d7f37e)
1*7304104dSAndroid Build Coastguard Worker /* Recover relocatibility for addresses computed from debug information.
2*7304104dSAndroid Build Coastguard Worker    Copyright (C) 2005-2009, 2012 Red Hat, Inc.
3*7304104dSAndroid Build Coastguard Worker    Copyright (C) 2022 Mark J. Wielaard <[email protected]>
4*7304104dSAndroid Build Coastguard Worker    Copyright (C) 2022 Google LLC
5*7304104dSAndroid Build Coastguard Worker    This file is part of elfutils.
6*7304104dSAndroid Build Coastguard Worker 
7*7304104dSAndroid Build Coastguard Worker    This file is free software; you can redistribute it and/or modify
8*7304104dSAndroid Build Coastguard Worker    it under the terms of either
9*7304104dSAndroid Build Coastguard Worker 
10*7304104dSAndroid Build Coastguard Worker      * the GNU Lesser General Public License as published by the Free
11*7304104dSAndroid Build Coastguard Worker        Software Foundation; either version 3 of the License, or (at
12*7304104dSAndroid Build Coastguard Worker        your option) any later version
13*7304104dSAndroid Build Coastguard Worker 
14*7304104dSAndroid Build Coastguard Worker    or
15*7304104dSAndroid Build Coastguard Worker 
16*7304104dSAndroid Build Coastguard Worker      * the GNU General Public License as published by the Free
17*7304104dSAndroid Build Coastguard Worker        Software Foundation; either version 2 of the License, or (at
18*7304104dSAndroid Build Coastguard Worker        your option) any later version
19*7304104dSAndroid Build Coastguard Worker 
20*7304104dSAndroid Build Coastguard Worker    or both in parallel, as here.
21*7304104dSAndroid Build Coastguard Worker 
22*7304104dSAndroid Build Coastguard Worker    elfutils is distributed in the hope that it will be useful, but
23*7304104dSAndroid Build Coastguard Worker    WITHOUT ANY WARRANTY; without even the implied warranty of
24*7304104dSAndroid Build Coastguard Worker    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25*7304104dSAndroid Build Coastguard Worker    General Public License for more details.
26*7304104dSAndroid Build Coastguard Worker 
27*7304104dSAndroid Build Coastguard Worker    You should have received copies of the GNU General Public License and
28*7304104dSAndroid Build Coastguard Worker    the GNU Lesser General Public License along with this program.  If
29*7304104dSAndroid Build Coastguard Worker    not, see <http://www.gnu.org/licenses/>.  */
30*7304104dSAndroid Build Coastguard Worker 
31*7304104dSAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
32*7304104dSAndroid Build Coastguard Worker # include <config.h>
33*7304104dSAndroid Build Coastguard Worker #endif
34*7304104dSAndroid Build Coastguard Worker 
35*7304104dSAndroid Build Coastguard Worker #include "libelfP.h"
36*7304104dSAndroid Build Coastguard Worker #include "libdwflP.h"
37*7304104dSAndroid Build Coastguard Worker #include <fcntl.h>
38*7304104dSAndroid Build Coastguard Worker 
39*7304104dSAndroid Build Coastguard Worker /* Since dwfl_report_elf lays out the sections already, this will only be
40*7304104dSAndroid Build Coastguard Worker    called when the section headers of the debuginfo file are being
41*7304104dSAndroid Build Coastguard Worker    consulted instead, or for the section placed at 0.  With binutils
42*7304104dSAndroid Build Coastguard Worker    strip-to-debug, the symbol table is in the debuginfo file and relocation
43*7304104dSAndroid Build Coastguard Worker    looks there.  */
44*7304104dSAndroid Build Coastguard Worker int
dwfl_offline_section_address(Dwfl_Module * mod,void ** userdata,const char * modname,Dwarf_Addr base,const char * secname,Elf32_Word shndx,const GElf_Shdr * shdr,Dwarf_Addr * addr)45*7304104dSAndroid Build Coastguard Worker dwfl_offline_section_address (Dwfl_Module *mod,
46*7304104dSAndroid Build Coastguard Worker 			      void **userdata __attribute__ ((unused)),
47*7304104dSAndroid Build Coastguard Worker 			      const char *modname __attribute__ ((unused)),
48*7304104dSAndroid Build Coastguard Worker 			      Dwarf_Addr base __attribute__ ((unused)),
49*7304104dSAndroid Build Coastguard Worker 			      const char *secname __attribute__ ((unused)),
50*7304104dSAndroid Build Coastguard Worker 			      Elf32_Word shndx,
51*7304104dSAndroid Build Coastguard Worker 			      const GElf_Shdr *shdr __attribute__ ((unused)),
52*7304104dSAndroid Build Coastguard Worker 			      Dwarf_Addr *addr)
53*7304104dSAndroid Build Coastguard Worker {
54*7304104dSAndroid Build Coastguard Worker   if (mod->e_type != ET_REL
55*7304104dSAndroid Build Coastguard Worker       || shdr->sh_addr != 0
56*7304104dSAndroid Build Coastguard Worker       || !(shdr->sh_flags & SHF_ALLOC)
57*7304104dSAndroid Build Coastguard Worker       || shndx == 0)
58*7304104dSAndroid Build Coastguard Worker     return -1;
59*7304104dSAndroid Build Coastguard Worker 
60*7304104dSAndroid Build Coastguard Worker   if (mod->debug.elf == NULL)
61*7304104dSAndroid Build Coastguard Worker     /* We are only here because sh_addr is zero even though layout is complete.
62*7304104dSAndroid Build Coastguard Worker        The first section in the first file under -e is placed at 0.  */
63*7304104dSAndroid Build Coastguard Worker     return 0;
64*7304104dSAndroid Build Coastguard Worker 
65*7304104dSAndroid Build Coastguard Worker   /* The section numbers might not match between the two files.
66*7304104dSAndroid Build Coastguard Worker      The best we can rely on is the order of SHF_ALLOC sections.  */
67*7304104dSAndroid Build Coastguard Worker 
68*7304104dSAndroid Build Coastguard Worker   Elf_Scn *ourscn = elf_getscn (mod->debug.elf, shndx);
69*7304104dSAndroid Build Coastguard Worker   Elf_Scn *scn = NULL;
70*7304104dSAndroid Build Coastguard Worker   uint_fast32_t skip_alloc = 0;
71*7304104dSAndroid Build Coastguard Worker   while ((scn = elf_nextscn (mod->debug.elf, scn)) != ourscn)
72*7304104dSAndroid Build Coastguard Worker     {
73*7304104dSAndroid Build Coastguard Worker       assert (scn != NULL);
74*7304104dSAndroid Build Coastguard Worker       GElf_Shdr shdr_mem;
75*7304104dSAndroid Build Coastguard Worker       GElf_Shdr *sh = gelf_getshdr (scn, &shdr_mem);
76*7304104dSAndroid Build Coastguard Worker       if (unlikely (sh == NULL))
77*7304104dSAndroid Build Coastguard Worker 	return -1;
78*7304104dSAndroid Build Coastguard Worker       if (sh->sh_flags & SHF_ALLOC)
79*7304104dSAndroid Build Coastguard Worker 	++skip_alloc;
80*7304104dSAndroid Build Coastguard Worker     }
81*7304104dSAndroid Build Coastguard Worker 
82*7304104dSAndroid Build Coastguard Worker   scn = NULL;
83*7304104dSAndroid Build Coastguard Worker   while ((scn = elf_nextscn (mod->main.elf, scn)) != NULL)
84*7304104dSAndroid Build Coastguard Worker     {
85*7304104dSAndroid Build Coastguard Worker       GElf_Shdr shdr_mem;
86*7304104dSAndroid Build Coastguard Worker       GElf_Shdr *main_shdr = gelf_getshdr (scn, &shdr_mem);
87*7304104dSAndroid Build Coastguard Worker       if (unlikely (main_shdr == NULL))
88*7304104dSAndroid Build Coastguard Worker 	return -1;
89*7304104dSAndroid Build Coastguard Worker       if ((main_shdr->sh_flags & SHF_ALLOC) && skip_alloc-- == 0)
90*7304104dSAndroid Build Coastguard Worker 	{
91*7304104dSAndroid Build Coastguard Worker 	  assert (main_shdr->sh_flags == shdr->sh_flags);
92*7304104dSAndroid Build Coastguard Worker 	  *addr = main_shdr->sh_addr;
93*7304104dSAndroid Build Coastguard Worker 	  return 0;
94*7304104dSAndroid Build Coastguard Worker 	}
95*7304104dSAndroid Build Coastguard Worker     }
96*7304104dSAndroid Build Coastguard Worker 
97*7304104dSAndroid Build Coastguard Worker   /* This should never happen.  */
98*7304104dSAndroid Build Coastguard Worker   return -1;
99*7304104dSAndroid Build Coastguard Worker }
100*7304104dSAndroid Build Coastguard Worker INTDEF (dwfl_offline_section_address)
101*7304104dSAndroid Build Coastguard Worker 
102*7304104dSAndroid Build Coastguard Worker /* Forward declarations.  */
103*7304104dSAndroid Build Coastguard Worker static Dwfl_Module *process_elf (Dwfl *dwfl, const char *name,
104*7304104dSAndroid Build Coastguard Worker 				 const char *file_name, int fd, Elf *elf);
105*7304104dSAndroid Build Coastguard Worker static Dwfl_Module *process_archive (Dwfl *dwfl, const char *name,
106*7304104dSAndroid Build Coastguard Worker 				     const char *file_name, int fd, Elf *elf,
107*7304104dSAndroid Build Coastguard Worker 				     int (*predicate) (const char *module,
108*7304104dSAndroid Build Coastguard Worker 						       const char *file));
109*7304104dSAndroid Build Coastguard Worker 
110*7304104dSAndroid Build Coastguard Worker /* Report one module for an ELF file, or many for an archive.
111*7304104dSAndroid Build Coastguard Worker    Always consumes ELF and FD.  */
112*7304104dSAndroid Build Coastguard Worker static Dwfl_Module *
process_file(Dwfl * dwfl,const char * name,const char * file_name,int fd,Elf * elf,int (* predicate)(const char * module,const char * file))113*7304104dSAndroid Build Coastguard Worker process_file (Dwfl *dwfl, const char *name, const char *file_name, int fd,
114*7304104dSAndroid Build Coastguard Worker 	      Elf *elf, int (*predicate) (const char *module,
115*7304104dSAndroid Build Coastguard Worker 					  const char *file))
116*7304104dSAndroid Build Coastguard Worker {
117*7304104dSAndroid Build Coastguard Worker   switch (elf_kind (elf))
118*7304104dSAndroid Build Coastguard Worker     {
119*7304104dSAndroid Build Coastguard Worker     default:
120*7304104dSAndroid Build Coastguard Worker     case ELF_K_NONE:
121*7304104dSAndroid Build Coastguard Worker       __libdwfl_seterrno (elf == NULL ? DWFL_E_LIBELF : DWFL_E_BADELF);
122*7304104dSAndroid Build Coastguard Worker       return NULL;
123*7304104dSAndroid Build Coastguard Worker 
124*7304104dSAndroid Build Coastguard Worker     case ELF_K_ELF:
125*7304104dSAndroid Build Coastguard Worker       return process_elf (dwfl, name, file_name, fd, elf);
126*7304104dSAndroid Build Coastguard Worker 
127*7304104dSAndroid Build Coastguard Worker     case ELF_K_AR:
128*7304104dSAndroid Build Coastguard Worker       return process_archive (dwfl, name, file_name, fd, elf, predicate);
129*7304104dSAndroid Build Coastguard Worker     }
130*7304104dSAndroid Build Coastguard Worker }
131*7304104dSAndroid Build Coastguard Worker 
132*7304104dSAndroid Build Coastguard Worker /* Report the open ELF file as a module.  Always consumes ELF and FD.  */
133*7304104dSAndroid Build Coastguard Worker static Dwfl_Module *
process_elf(Dwfl * dwfl,const char * name,const char * file_name,int fd,Elf * elf)134*7304104dSAndroid Build Coastguard Worker process_elf (Dwfl *dwfl, const char *name, const char *file_name, int fd,
135*7304104dSAndroid Build Coastguard Worker 	     Elf *elf)
136*7304104dSAndroid Build Coastguard Worker {
137*7304104dSAndroid Build Coastguard Worker   Dwfl_Module *mod = __libdwfl_report_elf (dwfl, name, file_name, fd, elf,
138*7304104dSAndroid Build Coastguard Worker 					   dwfl->offline_next_address, true,
139*7304104dSAndroid Build Coastguard Worker 					   false);
140*7304104dSAndroid Build Coastguard Worker   if (mod != NULL)
141*7304104dSAndroid Build Coastguard Worker     {
142*7304104dSAndroid Build Coastguard Worker       /* If this is an ET_EXEC file with fixed addresses, the address range
143*7304104dSAndroid Build Coastguard Worker 	 it consumed may or may not intersect with the arbitrary range we
144*7304104dSAndroid Build Coastguard Worker 	 will use for relocatable modules.  Make sure we always use a free
145*7304104dSAndroid Build Coastguard Worker 	 range for the offline allocations.  If this module did use
146*7304104dSAndroid Build Coastguard Worker 	 offline_next_address, it may have rounded it up for the module's
147*7304104dSAndroid Build Coastguard Worker 	 alignment requirements.  */
148*7304104dSAndroid Build Coastguard Worker       if ((dwfl->offline_next_address >= mod->low_addr
149*7304104dSAndroid Build Coastguard Worker 	   || mod->low_addr - dwfl->offline_next_address < OFFLINE_REDZONE)
150*7304104dSAndroid Build Coastguard Worker 	  && dwfl->offline_next_address < mod->high_addr + OFFLINE_REDZONE)
151*7304104dSAndroid Build Coastguard Worker 	dwfl->offline_next_address = mod->high_addr + OFFLINE_REDZONE;
152*7304104dSAndroid Build Coastguard Worker 
153*7304104dSAndroid Build Coastguard Worker       /* Don't keep the file descriptor around.  */
154*7304104dSAndroid Build Coastguard Worker       if (mod->main.fd != -1 && elf_cntl (mod->main.elf, ELF_C_FDREAD) == 0)
155*7304104dSAndroid Build Coastguard Worker 	{
156*7304104dSAndroid Build Coastguard Worker 	  /* Grab the path in case we want to report this file as
157*7304104dSAndroid Build Coastguard Worker 	     Dwarf later.  */
158*7304104dSAndroid Build Coastguard Worker 	  mod->elfpath = __libdw_elfpath (mod->main.fd);
159*7304104dSAndroid Build Coastguard Worker 	  close (mod->main.fd);
160*7304104dSAndroid Build Coastguard Worker 	  mod->main.fd = -1;
161*7304104dSAndroid Build Coastguard Worker 	}
162*7304104dSAndroid Build Coastguard Worker     }
163*7304104dSAndroid Build Coastguard Worker 
164*7304104dSAndroid Build Coastguard Worker   return mod;
165*7304104dSAndroid Build Coastguard Worker }
166*7304104dSAndroid Build Coastguard Worker 
167*7304104dSAndroid Build Coastguard Worker /* Always consumes MEMBER.  Returns elf_next result on success.
168*7304104dSAndroid Build Coastguard Worker    For errors returns ELF_C_NULL with *MOD set to null.  */
169*7304104dSAndroid Build Coastguard Worker static Elf_Cmd
process_archive_member(Dwfl * dwfl,const char * name,const char * file_name,int (* predicate)(const char * module,const char * file),int fd,Elf * member,Dwfl_Module ** mod)170*7304104dSAndroid Build Coastguard Worker process_archive_member (Dwfl *dwfl, const char *name, const char *file_name,
171*7304104dSAndroid Build Coastguard Worker 			int (*predicate) (const char *module, const char *file),
172*7304104dSAndroid Build Coastguard Worker 			int fd, Elf *member, Dwfl_Module **mod)
173*7304104dSAndroid Build Coastguard Worker {
174*7304104dSAndroid Build Coastguard Worker   const Elf_Arhdr *h = elf_getarhdr (member);
175*7304104dSAndroid Build Coastguard Worker   if (unlikely (h == NULL))
176*7304104dSAndroid Build Coastguard Worker     {
177*7304104dSAndroid Build Coastguard Worker       __libdwfl_seterrno (DWFL_E_LIBELF);
178*7304104dSAndroid Build Coastguard Worker     fail:
179*7304104dSAndroid Build Coastguard Worker       elf_end (member);
180*7304104dSAndroid Build Coastguard Worker       *mod = NULL;
181*7304104dSAndroid Build Coastguard Worker       return ELF_C_NULL;
182*7304104dSAndroid Build Coastguard Worker     }
183*7304104dSAndroid Build Coastguard Worker 
184*7304104dSAndroid Build Coastguard Worker   if (!strcmp (h->ar_name, "/") || !strcmp (h->ar_name, "//")
185*7304104dSAndroid Build Coastguard Worker       || !strcmp (h->ar_name, "/SYM64/"))
186*7304104dSAndroid Build Coastguard Worker     {
187*7304104dSAndroid Build Coastguard Worker     skip:;
188*7304104dSAndroid Build Coastguard Worker       /* Skip this and go to the next.  */
189*7304104dSAndroid Build Coastguard Worker       Elf_Cmd result = elf_next (member);
190*7304104dSAndroid Build Coastguard Worker       elf_end (member);
191*7304104dSAndroid Build Coastguard Worker       return result;
192*7304104dSAndroid Build Coastguard Worker     }
193*7304104dSAndroid Build Coastguard Worker 
194*7304104dSAndroid Build Coastguard Worker   char *member_name;
195*7304104dSAndroid Build Coastguard Worker   if (unlikely (asprintf (&member_name, "%s(%s)", file_name, h->ar_name) < 0))
196*7304104dSAndroid Build Coastguard Worker     {
197*7304104dSAndroid Build Coastguard Worker     nomem:
198*7304104dSAndroid Build Coastguard Worker       __libdwfl_seterrno (DWFL_E_NOMEM);
199*7304104dSAndroid Build Coastguard Worker       elf_end (member);
200*7304104dSAndroid Build Coastguard Worker       *mod = NULL;
201*7304104dSAndroid Build Coastguard Worker       return ELF_C_NULL;
202*7304104dSAndroid Build Coastguard Worker     }
203*7304104dSAndroid Build Coastguard Worker 
204*7304104dSAndroid Build Coastguard Worker   char *module_name = NULL;
205*7304104dSAndroid Build Coastguard Worker   if (name == NULL || name[0] == '\0')
206*7304104dSAndroid Build Coastguard Worker     name = h->ar_name;
207*7304104dSAndroid Build Coastguard Worker   else if (unlikely (asprintf (&module_name, "%s:%s", name, h->ar_name) < 0))
208*7304104dSAndroid Build Coastguard Worker     {
209*7304104dSAndroid Build Coastguard Worker       free (member_name);
210*7304104dSAndroid Build Coastguard Worker       goto nomem;
211*7304104dSAndroid Build Coastguard Worker     }
212*7304104dSAndroid Build Coastguard Worker   else
213*7304104dSAndroid Build Coastguard Worker     name = module_name;
214*7304104dSAndroid Build Coastguard Worker 
215*7304104dSAndroid Build Coastguard Worker   if (predicate != NULL)
216*7304104dSAndroid Build Coastguard Worker     {
217*7304104dSAndroid Build Coastguard Worker       /* Let the predicate decide whether to use this one.  */
218*7304104dSAndroid Build Coastguard Worker       int want = (*predicate) (name, member_name);
219*7304104dSAndroid Build Coastguard Worker       if (want <= 0)
220*7304104dSAndroid Build Coastguard Worker 	{
221*7304104dSAndroid Build Coastguard Worker 	  free (member_name);
222*7304104dSAndroid Build Coastguard Worker 	  free (module_name);
223*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (want < 0))
224*7304104dSAndroid Build Coastguard Worker 	    {
225*7304104dSAndroid Build Coastguard Worker 	      __libdwfl_seterrno (DWFL_E_CB);
226*7304104dSAndroid Build Coastguard Worker 	      goto fail;
227*7304104dSAndroid Build Coastguard Worker 	    }
228*7304104dSAndroid Build Coastguard Worker 	  goto skip;
229*7304104dSAndroid Build Coastguard Worker 	}
230*7304104dSAndroid Build Coastguard Worker     }
231*7304104dSAndroid Build Coastguard Worker 
232*7304104dSAndroid Build Coastguard Worker   /* We let __libdwfl_report_elf cache the fd in mod->main.fd,
233*7304104dSAndroid Build Coastguard Worker      though it's the same fd for all the members.
234*7304104dSAndroid Build Coastguard Worker      On module teardown we will close it only on the last Elf reference.  */
235*7304104dSAndroid Build Coastguard Worker   *mod = process_file (dwfl, name, member_name, fd, member, predicate);
236*7304104dSAndroid Build Coastguard Worker   free (member_name);
237*7304104dSAndroid Build Coastguard Worker   free (module_name);
238*7304104dSAndroid Build Coastguard Worker 
239*7304104dSAndroid Build Coastguard Worker   if (*mod == NULL)
240*7304104dSAndroid Build Coastguard Worker     {
241*7304104dSAndroid Build Coastguard Worker       elf_end (member);
242*7304104dSAndroid Build Coastguard Worker       return ELF_C_NULL;
243*7304104dSAndroid Build Coastguard Worker     }
244*7304104dSAndroid Build Coastguard Worker 
245*7304104dSAndroid Build Coastguard Worker   /* Advance the archive-reading offset for the next iteration.  */
246*7304104dSAndroid Build Coastguard Worker   return elf_next (member);
247*7304104dSAndroid Build Coastguard Worker }
248*7304104dSAndroid Build Coastguard Worker 
249*7304104dSAndroid Build Coastguard Worker /* Report each member of the archive as its own module.  */
250*7304104dSAndroid Build Coastguard Worker static Dwfl_Module *
process_archive(Dwfl * dwfl,const char * name,const char * file_name,int fd,Elf * archive,int (* predicate)(const char * module,const char * file))251*7304104dSAndroid Build Coastguard Worker process_archive (Dwfl *dwfl, const char *name, const char *file_name, int fd,
252*7304104dSAndroid Build Coastguard Worker 		 Elf *archive,
253*7304104dSAndroid Build Coastguard Worker 		 int (*predicate) (const char *module, const char *file))
254*7304104dSAndroid Build Coastguard Worker 
255*7304104dSAndroid Build Coastguard Worker {
256*7304104dSAndroid Build Coastguard Worker   Dwfl_Module *mod = NULL;
257*7304104dSAndroid Build Coastguard Worker   /* elf_begin supports opening archives even with fd == -1 passed.  */
258*7304104dSAndroid Build Coastguard Worker   Elf *member = elf_begin (fd, archive->cmd, archive);
259*7304104dSAndroid Build Coastguard Worker   if (unlikely (member == NULL)) /* Empty archive.  */
260*7304104dSAndroid Build Coastguard Worker     {
261*7304104dSAndroid Build Coastguard Worker       __libdwfl_seterrno (DWFL_E_BADELF);
262*7304104dSAndroid Build Coastguard Worker       return NULL;
263*7304104dSAndroid Build Coastguard Worker     }
264*7304104dSAndroid Build Coastguard Worker 
265*7304104dSAndroid Build Coastguard Worker   while (process_archive_member (dwfl, name, file_name, predicate,
266*7304104dSAndroid Build Coastguard Worker 				 fd, member, &mod) != ELF_C_NULL)
267*7304104dSAndroid Build Coastguard Worker     member = elf_begin (fd, archive->cmd, archive);
268*7304104dSAndroid Build Coastguard Worker 
269*7304104dSAndroid Build Coastguard Worker   /* We can drop the archive Elf handle even if we're still using members
270*7304104dSAndroid Build Coastguard Worker      in live modules.  When the last module's elf_end on a member returns
271*7304104dSAndroid Build Coastguard Worker      zero, that module will close FD.  If no modules survived the predicate,
272*7304104dSAndroid Build Coastguard Worker      we are all done with the file right here.  */
273*7304104dSAndroid Build Coastguard Worker   if (mod != NULL		/* If no modules, caller will clean up.  */
274*7304104dSAndroid Build Coastguard Worker       && elf_end (archive) == 0)
275*7304104dSAndroid Build Coastguard Worker     close (fd);
276*7304104dSAndroid Build Coastguard Worker 
277*7304104dSAndroid Build Coastguard Worker   return mod;
278*7304104dSAndroid Build Coastguard Worker }
279*7304104dSAndroid Build Coastguard Worker 
280*7304104dSAndroid Build Coastguard Worker Dwfl_Module *
281*7304104dSAndroid Build Coastguard Worker internal_function
__libdwfl_report_offline(Dwfl * dwfl,const char * name,const char * file_name,int fd,bool closefd,int (* predicate)(const char * module,const char * file))282*7304104dSAndroid Build Coastguard Worker __libdwfl_report_offline (Dwfl *dwfl, const char *name,
283*7304104dSAndroid Build Coastguard Worker 			  const char *file_name, int fd, bool closefd,
284*7304104dSAndroid Build Coastguard Worker 			  int (*predicate) (const char *module,
285*7304104dSAndroid Build Coastguard Worker 					    const char *file))
286*7304104dSAndroid Build Coastguard Worker {
287*7304104dSAndroid Build Coastguard Worker   Elf *elf;
288*7304104dSAndroid Build Coastguard Worker   Dwfl_Error error = __libdw_open_file (&fd, &elf, closefd, true);
289*7304104dSAndroid Build Coastguard Worker   if (error != DWFL_E_NOERROR)
290*7304104dSAndroid Build Coastguard Worker     {
291*7304104dSAndroid Build Coastguard Worker       __libdwfl_seterrno (error);
292*7304104dSAndroid Build Coastguard Worker       return NULL;
293*7304104dSAndroid Build Coastguard Worker     }
294*7304104dSAndroid Build Coastguard Worker   Dwfl_Module *mod = process_file (dwfl, name, file_name, fd, elf, predicate);
295*7304104dSAndroid Build Coastguard Worker   if (mod == NULL)
296*7304104dSAndroid Build Coastguard Worker     {
297*7304104dSAndroid Build Coastguard Worker       elf_end (elf);
298*7304104dSAndroid Build Coastguard Worker       if (closefd)
299*7304104dSAndroid Build Coastguard Worker 	close (fd);
300*7304104dSAndroid Build Coastguard Worker     }
301*7304104dSAndroid Build Coastguard Worker   return mod;
302*7304104dSAndroid Build Coastguard Worker }
303*7304104dSAndroid Build Coastguard Worker 
304*7304104dSAndroid Build Coastguard Worker Dwfl_Module *
dwfl_report_offline(Dwfl * dwfl,const char * name,const char * file_name,int fd)305*7304104dSAndroid Build Coastguard Worker dwfl_report_offline (Dwfl *dwfl, const char *name,
306*7304104dSAndroid Build Coastguard Worker 		     const char *file_name, int fd)
307*7304104dSAndroid Build Coastguard Worker {
308*7304104dSAndroid Build Coastguard Worker   if (dwfl == NULL)
309*7304104dSAndroid Build Coastguard Worker     return NULL;
310*7304104dSAndroid Build Coastguard Worker 
311*7304104dSAndroid Build Coastguard Worker   bool closefd = false;
312*7304104dSAndroid Build Coastguard Worker   if (fd < 0)
313*7304104dSAndroid Build Coastguard Worker     {
314*7304104dSAndroid Build Coastguard Worker       closefd = true;
315*7304104dSAndroid Build Coastguard Worker       fd = open (file_name, O_RDONLY);
316*7304104dSAndroid Build Coastguard Worker       if (fd < 0)
317*7304104dSAndroid Build Coastguard Worker 	{
318*7304104dSAndroid Build Coastguard Worker 	  __libdwfl_seterrno (DWFL_E_ERRNO);
319*7304104dSAndroid Build Coastguard Worker 	  return NULL;
320*7304104dSAndroid Build Coastguard Worker 	}
321*7304104dSAndroid Build Coastguard Worker     }
322*7304104dSAndroid Build Coastguard Worker 
323*7304104dSAndroid Build Coastguard Worker   return __libdwfl_report_offline (dwfl, name, file_name, fd, closefd, NULL);
324*7304104dSAndroid Build Coastguard Worker }
INTDEF(dwfl_report_offline)325*7304104dSAndroid Build Coastguard Worker INTDEF (dwfl_report_offline)
326*7304104dSAndroid Build Coastguard Worker 
327*7304104dSAndroid Build Coastguard Worker Dwfl_Module *
328*7304104dSAndroid Build Coastguard Worker dwfl_report_offline_memory (Dwfl *dwfl, const char *name,
329*7304104dSAndroid Build Coastguard Worker 			    const char *file_name, char *data, size_t size)
330*7304104dSAndroid Build Coastguard Worker {
331*7304104dSAndroid Build Coastguard Worker   if (dwfl == NULL)
332*7304104dSAndroid Build Coastguard Worker     return NULL;
333*7304104dSAndroid Build Coastguard Worker 
334*7304104dSAndroid Build Coastguard Worker   Elf *elf;
335*7304104dSAndroid Build Coastguard Worker   Dwfl_Error error = __libdw_open_elf_memory (data, size, &elf, true);
336*7304104dSAndroid Build Coastguard Worker   if (error != DWFL_E_NOERROR)
337*7304104dSAndroid Build Coastguard Worker     {
338*7304104dSAndroid Build Coastguard Worker       __libdwfl_seterrno (error);
339*7304104dSAndroid Build Coastguard Worker       return NULL;
340*7304104dSAndroid Build Coastguard Worker     }
341*7304104dSAndroid Build Coastguard Worker   /* It is ok to pass fd == -1 here, because libelf uses it as a value for
342*7304104dSAndroid Build Coastguard Worker      "no file opened" and supports working with files without fd, thanks to
343*7304104dSAndroid Build Coastguard Worker      the existence of the elf_memory function.  */
344*7304104dSAndroid Build Coastguard Worker   Dwfl_Module *mod = process_file (dwfl, name, file_name, -1, elf, NULL);
345*7304104dSAndroid Build Coastguard Worker   if (mod == NULL)
346*7304104dSAndroid Build Coastguard Worker     elf_end (elf);
347*7304104dSAndroid Build Coastguard Worker   return mod;
348*7304104dSAndroid Build Coastguard Worker }
349*7304104dSAndroid Build Coastguard Worker INTDEF (dwfl_report_offline_memory)
350