125b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Reconstruct an ELF file by reading the segments out of remote memory. 225b3c049e70834cf33790a28643ab058b507b35cBen Cheng Copyright (C) 2005-2011 Red Hat, Inc. 325b3c049e70834cf33790a28643ab058b507b35cBen Cheng This file is part of Red Hat elfutils. 425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 525b3c049e70834cf33790a28643ab058b507b35cBen Cheng Red Hat elfutils is free software; you can redistribute it and/or modify 625b3c049e70834cf33790a28643ab058b507b35cBen Cheng it under the terms of the GNU General Public License as published by the 725b3c049e70834cf33790a28643ab058b507b35cBen Cheng Free Software Foundation; version 2 of the License. 825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 925b3c049e70834cf33790a28643ab058b507b35cBen Cheng Red Hat elfutils is distributed in the hope that it will be useful, but 1025b3c049e70834cf33790a28643ab058b507b35cBen Cheng WITHOUT ANY WARRANTY; without even the implied warranty of 1125b3c049e70834cf33790a28643ab058b507b35cBen Cheng MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1225b3c049e70834cf33790a28643ab058b507b35cBen Cheng General Public License for more details. 1325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 1425b3c049e70834cf33790a28643ab058b507b35cBen Cheng You should have received a copy of the GNU General Public License along 1525b3c049e70834cf33790a28643ab058b507b35cBen Cheng with Red Hat elfutils; if not, write to the Free Software Foundation, 1625b3c049e70834cf33790a28643ab058b507b35cBen Cheng Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. 1725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 1825b3c049e70834cf33790a28643ab058b507b35cBen Cheng In addition, as a special exception, Red Hat, Inc. gives You the 1925b3c049e70834cf33790a28643ab058b507b35cBen Cheng additional right to link the code of Red Hat elfutils with code licensed 2025b3c049e70834cf33790a28643ab058b507b35cBen Cheng under any Open Source Initiative certified open source license 2125b3c049e70834cf33790a28643ab058b507b35cBen Cheng (http://www.opensource.org/licenses/index.php) which requires the 2225b3c049e70834cf33790a28643ab058b507b35cBen Cheng distribution of source code with any binary distribution and to 2325b3c049e70834cf33790a28643ab058b507b35cBen Cheng distribute linked combinations of the two. Non-GPL Code permitted under 2425b3c049e70834cf33790a28643ab058b507b35cBen Cheng this exception must only link to the code of Red Hat elfutils through 2525b3c049e70834cf33790a28643ab058b507b35cBen Cheng those well defined interfaces identified in the file named EXCEPTION 2625b3c049e70834cf33790a28643ab058b507b35cBen Cheng found in the source code files (the "Approved Interfaces"). The files 2725b3c049e70834cf33790a28643ab058b507b35cBen Cheng of Non-GPL Code may instantiate templates or use macros or inline 2825b3c049e70834cf33790a28643ab058b507b35cBen Cheng functions from the Approved Interfaces without causing the resulting 2925b3c049e70834cf33790a28643ab058b507b35cBen Cheng work to be covered by the GNU General Public License. Only Red Hat, 3025b3c049e70834cf33790a28643ab058b507b35cBen Cheng Inc. may make changes or additions to the list of Approved Interfaces. 3125b3c049e70834cf33790a28643ab058b507b35cBen Cheng Red Hat's grant of this exception is conditioned upon your not adding 3225b3c049e70834cf33790a28643ab058b507b35cBen Cheng any new exceptions. If you wish to add a new Approved Interface or 3325b3c049e70834cf33790a28643ab058b507b35cBen Cheng exception, please contact Red Hat. You must obey the GNU General Public 3425b3c049e70834cf33790a28643ab058b507b35cBen Cheng License in all respects for all of the Red Hat elfutils code and other 3525b3c049e70834cf33790a28643ab058b507b35cBen Cheng code used in conjunction with Red Hat elfutils except the Non-GPL Code 3625b3c049e70834cf33790a28643ab058b507b35cBen Cheng covered by this exception. If you modify this file, you may extend this 3725b3c049e70834cf33790a28643ab058b507b35cBen Cheng exception to your version of the file, but you are not obligated to do 3825b3c049e70834cf33790a28643ab058b507b35cBen Cheng so. If you do not wish to provide this exception without modification, 3925b3c049e70834cf33790a28643ab058b507b35cBen Cheng you must delete this exception statement from your version and license 4025b3c049e70834cf33790a28643ab058b507b35cBen Cheng this file solely under the GPL without exception. 4125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 4225b3c049e70834cf33790a28643ab058b507b35cBen Cheng Red Hat elfutils is an included package of the Open Invention Network. 4325b3c049e70834cf33790a28643ab058b507b35cBen Cheng An included package of the Open Invention Network is a package for which 4425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Open Invention Network licensees cross-license their patents. No patent 4525b3c049e70834cf33790a28643ab058b507b35cBen Cheng license is granted, either expressly or impliedly, by designation as an 4625b3c049e70834cf33790a28643ab058b507b35cBen Cheng included package. Should you wish to participate in the Open Invention 4725b3c049e70834cf33790a28643ab058b507b35cBen Cheng Network licensing program, please visit www.openinventionnetwork.com 4825b3c049e70834cf33790a28643ab058b507b35cBen Cheng <http://www.openinventionnetwork.com>. */ 4925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 5025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <config.h> 5125b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "../libelf/libelfP.h" 5225b3c049e70834cf33790a28643ab058b507b35cBen Cheng#undef _ 5325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 5425b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include "libdwflP.h" 5525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 5625b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <gelf.h> 5725b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <sys/types.h> 5825b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdbool.h> 5925b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <stdlib.h> 6025b3c049e70834cf33790a28643ab058b507b35cBen Cheng#include <string.h> 6125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 6225b3c049e70834cf33790a28643ab058b507b35cBen Cheng/* Reconstruct an ELF file by reading the segments out of remote memory 6325b3c049e70834cf33790a28643ab058b507b35cBen Cheng based on the ELF file header at EHDR_VMA and the ELF program headers it 6425b3c049e70834cf33790a28643ab058b507b35cBen Cheng points to. If not null, *LOADBASEP is filled in with the difference 6525b3c049e70834cf33790a28643ab058b507b35cBen Cheng between the addresses from which the segments were read, and the 6625b3c049e70834cf33790a28643ab058b507b35cBen Cheng addresses the file headers put them at. 6725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 6825b3c049e70834cf33790a28643ab058b507b35cBen Cheng The function READ_MEMORY is called to copy at least MINREAD and at most 6925b3c049e70834cf33790a28643ab058b507b35cBen Cheng MAXREAD bytes from the remote memory at target address ADDRESS into the 7025b3c049e70834cf33790a28643ab058b507b35cBen Cheng local buffer at DATA; it should return -1 for errors (with code in 7125b3c049e70834cf33790a28643ab058b507b35cBen Cheng `errno'), 0 if it failed to read at least MINREAD bytes due to EOF, or 7225b3c049e70834cf33790a28643ab058b507b35cBen Cheng the number of bytes read if >= MINREAD. ARG is passed through. */ 7325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 7425b3c049e70834cf33790a28643ab058b507b35cBen ChengElf * 7525b3c049e70834cf33790a28643ab058b507b35cBen Chengelf_from_remote_memory (GElf_Addr ehdr_vma, 7625b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Addr *loadbasep, 7725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ssize_t (*read_memory) (void *arg, void *data, 7825b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Addr address, 7925b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t minread, 8025b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t maxread), 8125b3c049e70834cf33790a28643ab058b507b35cBen Cheng void *arg) 8225b3c049e70834cf33790a28643ab058b507b35cBen Cheng{ 8325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* First read in the file header and check its sanity. */ 8425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 8525b3c049e70834cf33790a28643ab058b507b35cBen Cheng const size_t initial_bufsize = 256; 8625b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned char *buffer = malloc (initial_bufsize); 8725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (buffer == NULL) 8825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 8925b3c049e70834cf33790a28643ab058b507b35cBen Cheng no_memory: 9025b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libdwfl_seterrno (DWFL_E_NOMEM); 9125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 9225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 9325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 9425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ssize_t nread = (*read_memory) (arg, buffer, ehdr_vma, 9525b3c049e70834cf33790a28643ab058b507b35cBen Cheng sizeof (Elf32_Ehdr), initial_bufsize); 9625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (nread <= 0) 9725b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 9825b3c049e70834cf33790a28643ab058b507b35cBen Cheng read_error: 9925b3c049e70834cf33790a28643ab058b507b35cBen Cheng free (buffer); 10025b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libdwfl_seterrno (nread < 0 ? DWFL_E_ERRNO : DWFL_E_TRUNCATED); 10125b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 10225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 10325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 10425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (memcmp (buffer, ELFMAG, SELFMAG) != 0) 10525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 10625b3c049e70834cf33790a28643ab058b507b35cBen Cheng bad_elf: 10725b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libdwfl_seterrno (DWFL_E_BADELF); 10825b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 10925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 11025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 11125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Extract the information we need from the file header. */ 11225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 11325b3c049e70834cf33790a28643ab058b507b35cBen Cheng union 11425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 11525b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf32_Ehdr e32; 11625b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf64_Ehdr e64; 11725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } ehdr; 11825b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data xlatefrom = 11925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 12025b3c049e70834cf33790a28643ab058b507b35cBen Cheng .d_type = ELF_T_EHDR, 12125b3c049e70834cf33790a28643ab058b507b35cBen Cheng .d_buf = buffer, 12225b3c049e70834cf33790a28643ab058b507b35cBen Cheng .d_version = EV_CURRENT, 12325b3c049e70834cf33790a28643ab058b507b35cBen Cheng }; 12425b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf_Data xlateto = 12525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 12625b3c049e70834cf33790a28643ab058b507b35cBen Cheng .d_type = ELF_T_EHDR, 12725b3c049e70834cf33790a28643ab058b507b35cBen Cheng .d_buf = &ehdr, 12825b3c049e70834cf33790a28643ab058b507b35cBen Cheng .d_size = sizeof ehdr, 12925b3c049e70834cf33790a28643ab058b507b35cBen Cheng .d_version = EV_CURRENT, 13025b3c049e70834cf33790a28643ab058b507b35cBen Cheng }; 13125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 13225b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Off phoff; 13325b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint_fast16_t phnum; 13425b3c049e70834cf33790a28643ab058b507b35cBen Cheng uint_fast16_t phentsize; 13525b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Off shdrs_end; 13625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 13725b3c049e70834cf33790a28643ab058b507b35cBen Cheng switch (buffer[EI_CLASS]) 13825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 13925b3c049e70834cf33790a28643ab058b507b35cBen Cheng case ELFCLASS32: 14025b3c049e70834cf33790a28643ab058b507b35cBen Cheng xlatefrom.d_size = sizeof (Elf32_Ehdr); 14125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elf32_xlatetom (&xlateto, &xlatefrom, buffer[EI_DATA]) == NULL) 14225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 14325b3c049e70834cf33790a28643ab058b507b35cBen Cheng libelf_error: 14425b3c049e70834cf33790a28643ab058b507b35cBen Cheng __libdwfl_seterrno (DWFL_E_LIBELF); 14525b3c049e70834cf33790a28643ab058b507b35cBen Cheng return NULL; 14625b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 14725b3c049e70834cf33790a28643ab058b507b35cBen Cheng phoff = ehdr.e32.e_phoff; 14825b3c049e70834cf33790a28643ab058b507b35cBen Cheng phnum = ehdr.e32.e_phnum; 14925b3c049e70834cf33790a28643ab058b507b35cBen Cheng phentsize = ehdr.e32.e_phentsize; 15025b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (phentsize != sizeof (Elf32_Phdr) || phnum == 0) 15125b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto bad_elf; 15225b3c049e70834cf33790a28643ab058b507b35cBen Cheng shdrs_end = ehdr.e32.e_shoff + ehdr.e32.e_shnum * ehdr.e32.e_shentsize; 15325b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 15425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 15525b3c049e70834cf33790a28643ab058b507b35cBen Cheng case ELFCLASS64: 15625b3c049e70834cf33790a28643ab058b507b35cBen Cheng xlatefrom.d_size = sizeof (Elf64_Ehdr); 15725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elf64_xlatetom (&xlateto, &xlatefrom, buffer[EI_DATA]) == NULL) 15825b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto libelf_error; 15925b3c049e70834cf33790a28643ab058b507b35cBen Cheng phoff = ehdr.e64.e_phoff; 16025b3c049e70834cf33790a28643ab058b507b35cBen Cheng phnum = ehdr.e64.e_phnum; 16125b3c049e70834cf33790a28643ab058b507b35cBen Cheng phentsize = ehdr.e64.e_phentsize; 16225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (phentsize != sizeof (Elf64_Phdr) || phnum == 0) 16325b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto bad_elf; 16425b3c049e70834cf33790a28643ab058b507b35cBen Cheng shdrs_end = ehdr.e64.e_shoff + ehdr.e64.e_shnum * ehdr.e64.e_shentsize; 16525b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 16625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 16725b3c049e70834cf33790a28643ab058b507b35cBen Cheng default: 16825b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto bad_elf; 16925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 17025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 17125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 17225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* The file header tells where to find the program headers. 17325b3c049e70834cf33790a28643ab058b507b35cBen Cheng These are what we use to actually choose what to read. */ 17425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 17525b3c049e70834cf33790a28643ab058b507b35cBen Cheng xlatefrom.d_type = xlateto.d_type = ELF_T_PHDR; 17625b3c049e70834cf33790a28643ab058b507b35cBen Cheng xlatefrom.d_size = phnum * phentsize; 17725b3c049e70834cf33790a28643ab058b507b35cBen Cheng 17825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((size_t) nread >= phoff + phnum * phentsize) 17925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* We already have all the phdrs from the initial read. */ 18025b3c049e70834cf33790a28643ab058b507b35cBen Cheng xlatefrom.d_buf = buffer + phoff; 18125b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 18225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 18325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Read in the program headers. */ 18425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 18525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (initial_bufsize < phnum * phentsize) 18625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 18725b3c049e70834cf33790a28643ab058b507b35cBen Cheng unsigned char *newbuf = realloc (buffer, phnum * phentsize); 18825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (newbuf == NULL) 18925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 19025b3c049e70834cf33790a28643ab058b507b35cBen Cheng free (buffer); 19125b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto no_memory; 19225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 19325b3c049e70834cf33790a28643ab058b507b35cBen Cheng buffer = newbuf; 19425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 19525b3c049e70834cf33790a28643ab058b507b35cBen Cheng nread = (*read_memory) (arg, buffer, ehdr_vma + phoff, 19625b3c049e70834cf33790a28643ab058b507b35cBen Cheng phnum * phentsize, phnum * phentsize); 19725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (nread <= 0) 19825b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto read_error; 19925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 20025b3c049e70834cf33790a28643ab058b507b35cBen Cheng xlatefrom.d_buf = buffer; 20125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 20225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 20325b3c049e70834cf33790a28643ab058b507b35cBen Cheng union 20425b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 20525b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf32_Phdr p32[phnum]; 20625b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf64_Phdr p64[phnum]; 20725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } phdrs; 20825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 20925b3c049e70834cf33790a28643ab058b507b35cBen Cheng xlateto.d_buf = &phdrs; 21025b3c049e70834cf33790a28643ab058b507b35cBen Cheng xlateto.d_size = sizeof phdrs; 21125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 21225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Scan for PT_LOAD segments to find the total size of the file image. */ 21325b3c049e70834cf33790a28643ab058b507b35cBen Cheng size_t contents_size = 0; 21425b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Off segments_end = 0; 21525b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Addr loadbase = ehdr_vma; 21625b3c049e70834cf33790a28643ab058b507b35cBen Cheng bool found_base = false; 21725b3c049e70834cf33790a28643ab058b507b35cBen Cheng switch (ehdr.e32.e_ident[EI_CLASS]) 21825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 21925b3c049e70834cf33790a28643ab058b507b35cBen Cheng inline void handle_segment (GElf_Addr vaddr, GElf_Off offset, 22025b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Xword filesz, GElf_Xword align) 22125b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 22225b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Off segment_end = ((offset + filesz + align - 1) & -align); 22325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 22425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (segment_end > (GElf_Off) contents_size) 22525b3c049e70834cf33790a28643ab058b507b35cBen Cheng contents_size = segment_end; 22625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 22725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (!found_base && (offset & -align) == 0) 22825b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 22925b3c049e70834cf33790a28643ab058b507b35cBen Cheng loadbase = ehdr_vma - (vaddr & -align); 23025b3c049e70834cf33790a28643ab058b507b35cBen Cheng found_base = true; 23125b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 23225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 23325b3c049e70834cf33790a28643ab058b507b35cBen Cheng segments_end = offset + filesz; 23425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 23525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 23625b3c049e70834cf33790a28643ab058b507b35cBen Cheng case ELFCLASS32: 23725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elf32_xlatetom (&xlateto, &xlatefrom, 23825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ehdr.e32.e_ident[EI_DATA]) == NULL) 23925b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto libelf_error; 24025b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (uint_fast16_t i = 0; i < phnum; ++i) 24125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (phdrs.p32[i].p_type == PT_LOAD) 24225b3c049e70834cf33790a28643ab058b507b35cBen Cheng handle_segment (phdrs.p32[i].p_vaddr, phdrs.p32[i].p_offset, 24325b3c049e70834cf33790a28643ab058b507b35cBen Cheng phdrs.p32[i].p_filesz, phdrs.p32[i].p_align); 24425b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 24525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 24625b3c049e70834cf33790a28643ab058b507b35cBen Cheng case ELFCLASS64: 24725b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elf64_xlatetom (&xlateto, &xlatefrom, 24825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ehdr.e64.e_ident[EI_DATA]) == NULL) 24925b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto libelf_error; 25025b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (uint_fast16_t i = 0; i < phnum; ++i) 25125b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (phdrs.p64[i].p_type == PT_LOAD) 25225b3c049e70834cf33790a28643ab058b507b35cBen Cheng handle_segment (phdrs.p64[i].p_vaddr, phdrs.p64[i].p_offset, 25325b3c049e70834cf33790a28643ab058b507b35cBen Cheng phdrs.p64[i].p_filesz, phdrs.p64[i].p_align); 25425b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 25525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 25625b3c049e70834cf33790a28643ab058b507b35cBen Cheng default: 25725b3c049e70834cf33790a28643ab058b507b35cBen Cheng abort (); 25825b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 25925b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 26025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 26125b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Trim the last segment so we don't bother with zeros in the last page 26225b3c049e70834cf33790a28643ab058b507b35cBen Cheng that are off the end of the file. However, if the extra bit in that 26325b3c049e70834cf33790a28643ab058b507b35cBen Cheng page includes the section headers, keep them. */ 26425b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((GElf_Off) contents_size > segments_end 26525b3c049e70834cf33790a28643ab058b507b35cBen Cheng && (GElf_Off) contents_size >= shdrs_end) 26625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 26725b3c049e70834cf33790a28643ab058b507b35cBen Cheng contents_size = segments_end; 26825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if ((GElf_Off) contents_size < shdrs_end) 26925b3c049e70834cf33790a28643ab058b507b35cBen Cheng contents_size = shdrs_end; 27025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 27125b3c049e70834cf33790a28643ab058b507b35cBen Cheng else 27225b3c049e70834cf33790a28643ab058b507b35cBen Cheng contents_size = segments_end; 27325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 27425b3c049e70834cf33790a28643ab058b507b35cBen Cheng free (buffer); 27525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 27625b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Now we know the size of the whole image we want read in. */ 27725b3c049e70834cf33790a28643ab058b507b35cBen Cheng buffer = calloc (1, contents_size); 27825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (buffer == NULL) 27925b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto no_memory; 28025b3c049e70834cf33790a28643ab058b507b35cBen Cheng 28125b3c049e70834cf33790a28643ab058b507b35cBen Cheng switch (ehdr.e32.e_ident[EI_CLASS]) 28225b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 28325b3c049e70834cf33790a28643ab058b507b35cBen Cheng inline bool handle_segment (GElf_Addr vaddr, GElf_Off offset, 28425b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Xword filesz, GElf_Xword align) 28525b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 28625b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Off start = offset & -align; 28725b3c049e70834cf33790a28643ab058b507b35cBen Cheng GElf_Off end = (offset + filesz + align - 1) & -align; 28825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (end > (GElf_Off) contents_size) 28925b3c049e70834cf33790a28643ab058b507b35cBen Cheng end = contents_size; 29025b3c049e70834cf33790a28643ab058b507b35cBen Cheng nread = (*read_memory) (arg, buffer + start, 29125b3c049e70834cf33790a28643ab058b507b35cBen Cheng (loadbase + vaddr) & -align, 29225b3c049e70834cf33790a28643ab058b507b35cBen Cheng end - start, end - start); 29325b3c049e70834cf33790a28643ab058b507b35cBen Cheng return nread <= 0; 29425b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 29525b3c049e70834cf33790a28643ab058b507b35cBen Cheng 29625b3c049e70834cf33790a28643ab058b507b35cBen Cheng case ELFCLASS32: 29725b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (uint_fast16_t i = 0; i < phnum; ++i) 29825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (phdrs.p32[i].p_type == PT_LOAD) 29925b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (handle_segment (phdrs.p32[i].p_vaddr, phdrs.p32[i].p_offset, 30025b3c049e70834cf33790a28643ab058b507b35cBen Cheng phdrs.p32[i].p_filesz, phdrs.p32[i].p_align)) 30125b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto read_error; 30225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 30325b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* If the segments visible in memory didn't include the section 30425b3c049e70834cf33790a28643ab058b507b35cBen Cheng headers, then clear them from the file header. */ 30525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (contents_size < shdrs_end) 30625b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 30725b3c049e70834cf33790a28643ab058b507b35cBen Cheng ehdr.e32.e_shoff = 0; 30825b3c049e70834cf33790a28643ab058b507b35cBen Cheng ehdr.e32.e_shnum = 0; 30925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ehdr.e32.e_shstrndx = 0; 31025b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 31125b3c049e70834cf33790a28643ab058b507b35cBen Cheng 31225b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* This will normally have been in the first PT_LOAD segment. But it 31325b3c049e70834cf33790a28643ab058b507b35cBen Cheng conceivably could be missing, and we might have just changed it. */ 31425b3c049e70834cf33790a28643ab058b507b35cBen Cheng xlatefrom.d_type = xlateto.d_type = ELF_T_EHDR; 31525b3c049e70834cf33790a28643ab058b507b35cBen Cheng xlatefrom.d_size = xlateto.d_size = sizeof ehdr.e32; 31625b3c049e70834cf33790a28643ab058b507b35cBen Cheng xlatefrom.d_buf = &ehdr.e32; 31725b3c049e70834cf33790a28643ab058b507b35cBen Cheng xlateto.d_buf = buffer; 31825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elf32_xlatetof (&xlateto, &xlatefrom, 31925b3c049e70834cf33790a28643ab058b507b35cBen Cheng ehdr.e32.e_ident[EI_DATA]) == NULL) 32025b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto libelf_error; 32125b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 32225b3c049e70834cf33790a28643ab058b507b35cBen Cheng 32325b3c049e70834cf33790a28643ab058b507b35cBen Cheng case ELFCLASS64: 32425b3c049e70834cf33790a28643ab058b507b35cBen Cheng for (uint_fast16_t i = 0; i < phnum; ++i) 32525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (phdrs.p32[i].p_type == PT_LOAD) 32625b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (handle_segment (phdrs.p64[i].p_vaddr, phdrs.p64[i].p_offset, 32725b3c049e70834cf33790a28643ab058b507b35cBen Cheng phdrs.p64[i].p_filesz, phdrs.p64[i].p_align)) 32825b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto read_error; 32925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 33025b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* If the segments visible in memory didn't include the section 33125b3c049e70834cf33790a28643ab058b507b35cBen Cheng headers, then clear them from the file header. */ 33225b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (contents_size < shdrs_end) 33325b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 33425b3c049e70834cf33790a28643ab058b507b35cBen Cheng ehdr.e64.e_shoff = 0; 33525b3c049e70834cf33790a28643ab058b507b35cBen Cheng ehdr.e64.e_shnum = 0; 33625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ehdr.e64.e_shstrndx = 0; 33725b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 33825b3c049e70834cf33790a28643ab058b507b35cBen Cheng 33925b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* This will normally have been in the first PT_LOAD segment. But it 34025b3c049e70834cf33790a28643ab058b507b35cBen Cheng conceivably could be missing, and we might have just changed it. */ 34125b3c049e70834cf33790a28643ab058b507b35cBen Cheng xlatefrom.d_type = xlateto.d_type = ELF_T_EHDR; 34225b3c049e70834cf33790a28643ab058b507b35cBen Cheng xlatefrom.d_size = xlateto.d_size = sizeof ehdr.e64; 34325b3c049e70834cf33790a28643ab058b507b35cBen Cheng xlatefrom.d_buf = &ehdr.e64; 34425b3c049e70834cf33790a28643ab058b507b35cBen Cheng xlateto.d_buf = buffer; 34525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elf64_xlatetof (&xlateto, &xlatefrom, 34625b3c049e70834cf33790a28643ab058b507b35cBen Cheng ehdr.e64.e_ident[EI_DATA]) == NULL) 34725b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto libelf_error; 34825b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 34925b3c049e70834cf33790a28643ab058b507b35cBen Cheng 35025b3c049e70834cf33790a28643ab058b507b35cBen Cheng default: 35125b3c049e70834cf33790a28643ab058b507b35cBen Cheng abort (); 35225b3c049e70834cf33790a28643ab058b507b35cBen Cheng break; 35325b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 35425b3c049e70834cf33790a28643ab058b507b35cBen Cheng 35525b3c049e70834cf33790a28643ab058b507b35cBen Cheng /* Now we have the image. Open libelf on it. */ 35625b3c049e70834cf33790a28643ab058b507b35cBen Cheng 35725b3c049e70834cf33790a28643ab058b507b35cBen Cheng Elf *elf = elf_memory ((char *) buffer, contents_size); 35825b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (elf == NULL) 35925b3c049e70834cf33790a28643ab058b507b35cBen Cheng { 36025b3c049e70834cf33790a28643ab058b507b35cBen Cheng free (buffer); 36125b3c049e70834cf33790a28643ab058b507b35cBen Cheng goto libelf_error; 36225b3c049e70834cf33790a28643ab058b507b35cBen Cheng } 36325b3c049e70834cf33790a28643ab058b507b35cBen Cheng 36425b3c049e70834cf33790a28643ab058b507b35cBen Cheng elf->flags |= ELF_F_MALLOCED; 36525b3c049e70834cf33790a28643ab058b507b35cBen Cheng if (loadbasep != NULL) 36625b3c049e70834cf33790a28643ab058b507b35cBen Cheng *loadbasep = loadbase; 36725b3c049e70834cf33790a28643ab058b507b35cBen Cheng return elf; 36825b3c049e70834cf33790a28643ab058b507b35cBen Cheng} 369