1 /* Reconstruct an ELF file by reading the segments out of remote memory. 2 Copyright (C) 2005-2011 Red Hat, Inc. 3 This file is part of Red Hat elfutils. 4 5 Red Hat elfutils is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by the 7 Free Software Foundation; version 2 of the License. 8 9 Red Hat elfutils is distributed in the hope that it will be useful, but 10 WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 General Public License for more details. 13 14 You should have received a copy of the GNU General Public License along 15 with Red Hat elfutils; if not, write to the Free Software Foundation, 16 Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. 17 18 In addition, as a special exception, Red Hat, Inc. gives You the 19 additional right to link the code of Red Hat elfutils with code licensed 20 under any Open Source Initiative certified open source license 21 (http://www.opensource.org/licenses/index.php) which requires the 22 distribution of source code with any binary distribution and to 23 distribute linked combinations of the two. Non-GPL Code permitted under 24 this exception must only link to the code of Red Hat elfutils through 25 those well defined interfaces identified in the file named EXCEPTION 26 found in the source code files (the "Approved Interfaces"). The files 27 of Non-GPL Code may instantiate templates or use macros or inline 28 functions from the Approved Interfaces without causing the resulting 29 work to be covered by the GNU General Public License. Only Red Hat, 30 Inc. may make changes or additions to the list of Approved Interfaces. 31 Red Hat's grant of this exception is conditioned upon your not adding 32 any new exceptions. If you wish to add a new Approved Interface or 33 exception, please contact Red Hat. You must obey the GNU General Public 34 License in all respects for all of the Red Hat elfutils code and other 35 code used in conjunction with Red Hat elfutils except the Non-GPL Code 36 covered by this exception. If you modify this file, you may extend this 37 exception to your version of the file, but you are not obligated to do 38 so. If you do not wish to provide this exception without modification, 39 you must delete this exception statement from your version and license 40 this file solely under the GPL without exception. 41 42 Red Hat elfutils is an included package of the Open Invention Network. 43 An included package of the Open Invention Network is a package for which 44 Open Invention Network licensees cross-license their patents. No patent 45 license is granted, either expressly or impliedly, by designation as an 46 included package. Should you wish to participate in the Open Invention 47 Network licensing program, please visit www.openinventionnetwork.com 48 <http://www.openinventionnetwork.com>. */ 49 50 #include <config.h> 51 #include "../libelf/libelfP.h" 52 #undef _ 53 54 #include "libdwflP.h" 55 56 #include <gelf.h> 57 #include <sys/types.h> 58 #include <stdbool.h> 59 #include <stdlib.h> 60 #include <string.h> 61 62 /* Reconstruct an ELF file by reading the segments out of remote memory 63 based on the ELF file header at EHDR_VMA and the ELF program headers it 64 points to. If not null, *LOADBASEP is filled in with the difference 65 between the addresses from which the segments were read, and the 66 addresses the file headers put them at. 67 68 The function READ_MEMORY is called to copy at least MINREAD and at most 69 MAXREAD bytes from the remote memory at target address ADDRESS into the 70 local buffer at DATA; it should return -1 for errors (with code in 71 `errno'), 0 if it failed to read at least MINREAD bytes due to EOF, or 72 the number of bytes read if >= MINREAD. ARG is passed through. */ 73 74 Elf * 75 elf_from_remote_memory (GElf_Addr ehdr_vma, 76 GElf_Addr *loadbasep, 77 ssize_t (*read_memory) (void *arg, void *data, 78 GElf_Addr address, 79 size_t minread, 80 size_t maxread), 81 void *arg) 82 { 83 /* First read in the file header and check its sanity. */ 84 85 const size_t initial_bufsize = 256; 86 unsigned char *buffer = malloc (initial_bufsize); 87 if (buffer == NULL) 88 { 89 no_memory: 90 __libdwfl_seterrno (DWFL_E_NOMEM); 91 return NULL; 92 } 93 94 ssize_t nread = (*read_memory) (arg, buffer, ehdr_vma, 95 sizeof (Elf32_Ehdr), initial_bufsize); 96 if (nread <= 0) 97 { 98 read_error: 99 free (buffer); 100 __libdwfl_seterrno (nread < 0 ? DWFL_E_ERRNO : DWFL_E_TRUNCATED); 101 return NULL; 102 } 103 104 if (memcmp (buffer, ELFMAG, SELFMAG) != 0) 105 { 106 bad_elf: 107 __libdwfl_seterrno (DWFL_E_BADELF); 108 return NULL; 109 } 110 111 /* Extract the information we need from the file header. */ 112 113 union 114 { 115 Elf32_Ehdr e32; 116 Elf64_Ehdr e64; 117 } ehdr; 118 Elf_Data xlatefrom = 119 { 120 .d_type = ELF_T_EHDR, 121 .d_buf = buffer, 122 .d_version = EV_CURRENT, 123 }; 124 Elf_Data xlateto = 125 { 126 .d_type = ELF_T_EHDR, 127 .d_buf = &ehdr, 128 .d_size = sizeof ehdr, 129 .d_version = EV_CURRENT, 130 }; 131 132 GElf_Off phoff; 133 uint_fast16_t phnum; 134 uint_fast16_t phentsize; 135 GElf_Off shdrs_end; 136 137 switch (buffer[EI_CLASS]) 138 { 139 case ELFCLASS32: 140 xlatefrom.d_size = sizeof (Elf32_Ehdr); 141 if (elf32_xlatetom (&xlateto, &xlatefrom, buffer[EI_DATA]) == NULL) 142 { 143 libelf_error: 144 __libdwfl_seterrno (DWFL_E_LIBELF); 145 return NULL; 146 } 147 phoff = ehdr.e32.e_phoff; 148 phnum = ehdr.e32.e_phnum; 149 phentsize = ehdr.e32.e_phentsize; 150 if (phentsize != sizeof (Elf32_Phdr) || phnum == 0) 151 goto bad_elf; 152 shdrs_end = ehdr.e32.e_shoff + ehdr.e32.e_shnum * ehdr.e32.e_shentsize; 153 break; 154 155 case ELFCLASS64: 156 xlatefrom.d_size = sizeof (Elf64_Ehdr); 157 if (elf64_xlatetom (&xlateto, &xlatefrom, buffer[EI_DATA]) == NULL) 158 goto libelf_error; 159 phoff = ehdr.e64.e_phoff; 160 phnum = ehdr.e64.e_phnum; 161 phentsize = ehdr.e64.e_phentsize; 162 if (phentsize != sizeof (Elf64_Phdr) || phnum == 0) 163 goto bad_elf; 164 shdrs_end = ehdr.e64.e_shoff + ehdr.e64.e_shnum * ehdr.e64.e_shentsize; 165 break; 166 167 default: 168 goto bad_elf; 169 } 170 171 172 /* The file header tells where to find the program headers. 173 These are what we use to actually choose what to read. */ 174 175 xlatefrom.d_type = xlateto.d_type = ELF_T_PHDR; 176 xlatefrom.d_size = phnum * phentsize; 177 178 if ((size_t) nread >= phoff + phnum * phentsize) 179 /* We already have all the phdrs from the initial read. */ 180 xlatefrom.d_buf = buffer + phoff; 181 else 182 { 183 /* Read in the program headers. */ 184 185 if (initial_bufsize < phnum * phentsize) 186 { 187 unsigned char *newbuf = realloc (buffer, phnum * phentsize); 188 if (newbuf == NULL) 189 { 190 free (buffer); 191 goto no_memory; 192 } 193 buffer = newbuf; 194 } 195 nread = (*read_memory) (arg, buffer, ehdr_vma + phoff, 196 phnum * phentsize, phnum * phentsize); 197 if (nread <= 0) 198 goto read_error; 199 200 xlatefrom.d_buf = buffer; 201 } 202 203 union 204 { 205 Elf32_Phdr p32[phnum]; 206 Elf64_Phdr p64[phnum]; 207 } phdrs; 208 209 xlateto.d_buf = &phdrs; 210 xlateto.d_size = sizeof phdrs; 211 212 /* Scan for PT_LOAD segments to find the total size of the file image. */ 213 size_t contents_size = 0; 214 GElf_Off segments_end = 0; 215 GElf_Addr loadbase = ehdr_vma; 216 bool found_base = false; 217 switch (ehdr.e32.e_ident[EI_CLASS]) 218 { 219 inline void handle_segment (GElf_Addr vaddr, GElf_Off offset, 220 GElf_Xword filesz, GElf_Xword align) 221 { 222 GElf_Off segment_end = ((offset + filesz + align - 1) & -align); 223 224 if (segment_end > (GElf_Off) contents_size) 225 contents_size = segment_end; 226 227 if (!found_base && (offset & -align) == 0) 228 { 229 loadbase = ehdr_vma - (vaddr & -align); 230 found_base = true; 231 } 232 233 segments_end = offset + filesz; 234 } 235 236 case ELFCLASS32: 237 if (elf32_xlatetom (&xlateto, &xlatefrom, 238 ehdr.e32.e_ident[EI_DATA]) == NULL) 239 goto libelf_error; 240 for (uint_fast16_t i = 0; i < phnum; ++i) 241 if (phdrs.p32[i].p_type == PT_LOAD) 242 handle_segment (phdrs.p32[i].p_vaddr, phdrs.p32[i].p_offset, 243 phdrs.p32[i].p_filesz, phdrs.p32[i].p_align); 244 break; 245 246 case ELFCLASS64: 247 if (elf64_xlatetom (&xlateto, &xlatefrom, 248 ehdr.e64.e_ident[EI_DATA]) == NULL) 249 goto libelf_error; 250 for (uint_fast16_t i = 0; i < phnum; ++i) 251 if (phdrs.p64[i].p_type == PT_LOAD) 252 handle_segment (phdrs.p64[i].p_vaddr, phdrs.p64[i].p_offset, 253 phdrs.p64[i].p_filesz, phdrs.p64[i].p_align); 254 break; 255 256 default: 257 abort (); 258 break; 259 } 260 261 /* Trim the last segment so we don't bother with zeros in the last page 262 that are off the end of the file. However, if the extra bit in that 263 page includes the section headers, keep them. */ 264 if ((GElf_Off) contents_size > segments_end 265 && (GElf_Off) contents_size >= shdrs_end) 266 { 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 { 283 inline bool handle_segment (GElf_Addr vaddr, GElf_Off offset, 284 GElf_Xword filesz, GElf_Xword align) 285 { 286 GElf_Off start = offset & -align; 287 GElf_Off end = (offset + filesz + align - 1) & -align; 288 if (end > (GElf_Off) contents_size) 289 end = contents_size; 290 nread = (*read_memory) (arg, buffer + start, 291 (loadbase + vaddr) & -align, 292 end - start, end - start); 293 return nread <= 0; 294 } 295 296 case ELFCLASS32: 297 for (uint_fast16_t i = 0; i < phnum; ++i) 298 if (phdrs.p32[i].p_type == PT_LOAD) 299 if (handle_segment (phdrs.p32[i].p_vaddr, phdrs.p32[i].p_offset, 300 phdrs.p32[i].p_filesz, phdrs.p32[i].p_align)) 301 goto read_error; 302 303 /* If the segments visible in memory didn't include the section 304 headers, then clear them from the file header. */ 305 if (contents_size < shdrs_end) 306 { 307 ehdr.e32.e_shoff = 0; 308 ehdr.e32.e_shnum = 0; 309 ehdr.e32.e_shstrndx = 0; 310 } 311 312 /* This will normally have been in the first PT_LOAD segment. But it 313 conceivably could be missing, and we might have just changed it. */ 314 xlatefrom.d_type = xlateto.d_type = ELF_T_EHDR; 315 xlatefrom.d_size = xlateto.d_size = sizeof ehdr.e32; 316 xlatefrom.d_buf = &ehdr.e32; 317 xlateto.d_buf = buffer; 318 if (elf32_xlatetof (&xlateto, &xlatefrom, 319 ehdr.e32.e_ident[EI_DATA]) == NULL) 320 goto libelf_error; 321 break; 322 323 case ELFCLASS64: 324 for (uint_fast16_t i = 0; i < phnum; ++i) 325 if (phdrs.p32[i].p_type == PT_LOAD) 326 if (handle_segment (phdrs.p64[i].p_vaddr, phdrs.p64[i].p_offset, 327 phdrs.p64[i].p_filesz, phdrs.p64[i].p_align)) 328 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.e64.e_shoff = 0; 335 ehdr.e64.e_shnum = 0; 336 ehdr.e64.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.e64; 343 xlatefrom.d_buf = &ehdr.e64; 344 xlateto.d_buf = buffer; 345 if (elf64_xlatetof (&xlateto, &xlatefrom, 346 ehdr.e64.e_ident[EI_DATA]) == NULL) 347 goto libelf_error; 348 break; 349 350 default: 351 abort (); 352 break; 353 } 354 355 /* Now we have the image. Open libelf on it. */ 356 357 Elf *elf = elf_memory ((char *) buffer, contents_size); 358 if (elf == NULL) 359 { 360 free (buffer); 361 goto libelf_error; 362 } 363 364 elf->flags |= ELF_F_MALLOCED; 365 if (loadbasep != NULL) 366 *loadbasep = loadbase; 367 return elf; 368 } 369