blob: 3175ab16346c7cf10b00b812e9b1cd77bfc6f916 [file] [log] [blame]
Ulrich Drepperb08d5a82005-07-26 05:00:05 +00001/* Reconstruct an ELF file by reading the segments out of remote memory.
2 Copyright (C) 2005 Red Hat, Inc.
3
4 This program is Open Source software; you can redistribute it and/or
5 modify it under the terms of the Open Software License version 1.0 as
6 published by the Open Source Initiative.
7
8 You should have received a copy of the Open Software License along
9 with this program; if not, you may obtain a copy of the Open Software
10 License version 1.0 from http://www.opensource.org/licenses/osl.php or
11 by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
12 3001 King Ranch Road, Ukiah, CA 95482. */
13
14#include <config.h>
15#include "../libelf/libelfP.h"
16#undef _
17
18#include "libdwflP.h"
19
20#include <gelf.h>
21#include <sys/types.h>
22#include <stdbool.h>
23#include <stdlib.h>
24#include <string.h>
25
26/* Reconstruct an ELF file by reading the segments out of remote memory
27 based on the ELF file header at EHDR_VMA and the ELF program headers it
28 points to. If not null, *LOADBASEP is filled in with the difference
29 between the addresses from which the segments were read, and the
30 addresses the file headers put them at.
31
32 The function READ_MEMORY is called to copy at least MINREAD and at most
33 MAXREAD bytes from the remote memory at target address ADDRESS into the
34 local buffer at DATA; it should return -1 for errors (with code in
35 `errno'), 0 if it failed to read at least MINREAD bytes due to EOF, or
36 the number of bytes read if >= MINREAD. ARG is passed through. */
37
38Elf *
39elf_from_remote_memory (GElf_Addr ehdr_vma,
40 GElf_Addr *loadbasep,
41 ssize_t (*read_memory) (void *arg, void *data,
42 GElf_Addr address,
43 size_t minread,
44 size_t maxread),
45 void *arg)
46{
47 /* First read in the file header and check its sanity. */
48
49 const size_t initial_bufsize = 256;
50 unsigned char *buffer = malloc (initial_bufsize);
51 if (buffer == NULL)
52 {
53 no_memory:
54 __libdwfl_seterrno (DWFL_E_NOMEM);
55 return NULL;
56 }
57
58 ssize_t nread = (*read_memory) (arg, buffer, ehdr_vma,
59 sizeof (Elf32_Ehdr), initial_bufsize);
60 if (nread <= 0)
61 {
62 read_error:
63 free (buffer);
64 __libdwfl_seterrno (nread < 0 ? DWFL_E_ERRNO : DWFL_E_TRUNCATED);
65 return NULL;
66 }
67
68 if (memcmp (buffer, ELFMAG, SELFMAG) != 0)
69 {
70 bad_elf:
71 __libdwfl_seterrno (DWFL_E_BADELF);
72 return NULL;
73 }
74
75 /* Extract the information we need from the file header. */
76
77 union
78 {
79 Elf32_Ehdr e32;
80 Elf64_Ehdr e64;
81 } ehdr;
82 Elf_Data xlatefrom =
83 {
84 .d_type = ELF_T_EHDR,
85 .d_buf = buffer,
86 .d_version = EV_CURRENT,
87 };
88 Elf_Data xlateto =
89 {
90 .d_type = ELF_T_EHDR,
91 .d_buf = &ehdr,
92 .d_size = sizeof ehdr,
93 .d_version = EV_CURRENT,
94 };
95
96 GElf_Off phoff;
97 uint_fast16_t phnum;
98 uint_fast16_t phentsize;
99 GElf_Off shdrs_end;
100
101 switch (buffer[EI_CLASS])
102 {
103 case ELFCLASS32:
104 xlatefrom.d_size = sizeof (Elf32_Ehdr);
105 if (elf32_xlatetom (&xlateto, &xlatefrom, buffer[EI_DATA]) == NULL)
106 {
107 libelf_error:
108 __libdwfl_seterrno (DWFL_E_LIBELF);
109 return NULL;
110 }
111 phoff = ehdr.e32.e_phoff;
112 phnum = ehdr.e32.e_phnum;
113 phentsize = ehdr.e32.e_phentsize;
114 if (phentsize != sizeof (Elf32_Phdr) || phnum == 0)
115 goto bad_elf;
116 shdrs_end = ehdr.e32.e_shoff + ehdr.e32.e_shnum * ehdr.e32.e_shentsize;
117 break;
118
119 case ELFCLASS64:
120 xlatefrom.d_size = sizeof (Elf64_Ehdr);
121 if (elf32_xlatetom (&xlateto, &xlatefrom, buffer[EI_DATA]) == NULL)
122 goto libelf_error;
123 phoff = ehdr.e64.e_phoff;
124 phnum = ehdr.e64.e_phnum;
125 phentsize = ehdr.e64.e_phentsize;
126 if (phentsize != sizeof (Elf64_Phdr) || phnum == 0)
127 goto bad_elf;
128 shdrs_end = ehdr.e64.e_shoff + ehdr.e64.e_shnum * ehdr.e64.e_shentsize;
129 break;
130
131 default:
132 goto bad_elf;
133 }
134
135
136 /* The file header tells where to find the program headers.
137 These are what we use to actually choose what to read. */
138
139 xlatefrom.d_type = xlateto.d_type = ELF_T_PHDR;
140 xlatefrom.d_size = phnum * phentsize;
141
142 if ((size_t) nread >= phoff + phnum * phentsize)
143 /* We already have all the phdrs from the initial read. */
144 xlatefrom.d_buf = buffer + phoff;
145 else
146 {
147 /* Read in the program headers. */
148
149 if (initial_bufsize < phnum * phentsize)
150 {
151 unsigned char *newbuf = realloc (buffer, phnum * phentsize);
152 if (newbuf == NULL)
153 {
154 free (buffer);
155 goto no_memory;
156 }
157 buffer = newbuf;
158 }
159 nread = (*read_memory) (arg, buffer, ehdr_vma + phoff,
160 phnum * phentsize, phnum * phentsize);
161 if (nread <= 0)
162 goto read_error;
163
164 xlatefrom.d_buf = buffer;
165 }
166
167 union
168 {
169 Elf32_Phdr p32[phnum];
170 Elf64_Phdr p64[phnum];
171 } phdrs;
172
173 xlateto.d_buf = &phdrs;
174 xlateto.d_size = sizeof phdrs;
175
176 /* Scan for PT_LOAD segments to find the total size of the file image. */
177 size_t contents_size = 0;
178 GElf_Off segments_end = 0;
179 GElf_Addr loadbase = ehdr_vma;
180 switch (ehdr.e32.e_ident[EI_CLASS])
181 {
182 inline void handle_segment (GElf_Addr vaddr, GElf_Off offset,
183 GElf_Xword filesz, GElf_Xword align)
184 {
185 GElf_Off segment_end = ((offset + filesz + align - 1) & -align);
186
187 if (segment_end > (GElf_Off) contents_size)
188 contents_size = segment_end;
189
190 if ((offset & -align) == 0 && loadbase == ehdr_vma)
191 loadbase = ehdr_vma - (vaddr & -align);
192
193 segments_end = offset + filesz;
194 }
195
196 case ELFCLASS32:
197 if (elf32_xlatetom (&xlateto, &xlatefrom,
198 ehdr.e32.e_ident[EI_DATA]) == NULL)
199 goto libelf_error;
200 for (uint_fast16_t i = 0; i < phnum; ++i)
201 if (phdrs.p32[i].p_type == PT_LOAD)
202 handle_segment (phdrs.p32[i].p_vaddr, phdrs.p32[i].p_offset,
203 phdrs.p32[i].p_filesz, phdrs.p32[i].p_align);
204 break;
205
206 case ELFCLASS64:
207 if (elf32_xlatetom (&xlateto, &xlatefrom,
208 ehdr.e32.e_ident[EI_DATA]) == NULL)
209 goto libelf_error;
210 for (uint_fast16_t i = 0; i < phnum; ++i)
211 if (phdrs.p32[i].p_type == PT_LOAD)
212 handle_segment (phdrs.p64[i].p_vaddr, phdrs.p64[i].p_offset,
213 phdrs.p64[i].p_filesz, phdrs.p64[i].p_align);
214 break;
215
216 default:
217 abort ();
218 break;
219 }
220
221 /* Trim the last segment so we don't bother with zeros in the last page
222 that are off the end of the file. However, if the extra bit in that
223 page includes the section headers, keep them. */
224 if ((GElf_Off) contents_size > segments_end
225 && (GElf_Off) contents_size >= shdrs_end)
226 {
227 contents_size = segments_end;
228 if ((GElf_Off) contents_size < shdrs_end)
229 contents_size = shdrs_end;
230 }
231 else
232 contents_size = segments_end;
233
234 free (buffer);
235
236 /* Now we know the size of the whole image we want read in. */
237 buffer = calloc (1, contents_size);
238 if (buffer == NULL)
239 goto no_memory;
240
241 switch (ehdr.e32.e_ident[EI_CLASS])
242 {
243 inline bool handle_segment (GElf_Addr vaddr, GElf_Off offset,
244 GElf_Xword filesz, GElf_Xword align)
245 {
246 GElf_Off start = offset & -align;
247 GElf_Off end = (offset + filesz + align - 1) & -align;
248 if (end > (GElf_Off) contents_size)
249 end = contents_size;
250 nread = (*read_memory) (arg, buffer + start,
251 (loadbase + vaddr) & -align,
252 end - start, end - start);
253 return nread <= 0;
254 }
255
256 case ELFCLASS32:
257 for (uint_fast16_t i = 0; i < phnum; ++i)
258 if (phdrs.p32[i].p_type == PT_LOAD)
259 if (handle_segment (phdrs.p32[i].p_vaddr, phdrs.p32[i].p_offset,
260 phdrs.p32[i].p_filesz, phdrs.p32[i].p_align))
261 goto read_error;
262
263 /* If the segments visible in memory didn't include the section
264 headers, then clear them from the file header. */
265 if (contents_size < shdrs_end)
266 {
267 ehdr.e32.e_shoff = 0;
268 ehdr.e32.e_shnum = 0;
269 ehdr.e32.e_shstrndx = 0;
270 }
271
272 /* This will normally have been in the first PT_LOAD segment. But it
273 conceivably could be missing, and we might have just changed it. */
274 xlatefrom.d_type = xlateto.d_type = ELF_T_EHDR;
275 xlatefrom.d_size = xlateto.d_size = sizeof ehdr.e32;
276 xlatefrom.d_buf = &ehdr.e32;
277 xlateto.d_buf = buffer;
278 if (elf32_xlatetof (&xlateto, &xlatefrom,
279 ehdr.e32.e_ident[EI_DATA]) == NULL)
280 goto libelf_error;
281 break;
282
283 case ELFCLASS64:
284 for (uint_fast16_t i = 0; i < phnum; ++i)
285 if (phdrs.p32[i].p_type == PT_LOAD)
286 if (handle_segment (phdrs.p64[i].p_vaddr, phdrs.p64[i].p_offset,
287 phdrs.p64[i].p_filesz, phdrs.p64[i].p_align))
288 goto read_error;
289
290 /* If the segments visible in memory didn't include the section
291 headers, then clear them from the file header. */
292 if (contents_size < shdrs_end)
293 {
294 ehdr.e64.e_shoff = 0;
295 ehdr.e64.e_shnum = 0;
296 ehdr.e64.e_shstrndx = 0;
297 }
298
299 /* This will normally have been in the first PT_LOAD segment. But it
300 conceivably could be missing, and we might have just changed it. */
301 xlatefrom.d_type = xlateto.d_type = ELF_T_EHDR;
302 xlatefrom.d_size = xlateto.d_size = sizeof ehdr.e64;
303 xlatefrom.d_buf = &ehdr.e64;
304 xlateto.d_buf = buffer;
305 if (elf32_xlatetof (&xlateto, &xlatefrom,
306 ehdr.e64.e_ident[EI_DATA]) == NULL)
307 goto libelf_error;
308 break;
309
310 default:
311 abort ();
312 break;
313 }
314
315 /* Now we have the image. Open libelf on it. */
316
317 Elf *elf = elf_memory ((char *) buffer, contents_size);
318 if (elf == NULL)
319 {
320 free (buffer);
321 return NULL;
322 }
323
324 elf->flags |= ELF_F_MALLOCED;
325 if (loadbasep != NULL)
326 *loadbasep = loadbase;
327 return elf;
328}