xref: /aosp_15_r20/external/elfutils/libdwfl/core-file.c (revision 7304104da70ce23c86437a01be71edd1a2d7f37e)
1*7304104dSAndroid Build Coastguard Worker /* Core file handling.
2*7304104dSAndroid Build Coastguard Worker    Copyright (C) 2008-2010, 2013, 2015 Red Hat, Inc.
3*7304104dSAndroid Build Coastguard Worker    Copyright (C) 2021 Mark J. Wielaard <[email protected]>
4*7304104dSAndroid Build Coastguard Worker    This file is part of elfutils.
5*7304104dSAndroid Build Coastguard Worker 
6*7304104dSAndroid Build Coastguard Worker    This file is free software; you can redistribute it and/or modify
7*7304104dSAndroid Build Coastguard Worker    it under the terms of either
8*7304104dSAndroid Build Coastguard Worker 
9*7304104dSAndroid Build Coastguard Worker      * the GNU Lesser General Public License as published by the Free
10*7304104dSAndroid Build Coastguard Worker        Software Foundation; either version 3 of the License, or (at
11*7304104dSAndroid Build Coastguard Worker        your option) any later version
12*7304104dSAndroid Build Coastguard Worker 
13*7304104dSAndroid Build Coastguard Worker    or
14*7304104dSAndroid Build Coastguard Worker 
15*7304104dSAndroid Build Coastguard Worker      * the GNU General Public License as published by the Free
16*7304104dSAndroid Build Coastguard Worker        Software Foundation; either version 2 of the License, or (at
17*7304104dSAndroid Build Coastguard Worker        your option) any later version
18*7304104dSAndroid Build Coastguard Worker 
19*7304104dSAndroid Build Coastguard Worker    or both in parallel, as here.
20*7304104dSAndroid Build Coastguard Worker 
21*7304104dSAndroid Build Coastguard Worker    elfutils is distributed in the hope that it will be useful, but
22*7304104dSAndroid Build Coastguard Worker    WITHOUT ANY WARRANTY; without even the implied warranty of
23*7304104dSAndroid Build Coastguard Worker    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24*7304104dSAndroid Build Coastguard Worker    General Public License for more details.
25*7304104dSAndroid Build Coastguard Worker 
26*7304104dSAndroid Build Coastguard Worker    You should have received copies of the GNU General Public License and
27*7304104dSAndroid Build Coastguard Worker    the GNU Lesser General Public License along with this program.  If
28*7304104dSAndroid Build Coastguard Worker    not, see <http://www.gnu.org/licenses/>.  */
29*7304104dSAndroid Build Coastguard Worker 
30*7304104dSAndroid Build Coastguard Worker #include <config.h>
31*7304104dSAndroid Build Coastguard Worker #include "libelfP.h"	/* For NOTE_ALIGN.  */
32*7304104dSAndroid Build Coastguard Worker #include "libdwflP.h"
33*7304104dSAndroid Build Coastguard Worker #include <gelf.h>
34*7304104dSAndroid Build Coastguard Worker 
35*7304104dSAndroid Build Coastguard Worker /* On failure return, we update *NEXT to point back at OFFSET.  */
36*7304104dSAndroid Build Coastguard Worker static inline Elf *
do_fail(int error,off_t * next,off_t offset)37*7304104dSAndroid Build Coastguard Worker do_fail (int error, off_t *next, off_t offset)
38*7304104dSAndroid Build Coastguard Worker {
39*7304104dSAndroid Build Coastguard Worker     if (next != NULL)
40*7304104dSAndroid Build Coastguard Worker       *next = offset;
41*7304104dSAndroid Build Coastguard Worker     //__libelf_seterrno (error);
42*7304104dSAndroid Build Coastguard Worker     __libdwfl_seterrno (DWFL_E (LIBELF, error));
43*7304104dSAndroid Build Coastguard Worker     return NULL;
44*7304104dSAndroid Build Coastguard Worker }
45*7304104dSAndroid Build Coastguard Worker 
46*7304104dSAndroid Build Coastguard Worker #define fail(error) do_fail (error, next, offset)
47*7304104dSAndroid Build Coastguard Worker 
48*7304104dSAndroid Build Coastguard Worker /* This is a prototype of what a new libelf interface might be.
49*7304104dSAndroid Build Coastguard Worker    This implementation is pessimal for non-mmap cases and should
50*7304104dSAndroid Build Coastguard Worker    be replaced by more diddling inside libelf internals.  */
51*7304104dSAndroid Build Coastguard Worker static Elf *
elf_begin_rand(Elf * parent,off_t offset,off_t size,off_t * next)52*7304104dSAndroid Build Coastguard Worker elf_begin_rand (Elf *parent, off_t offset, off_t size, off_t *next)
53*7304104dSAndroid Build Coastguard Worker {
54*7304104dSAndroid Build Coastguard Worker   if (parent == NULL)
55*7304104dSAndroid Build Coastguard Worker     return NULL;
56*7304104dSAndroid Build Coastguard Worker 
57*7304104dSAndroid Build Coastguard Worker   off_t min = (parent->kind == ELF_K_ELF ?
58*7304104dSAndroid Build Coastguard Worker 		(parent->class == ELFCLASS32
59*7304104dSAndroid Build Coastguard Worker 		 ? sizeof (Elf32_Ehdr) : sizeof (Elf64_Ehdr))
60*7304104dSAndroid Build Coastguard Worker 		: parent->kind == ELF_K_AR ? SARMAG
61*7304104dSAndroid Build Coastguard Worker 		: 0);
62*7304104dSAndroid Build Coastguard Worker 
63*7304104dSAndroid Build Coastguard Worker   if (unlikely (offset < min)
64*7304104dSAndroid Build Coastguard Worker       || unlikely (offset >= (off_t) parent->maximum_size))
65*7304104dSAndroid Build Coastguard Worker     return fail (ELF_E_RANGE);
66*7304104dSAndroid Build Coastguard Worker 
67*7304104dSAndroid Build Coastguard Worker   /* For an archive, fetch just the size field
68*7304104dSAndroid Build Coastguard Worker      from the archive header to override SIZE.  */
69*7304104dSAndroid Build Coastguard Worker   if (parent->kind == ELF_K_AR)
70*7304104dSAndroid Build Coastguard Worker     {
71*7304104dSAndroid Build Coastguard Worker       /* File size, in ASCII decimal, right-padded with ASCII spaces.
72*7304104dSAndroid Build Coastguard Worker          Max 10 characters. Not zero terminated. So make this ar_size
73*7304104dSAndroid Build Coastguard Worker          array one larger and explicitly zero terminate it.  As needed
74*7304104dSAndroid Build Coastguard Worker          for strtoll.  */
75*7304104dSAndroid Build Coastguard Worker       #define AR_SIZE_CHARS 10
76*7304104dSAndroid Build Coastguard Worker       char ar_size[AR_SIZE_CHARS + 1];
77*7304104dSAndroid Build Coastguard Worker       ar_size[AR_SIZE_CHARS] = '\0';
78*7304104dSAndroid Build Coastguard Worker 
79*7304104dSAndroid Build Coastguard Worker       if (unlikely (parent->maximum_size - offset < sizeof (struct ar_hdr)))
80*7304104dSAndroid Build Coastguard Worker 	return fail (ELF_E_RANGE);
81*7304104dSAndroid Build Coastguard Worker 
82*7304104dSAndroid Build Coastguard Worker       if (parent->map_address != NULL)
83*7304104dSAndroid Build Coastguard Worker 	memcpy (ar_size, parent->map_address + parent->start_offset + offset,
84*7304104dSAndroid Build Coastguard Worker 		AR_SIZE_CHARS);
85*7304104dSAndroid Build Coastguard Worker       else if (unlikely (pread_retry (parent->fildes,
86*7304104dSAndroid Build Coastguard Worker 				      ar_size, AR_SIZE_CHARS,
87*7304104dSAndroid Build Coastguard Worker 				      parent->start_offset + offset
88*7304104dSAndroid Build Coastguard Worker 				      + offsetof (struct ar_hdr, ar_size))
89*7304104dSAndroid Build Coastguard Worker 			 != AR_SIZE_CHARS))
90*7304104dSAndroid Build Coastguard Worker 	return fail (ELF_E_READ_ERROR);
91*7304104dSAndroid Build Coastguard Worker 
92*7304104dSAndroid Build Coastguard Worker       offset += sizeof (struct ar_hdr);
93*7304104dSAndroid Build Coastguard Worker 
94*7304104dSAndroid Build Coastguard Worker       char *endp;
95*7304104dSAndroid Build Coastguard Worker       size = strtoll (ar_size, &endp, 10);
96*7304104dSAndroid Build Coastguard Worker       if (unlikely (endp == ar_size)
97*7304104dSAndroid Build Coastguard Worker 	  || unlikely ((off_t) parent->maximum_size - offset < size))
98*7304104dSAndroid Build Coastguard Worker 	return fail (ELF_E_INVALID_ARCHIVE);
99*7304104dSAndroid Build Coastguard Worker     }
100*7304104dSAndroid Build Coastguard Worker 
101*7304104dSAndroid Build Coastguard Worker   if (unlikely ((off_t) parent->maximum_size - offset < size))
102*7304104dSAndroid Build Coastguard Worker     return fail (ELF_E_RANGE);
103*7304104dSAndroid Build Coastguard Worker 
104*7304104dSAndroid Build Coastguard Worker   /* Even if we fail at this point, update *NEXT to point past the file.  */
105*7304104dSAndroid Build Coastguard Worker   if (next != NULL)
106*7304104dSAndroid Build Coastguard Worker     *next = offset + size;
107*7304104dSAndroid Build Coastguard Worker 
108*7304104dSAndroid Build Coastguard Worker   if (unlikely (offset == 0)
109*7304104dSAndroid Build Coastguard Worker       && unlikely (size == (off_t) parent->maximum_size))
110*7304104dSAndroid Build Coastguard Worker     return elf_clone (parent, parent->cmd);
111*7304104dSAndroid Build Coastguard Worker 
112*7304104dSAndroid Build Coastguard Worker   /* Note the image is guaranteed live only as long as PARENT
113*7304104dSAndroid Build Coastguard Worker      lives.  Using elf_memory is quite suboptimal if the whole
114*7304104dSAndroid Build Coastguard Worker      file is not mmap'd.  We really should have something like
115*7304104dSAndroid Build Coastguard Worker      a generalization of the archive support.  */
116*7304104dSAndroid Build Coastguard Worker   Elf_Data *data = elf_getdata_rawchunk (parent, offset, size, ELF_T_BYTE);
117*7304104dSAndroid Build Coastguard Worker   if (data == NULL)
118*7304104dSAndroid Build Coastguard Worker     return NULL;
119*7304104dSAndroid Build Coastguard Worker   assert ((off_t) data->d_size == size);
120*7304104dSAndroid Build Coastguard Worker   return elf_memory (data->d_buf, size);
121*7304104dSAndroid Build Coastguard Worker }
122*7304104dSAndroid Build Coastguard Worker 
123*7304104dSAndroid Build Coastguard Worker 
124*7304104dSAndroid Build Coastguard Worker int
dwfl_report_core_segments(Dwfl * dwfl,Elf * elf,size_t phnum,GElf_Phdr * notes)125*7304104dSAndroid Build Coastguard Worker dwfl_report_core_segments (Dwfl *dwfl, Elf *elf, size_t phnum, GElf_Phdr *notes)
126*7304104dSAndroid Build Coastguard Worker {
127*7304104dSAndroid Build Coastguard Worker   if (unlikely (dwfl == NULL))
128*7304104dSAndroid Build Coastguard Worker     return -1;
129*7304104dSAndroid Build Coastguard Worker 
130*7304104dSAndroid Build Coastguard Worker   int result = 0;
131*7304104dSAndroid Build Coastguard Worker 
132*7304104dSAndroid Build Coastguard Worker   if (notes != NULL)
133*7304104dSAndroid Build Coastguard Worker     notes->p_type = PT_NULL;
134*7304104dSAndroid Build Coastguard Worker 
135*7304104dSAndroid Build Coastguard Worker   for (size_t ndx = 0; result >= 0 && ndx < phnum; ++ndx)
136*7304104dSAndroid Build Coastguard Worker     {
137*7304104dSAndroid Build Coastguard Worker       GElf_Phdr phdr_mem;
138*7304104dSAndroid Build Coastguard Worker       GElf_Phdr *phdr = gelf_getphdr (elf, ndx, &phdr_mem);
139*7304104dSAndroid Build Coastguard Worker       if (unlikely (phdr == NULL))
140*7304104dSAndroid Build Coastguard Worker 	{
141*7304104dSAndroid Build Coastguard Worker 	  __libdwfl_seterrno (DWFL_E_LIBELF);
142*7304104dSAndroid Build Coastguard Worker 	  return -1;
143*7304104dSAndroid Build Coastguard Worker 	}
144*7304104dSAndroid Build Coastguard Worker       switch (phdr->p_type)
145*7304104dSAndroid Build Coastguard Worker 	{
146*7304104dSAndroid Build Coastguard Worker 	case PT_LOAD:
147*7304104dSAndroid Build Coastguard Worker 	  result = dwfl_report_segment (dwfl, ndx, phdr, 0, NULL);
148*7304104dSAndroid Build Coastguard Worker 	  break;
149*7304104dSAndroid Build Coastguard Worker 
150*7304104dSAndroid Build Coastguard Worker 	case PT_NOTE:
151*7304104dSAndroid Build Coastguard Worker 	  if (notes != NULL)
152*7304104dSAndroid Build Coastguard Worker 	    {
153*7304104dSAndroid Build Coastguard Worker 	      *notes = *phdr;
154*7304104dSAndroid Build Coastguard Worker 	      notes = NULL;
155*7304104dSAndroid Build Coastguard Worker 	    }
156*7304104dSAndroid Build Coastguard Worker 	  break;
157*7304104dSAndroid Build Coastguard Worker 	}
158*7304104dSAndroid Build Coastguard Worker     }
159*7304104dSAndroid Build Coastguard Worker 
160*7304104dSAndroid Build Coastguard Worker   return result;
161*7304104dSAndroid Build Coastguard Worker }
162*7304104dSAndroid Build Coastguard Worker 
163*7304104dSAndroid Build Coastguard Worker /* Never read more than this much without mmap.  */
164*7304104dSAndroid Build Coastguard Worker #define MAX_EAGER_COST	8192
165*7304104dSAndroid Build Coastguard Worker 
166*7304104dSAndroid Build Coastguard Worker /* Dwfl_Module_Callback passed to and called by dwfl_segment_report_module
167*7304104dSAndroid Build Coastguard Worker    to read in a segment as ELF image directly if possible or indicate an
168*7304104dSAndroid Build Coastguard Worker    attempt must be made to read in the while segment right now.  */
169*7304104dSAndroid Build Coastguard Worker static bool
core_file_read_eagerly(Dwfl_Module * mod,void ** userdata,const char * name,Dwarf_Addr start,void ** buffer,size_t * buffer_available,GElf_Off cost,GElf_Off worthwhile,GElf_Off whole,GElf_Off contiguous,void * arg,Elf ** elfp)170*7304104dSAndroid Build Coastguard Worker core_file_read_eagerly (Dwfl_Module *mod,
171*7304104dSAndroid Build Coastguard Worker 			void **userdata __attribute__ ((unused)),
172*7304104dSAndroid Build Coastguard Worker 			const char *name __attribute__ ((unused)),
173*7304104dSAndroid Build Coastguard Worker 			Dwarf_Addr start __attribute__ ((unused)),
174*7304104dSAndroid Build Coastguard Worker 			void **buffer, size_t *buffer_available,
175*7304104dSAndroid Build Coastguard Worker 			GElf_Off cost, GElf_Off worthwhile,
176*7304104dSAndroid Build Coastguard Worker 			GElf_Off whole,
177*7304104dSAndroid Build Coastguard Worker 			GElf_Off contiguous __attribute__ ((unused)),
178*7304104dSAndroid Build Coastguard Worker 			void *arg, Elf **elfp)
179*7304104dSAndroid Build Coastguard Worker {
180*7304104dSAndroid Build Coastguard Worker   Elf *core = arg;
181*7304104dSAndroid Build Coastguard Worker 
182*7304104dSAndroid Build Coastguard Worker   /* The available buffer is often the whole segment when the core file
183*7304104dSAndroid Build Coastguard Worker      was mmap'd if used together with the dwfl_elf_phdr_memory_callback.
184*7304104dSAndroid Build Coastguard Worker      Which means that if it is complete we can just construct the whole
185*7304104dSAndroid Build Coastguard Worker      ELF image right now without having to read in anything more.  */
186*7304104dSAndroid Build Coastguard Worker   if (whole <= *buffer_available)
187*7304104dSAndroid Build Coastguard Worker     {
188*7304104dSAndroid Build Coastguard Worker       /* All there ever was, we already have on hand.  */
189*7304104dSAndroid Build Coastguard Worker 
190*7304104dSAndroid Build Coastguard Worker       if (core->map_address == NULL)
191*7304104dSAndroid Build Coastguard Worker 	{
192*7304104dSAndroid Build Coastguard Worker 	  /* We already malloc'd the buffer.  */
193*7304104dSAndroid Build Coastguard Worker 	  *elfp = elf_memory (*buffer, whole);
194*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (*elfp == NULL))
195*7304104dSAndroid Build Coastguard Worker 	    return false;
196*7304104dSAndroid Build Coastguard Worker 
197*7304104dSAndroid Build Coastguard Worker 	  (*elfp)->flags |= ELF_F_MALLOCED;
198*7304104dSAndroid Build Coastguard Worker 	  *buffer = NULL;
199*7304104dSAndroid Build Coastguard Worker 	  *buffer_available = 0;
200*7304104dSAndroid Build Coastguard Worker 	  return true;
201*7304104dSAndroid Build Coastguard Worker 	}
202*7304104dSAndroid Build Coastguard Worker 
203*7304104dSAndroid Build Coastguard Worker       /* We can use the image inside the core file directly.  */
204*7304104dSAndroid Build Coastguard Worker       *elfp = elf_begin_rand (core, *buffer - core->map_address, whole, NULL);
205*7304104dSAndroid Build Coastguard Worker       *buffer = NULL;
206*7304104dSAndroid Build Coastguard Worker       *buffer_available = 0;
207*7304104dSAndroid Build Coastguard Worker       return *elfp != NULL;
208*7304104dSAndroid Build Coastguard Worker     }
209*7304104dSAndroid Build Coastguard Worker 
210*7304104dSAndroid Build Coastguard Worker   /* We don't have the whole file.  Which either means the core file
211*7304104dSAndroid Build Coastguard Worker      wasn't mmap'd, but needs to still be read in, or that the segment
212*7304104dSAndroid Build Coastguard Worker      is truncated.  Figure out if this is better than nothing.  */
213*7304104dSAndroid Build Coastguard Worker 
214*7304104dSAndroid Build Coastguard Worker   if (worthwhile == 0)
215*7304104dSAndroid Build Coastguard Worker     /* Caller doesn't think so.  */
216*7304104dSAndroid Build Coastguard Worker     return false;
217*7304104dSAndroid Build Coastguard Worker 
218*7304104dSAndroid Build Coastguard Worker   /*
219*7304104dSAndroid Build Coastguard Worker     XXX would like to fall back to partial file via memory
220*7304104dSAndroid Build Coastguard Worker     when build id find_elf fails
221*7304104dSAndroid Build Coastguard Worker     also, link_map name may give file name from disk better than partial here
222*7304104dSAndroid Build Coastguard Worker     requires find_elf hook re-doing the magic to fall back if no file found
223*7304104dSAndroid Build Coastguard Worker   */
224*7304104dSAndroid Build Coastguard Worker 
225*7304104dSAndroid Build Coastguard Worker   if (whole > MAX_EAGER_COST && mod->build_id_len > 0)
226*7304104dSAndroid Build Coastguard Worker     /* We can't cheaply read the whole file here, so we'd
227*7304104dSAndroid Build Coastguard Worker        be using a partial file.  But there is a build ID that could
228*7304104dSAndroid Build Coastguard Worker        help us find the whole file, which might be more useful than
229*7304104dSAndroid Build Coastguard Worker        what we have.  We'll just rely on that.  */
230*7304104dSAndroid Build Coastguard Worker     return false;
231*7304104dSAndroid Build Coastguard Worker 
232*7304104dSAndroid Build Coastguard Worker   /* The file is either small (most likely the vdso) or big and incomplete,
233*7304104dSAndroid Build Coastguard Worker      but we don't have a build-id.  */
234*7304104dSAndroid Build Coastguard Worker 
235*7304104dSAndroid Build Coastguard Worker   if (core->map_address != NULL)
236*7304104dSAndroid Build Coastguard Worker     /* It's cheap to get, so get it.  */
237*7304104dSAndroid Build Coastguard Worker     return true;
238*7304104dSAndroid Build Coastguard Worker 
239*7304104dSAndroid Build Coastguard Worker   /* Only use it if there isn't too much to be read.  */
240*7304104dSAndroid Build Coastguard Worker   return cost <= MAX_EAGER_COST;
241*7304104dSAndroid Build Coastguard Worker }
242*7304104dSAndroid Build Coastguard Worker 
243*7304104dSAndroid Build Coastguard Worker static inline void
update_end(GElf_Phdr * pphdr,const GElf_Off align,GElf_Off * pend,GElf_Addr * pend_vaddr)244*7304104dSAndroid Build Coastguard Worker update_end (GElf_Phdr *pphdr, const GElf_Off align,
245*7304104dSAndroid Build Coastguard Worker             GElf_Off *pend, GElf_Addr *pend_vaddr)
246*7304104dSAndroid Build Coastguard Worker {
247*7304104dSAndroid Build Coastguard Worker   *pend = (pphdr->p_offset + pphdr->p_filesz + align - 1) & -align;
248*7304104dSAndroid Build Coastguard Worker   *pend_vaddr = (pphdr->p_vaddr + pphdr->p_memsz + align - 1) & -align;
249*7304104dSAndroid Build Coastguard Worker }
250*7304104dSAndroid Build Coastguard Worker 
251*7304104dSAndroid Build Coastguard Worker /* Use following contiguous segments to get towards SIZE.  */
252*7304104dSAndroid Build Coastguard Worker static inline bool
do_more(size_t size,GElf_Phdr * pphdr,const GElf_Off align,Elf * elf,GElf_Off start,int * pndx,GElf_Off * pend,GElf_Addr * pend_vaddr)253*7304104dSAndroid Build Coastguard Worker do_more (size_t size, GElf_Phdr *pphdr, const GElf_Off align,
254*7304104dSAndroid Build Coastguard Worker          Elf *elf, GElf_Off start, int *pndx,
255*7304104dSAndroid Build Coastguard Worker          GElf_Off *pend, GElf_Addr *pend_vaddr)
256*7304104dSAndroid Build Coastguard Worker {
257*7304104dSAndroid Build Coastguard Worker   while (*pend <= start || *pend - start < size)
258*7304104dSAndroid Build Coastguard Worker     {
259*7304104dSAndroid Build Coastguard Worker       if (pphdr->p_filesz < pphdr->p_memsz)
260*7304104dSAndroid Build Coastguard Worker 	/* This segment is truncated, so no following one helps us.  */
261*7304104dSAndroid Build Coastguard Worker 	return false;
262*7304104dSAndroid Build Coastguard Worker 
263*7304104dSAndroid Build Coastguard Worker       if (unlikely (gelf_getphdr (elf, (*pndx)++, pphdr) == NULL))
264*7304104dSAndroid Build Coastguard Worker 	return false;
265*7304104dSAndroid Build Coastguard Worker 
266*7304104dSAndroid Build Coastguard Worker       if (pphdr->p_type == PT_LOAD)
267*7304104dSAndroid Build Coastguard Worker 	{
268*7304104dSAndroid Build Coastguard Worker 	  if (pphdr->p_offset > *pend
269*7304104dSAndroid Build Coastguard Worker 	      || pphdr->p_vaddr > *pend_vaddr)
270*7304104dSAndroid Build Coastguard Worker 	    /* It's discontiguous!  */
271*7304104dSAndroid Build Coastguard Worker 	    return false;
272*7304104dSAndroid Build Coastguard Worker 
273*7304104dSAndroid Build Coastguard Worker 	  update_end (pphdr, align, pend, pend_vaddr);
274*7304104dSAndroid Build Coastguard Worker 	}
275*7304104dSAndroid Build Coastguard Worker     }
276*7304104dSAndroid Build Coastguard Worker   return true;
277*7304104dSAndroid Build Coastguard Worker }
278*7304104dSAndroid Build Coastguard Worker 
279*7304104dSAndroid Build Coastguard Worker #define more(size) do_more (size, &phdr, align, elf, start, &ndx, &end, &end_vaddr)
280*7304104dSAndroid Build Coastguard Worker 
281*7304104dSAndroid Build Coastguard Worker bool
dwfl_elf_phdr_memory_callback(Dwfl * dwfl,int ndx,void ** buffer,size_t * buffer_available,GElf_Addr vaddr,size_t minread,void * arg)282*7304104dSAndroid Build Coastguard Worker dwfl_elf_phdr_memory_callback (Dwfl *dwfl, int ndx,
283*7304104dSAndroid Build Coastguard Worker 			       void **buffer, size_t *buffer_available,
284*7304104dSAndroid Build Coastguard Worker 			       GElf_Addr vaddr,
285*7304104dSAndroid Build Coastguard Worker 			       size_t minread,
286*7304104dSAndroid Build Coastguard Worker 			       void *arg)
287*7304104dSAndroid Build Coastguard Worker {
288*7304104dSAndroid Build Coastguard Worker   Elf *elf = arg;
289*7304104dSAndroid Build Coastguard Worker 
290*7304104dSAndroid Build Coastguard Worker   if (ndx == -1)
291*7304104dSAndroid Build Coastguard Worker     {
292*7304104dSAndroid Build Coastguard Worker       /* Called for cleanup.  */
293*7304104dSAndroid Build Coastguard Worker       if (elf->map_address == NULL)
294*7304104dSAndroid Build Coastguard Worker 	free (*buffer);
295*7304104dSAndroid Build Coastguard Worker       *buffer = NULL;
296*7304104dSAndroid Build Coastguard Worker       *buffer_available = 0;
297*7304104dSAndroid Build Coastguard Worker       return false;
298*7304104dSAndroid Build Coastguard Worker     }
299*7304104dSAndroid Build Coastguard Worker 
300*7304104dSAndroid Build Coastguard Worker   const GElf_Off align = dwfl->segment_align ?: 1;
301*7304104dSAndroid Build Coastguard Worker   GElf_Phdr phdr;
302*7304104dSAndroid Build Coastguard Worker 
303*7304104dSAndroid Build Coastguard Worker   do
304*7304104dSAndroid Build Coastguard Worker     if (unlikely (gelf_getphdr (elf, ndx++, &phdr) == NULL))
305*7304104dSAndroid Build Coastguard Worker       return false;
306*7304104dSAndroid Build Coastguard Worker   while (phdr.p_type != PT_LOAD
307*7304104dSAndroid Build Coastguard Worker 	 || ((phdr.p_vaddr + phdr.p_memsz + align - 1) & -align) <= vaddr);
308*7304104dSAndroid Build Coastguard Worker 
309*7304104dSAndroid Build Coastguard Worker   GElf_Off start = vaddr - phdr.p_vaddr + phdr.p_offset;
310*7304104dSAndroid Build Coastguard Worker   GElf_Off end;
311*7304104dSAndroid Build Coastguard Worker   GElf_Addr end_vaddr;
312*7304104dSAndroid Build Coastguard Worker 
313*7304104dSAndroid Build Coastguard Worker   update_end (&phdr, align, &end, &end_vaddr);
314*7304104dSAndroid Build Coastguard Worker 
315*7304104dSAndroid Build Coastguard Worker   /* We need at least this much.  */
316*7304104dSAndroid Build Coastguard Worker   if (! more (minread))
317*7304104dSAndroid Build Coastguard Worker     return false;
318*7304104dSAndroid Build Coastguard Worker 
319*7304104dSAndroid Build Coastguard Worker   /* See how much more we can get of what the caller wants.  */
320*7304104dSAndroid Build Coastguard Worker   (void) more (*buffer_available);
321*7304104dSAndroid Build Coastguard Worker 
322*7304104dSAndroid Build Coastguard Worker   /* If it's already on hand anyway, use as much as there is.  */
323*7304104dSAndroid Build Coastguard Worker   if (elf->map_address != NULL && start < elf->maximum_size)
324*7304104dSAndroid Build Coastguard Worker     (void) more (elf->maximum_size - start);
325*7304104dSAndroid Build Coastguard Worker 
326*7304104dSAndroid Build Coastguard Worker   /* Make sure we don't look past the end of the actual file,
327*7304104dSAndroid Build Coastguard Worker      even if the headers tell us to.  */
328*7304104dSAndroid Build Coastguard Worker   if (unlikely (end > elf->maximum_size))
329*7304104dSAndroid Build Coastguard Worker     end = elf->maximum_size;
330*7304104dSAndroid Build Coastguard Worker 
331*7304104dSAndroid Build Coastguard Worker   /* If the file is too small, there is nothing at all to get.  */
332*7304104dSAndroid Build Coastguard Worker   if (unlikely (start >= end))
333*7304104dSAndroid Build Coastguard Worker     return false;
334*7304104dSAndroid Build Coastguard Worker 
335*7304104dSAndroid Build Coastguard Worker   if (end - start < minread)
336*7304104dSAndroid Build Coastguard Worker     return false;
337*7304104dSAndroid Build Coastguard Worker 
338*7304104dSAndroid Build Coastguard Worker   if (elf->map_address != NULL)
339*7304104dSAndroid Build Coastguard Worker     {
340*7304104dSAndroid Build Coastguard Worker       void *contents = elf->map_address + elf->start_offset + start;
341*7304104dSAndroid Build Coastguard Worker       size_t size = end - start;
342*7304104dSAndroid Build Coastguard Worker 
343*7304104dSAndroid Build Coastguard Worker       if (minread == 0)		/* String mode.  */
344*7304104dSAndroid Build Coastguard Worker 	{
345*7304104dSAndroid Build Coastguard Worker 	  const void *eos = memchr (contents, '\0', size);
346*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (eos == NULL) || unlikely (eos == contents))
347*7304104dSAndroid Build Coastguard Worker 	    return false;
348*7304104dSAndroid Build Coastguard Worker 	  size = eos + 1 - contents;
349*7304104dSAndroid Build Coastguard Worker 	}
350*7304104dSAndroid Build Coastguard Worker 
351*7304104dSAndroid Build Coastguard Worker       if (*buffer == NULL)
352*7304104dSAndroid Build Coastguard Worker 	{
353*7304104dSAndroid Build Coastguard Worker 	  *buffer = contents;
354*7304104dSAndroid Build Coastguard Worker 	  *buffer_available = size;
355*7304104dSAndroid Build Coastguard Worker 	}
356*7304104dSAndroid Build Coastguard Worker       else
357*7304104dSAndroid Build Coastguard Worker 	{
358*7304104dSAndroid Build Coastguard Worker 	  *buffer_available = MIN (size, *buffer_available);
359*7304104dSAndroid Build Coastguard Worker 	  memcpy (*buffer, contents, *buffer_available);
360*7304104dSAndroid Build Coastguard Worker 	}
361*7304104dSAndroid Build Coastguard Worker     }
362*7304104dSAndroid Build Coastguard Worker   else
363*7304104dSAndroid Build Coastguard Worker     {
364*7304104dSAndroid Build Coastguard Worker       void *into = *buffer;
365*7304104dSAndroid Build Coastguard Worker       if (*buffer == NULL)
366*7304104dSAndroid Build Coastguard Worker 	{
367*7304104dSAndroid Build Coastguard Worker 	  *buffer_available = MIN (minread ?: 512,
368*7304104dSAndroid Build Coastguard Worker 				   MAX (4096, MIN (end - start,
369*7304104dSAndroid Build Coastguard Worker 						   *buffer_available)));
370*7304104dSAndroid Build Coastguard Worker 	  into = malloc (*buffer_available);
371*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (into == NULL))
372*7304104dSAndroid Build Coastguard Worker 	    {
373*7304104dSAndroid Build Coastguard Worker 	      __libdwfl_seterrno (DWFL_E_NOMEM);
374*7304104dSAndroid Build Coastguard Worker 	      return false;
375*7304104dSAndroid Build Coastguard Worker 	    }
376*7304104dSAndroid Build Coastguard Worker 	}
377*7304104dSAndroid Build Coastguard Worker 
378*7304104dSAndroid Build Coastguard Worker       ssize_t nread = pread_retry (elf->fildes, into, *buffer_available, start);
379*7304104dSAndroid Build Coastguard Worker       if (nread < (ssize_t) minread)
380*7304104dSAndroid Build Coastguard Worker 	{
381*7304104dSAndroid Build Coastguard Worker 	  if (into != *buffer)
382*7304104dSAndroid Build Coastguard Worker 	    free (into);
383*7304104dSAndroid Build Coastguard Worker 	  if (nread < 0)
384*7304104dSAndroid Build Coastguard Worker 	    __libdwfl_seterrno (DWFL_E_ERRNO);
385*7304104dSAndroid Build Coastguard Worker 	  return false;
386*7304104dSAndroid Build Coastguard Worker 	}
387*7304104dSAndroid Build Coastguard Worker 
388*7304104dSAndroid Build Coastguard Worker       if (minread == 0)		/* String mode.  */
389*7304104dSAndroid Build Coastguard Worker 	{
390*7304104dSAndroid Build Coastguard Worker 	  const void *eos = memchr (into, '\0', nread);
391*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (eos == NULL) || unlikely (eos == into))
392*7304104dSAndroid Build Coastguard Worker 	    {
393*7304104dSAndroid Build Coastguard Worker 	      if (*buffer == NULL)
394*7304104dSAndroid Build Coastguard Worker 		free (into);
395*7304104dSAndroid Build Coastguard Worker 	      return false;
396*7304104dSAndroid Build Coastguard Worker 	    }
397*7304104dSAndroid Build Coastguard Worker 	  nread = eos + 1 - into;
398*7304104dSAndroid Build Coastguard Worker 	}
399*7304104dSAndroid Build Coastguard Worker 
400*7304104dSAndroid Build Coastguard Worker       if (*buffer == NULL)
401*7304104dSAndroid Build Coastguard Worker 	*buffer = into;
402*7304104dSAndroid Build Coastguard Worker       *buffer_available = nread;
403*7304104dSAndroid Build Coastguard Worker     }
404*7304104dSAndroid Build Coastguard Worker 
405*7304104dSAndroid Build Coastguard Worker   return true;
406*7304104dSAndroid Build Coastguard Worker }
407*7304104dSAndroid Build Coastguard Worker 
408*7304104dSAndroid Build Coastguard Worker /* Free the contents of R_DEBUG_INFO without the R_DEBUG_INFO memory itself.  */
409*7304104dSAndroid Build Coastguard Worker 
410*7304104dSAndroid Build Coastguard Worker static void
clear_r_debug_info(struct r_debug_info * r_debug_info)411*7304104dSAndroid Build Coastguard Worker clear_r_debug_info (struct r_debug_info *r_debug_info)
412*7304104dSAndroid Build Coastguard Worker {
413*7304104dSAndroid Build Coastguard Worker   while (r_debug_info->module != NULL)
414*7304104dSAndroid Build Coastguard Worker     {
415*7304104dSAndroid Build Coastguard Worker       struct r_debug_info_module *module = r_debug_info->module;
416*7304104dSAndroid Build Coastguard Worker       r_debug_info->module = module->next;
417*7304104dSAndroid Build Coastguard Worker       elf_end (module->elf);
418*7304104dSAndroid Build Coastguard Worker       if (module->fd != -1)
419*7304104dSAndroid Build Coastguard Worker 	close (module->fd);
420*7304104dSAndroid Build Coastguard Worker       free (module);
421*7304104dSAndroid Build Coastguard Worker     }
422*7304104dSAndroid Build Coastguard Worker }
423*7304104dSAndroid Build Coastguard Worker 
424*7304104dSAndroid Build Coastguard Worker bool
425*7304104dSAndroid Build Coastguard Worker internal_function
__libdwfl_dynamic_vaddr_get(Elf * elf,GElf_Addr * vaddrp)426*7304104dSAndroid Build Coastguard Worker __libdwfl_dynamic_vaddr_get (Elf *elf, GElf_Addr *vaddrp)
427*7304104dSAndroid Build Coastguard Worker {
428*7304104dSAndroid Build Coastguard Worker   size_t phnum;
429*7304104dSAndroid Build Coastguard Worker   if (unlikely (elf_getphdrnum (elf, &phnum) != 0))
430*7304104dSAndroid Build Coastguard Worker     return false;
431*7304104dSAndroid Build Coastguard Worker   for (size_t i = 0; i < phnum; ++i)
432*7304104dSAndroid Build Coastguard Worker     {
433*7304104dSAndroid Build Coastguard Worker       GElf_Phdr phdr_mem;
434*7304104dSAndroid Build Coastguard Worker       GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem);
435*7304104dSAndroid Build Coastguard Worker       if (unlikely (phdr == NULL))
436*7304104dSAndroid Build Coastguard Worker 	return false;
437*7304104dSAndroid Build Coastguard Worker       if (phdr->p_type == PT_DYNAMIC)
438*7304104dSAndroid Build Coastguard Worker 	{
439*7304104dSAndroid Build Coastguard Worker 	  *vaddrp = phdr->p_vaddr;
440*7304104dSAndroid Build Coastguard Worker 	  return true;
441*7304104dSAndroid Build Coastguard Worker 	}
442*7304104dSAndroid Build Coastguard Worker     }
443*7304104dSAndroid Build Coastguard Worker   return false;
444*7304104dSAndroid Build Coastguard Worker }
445*7304104dSAndroid Build Coastguard Worker 
446*7304104dSAndroid Build Coastguard Worker NEW_VERSION (dwfl_core_file_report, ELFUTILS_0.158)
447*7304104dSAndroid Build Coastguard Worker int
dwfl_core_file_report(Dwfl * dwfl,Elf * elf,const char * executable)448*7304104dSAndroid Build Coastguard Worker dwfl_core_file_report (Dwfl *dwfl, Elf *elf, const char *executable)
449*7304104dSAndroid Build Coastguard Worker {
450*7304104dSAndroid Build Coastguard Worker   size_t phnum;
451*7304104dSAndroid Build Coastguard Worker   if (unlikely (elf_getphdrnum (elf, &phnum) != 0))
452*7304104dSAndroid Build Coastguard Worker     {
453*7304104dSAndroid Build Coastguard Worker       __libdwfl_seterrno (DWFL_E_LIBELF);
454*7304104dSAndroid Build Coastguard Worker       return -1;
455*7304104dSAndroid Build Coastguard Worker     }
456*7304104dSAndroid Build Coastguard Worker 
457*7304104dSAndroid Build Coastguard Worker   bool cleanup_user_core = false;
458*7304104dSAndroid Build Coastguard Worker   if (dwfl->user_core != NULL)
459*7304104dSAndroid Build Coastguard Worker     free (dwfl->user_core->executable_for_core);
460*7304104dSAndroid Build Coastguard Worker   if (executable == NULL)
461*7304104dSAndroid Build Coastguard Worker     {
462*7304104dSAndroid Build Coastguard Worker       if (dwfl->user_core != NULL)
463*7304104dSAndroid Build Coastguard Worker 	dwfl->user_core->executable_for_core = NULL;
464*7304104dSAndroid Build Coastguard Worker     }
465*7304104dSAndroid Build Coastguard Worker   else
466*7304104dSAndroid Build Coastguard Worker     {
467*7304104dSAndroid Build Coastguard Worker       if (dwfl->user_core == NULL)
468*7304104dSAndroid Build Coastguard Worker 	{
469*7304104dSAndroid Build Coastguard Worker 	  cleanup_user_core = true;
470*7304104dSAndroid Build Coastguard Worker 	  dwfl->user_core = calloc (1, sizeof (struct Dwfl_User_Core));
471*7304104dSAndroid Build Coastguard Worker 	  if (dwfl->user_core == NULL)
472*7304104dSAndroid Build Coastguard Worker 	    {
473*7304104dSAndroid Build Coastguard Worker 	      __libdwfl_seterrno (DWFL_E_NOMEM);
474*7304104dSAndroid Build Coastguard Worker 	      return -1;
475*7304104dSAndroid Build Coastguard Worker 	    }
476*7304104dSAndroid Build Coastguard Worker 	  dwfl->user_core->fd = -1;
477*7304104dSAndroid Build Coastguard Worker 	}
478*7304104dSAndroid Build Coastguard Worker       dwfl->user_core->executable_for_core = strdup (executable);
479*7304104dSAndroid Build Coastguard Worker       if (dwfl->user_core->executable_for_core == NULL)
480*7304104dSAndroid Build Coastguard Worker 	{
481*7304104dSAndroid Build Coastguard Worker 	  if (cleanup_user_core)
482*7304104dSAndroid Build Coastguard Worker 	    {
483*7304104dSAndroid Build Coastguard Worker 	      free (dwfl->user_core);
484*7304104dSAndroid Build Coastguard Worker 	      dwfl->user_core = NULL;
485*7304104dSAndroid Build Coastguard Worker 	    }
486*7304104dSAndroid Build Coastguard Worker 	  __libdwfl_seterrno (DWFL_E_NOMEM);
487*7304104dSAndroid Build Coastguard Worker 	  return -1;
488*7304104dSAndroid Build Coastguard Worker 	}
489*7304104dSAndroid Build Coastguard Worker     }
490*7304104dSAndroid Build Coastguard Worker 
491*7304104dSAndroid Build Coastguard Worker   /* First report each PT_LOAD segment.  */
492*7304104dSAndroid Build Coastguard Worker   GElf_Phdr notes_phdr;
493*7304104dSAndroid Build Coastguard Worker   int ndx = dwfl_report_core_segments (dwfl, elf, phnum, &notes_phdr);
494*7304104dSAndroid Build Coastguard Worker   if (unlikely (ndx <= 0))
495*7304104dSAndroid Build Coastguard Worker     {
496*7304104dSAndroid Build Coastguard Worker       if (cleanup_user_core)
497*7304104dSAndroid Build Coastguard Worker 	{
498*7304104dSAndroid Build Coastguard Worker 	  free (dwfl->user_core->executable_for_core);
499*7304104dSAndroid Build Coastguard Worker 	  free (dwfl->user_core);
500*7304104dSAndroid Build Coastguard Worker 	  dwfl->user_core = NULL;
501*7304104dSAndroid Build Coastguard Worker 	}
502*7304104dSAndroid Build Coastguard Worker       return ndx;
503*7304104dSAndroid Build Coastguard Worker     }
504*7304104dSAndroid Build Coastguard Worker 
505*7304104dSAndroid Build Coastguard Worker   /* Next, we should follow the chain from DT_DEBUG.  */
506*7304104dSAndroid Build Coastguard Worker 
507*7304104dSAndroid Build Coastguard Worker   const void *auxv = NULL;
508*7304104dSAndroid Build Coastguard Worker   const void *note_file = NULL;
509*7304104dSAndroid Build Coastguard Worker   size_t auxv_size = 0;
510*7304104dSAndroid Build Coastguard Worker   size_t note_file_size = 0;
511*7304104dSAndroid Build Coastguard Worker   if (likely (notes_phdr.p_type == PT_NOTE))
512*7304104dSAndroid Build Coastguard Worker     {
513*7304104dSAndroid Build Coastguard Worker       /* PT_NOTE -> NT_AUXV -> AT_PHDR -> PT_DYNAMIC -> DT_DEBUG */
514*7304104dSAndroid Build Coastguard Worker 
515*7304104dSAndroid Build Coastguard Worker       Elf_Data *notes = elf_getdata_rawchunk (elf,
516*7304104dSAndroid Build Coastguard Worker 					      notes_phdr.p_offset,
517*7304104dSAndroid Build Coastguard Worker 					      notes_phdr.p_filesz,
518*7304104dSAndroid Build Coastguard Worker 					      (notes_phdr.p_align == 8
519*7304104dSAndroid Build Coastguard Worker 					       ? ELF_T_NHDR8
520*7304104dSAndroid Build Coastguard Worker 					       : ELF_T_NHDR));
521*7304104dSAndroid Build Coastguard Worker       if (likely (notes != NULL))
522*7304104dSAndroid Build Coastguard Worker 	{
523*7304104dSAndroid Build Coastguard Worker 	  size_t pos = 0;
524*7304104dSAndroid Build Coastguard Worker 	  GElf_Nhdr nhdr;
525*7304104dSAndroid Build Coastguard Worker 	  size_t name_pos;
526*7304104dSAndroid Build Coastguard Worker 	  size_t desc_pos;
527*7304104dSAndroid Build Coastguard Worker 	  while ((pos = gelf_getnote (notes, pos, &nhdr,
528*7304104dSAndroid Build Coastguard Worker 				      &name_pos, &desc_pos)) > 0)
529*7304104dSAndroid Build Coastguard Worker 	    if (nhdr.n_namesz == sizeof "CORE"
530*7304104dSAndroid Build Coastguard Worker 		&& !memcmp (notes->d_buf + name_pos, "CORE", sizeof "CORE"))
531*7304104dSAndroid Build Coastguard Worker 	      {
532*7304104dSAndroid Build Coastguard Worker 		if (nhdr.n_type == NT_AUXV)
533*7304104dSAndroid Build Coastguard Worker 		  {
534*7304104dSAndroid Build Coastguard Worker 		    auxv = notes->d_buf + desc_pos;
535*7304104dSAndroid Build Coastguard Worker 		    auxv_size = nhdr.n_descsz;
536*7304104dSAndroid Build Coastguard Worker 		  }
537*7304104dSAndroid Build Coastguard Worker 		if (nhdr.n_type == NT_FILE)
538*7304104dSAndroid Build Coastguard Worker 		  {
539*7304104dSAndroid Build Coastguard Worker 		    note_file = notes->d_buf + desc_pos;
540*7304104dSAndroid Build Coastguard Worker 		    note_file_size = nhdr.n_descsz;
541*7304104dSAndroid Build Coastguard Worker 		  }
542*7304104dSAndroid Build Coastguard Worker 	      }
543*7304104dSAndroid Build Coastguard Worker 	}
544*7304104dSAndroid Build Coastguard Worker     }
545*7304104dSAndroid Build Coastguard Worker 
546*7304104dSAndroid Build Coastguard Worker   /* Now we have NT_AUXV contents.  From here on this processing could be
547*7304104dSAndroid Build Coastguard Worker      used for a live process with auxv read from /proc.  */
548*7304104dSAndroid Build Coastguard Worker 
549*7304104dSAndroid Build Coastguard Worker   struct r_debug_info r_debug_info;
550*7304104dSAndroid Build Coastguard Worker   memset (&r_debug_info, 0, sizeof r_debug_info);
551*7304104dSAndroid Build Coastguard Worker   int retval = dwfl_link_map_report (dwfl, auxv, auxv_size,
552*7304104dSAndroid Build Coastguard Worker 				     dwfl_elf_phdr_memory_callback, elf,
553*7304104dSAndroid Build Coastguard Worker 				     &r_debug_info);
554*7304104dSAndroid Build Coastguard Worker   int listed = retval > 0 ? retval : 0;
555*7304104dSAndroid Build Coastguard Worker 
556*7304104dSAndroid Build Coastguard Worker   /* Now sniff segment contents for modules hinted by information gathered
557*7304104dSAndroid Build Coastguard Worker      from DT_DEBUG.  */
558*7304104dSAndroid Build Coastguard Worker 
559*7304104dSAndroid Build Coastguard Worker   ndx = 0;
560*7304104dSAndroid Build Coastguard Worker   do
561*7304104dSAndroid Build Coastguard Worker     {
562*7304104dSAndroid Build Coastguard Worker       int seg = dwfl_segment_report_module (dwfl, ndx, NULL,
563*7304104dSAndroid Build Coastguard Worker 					    &dwfl_elf_phdr_memory_callback, elf,
564*7304104dSAndroid Build Coastguard Worker 					    core_file_read_eagerly, elf,
565*7304104dSAndroid Build Coastguard Worker 					    elf->maximum_size,
566*7304104dSAndroid Build Coastguard Worker 					    note_file, note_file_size,
567*7304104dSAndroid Build Coastguard Worker 					    &r_debug_info);
568*7304104dSAndroid Build Coastguard Worker       if (unlikely (seg < 0))
569*7304104dSAndroid Build Coastguard Worker 	{
570*7304104dSAndroid Build Coastguard Worker 	  clear_r_debug_info (&r_debug_info);
571*7304104dSAndroid Build Coastguard Worker 	  return seg;
572*7304104dSAndroid Build Coastguard Worker 	}
573*7304104dSAndroid Build Coastguard Worker       if (seg > ndx)
574*7304104dSAndroid Build Coastguard Worker 	{
575*7304104dSAndroid Build Coastguard Worker 	  ndx = seg;
576*7304104dSAndroid Build Coastguard Worker 	  ++listed;
577*7304104dSAndroid Build Coastguard Worker 	}
578*7304104dSAndroid Build Coastguard Worker       else
579*7304104dSAndroid Build Coastguard Worker 	++ndx;
580*7304104dSAndroid Build Coastguard Worker     }
581*7304104dSAndroid Build Coastguard Worker   while (ndx < (int) phnum);
582*7304104dSAndroid Build Coastguard Worker 
583*7304104dSAndroid Build Coastguard Worker   /* Now report the modules from dwfl_link_map_report which were not filtered
584*7304104dSAndroid Build Coastguard Worker      out by dwfl_segment_report_module.  */
585*7304104dSAndroid Build Coastguard Worker 
586*7304104dSAndroid Build Coastguard Worker   Dwfl_Module **lastmodp = &dwfl->modulelist;
587*7304104dSAndroid Build Coastguard Worker   while (*lastmodp != NULL)
588*7304104dSAndroid Build Coastguard Worker     lastmodp = &(*lastmodp)->next;
589*7304104dSAndroid Build Coastguard Worker   for (struct r_debug_info_module *module = r_debug_info.module;
590*7304104dSAndroid Build Coastguard Worker        module != NULL; module = module->next)
591*7304104dSAndroid Build Coastguard Worker     {
592*7304104dSAndroid Build Coastguard Worker       if (module->elf == NULL)
593*7304104dSAndroid Build Coastguard Worker 	continue;
594*7304104dSAndroid Build Coastguard Worker       GElf_Addr file_dynamic_vaddr;
595*7304104dSAndroid Build Coastguard Worker       if (! __libdwfl_dynamic_vaddr_get (module->elf, &file_dynamic_vaddr))
596*7304104dSAndroid Build Coastguard Worker 	continue;
597*7304104dSAndroid Build Coastguard Worker       Dwfl_Module *mod;
598*7304104dSAndroid Build Coastguard Worker       mod = __libdwfl_report_elf (dwfl, xbasename (module->name), module->name,
599*7304104dSAndroid Build Coastguard Worker 				  module->fd, module->elf,
600*7304104dSAndroid Build Coastguard Worker 				  module->l_ld - file_dynamic_vaddr,
601*7304104dSAndroid Build Coastguard Worker 				  true, true);
602*7304104dSAndroid Build Coastguard Worker       if (mod == NULL)
603*7304104dSAndroid Build Coastguard Worker 	continue;
604*7304104dSAndroid Build Coastguard Worker       ++listed;
605*7304104dSAndroid Build Coastguard Worker       module->elf = NULL;
606*7304104dSAndroid Build Coastguard Worker       module->fd = -1;
607*7304104dSAndroid Build Coastguard Worker       /* Move this module to the end of the list, so that we end
608*7304104dSAndroid Build Coastguard Worker 	 up with a list in the same order as the link_map chain.  */
609*7304104dSAndroid Build Coastguard Worker       if (mod->next != NULL)
610*7304104dSAndroid Build Coastguard Worker 	{
611*7304104dSAndroid Build Coastguard Worker 	  if (*lastmodp != mod)
612*7304104dSAndroid Build Coastguard Worker 	    {
613*7304104dSAndroid Build Coastguard Worker 	      lastmodp = &dwfl->modulelist;
614*7304104dSAndroid Build Coastguard Worker 	      while (*lastmodp != mod)
615*7304104dSAndroid Build Coastguard Worker 		lastmodp = &(*lastmodp)->next;
616*7304104dSAndroid Build Coastguard Worker 	    }
617*7304104dSAndroid Build Coastguard Worker 	  *lastmodp = mod->next;
618*7304104dSAndroid Build Coastguard Worker 	  mod->next = NULL;
619*7304104dSAndroid Build Coastguard Worker 	  while (*lastmodp != NULL)
620*7304104dSAndroid Build Coastguard Worker 	    lastmodp = &(*lastmodp)->next;
621*7304104dSAndroid Build Coastguard Worker 	  *lastmodp = mod;
622*7304104dSAndroid Build Coastguard Worker 	}
623*7304104dSAndroid Build Coastguard Worker       lastmodp = &mod->next;
624*7304104dSAndroid Build Coastguard Worker     }
625*7304104dSAndroid Build Coastguard Worker 
626*7304104dSAndroid Build Coastguard Worker   clear_r_debug_info (&r_debug_info);
627*7304104dSAndroid Build Coastguard Worker 
628*7304104dSAndroid Build Coastguard Worker   /* We return the number of modules we found if we found any.
629*7304104dSAndroid Build Coastguard Worker      If we found none, we return -1 instead of 0 if there was an
630*7304104dSAndroid Build Coastguard Worker      error rather than just nothing found.  */
631*7304104dSAndroid Build Coastguard Worker   return listed > 0 ? listed : retval;
632*7304104dSAndroid Build Coastguard Worker }
633*7304104dSAndroid Build Coastguard Worker NEW_INTDEF (dwfl_core_file_report)
634*7304104dSAndroid Build Coastguard Worker 
635*7304104dSAndroid Build Coastguard Worker #ifdef SYMBOL_VERSIONING
636*7304104dSAndroid Build Coastguard Worker int _compat_without_executable_dwfl_core_file_report (Dwfl *dwfl, Elf *elf);
637*7304104dSAndroid Build Coastguard Worker COMPAT_VERSION_NEWPROTO (dwfl_core_file_report, ELFUTILS_0.146,
638*7304104dSAndroid Build Coastguard Worker 			 without_executable)
639*7304104dSAndroid Build Coastguard Worker 
640*7304104dSAndroid Build Coastguard Worker int
_compat_without_executable_dwfl_core_file_report(Dwfl * dwfl,Elf * elf)641*7304104dSAndroid Build Coastguard Worker _compat_without_executable_dwfl_core_file_report (Dwfl *dwfl, Elf *elf)
642*7304104dSAndroid Build Coastguard Worker {
643*7304104dSAndroid Build Coastguard Worker   return dwfl_core_file_report (dwfl, elf, NULL);
644*7304104dSAndroid Build Coastguard Worker }
645*7304104dSAndroid Build Coastguard Worker #endif
646