xref: /aosp_15_r20/external/elfutils/libdwfl/elf-from-memory.c (revision 7304104da70ce23c86437a01be71edd1a2d7f37e)
1*7304104dSAndroid Build Coastguard Worker /* Reconstruct an ELF file by reading the segments out of remote memory.
2*7304104dSAndroid Build Coastguard Worker    Copyright (C) 2005-2011, 2014, 2015 Red Hat, Inc.
3*7304104dSAndroid Build Coastguard Worker    This file is part of elfutils.
4*7304104dSAndroid Build Coastguard Worker 
5*7304104dSAndroid Build Coastguard Worker    This file is free software; you can redistribute it and/or modify
6*7304104dSAndroid Build Coastguard Worker    it under the terms of either
7*7304104dSAndroid Build Coastguard Worker 
8*7304104dSAndroid Build Coastguard Worker      * the GNU Lesser General Public License as published by the Free
9*7304104dSAndroid Build Coastguard Worker        Software Foundation; either version 3 of the License, or (at
10*7304104dSAndroid Build Coastguard Worker        your option) any later version
11*7304104dSAndroid Build Coastguard Worker 
12*7304104dSAndroid Build Coastguard Worker    or
13*7304104dSAndroid Build Coastguard Worker 
14*7304104dSAndroid Build Coastguard Worker      * the GNU General Public License as published by the Free
15*7304104dSAndroid Build Coastguard Worker        Software Foundation; either version 2 of the License, or (at
16*7304104dSAndroid Build Coastguard Worker        your option) any later version
17*7304104dSAndroid Build Coastguard Worker 
18*7304104dSAndroid Build Coastguard Worker    or both in parallel, as here.
19*7304104dSAndroid Build Coastguard Worker 
20*7304104dSAndroid Build Coastguard Worker    elfutils is distributed in the hope that it will be useful, but
21*7304104dSAndroid Build Coastguard Worker    WITHOUT ANY WARRANTY; without even the implied warranty of
22*7304104dSAndroid Build Coastguard Worker    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23*7304104dSAndroid Build Coastguard Worker    General Public License for more details.
24*7304104dSAndroid Build Coastguard Worker 
25*7304104dSAndroid Build Coastguard Worker    You should have received copies of the GNU General Public License and
26*7304104dSAndroid Build Coastguard Worker    the GNU Lesser General Public License along with this program.  If
27*7304104dSAndroid Build Coastguard Worker    not, see <http://www.gnu.org/licenses/>.  */
28*7304104dSAndroid Build Coastguard Worker 
29*7304104dSAndroid Build Coastguard Worker #include <config.h>
30*7304104dSAndroid Build Coastguard Worker #include "libelfP.h"
31*7304104dSAndroid Build Coastguard Worker 
32*7304104dSAndroid Build Coastguard Worker #include "libdwflP.h"
33*7304104dSAndroid Build Coastguard Worker 
34*7304104dSAndroid Build Coastguard Worker #include <gelf.h>
35*7304104dSAndroid Build Coastguard Worker #include <sys/types.h>
36*7304104dSAndroid Build Coastguard Worker #include <stdbool.h>
37*7304104dSAndroid Build Coastguard Worker #include <stdlib.h>
38*7304104dSAndroid Build Coastguard Worker #include <string.h>
39*7304104dSAndroid Build Coastguard Worker 
40*7304104dSAndroid Build Coastguard Worker /* Reconstruct an ELF file by reading the segments out of remote memory
41*7304104dSAndroid Build Coastguard Worker    based on the ELF file header at EHDR_VMA and the ELF program headers it
42*7304104dSAndroid Build Coastguard Worker    points to.  If not null, *LOADBASEP is filled in with the difference
43*7304104dSAndroid Build Coastguard Worker    between the addresses from which the segments were read, and the
44*7304104dSAndroid Build Coastguard Worker    addresses the file headers put them at.
45*7304104dSAndroid Build Coastguard Worker 
46*7304104dSAndroid Build Coastguard Worker    The function READ_MEMORY is called to copy at least MINREAD and at most
47*7304104dSAndroid Build Coastguard Worker    MAXREAD bytes from the remote memory at target address ADDRESS into the
48*7304104dSAndroid Build Coastguard Worker    local buffer at DATA; it should return -1 for errors (with code in
49*7304104dSAndroid Build Coastguard Worker    `errno'), 0 if it failed to read at least MINREAD bytes due to EOF, or
50*7304104dSAndroid Build Coastguard Worker    the number of bytes read if >= MINREAD.  ARG is passed through.
51*7304104dSAndroid Build Coastguard Worker 
52*7304104dSAndroid Build Coastguard Worker    PAGESIZE is the minimum page size and alignment used for the PT_LOAD
53*7304104dSAndroid Build Coastguard Worker    segments.  */
54*7304104dSAndroid Build Coastguard Worker 
55*7304104dSAndroid Build Coastguard Worker Elf *
elf_from_remote_memory(GElf_Addr ehdr_vma,GElf_Xword pagesize,GElf_Addr * loadbasep,ssize_t (* read_memory)(void * arg,void * data,GElf_Addr address,size_t minread,size_t maxread),void * arg)56*7304104dSAndroid Build Coastguard Worker elf_from_remote_memory (GElf_Addr ehdr_vma,
57*7304104dSAndroid Build Coastguard Worker 			GElf_Xword pagesize,
58*7304104dSAndroid Build Coastguard Worker 			GElf_Addr *loadbasep,
59*7304104dSAndroid Build Coastguard Worker 			ssize_t (*read_memory) (void *arg, void *data,
60*7304104dSAndroid Build Coastguard Worker 						GElf_Addr address,
61*7304104dSAndroid Build Coastguard Worker 						size_t minread,
62*7304104dSAndroid Build Coastguard Worker 						size_t maxread),
63*7304104dSAndroid Build Coastguard Worker 			void *arg)
64*7304104dSAndroid Build Coastguard Worker {
65*7304104dSAndroid Build Coastguard Worker   /* We might have to reserve some memory for the phdrs.  Set to NULL
66*7304104dSAndroid Build Coastguard Worker      here so we can always safely free it.  */
67*7304104dSAndroid Build Coastguard Worker   void *phdrsp = NULL;
68*7304104dSAndroid Build Coastguard Worker 
69*7304104dSAndroid Build Coastguard Worker   /* First read in the file header and check its sanity.  */
70*7304104dSAndroid Build Coastguard Worker 
71*7304104dSAndroid Build Coastguard Worker   const size_t initial_bufsize = 256;
72*7304104dSAndroid Build Coastguard Worker   unsigned char *buffer = malloc (initial_bufsize);
73*7304104dSAndroid Build Coastguard Worker   if (unlikely (buffer == NULL))
74*7304104dSAndroid Build Coastguard Worker     {
75*7304104dSAndroid Build Coastguard Worker     no_memory:
76*7304104dSAndroid Build Coastguard Worker       __libdwfl_seterrno (DWFL_E_NOMEM);
77*7304104dSAndroid Build Coastguard Worker       return NULL;
78*7304104dSAndroid Build Coastguard Worker     }
79*7304104dSAndroid Build Coastguard Worker 
80*7304104dSAndroid Build Coastguard Worker   ssize_t nread = (*read_memory) (arg, buffer, ehdr_vma,
81*7304104dSAndroid Build Coastguard Worker 				  sizeof (Elf32_Ehdr), initial_bufsize);
82*7304104dSAndroid Build Coastguard Worker   if (nread <= 0)
83*7304104dSAndroid Build Coastguard Worker     {
84*7304104dSAndroid Build Coastguard Worker     read_error:
85*7304104dSAndroid Build Coastguard Worker       free (buffer);
86*7304104dSAndroid Build Coastguard Worker       free (phdrsp);
87*7304104dSAndroid Build Coastguard Worker       __libdwfl_seterrno (nread < 0 ? DWFL_E_ERRNO : DWFL_E_TRUNCATED);
88*7304104dSAndroid Build Coastguard Worker       return NULL;
89*7304104dSAndroid Build Coastguard Worker     }
90*7304104dSAndroid Build Coastguard Worker 
91*7304104dSAndroid Build Coastguard Worker   if (memcmp (buffer, ELFMAG, SELFMAG) != 0)
92*7304104dSAndroid Build Coastguard Worker     {
93*7304104dSAndroid Build Coastguard Worker     bad_elf:
94*7304104dSAndroid Build Coastguard Worker       free (buffer);
95*7304104dSAndroid Build Coastguard Worker       free (phdrsp);
96*7304104dSAndroid Build Coastguard Worker       __libdwfl_seterrno (DWFL_E_BADELF);
97*7304104dSAndroid Build Coastguard Worker       return NULL;
98*7304104dSAndroid Build Coastguard Worker     }
99*7304104dSAndroid Build Coastguard Worker 
100*7304104dSAndroid Build Coastguard Worker   /* Extract the information we need from the file header.  */
101*7304104dSAndroid Build Coastguard Worker 
102*7304104dSAndroid Build Coastguard Worker   union
103*7304104dSAndroid Build Coastguard Worker   {
104*7304104dSAndroid Build Coastguard Worker     Elf32_Ehdr e32;
105*7304104dSAndroid Build Coastguard Worker     Elf64_Ehdr e64;
106*7304104dSAndroid Build Coastguard Worker   } ehdr;
107*7304104dSAndroid Build Coastguard Worker   Elf_Data xlatefrom =
108*7304104dSAndroid Build Coastguard Worker     {
109*7304104dSAndroid Build Coastguard Worker       .d_type = ELF_T_EHDR,
110*7304104dSAndroid Build Coastguard Worker       .d_buf = buffer,
111*7304104dSAndroid Build Coastguard Worker       .d_version = EV_CURRENT,
112*7304104dSAndroid Build Coastguard Worker     };
113*7304104dSAndroid Build Coastguard Worker   Elf_Data xlateto =
114*7304104dSAndroid Build Coastguard Worker     {
115*7304104dSAndroid Build Coastguard Worker       .d_type = ELF_T_EHDR,
116*7304104dSAndroid Build Coastguard Worker       .d_buf = &ehdr,
117*7304104dSAndroid Build Coastguard Worker       .d_size = sizeof ehdr,
118*7304104dSAndroid Build Coastguard Worker       .d_version = EV_CURRENT,
119*7304104dSAndroid Build Coastguard Worker     };
120*7304104dSAndroid Build Coastguard Worker 
121*7304104dSAndroid Build Coastguard Worker   GElf_Off phoff;
122*7304104dSAndroid Build Coastguard Worker   uint_fast16_t phnum;
123*7304104dSAndroid Build Coastguard Worker   uint_fast16_t phentsize;
124*7304104dSAndroid Build Coastguard Worker   GElf_Off shdrs_end;
125*7304104dSAndroid Build Coastguard Worker 
126*7304104dSAndroid Build Coastguard Worker   switch (buffer[EI_CLASS])
127*7304104dSAndroid Build Coastguard Worker     {
128*7304104dSAndroid Build Coastguard Worker     case ELFCLASS32:
129*7304104dSAndroid Build Coastguard Worker       xlatefrom.d_size = sizeof (Elf32_Ehdr);
130*7304104dSAndroid Build Coastguard Worker       if (elf32_xlatetom (&xlateto, &xlatefrom, buffer[EI_DATA]) == NULL)
131*7304104dSAndroid Build Coastguard Worker 	{
132*7304104dSAndroid Build Coastguard Worker 	libelf_error:
133*7304104dSAndroid Build Coastguard Worker 	  __libdwfl_seterrno (DWFL_E_LIBELF);
134*7304104dSAndroid Build Coastguard Worker 	  return NULL;
135*7304104dSAndroid Build Coastguard Worker 	}
136*7304104dSAndroid Build Coastguard Worker       phoff = ehdr.e32.e_phoff;
137*7304104dSAndroid Build Coastguard Worker       phnum = ehdr.e32.e_phnum;
138*7304104dSAndroid Build Coastguard Worker       phentsize = ehdr.e32.e_phentsize;
139*7304104dSAndroid Build Coastguard Worker       if (phentsize != sizeof (Elf32_Phdr) || phnum == 0)
140*7304104dSAndroid Build Coastguard Worker 	goto bad_elf;
141*7304104dSAndroid Build Coastguard Worker       /* NOTE if the number of sections is > 0xff00 then e_shnum
142*7304104dSAndroid Build Coastguard Worker 	 is zero and the actual number would come from the section
143*7304104dSAndroid Build Coastguard Worker 	 zero sh_size field. We ignore this here because getting shdrs
144*7304104dSAndroid Build Coastguard Worker 	 is just a nice bonus (see below where we trim the last phdrs
145*7304104dSAndroid Build Coastguard Worker 	 PT_LOAD segment).  */
146*7304104dSAndroid Build Coastguard Worker       shdrs_end = ehdr.e32.e_shoff + ehdr.e32.e_shnum * ehdr.e32.e_shentsize;
147*7304104dSAndroid Build Coastguard Worker       break;
148*7304104dSAndroid Build Coastguard Worker 
149*7304104dSAndroid Build Coastguard Worker     case ELFCLASS64:
150*7304104dSAndroid Build Coastguard Worker       xlatefrom.d_size = sizeof (Elf64_Ehdr);
151*7304104dSAndroid Build Coastguard Worker       if (elf64_xlatetom (&xlateto, &xlatefrom, buffer[EI_DATA]) == NULL)
152*7304104dSAndroid Build Coastguard Worker 	goto libelf_error;
153*7304104dSAndroid Build Coastguard Worker       phoff = ehdr.e64.e_phoff;
154*7304104dSAndroid Build Coastguard Worker       phnum = ehdr.e64.e_phnum;
155*7304104dSAndroid Build Coastguard Worker       phentsize = ehdr.e64.e_phentsize;
156*7304104dSAndroid Build Coastguard Worker       if (phentsize != sizeof (Elf64_Phdr) || phnum == 0)
157*7304104dSAndroid Build Coastguard Worker 	goto bad_elf;
158*7304104dSAndroid Build Coastguard Worker       /* See the NOTE above for shdrs_end and ehdr.e32.e_shnum.  */
159*7304104dSAndroid Build Coastguard Worker       shdrs_end = ehdr.e64.e_shoff + ehdr.e64.e_shnum * ehdr.e64.e_shentsize;
160*7304104dSAndroid Build Coastguard Worker       break;
161*7304104dSAndroid Build Coastguard Worker 
162*7304104dSAndroid Build Coastguard Worker     default:
163*7304104dSAndroid Build Coastguard Worker       goto bad_elf;
164*7304104dSAndroid Build Coastguard Worker     }
165*7304104dSAndroid Build Coastguard Worker 
166*7304104dSAndroid Build Coastguard Worker 
167*7304104dSAndroid Build Coastguard Worker   /* The file header tells where to find the program headers.
168*7304104dSAndroid Build Coastguard Worker      These are what we use to actually choose what to read.  */
169*7304104dSAndroid Build Coastguard Worker 
170*7304104dSAndroid Build Coastguard Worker   xlatefrom.d_type = xlateto.d_type = ELF_T_PHDR;
171*7304104dSAndroid Build Coastguard Worker   xlatefrom.d_size = phnum * phentsize;
172*7304104dSAndroid Build Coastguard Worker 
173*7304104dSAndroid Build Coastguard Worker   if ((size_t) nread >= phoff + phnum * phentsize)
174*7304104dSAndroid Build Coastguard Worker     /* We already have all the phdrs from the initial read.  */
175*7304104dSAndroid Build Coastguard Worker     xlatefrom.d_buf = buffer + phoff;
176*7304104dSAndroid Build Coastguard Worker   else
177*7304104dSAndroid Build Coastguard Worker     {
178*7304104dSAndroid Build Coastguard Worker       /* Read in the program headers.  */
179*7304104dSAndroid Build Coastguard Worker 
180*7304104dSAndroid Build Coastguard Worker       if (initial_bufsize < (size_t)phnum * phentsize)
181*7304104dSAndroid Build Coastguard Worker 	{
182*7304104dSAndroid Build Coastguard Worker 	  unsigned char *newbuf = realloc (buffer, phnum * phentsize);
183*7304104dSAndroid Build Coastguard Worker 	  if (newbuf == NULL)
184*7304104dSAndroid Build Coastguard Worker 	    {
185*7304104dSAndroid Build Coastguard Worker 	      free (buffer);
186*7304104dSAndroid Build Coastguard Worker 	      free (phdrsp);
187*7304104dSAndroid Build Coastguard Worker 	      goto no_memory;
188*7304104dSAndroid Build Coastguard Worker 	    }
189*7304104dSAndroid Build Coastguard Worker 	  buffer = newbuf;
190*7304104dSAndroid Build Coastguard Worker 	}
191*7304104dSAndroid Build Coastguard Worker       nread = (*read_memory) (arg, buffer, ehdr_vma + phoff,
192*7304104dSAndroid Build Coastguard Worker 			      phnum * phentsize, phnum * phentsize);
193*7304104dSAndroid Build Coastguard Worker       if (nread <= 0)
194*7304104dSAndroid Build Coastguard Worker 	goto read_error;
195*7304104dSAndroid Build Coastguard Worker 
196*7304104dSAndroid Build Coastguard Worker       xlatefrom.d_buf = buffer;
197*7304104dSAndroid Build Coastguard Worker     }
198*7304104dSAndroid Build Coastguard Worker 
199*7304104dSAndroid Build Coastguard Worker   bool class32 = ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32;
200*7304104dSAndroid Build Coastguard Worker   size_t phdr_size = class32 ? sizeof (Elf32_Phdr) : sizeof (Elf64_Phdr);
201*7304104dSAndroid Build Coastguard Worker   if (unlikely (phnum > SIZE_MAX / phdr_size))
202*7304104dSAndroid Build Coastguard Worker     {
203*7304104dSAndroid Build Coastguard Worker       free (buffer);
204*7304104dSAndroid Build Coastguard Worker       goto no_memory;
205*7304104dSAndroid Build Coastguard Worker     }
206*7304104dSAndroid Build Coastguard Worker   const size_t phdrsp_bytes = phnum * phdr_size;
207*7304104dSAndroid Build Coastguard Worker   phdrsp = malloc (phdrsp_bytes);
208*7304104dSAndroid Build Coastguard Worker   if (unlikely (phdrsp == NULL))
209*7304104dSAndroid Build Coastguard Worker     {
210*7304104dSAndroid Build Coastguard Worker       free (buffer);
211*7304104dSAndroid Build Coastguard Worker       goto no_memory;
212*7304104dSAndroid Build Coastguard Worker     }
213*7304104dSAndroid Build Coastguard Worker 
214*7304104dSAndroid Build Coastguard Worker   xlateto.d_buf = phdrsp;
215*7304104dSAndroid Build Coastguard Worker   xlateto.d_size = phdrsp_bytes;
216*7304104dSAndroid Build Coastguard Worker 
217*7304104dSAndroid Build Coastguard Worker   /* Scan for PT_LOAD segments to find the total size of the file image.  */
218*7304104dSAndroid Build Coastguard Worker   size_t contents_size = 0;
219*7304104dSAndroid Build Coastguard Worker   GElf_Off segments_end = 0;
220*7304104dSAndroid Build Coastguard Worker   GElf_Off segments_end_mem = 0;
221*7304104dSAndroid Build Coastguard Worker   GElf_Addr loadbase = ehdr_vma;
222*7304104dSAndroid Build Coastguard Worker   bool found_base = false;
223*7304104dSAndroid Build Coastguard Worker   Elf32_Phdr (*p32)[phnum] = phdrsp;
224*7304104dSAndroid Build Coastguard Worker   Elf64_Phdr (*p64)[phnum] = phdrsp;
225*7304104dSAndroid Build Coastguard Worker 
226*7304104dSAndroid Build Coastguard Worker   if (class32)
227*7304104dSAndroid Build Coastguard Worker     {
228*7304104dSAndroid Build Coastguard Worker       if (! elf32_xlatetom (&xlateto, &xlatefrom, ehdr.e32.e_ident[EI_DATA]))
229*7304104dSAndroid Build Coastguard Worker         goto libelf_error;
230*7304104dSAndroid Build Coastguard Worker     }
231*7304104dSAndroid Build Coastguard Worker   else
232*7304104dSAndroid Build Coastguard Worker     {
233*7304104dSAndroid Build Coastguard Worker       if (! elf64_xlatetom (&xlateto, &xlatefrom, ehdr.e64.e_ident[EI_DATA]))
234*7304104dSAndroid Build Coastguard Worker         goto libelf_error;
235*7304104dSAndroid Build Coastguard Worker     }
236*7304104dSAndroid Build Coastguard Worker 
237*7304104dSAndroid Build Coastguard Worker   for (uint_fast16_t i = 0; i < phnum; ++i)
238*7304104dSAndroid Build Coastguard Worker     {
239*7304104dSAndroid Build Coastguard Worker       GElf_Word type = class32 ? (*p32)[i].p_type : (*p64)[i].p_type;
240*7304104dSAndroid Build Coastguard Worker 
241*7304104dSAndroid Build Coastguard Worker       if (type != PT_LOAD)
242*7304104dSAndroid Build Coastguard Worker         continue;
243*7304104dSAndroid Build Coastguard Worker 
244*7304104dSAndroid Build Coastguard Worker       GElf_Addr vaddr = class32 ? (*p32)[i].p_vaddr : (*p64)[i].p_vaddr;
245*7304104dSAndroid Build Coastguard Worker       GElf_Xword memsz = class32 ? (*p32)[i].p_memsz : (*p64)[i].p_memsz;
246*7304104dSAndroid Build Coastguard Worker       GElf_Off offset = class32 ? (*p32)[i].p_offset : (*p64)[i].p_offset;
247*7304104dSAndroid Build Coastguard Worker       GElf_Xword filesz = class32 ? (*p32)[i].p_filesz : (*p64)[i].p_filesz;
248*7304104dSAndroid Build Coastguard Worker 
249*7304104dSAndroid Build Coastguard Worker       /* Sanity check the segment load aligns with the pagesize.  */
250*7304104dSAndroid Build Coastguard Worker       if (((vaddr - offset) & (pagesize - 1)) != 0)
251*7304104dSAndroid Build Coastguard Worker         goto bad_elf;
252*7304104dSAndroid Build Coastguard Worker 
253*7304104dSAndroid Build Coastguard Worker       GElf_Off segment_end = ((offset + filesz + pagesize - 1)
254*7304104dSAndroid Build Coastguard Worker                               & -pagesize);
255*7304104dSAndroid Build Coastguard Worker 
256*7304104dSAndroid Build Coastguard Worker       if (segment_end > (GElf_Off) contents_size)
257*7304104dSAndroid Build Coastguard Worker         contents_size = segment_end;
258*7304104dSAndroid Build Coastguard Worker 
259*7304104dSAndroid Build Coastguard Worker       if (!found_base && (offset & -pagesize) == 0)
260*7304104dSAndroid Build Coastguard Worker         {
261*7304104dSAndroid Build Coastguard Worker           loadbase = ehdr_vma - (vaddr & -pagesize);
262*7304104dSAndroid Build Coastguard Worker           found_base = true;
263*7304104dSAndroid Build Coastguard Worker         }
264*7304104dSAndroid Build Coastguard Worker 
265*7304104dSAndroid Build Coastguard Worker       segments_end = offset + filesz;
266*7304104dSAndroid Build Coastguard Worker       segments_end_mem = offset + memsz;
267*7304104dSAndroid Build Coastguard Worker     }
268*7304104dSAndroid Build Coastguard Worker 
269*7304104dSAndroid Build Coastguard Worker   /* Trim the last segment so we don't bother with zeros in the last page
270*7304104dSAndroid Build Coastguard Worker      that are off the end of the file.  However, if the extra bit in that
271*7304104dSAndroid Build Coastguard Worker      page includes the section headers and the memory isn't extended (which
272*7304104dSAndroid Build Coastguard Worker      might indicate it will have been reused otherwise), keep them.  */
273*7304104dSAndroid Build Coastguard Worker   if ((GElf_Off) contents_size > segments_end
274*7304104dSAndroid Build Coastguard Worker       && (GElf_Off) contents_size >= shdrs_end
275*7304104dSAndroid Build Coastguard Worker       && segments_end == segments_end_mem)
276*7304104dSAndroid Build Coastguard Worker     {
277*7304104dSAndroid Build Coastguard Worker       contents_size = segments_end;
278*7304104dSAndroid Build Coastguard Worker       if ((GElf_Off) contents_size < shdrs_end)
279*7304104dSAndroid Build Coastguard Worker 	contents_size = shdrs_end;
280*7304104dSAndroid Build Coastguard Worker     }
281*7304104dSAndroid Build Coastguard Worker   else
282*7304104dSAndroid Build Coastguard Worker     contents_size = segments_end;
283*7304104dSAndroid Build Coastguard Worker 
284*7304104dSAndroid Build Coastguard Worker   free (buffer);
285*7304104dSAndroid Build Coastguard Worker 
286*7304104dSAndroid Build Coastguard Worker   /* Now we know the size of the whole image we want read in.  */
287*7304104dSAndroid Build Coastguard Worker   buffer = calloc (1, contents_size);
288*7304104dSAndroid Build Coastguard Worker   if (buffer == NULL)
289*7304104dSAndroid Build Coastguard Worker     {
290*7304104dSAndroid Build Coastguard Worker       free (phdrsp);
291*7304104dSAndroid Build Coastguard Worker       goto no_memory;
292*7304104dSAndroid Build Coastguard Worker     }
293*7304104dSAndroid Build Coastguard Worker 
294*7304104dSAndroid Build Coastguard Worker   for (uint_fast16_t i = 0; i < phnum; ++i)
295*7304104dSAndroid Build Coastguard Worker     {
296*7304104dSAndroid Build Coastguard Worker       GElf_Word type = class32 ? (*p32)[i].p_type : (*p64)[i].p_type;
297*7304104dSAndroid Build Coastguard Worker 
298*7304104dSAndroid Build Coastguard Worker       if (type != PT_LOAD)
299*7304104dSAndroid Build Coastguard Worker         continue;
300*7304104dSAndroid Build Coastguard Worker 
301*7304104dSAndroid Build Coastguard Worker       GElf_Addr vaddr = class32 ? (*p32)[i].p_vaddr : (*p64)[i].p_vaddr;
302*7304104dSAndroid Build Coastguard Worker       GElf_Off offset = class32 ? (*p32)[i].p_offset : (*p64)[i].p_offset;
303*7304104dSAndroid Build Coastguard Worker       GElf_Xword filesz = class32 ? (*p32)[i].p_filesz : (*p64)[i].p_filesz;
304*7304104dSAndroid Build Coastguard Worker 
305*7304104dSAndroid Build Coastguard Worker       GElf_Off start = offset & -pagesize;
306*7304104dSAndroid Build Coastguard Worker       GElf_Off end = (offset + filesz + pagesize - 1) & -pagesize;
307*7304104dSAndroid Build Coastguard Worker       if (end > (GElf_Off) contents_size)
308*7304104dSAndroid Build Coastguard Worker         end = contents_size;
309*7304104dSAndroid Build Coastguard Worker       nread = (*read_memory) (arg, buffer + start,
310*7304104dSAndroid Build Coastguard Worker                               (loadbase + vaddr) & -pagesize,
311*7304104dSAndroid Build Coastguard Worker                               end - start, end - start);
312*7304104dSAndroid Build Coastguard Worker       if (nread <= 0)
313*7304104dSAndroid Build Coastguard Worker         goto read_error;
314*7304104dSAndroid Build Coastguard Worker     }
315*7304104dSAndroid Build Coastguard Worker 
316*7304104dSAndroid Build Coastguard Worker   /* If the segments visible in memory didn't include the section
317*7304104dSAndroid Build Coastguard Worker      headers, then clear them from the file header.  */
318*7304104dSAndroid Build Coastguard Worker   if (contents_size < shdrs_end)
319*7304104dSAndroid Build Coastguard Worker     {
320*7304104dSAndroid Build Coastguard Worker       if (class32)
321*7304104dSAndroid Build Coastguard Worker         {
322*7304104dSAndroid Build Coastguard Worker           ehdr.e32.e_shoff = 0;
323*7304104dSAndroid Build Coastguard Worker           ehdr.e32.e_shnum = 0;
324*7304104dSAndroid Build Coastguard Worker           ehdr.e32.e_shstrndx = 0;
325*7304104dSAndroid Build Coastguard Worker         }
326*7304104dSAndroid Build Coastguard Worker       else
327*7304104dSAndroid Build Coastguard Worker         {
328*7304104dSAndroid Build Coastguard Worker           ehdr.e64.e_shoff = 0;
329*7304104dSAndroid Build Coastguard Worker           ehdr.e64.e_shnum = 0;
330*7304104dSAndroid Build Coastguard Worker           ehdr.e64.e_shstrndx = 0;
331*7304104dSAndroid Build Coastguard Worker         }
332*7304104dSAndroid Build Coastguard Worker     }
333*7304104dSAndroid Build Coastguard Worker 
334*7304104dSAndroid Build Coastguard Worker   /* This will normally have been in the first PT_LOAD segment.  But it
335*7304104dSAndroid Build Coastguard Worker      conceivably could be missing, and we might have just changed it.  */
336*7304104dSAndroid Build Coastguard Worker   xlatefrom.d_type = xlateto.d_type = ELF_T_EHDR;
337*7304104dSAndroid Build Coastguard Worker   xlateto.d_buf = buffer;
338*7304104dSAndroid Build Coastguard Worker   if (class32)
339*7304104dSAndroid Build Coastguard Worker     {
340*7304104dSAndroid Build Coastguard Worker       xlatefrom.d_size = xlateto.d_size = sizeof ehdr.e32;
341*7304104dSAndroid Build Coastguard Worker       xlatefrom.d_buf = &ehdr.e32;
342*7304104dSAndroid Build Coastguard Worker       if (elf32_xlatetof (&xlateto, &xlatefrom,
343*7304104dSAndroid Build Coastguard Worker                           ehdr.e32.e_ident[EI_DATA]) == NULL)
344*7304104dSAndroid Build Coastguard Worker         goto libelf_error;
345*7304104dSAndroid Build Coastguard Worker     }
346*7304104dSAndroid Build Coastguard Worker   else
347*7304104dSAndroid Build Coastguard Worker     {
348*7304104dSAndroid Build Coastguard Worker       xlatefrom.d_size = xlateto.d_size = sizeof ehdr.e64;
349*7304104dSAndroid Build Coastguard Worker       xlatefrom.d_buf = &ehdr.e64;
350*7304104dSAndroid Build Coastguard Worker       if (elf64_xlatetof (&xlateto, &xlatefrom,
351*7304104dSAndroid Build Coastguard Worker                           ehdr.e64.e_ident[EI_DATA]) == NULL)
352*7304104dSAndroid Build Coastguard Worker         goto libelf_error;
353*7304104dSAndroid Build Coastguard Worker     }
354*7304104dSAndroid Build Coastguard Worker 
355*7304104dSAndroid Build Coastguard Worker   free (phdrsp);
356*7304104dSAndroid Build Coastguard Worker   phdrsp = NULL;
357*7304104dSAndroid Build Coastguard Worker 
358*7304104dSAndroid Build Coastguard Worker   /* Now we have the image.  Open libelf on it.  */
359*7304104dSAndroid Build Coastguard Worker 
360*7304104dSAndroid Build Coastguard Worker   Elf *elf = elf_memory ((char *) buffer, contents_size);
361*7304104dSAndroid Build Coastguard Worker   if (elf == NULL)
362*7304104dSAndroid Build Coastguard Worker     {
363*7304104dSAndroid Build Coastguard Worker       free (buffer);
364*7304104dSAndroid Build Coastguard Worker       goto libelf_error;
365*7304104dSAndroid Build Coastguard Worker     }
366*7304104dSAndroid Build Coastguard Worker 
367*7304104dSAndroid Build Coastguard Worker   elf->flags |= ELF_F_MALLOCED;
368*7304104dSAndroid Build Coastguard Worker   if (loadbasep != NULL)
369*7304104dSAndroid Build Coastguard Worker     *loadbasep = loadbase;
370*7304104dSAndroid Build Coastguard Worker   return elf;
371*7304104dSAndroid Build Coastguard Worker }
372