elf-from-memory.c revision dd64d4a9268b822b035f8c59c2b8f55a65f80819
1/* Reconstruct an ELF file by reading the segments out of remote memory. 2 Copyright (C) 2005-2011, 2014 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 56Elf * 57elf_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 /* 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: 90 free (buffer); 91 __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); 141 if (elf64_xlatetom (&xlateto, &xlatefrom, buffer[EI_DATA]) == NULL) 142 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; 199 GElf_Off segments_end_mem = 0; 200 GElf_Addr loadbase = ehdr_vma; 201 bool found_base = false; 202 switch (ehdr.e32.e_ident[EI_CLASS]) 203 { 204 /* 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, 209 GElf_Xword filesz, GElf_Xword memsz, 210 GElf_Xword palign) 211 { 212 /* Sanity check the alignment requirements. */ 213 if ((palign & (pagesize - 1)) != 0 214 || ((vaddr - offset) & (palign - 1)) != 0) 215 return true; 216 217 GElf_Off segment_end = ((offset + filesz + pagesize - 1) 218 & -pagesize); 219 220 if (segment_end > (GElf_Off) contents_size) 221 contents_size = segment_end; 222 223 if (!found_base && (offset & -pagesize) == 0) 224 { 225 loadbase = ehdr_vma - (vaddr & -pagesize); 226 found_base = true; 227 } 228 229 segments_end = offset + filesz; 230 segments_end_mem = offset + memsz; 231 return false; 232 } 233 234 case ELFCLASS32: 235 if (elf32_xlatetom (&xlateto, &xlatefrom, 236 ehdr.e32.e_ident[EI_DATA]) == NULL) 237 goto libelf_error; 238 for (uint_fast16_t i = 0; i < phnum; ++i) 239 if (phdrs.p32[i].p_type == PT_LOAD) 240 if (handle_segment (phdrs.p32[i].p_vaddr, phdrs.p32[i].p_offset, 241 phdrs.p32[i].p_filesz, phdrs.p32[i].p_memsz, 242 phdrs.p32[i].p_align)) 243 goto bad_elf; 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 if (handle_segment (phdrs.p64[i].p_vaddr, phdrs.p64[i].p_offset, 253 phdrs.p64[i].p_filesz, phdrs.p64[i].p_memsz, 254 phdrs.p64[i].p_align)) 255 goto bad_elf; 256 break; 257 258 default: 259 abort (); 260 break; 261 } 262 263 /* Trim the last segment so we don't bother with zeros in the last page 264 that are off the end of the file. However, if the extra bit in that 265 page includes the section headers and the memory isn't extended (which 266 might indicate it will have been reused otherwise), keep them. */ 267 if ((GElf_Off) contents_size > segments_end 268 && (GElf_Off) contents_size >= shdrs_end 269 && segments_end == segments_end_mem) 270 { 271 contents_size = segments_end; 272 if ((GElf_Off) contents_size < shdrs_end) 273 contents_size = shdrs_end; 274 } 275 else 276 contents_size = segments_end; 277 278 free (buffer); 279 280 /* Now we know the size of the whole image we want read in. */ 281 buffer = calloc (1, contents_size); 282 if (buffer == NULL) 283 goto no_memory; 284 285 switch (ehdr.e32.e_ident[EI_CLASS]) 286 { 287 /* Reads the given segment. Returns true if reading fails, 288 false otherwise. */ 289 inline bool handle_segment (GElf_Addr vaddr, GElf_Off offset, 290 GElf_Xword filesz) 291 { 292 GElf_Off start = offset & -pagesize; 293 GElf_Off end = (offset + filesz + pagesize - 1) & -pagesize; 294 if (end > (GElf_Off) contents_size) 295 end = contents_size; 296 nread = (*read_memory) (arg, buffer + start, 297 (loadbase + vaddr) & -pagesize, 298 end - start, end - start); 299 return nread <= 0; 300 } 301 302 case ELFCLASS32: 303 for (uint_fast16_t i = 0; i < phnum; ++i) 304 if (phdrs.p32[i].p_type == PT_LOAD) 305 if (handle_segment (phdrs.p32[i].p_vaddr, phdrs.p32[i].p_offset, 306 phdrs.p32[i].p_filesz)) 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.e32.e_shoff = 0; 314 ehdr.e32.e_shnum = 0; 315 ehdr.e32.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.e32; 322 xlatefrom.d_buf = &ehdr.e32; 323 xlateto.d_buf = buffer; 324 if (elf32_xlatetof (&xlateto, &xlatefrom, 325 ehdr.e32.e_ident[EI_DATA]) == NULL) 326 goto libelf_error; 327 break; 328 329 case ELFCLASS64: 330 for (uint_fast16_t i = 0; i < phnum; ++i) 331 if (phdrs.p64[i].p_type == PT_LOAD) 332 if (handle_segment (phdrs.p64[i].p_vaddr, phdrs.p64[i].p_offset, 333 phdrs.p64[i].p_filesz)) 334 goto read_error; 335 336 /* If the segments visible in memory didn't include the section 337 headers, then clear them from the file header. */ 338 if (contents_size < shdrs_end) 339 { 340 ehdr.e64.e_shoff = 0; 341 ehdr.e64.e_shnum = 0; 342 ehdr.e64.e_shstrndx = 0; 343 } 344 345 /* This will normally have been in the first PT_LOAD segment. But it 346 conceivably could be missing, and we might have just changed it. */ 347 xlatefrom.d_type = xlateto.d_type = ELF_T_EHDR; 348 xlatefrom.d_size = xlateto.d_size = sizeof ehdr.e64; 349 xlatefrom.d_buf = &ehdr.e64; 350 xlateto.d_buf = buffer; 351 if (elf64_xlatetof (&xlateto, &xlatefrom, 352 ehdr.e64.e_ident[EI_DATA]) == NULL) 353 goto libelf_error; 354 break; 355 356 default: 357 abort (); 358 break; 359 } 360 361 /* Now we have the image. Open libelf on it. */ 362 363 Elf *elf = elf_memory ((char *) buffer, contents_size); 364 if (elf == NULL) 365 { 366 free (buffer); 367 goto libelf_error; 368 } 369 370 elf->flags |= ELF_F_MALLOCED; 371 if (loadbasep != NULL) 372 *loadbasep = loadbase; 373 return elf; 374} 375