1da0c48c4Sopenharmony_ci/* Reconstruct an ELF file by reading the segments out of remote memory. 2da0c48c4Sopenharmony_ci Copyright (C) 2005-2011, 2014, 2015 Red Hat, Inc. 3da0c48c4Sopenharmony_ci This file is part of elfutils. 4da0c48c4Sopenharmony_ci 5da0c48c4Sopenharmony_ci This file is free software; you can redistribute it and/or modify 6da0c48c4Sopenharmony_ci it under the terms of either 7da0c48c4Sopenharmony_ci 8da0c48c4Sopenharmony_ci * the GNU Lesser General Public License as published by the Free 9da0c48c4Sopenharmony_ci Software Foundation; either version 3 of the License, or (at 10da0c48c4Sopenharmony_ci your option) any later version 11da0c48c4Sopenharmony_ci 12da0c48c4Sopenharmony_ci or 13da0c48c4Sopenharmony_ci 14da0c48c4Sopenharmony_ci * the GNU General Public License as published by the Free 15da0c48c4Sopenharmony_ci Software Foundation; either version 2 of the License, or (at 16da0c48c4Sopenharmony_ci your option) any later version 17da0c48c4Sopenharmony_ci 18da0c48c4Sopenharmony_ci or both in parallel, as here. 19da0c48c4Sopenharmony_ci 20da0c48c4Sopenharmony_ci elfutils is distributed in the hope that it will be useful, but 21da0c48c4Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 22da0c48c4Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23da0c48c4Sopenharmony_ci General Public License for more details. 24da0c48c4Sopenharmony_ci 25da0c48c4Sopenharmony_ci You should have received copies of the GNU General Public License and 26da0c48c4Sopenharmony_ci the GNU Lesser General Public License along with this program. If 27da0c48c4Sopenharmony_ci not, see <http://www.gnu.org/licenses/>. */ 28da0c48c4Sopenharmony_ci 29da0c48c4Sopenharmony_ci#include <config.h> 30da0c48c4Sopenharmony_ci#include "../libelf/libelfP.h" 31da0c48c4Sopenharmony_ci#undef _ 32da0c48c4Sopenharmony_ci 33da0c48c4Sopenharmony_ci#include "libdwflP.h" 34da0c48c4Sopenharmony_ci 35da0c48c4Sopenharmony_ci#include <gelf.h> 36da0c48c4Sopenharmony_ci#include <sys/types.h> 37da0c48c4Sopenharmony_ci#include <stdbool.h> 38da0c48c4Sopenharmony_ci#include <stdlib.h> 39da0c48c4Sopenharmony_ci#include <string.h> 40da0c48c4Sopenharmony_ci 41da0c48c4Sopenharmony_ci/* Reconstruct an ELF file by reading the segments out of remote memory 42da0c48c4Sopenharmony_ci based on the ELF file header at EHDR_VMA and the ELF program headers it 43da0c48c4Sopenharmony_ci points to. If not null, *LOADBASEP is filled in with the difference 44da0c48c4Sopenharmony_ci between the addresses from which the segments were read, and the 45da0c48c4Sopenharmony_ci addresses the file headers put them at. 46da0c48c4Sopenharmony_ci 47da0c48c4Sopenharmony_ci The function READ_MEMORY is called to copy at least MINREAD and at most 48da0c48c4Sopenharmony_ci MAXREAD bytes from the remote memory at target address ADDRESS into the 49da0c48c4Sopenharmony_ci local buffer at DATA; it should return -1 for errors (with code in 50da0c48c4Sopenharmony_ci `errno'), 0 if it failed to read at least MINREAD bytes due to EOF, or 51da0c48c4Sopenharmony_ci the number of bytes read if >= MINREAD. ARG is passed through. 52da0c48c4Sopenharmony_ci 53da0c48c4Sopenharmony_ci PAGESIZE is the minimum page size and alignment used for the PT_LOAD 54da0c48c4Sopenharmony_ci segments. */ 55da0c48c4Sopenharmony_ci 56da0c48c4Sopenharmony_ciElf * 57da0c48c4Sopenharmony_cielf_from_remote_memory (GElf_Addr ehdr_vma, 58da0c48c4Sopenharmony_ci GElf_Xword pagesize, 59da0c48c4Sopenharmony_ci GElf_Addr *loadbasep, 60da0c48c4Sopenharmony_ci ssize_t (*read_memory) (void *arg, void *data, 61da0c48c4Sopenharmony_ci GElf_Addr address, 62da0c48c4Sopenharmony_ci size_t minread, 63da0c48c4Sopenharmony_ci size_t maxread), 64da0c48c4Sopenharmony_ci void *arg) 65da0c48c4Sopenharmony_ci{ 66da0c48c4Sopenharmony_ci /* We might have to reserve some memory for the phdrs. Set to NULL 67da0c48c4Sopenharmony_ci here so we can always safely free it. */ 68da0c48c4Sopenharmony_ci void *phdrsp = NULL; 69da0c48c4Sopenharmony_ci 70da0c48c4Sopenharmony_ci /* First read in the file header and check its sanity. */ 71da0c48c4Sopenharmony_ci 72da0c48c4Sopenharmony_ci const size_t initial_bufsize = 256; 73da0c48c4Sopenharmony_ci unsigned char *buffer = malloc (initial_bufsize); 74da0c48c4Sopenharmony_ci if (unlikely (buffer == NULL)) 75da0c48c4Sopenharmony_ci { 76da0c48c4Sopenharmony_ci no_memory: 77da0c48c4Sopenharmony_ci __libdwfl_seterrno (DWFL_E_NOMEM); 78da0c48c4Sopenharmony_ci return NULL; 79da0c48c4Sopenharmony_ci } 80da0c48c4Sopenharmony_ci 81da0c48c4Sopenharmony_ci ssize_t nread = (*read_memory) (arg, buffer, ehdr_vma, 82da0c48c4Sopenharmony_ci sizeof (Elf32_Ehdr), initial_bufsize); 83da0c48c4Sopenharmony_ci if (nread <= 0) 84da0c48c4Sopenharmony_ci { 85da0c48c4Sopenharmony_ci read_error: 86da0c48c4Sopenharmony_ci free (buffer); 87da0c48c4Sopenharmony_ci free (phdrsp); 88da0c48c4Sopenharmony_ci __libdwfl_seterrno (nread < 0 ? DWFL_E_ERRNO : DWFL_E_TRUNCATED); 89da0c48c4Sopenharmony_ci return NULL; 90da0c48c4Sopenharmony_ci } 91da0c48c4Sopenharmony_ci 92da0c48c4Sopenharmony_ci if (memcmp (buffer, ELFMAG, SELFMAG) != 0) 93da0c48c4Sopenharmony_ci { 94da0c48c4Sopenharmony_ci bad_elf: 95da0c48c4Sopenharmony_ci free (buffer); 96da0c48c4Sopenharmony_ci free (phdrsp); 97da0c48c4Sopenharmony_ci __libdwfl_seterrno (DWFL_E_BADELF); 98da0c48c4Sopenharmony_ci return NULL; 99da0c48c4Sopenharmony_ci } 100da0c48c4Sopenharmony_ci 101da0c48c4Sopenharmony_ci /* Extract the information we need from the file header. */ 102da0c48c4Sopenharmony_ci 103da0c48c4Sopenharmony_ci union 104da0c48c4Sopenharmony_ci { 105da0c48c4Sopenharmony_ci Elf32_Ehdr e32; 106da0c48c4Sopenharmony_ci Elf64_Ehdr e64; 107da0c48c4Sopenharmony_ci } ehdr; 108da0c48c4Sopenharmony_ci Elf_Data xlatefrom = 109da0c48c4Sopenharmony_ci { 110da0c48c4Sopenharmony_ci .d_type = ELF_T_EHDR, 111da0c48c4Sopenharmony_ci .d_buf = buffer, 112da0c48c4Sopenharmony_ci .d_version = EV_CURRENT, 113da0c48c4Sopenharmony_ci }; 114da0c48c4Sopenharmony_ci Elf_Data xlateto = 115da0c48c4Sopenharmony_ci { 116da0c48c4Sopenharmony_ci .d_type = ELF_T_EHDR, 117da0c48c4Sopenharmony_ci .d_buf = &ehdr, 118da0c48c4Sopenharmony_ci .d_size = sizeof ehdr, 119da0c48c4Sopenharmony_ci .d_version = EV_CURRENT, 120da0c48c4Sopenharmony_ci }; 121da0c48c4Sopenharmony_ci 122da0c48c4Sopenharmony_ci GElf_Off phoff; 123da0c48c4Sopenharmony_ci uint_fast16_t phnum; 124da0c48c4Sopenharmony_ci uint_fast16_t phentsize; 125da0c48c4Sopenharmony_ci GElf_Off shdrs_end; 126da0c48c4Sopenharmony_ci 127da0c48c4Sopenharmony_ci switch (buffer[EI_CLASS]) 128da0c48c4Sopenharmony_ci { 129da0c48c4Sopenharmony_ci case ELFCLASS32: 130da0c48c4Sopenharmony_ci xlatefrom.d_size = sizeof (Elf32_Ehdr); 131da0c48c4Sopenharmony_ci if (elf32_xlatetom (&xlateto, &xlatefrom, buffer[EI_DATA]) == NULL) 132da0c48c4Sopenharmony_ci { 133da0c48c4Sopenharmony_ci libelf_error: 134da0c48c4Sopenharmony_ci __libdwfl_seterrno (DWFL_E_LIBELF); 135da0c48c4Sopenharmony_ci return NULL; 136da0c48c4Sopenharmony_ci } 137da0c48c4Sopenharmony_ci phoff = ehdr.e32.e_phoff; 138da0c48c4Sopenharmony_ci phnum = ehdr.e32.e_phnum; 139da0c48c4Sopenharmony_ci phentsize = ehdr.e32.e_phentsize; 140da0c48c4Sopenharmony_ci if (phentsize != sizeof (Elf32_Phdr) || phnum == 0) 141da0c48c4Sopenharmony_ci goto bad_elf; 142da0c48c4Sopenharmony_ci /* NOTE if the number of sections is > 0xff00 then e_shnum 143da0c48c4Sopenharmony_ci is zero and the actual number would come from the section 144da0c48c4Sopenharmony_ci zero sh_size field. We ignore this here because getting shdrs 145da0c48c4Sopenharmony_ci is just a nice bonus (see below where we trim the last phdrs 146da0c48c4Sopenharmony_ci PT_LOAD segment). */ 147da0c48c4Sopenharmony_ci shdrs_end = ehdr.e32.e_shoff + ehdr.e32.e_shnum * ehdr.e32.e_shentsize; 148da0c48c4Sopenharmony_ci break; 149da0c48c4Sopenharmony_ci 150da0c48c4Sopenharmony_ci case ELFCLASS64: 151da0c48c4Sopenharmony_ci xlatefrom.d_size = sizeof (Elf64_Ehdr); 152da0c48c4Sopenharmony_ci if (elf64_xlatetom (&xlateto, &xlatefrom, buffer[EI_DATA]) == NULL) 153da0c48c4Sopenharmony_ci goto libelf_error; 154da0c48c4Sopenharmony_ci phoff = ehdr.e64.e_phoff; 155da0c48c4Sopenharmony_ci phnum = ehdr.e64.e_phnum; 156da0c48c4Sopenharmony_ci phentsize = ehdr.e64.e_phentsize; 157da0c48c4Sopenharmony_ci if (phentsize != sizeof (Elf64_Phdr) || phnum == 0) 158da0c48c4Sopenharmony_ci goto bad_elf; 159da0c48c4Sopenharmony_ci /* See the NOTE above for shdrs_end and ehdr.e32.e_shnum. */ 160da0c48c4Sopenharmony_ci shdrs_end = ehdr.e64.e_shoff + ehdr.e64.e_shnum * ehdr.e64.e_shentsize; 161da0c48c4Sopenharmony_ci break; 162da0c48c4Sopenharmony_ci 163da0c48c4Sopenharmony_ci default: 164da0c48c4Sopenharmony_ci goto bad_elf; 165da0c48c4Sopenharmony_ci } 166da0c48c4Sopenharmony_ci 167da0c48c4Sopenharmony_ci 168da0c48c4Sopenharmony_ci /* The file header tells where to find the program headers. 169da0c48c4Sopenharmony_ci These are what we use to actually choose what to read. */ 170da0c48c4Sopenharmony_ci 171da0c48c4Sopenharmony_ci xlatefrom.d_type = xlateto.d_type = ELF_T_PHDR; 172da0c48c4Sopenharmony_ci xlatefrom.d_size = phnum * phentsize; 173da0c48c4Sopenharmony_ci 174da0c48c4Sopenharmony_ci if ((size_t) nread >= phoff + phnum * phentsize) 175da0c48c4Sopenharmony_ci /* We already have all the phdrs from the initial read. */ 176da0c48c4Sopenharmony_ci xlatefrom.d_buf = buffer + phoff; 177da0c48c4Sopenharmony_ci else 178da0c48c4Sopenharmony_ci { 179da0c48c4Sopenharmony_ci /* Read in the program headers. */ 180da0c48c4Sopenharmony_ci 181da0c48c4Sopenharmony_ci if (initial_bufsize < (size_t)phnum * phentsize) 182da0c48c4Sopenharmony_ci { 183da0c48c4Sopenharmony_ci unsigned char *newbuf = realloc (buffer, phnum * phentsize); 184da0c48c4Sopenharmony_ci if (newbuf == NULL) 185da0c48c4Sopenharmony_ci { 186da0c48c4Sopenharmony_ci free (buffer); 187da0c48c4Sopenharmony_ci free (phdrsp); 188da0c48c4Sopenharmony_ci goto no_memory; 189da0c48c4Sopenharmony_ci } 190da0c48c4Sopenharmony_ci buffer = newbuf; 191da0c48c4Sopenharmony_ci } 192da0c48c4Sopenharmony_ci nread = (*read_memory) (arg, buffer, ehdr_vma + phoff, 193da0c48c4Sopenharmony_ci phnum * phentsize, phnum * phentsize); 194da0c48c4Sopenharmony_ci if (nread <= 0) 195da0c48c4Sopenharmony_ci goto read_error; 196da0c48c4Sopenharmony_ci 197da0c48c4Sopenharmony_ci xlatefrom.d_buf = buffer; 198da0c48c4Sopenharmony_ci } 199da0c48c4Sopenharmony_ci 200da0c48c4Sopenharmony_ci bool class32 = ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32; 201da0c48c4Sopenharmony_ci size_t phdr_size = class32 ? sizeof (Elf32_Phdr) : sizeof (Elf64_Phdr); 202da0c48c4Sopenharmony_ci if (unlikely (phnum > SIZE_MAX / phdr_size)) 203da0c48c4Sopenharmony_ci { 204da0c48c4Sopenharmony_ci free (buffer); 205da0c48c4Sopenharmony_ci goto no_memory; 206da0c48c4Sopenharmony_ci } 207da0c48c4Sopenharmony_ci const size_t phdrsp_bytes = phnum * phdr_size; 208da0c48c4Sopenharmony_ci phdrsp = malloc (phdrsp_bytes); 209da0c48c4Sopenharmony_ci if (unlikely (phdrsp == NULL)) 210da0c48c4Sopenharmony_ci { 211da0c48c4Sopenharmony_ci free (buffer); 212da0c48c4Sopenharmony_ci goto no_memory; 213da0c48c4Sopenharmony_ci } 214da0c48c4Sopenharmony_ci 215da0c48c4Sopenharmony_ci xlateto.d_buf = phdrsp; 216da0c48c4Sopenharmony_ci xlateto.d_size = phdrsp_bytes; 217da0c48c4Sopenharmony_ci 218da0c48c4Sopenharmony_ci /* Scan for PT_LOAD segments to find the total size of the file image. */ 219da0c48c4Sopenharmony_ci size_t contents_size = 0; 220da0c48c4Sopenharmony_ci GElf_Off segments_end = 0; 221da0c48c4Sopenharmony_ci GElf_Off segments_end_mem = 0; 222da0c48c4Sopenharmony_ci GElf_Addr loadbase = ehdr_vma; 223da0c48c4Sopenharmony_ci bool found_base = false; 224da0c48c4Sopenharmony_ci Elf32_Phdr (*p32)[phnum] = phdrsp; 225da0c48c4Sopenharmony_ci Elf64_Phdr (*p64)[phnum] = phdrsp; 226da0c48c4Sopenharmony_ci 227da0c48c4Sopenharmony_ci if (class32) 228da0c48c4Sopenharmony_ci { 229da0c48c4Sopenharmony_ci if (! elf32_xlatetom (&xlateto, &xlatefrom, ehdr.e32.e_ident[EI_DATA])) 230da0c48c4Sopenharmony_ci goto libelf_error; 231da0c48c4Sopenharmony_ci } 232da0c48c4Sopenharmony_ci else 233da0c48c4Sopenharmony_ci { 234da0c48c4Sopenharmony_ci if (! elf64_xlatetom (&xlateto, &xlatefrom, ehdr.e64.e_ident[EI_DATA])) 235da0c48c4Sopenharmony_ci goto libelf_error; 236da0c48c4Sopenharmony_ci } 237da0c48c4Sopenharmony_ci 238da0c48c4Sopenharmony_ci for (uint_fast16_t i = 0; i < phnum; ++i) 239da0c48c4Sopenharmony_ci { 240da0c48c4Sopenharmony_ci GElf_Word type = class32 ? (*p32)[i].p_type : (*p64)[i].p_type; 241da0c48c4Sopenharmony_ci 242da0c48c4Sopenharmony_ci if (type != PT_LOAD) 243da0c48c4Sopenharmony_ci continue; 244da0c48c4Sopenharmony_ci 245da0c48c4Sopenharmony_ci GElf_Addr vaddr = class32 ? (*p32)[i].p_vaddr : (*p64)[i].p_vaddr; 246da0c48c4Sopenharmony_ci GElf_Xword memsz = class32 ? (*p32)[i].p_memsz : (*p64)[i].p_memsz; 247da0c48c4Sopenharmony_ci GElf_Off offset = class32 ? (*p32)[i].p_offset : (*p64)[i].p_offset; 248da0c48c4Sopenharmony_ci GElf_Xword filesz = class32 ? (*p32)[i].p_filesz : (*p64)[i].p_filesz; 249da0c48c4Sopenharmony_ci 250da0c48c4Sopenharmony_ci /* Sanity check the segment load aligns with the pagesize. */ 251da0c48c4Sopenharmony_ci if (((vaddr - offset) & (pagesize - 1)) != 0) 252da0c48c4Sopenharmony_ci goto bad_elf; 253da0c48c4Sopenharmony_ci 254da0c48c4Sopenharmony_ci GElf_Off segment_end = ((offset + filesz + pagesize - 1) 255da0c48c4Sopenharmony_ci & -pagesize); 256da0c48c4Sopenharmony_ci 257da0c48c4Sopenharmony_ci if (segment_end > (GElf_Off) contents_size) 258da0c48c4Sopenharmony_ci contents_size = segment_end; 259da0c48c4Sopenharmony_ci 260da0c48c4Sopenharmony_ci if (!found_base && (offset & -pagesize) == 0) 261da0c48c4Sopenharmony_ci { 262da0c48c4Sopenharmony_ci loadbase = ehdr_vma - (vaddr & -pagesize); 263da0c48c4Sopenharmony_ci found_base = true; 264da0c48c4Sopenharmony_ci } 265da0c48c4Sopenharmony_ci 266da0c48c4Sopenharmony_ci segments_end = offset + filesz; 267da0c48c4Sopenharmony_ci segments_end_mem = offset + memsz; 268da0c48c4Sopenharmony_ci } 269da0c48c4Sopenharmony_ci 270da0c48c4Sopenharmony_ci /* Trim the last segment so we don't bother with zeros in the last page 271da0c48c4Sopenharmony_ci that are off the end of the file. However, if the extra bit in that 272da0c48c4Sopenharmony_ci page includes the section headers and the memory isn't extended (which 273da0c48c4Sopenharmony_ci might indicate it will have been reused otherwise), keep them. */ 274da0c48c4Sopenharmony_ci if ((GElf_Off) contents_size > segments_end 275da0c48c4Sopenharmony_ci && (GElf_Off) contents_size >= shdrs_end 276da0c48c4Sopenharmony_ci && segments_end == segments_end_mem) 277da0c48c4Sopenharmony_ci { 278da0c48c4Sopenharmony_ci contents_size = segments_end; 279da0c48c4Sopenharmony_ci if ((GElf_Off) contents_size < shdrs_end) 280da0c48c4Sopenharmony_ci contents_size = shdrs_end; 281da0c48c4Sopenharmony_ci } 282da0c48c4Sopenharmony_ci else 283da0c48c4Sopenharmony_ci contents_size = segments_end; 284da0c48c4Sopenharmony_ci 285da0c48c4Sopenharmony_ci free (buffer); 286da0c48c4Sopenharmony_ci 287da0c48c4Sopenharmony_ci /* Now we know the size of the whole image we want read in. */ 288da0c48c4Sopenharmony_ci buffer = calloc (1, contents_size); 289da0c48c4Sopenharmony_ci if (buffer == NULL) 290da0c48c4Sopenharmony_ci { 291da0c48c4Sopenharmony_ci free (phdrsp); 292da0c48c4Sopenharmony_ci goto no_memory; 293da0c48c4Sopenharmony_ci } 294da0c48c4Sopenharmony_ci 295da0c48c4Sopenharmony_ci for (uint_fast16_t i = 0; i < phnum; ++i) 296da0c48c4Sopenharmony_ci { 297da0c48c4Sopenharmony_ci GElf_Word type = class32 ? (*p32)[i].p_type : (*p64)[i].p_type; 298da0c48c4Sopenharmony_ci 299da0c48c4Sopenharmony_ci if (type != PT_LOAD) 300da0c48c4Sopenharmony_ci continue; 301da0c48c4Sopenharmony_ci 302da0c48c4Sopenharmony_ci GElf_Addr vaddr = class32 ? (*p32)[i].p_vaddr : (*p64)[i].p_vaddr; 303da0c48c4Sopenharmony_ci GElf_Off offset = class32 ? (*p32)[i].p_offset : (*p64)[i].p_offset; 304da0c48c4Sopenharmony_ci GElf_Xword filesz = class32 ? (*p32)[i].p_filesz : (*p64)[i].p_filesz; 305da0c48c4Sopenharmony_ci 306da0c48c4Sopenharmony_ci GElf_Off start = offset & -pagesize; 307da0c48c4Sopenharmony_ci GElf_Off end = (offset + filesz + pagesize - 1) & -pagesize; 308da0c48c4Sopenharmony_ci if (end > (GElf_Off) contents_size) 309da0c48c4Sopenharmony_ci end = contents_size; 310da0c48c4Sopenharmony_ci nread = (*read_memory) (arg, buffer + start, 311da0c48c4Sopenharmony_ci (loadbase + vaddr) & -pagesize, 312da0c48c4Sopenharmony_ci end - start, end - start); 313da0c48c4Sopenharmony_ci if (nread <= 0) 314da0c48c4Sopenharmony_ci goto read_error; 315da0c48c4Sopenharmony_ci } 316da0c48c4Sopenharmony_ci 317da0c48c4Sopenharmony_ci /* If the segments visible in memory didn't include the section 318da0c48c4Sopenharmony_ci headers, then clear them from the file header. */ 319da0c48c4Sopenharmony_ci if (contents_size < shdrs_end) 320da0c48c4Sopenharmony_ci { 321da0c48c4Sopenharmony_ci if (class32) 322da0c48c4Sopenharmony_ci { 323da0c48c4Sopenharmony_ci ehdr.e32.e_shoff = 0; 324da0c48c4Sopenharmony_ci ehdr.e32.e_shnum = 0; 325da0c48c4Sopenharmony_ci ehdr.e32.e_shstrndx = 0; 326da0c48c4Sopenharmony_ci } 327da0c48c4Sopenharmony_ci else 328da0c48c4Sopenharmony_ci { 329da0c48c4Sopenharmony_ci ehdr.e64.e_shoff = 0; 330da0c48c4Sopenharmony_ci ehdr.e64.e_shnum = 0; 331da0c48c4Sopenharmony_ci ehdr.e64.e_shstrndx = 0; 332da0c48c4Sopenharmony_ci } 333da0c48c4Sopenharmony_ci } 334da0c48c4Sopenharmony_ci 335da0c48c4Sopenharmony_ci /* This will normally have been in the first PT_LOAD segment. But it 336da0c48c4Sopenharmony_ci conceivably could be missing, and we might have just changed it. */ 337da0c48c4Sopenharmony_ci xlatefrom.d_type = xlateto.d_type = ELF_T_EHDR; 338da0c48c4Sopenharmony_ci xlateto.d_buf = buffer; 339da0c48c4Sopenharmony_ci if (class32) 340da0c48c4Sopenharmony_ci { 341da0c48c4Sopenharmony_ci xlatefrom.d_size = xlateto.d_size = sizeof ehdr.e32; 342da0c48c4Sopenharmony_ci xlatefrom.d_buf = &ehdr.e32; 343da0c48c4Sopenharmony_ci if (elf32_xlatetof (&xlateto, &xlatefrom, 344da0c48c4Sopenharmony_ci ehdr.e32.e_ident[EI_DATA]) == NULL) 345da0c48c4Sopenharmony_ci goto libelf_error; 346da0c48c4Sopenharmony_ci } 347da0c48c4Sopenharmony_ci else 348da0c48c4Sopenharmony_ci { 349da0c48c4Sopenharmony_ci xlatefrom.d_size = xlateto.d_size = sizeof ehdr.e64; 350da0c48c4Sopenharmony_ci xlatefrom.d_buf = &ehdr.e64; 351da0c48c4Sopenharmony_ci if (elf64_xlatetof (&xlateto, &xlatefrom, 352da0c48c4Sopenharmony_ci ehdr.e64.e_ident[EI_DATA]) == NULL) 353da0c48c4Sopenharmony_ci goto libelf_error; 354da0c48c4Sopenharmony_ci } 355da0c48c4Sopenharmony_ci 356da0c48c4Sopenharmony_ci free (phdrsp); 357da0c48c4Sopenharmony_ci phdrsp = NULL; 358da0c48c4Sopenharmony_ci 359da0c48c4Sopenharmony_ci /* Now we have the image. Open libelf on it. */ 360da0c48c4Sopenharmony_ci 361da0c48c4Sopenharmony_ci Elf *elf = elf_memory ((char *) buffer, contents_size); 362da0c48c4Sopenharmony_ci if (elf == NULL) 363da0c48c4Sopenharmony_ci { 364da0c48c4Sopenharmony_ci free (buffer); 365da0c48c4Sopenharmony_ci goto libelf_error; 366da0c48c4Sopenharmony_ci } 367da0c48c4Sopenharmony_ci 368da0c48c4Sopenharmony_ci elf->flags |= ELF_F_MALLOCED; 369da0c48c4Sopenharmony_ci if (loadbasep != NULL) 370da0c48c4Sopenharmony_ci *loadbasep = loadbase; 371da0c48c4Sopenharmony_ci return elf; 372da0c48c4Sopenharmony_ci} 373