blob: 5be21bb033908a372ad58eb1cb4988b067504153 [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
Chih-Hung Hsieh7eff36d2015-10-06 15:53:15 -070041#ifndef MAX
42# define MAX(a, b) ((a) > (b) ? (a) : (b))
43#endif
44
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000045/* Reconstruct an ELF file by reading the segments out of remote memory
46 based on the ELF file header at EHDR_VMA and the ELF program headers it
47 points to. If not null, *LOADBASEP is filled in with the difference
48 between the addresses from which the segments were read, and the
49 addresses the file headers put them at.
50
51 The function READ_MEMORY is called to copy at least MINREAD and at most
52 MAXREAD bytes from the remote memory at target address ADDRESS into the
53 local buffer at DATA; it should return -1 for errors (with code in
54 `errno'), 0 if it failed to read at least MINREAD bytes due to EOF, or
Mark Wielaardf15bcda2014-03-03 11:43:43 +010055 the number of bytes read if >= MINREAD. ARG is passed through.
56
57 PAGESIZE is the minimum page size and alignment used for the PT_LOAD
58 segments. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000059
60Elf *
61elf_from_remote_memory (GElf_Addr ehdr_vma,
Mark Wielaardf15bcda2014-03-03 11:43:43 +010062 GElf_Xword pagesize,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000063 GElf_Addr *loadbasep,
64 ssize_t (*read_memory) (void *arg, void *data,
65 GElf_Addr address,
66 size_t minread,
67 size_t maxread),
68 void *arg)
69{
Mark Wielaard9202fe12015-05-19 13:39:39 +020070 /* We might have to reserve some memory for the phdrs. Set to NULL
71 here so we can always safely free it. */
72 void *phdrsp = NULL;
73
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000074 /* First read in the file header and check its sanity. */
75
76 const size_t initial_bufsize = 256;
77 unsigned char *buffer = malloc (initial_bufsize);
Mark Wielaard9202fe12015-05-19 13:39:39 +020078 if (unlikely (buffer == NULL))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000079 {
80 no_memory:
81 __libdwfl_seterrno (DWFL_E_NOMEM);
82 return NULL;
83 }
84
85 ssize_t nread = (*read_memory) (arg, buffer, ehdr_vma,
86 sizeof (Elf32_Ehdr), initial_bufsize);
87 if (nread <= 0)
88 {
89 read_error:
90 free (buffer);
Mark Wielaard9202fe12015-05-19 13:39:39 +020091 free (phdrsp);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000092 __libdwfl_seterrno (nread < 0 ? DWFL_E_ERRNO : DWFL_E_TRUNCATED);
93 return NULL;
94 }
95
96 if (memcmp (buffer, ELFMAG, SELFMAG) != 0)
97 {
98 bad_elf:
Mark Wielaardf15bcda2014-03-03 11:43:43 +010099 free (buffer);
Mark Wielaard9202fe12015-05-19 13:39:39 +0200100 free (phdrsp);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000101 __libdwfl_seterrno (DWFL_E_BADELF);
102 return NULL;
103 }
104
105 /* Extract the information we need from the file header. */
106
107 union
108 {
109 Elf32_Ehdr e32;
110 Elf64_Ehdr e64;
111 } ehdr;
112 Elf_Data xlatefrom =
113 {
114 .d_type = ELF_T_EHDR,
115 .d_buf = buffer,
116 .d_version = EV_CURRENT,
117 };
118 Elf_Data xlateto =
119 {
120 .d_type = ELF_T_EHDR,
121 .d_buf = &ehdr,
122 .d_size = sizeof ehdr,
123 .d_version = EV_CURRENT,
124 };
125
126 GElf_Off phoff;
127 uint_fast16_t phnum;
128 uint_fast16_t phentsize;
129 GElf_Off shdrs_end;
130
131 switch (buffer[EI_CLASS])
132 {
133 case ELFCLASS32:
134 xlatefrom.d_size = sizeof (Elf32_Ehdr);
135 if (elf32_xlatetom (&xlateto, &xlatefrom, buffer[EI_DATA]) == NULL)
136 {
137 libelf_error:
138 __libdwfl_seterrno (DWFL_E_LIBELF);
139 return NULL;
140 }
141 phoff = ehdr.e32.e_phoff;
142 phnum = ehdr.e32.e_phnum;
143 phentsize = ehdr.e32.e_phentsize;
144 if (phentsize != sizeof (Elf32_Phdr) || phnum == 0)
145 goto bad_elf;
146 shdrs_end = ehdr.e32.e_shoff + ehdr.e32.e_shnum * ehdr.e32.e_shentsize;
147 break;
148
149 case ELFCLASS64:
150 xlatefrom.d_size = sizeof (Elf64_Ehdr);
Ulrich Drepper6258e742007-03-13 06:22:40 +0000151 if (elf64_xlatetom (&xlateto, &xlatefrom, buffer[EI_DATA]) == NULL)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000152 goto libelf_error;
153 phoff = ehdr.e64.e_phoff;
154 phnum = ehdr.e64.e_phnum;
155 phentsize = ehdr.e64.e_phentsize;
156 if (phentsize != sizeof (Elf64_Phdr) || phnum == 0)
157 goto bad_elf;
158 shdrs_end = ehdr.e64.e_shoff + ehdr.e64.e_shnum * ehdr.e64.e_shentsize;
159 break;
160
161 default:
162 goto bad_elf;
163 }
164
165
166 /* The file header tells where to find the program headers.
167 These are what we use to actually choose what to read. */
168
169 xlatefrom.d_type = xlateto.d_type = ELF_T_PHDR;
170 xlatefrom.d_size = phnum * phentsize;
171
172 if ((size_t) nread >= phoff + phnum * phentsize)
173 /* We already have all the phdrs from the initial read. */
174 xlatefrom.d_buf = buffer + phoff;
175 else
176 {
177 /* Read in the program headers. */
178
179 if (initial_bufsize < phnum * phentsize)
180 {
181 unsigned char *newbuf = realloc (buffer, phnum * phentsize);
182 if (newbuf == NULL)
183 {
184 free (buffer);
Mark Wielaard9202fe12015-05-19 13:39:39 +0200185 free (phdrsp);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000186 goto no_memory;
187 }
188 buffer = newbuf;
189 }
190 nread = (*read_memory) (arg, buffer, ehdr_vma + phoff,
191 phnum * phentsize, phnum * phentsize);
192 if (nread <= 0)
193 goto read_error;
194
195 xlatefrom.d_buf = buffer;
196 }
197
Chih-Hung Hsieh7eff36d2015-10-06 15:53:15 -0700198 if (unlikely (phnum >
199 SIZE_MAX / MAX (sizeof (Elf32_Phdr), sizeof (Elf64_Phdr))))
200 {
201 free (buffer);
202 goto no_memory;
203 }
204 const size_t phdrsp_bytes =
205 phnum * MAX (sizeof (Elf32_Phdr), sizeof (Elf64_Phdr));
206 phdrsp = malloc (phdrsp_bytes);
207 Elf32_Phdr (*p32)[phnum] = phdrsp;
208 Elf64_Phdr (*p64)[phnum] = phdrsp;
Mark Wielaard9202fe12015-05-19 13:39:39 +0200209 if (unlikely (phdrsp == NULL))
210 {
211 free (buffer);
212 goto no_memory;
213 }
Mark Wielaard9202fe12015-05-19 13:39:39 +0200214
Chih-Hung Hsieh7eff36d2015-10-06 15:53:15 -0700215 xlateto.d_buf = phdrsp;
216 xlateto.d_size = phdrsp_bytes;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000217
218 /* Scan for PT_LOAD segments to find the total size of the file image. */
219 size_t contents_size = 0;
220 GElf_Off segments_end = 0;
Mark Wielaarddd64d4a2014-03-03 15:07:31 +0100221 GElf_Off segments_end_mem = 0;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000222 GElf_Addr loadbase = ehdr_vma;
Roland McGrath099dd522007-08-13 22:58:36 +0000223 bool found_base = false;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000224 switch (ehdr.e32.e_ident[EI_CLASS])
225 {
Mark Wielaardf15bcda2014-03-03 11:43:43 +0100226 /* Sanity checks segments and calculates segment_end,
227 segments_end, segments_end_mem and loadbase (if not
228 found_base yet). Returns true if sanity checking failed,
229 false otherwise. */
230 inline bool handle_segment (GElf_Addr vaddr, GElf_Off offset,
Mark Wielaard32b6c6a2014-12-19 15:40:16 +0100231 GElf_Xword filesz, GElf_Xword memsz)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000232 {
Mark Wielaard32b6c6a2014-12-19 15:40:16 +0100233 /* Sanity check the segment load aligns with the pagesize. */
234 if (((vaddr - offset) & (pagesize - 1)) != 0)
Mark Wielaardf15bcda2014-03-03 11:43:43 +0100235 return true;
236
237 GElf_Off segment_end = ((offset + filesz + pagesize - 1)
238 & -pagesize);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000239
240 if (segment_end > (GElf_Off) contents_size)
241 contents_size = segment_end;
242
Mark Wielaardf15bcda2014-03-03 11:43:43 +0100243 if (!found_base && (offset & -pagesize) == 0)
Roland McGrath099dd522007-08-13 22:58:36 +0000244 {
Mark Wielaardf15bcda2014-03-03 11:43:43 +0100245 loadbase = ehdr_vma - (vaddr & -pagesize);
Roland McGrath099dd522007-08-13 22:58:36 +0000246 found_base = true;
247 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000248
249 segments_end = offset + filesz;
Mark Wielaarddd64d4a2014-03-03 15:07:31 +0100250 segments_end_mem = offset + memsz;
Mark Wielaardf15bcda2014-03-03 11:43:43 +0100251 return false;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000252 }
253
254 case ELFCLASS32:
255 if (elf32_xlatetom (&xlateto, &xlatefrom,
256 ehdr.e32.e_ident[EI_DATA]) == NULL)
257 goto libelf_error;
258 for (uint_fast16_t i = 0; i < phnum; ++i)
Chih-Hung Hsieh7eff36d2015-10-06 15:53:15 -0700259 if ((*p32)[i].p_type == PT_LOAD)
260 if (handle_segment ((*p32)[i].p_vaddr, (*p32)[i].p_offset,
261 (*p32)[i].p_filesz, (*p32)[i].p_memsz))
Mark Wielaardf15bcda2014-03-03 11:43:43 +0100262 goto bad_elf;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000263 break;
264
265 case ELFCLASS64:
Roland McGrath01fef9d2011-12-02 09:45:53 -0800266 if (elf64_xlatetom (&xlateto, &xlatefrom,
267 ehdr.e64.e_ident[EI_DATA]) == NULL)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000268 goto libelf_error;
269 for (uint_fast16_t i = 0; i < phnum; ++i)
Chih-Hung Hsieh7eff36d2015-10-06 15:53:15 -0700270 if ((*p64)[i].p_type == PT_LOAD)
271 if (handle_segment ((*p64)[i].p_vaddr, (*p64)[i].p_offset,
272 (*p64)[i].p_filesz, (*p64)[i].p_memsz))
Mark Wielaardf15bcda2014-03-03 11:43:43 +0100273 goto bad_elf;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000274 break;
275
276 default:
277 abort ();
278 break;
279 }
280
281 /* Trim the last segment so we don't bother with zeros in the last page
282 that are off the end of the file. However, if the extra bit in that
Mark Wielaarddd64d4a2014-03-03 15:07:31 +0100283 page includes the section headers and the memory isn't extended (which
284 might indicate it will have been reused otherwise), keep them. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000285 if ((GElf_Off) contents_size > segments_end
Mark Wielaarddd64d4a2014-03-03 15:07:31 +0100286 && (GElf_Off) contents_size >= shdrs_end
287 && segments_end == segments_end_mem)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000288 {
289 contents_size = segments_end;
290 if ((GElf_Off) contents_size < shdrs_end)
291 contents_size = shdrs_end;
292 }
293 else
294 contents_size = segments_end;
295
296 free (buffer);
297
298 /* Now we know the size of the whole image we want read in. */
299 buffer = calloc (1, contents_size);
300 if (buffer == NULL)
Mark Wielaard9202fe12015-05-19 13:39:39 +0200301 {
302 free (phdrsp);
303 goto no_memory;
304 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000305
306 switch (ehdr.e32.e_ident[EI_CLASS])
307 {
Mark Wielaardf15bcda2014-03-03 11:43:43 +0100308 /* Reads the given segment. Returns true if reading fails,
309 false otherwise. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000310 inline bool handle_segment (GElf_Addr vaddr, GElf_Off offset,
Mark Wielaardf15bcda2014-03-03 11:43:43 +0100311 GElf_Xword filesz)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000312 {
Mark Wielaardf15bcda2014-03-03 11:43:43 +0100313 GElf_Off start = offset & -pagesize;
314 GElf_Off end = (offset + filesz + pagesize - 1) & -pagesize;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000315 if (end > (GElf_Off) contents_size)
316 end = contents_size;
317 nread = (*read_memory) (arg, buffer + start,
Mark Wielaardf15bcda2014-03-03 11:43:43 +0100318 (loadbase + vaddr) & -pagesize,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000319 end - start, end - start);
320 return nread <= 0;
321 }
322
323 case ELFCLASS32:
324 for (uint_fast16_t i = 0; i < phnum; ++i)
Chih-Hung Hsieh7eff36d2015-10-06 15:53:15 -0700325 if ((*p32)[i].p_type == PT_LOAD)
326 if (handle_segment ((*p32)[i].p_vaddr, (*p32)[i].p_offset,
327 (*p32)[i].p_filesz))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000328 goto read_error;
329
330 /* If the segments visible in memory didn't include the section
331 headers, then clear them from the file header. */
332 if (contents_size < shdrs_end)
333 {
334 ehdr.e32.e_shoff = 0;
335 ehdr.e32.e_shnum = 0;
336 ehdr.e32.e_shstrndx = 0;
337 }
338
339 /* This will normally have been in the first PT_LOAD segment. But it
340 conceivably could be missing, and we might have just changed it. */
341 xlatefrom.d_type = xlateto.d_type = ELF_T_EHDR;
342 xlatefrom.d_size = xlateto.d_size = sizeof ehdr.e32;
343 xlatefrom.d_buf = &ehdr.e32;
344 xlateto.d_buf = buffer;
345 if (elf32_xlatetof (&xlateto, &xlatefrom,
346 ehdr.e32.e_ident[EI_DATA]) == NULL)
347 goto libelf_error;
348 break;
349
350 case ELFCLASS64:
351 for (uint_fast16_t i = 0; i < phnum; ++i)
Chih-Hung Hsieh7eff36d2015-10-06 15:53:15 -0700352 if ((*p64)[i].p_type == PT_LOAD)
353 if (handle_segment ((*p64)[i].p_vaddr, (*p64)[i].p_offset,
354 (*p64)[i].p_filesz))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000355 goto read_error;
356
357 /* If the segments visible in memory didn't include the section
358 headers, then clear them from the file header. */
359 if (contents_size < shdrs_end)
360 {
361 ehdr.e64.e_shoff = 0;
362 ehdr.e64.e_shnum = 0;
363 ehdr.e64.e_shstrndx = 0;
364 }
365
366 /* This will normally have been in the first PT_LOAD segment. But it
367 conceivably could be missing, and we might have just changed it. */
368 xlatefrom.d_type = xlateto.d_type = ELF_T_EHDR;
369 xlatefrom.d_size = xlateto.d_size = sizeof ehdr.e64;
370 xlatefrom.d_buf = &ehdr.e64;
371 xlateto.d_buf = buffer;
Ulrich Drepperd5a75192006-06-15 03:07:46 +0000372 if (elf64_xlatetof (&xlateto, &xlatefrom,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000373 ehdr.e64.e_ident[EI_DATA]) == NULL)
374 goto libelf_error;
375 break;
376
377 default:
378 abort ();
379 break;
380 }
381
Mark Wielaard9202fe12015-05-19 13:39:39 +0200382 free (phdrsp);
Chih-Hung Hsieh7eff36d2015-10-06 15:53:15 -0700383 phdrsp = NULL;
Mark Wielaard9202fe12015-05-19 13:39:39 +0200384
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000385 /* Now we have the image. Open libelf on it. */
386
387 Elf *elf = elf_memory ((char *) buffer, contents_size);
388 if (elf == NULL)
389 {
390 free (buffer);
Ulrich Drepperd5a75192006-06-15 03:07:46 +0000391 goto libelf_error;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000392 }
393
394 elf->flags |= ELF_F_MALLOCED;
395 if (loadbasep != NULL)
396 *loadbasep = loadbase;
397 return elf;
398}