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