blob: 528c35f41e22559478491a21f02f4c67ae24da6b [file] [log] [blame]
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001/* Reconstruct an ELF file by reading the segments out of remote memory.
Roland McGrath01fef9d2011-12-02 09:45:53 -08002 Copyright (C) 2005-2011 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
51 the number of bytes read if >= MINREAD. ARG is passed through. */
52
53Elf *
54elf_from_remote_memory (GElf_Addr ehdr_vma,
55 GElf_Addr *loadbasep,
56 ssize_t (*read_memory) (void *arg, void *data,
57 GElf_Addr address,
58 size_t minread,
59 size_t maxread),
60 void *arg)
61{
62 /* First read in the file header and check its sanity. */
63
64 const size_t initial_bufsize = 256;
65 unsigned char *buffer = malloc (initial_bufsize);
66 if (buffer == NULL)
67 {
68 no_memory:
69 __libdwfl_seterrno (DWFL_E_NOMEM);
70 return NULL;
71 }
72
73 ssize_t nread = (*read_memory) (arg, buffer, ehdr_vma,
74 sizeof (Elf32_Ehdr), initial_bufsize);
75 if (nread <= 0)
76 {
77 read_error:
78 free (buffer);
79 __libdwfl_seterrno (nread < 0 ? DWFL_E_ERRNO : DWFL_E_TRUNCATED);
80 return NULL;
81 }
82
83 if (memcmp (buffer, ELFMAG, SELFMAG) != 0)
84 {
85 bad_elf:
86 __libdwfl_seterrno (DWFL_E_BADELF);
87 return NULL;
88 }
89
90 /* Extract the information we need from the file header. */
91
92 union
93 {
94 Elf32_Ehdr e32;
95 Elf64_Ehdr e64;
96 } ehdr;
97 Elf_Data xlatefrom =
98 {
99 .d_type = ELF_T_EHDR,
100 .d_buf = buffer,
101 .d_version = EV_CURRENT,
102 };
103 Elf_Data xlateto =
104 {
105 .d_type = ELF_T_EHDR,
106 .d_buf = &ehdr,
107 .d_size = sizeof ehdr,
108 .d_version = EV_CURRENT,
109 };
110
111 GElf_Off phoff;
112 uint_fast16_t phnum;
113 uint_fast16_t phentsize;
114 GElf_Off shdrs_end;
115
116 switch (buffer[EI_CLASS])
117 {
118 case ELFCLASS32:
119 xlatefrom.d_size = sizeof (Elf32_Ehdr);
120 if (elf32_xlatetom (&xlateto, &xlatefrom, buffer[EI_DATA]) == NULL)
121 {
122 libelf_error:
123 __libdwfl_seterrno (DWFL_E_LIBELF);
124 return NULL;
125 }
126 phoff = ehdr.e32.e_phoff;
127 phnum = ehdr.e32.e_phnum;
128 phentsize = ehdr.e32.e_phentsize;
129 if (phentsize != sizeof (Elf32_Phdr) || phnum == 0)
130 goto bad_elf;
131 shdrs_end = ehdr.e32.e_shoff + ehdr.e32.e_shnum * ehdr.e32.e_shentsize;
132 break;
133
134 case ELFCLASS64:
135 xlatefrom.d_size = sizeof (Elf64_Ehdr);
Ulrich Drepper6258e742007-03-13 06:22:40 +0000136 if (elf64_xlatetom (&xlateto, &xlatefrom, buffer[EI_DATA]) == NULL)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000137 goto libelf_error;
138 phoff = ehdr.e64.e_phoff;
139 phnum = ehdr.e64.e_phnum;
140 phentsize = ehdr.e64.e_phentsize;
141 if (phentsize != sizeof (Elf64_Phdr) || phnum == 0)
142 goto bad_elf;
143 shdrs_end = ehdr.e64.e_shoff + ehdr.e64.e_shnum * ehdr.e64.e_shentsize;
144 break;
145
146 default:
147 goto bad_elf;
148 }
149
150
151 /* The file header tells where to find the program headers.
152 These are what we use to actually choose what to read. */
153
154 xlatefrom.d_type = xlateto.d_type = ELF_T_PHDR;
155 xlatefrom.d_size = phnum * phentsize;
156
157 if ((size_t) nread >= phoff + phnum * phentsize)
158 /* We already have all the phdrs from the initial read. */
159 xlatefrom.d_buf = buffer + phoff;
160 else
161 {
162 /* Read in the program headers. */
163
164 if (initial_bufsize < phnum * phentsize)
165 {
166 unsigned char *newbuf = realloc (buffer, phnum * phentsize);
167 if (newbuf == NULL)
168 {
169 free (buffer);
170 goto no_memory;
171 }
172 buffer = newbuf;
173 }
174 nread = (*read_memory) (arg, buffer, ehdr_vma + phoff,
175 phnum * phentsize, phnum * phentsize);
176 if (nread <= 0)
177 goto read_error;
178
179 xlatefrom.d_buf = buffer;
180 }
181
182 union
183 {
184 Elf32_Phdr p32[phnum];
185 Elf64_Phdr p64[phnum];
186 } phdrs;
187
188 xlateto.d_buf = &phdrs;
189 xlateto.d_size = sizeof phdrs;
190
191 /* Scan for PT_LOAD segments to find the total size of the file image. */
192 size_t contents_size = 0;
193 GElf_Off segments_end = 0;
194 GElf_Addr loadbase = ehdr_vma;
Roland McGrath099dd522007-08-13 22:58:36 +0000195 bool found_base = false;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000196 switch (ehdr.e32.e_ident[EI_CLASS])
197 {
198 inline void handle_segment (GElf_Addr vaddr, GElf_Off offset,
199 GElf_Xword filesz, GElf_Xword align)
200 {
201 GElf_Off segment_end = ((offset + filesz + align - 1) & -align);
202
203 if (segment_end > (GElf_Off) contents_size)
204 contents_size = segment_end;
205
Roland McGrath099dd522007-08-13 22:58:36 +0000206 if (!found_base && (offset & -align) == 0)
207 {
208 loadbase = ehdr_vma - (vaddr & -align);
209 found_base = true;
210 }
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000211
212 segments_end = offset + filesz;
213 }
214
215 case ELFCLASS32:
216 if (elf32_xlatetom (&xlateto, &xlatefrom,
217 ehdr.e32.e_ident[EI_DATA]) == NULL)
218 goto libelf_error;
219 for (uint_fast16_t i = 0; i < phnum; ++i)
220 if (phdrs.p32[i].p_type == PT_LOAD)
221 handle_segment (phdrs.p32[i].p_vaddr, phdrs.p32[i].p_offset,
222 phdrs.p32[i].p_filesz, phdrs.p32[i].p_align);
223 break;
224
225 case ELFCLASS64:
Roland McGrath01fef9d2011-12-02 09:45:53 -0800226 if (elf64_xlatetom (&xlateto, &xlatefrom,
227 ehdr.e64.e_ident[EI_DATA]) == NULL)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000228 goto libelf_error;
229 for (uint_fast16_t i = 0; i < phnum; ++i)
Roland McGrath01fef9d2011-12-02 09:45:53 -0800230 if (phdrs.p64[i].p_type == PT_LOAD)
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000231 handle_segment (phdrs.p64[i].p_vaddr, phdrs.p64[i].p_offset,
232 phdrs.p64[i].p_filesz, phdrs.p64[i].p_align);
233 break;
234
235 default:
236 abort ();
237 break;
238 }
239
240 /* Trim the last segment so we don't bother with zeros in the last page
241 that are off the end of the file. However, if the extra bit in that
242 page includes the section headers, keep them. */
243 if ((GElf_Off) contents_size > segments_end
244 && (GElf_Off) contents_size >= shdrs_end)
245 {
246 contents_size = segments_end;
247 if ((GElf_Off) contents_size < shdrs_end)
248 contents_size = shdrs_end;
249 }
250 else
251 contents_size = segments_end;
252
253 free (buffer);
254
255 /* Now we know the size of the whole image we want read in. */
256 buffer = calloc (1, contents_size);
257 if (buffer == NULL)
258 goto no_memory;
259
260 switch (ehdr.e32.e_ident[EI_CLASS])
261 {
262 inline bool handle_segment (GElf_Addr vaddr, GElf_Off offset,
263 GElf_Xword filesz, GElf_Xword align)
264 {
265 GElf_Off start = offset & -align;
266 GElf_Off end = (offset + filesz + align - 1) & -align;
267 if (end > (GElf_Off) contents_size)
268 end = contents_size;
269 nread = (*read_memory) (arg, buffer + start,
270 (loadbase + vaddr) & -align,
271 end - start, end - start);
272 return nread <= 0;
273 }
274
275 case ELFCLASS32:
276 for (uint_fast16_t i = 0; i < phnum; ++i)
277 if (phdrs.p32[i].p_type == PT_LOAD)
278 if (handle_segment (phdrs.p32[i].p_vaddr, phdrs.p32[i].p_offset,
279 phdrs.p32[i].p_filesz, phdrs.p32[i].p_align))
280 goto read_error;
281
282 /* If the segments visible in memory didn't include the section
283 headers, then clear them from the file header. */
284 if (contents_size < shdrs_end)
285 {
286 ehdr.e32.e_shoff = 0;
287 ehdr.e32.e_shnum = 0;
288 ehdr.e32.e_shstrndx = 0;
289 }
290
291 /* This will normally have been in the first PT_LOAD segment. But it
292 conceivably could be missing, and we might have just changed it. */
293 xlatefrom.d_type = xlateto.d_type = ELF_T_EHDR;
294 xlatefrom.d_size = xlateto.d_size = sizeof ehdr.e32;
295 xlatefrom.d_buf = &ehdr.e32;
296 xlateto.d_buf = buffer;
297 if (elf32_xlatetof (&xlateto, &xlatefrom,
298 ehdr.e32.e_ident[EI_DATA]) == NULL)
299 goto libelf_error;
300 break;
301
302 case ELFCLASS64:
303 for (uint_fast16_t i = 0; i < phnum; ++i)
304 if (phdrs.p32[i].p_type == PT_LOAD)
305 if (handle_segment (phdrs.p64[i].p_vaddr, phdrs.p64[i].p_offset,
306 phdrs.p64[i].p_filesz, phdrs.p64[i].p_align))
307 goto read_error;
308
309 /* If the segments visible in memory didn't include the section
310 headers, then clear them from the file header. */
311 if (contents_size < shdrs_end)
312 {
313 ehdr.e64.e_shoff = 0;
314 ehdr.e64.e_shnum = 0;
315 ehdr.e64.e_shstrndx = 0;
316 }
317
318 /* This will normally have been in the first PT_LOAD segment. But it
319 conceivably could be missing, and we might have just changed it. */
320 xlatefrom.d_type = xlateto.d_type = ELF_T_EHDR;
321 xlatefrom.d_size = xlateto.d_size = sizeof ehdr.e64;
322 xlatefrom.d_buf = &ehdr.e64;
323 xlateto.d_buf = buffer;
Ulrich Drepperd5a75192006-06-15 03:07:46 +0000324 if (elf64_xlatetof (&xlateto, &xlatefrom,
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000325 ehdr.e64.e_ident[EI_DATA]) == NULL)
326 goto libelf_error;
327 break;
328
329 default:
330 abort ();
331 break;
332 }
333
334 /* Now we have the image. Open libelf on it. */
335
336 Elf *elf = elf_memory ((char *) buffer, contents_size);
337 if (elf == NULL)
338 {
339 free (buffer);
Ulrich Drepperd5a75192006-06-15 03:07:46 +0000340 goto libelf_error;
Ulrich Drepperb08d5a82005-07-26 05:00:05 +0000341 }
342
343 elf->flags |= ELF_F_MALLOCED;
344 if (loadbasep != NULL)
345 *loadbasep = loadbase;
346 return elf;
347}