blob: b35fac71916d11f555aefd211cc36c5b6e409d7e [file] [log] [blame]
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001/* Reconstruct an ELF file by reading the segments out of remote memory.
Mark Wielaardf15bcda2014-03-03 11:43:43 +01002 Copyright (C) 2005-2011, 2014 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{
66 /* First read in the file header and check its sanity. */
67
68 const size_t initial_bufsize = 256;
69 unsigned char *buffer = malloc (initial_bufsize);
70 if (buffer == NULL)
71 {
72 no_memory:
73 __libdwfl_seterrno (DWFL_E_NOMEM);
74 return NULL;
75 }
76
77 ssize_t nread = (*read_memory) (arg, buffer, ehdr_vma,
78 sizeof (Elf32_Ehdr), initial_bufsize);
79 if (nread <= 0)
80 {
81 read_error:
82 free (buffer);
83 __libdwfl_seterrno (nread < 0 ? DWFL_E_ERRNO : DWFL_E_TRUNCATED);
84 return NULL;
85 }
86
87 if (memcmp (buffer, ELFMAG, SELFMAG) != 0)
88 {
89 bad_elf:
Mark Wielaardf15bcda2014-03-03 11:43:43 +010090 free (buffer);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +000091 __libdwfl_seterrno (DWFL_E_BADELF);
92 return NULL;
93 }
94
95 /* Extract the information we need from the file header. */
96
97 union
98 {
99 Elf32_Ehdr e32;
100 Elf64_Ehdr e64;
101 } ehdr;
102 Elf_Data xlatefrom =
103 {
104 .d_type = ELF_T_EHDR,
105 .d_buf = buffer,
106 .d_version = EV_CURRENT,
107 };
108 Elf_Data xlateto =
109 {
110 .d_type = ELF_T_EHDR,
111 .d_buf = &ehdr,
112 .d_size = sizeof ehdr,
113 .d_version = EV_CURRENT,
114 };
115
116 GElf_Off phoff;
117 uint_fast16_t phnum;
118 uint_fast16_t phentsize;
119 GElf_Off shdrs_end;
120
121 switch (buffer[EI_CLASS])
122 {
123 case ELFCLASS32:
124 xlatefrom.d_size = sizeof (Elf32_Ehdr);
125 if (elf32_xlatetom (&xlateto, &xlatefrom, buffer[EI_DATA]) == NULL)
126 {
127 libelf_error:
128 __libdwfl_seterrno (DWFL_E_LIBELF);
129 return NULL;
130 }
131 phoff = ehdr.e32.e_phoff;
132 phnum = ehdr.e32.e_phnum;
133 phentsize = ehdr.e32.e_phentsize;
134 if (phentsize != sizeof (Elf32_Phdr) || phnum == 0)
135 goto bad_elf;
136 shdrs_end = ehdr.e32.e_shoff + ehdr.e32.e_shnum * ehdr.e32.e_shentsize;
137 break;
138
139 case ELFCLASS64:
140 xlatefrom.d_size = sizeof (Elf64_Ehdr);
Ulrich Drepper6258e742007-03-13 06:22:40 +0000141 if (elf64_xlatetom (&xlateto, &xlatefrom, buffer[EI_DATA]) == NULL)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000142 goto libelf_error;
143 phoff = ehdr.e64.e_phoff;
144 phnum = ehdr.e64.e_phnum;
145 phentsize = ehdr.e64.e_phentsize;
146 if (phentsize != sizeof (Elf64_Phdr) || phnum == 0)
147 goto bad_elf;
148 shdrs_end = ehdr.e64.e_shoff + ehdr.e64.e_shnum * ehdr.e64.e_shentsize;
149 break;
150
151 default:
152 goto bad_elf;
153 }
154
155
156 /* The file header tells where to find the program headers.
157 These are what we use to actually choose what to read. */
158
159 xlatefrom.d_type = xlateto.d_type = ELF_T_PHDR;
160 xlatefrom.d_size = phnum * phentsize;
161
162 if ((size_t) nread >= phoff + phnum * phentsize)
163 /* We already have all the phdrs from the initial read. */
164 xlatefrom.d_buf = buffer + phoff;
165 else
166 {
167 /* Read in the program headers. */
168
169 if (initial_bufsize < phnum * phentsize)
170 {
171 unsigned char *newbuf = realloc (buffer, phnum * phentsize);
172 if (newbuf == NULL)
173 {
174 free (buffer);
175 goto no_memory;
176 }
177 buffer = newbuf;
178 }
179 nread = (*read_memory) (arg, buffer, ehdr_vma + phoff,
180 phnum * phentsize, phnum * phentsize);
181 if (nread <= 0)
182 goto read_error;
183
184 xlatefrom.d_buf = buffer;
185 }
186
187 union
188 {
189 Elf32_Phdr p32[phnum];
190 Elf64_Phdr p64[phnum];
191 } phdrs;
192
193 xlateto.d_buf = &phdrs;
194 xlateto.d_size = sizeof phdrs;
195
196 /* Scan for PT_LOAD segments to find the total size of the file image. */
197 size_t contents_size = 0;
198 GElf_Off segments_end = 0;
Mark Wielaarddd64d4a2014-03-03 15:07:31 +0100199 GElf_Off segments_end_mem = 0;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000200 GElf_Addr loadbase = ehdr_vma;
Roland McGrath099dd522007-08-13 22:58:36 +0000201 bool found_base = false;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000202 switch (ehdr.e32.e_ident[EI_CLASS])
203 {
Mark Wielaardf15bcda2014-03-03 11:43:43 +0100204 /* Sanity checks segments and calculates segment_end,
205 segments_end, segments_end_mem and loadbase (if not
206 found_base yet). Returns true if sanity checking failed,
207 false otherwise. */
208 inline bool handle_segment (GElf_Addr vaddr, GElf_Off offset,
Mark Wielaard32b6c6a2014-12-19 15:40:16 +0100209 GElf_Xword filesz, GElf_Xword memsz)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000210 {
Mark Wielaard32b6c6a2014-12-19 15:40:16 +0100211 /* Sanity check the segment load aligns with the pagesize. */
212 if (((vaddr - offset) & (pagesize - 1)) != 0)
Mark Wielaardf15bcda2014-03-03 11:43:43 +0100213 return true;
214
215 GElf_Off segment_end = ((offset + filesz + pagesize - 1)
216 & -pagesize);
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000217
218 if (segment_end > (GElf_Off) contents_size)
219 contents_size = segment_end;
220
Mark Wielaardf15bcda2014-03-03 11:43:43 +0100221 if (!found_base && (offset & -pagesize) == 0)
Roland McGrath099dd522007-08-13 22:58:36 +0000222 {
Mark Wielaardf15bcda2014-03-03 11:43:43 +0100223 loadbase = ehdr_vma - (vaddr & -pagesize);
Roland McGrath099dd522007-08-13 22:58:36 +0000224 found_base = true;
225 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000226
227 segments_end = offset + filesz;
Mark Wielaarddd64d4a2014-03-03 15:07:31 +0100228 segments_end_mem = offset + memsz;
Mark Wielaardf15bcda2014-03-03 11:43:43 +0100229 return false;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000230 }
231
232 case ELFCLASS32:
233 if (elf32_xlatetom (&xlateto, &xlatefrom,
234 ehdr.e32.e_ident[EI_DATA]) == NULL)
235 goto libelf_error;
236 for (uint_fast16_t i = 0; i < phnum; ++i)
237 if (phdrs.p32[i].p_type == PT_LOAD)
Mark Wielaardf15bcda2014-03-03 11:43:43 +0100238 if (handle_segment (phdrs.p32[i].p_vaddr, phdrs.p32[i].p_offset,
Mark Wielaard32b6c6a2014-12-19 15:40:16 +0100239 phdrs.p32[i].p_filesz, phdrs.p32[i].p_memsz))
Mark Wielaardf15bcda2014-03-03 11:43:43 +0100240 goto bad_elf;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000241 break;
242
243 case ELFCLASS64:
Roland McGrath01fef9d2011-12-02 09:45:53 -0800244 if (elf64_xlatetom (&xlateto, &xlatefrom,
245 ehdr.e64.e_ident[EI_DATA]) == NULL)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000246 goto libelf_error;
247 for (uint_fast16_t i = 0; i < phnum; ++i)
Roland McGrath01fef9d2011-12-02 09:45:53 -0800248 if (phdrs.p64[i].p_type == PT_LOAD)
Mark Wielaardf15bcda2014-03-03 11:43:43 +0100249 if (handle_segment (phdrs.p64[i].p_vaddr, phdrs.p64[i].p_offset,
Mark Wielaard32b6c6a2014-12-19 15:40:16 +0100250 phdrs.p64[i].p_filesz, phdrs.p64[i].p_memsz))
Mark Wielaardf15bcda2014-03-03 11:43:43 +0100251 goto bad_elf;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000252 break;
253
254 default:
255 abort ();
256 break;
257 }
258
259 /* Trim the last segment so we don't bother with zeros in the last page
260 that are off the end of the file. However, if the extra bit in that
Mark Wielaarddd64d4a2014-03-03 15:07:31 +0100261 page includes the section headers and the memory isn't extended (which
262 might indicate it will have been reused otherwise), keep them. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000263 if ((GElf_Off) contents_size > segments_end
Mark Wielaarddd64d4a2014-03-03 15:07:31 +0100264 && (GElf_Off) contents_size >= shdrs_end
265 && segments_end == segments_end_mem)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000266 {
267 contents_size = segments_end;
268 if ((GElf_Off) contents_size < shdrs_end)
269 contents_size = shdrs_end;
270 }
271 else
272 contents_size = segments_end;
273
274 free (buffer);
275
276 /* Now we know the size of the whole image we want read in. */
277 buffer = calloc (1, contents_size);
278 if (buffer == NULL)
279 goto no_memory;
280
281 switch (ehdr.e32.e_ident[EI_CLASS])
282 {
Mark Wielaardf15bcda2014-03-03 11:43:43 +0100283 /* Reads the given segment. Returns true if reading fails,
284 false otherwise. */
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000285 inline bool handle_segment (GElf_Addr vaddr, GElf_Off offset,
Mark Wielaardf15bcda2014-03-03 11:43:43 +0100286 GElf_Xword filesz)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000287 {
Mark Wielaardf15bcda2014-03-03 11:43:43 +0100288 GElf_Off start = offset & -pagesize;
289 GElf_Off end = (offset + filesz + pagesize - 1) & -pagesize;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000290 if (end > (GElf_Off) contents_size)
291 end = contents_size;
292 nread = (*read_memory) (arg, buffer + start,
Mark Wielaardf15bcda2014-03-03 11:43:43 +0100293 (loadbase + vaddr) & -pagesize,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000294 end - start, end - start);
295 return nread <= 0;
296 }
297
298 case ELFCLASS32:
299 for (uint_fast16_t i = 0; i < phnum; ++i)
300 if (phdrs.p32[i].p_type == PT_LOAD)
301 if (handle_segment (phdrs.p32[i].p_vaddr, phdrs.p32[i].p_offset,
Mark Wielaardf15bcda2014-03-03 11:43:43 +0100302 phdrs.p32[i].p_filesz))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000303 goto read_error;
304
305 /* If the segments visible in memory didn't include the section
306 headers, then clear them from the file header. */
307 if (contents_size < shdrs_end)
308 {
309 ehdr.e32.e_shoff = 0;
310 ehdr.e32.e_shnum = 0;
311 ehdr.e32.e_shstrndx = 0;
312 }
313
314 /* This will normally have been in the first PT_LOAD segment. But it
315 conceivably could be missing, and we might have just changed it. */
316 xlatefrom.d_type = xlateto.d_type = ELF_T_EHDR;
317 xlatefrom.d_size = xlateto.d_size = sizeof ehdr.e32;
318 xlatefrom.d_buf = &ehdr.e32;
319 xlateto.d_buf = buffer;
320 if (elf32_xlatetof (&xlateto, &xlatefrom,
321 ehdr.e32.e_ident[EI_DATA]) == NULL)
322 goto libelf_error;
323 break;
324
325 case ELFCLASS64:
326 for (uint_fast16_t i = 0; i < phnum; ++i)
Mark Wielaard48827ec2014-02-26 17:17:07 +0100327 if (phdrs.p64[i].p_type == PT_LOAD)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000328 if (handle_segment (phdrs.p64[i].p_vaddr, phdrs.p64[i].p_offset,
Mark Wielaardf15bcda2014-03-03 11:43:43 +0100329 phdrs.p64[i].p_filesz))
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000330 goto read_error;
331
332 /* If the segments visible in memory didn't include the section
333 headers, then clear them from the file header. */
334 if (contents_size < shdrs_end)
335 {
336 ehdr.e64.e_shoff = 0;
337 ehdr.e64.e_shnum = 0;
338 ehdr.e64.e_shstrndx = 0;
339 }
340
341 /* This will normally have been in the first PT_LOAD segment. But it
342 conceivably could be missing, and we might have just changed it. */
343 xlatefrom.d_type = xlateto.d_type = ELF_T_EHDR;
344 xlatefrom.d_size = xlateto.d_size = sizeof ehdr.e64;
345 xlatefrom.d_buf = &ehdr.e64;
346 xlateto.d_buf = buffer;
Ulrich Drepperd5a75192006-06-15 03:07:46 +0000347 if (elf64_xlatetof (&xlateto, &xlatefrom,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000348 ehdr.e64.e_ident[EI_DATA]) == NULL)
349 goto libelf_error;
350 break;
351
352 default:
353 abort ();
354 break;
355 }
356
357 /* Now we have the image. Open libelf on it. */
358
359 Elf *elf = elf_memory ((char *) buffer, contents_size);
360 if (elf == NULL)
361 {
362 free (buffer);
Ulrich Drepperd5a75192006-06-15 03:07:46 +0000363 goto libelf_error;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000364 }
365
366 elf->flags |= ELF_F_MALLOCED;
367 if (loadbasep != NULL)
368 *loadbasep = loadbase;
369 return elf;
370}