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