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