• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Reconstruct an ELF file by reading the segments out of remote memory.
2    Copyright (C) 2005-2011, 2014, 2015 Red Hat, Inc.
3    This file is part of elfutils.
4 
5    This file is free software; you can redistribute it and/or modify
6    it under the terms of either
7 
8      * 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
21    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 
25    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/>.  */
28 
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 
53    PAGESIZE is the minimum page size and alignment used for the PT_LOAD
54    segments.  */
55 
56 Elf *
elf_from_remote_memory(GElf_Addr ehdr_vma,GElf_Xword pagesize,GElf_Addr * loadbasep,ssize_t (* read_memory)(void * arg,void * data,GElf_Addr address,size_t minread,size_t maxread),void * arg)57 elf_from_remote_memory (GElf_Addr ehdr_vma,
58 			GElf_Xword pagesize,
59 			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   /* 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 
70   /* 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);
74   if (unlikely (buffer == NULL))
75     {
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);
87       free (phdrsp);
88       __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:
95       free (buffer);
96       free (phdrsp);
97       __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       /* NOTE if the number of sections is > 0xff00 then e_shnum
143 	 is zero and the actual number would come from the section
144 	 zero sh_size field. We ignore this here because getting shdrs
145 	 is just a nice bonus (see below where we trim the last phdrs
146 	 PT_LOAD segment).  */
147       shdrs_end = ehdr.e32.e_shoff + ehdr.e32.e_shnum * ehdr.e32.e_shentsize;
148       break;
149 
150     case ELFCLASS64:
151       xlatefrom.d_size = sizeof (Elf64_Ehdr);
152       if (elf64_xlatetom (&xlateto, &xlatefrom, buffer[EI_DATA]) == NULL)
153 	goto libelf_error;
154       phoff = ehdr.e64.e_phoff;
155       phnum = ehdr.e64.e_phnum;
156       phentsize = ehdr.e64.e_phentsize;
157       if (phentsize != sizeof (Elf64_Phdr) || phnum == 0)
158 	goto bad_elf;
159       /* See the NOTE above for shdrs_end and ehdr.e32.e_shnum.  */
160       shdrs_end = ehdr.e64.e_shoff + ehdr.e64.e_shnum * ehdr.e64.e_shentsize;
161       break;
162 
163     default:
164       goto bad_elf;
165     }
166 
167 
168   /* The file header tells where to find the program headers.
169      These are what we use to actually choose what to read.  */
170 
171   xlatefrom.d_type = xlateto.d_type = ELF_T_PHDR;
172   xlatefrom.d_size = phnum * phentsize;
173 
174   if ((size_t) nread >= phoff + phnum * phentsize)
175     /* We already have all the phdrs from the initial read.  */
176     xlatefrom.d_buf = buffer + phoff;
177   else
178     {
179       /* Read in the program headers.  */
180 
181       if (initial_bufsize < (size_t)phnum * phentsize)
182 	{
183 	  unsigned char *newbuf = realloc (buffer, phnum * phentsize);
184 	  if (newbuf == NULL)
185 	    {
186 	      free (buffer);
187 	      free (phdrsp);
188 	      goto no_memory;
189 	    }
190 	  buffer = newbuf;
191 	}
192       nread = (*read_memory) (arg, buffer, ehdr_vma + phoff,
193 			      phnum * phentsize, phnum * phentsize);
194       if (nread <= 0)
195 	goto read_error;
196 
197       xlatefrom.d_buf = buffer;
198     }
199 
200   bool class32 = ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32;
201   size_t phdr_size = class32 ? sizeof (Elf32_Phdr) : sizeof (Elf64_Phdr);
202   if (unlikely (phnum > SIZE_MAX / phdr_size))
203     {
204       free (buffer);
205       goto no_memory;
206     }
207   const size_t phdrsp_bytes = phnum * phdr_size;
208   phdrsp = malloc (phdrsp_bytes);
209   if (unlikely (phdrsp == NULL))
210     {
211       free (buffer);
212       goto no_memory;
213     }
214 
215   xlateto.d_buf = phdrsp;
216   xlateto.d_size = phdrsp_bytes;
217 
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;
221   GElf_Off segments_end_mem = 0;
222   GElf_Addr loadbase = ehdr_vma;
223   bool found_base = false;
224   Elf32_Phdr (*p32)[phnum] = phdrsp;
225   Elf64_Phdr (*p64)[phnum] = phdrsp;
226 
227   if (class32)
228     {
229       if (! elf32_xlatetom (&xlateto, &xlatefrom, ehdr.e32.e_ident[EI_DATA]))
230         goto libelf_error;
231     }
232   else
233     {
234       if (! elf64_xlatetom (&xlateto, &xlatefrom, ehdr.e64.e_ident[EI_DATA]))
235         goto libelf_error;
236     }
237 
238   for (uint_fast16_t i = 0; i < phnum; ++i)
239     {
240       GElf_Word type = class32 ? (*p32)[i].p_type : (*p64)[i].p_type;
241 
242       if (type != PT_LOAD)
243         continue;
244 
245       GElf_Addr vaddr = class32 ? (*p32)[i].p_vaddr : (*p64)[i].p_vaddr;
246       GElf_Xword memsz = class32 ? (*p32)[i].p_memsz : (*p64)[i].p_memsz;
247       GElf_Off offset = class32 ? (*p32)[i].p_offset : (*p64)[i].p_offset;
248       GElf_Xword filesz = class32 ? (*p32)[i].p_filesz : (*p64)[i].p_filesz;
249 
250       /* Sanity check the segment load aligns with the pagesize.  */
251       if (((vaddr - offset) & (pagesize - 1)) != 0)
252         goto bad_elf;
253 
254       GElf_Off segment_end = ((offset + filesz + pagesize - 1)
255                               & -pagesize);
256 
257       if (segment_end > (GElf_Off) contents_size)
258         contents_size = segment_end;
259 
260       if (!found_base && (offset & -pagesize) == 0)
261         {
262           loadbase = ehdr_vma - (vaddr & -pagesize);
263           found_base = true;
264         }
265 
266       segments_end = offset + filesz;
267       segments_end_mem = offset + memsz;
268     }
269 
270   /* Trim the last segment so we don't bother with zeros in the last page
271      that are off the end of the file.  However, if the extra bit in that
272      page includes the section headers and the memory isn't extended (which
273      might indicate it will have been reused otherwise), keep them.  */
274   if ((GElf_Off) contents_size > segments_end
275       && (GElf_Off) contents_size >= shdrs_end
276       && segments_end == segments_end_mem)
277     {
278       contents_size = segments_end;
279       if ((GElf_Off) contents_size < shdrs_end)
280 	contents_size = shdrs_end;
281     }
282   else
283     contents_size = segments_end;
284 
285   free (buffer);
286 
287   /* Now we know the size of the whole image we want read in.  */
288   buffer = calloc (1, contents_size);
289   if (buffer == NULL)
290     {
291       free (phdrsp);
292       goto no_memory;
293     }
294 
295   for (uint_fast16_t i = 0; i < phnum; ++i)
296     {
297       GElf_Word type = class32 ? (*p32)[i].p_type : (*p64)[i].p_type;
298 
299       if (type != PT_LOAD)
300         continue;
301 
302       GElf_Addr vaddr = class32 ? (*p32)[i].p_vaddr : (*p64)[i].p_vaddr;
303       GElf_Off offset = class32 ? (*p32)[i].p_offset : (*p64)[i].p_offset;
304       GElf_Xword filesz = class32 ? (*p32)[i].p_filesz : (*p64)[i].p_filesz;
305 
306       GElf_Off start = offset & -pagesize;
307       GElf_Off end = (offset + filesz + pagesize - 1) & -pagesize;
308       if (end > (GElf_Off) contents_size)
309         end = contents_size;
310       nread = (*read_memory) (arg, buffer + start,
311                               (loadbase + vaddr) & -pagesize,
312                               end - start, end - start);
313       if (nread <= 0)
314         goto read_error;
315     }
316 
317   /* If the segments visible in memory didn't include the section
318      headers, then clear them from the file header.  */
319   if (contents_size < shdrs_end)
320     {
321       if (class32)
322         {
323           ehdr.e32.e_shoff = 0;
324           ehdr.e32.e_shnum = 0;
325           ehdr.e32.e_shstrndx = 0;
326         }
327       else
328         {
329           ehdr.e64.e_shoff = 0;
330           ehdr.e64.e_shnum = 0;
331           ehdr.e64.e_shstrndx = 0;
332         }
333     }
334 
335   /* This will normally have been in the first PT_LOAD segment.  But it
336      conceivably could be missing, and we might have just changed it.  */
337   xlatefrom.d_type = xlateto.d_type = ELF_T_EHDR;
338   xlateto.d_buf = buffer;
339   if (class32)
340     {
341       xlatefrom.d_size = xlateto.d_size = sizeof ehdr.e32;
342       xlatefrom.d_buf = &ehdr.e32;
343       if (elf32_xlatetof (&xlateto, &xlatefrom,
344                           ehdr.e32.e_ident[EI_DATA]) == NULL)
345         goto libelf_error;
346     }
347   else
348     {
349       xlatefrom.d_size = xlateto.d_size = sizeof ehdr.e64;
350       xlatefrom.d_buf = &ehdr.e64;
351       if (elf64_xlatetof (&xlateto, &xlatefrom,
352                           ehdr.e64.e_ident[EI_DATA]) == NULL)
353         goto libelf_error;
354     }
355 
356   free (phdrsp);
357   phdrsp = NULL;
358 
359   /* Now we have the image.  Open libelf on it.  */
360 
361   Elf *elf = elf_memory ((char *) buffer, contents_size);
362   if (elf == NULL)
363     {
364       free (buffer);
365       goto libelf_error;
366     }
367 
368   elf->flags |= ELF_F_MALLOCED;
369   if (loadbasep != NULL)
370     *loadbasep = loadbase;
371   return elf;
372 }
373