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