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