blob: ed8f6e920e8c97741c8272d58d19db14a5dd469e [file] [log] [blame]
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001/* Reconstruct an ELF file by reading the segments out of remote memory.
Mark Wielaard9202fe12015-05-19 13:39:39 +02002 Copyright (C) 2005-2011, 2014, 2015 Red Hat, Inc.
Mark Wielaardde2ed972012-06-05 17:15:16 +02003 This file is part of elfutils.
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00004
Mark Wielaardde2ed972012-06-05 17:15:16 +02005 This file is free software; you can redistribute it and/or modify
6 it under the terms of either
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00007
Mark Wielaardde2ed972012-06-05 17:15:16 +02008 * 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
Ulrich Drepper361df7d2006-04-04 21:38:57 +000021 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
Mark Wielaardde2ed972012-06-05 17:15:16 +020025 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/>. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000028
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
Mark Wielaardf15bcda2014-03-03 11:43:43 +010051 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. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000055
56Elf *
57elf_from_remote_memory (GElf_Addr ehdr_vma,
Mark Wielaardf15bcda2014-03-03 11:43:43 +010058 GElf_Xword pagesize,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000059 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{
Mark Wielaard9202fe12015-05-19 13:39:39 +020066 /* We might have to reserve some memory for the phdrs. Set to NULL
67 here so we can always safely free it. */
68 void *phdrsp = NULL;
69
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000070 /* First read in the file header and check its sanity. */
71
72 const size_t initial_bufsize = 256;
73 unsigned char *buffer = malloc (initial_bufsize);
Mark Wielaard9202fe12015-05-19 13:39:39 +020074 if (unlikely (buffer == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000075 {
76 no_memory:
77 __libdwfl_seterrno (DWFL_E_NOMEM);
78 return NULL;
79 }
80
81 ssize_t nread = (*read_memory) (arg, buffer, ehdr_vma,
82 sizeof (Elf32_Ehdr), initial_bufsize);
83 if (nread <= 0)
84 {
85 read_error:
86 free (buffer);
Mark Wielaard9202fe12015-05-19 13:39:39 +020087 free (phdrsp);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000088 __libdwfl_seterrno (nread < 0 ? DWFL_E_ERRNO : DWFL_E_TRUNCATED);
89 return NULL;
90 }
91
92 if (memcmp (buffer, ELFMAG, SELFMAG) != 0)
93 {
94 bad_elf:
Mark Wielaardf15bcda2014-03-03 11:43:43 +010095 free (buffer);
Mark Wielaard9202fe12015-05-19 13:39:39 +020096 free (phdrsp);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000097 __libdwfl_seterrno (DWFL_E_BADELF);
98 return NULL;
99 }
100
101 /* Extract the information we need from the file header. */
102
103 union
104 {
105 Elf32_Ehdr e32;
106 Elf64_Ehdr e64;
107 } ehdr;
108 Elf_Data xlatefrom =
109 {
110 .d_type = ELF_T_EHDR,
111 .d_buf = buffer,
112 .d_version = EV_CURRENT,
113 };
114 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 GElf_Off phoff;
123 uint_fast16_t phnum;
124 uint_fast16_t phentsize;
125 GElf_Off shdrs_end;
126
127 switch (buffer[EI_CLASS])
128 {
129 case ELFCLASS32:
130 xlatefrom.d_size = sizeof (Elf32_Ehdr);
131 if (elf32_xlatetom (&xlateto, &xlatefrom, buffer[EI_DATA]) == NULL)
132 {
133 libelf_error:
134 __libdwfl_seterrno (DWFL_E_LIBELF);
135 return NULL;
136 }
137 phoff = ehdr.e32.e_phoff;
138 phnum = ehdr.e32.e_phnum;
139 phentsize = ehdr.e32.e_phentsize;
140 if (phentsize != sizeof (Elf32_Phdr) || phnum == 0)
141 goto bad_elf;
142 shdrs_end = ehdr.e32.e_shoff + ehdr.e32.e_shnum * ehdr.e32.e_shentsize;
143 break;
144
145 case ELFCLASS64:
146 xlatefrom.d_size = sizeof (Elf64_Ehdr);
Ulrich Drepper6258e742007-03-13 06:22:40 +0000147 if (elf64_xlatetom (&xlateto, &xlatefrom, buffer[EI_DATA]) == NULL)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000148 goto libelf_error;
149 phoff = ehdr.e64.e_phoff;
150 phnum = ehdr.e64.e_phnum;
151 phentsize = ehdr.e64.e_phentsize;
152 if (phentsize != sizeof (Elf64_Phdr) || phnum == 0)
153 goto bad_elf;
154 shdrs_end = ehdr.e64.e_shoff + ehdr.e64.e_shnum * ehdr.e64.e_shentsize;
155 break;
156
157 default:
158 goto bad_elf;
159 }
160
161
162 /* The file header tells where to find the program headers.
163 These are what we use to actually choose what to read. */
164
165 xlatefrom.d_type = xlateto.d_type = ELF_T_PHDR;
166 xlatefrom.d_size = phnum * phentsize;
167
168 if ((size_t) nread >= phoff + phnum * phentsize)
169 /* We already have all the phdrs from the initial read. */
170 xlatefrom.d_buf = buffer + phoff;
171 else
172 {
173 /* Read in the program headers. */
174
175 if (initial_bufsize < phnum * phentsize)
176 {
177 unsigned char *newbuf = realloc (buffer, phnum * phentsize);
178 if (newbuf == NULL)
179 {
180 free (buffer);
Mark Wielaard9202fe12015-05-19 13:39:39 +0200181 free (phdrsp);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000182 goto no_memory;
183 }
184 buffer = newbuf;
185 }
186 nread = (*read_memory) (arg, buffer, ehdr_vma + phoff,
187 phnum * phentsize, phnum * phentsize);
188 if (nread <= 0)
189 goto read_error;
190
191 xlatefrom.d_buf = buffer;
192 }
193
Mark Wielaard9202fe12015-05-19 13:39:39 +0200194 typedef union
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000195 {
196 Elf32_Phdr p32[phnum];
197 Elf64_Phdr p64[phnum];
Mark Wielaard9202fe12015-05-19 13:39:39 +0200198 } phdrsn;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000199
Mark Wielaard9202fe12015-05-19 13:39:39 +0200200 phdrsp = malloc (sizeof (phdrsn));
201 if (unlikely (phdrsp == NULL))
202 {
203 free (buffer);
204 goto no_memory;
205 }
206 phdrsn *phdrs = (phdrsn *) phdrsp;
207
208 xlateto.d_buf = phdrs;
209 xlateto.d_size = sizeof (phdrsn);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000210
211 /* Scan for PT_LOAD segments to find the total size of the file image. */
212 size_t contents_size = 0;
213 GElf_Off segments_end = 0;
Mark Wielaarddd64d4a2014-03-03 15:07:31 +0100214 GElf_Off segments_end_mem = 0;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000215 GElf_Addr loadbase = ehdr_vma;
Roland McGrath099dd522007-08-13 22:58:36 +0000216 bool found_base = false;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000217 switch (ehdr.e32.e_ident[EI_CLASS])
218 {
Mark Wielaardf15bcda2014-03-03 11:43:43 +0100219 /* Sanity checks segments and calculates segment_end,
220 segments_end, segments_end_mem and loadbase (if not
221 found_base yet). Returns true if sanity checking failed,
222 false otherwise. */
223 inline bool handle_segment (GElf_Addr vaddr, GElf_Off offset,
Mark Wielaard32b6c6a2014-12-19 15:40:16 +0100224 GElf_Xword filesz, GElf_Xword memsz)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000225 {
Mark Wielaard32b6c6a2014-12-19 15:40:16 +0100226 /* Sanity check the segment load aligns with the pagesize. */
227 if (((vaddr - offset) & (pagesize - 1)) != 0)
Mark Wielaardf15bcda2014-03-03 11:43:43 +0100228 return true;
229
230 GElf_Off segment_end = ((offset + filesz + pagesize - 1)
231 & -pagesize);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000232
233 if (segment_end > (GElf_Off) contents_size)
234 contents_size = segment_end;
235
Mark Wielaardf15bcda2014-03-03 11:43:43 +0100236 if (!found_base && (offset & -pagesize) == 0)
Roland McGrath099dd522007-08-13 22:58:36 +0000237 {
Mark Wielaardf15bcda2014-03-03 11:43:43 +0100238 loadbase = ehdr_vma - (vaddr & -pagesize);
Roland McGrath099dd522007-08-13 22:58:36 +0000239 found_base = true;
240 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000241
242 segments_end = offset + filesz;
Mark Wielaarddd64d4a2014-03-03 15:07:31 +0100243 segments_end_mem = offset + memsz;
Mark Wielaardf15bcda2014-03-03 11:43:43 +0100244 return false;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000245 }
246
247 case ELFCLASS32:
248 if (elf32_xlatetom (&xlateto, &xlatefrom,
249 ehdr.e32.e_ident[EI_DATA]) == NULL)
250 goto libelf_error;
251 for (uint_fast16_t i = 0; i < phnum; ++i)
Mark Wielaard9202fe12015-05-19 13:39:39 +0200252 if (phdrs->p32[i].p_type == PT_LOAD)
253 if (handle_segment (phdrs->p32[i].p_vaddr, phdrs->p32[i].p_offset,
254 phdrs->p32[i].p_filesz, phdrs->p32[i].p_memsz))
Mark Wielaardf15bcda2014-03-03 11:43:43 +0100255 goto bad_elf;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000256 break;
257
258 case ELFCLASS64:
Roland McGrath01fef9d2011-12-02 09:45:53 -0800259 if (elf64_xlatetom (&xlateto, &xlatefrom,
260 ehdr.e64.e_ident[EI_DATA]) == NULL)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000261 goto libelf_error;
262 for (uint_fast16_t i = 0; i < phnum; ++i)
Mark Wielaard9202fe12015-05-19 13:39:39 +0200263 if (phdrs->p64[i].p_type == PT_LOAD)
264 if (handle_segment (phdrs->p64[i].p_vaddr, phdrs->p64[i].p_offset,
265 phdrs->p64[i].p_filesz, phdrs->p64[i].p_memsz))
Mark Wielaardf15bcda2014-03-03 11:43:43 +0100266 goto bad_elf;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000267 break;
268
269 default:
270 abort ();
271 break;
272 }
273
274 /* Trim the last segment so we don't bother with zeros in the last page
275 that are off the end of the file. However, if the extra bit in that
Mark Wielaarddd64d4a2014-03-03 15:07:31 +0100276 page includes the section headers and the memory isn't extended (which
277 might indicate it will have been reused otherwise), keep them. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000278 if ((GElf_Off) contents_size > segments_end
Mark Wielaarddd64d4a2014-03-03 15:07:31 +0100279 && (GElf_Off) contents_size >= shdrs_end
280 && segments_end == segments_end_mem)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000281 {
282 contents_size = segments_end;
283 if ((GElf_Off) contents_size < shdrs_end)
284 contents_size = shdrs_end;
285 }
286 else
287 contents_size = segments_end;
288
289 free (buffer);
290
291 /* Now we know the size of the whole image we want read in. */
292 buffer = calloc (1, contents_size);
293 if (buffer == NULL)
Mark Wielaard9202fe12015-05-19 13:39:39 +0200294 {
295 free (phdrsp);
296 goto no_memory;
297 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000298
299 switch (ehdr.e32.e_ident[EI_CLASS])
300 {
Mark Wielaardf15bcda2014-03-03 11:43:43 +0100301 /* Reads the given segment. Returns true if reading fails,
302 false otherwise. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000303 inline bool handle_segment (GElf_Addr vaddr, GElf_Off offset,
Mark Wielaardf15bcda2014-03-03 11:43:43 +0100304 GElf_Xword filesz)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000305 {
Mark Wielaardf15bcda2014-03-03 11:43:43 +0100306 GElf_Off start = offset & -pagesize;
307 GElf_Off end = (offset + filesz + pagesize - 1) & -pagesize;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000308 if (end > (GElf_Off) contents_size)
309 end = contents_size;
310 nread = (*read_memory) (arg, buffer + start,
Mark Wielaardf15bcda2014-03-03 11:43:43 +0100311 (loadbase + vaddr) & -pagesize,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000312 end - start, end - start);
313 return nread <= 0;
314 }
315
316 case ELFCLASS32:
317 for (uint_fast16_t i = 0; i < phnum; ++i)
Mark Wielaard9202fe12015-05-19 13:39:39 +0200318 if (phdrs->p32[i].p_type == PT_LOAD)
319 if (handle_segment (phdrs->p32[i].p_vaddr, phdrs->p32[i].p_offset,
320 phdrs->p32[i].p_filesz))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000321 goto read_error;
322
323 /* If the segments visible in memory didn't include the section
324 headers, then clear them from the file header. */
325 if (contents_size < shdrs_end)
326 {
327 ehdr.e32.e_shoff = 0;
328 ehdr.e32.e_shnum = 0;
329 ehdr.e32.e_shstrndx = 0;
330 }
331
332 /* This will normally have been in the first PT_LOAD segment. But it
333 conceivably could be missing, and we might have just changed it. */
334 xlatefrom.d_type = xlateto.d_type = ELF_T_EHDR;
335 xlatefrom.d_size = xlateto.d_size = sizeof ehdr.e32;
336 xlatefrom.d_buf = &ehdr.e32;
337 xlateto.d_buf = buffer;
338 if (elf32_xlatetof (&xlateto, &xlatefrom,
339 ehdr.e32.e_ident[EI_DATA]) == NULL)
340 goto libelf_error;
341 break;
342
343 case ELFCLASS64:
344 for (uint_fast16_t i = 0; i < phnum; ++i)
Mark Wielaard9202fe12015-05-19 13:39:39 +0200345 if (phdrs->p64[i].p_type == PT_LOAD)
346 if (handle_segment (phdrs->p64[i].p_vaddr, phdrs->p64[i].p_offset,
347 phdrs->p64[i].p_filesz))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000348 goto read_error;
349
350 /* If the segments visible in memory didn't include the section
351 headers, then clear them from the file header. */
352 if (contents_size < shdrs_end)
353 {
354 ehdr.e64.e_shoff = 0;
355 ehdr.e64.e_shnum = 0;
356 ehdr.e64.e_shstrndx = 0;
357 }
358
359 /* This will normally have been in the first PT_LOAD segment. But it
360 conceivably could be missing, and we might have just changed it. */
361 xlatefrom.d_type = xlateto.d_type = ELF_T_EHDR;
362 xlatefrom.d_size = xlateto.d_size = sizeof ehdr.e64;
363 xlatefrom.d_buf = &ehdr.e64;
364 xlateto.d_buf = buffer;
Ulrich Drepperd5a75192006-06-15 03:07:46 +0000365 if (elf64_xlatetof (&xlateto, &xlatefrom,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000366 ehdr.e64.e_ident[EI_DATA]) == NULL)
367 goto libelf_error;
368 break;
369
370 default:
371 abort ();
372 break;
373 }
374
Mark Wielaard9202fe12015-05-19 13:39:39 +0200375 free (phdrsp);
376 phdrs = phdrsp = NULL;
377
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000378 /* Now we have the image. Open libelf on it. */
379
380 Elf *elf = elf_memory ((char *) buffer, contents_size);
381 if (elf == NULL)
382 {
383 free (buffer);
Ulrich Drepperd5a75192006-06-15 03:07:46 +0000384 goto libelf_error;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000385 }
386
387 elf->flags |= ELF_F_MALLOCED;
388 if (loadbasep != NULL)
389 *loadbasep = loadbase;
390 return elf;
391}