1b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Reconstruct an ELF file by reading the segments out of remote memory. 29202fe132caea838cc7e2c7864e0ee702e62f155Mark Wielaard Copyright (C) 2005-2011, 2014, 2015 Red Hat, Inc. 3de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard This file is part of elfutils. 4b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 5de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard This file is free software; you can redistribute it and/or modify 6de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard it under the terms of either 7b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 8de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard * the GNU Lesser General Public License as published by the Free 9de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard Software Foundation; either version 3 of the License, or (at 10de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard your option) any later version 11de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard 12de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard or 13de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard 14de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard * the GNU General Public License as published by the Free 15de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard Software Foundation; either version 2 of the License, or (at 16de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard your option) any later version 17de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard 18de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard or both in parallel, as here. 19de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard 20de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard elfutils is distributed in the hope that it will be useful, but 21361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper WITHOUT ANY WARRANTY; without even the implied warranty of 22361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper General Public License for more details. 24361df7da6dfecd817b27e62b91752ac316d7cdd4Ulrich Drepper 25de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard You should have received copies of the GNU General Public License and 26de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard the GNU Lesser General Public License along with this program. If 27de2ed97f33139af5c7a0811e4ec66fc896a13cf2Mark Wielaard not, see <http://www.gnu.org/licenses/>. */ 28b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 29b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <config.h> 30b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include "../libelf/libelfP.h" 31b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#undef _ 32b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 33b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include "libdwflP.h" 34b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 35b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <gelf.h> 36b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <sys/types.h> 37b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <stdbool.h> 38b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <stdlib.h> 39b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper#include <string.h> 40b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 41b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper/* Reconstruct an ELF file by reading the segments out of remote memory 42b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper based on the ELF file header at EHDR_VMA and the ELF program headers it 43b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper points to. If not null, *LOADBASEP is filled in with the difference 44b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper between the addresses from which the segments were read, and the 45b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper addresses the file headers put them at. 46b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 47b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper The function READ_MEMORY is called to copy at least MINREAD and at most 48b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper MAXREAD bytes from the remote memory at target address ADDRESS into the 49b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper local buffer at DATA; it should return -1 for errors (with code in 50b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper `errno'), 0 if it failed to read at least MINREAD bytes due to EOF, or 51f15bcda4137446d4773bb54cb99cc18497e9822cMark Wielaard the number of bytes read if >= MINREAD. ARG is passed through. 52f15bcda4137446d4773bb54cb99cc18497e9822cMark Wielaard 53f15bcda4137446d4773bb54cb99cc18497e9822cMark Wielaard PAGESIZE is the minimum page size and alignment used for the PT_LOAD 54f15bcda4137446d4773bb54cb99cc18497e9822cMark Wielaard segments. */ 55b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 56b08d5a8fb42f4586d756068065186b5af7e48daUlrich DrepperElf * 57b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepperelf_from_remote_memory (GElf_Addr ehdr_vma, 58f15bcda4137446d4773bb54cb99cc18497e9822cMark Wielaard GElf_Xword pagesize, 59b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper GElf_Addr *loadbasep, 60b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper ssize_t (*read_memory) (void *arg, void *data, 61b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper GElf_Addr address, 62b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper size_t minread, 63b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper size_t maxread), 64b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper void *arg) 65b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper{ 669202fe132caea838cc7e2c7864e0ee702e62f155Mark Wielaard /* We might have to reserve some memory for the phdrs. Set to NULL 679202fe132caea838cc7e2c7864e0ee702e62f155Mark Wielaard here so we can always safely free it. */ 689202fe132caea838cc7e2c7864e0ee702e62f155Mark Wielaard void *phdrsp = NULL; 699202fe132caea838cc7e2c7864e0ee702e62f155Mark Wielaard 70b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper /* First read in the file header and check its sanity. */ 71b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 72b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper const size_t initial_bufsize = 256; 73b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper unsigned char *buffer = malloc (initial_bufsize); 749202fe132caea838cc7e2c7864e0ee702e62f155Mark Wielaard if (unlikely (buffer == NULL)) 75b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper { 76b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper no_memory: 77b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper __libdwfl_seterrno (DWFL_E_NOMEM); 78b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper return NULL; 79b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper } 80b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 81b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper ssize_t nread = (*read_memory) (arg, buffer, ehdr_vma, 82b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper sizeof (Elf32_Ehdr), initial_bufsize); 83b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper if (nread <= 0) 84b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper { 85b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper read_error: 86b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper free (buffer); 879202fe132caea838cc7e2c7864e0ee702e62f155Mark Wielaard free (phdrsp); 88b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper __libdwfl_seterrno (nread < 0 ? DWFL_E_ERRNO : DWFL_E_TRUNCATED); 89b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper return NULL; 90b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper } 91b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 92b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper if (memcmp (buffer, ELFMAG, SELFMAG) != 0) 93b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper { 94b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper bad_elf: 95f15bcda4137446d4773bb54cb99cc18497e9822cMark Wielaard free (buffer); 969202fe132caea838cc7e2c7864e0ee702e62f155Mark Wielaard free (phdrsp); 97b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper __libdwfl_seterrno (DWFL_E_BADELF); 98b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper return NULL; 99b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper } 100b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 101b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper /* Extract the information we need from the file header. */ 102b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 103b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper union 104b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper { 105b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper Elf32_Ehdr e32; 106b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper Elf64_Ehdr e64; 107b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper } ehdr; 108b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper Elf_Data xlatefrom = 109b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper { 110b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper .d_type = ELF_T_EHDR, 111b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper .d_buf = buffer, 112b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper .d_version = EV_CURRENT, 113b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper }; 114b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper Elf_Data xlateto = 115b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper { 116b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper .d_type = ELF_T_EHDR, 117b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper .d_buf = &ehdr, 118b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper .d_size = sizeof ehdr, 119b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper .d_version = EV_CURRENT, 120b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper }; 121b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 122b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper GElf_Off phoff; 123b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper uint_fast16_t phnum; 124b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper uint_fast16_t phentsize; 125b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper GElf_Off shdrs_end; 126b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 127b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper switch (buffer[EI_CLASS]) 128b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper { 129b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper case ELFCLASS32: 130b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper xlatefrom.d_size = sizeof (Elf32_Ehdr); 131b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper if (elf32_xlatetom (&xlateto, &xlatefrom, buffer[EI_DATA]) == NULL) 132b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper { 133b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper libelf_error: 134b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper __libdwfl_seterrno (DWFL_E_LIBELF); 135b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper return NULL; 136b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper } 137b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper phoff = ehdr.e32.e_phoff; 138b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper phnum = ehdr.e32.e_phnum; 139b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper phentsize = ehdr.e32.e_phentsize; 140b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper if (phentsize != sizeof (Elf32_Phdr) || phnum == 0) 141b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper goto bad_elf; 142b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper shdrs_end = ehdr.e32.e_shoff + ehdr.e32.e_shnum * ehdr.e32.e_shentsize; 143b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper break; 144b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 145b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper case ELFCLASS64: 146b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper xlatefrom.d_size = sizeof (Elf64_Ehdr); 1476258e7486eb3eed6e50005946795c5fbf73aa106Ulrich Drepper if (elf64_xlatetom (&xlateto, &xlatefrom, buffer[EI_DATA]) == NULL) 148b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper goto libelf_error; 149b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper phoff = ehdr.e64.e_phoff; 150b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper phnum = ehdr.e64.e_phnum; 151b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper phentsize = ehdr.e64.e_phentsize; 152b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper if (phentsize != sizeof (Elf64_Phdr) || phnum == 0) 153b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper goto bad_elf; 154b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper shdrs_end = ehdr.e64.e_shoff + ehdr.e64.e_shnum * ehdr.e64.e_shentsize; 155b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper break; 156b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 157b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper default: 158b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper goto bad_elf; 159b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper } 160b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 161b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 162b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper /* The file header tells where to find the program headers. 163b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper These are what we use to actually choose what to read. */ 164b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 165b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper xlatefrom.d_type = xlateto.d_type = ELF_T_PHDR; 166b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper xlatefrom.d_size = phnum * phentsize; 167b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 168b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper if ((size_t) nread >= phoff + phnum * phentsize) 169b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper /* We already have all the phdrs from the initial read. */ 170b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper xlatefrom.d_buf = buffer + phoff; 171b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper else 172b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper { 173b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper /* Read in the program headers. */ 174b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 175b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper if (initial_bufsize < phnum * phentsize) 176b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper { 177b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper unsigned char *newbuf = realloc (buffer, phnum * phentsize); 178b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper if (newbuf == NULL) 179b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper { 180b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper free (buffer); 1819202fe132caea838cc7e2c7864e0ee702e62f155Mark Wielaard free (phdrsp); 182b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper goto no_memory; 183b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper } 184b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper buffer = newbuf; 185b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper } 186b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper nread = (*read_memory) (arg, buffer, ehdr_vma + phoff, 187b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper phnum * phentsize, phnum * phentsize); 188b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper if (nread <= 0) 189b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper goto read_error; 190b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 191b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper xlatefrom.d_buf = buffer; 192b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper } 193b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 19486ed7f7f53179d7a893329e6b9851dbb75aba405Mark Wielaard bool class32 = ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32; 19586ed7f7f53179d7a893329e6b9851dbb75aba405Mark Wielaard size_t phdr_size = class32 ? sizeof (Elf32_Phdr) : sizeof (Elf64_Phdr); 19686ed7f7f53179d7a893329e6b9851dbb75aba405Mark Wielaard if (unlikely (phnum > SIZE_MAX / phdr_size)) 1977eff36d5daa6ebca5e6399638a7643af105ae5b0Chih-Hung Hsieh { 1987eff36d5daa6ebca5e6399638a7643af105ae5b0Chih-Hung Hsieh free (buffer); 1997eff36d5daa6ebca5e6399638a7643af105ae5b0Chih-Hung Hsieh goto no_memory; 2007eff36d5daa6ebca5e6399638a7643af105ae5b0Chih-Hung Hsieh } 20186ed7f7f53179d7a893329e6b9851dbb75aba405Mark Wielaard const size_t phdrsp_bytes = phnum * phdr_size; 2027eff36d5daa6ebca5e6399638a7643af105ae5b0Chih-Hung Hsieh phdrsp = malloc (phdrsp_bytes); 2039202fe132caea838cc7e2c7864e0ee702e62f155Mark Wielaard if (unlikely (phdrsp == NULL)) 2049202fe132caea838cc7e2c7864e0ee702e62f155Mark Wielaard { 2059202fe132caea838cc7e2c7864e0ee702e62f155Mark Wielaard free (buffer); 2069202fe132caea838cc7e2c7864e0ee702e62f155Mark Wielaard goto no_memory; 2079202fe132caea838cc7e2c7864e0ee702e62f155Mark Wielaard } 208b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 2097eff36d5daa6ebca5e6399638a7643af105ae5b0Chih-Hung Hsieh xlateto.d_buf = phdrsp; 2107eff36d5daa6ebca5e6399638a7643af105ae5b0Chih-Hung Hsieh xlateto.d_size = phdrsp_bytes; 211b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 212b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper /* Scan for PT_LOAD segments to find the total size of the file image. */ 213b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper size_t contents_size = 0; 214b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper GElf_Off segments_end = 0; 215dd64d4a9268b822b035f8c59c2b8f55a65f80819Mark Wielaard GElf_Off segments_end_mem = 0; 216b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper GElf_Addr loadbase = ehdr_vma; 217099dd52727f2ce1a2c73cde82af8cd5e06368aecRoland McGrath bool found_base = false; 21886ed7f7f53179d7a893329e6b9851dbb75aba405Mark Wielaard Elf32_Phdr (*p32)[phnum] = phdrsp; 21986ed7f7f53179d7a893329e6b9851dbb75aba405Mark Wielaard Elf64_Phdr (*p64)[phnum] = phdrsp; 220b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper switch (ehdr.e32.e_ident[EI_CLASS]) 221b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper { 222f15bcda4137446d4773bb54cb99cc18497e9822cMark Wielaard /* Sanity checks segments and calculates segment_end, 223f15bcda4137446d4773bb54cb99cc18497e9822cMark Wielaard segments_end, segments_end_mem and loadbase (if not 224f15bcda4137446d4773bb54cb99cc18497e9822cMark Wielaard found_base yet). Returns true if sanity checking failed, 225f15bcda4137446d4773bb54cb99cc18497e9822cMark Wielaard false otherwise. */ 226f15bcda4137446d4773bb54cb99cc18497e9822cMark Wielaard inline bool handle_segment (GElf_Addr vaddr, GElf_Off offset, 22732b6c6aa608d64529e863684d3d7ec3f49afe7faMark Wielaard GElf_Xword filesz, GElf_Xword memsz) 228b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper { 22932b6c6aa608d64529e863684d3d7ec3f49afe7faMark Wielaard /* Sanity check the segment load aligns with the pagesize. */ 23032b6c6aa608d64529e863684d3d7ec3f49afe7faMark Wielaard if (((vaddr - offset) & (pagesize - 1)) != 0) 231f15bcda4137446d4773bb54cb99cc18497e9822cMark Wielaard return true; 232f15bcda4137446d4773bb54cb99cc18497e9822cMark Wielaard 233f15bcda4137446d4773bb54cb99cc18497e9822cMark Wielaard GElf_Off segment_end = ((offset + filesz + pagesize - 1) 234f15bcda4137446d4773bb54cb99cc18497e9822cMark Wielaard & -pagesize); 235b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 236b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper if (segment_end > (GElf_Off) contents_size) 237b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper contents_size = segment_end; 238b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 239f15bcda4137446d4773bb54cb99cc18497e9822cMark Wielaard if (!found_base && (offset & -pagesize) == 0) 240099dd52727f2ce1a2c73cde82af8cd5e06368aecRoland McGrath { 241f15bcda4137446d4773bb54cb99cc18497e9822cMark Wielaard loadbase = ehdr_vma - (vaddr & -pagesize); 242099dd52727f2ce1a2c73cde82af8cd5e06368aecRoland McGrath found_base = true; 243099dd52727f2ce1a2c73cde82af8cd5e06368aecRoland McGrath } 244b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 245b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper segments_end = offset + filesz; 246dd64d4a9268b822b035f8c59c2b8f55a65f80819Mark Wielaard segments_end_mem = offset + memsz; 247f15bcda4137446d4773bb54cb99cc18497e9822cMark Wielaard return false; 248b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper } 249b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 250b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper case ELFCLASS32: 251b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper if (elf32_xlatetom (&xlateto, &xlatefrom, 252b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper ehdr.e32.e_ident[EI_DATA]) == NULL) 253b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper goto libelf_error; 254b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper for (uint_fast16_t i = 0; i < phnum; ++i) 2557eff36d5daa6ebca5e6399638a7643af105ae5b0Chih-Hung Hsieh if ((*p32)[i].p_type == PT_LOAD) 2567eff36d5daa6ebca5e6399638a7643af105ae5b0Chih-Hung Hsieh if (handle_segment ((*p32)[i].p_vaddr, (*p32)[i].p_offset, 2577eff36d5daa6ebca5e6399638a7643af105ae5b0Chih-Hung Hsieh (*p32)[i].p_filesz, (*p32)[i].p_memsz)) 258f15bcda4137446d4773bb54cb99cc18497e9822cMark Wielaard goto bad_elf; 259b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper break; 260b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 261b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper case ELFCLASS64: 26201fef9d502eb1e21ac7b7e8ec9451dc96c72f7edRoland McGrath if (elf64_xlatetom (&xlateto, &xlatefrom, 26301fef9d502eb1e21ac7b7e8ec9451dc96c72f7edRoland McGrath ehdr.e64.e_ident[EI_DATA]) == NULL) 264b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper goto libelf_error; 265b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper for (uint_fast16_t i = 0; i < phnum; ++i) 2667eff36d5daa6ebca5e6399638a7643af105ae5b0Chih-Hung Hsieh if ((*p64)[i].p_type == PT_LOAD) 2677eff36d5daa6ebca5e6399638a7643af105ae5b0Chih-Hung Hsieh if (handle_segment ((*p64)[i].p_vaddr, (*p64)[i].p_offset, 2687eff36d5daa6ebca5e6399638a7643af105ae5b0Chih-Hung Hsieh (*p64)[i].p_filesz, (*p64)[i].p_memsz)) 269f15bcda4137446d4773bb54cb99cc18497e9822cMark Wielaard goto bad_elf; 270b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper break; 271b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 272b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper default: 273b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper abort (); 274b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper break; 275b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper } 276b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 277b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper /* Trim the last segment so we don't bother with zeros in the last page 278b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper that are off the end of the file. However, if the extra bit in that 279dd64d4a9268b822b035f8c59c2b8f55a65f80819Mark Wielaard page includes the section headers and the memory isn't extended (which 280dd64d4a9268b822b035f8c59c2b8f55a65f80819Mark Wielaard might indicate it will have been reused otherwise), keep them. */ 281b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper if ((GElf_Off) contents_size > segments_end 282dd64d4a9268b822b035f8c59c2b8f55a65f80819Mark Wielaard && (GElf_Off) contents_size >= shdrs_end 283dd64d4a9268b822b035f8c59c2b8f55a65f80819Mark Wielaard && segments_end == segments_end_mem) 284b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper { 285b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper contents_size = segments_end; 286b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper if ((GElf_Off) contents_size < shdrs_end) 287b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper contents_size = shdrs_end; 288b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper } 289b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper else 290b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper contents_size = segments_end; 291b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 292b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper free (buffer); 293b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 294b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper /* Now we know the size of the whole image we want read in. */ 295b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper buffer = calloc (1, contents_size); 296b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper if (buffer == NULL) 2979202fe132caea838cc7e2c7864e0ee702e62f155Mark Wielaard { 2989202fe132caea838cc7e2c7864e0ee702e62f155Mark Wielaard free (phdrsp); 2999202fe132caea838cc7e2c7864e0ee702e62f155Mark Wielaard goto no_memory; 3009202fe132caea838cc7e2c7864e0ee702e62f155Mark Wielaard } 301b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 302b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper switch (ehdr.e32.e_ident[EI_CLASS]) 303b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper { 304f15bcda4137446d4773bb54cb99cc18497e9822cMark Wielaard /* Reads the given segment. Returns true if reading fails, 305f15bcda4137446d4773bb54cb99cc18497e9822cMark Wielaard false otherwise. */ 306b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper inline bool handle_segment (GElf_Addr vaddr, GElf_Off offset, 307f15bcda4137446d4773bb54cb99cc18497e9822cMark Wielaard GElf_Xword filesz) 308b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper { 309f15bcda4137446d4773bb54cb99cc18497e9822cMark Wielaard GElf_Off start = offset & -pagesize; 310f15bcda4137446d4773bb54cb99cc18497e9822cMark Wielaard GElf_Off end = (offset + filesz + pagesize - 1) & -pagesize; 311b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper if (end > (GElf_Off) contents_size) 312b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper end = contents_size; 313b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper nread = (*read_memory) (arg, buffer + start, 314f15bcda4137446d4773bb54cb99cc18497e9822cMark Wielaard (loadbase + vaddr) & -pagesize, 315b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper end - start, end - start); 316b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper return nread <= 0; 317b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper } 318b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 319b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper case ELFCLASS32: 320b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper for (uint_fast16_t i = 0; i < phnum; ++i) 3217eff36d5daa6ebca5e6399638a7643af105ae5b0Chih-Hung Hsieh if ((*p32)[i].p_type == PT_LOAD) 3227eff36d5daa6ebca5e6399638a7643af105ae5b0Chih-Hung Hsieh if (handle_segment ((*p32)[i].p_vaddr, (*p32)[i].p_offset, 3237eff36d5daa6ebca5e6399638a7643af105ae5b0Chih-Hung Hsieh (*p32)[i].p_filesz)) 324b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper goto read_error; 325b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 326b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper /* If the segments visible in memory didn't include the section 327b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper headers, then clear them from the file header. */ 328b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper if (contents_size < shdrs_end) 329b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper { 330b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper ehdr.e32.e_shoff = 0; 331b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper ehdr.e32.e_shnum = 0; 332b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper ehdr.e32.e_shstrndx = 0; 333b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper } 334b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 335b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper /* This will normally have been in the first PT_LOAD segment. But it 336b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper conceivably could be missing, and we might have just changed it. */ 337b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper xlatefrom.d_type = xlateto.d_type = ELF_T_EHDR; 338b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper xlatefrom.d_size = xlateto.d_size = sizeof ehdr.e32; 339b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper xlatefrom.d_buf = &ehdr.e32; 340b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper xlateto.d_buf = buffer; 341b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper if (elf32_xlatetof (&xlateto, &xlatefrom, 342b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper ehdr.e32.e_ident[EI_DATA]) == NULL) 343b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper goto libelf_error; 344b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper break; 345b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 346b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper case ELFCLASS64: 347b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper for (uint_fast16_t i = 0; i < phnum; ++i) 3487eff36d5daa6ebca5e6399638a7643af105ae5b0Chih-Hung Hsieh if ((*p64)[i].p_type == PT_LOAD) 3497eff36d5daa6ebca5e6399638a7643af105ae5b0Chih-Hung Hsieh if (handle_segment ((*p64)[i].p_vaddr, (*p64)[i].p_offset, 3507eff36d5daa6ebca5e6399638a7643af105ae5b0Chih-Hung Hsieh (*p64)[i].p_filesz)) 351b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper goto read_error; 352b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 353b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper /* If the segments visible in memory didn't include the section 354b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper headers, then clear them from the file header. */ 355b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper if (contents_size < shdrs_end) 356b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper { 357b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper ehdr.e64.e_shoff = 0; 358b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper ehdr.e64.e_shnum = 0; 359b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper ehdr.e64.e_shstrndx = 0; 360b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper } 361b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 362b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper /* This will normally have been in the first PT_LOAD segment. But it 363b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper conceivably could be missing, and we might have just changed it. */ 364b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper xlatefrom.d_type = xlateto.d_type = ELF_T_EHDR; 365b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper xlatefrom.d_size = xlateto.d_size = sizeof ehdr.e64; 366b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper xlatefrom.d_buf = &ehdr.e64; 367b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper xlateto.d_buf = buffer; 368d5a7519085f35bf48c9b33b8698835b24caa2da1Ulrich Drepper if (elf64_xlatetof (&xlateto, &xlatefrom, 369b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper ehdr.e64.e_ident[EI_DATA]) == NULL) 370b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper goto libelf_error; 371b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper break; 372b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 373b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper default: 374b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper abort (); 375b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper break; 376b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper } 377b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 3789202fe132caea838cc7e2c7864e0ee702e62f155Mark Wielaard free (phdrsp); 3797eff36d5daa6ebca5e6399638a7643af105ae5b0Chih-Hung Hsieh phdrsp = NULL; 3809202fe132caea838cc7e2c7864e0ee702e62f155Mark Wielaard 381b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper /* Now we have the image. Open libelf on it. */ 382b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 383b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper Elf *elf = elf_memory ((char *) buffer, contents_size); 384b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper if (elf == NULL) 385b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper { 386b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper free (buffer); 387d5a7519085f35bf48c9b33b8698835b24caa2da1Ulrich Drepper goto libelf_error; 388b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper } 389b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper 390b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper elf->flags |= ELF_F_MALLOCED; 391b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper if (loadbasep != NULL) 392b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper *loadbasep = loadbase; 393b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper return elf; 394b08d5a8fb42f4586d756068065186b5af7e48daUlrich Drepper} 395