xref: /aosp_15_r20/external/elfutils/libelf/elf_begin.c (revision 7304104da70ce23c86437a01be71edd1a2d7f37e)
1*7304104dSAndroid Build Coastguard Worker /* Create descriptor for processing file.
2*7304104dSAndroid Build Coastguard Worker    Copyright (C) 1998-2010, 2012, 2014, 2015, 2016 Red Hat, Inc.
3*7304104dSAndroid Build Coastguard Worker    Copyright (C) 2021, 2022 Mark J. Wielaard <[email protected]>
4*7304104dSAndroid Build Coastguard Worker    This file is part of elfutils.
5*7304104dSAndroid Build Coastguard Worker    Written by Ulrich Drepper <[email protected]>, 1998.
6*7304104dSAndroid Build Coastguard Worker 
7*7304104dSAndroid Build Coastguard Worker    This file is free software; you can redistribute it and/or modify
8*7304104dSAndroid Build Coastguard Worker    it under the terms of either
9*7304104dSAndroid Build Coastguard Worker 
10*7304104dSAndroid Build Coastguard Worker      * the GNU Lesser General Public License as published by the Free
11*7304104dSAndroid Build Coastguard Worker        Software Foundation; either version 3 of the License, or (at
12*7304104dSAndroid Build Coastguard Worker        your option) any later version
13*7304104dSAndroid Build Coastguard Worker 
14*7304104dSAndroid Build Coastguard Worker    or
15*7304104dSAndroid Build Coastguard Worker 
16*7304104dSAndroid Build Coastguard Worker      * the GNU General Public License as published by the Free
17*7304104dSAndroid Build Coastguard Worker        Software Foundation; either version 2 of the License, or (at
18*7304104dSAndroid Build Coastguard Worker        your option) any later version
19*7304104dSAndroid Build Coastguard Worker 
20*7304104dSAndroid Build Coastguard Worker    or both in parallel, as here.
21*7304104dSAndroid Build Coastguard Worker 
22*7304104dSAndroid Build Coastguard Worker    elfutils is distributed in the hope that it will be useful, but
23*7304104dSAndroid Build Coastguard Worker    WITHOUT ANY WARRANTY; without even the implied warranty of
24*7304104dSAndroid Build Coastguard Worker    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25*7304104dSAndroid Build Coastguard Worker    General Public License for more details.
26*7304104dSAndroid Build Coastguard Worker 
27*7304104dSAndroid Build Coastguard Worker    You should have received copies of the GNU General Public License and
28*7304104dSAndroid Build Coastguard Worker    the GNU Lesser General Public License along with this program.  If
29*7304104dSAndroid Build Coastguard Worker    not, see <http://www.gnu.org/licenses/>.  */
30*7304104dSAndroid Build Coastguard Worker 
31*7304104dSAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
32*7304104dSAndroid Build Coastguard Worker # include <config.h>
33*7304104dSAndroid Build Coastguard Worker #endif
34*7304104dSAndroid Build Coastguard Worker 
35*7304104dSAndroid Build Coastguard Worker #include <assert.h>
36*7304104dSAndroid Build Coastguard Worker #include <ctype.h>
37*7304104dSAndroid Build Coastguard Worker #include <errno.h>
38*7304104dSAndroid Build Coastguard Worker #include <fcntl.h>
39*7304104dSAndroid Build Coastguard Worker #include <stdbool.h>
40*7304104dSAndroid Build Coastguard Worker #include <stddef.h>
41*7304104dSAndroid Build Coastguard Worker #include <stdint.h>
42*7304104dSAndroid Build Coastguard Worker #include <string.h>
43*7304104dSAndroid Build Coastguard Worker #include <sys/stat.h>
44*7304104dSAndroid Build Coastguard Worker 
45*7304104dSAndroid Build Coastguard Worker #include "libelfP.h"
46*7304104dSAndroid Build Coastguard Worker #include "common.h"
47*7304104dSAndroid Build Coastguard Worker 
48*7304104dSAndroid Build Coastguard Worker 
49*7304104dSAndroid Build Coastguard Worker /* Create descriptor for archive in memory.  */
50*7304104dSAndroid Build Coastguard Worker static inline Elf *
file_read_ar(int fildes,void * map_address,off_t offset,size_t maxsize,Elf_Cmd cmd,Elf * parent)51*7304104dSAndroid Build Coastguard Worker file_read_ar (int fildes, void *map_address, off_t offset, size_t maxsize,
52*7304104dSAndroid Build Coastguard Worker 	      Elf_Cmd cmd, Elf *parent)
53*7304104dSAndroid Build Coastguard Worker {
54*7304104dSAndroid Build Coastguard Worker   Elf *elf;
55*7304104dSAndroid Build Coastguard Worker 
56*7304104dSAndroid Build Coastguard Worker   /* Create a descriptor.  */
57*7304104dSAndroid Build Coastguard Worker   elf = allocate_elf (fildes, map_address, offset, maxsize, cmd, parent,
58*7304104dSAndroid Build Coastguard Worker                       ELF_K_AR, 0);
59*7304104dSAndroid Build Coastguard Worker   if (elf != NULL)
60*7304104dSAndroid Build Coastguard Worker     {
61*7304104dSAndroid Build Coastguard Worker       /* We don't read all the symbol tables in advance.  All this will
62*7304104dSAndroid Build Coastguard Worker 	 happen on demand.  */
63*7304104dSAndroid Build Coastguard Worker       elf->state.ar.offset = offset + SARMAG;
64*7304104dSAndroid Build Coastguard Worker 
65*7304104dSAndroid Build Coastguard Worker       elf->state.ar.elf_ar_hdr.ar_rawname = elf->state.ar.raw_name;
66*7304104dSAndroid Build Coastguard Worker     }
67*7304104dSAndroid Build Coastguard Worker 
68*7304104dSAndroid Build Coastguard Worker   return elf;
69*7304104dSAndroid Build Coastguard Worker }
70*7304104dSAndroid Build Coastguard Worker 
71*7304104dSAndroid Build Coastguard Worker 
72*7304104dSAndroid Build Coastguard Worker static size_t
get_shnum(void * map_address,unsigned char * e_ident,int fildes,int64_t offset,size_t maxsize)73*7304104dSAndroid Build Coastguard Worker get_shnum (void *map_address, unsigned char *e_ident, int fildes,
74*7304104dSAndroid Build Coastguard Worker 	   int64_t offset, size_t maxsize)
75*7304104dSAndroid Build Coastguard Worker {
76*7304104dSAndroid Build Coastguard Worker   size_t result;
77*7304104dSAndroid Build Coastguard Worker   union
78*7304104dSAndroid Build Coastguard Worker   {
79*7304104dSAndroid Build Coastguard Worker     Elf32_Ehdr *e32;
80*7304104dSAndroid Build Coastguard Worker     Elf64_Ehdr *e64;
81*7304104dSAndroid Build Coastguard Worker     void *p;
82*7304104dSAndroid Build Coastguard Worker   } ehdr;
83*7304104dSAndroid Build Coastguard Worker   union
84*7304104dSAndroid Build Coastguard Worker   {
85*7304104dSAndroid Build Coastguard Worker     Elf32_Ehdr e32;
86*7304104dSAndroid Build Coastguard Worker     Elf64_Ehdr e64;
87*7304104dSAndroid Build Coastguard Worker   } ehdr_mem;
88*7304104dSAndroid Build Coastguard Worker   bool is32 = e_ident[EI_CLASS] == ELFCLASS32;
89*7304104dSAndroid Build Coastguard Worker 
90*7304104dSAndroid Build Coastguard Worker   if ((is32 && maxsize < sizeof (Elf32_Ehdr))
91*7304104dSAndroid Build Coastguard Worker       || (!is32 && maxsize < sizeof (Elf64_Ehdr)))
92*7304104dSAndroid Build Coastguard Worker     {
93*7304104dSAndroid Build Coastguard Worker        __libelf_seterrno (ELF_E_INVALID_ELF);
94*7304104dSAndroid Build Coastguard Worker       return (size_t) -1l;
95*7304104dSAndroid Build Coastguard Worker     }
96*7304104dSAndroid Build Coastguard Worker 
97*7304104dSAndroid Build Coastguard Worker   /* Make the ELF header available.  */
98*7304104dSAndroid Build Coastguard Worker   if (e_ident[EI_DATA] == MY_ELFDATA
99*7304104dSAndroid Build Coastguard Worker       && (ALLOW_UNALIGNED
100*7304104dSAndroid Build Coastguard Worker 	  || (((size_t) e_ident
101*7304104dSAndroid Build Coastguard Worker 	       & ((is32 ? __alignof__ (Elf32_Ehdr) : __alignof__ (Elf64_Ehdr))
102*7304104dSAndroid Build Coastguard Worker 		  - 1)) == 0)))
103*7304104dSAndroid Build Coastguard Worker     ehdr.p = e_ident;
104*7304104dSAndroid Build Coastguard Worker   else
105*7304104dSAndroid Build Coastguard Worker     {
106*7304104dSAndroid Build Coastguard Worker       /* We already read the ELF header.  We have to copy the header
107*7304104dSAndroid Build Coastguard Worker 	 since we possibly modify the data here and the caller
108*7304104dSAndroid Build Coastguard Worker 	 expects the memory it passes in to be preserved.  */
109*7304104dSAndroid Build Coastguard Worker       ehdr.p = &ehdr_mem;
110*7304104dSAndroid Build Coastguard Worker 
111*7304104dSAndroid Build Coastguard Worker       if (is32)
112*7304104dSAndroid Build Coastguard Worker 	{
113*7304104dSAndroid Build Coastguard Worker 	  if (ALLOW_UNALIGNED)
114*7304104dSAndroid Build Coastguard Worker 	    {
115*7304104dSAndroid Build Coastguard Worker 	      ehdr_mem.e32.e_shnum = ((Elf32_Ehdr *) e_ident)->e_shnum;
116*7304104dSAndroid Build Coastguard Worker 	      ehdr_mem.e32.e_shoff = ((Elf32_Ehdr *) e_ident)->e_shoff;
117*7304104dSAndroid Build Coastguard Worker 	    }
118*7304104dSAndroid Build Coastguard Worker 	  else
119*7304104dSAndroid Build Coastguard Worker 	    memcpy (&ehdr_mem, e_ident, sizeof (Elf32_Ehdr));
120*7304104dSAndroid Build Coastguard Worker 
121*7304104dSAndroid Build Coastguard Worker 	  if (e_ident[EI_DATA] != MY_ELFDATA)
122*7304104dSAndroid Build Coastguard Worker 	    {
123*7304104dSAndroid Build Coastguard Worker 	      CONVERT (ehdr_mem.e32.e_shnum);
124*7304104dSAndroid Build Coastguard Worker 	      CONVERT (ehdr_mem.e32.e_shoff);
125*7304104dSAndroid Build Coastguard Worker 	    }
126*7304104dSAndroid Build Coastguard Worker 	}
127*7304104dSAndroid Build Coastguard Worker       else
128*7304104dSAndroid Build Coastguard Worker 	{
129*7304104dSAndroid Build Coastguard Worker 	  if (ALLOW_UNALIGNED)
130*7304104dSAndroid Build Coastguard Worker 	    {
131*7304104dSAndroid Build Coastguard Worker 	      ehdr_mem.e64.e_shnum = ((Elf64_Ehdr *) e_ident)->e_shnum;
132*7304104dSAndroid Build Coastguard Worker 	      ehdr_mem.e64.e_shoff = ((Elf64_Ehdr *) e_ident)->e_shoff;
133*7304104dSAndroid Build Coastguard Worker 	    }
134*7304104dSAndroid Build Coastguard Worker 	  else
135*7304104dSAndroid Build Coastguard Worker 	    memcpy (&ehdr_mem, e_ident, sizeof (Elf64_Ehdr));
136*7304104dSAndroid Build Coastguard Worker 
137*7304104dSAndroid Build Coastguard Worker 	  if (e_ident[EI_DATA] != MY_ELFDATA)
138*7304104dSAndroid Build Coastguard Worker 	    {
139*7304104dSAndroid Build Coastguard Worker 	      CONVERT (ehdr_mem.e64.e_shnum);
140*7304104dSAndroid Build Coastguard Worker 	      CONVERT (ehdr_mem.e64.e_shoff);
141*7304104dSAndroid Build Coastguard Worker 	    }
142*7304104dSAndroid Build Coastguard Worker 	}
143*7304104dSAndroid Build Coastguard Worker     }
144*7304104dSAndroid Build Coastguard Worker 
145*7304104dSAndroid Build Coastguard Worker   if (is32)
146*7304104dSAndroid Build Coastguard Worker     {
147*7304104dSAndroid Build Coastguard Worker       /* Get the number of sections from the ELF header.  */
148*7304104dSAndroid Build Coastguard Worker       result = ehdr.e32->e_shnum;
149*7304104dSAndroid Build Coastguard Worker 
150*7304104dSAndroid Build Coastguard Worker       if (unlikely (result == 0) && ehdr.e32->e_shoff != 0)
151*7304104dSAndroid Build Coastguard Worker 	{
152*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (ehdr.e32->e_shoff >= maxsize)
153*7304104dSAndroid Build Coastguard Worker 	      || unlikely (maxsize - ehdr.e32->e_shoff < sizeof (Elf32_Shdr)))
154*7304104dSAndroid Build Coastguard Worker 	    /* Cannot read the first section header.  */
155*7304104dSAndroid Build Coastguard Worker 	    return 0;
156*7304104dSAndroid Build Coastguard Worker 
157*7304104dSAndroid Build Coastguard Worker 	  if (likely (map_address != NULL) && e_ident[EI_DATA] == MY_ELFDATA
158*7304104dSAndroid Build Coastguard Worker 	      && (ALLOW_UNALIGNED
159*7304104dSAndroid Build Coastguard Worker 		  || (((size_t) ((char *) (map_address + ehdr.e32->e_shoff
160*7304104dSAndroid Build Coastguard Worker 					   + offset)))
161*7304104dSAndroid Build Coastguard Worker 		      & (__alignof__ (Elf32_Shdr) - 1)) == 0))
162*7304104dSAndroid Build Coastguard Worker 	    /* We can directly access the memory.  */
163*7304104dSAndroid Build Coastguard Worker 	    result = ((Elf32_Shdr *) ((char *) map_address + ehdr.e32->e_shoff
164*7304104dSAndroid Build Coastguard Worker 				      + offset))->sh_size;
165*7304104dSAndroid Build Coastguard Worker 	  else
166*7304104dSAndroid Build Coastguard Worker 	    {
167*7304104dSAndroid Build Coastguard Worker 	      Elf32_Word size;
168*7304104dSAndroid Build Coastguard Worker 	      ssize_t r;
169*7304104dSAndroid Build Coastguard Worker 
170*7304104dSAndroid Build Coastguard Worker 	      if (likely (map_address != NULL))
171*7304104dSAndroid Build Coastguard Worker 		/* gcc will optimize the memcpy to a simple memory
172*7304104dSAndroid Build Coastguard Worker 		   access while taking care of alignment issues.  */
173*7304104dSAndroid Build Coastguard Worker 		memcpy (&size, ((char *) map_address
174*7304104dSAndroid Build Coastguard Worker 					 + ehdr.e32->e_shoff
175*7304104dSAndroid Build Coastguard Worker 					 + offset
176*7304104dSAndroid Build Coastguard Worker 					 + offsetof (Elf32_Shdr, sh_size)),
177*7304104dSAndroid Build Coastguard Worker 			sizeof (Elf32_Word));
178*7304104dSAndroid Build Coastguard Worker 	      else
179*7304104dSAndroid Build Coastguard Worker 		if (unlikely ((r = pread_retry (fildes, &size,
180*7304104dSAndroid Build Coastguard Worker 						sizeof (Elf32_Word),
181*7304104dSAndroid Build Coastguard Worker 						offset + ehdr.e32->e_shoff
182*7304104dSAndroid Build Coastguard Worker 						+ offsetof (Elf32_Shdr,
183*7304104dSAndroid Build Coastguard Worker 							    sh_size)))
184*7304104dSAndroid Build Coastguard Worker 			      != sizeof (Elf32_Word)))
185*7304104dSAndroid Build Coastguard Worker 		  {
186*7304104dSAndroid Build Coastguard Worker 		    if (r < 0)
187*7304104dSAndroid Build Coastguard Worker 		      __libelf_seterrno (ELF_E_INVALID_FILE);
188*7304104dSAndroid Build Coastguard Worker 		    else
189*7304104dSAndroid Build Coastguard Worker 		      __libelf_seterrno (ELF_E_INVALID_ELF);
190*7304104dSAndroid Build Coastguard Worker 		    return (size_t) -1l;
191*7304104dSAndroid Build Coastguard Worker 		  }
192*7304104dSAndroid Build Coastguard Worker 
193*7304104dSAndroid Build Coastguard Worker 	      if (e_ident[EI_DATA] != MY_ELFDATA)
194*7304104dSAndroid Build Coastguard Worker 		CONVERT (size);
195*7304104dSAndroid Build Coastguard Worker 
196*7304104dSAndroid Build Coastguard Worker 	      result = size;
197*7304104dSAndroid Build Coastguard Worker 	    }
198*7304104dSAndroid Build Coastguard Worker 	}
199*7304104dSAndroid Build Coastguard Worker 
200*7304104dSAndroid Build Coastguard Worker       /* If the section headers were truncated, pretend none were there.  */
201*7304104dSAndroid Build Coastguard Worker       if (ehdr.e32->e_shoff > maxsize
202*7304104dSAndroid Build Coastguard Worker 	  || maxsize - ehdr.e32->e_shoff < sizeof (Elf32_Shdr) * result)
203*7304104dSAndroid Build Coastguard Worker 	result = 0;
204*7304104dSAndroid Build Coastguard Worker     }
205*7304104dSAndroid Build Coastguard Worker   else
206*7304104dSAndroid Build Coastguard Worker     {
207*7304104dSAndroid Build Coastguard Worker       /* Get the number of sections from the ELF header.  */
208*7304104dSAndroid Build Coastguard Worker       result = ehdr.e64->e_shnum;
209*7304104dSAndroid Build Coastguard Worker 
210*7304104dSAndroid Build Coastguard Worker       if (unlikely (result == 0) && ehdr.e64->e_shoff != 0)
211*7304104dSAndroid Build Coastguard Worker 	{
212*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (ehdr.e64->e_shoff >= maxsize)
213*7304104dSAndroid Build Coastguard Worker 	      || unlikely (ehdr.e64->e_shoff + sizeof (Elf64_Shdr) > maxsize))
214*7304104dSAndroid Build Coastguard Worker 	    /* Cannot read the first section header.  */
215*7304104dSAndroid Build Coastguard Worker 	    return 0;
216*7304104dSAndroid Build Coastguard Worker 
217*7304104dSAndroid Build Coastguard Worker 	  Elf64_Xword size;
218*7304104dSAndroid Build Coastguard Worker 	  if (likely (map_address != NULL) && e_ident[EI_DATA] == MY_ELFDATA
219*7304104dSAndroid Build Coastguard Worker 	      && (ALLOW_UNALIGNED
220*7304104dSAndroid Build Coastguard Worker 		  || (((size_t) ((char *) (map_address + ehdr.e64->e_shoff
221*7304104dSAndroid Build Coastguard Worker 					   + offset)))
222*7304104dSAndroid Build Coastguard Worker 		      & (__alignof__ (Elf64_Shdr) - 1)) == 0))
223*7304104dSAndroid Build Coastguard Worker 	    /* We can directly access the memory.  */
224*7304104dSAndroid Build Coastguard Worker 	    size = ((Elf64_Shdr *) ((char *) map_address + ehdr.e64->e_shoff
225*7304104dSAndroid Build Coastguard Worker 				    + offset))->sh_size;
226*7304104dSAndroid Build Coastguard Worker 	  else
227*7304104dSAndroid Build Coastguard Worker 	    {
228*7304104dSAndroid Build Coastguard Worker 	      ssize_t r;
229*7304104dSAndroid Build Coastguard Worker 	      if (likely (map_address != NULL))
230*7304104dSAndroid Build Coastguard Worker 		/* gcc will optimize the memcpy to a simple memory
231*7304104dSAndroid Build Coastguard Worker 		   access while taking care of alignment issues.  */
232*7304104dSAndroid Build Coastguard Worker 		memcpy (&size, ((char *) map_address
233*7304104dSAndroid Build Coastguard Worker 					 + ehdr.e64->e_shoff
234*7304104dSAndroid Build Coastguard Worker 					 + offset
235*7304104dSAndroid Build Coastguard Worker 					 + offsetof (Elf64_Shdr, sh_size)),
236*7304104dSAndroid Build Coastguard Worker 			sizeof (Elf64_Xword));
237*7304104dSAndroid Build Coastguard Worker 	      else
238*7304104dSAndroid Build Coastguard Worker 		if (unlikely ((r = pread_retry (fildes, &size,
239*7304104dSAndroid Build Coastguard Worker 						sizeof (Elf64_Xword),
240*7304104dSAndroid Build Coastguard Worker 						offset + ehdr.e64->e_shoff
241*7304104dSAndroid Build Coastguard Worker 						+ offsetof (Elf64_Shdr,
242*7304104dSAndroid Build Coastguard Worker 							    sh_size)))
243*7304104dSAndroid Build Coastguard Worker 			      != sizeof (Elf64_Xword)))
244*7304104dSAndroid Build Coastguard Worker 		  {
245*7304104dSAndroid Build Coastguard Worker 		    if (r < 0)
246*7304104dSAndroid Build Coastguard Worker 		      __libelf_seterrno (ELF_E_INVALID_FILE);
247*7304104dSAndroid Build Coastguard Worker 		    else
248*7304104dSAndroid Build Coastguard Worker 		      __libelf_seterrno (ELF_E_INVALID_ELF);
249*7304104dSAndroid Build Coastguard Worker 		    return (size_t) -1l;
250*7304104dSAndroid Build Coastguard Worker 		  }
251*7304104dSAndroid Build Coastguard Worker 
252*7304104dSAndroid Build Coastguard Worker 	      if (e_ident[EI_DATA] != MY_ELFDATA)
253*7304104dSAndroid Build Coastguard Worker 		CONVERT (size);
254*7304104dSAndroid Build Coastguard Worker 	    }
255*7304104dSAndroid Build Coastguard Worker 
256*7304104dSAndroid Build Coastguard Worker 	  /* Although sh_size is an Elf64_Xword and can contain a 64bit
257*7304104dSAndroid Build Coastguard Worker 	     value, we only expect an 32bit value max.  GElf_Word is
258*7304104dSAndroid Build Coastguard Worker 	     32bit unsigned.  */
259*7304104dSAndroid Build Coastguard Worker 	  if (size > ~((GElf_Word) 0))
260*7304104dSAndroid Build Coastguard Worker 	    {
261*7304104dSAndroid Build Coastguard Worker 	      /* Invalid value, it is too large.  */
262*7304104dSAndroid Build Coastguard Worker 	      __libelf_seterrno (ELF_E_INVALID_ELF);
263*7304104dSAndroid Build Coastguard Worker 	      return (size_t) -1l;
264*7304104dSAndroid Build Coastguard Worker 	    }
265*7304104dSAndroid Build Coastguard Worker 
266*7304104dSAndroid Build Coastguard Worker 	  result = size;
267*7304104dSAndroid Build Coastguard Worker 	}
268*7304104dSAndroid Build Coastguard Worker 
269*7304104dSAndroid Build Coastguard Worker       /* If the section headers were truncated, pretend none were there.  */
270*7304104dSAndroid Build Coastguard Worker       if (ehdr.e64->e_shoff > maxsize
271*7304104dSAndroid Build Coastguard Worker 	  || maxsize - ehdr.e64->e_shoff < sizeof (Elf64_Shdr) * result)
272*7304104dSAndroid Build Coastguard Worker 	result = 0;
273*7304104dSAndroid Build Coastguard Worker     }
274*7304104dSAndroid Build Coastguard Worker 
275*7304104dSAndroid Build Coastguard Worker   return result;
276*7304104dSAndroid Build Coastguard Worker }
277*7304104dSAndroid Build Coastguard Worker 
278*7304104dSAndroid Build Coastguard Worker 
279*7304104dSAndroid Build Coastguard Worker /* Create descriptor for ELF file in memory.  */
280*7304104dSAndroid Build Coastguard Worker static Elf *
file_read_elf(int fildes,void * map_address,unsigned char * e_ident,int64_t offset,size_t maxsize,Elf_Cmd cmd,Elf * parent)281*7304104dSAndroid Build Coastguard Worker file_read_elf (int fildes, void *map_address, unsigned char *e_ident,
282*7304104dSAndroid Build Coastguard Worker 	       int64_t offset, size_t maxsize, Elf_Cmd cmd, Elf *parent)
283*7304104dSAndroid Build Coastguard Worker {
284*7304104dSAndroid Build Coastguard Worker   /* Verify the binary is of the class we can handle.  */
285*7304104dSAndroid Build Coastguard Worker   if (unlikely ((e_ident[EI_CLASS] != ELFCLASS32
286*7304104dSAndroid Build Coastguard Worker 		 && e_ident[EI_CLASS] != ELFCLASS64)
287*7304104dSAndroid Build Coastguard Worker 		/* We also can only handle two encodings.  */
288*7304104dSAndroid Build Coastguard Worker 		|| (e_ident[EI_DATA] != ELFDATA2LSB
289*7304104dSAndroid Build Coastguard Worker 		    && e_ident[EI_DATA] != ELFDATA2MSB)))
290*7304104dSAndroid Build Coastguard Worker     {
291*7304104dSAndroid Build Coastguard Worker       /* Cannot handle this.  */
292*7304104dSAndroid Build Coastguard Worker       __libelf_seterrno (ELF_E_INVALID_ELF);
293*7304104dSAndroid Build Coastguard Worker       return NULL;
294*7304104dSAndroid Build Coastguard Worker     }
295*7304104dSAndroid Build Coastguard Worker 
296*7304104dSAndroid Build Coastguard Worker   /* Determine the number of sections.  Returns -1 and sets libelf errno
297*7304104dSAndroid Build Coastguard Worker      if the file handle or elf file is invalid.  Returns zero if there
298*7304104dSAndroid Build Coastguard Worker      are no section headers (or they cannot be read).  */
299*7304104dSAndroid Build Coastguard Worker   size_t scncnt = get_shnum (map_address, e_ident, fildes, offset, maxsize);
300*7304104dSAndroid Build Coastguard Worker   if (scncnt == (size_t) -1l)
301*7304104dSAndroid Build Coastguard Worker     /* Could not determine the number of sections.  */
302*7304104dSAndroid Build Coastguard Worker     return NULL;
303*7304104dSAndroid Build Coastguard Worker 
304*7304104dSAndroid Build Coastguard Worker   /* Check for too many sections.  */
305*7304104dSAndroid Build Coastguard Worker   if (e_ident[EI_CLASS] == ELFCLASS32)
306*7304104dSAndroid Build Coastguard Worker     {
307*7304104dSAndroid Build Coastguard Worker       if (scncnt > SIZE_MAX / (sizeof (Elf_Scn) + sizeof (Elf32_Shdr)))
308*7304104dSAndroid Build Coastguard Worker 	{
309*7304104dSAndroid Build Coastguard Worker 	  __libelf_seterrno (ELF_E_INVALID_ELF);
310*7304104dSAndroid Build Coastguard Worker 	  return NULL;
311*7304104dSAndroid Build Coastguard Worker 	}
312*7304104dSAndroid Build Coastguard Worker     }
313*7304104dSAndroid Build Coastguard Worker   else if (scncnt > SIZE_MAX / (sizeof (Elf_Scn) + sizeof (Elf64_Shdr)))
314*7304104dSAndroid Build Coastguard Worker     {
315*7304104dSAndroid Build Coastguard Worker       __libelf_seterrno (ELF_E_INVALID_ELF);
316*7304104dSAndroid Build Coastguard Worker       return NULL;
317*7304104dSAndroid Build Coastguard Worker     }
318*7304104dSAndroid Build Coastguard Worker 
319*7304104dSAndroid Build Coastguard Worker   /* We can now allocate the memory.  Even if there are no section headers,
320*7304104dSAndroid Build Coastguard Worker      we allocate space for a zeroth section in case we need it later.  */
321*7304104dSAndroid Build Coastguard Worker   const size_t scnmax = (scncnt ?: (cmd == ELF_C_RDWR || cmd == ELF_C_RDWR_MMAP)
322*7304104dSAndroid Build Coastguard Worker 			 ? 1 : 0);
323*7304104dSAndroid Build Coastguard Worker   Elf *elf = allocate_elf (fildes, map_address, offset, maxsize, cmd, parent,
324*7304104dSAndroid Build Coastguard Worker 			   ELF_K_ELF, scnmax * sizeof (Elf_Scn));
325*7304104dSAndroid Build Coastguard Worker   if (elf == NULL)
326*7304104dSAndroid Build Coastguard Worker     /* Not enough memory.  allocate_elf will have set libelf errno.  */
327*7304104dSAndroid Build Coastguard Worker     return NULL;
328*7304104dSAndroid Build Coastguard Worker 
329*7304104dSAndroid Build Coastguard Worker   assert ((unsigned int) scncnt == scncnt);
330*7304104dSAndroid Build Coastguard Worker   assert (offsetof (struct Elf, state.elf32.scns)
331*7304104dSAndroid Build Coastguard Worker 	  == offsetof (struct Elf, state.elf64.scns));
332*7304104dSAndroid Build Coastguard Worker   elf->state.elf32.scns.cnt = scncnt;
333*7304104dSAndroid Build Coastguard Worker   elf->state.elf32.scns.max = scnmax;
334*7304104dSAndroid Build Coastguard Worker 
335*7304104dSAndroid Build Coastguard Worker   /* Some more or less arbitrary value.  */
336*7304104dSAndroid Build Coastguard Worker   elf->state.elf.scnincr = 10;
337*7304104dSAndroid Build Coastguard Worker 
338*7304104dSAndroid Build Coastguard Worker   /* Make the class easily available.  */
339*7304104dSAndroid Build Coastguard Worker   elf->class = e_ident[EI_CLASS];
340*7304104dSAndroid Build Coastguard Worker 
341*7304104dSAndroid Build Coastguard Worker   if (e_ident[EI_CLASS] == ELFCLASS32)
342*7304104dSAndroid Build Coastguard Worker     {
343*7304104dSAndroid Build Coastguard Worker       /* This pointer might not be directly usable if the alignment is
344*7304104dSAndroid Build Coastguard Worker 	 not sufficient for the architecture.  */
345*7304104dSAndroid Build Coastguard Worker       uintptr_t ehdr = (uintptr_t) map_address + offset;
346*7304104dSAndroid Build Coastguard Worker 
347*7304104dSAndroid Build Coastguard Worker       /* This is a 32-bit binary.  */
348*7304104dSAndroid Build Coastguard Worker       if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
349*7304104dSAndroid Build Coastguard Worker 	  && (ALLOW_UNALIGNED
350*7304104dSAndroid Build Coastguard Worker 	      || (ehdr & (__alignof__ (Elf32_Ehdr) - 1)) == 0))
351*7304104dSAndroid Build Coastguard Worker 	{
352*7304104dSAndroid Build Coastguard Worker 	  /* We can use the mmapped memory.  */
353*7304104dSAndroid Build Coastguard Worker 	  elf->state.elf32.ehdr = (Elf32_Ehdr *) ehdr;
354*7304104dSAndroid Build Coastguard Worker 	}
355*7304104dSAndroid Build Coastguard Worker       else
356*7304104dSAndroid Build Coastguard Worker 	{
357*7304104dSAndroid Build Coastguard Worker 	  /* Copy the ELF header.  */
358*7304104dSAndroid Build Coastguard Worker 	  elf->state.elf32.ehdr = memcpy (&elf->state.elf32.ehdr_mem, e_ident,
359*7304104dSAndroid Build Coastguard Worker 					  sizeof (Elf32_Ehdr));
360*7304104dSAndroid Build Coastguard Worker 
361*7304104dSAndroid Build Coastguard Worker 	  if (e_ident[EI_DATA] != MY_ELFDATA)
362*7304104dSAndroid Build Coastguard Worker 	    {
363*7304104dSAndroid Build Coastguard Worker 	      CONVERT (elf->state.elf32.ehdr_mem.e_type);
364*7304104dSAndroid Build Coastguard Worker 	      CONVERT (elf->state.elf32.ehdr_mem.e_machine);
365*7304104dSAndroid Build Coastguard Worker 	      CONVERT (elf->state.elf32.ehdr_mem.e_version);
366*7304104dSAndroid Build Coastguard Worker 	      CONVERT (elf->state.elf32.ehdr_mem.e_entry);
367*7304104dSAndroid Build Coastguard Worker 	      CONVERT (elf->state.elf32.ehdr_mem.e_phoff);
368*7304104dSAndroid Build Coastguard Worker 	      CONVERT (elf->state.elf32.ehdr_mem.e_shoff);
369*7304104dSAndroid Build Coastguard Worker 	      CONVERT (elf->state.elf32.ehdr_mem.e_flags);
370*7304104dSAndroid Build Coastguard Worker 	      CONVERT (elf->state.elf32.ehdr_mem.e_ehsize);
371*7304104dSAndroid Build Coastguard Worker 	      CONVERT (elf->state.elf32.ehdr_mem.e_phentsize);
372*7304104dSAndroid Build Coastguard Worker 	      CONVERT (elf->state.elf32.ehdr_mem.e_phnum);
373*7304104dSAndroid Build Coastguard Worker 	      CONVERT (elf->state.elf32.ehdr_mem.e_shentsize);
374*7304104dSAndroid Build Coastguard Worker 	      CONVERT (elf->state.elf32.ehdr_mem.e_shnum);
375*7304104dSAndroid Build Coastguard Worker 	      CONVERT (elf->state.elf32.ehdr_mem.e_shstrndx);
376*7304104dSAndroid Build Coastguard Worker 	    }
377*7304104dSAndroid Build Coastguard Worker 	}
378*7304104dSAndroid Build Coastguard Worker 
379*7304104dSAndroid Build Coastguard Worker       /* Don't precache the phdr pointer here.
380*7304104dSAndroid Build Coastguard Worker 	 elf32_getphdr will validate it against the size when asked.  */
381*7304104dSAndroid Build Coastguard Worker 
382*7304104dSAndroid Build Coastguard Worker       Elf32_Off e_shoff = elf->state.elf32.ehdr->e_shoff;
383*7304104dSAndroid Build Coastguard Worker       if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
384*7304104dSAndroid Build Coastguard Worker 	  && cmd != ELF_C_READ_MMAP /* We need a copy to be able to write.  */
385*7304104dSAndroid Build Coastguard Worker 	  && (ALLOW_UNALIGNED
386*7304104dSAndroid Build Coastguard Worker 	      || (((ehdr + e_shoff) & (__alignof__ (Elf32_Shdr) - 1)) == 0)))
387*7304104dSAndroid Build Coastguard Worker 	{
388*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (scncnt > 0 && e_shoff >= maxsize)
389*7304104dSAndroid Build Coastguard Worker 	      || unlikely (maxsize - e_shoff
390*7304104dSAndroid Build Coastguard Worker 			   < scncnt * sizeof (Elf32_Shdr)))
391*7304104dSAndroid Build Coastguard Worker 	    {
392*7304104dSAndroid Build Coastguard Worker 	    free_and_out:
393*7304104dSAndroid Build Coastguard Worker 	      free (elf);
394*7304104dSAndroid Build Coastguard Worker 	      __libelf_seterrno (ELF_E_INVALID_ELF);
395*7304104dSAndroid Build Coastguard Worker 	      return NULL;
396*7304104dSAndroid Build Coastguard Worker 	    }
397*7304104dSAndroid Build Coastguard Worker 
398*7304104dSAndroid Build Coastguard Worker 	  if (scncnt > 0)
399*7304104dSAndroid Build Coastguard Worker 	    elf->state.elf32.shdr = (Elf32_Shdr *) (ehdr + e_shoff);
400*7304104dSAndroid Build Coastguard Worker 
401*7304104dSAndroid Build Coastguard Worker 	  for (size_t cnt = 0; cnt < scncnt; ++cnt)
402*7304104dSAndroid Build Coastguard Worker 	    {
403*7304104dSAndroid Build Coastguard Worker 	      elf->state.elf32.scns.data[cnt].index = cnt;
404*7304104dSAndroid Build Coastguard Worker 	      elf->state.elf32.scns.data[cnt].elf = elf;
405*7304104dSAndroid Build Coastguard Worker 	      elf->state.elf32.scns.data[cnt].shdr.e32 =
406*7304104dSAndroid Build Coastguard Worker 		&elf->state.elf32.shdr[cnt];
407*7304104dSAndroid Build Coastguard Worker 	      if (likely (elf->state.elf32.shdr[cnt].sh_offset < maxsize)
408*7304104dSAndroid Build Coastguard Worker 		  && likely (elf->state.elf32.shdr[cnt].sh_size
409*7304104dSAndroid Build Coastguard Worker 			     <= maxsize - elf->state.elf32.shdr[cnt].sh_offset))
410*7304104dSAndroid Build Coastguard Worker 		elf->state.elf32.scns.data[cnt].rawdata_base =
411*7304104dSAndroid Build Coastguard Worker 		  elf->state.elf32.scns.data[cnt].data_base =
412*7304104dSAndroid Build Coastguard Worker 		  ((char *) map_address + offset
413*7304104dSAndroid Build Coastguard Worker 		   + elf->state.elf32.shdr[cnt].sh_offset);
414*7304104dSAndroid Build Coastguard Worker 	      elf->state.elf32.scns.data[cnt].list = &elf->state.elf32.scns;
415*7304104dSAndroid Build Coastguard Worker 
416*7304104dSAndroid Build Coastguard Worker 	      /* If this is a section with an extended index add a
417*7304104dSAndroid Build Coastguard Worker 		 reference in the section which uses the extended
418*7304104dSAndroid Build Coastguard Worker 		 index.  */
419*7304104dSAndroid Build Coastguard Worker 	      if (elf->state.elf32.shdr[cnt].sh_type == SHT_SYMTAB_SHNDX
420*7304104dSAndroid Build Coastguard Worker 		  && elf->state.elf32.shdr[cnt].sh_link < scncnt)
421*7304104dSAndroid Build Coastguard Worker 		elf->state.elf32.scns.data[elf->state.elf32.shdr[cnt].sh_link].shndx_index
422*7304104dSAndroid Build Coastguard Worker 		  = cnt;
423*7304104dSAndroid Build Coastguard Worker 
424*7304104dSAndroid Build Coastguard Worker 	      /* Set the own shndx_index field in case it has not yet
425*7304104dSAndroid Build Coastguard Worker 		 been set.  */
426*7304104dSAndroid Build Coastguard Worker 	      if (elf->state.elf32.scns.data[cnt].shndx_index == 0)
427*7304104dSAndroid Build Coastguard Worker 		elf->state.elf32.scns.data[cnt].shndx_index = -1;
428*7304104dSAndroid Build Coastguard Worker 	    }
429*7304104dSAndroid Build Coastguard Worker 	}
430*7304104dSAndroid Build Coastguard Worker       else
431*7304104dSAndroid Build Coastguard Worker 	{
432*7304104dSAndroid Build Coastguard Worker 	  for (size_t cnt = 0; cnt < scncnt; ++cnt)
433*7304104dSAndroid Build Coastguard Worker 	    {
434*7304104dSAndroid Build Coastguard Worker 	      elf->state.elf32.scns.data[cnt].index = cnt;
435*7304104dSAndroid Build Coastguard Worker 	      elf->state.elf32.scns.data[cnt].elf = elf;
436*7304104dSAndroid Build Coastguard Worker 	      elf->state.elf32.scns.data[cnt].list = &elf->state.elf32.scns;
437*7304104dSAndroid Build Coastguard Worker 	    }
438*7304104dSAndroid Build Coastguard Worker 	}
439*7304104dSAndroid Build Coastguard Worker 
440*7304104dSAndroid Build Coastguard Worker       /* So far only one block with sections.  */
441*7304104dSAndroid Build Coastguard Worker       elf->state.elf32.scns_last = &elf->state.elf32.scns;
442*7304104dSAndroid Build Coastguard Worker     }
443*7304104dSAndroid Build Coastguard Worker   else
444*7304104dSAndroid Build Coastguard Worker     {
445*7304104dSAndroid Build Coastguard Worker       /* This pointer might not be directly usable if the alignment is
446*7304104dSAndroid Build Coastguard Worker 	 not sufficient for the architecture.  */
447*7304104dSAndroid Build Coastguard Worker       uintptr_t ehdr = (uintptr_t) map_address + offset;
448*7304104dSAndroid Build Coastguard Worker 
449*7304104dSAndroid Build Coastguard Worker       /* This is a 64-bit binary.  */
450*7304104dSAndroid Build Coastguard Worker       if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
451*7304104dSAndroid Build Coastguard Worker 	  && (ALLOW_UNALIGNED
452*7304104dSAndroid Build Coastguard Worker 	      || (ehdr & (__alignof__ (Elf64_Ehdr) - 1)) == 0))
453*7304104dSAndroid Build Coastguard Worker 	{
454*7304104dSAndroid Build Coastguard Worker 	  /* We can use the mmapped memory.  */
455*7304104dSAndroid Build Coastguard Worker 	  elf->state.elf64.ehdr = (Elf64_Ehdr *) ehdr;
456*7304104dSAndroid Build Coastguard Worker 	}
457*7304104dSAndroid Build Coastguard Worker       else
458*7304104dSAndroid Build Coastguard Worker 	{
459*7304104dSAndroid Build Coastguard Worker 	  /* Copy the ELF header.  */
460*7304104dSAndroid Build Coastguard Worker 	  elf->state.elf64.ehdr = memcpy (&elf->state.elf64.ehdr_mem, e_ident,
461*7304104dSAndroid Build Coastguard Worker 					  sizeof (Elf64_Ehdr));
462*7304104dSAndroid Build Coastguard Worker 
463*7304104dSAndroid Build Coastguard Worker 	  if (e_ident[EI_DATA] != MY_ELFDATA)
464*7304104dSAndroid Build Coastguard Worker 	    {
465*7304104dSAndroid Build Coastguard Worker 	      CONVERT (elf->state.elf64.ehdr_mem.e_type);
466*7304104dSAndroid Build Coastguard Worker 	      CONVERT (elf->state.elf64.ehdr_mem.e_machine);
467*7304104dSAndroid Build Coastguard Worker 	      CONVERT (elf->state.elf64.ehdr_mem.e_version);
468*7304104dSAndroid Build Coastguard Worker 	      CONVERT (elf->state.elf64.ehdr_mem.e_entry);
469*7304104dSAndroid Build Coastguard Worker 	      CONVERT (elf->state.elf64.ehdr_mem.e_phoff);
470*7304104dSAndroid Build Coastguard Worker 	      CONVERT (elf->state.elf64.ehdr_mem.e_shoff);
471*7304104dSAndroid Build Coastguard Worker 	      CONVERT (elf->state.elf64.ehdr_mem.e_flags);
472*7304104dSAndroid Build Coastguard Worker 	      CONVERT (elf->state.elf64.ehdr_mem.e_ehsize);
473*7304104dSAndroid Build Coastguard Worker 	      CONVERT (elf->state.elf64.ehdr_mem.e_phentsize);
474*7304104dSAndroid Build Coastguard Worker 	      CONVERT (elf->state.elf64.ehdr_mem.e_phnum);
475*7304104dSAndroid Build Coastguard Worker 	      CONVERT (elf->state.elf64.ehdr_mem.e_shentsize);
476*7304104dSAndroid Build Coastguard Worker 	      CONVERT (elf->state.elf64.ehdr_mem.e_shnum);
477*7304104dSAndroid Build Coastguard Worker 	      CONVERT (elf->state.elf64.ehdr_mem.e_shstrndx);
478*7304104dSAndroid Build Coastguard Worker 	    }
479*7304104dSAndroid Build Coastguard Worker 	}
480*7304104dSAndroid Build Coastguard Worker 
481*7304104dSAndroid Build Coastguard Worker       /* Don't precache the phdr pointer here.
482*7304104dSAndroid Build Coastguard Worker 	 elf64_getphdr will validate it against the size when asked.  */
483*7304104dSAndroid Build Coastguard Worker 
484*7304104dSAndroid Build Coastguard Worker       Elf64_Off e_shoff = elf->state.elf64.ehdr->e_shoff;
485*7304104dSAndroid Build Coastguard Worker       if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
486*7304104dSAndroid Build Coastguard Worker 	  && cmd != ELF_C_READ_MMAP /* We need a copy to be able to write.  */
487*7304104dSAndroid Build Coastguard Worker 	  && (ALLOW_UNALIGNED
488*7304104dSAndroid Build Coastguard Worker 	      || (((ehdr + e_shoff) & (__alignof__ (Elf64_Shdr) - 1)) == 0)))
489*7304104dSAndroid Build Coastguard Worker 	{
490*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (scncnt > 0 && e_shoff >= maxsize)
491*7304104dSAndroid Build Coastguard Worker 	      || unlikely (maxsize - e_shoff
492*7304104dSAndroid Build Coastguard Worker 			   < scncnt * sizeof (Elf64_Shdr)))
493*7304104dSAndroid Build Coastguard Worker 	    goto free_and_out;
494*7304104dSAndroid Build Coastguard Worker 
495*7304104dSAndroid Build Coastguard Worker 	  if (scncnt > 0)
496*7304104dSAndroid Build Coastguard Worker 	    elf->state.elf64.shdr = (Elf64_Shdr *) (ehdr + (ptrdiff_t) e_shoff);
497*7304104dSAndroid Build Coastguard Worker 
498*7304104dSAndroid Build Coastguard Worker 	  for (size_t cnt = 0; cnt < scncnt; ++cnt)
499*7304104dSAndroid Build Coastguard Worker 	    {
500*7304104dSAndroid Build Coastguard Worker 	      elf->state.elf64.scns.data[cnt].index = cnt;
501*7304104dSAndroid Build Coastguard Worker 	      elf->state.elf64.scns.data[cnt].elf = elf;
502*7304104dSAndroid Build Coastguard Worker 	      elf->state.elf64.scns.data[cnt].shdr.e64 =
503*7304104dSAndroid Build Coastguard Worker 		&elf->state.elf64.shdr[cnt];
504*7304104dSAndroid Build Coastguard Worker 	      if (likely (elf->state.elf64.shdr[cnt].sh_offset < maxsize)
505*7304104dSAndroid Build Coastguard Worker 		  && likely (elf->state.elf64.shdr[cnt].sh_size
506*7304104dSAndroid Build Coastguard Worker 			     <= maxsize - elf->state.elf64.shdr[cnt].sh_offset))
507*7304104dSAndroid Build Coastguard Worker 		elf->state.elf64.scns.data[cnt].rawdata_base =
508*7304104dSAndroid Build Coastguard Worker 		  elf->state.elf64.scns.data[cnt].data_base =
509*7304104dSAndroid Build Coastguard Worker 		  ((char *) map_address + offset
510*7304104dSAndroid Build Coastguard Worker 		   + elf->state.elf64.shdr[cnt].sh_offset);
511*7304104dSAndroid Build Coastguard Worker 	      elf->state.elf64.scns.data[cnt].list = &elf->state.elf64.scns;
512*7304104dSAndroid Build Coastguard Worker 
513*7304104dSAndroid Build Coastguard Worker 	      /* If this is a section with an extended index add a
514*7304104dSAndroid Build Coastguard Worker 		 reference in the section which uses the extended
515*7304104dSAndroid Build Coastguard Worker 		 index.  */
516*7304104dSAndroid Build Coastguard Worker 	      if (elf->state.elf64.shdr[cnt].sh_type == SHT_SYMTAB_SHNDX
517*7304104dSAndroid Build Coastguard Worker 		  && elf->state.elf64.shdr[cnt].sh_link < scncnt)
518*7304104dSAndroid Build Coastguard Worker 		elf->state.elf64.scns.data[elf->state.elf64.shdr[cnt].sh_link].shndx_index
519*7304104dSAndroid Build Coastguard Worker 		  = cnt;
520*7304104dSAndroid Build Coastguard Worker 
521*7304104dSAndroid Build Coastguard Worker 	      /* Set the own shndx_index field in case it has not yet
522*7304104dSAndroid Build Coastguard Worker 		 been set.  */
523*7304104dSAndroid Build Coastguard Worker 	      if (elf->state.elf64.scns.data[cnt].shndx_index == 0)
524*7304104dSAndroid Build Coastguard Worker 		elf->state.elf64.scns.data[cnt].shndx_index = -1;
525*7304104dSAndroid Build Coastguard Worker 	    }
526*7304104dSAndroid Build Coastguard Worker 	}
527*7304104dSAndroid Build Coastguard Worker       else
528*7304104dSAndroid Build Coastguard Worker 	{
529*7304104dSAndroid Build Coastguard Worker 	  for (size_t cnt = 0; cnt < scncnt; ++cnt)
530*7304104dSAndroid Build Coastguard Worker 	    {
531*7304104dSAndroid Build Coastguard Worker 	      elf->state.elf64.scns.data[cnt].index = cnt;
532*7304104dSAndroid Build Coastguard Worker 	      elf->state.elf64.scns.data[cnt].elf = elf;
533*7304104dSAndroid Build Coastguard Worker 	      elf->state.elf64.scns.data[cnt].list = &elf->state.elf64.scns;
534*7304104dSAndroid Build Coastguard Worker 	    }
535*7304104dSAndroid Build Coastguard Worker 	}
536*7304104dSAndroid Build Coastguard Worker 
537*7304104dSAndroid Build Coastguard Worker       /* So far only one block with sections.  */
538*7304104dSAndroid Build Coastguard Worker       elf->state.elf64.scns_last = &elf->state.elf64.scns;
539*7304104dSAndroid Build Coastguard Worker     }
540*7304104dSAndroid Build Coastguard Worker 
541*7304104dSAndroid Build Coastguard Worker   return elf;
542*7304104dSAndroid Build Coastguard Worker }
543*7304104dSAndroid Build Coastguard Worker 
544*7304104dSAndroid Build Coastguard Worker 
545*7304104dSAndroid Build Coastguard Worker Elf *
546*7304104dSAndroid Build Coastguard Worker internal_function
__libelf_read_mmaped_file(int fildes,void * map_address,int64_t offset,size_t maxsize,Elf_Cmd cmd,Elf * parent)547*7304104dSAndroid Build Coastguard Worker __libelf_read_mmaped_file (int fildes, void *map_address,  int64_t offset,
548*7304104dSAndroid Build Coastguard Worker 			   size_t maxsize, Elf_Cmd cmd, Elf *parent)
549*7304104dSAndroid Build Coastguard Worker {
550*7304104dSAndroid Build Coastguard Worker   /* We have to find out what kind of file this is.  We handle ELF
551*7304104dSAndroid Build Coastguard Worker      files and archives.  To find out what we have we must look at the
552*7304104dSAndroid Build Coastguard Worker      header.  The header for an ELF file is EI_NIDENT bytes in size,
553*7304104dSAndroid Build Coastguard Worker      the header for an archive file SARMAG bytes long.  */
554*7304104dSAndroid Build Coastguard Worker   unsigned char *e_ident = (unsigned char *) map_address + offset;
555*7304104dSAndroid Build Coastguard Worker 
556*7304104dSAndroid Build Coastguard Worker   /* See what kind of object we have here.  */
557*7304104dSAndroid Build Coastguard Worker   Elf_Kind kind = determine_kind (e_ident, maxsize);
558*7304104dSAndroid Build Coastguard Worker 
559*7304104dSAndroid Build Coastguard Worker   switch (kind)
560*7304104dSAndroid Build Coastguard Worker     {
561*7304104dSAndroid Build Coastguard Worker     case ELF_K_ELF:
562*7304104dSAndroid Build Coastguard Worker       return file_read_elf (fildes, map_address, e_ident, offset, maxsize,
563*7304104dSAndroid Build Coastguard Worker 			    cmd, parent);
564*7304104dSAndroid Build Coastguard Worker 
565*7304104dSAndroid Build Coastguard Worker     case ELF_K_AR:
566*7304104dSAndroid Build Coastguard Worker       return file_read_ar (fildes, map_address, offset, maxsize, cmd, parent);
567*7304104dSAndroid Build Coastguard Worker 
568*7304104dSAndroid Build Coastguard Worker     default:
569*7304104dSAndroid Build Coastguard Worker       break;
570*7304104dSAndroid Build Coastguard Worker     }
571*7304104dSAndroid Build Coastguard Worker 
572*7304104dSAndroid Build Coastguard Worker   /* This case is easy.  Since we cannot do anything with this file
573*7304104dSAndroid Build Coastguard Worker      create a dummy descriptor.  */
574*7304104dSAndroid Build Coastguard Worker   return allocate_elf (fildes, map_address, offset, maxsize, cmd, parent,
575*7304104dSAndroid Build Coastguard Worker 		       ELF_K_NONE, 0);
576*7304104dSAndroid Build Coastguard Worker }
577*7304104dSAndroid Build Coastguard Worker 
578*7304104dSAndroid Build Coastguard Worker 
579*7304104dSAndroid Build Coastguard Worker static Elf *
read_unmmaped_file(int fildes,int64_t offset,size_t maxsize,Elf_Cmd cmd,Elf * parent)580*7304104dSAndroid Build Coastguard Worker read_unmmaped_file (int fildes, int64_t offset, size_t maxsize, Elf_Cmd cmd,
581*7304104dSAndroid Build Coastguard Worker 		    Elf *parent)
582*7304104dSAndroid Build Coastguard Worker {
583*7304104dSAndroid Build Coastguard Worker   /* We have to find out what kind of file this is.  We handle ELF
584*7304104dSAndroid Build Coastguard Worker      files and archives.  To find out what we have we must read the
585*7304104dSAndroid Build Coastguard Worker      header.  The identification header for an ELF file is EI_NIDENT
586*7304104dSAndroid Build Coastguard Worker      bytes in size, but we read the whole ELF header since we will
587*7304104dSAndroid Build Coastguard Worker      need it anyway later.  For archives the header in SARMAG bytes
588*7304104dSAndroid Build Coastguard Worker      long.  Read the maximum of these numbers.
589*7304104dSAndroid Build Coastguard Worker 
590*7304104dSAndroid Build Coastguard Worker      XXX We have to change this for the extended `ar' format some day.
591*7304104dSAndroid Build Coastguard Worker 
592*7304104dSAndroid Build Coastguard Worker      Use a union to ensure alignment.  We might later access the
593*7304104dSAndroid Build Coastguard Worker      memory as a ElfXX_Ehdr.  */
594*7304104dSAndroid Build Coastguard Worker   union
595*7304104dSAndroid Build Coastguard Worker   {
596*7304104dSAndroid Build Coastguard Worker     Elf64_Ehdr ehdr;
597*7304104dSAndroid Build Coastguard Worker     unsigned char header[MAX (sizeof (Elf64_Ehdr), SARMAG)];
598*7304104dSAndroid Build Coastguard Worker   } mem;
599*7304104dSAndroid Build Coastguard Worker 
600*7304104dSAndroid Build Coastguard Worker   /* Read the head of the file.  */
601*7304104dSAndroid Build Coastguard Worker   ssize_t nread = pread_retry (fildes, mem.header,
602*7304104dSAndroid Build Coastguard Worker 			       MIN (MAX (sizeof (Elf64_Ehdr), SARMAG),
603*7304104dSAndroid Build Coastguard Worker 				    maxsize),
604*7304104dSAndroid Build Coastguard Worker 			       offset);
605*7304104dSAndroid Build Coastguard Worker   if (unlikely (nread == -1))
606*7304104dSAndroid Build Coastguard Worker     {
607*7304104dSAndroid Build Coastguard Worker       /* We cannot even read the head of the file.  Maybe FILDES is associated
608*7304104dSAndroid Build Coastguard Worker 	 with an unseekable device.  This is nothing we can handle.  */
609*7304104dSAndroid Build Coastguard Worker       __libelf_seterrno (ELF_E_INVALID_FILE);
610*7304104dSAndroid Build Coastguard Worker       return NULL;
611*7304104dSAndroid Build Coastguard Worker     }
612*7304104dSAndroid Build Coastguard Worker 
613*7304104dSAndroid Build Coastguard Worker   /* See what kind of object we have here.  */
614*7304104dSAndroid Build Coastguard Worker   Elf_Kind kind = determine_kind (mem.header, nread);
615*7304104dSAndroid Build Coastguard Worker 
616*7304104dSAndroid Build Coastguard Worker   switch (kind)
617*7304104dSAndroid Build Coastguard Worker     {
618*7304104dSAndroid Build Coastguard Worker     case ELF_K_AR:
619*7304104dSAndroid Build Coastguard Worker       return file_read_ar (fildes, NULL, offset, maxsize, cmd, parent);
620*7304104dSAndroid Build Coastguard Worker 
621*7304104dSAndroid Build Coastguard Worker     case ELF_K_ELF:
622*7304104dSAndroid Build Coastguard Worker       /* Make sure at least the ELF header is contained in the file.  */
623*7304104dSAndroid Build Coastguard Worker       if ((size_t) nread >= (mem.header[EI_CLASS] == ELFCLASS32
624*7304104dSAndroid Build Coastguard Worker 			     ? sizeof (Elf32_Ehdr) : sizeof (Elf64_Ehdr)))
625*7304104dSAndroid Build Coastguard Worker 	return file_read_elf (fildes, NULL, mem.header, offset, maxsize, cmd,
626*7304104dSAndroid Build Coastguard Worker 			      parent);
627*7304104dSAndroid Build Coastguard Worker       FALLTHROUGH;
628*7304104dSAndroid Build Coastguard Worker 
629*7304104dSAndroid Build Coastguard Worker     default:
630*7304104dSAndroid Build Coastguard Worker       break;
631*7304104dSAndroid Build Coastguard Worker     }
632*7304104dSAndroid Build Coastguard Worker 
633*7304104dSAndroid Build Coastguard Worker   /* This case is easy.  Since we cannot do anything with this file
634*7304104dSAndroid Build Coastguard Worker      create a dummy descriptor.  */
635*7304104dSAndroid Build Coastguard Worker   return allocate_elf (fildes, NULL, offset, maxsize, cmd, parent,
636*7304104dSAndroid Build Coastguard Worker 		       ELF_K_NONE, 0);
637*7304104dSAndroid Build Coastguard Worker }
638*7304104dSAndroid Build Coastguard Worker 
639*7304104dSAndroid Build Coastguard Worker 
640*7304104dSAndroid Build Coastguard Worker /* Open a file for reading.  If possible we will try to mmap() the file.  */
641*7304104dSAndroid Build Coastguard Worker static struct Elf *
read_file(int fildes,int64_t offset,size_t maxsize,Elf_Cmd cmd,Elf * parent)642*7304104dSAndroid Build Coastguard Worker read_file (int fildes, int64_t offset, size_t maxsize,
643*7304104dSAndroid Build Coastguard Worker 	   Elf_Cmd cmd, Elf *parent)
644*7304104dSAndroid Build Coastguard Worker {
645*7304104dSAndroid Build Coastguard Worker   void *map_address = NULL;
646*7304104dSAndroid Build Coastguard Worker   int use_mmap = (cmd == ELF_C_READ_MMAP || cmd == ELF_C_RDWR_MMAP
647*7304104dSAndroid Build Coastguard Worker 		  || cmd == ELF_C_WRITE_MMAP
648*7304104dSAndroid Build Coastguard Worker 		  || cmd == ELF_C_READ_MMAP_PRIVATE);
649*7304104dSAndroid Build Coastguard Worker 
650*7304104dSAndroid Build Coastguard Worker   if (parent == NULL)
651*7304104dSAndroid Build Coastguard Worker     {
652*7304104dSAndroid Build Coastguard Worker       if (maxsize == ~((size_t) 0))
653*7304104dSAndroid Build Coastguard Worker 	{
654*7304104dSAndroid Build Coastguard Worker 	  /* We don't know in the moment how large the file is.
655*7304104dSAndroid Build Coastguard Worker 	     Determine it now.  */
656*7304104dSAndroid Build Coastguard Worker 	  struct stat st;
657*7304104dSAndroid Build Coastguard Worker 
658*7304104dSAndroid Build Coastguard Worker 	  if (fstat (fildes, &st) == 0
659*7304104dSAndroid Build Coastguard Worker 	      && (sizeof (size_t) >= sizeof (st.st_size)
660*7304104dSAndroid Build Coastguard Worker 		  || st.st_size <= ~((size_t) 0)))
661*7304104dSAndroid Build Coastguard Worker 	    maxsize = (size_t) st.st_size;
662*7304104dSAndroid Build Coastguard Worker 	}
663*7304104dSAndroid Build Coastguard Worker     }
664*7304104dSAndroid Build Coastguard Worker   else
665*7304104dSAndroid Build Coastguard Worker     {
666*7304104dSAndroid Build Coastguard Worker       /* The parent is already loaded.  Use it.  */
667*7304104dSAndroid Build Coastguard Worker       assert (maxsize != ~((size_t) 0));
668*7304104dSAndroid Build Coastguard Worker     }
669*7304104dSAndroid Build Coastguard Worker 
670*7304104dSAndroid Build Coastguard Worker   if (use_mmap)
671*7304104dSAndroid Build Coastguard Worker     {
672*7304104dSAndroid Build Coastguard Worker       if (parent == NULL)
673*7304104dSAndroid Build Coastguard Worker 	{
674*7304104dSAndroid Build Coastguard Worker 	  /* We try to map the file ourself.  */
675*7304104dSAndroid Build Coastguard Worker 	  map_address = mmap (NULL, maxsize, (cmd == ELF_C_READ_MMAP
676*7304104dSAndroid Build Coastguard Worker 					      ? PROT_READ
677*7304104dSAndroid Build Coastguard Worker 					      : PROT_READ|PROT_WRITE),
678*7304104dSAndroid Build Coastguard Worker 			      cmd == ELF_C_READ_MMAP_PRIVATE
679*7304104dSAndroid Build Coastguard Worker 			      || cmd == ELF_C_READ_MMAP
680*7304104dSAndroid Build Coastguard Worker 			      ? MAP_PRIVATE : MAP_SHARED,
681*7304104dSAndroid Build Coastguard Worker 			      fildes, offset);
682*7304104dSAndroid Build Coastguard Worker 
683*7304104dSAndroid Build Coastguard Worker 	  if (map_address == MAP_FAILED)
684*7304104dSAndroid Build Coastguard Worker 	    map_address = NULL;
685*7304104dSAndroid Build Coastguard Worker 	}
686*7304104dSAndroid Build Coastguard Worker       else
687*7304104dSAndroid Build Coastguard Worker 	{
688*7304104dSAndroid Build Coastguard Worker 	  map_address = parent->map_address;
689*7304104dSAndroid Build Coastguard Worker 	}
690*7304104dSAndroid Build Coastguard Worker     }
691*7304104dSAndroid Build Coastguard Worker 
692*7304104dSAndroid Build Coastguard Worker   /* If we have the file in memory optimize the access.  */
693*7304104dSAndroid Build Coastguard Worker   if (map_address != NULL)
694*7304104dSAndroid Build Coastguard Worker     {
695*7304104dSAndroid Build Coastguard Worker       assert (map_address != MAP_FAILED);
696*7304104dSAndroid Build Coastguard Worker 
697*7304104dSAndroid Build Coastguard Worker       struct Elf *result = __libelf_read_mmaped_file (fildes, map_address,
698*7304104dSAndroid Build Coastguard Worker 						      offset, maxsize, cmd,
699*7304104dSAndroid Build Coastguard Worker 						      parent);
700*7304104dSAndroid Build Coastguard Worker 
701*7304104dSAndroid Build Coastguard Worker       /* If something went wrong during the initialization unmap the
702*7304104dSAndroid Build Coastguard Worker 	 memory if we mmaped here.  */
703*7304104dSAndroid Build Coastguard Worker       if (result == NULL
704*7304104dSAndroid Build Coastguard Worker 	  && (parent == NULL
705*7304104dSAndroid Build Coastguard Worker 	      || parent->map_address != map_address))
706*7304104dSAndroid Build Coastguard Worker 	munmap (map_address, maxsize);
707*7304104dSAndroid Build Coastguard Worker       else if (parent == NULL)
708*7304104dSAndroid Build Coastguard Worker 	/* Remember that we mmap()ed the memory.  */
709*7304104dSAndroid Build Coastguard Worker 	result->flags |= ELF_F_MMAPPED;
710*7304104dSAndroid Build Coastguard Worker 
711*7304104dSAndroid Build Coastguard Worker       return result;
712*7304104dSAndroid Build Coastguard Worker     }
713*7304104dSAndroid Build Coastguard Worker 
714*7304104dSAndroid Build Coastguard Worker   /* Otherwise we have to do it the hard way.  We read as much as necessary
715*7304104dSAndroid Build Coastguard Worker      from the file whenever we need information which is not available.  */
716*7304104dSAndroid Build Coastguard Worker   return read_unmmaped_file (fildes, offset, maxsize, cmd, parent);
717*7304104dSAndroid Build Coastguard Worker }
718*7304104dSAndroid Build Coastguard Worker 
719*7304104dSAndroid Build Coastguard Worker 
720*7304104dSAndroid Build Coastguard Worker /* Find the entry with the long names for the content of this archive.  */
721*7304104dSAndroid Build Coastguard Worker static const char *
read_long_names(Elf * elf)722*7304104dSAndroid Build Coastguard Worker read_long_names (Elf *elf)
723*7304104dSAndroid Build Coastguard Worker {
724*7304104dSAndroid Build Coastguard Worker   off_t offset = SARMAG;	/* This is the first entry.  */
725*7304104dSAndroid Build Coastguard Worker   struct ar_hdr hdrm;
726*7304104dSAndroid Build Coastguard Worker   struct ar_hdr *hdr;
727*7304104dSAndroid Build Coastguard Worker   char *newp;
728*7304104dSAndroid Build Coastguard Worker   size_t len;
729*7304104dSAndroid Build Coastguard Worker 
730*7304104dSAndroid Build Coastguard Worker   while (1)
731*7304104dSAndroid Build Coastguard Worker     {
732*7304104dSAndroid Build Coastguard Worker       if (elf->map_address != NULL)
733*7304104dSAndroid Build Coastguard Worker 	{
734*7304104dSAndroid Build Coastguard Worker 	  if ((size_t) offset > elf->maximum_size
735*7304104dSAndroid Build Coastguard Worker 	      || elf->maximum_size - offset < sizeof (struct ar_hdr))
736*7304104dSAndroid Build Coastguard Worker 	    return NULL;
737*7304104dSAndroid Build Coastguard Worker 
738*7304104dSAndroid Build Coastguard Worker 	  /* The data is mapped.  */
739*7304104dSAndroid Build Coastguard Worker 	  hdr = (struct ar_hdr *) (elf->map_address + offset);
740*7304104dSAndroid Build Coastguard Worker 	}
741*7304104dSAndroid Build Coastguard Worker       else
742*7304104dSAndroid Build Coastguard Worker 	{
743*7304104dSAndroid Build Coastguard Worker 	  /* Read the header from the file.  */
744*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (pread_retry (elf->fildes, &hdrm, sizeof (hdrm),
745*7304104dSAndroid Build Coastguard Worker 				     elf->start_offset + offset)
746*7304104dSAndroid Build Coastguard Worker 			!= sizeof (hdrm)))
747*7304104dSAndroid Build Coastguard Worker 	    return NULL;
748*7304104dSAndroid Build Coastguard Worker 
749*7304104dSAndroid Build Coastguard Worker 	  hdr = &hdrm;
750*7304104dSAndroid Build Coastguard Worker 	}
751*7304104dSAndroid Build Coastguard Worker 
752*7304104dSAndroid Build Coastguard Worker       /* The ar_size is given as a fixed size decimal string, right
753*7304104dSAndroid Build Coastguard Worker 	 padded with spaces.  Make sure we read it properly even if
754*7304104dSAndroid Build Coastguard Worker 	 there is no terminating space.  */
755*7304104dSAndroid Build Coastguard Worker       char buf[sizeof (hdr->ar_size) + 1];
756*7304104dSAndroid Build Coastguard Worker       const char *string = hdr->ar_size;
757*7304104dSAndroid Build Coastguard Worker       if (hdr->ar_size[sizeof (hdr->ar_size) - 1] != ' ')
758*7304104dSAndroid Build Coastguard Worker 	{
759*7304104dSAndroid Build Coastguard Worker 	  *((char *) mempcpy (buf, hdr->ar_size, sizeof (hdr->ar_size))) = '\0';
760*7304104dSAndroid Build Coastguard Worker 	  string = buf;
761*7304104dSAndroid Build Coastguard Worker 	}
762*7304104dSAndroid Build Coastguard Worker 
763*7304104dSAndroid Build Coastguard Worker       /* atol expects to see at least one digit.
764*7304104dSAndroid Build Coastguard Worker 	 It also cannot be negative (-).  */
765*7304104dSAndroid Build Coastguard Worker       if (!isdigit(string[0]))
766*7304104dSAndroid Build Coastguard Worker 	return NULL;
767*7304104dSAndroid Build Coastguard Worker       len = atol (string);
768*7304104dSAndroid Build Coastguard Worker 
769*7304104dSAndroid Build Coastguard Worker       if (memcmp (hdr->ar_name, "//              ", 16) == 0)
770*7304104dSAndroid Build Coastguard Worker 	break;
771*7304104dSAndroid Build Coastguard Worker 
772*7304104dSAndroid Build Coastguard Worker       offset += sizeof (struct ar_hdr) + ((len + 1) & ~1l);
773*7304104dSAndroid Build Coastguard Worker     }
774*7304104dSAndroid Build Coastguard Worker 
775*7304104dSAndroid Build Coastguard Worker   /* Sanity check len early if we can.  */
776*7304104dSAndroid Build Coastguard Worker   if (elf->map_address != NULL)
777*7304104dSAndroid Build Coastguard Worker     {
778*7304104dSAndroid Build Coastguard Worker       if (len > elf->maximum_size - offset - sizeof (struct ar_hdr))
779*7304104dSAndroid Build Coastguard Worker 	return NULL;
780*7304104dSAndroid Build Coastguard Worker     }
781*7304104dSAndroid Build Coastguard Worker 
782*7304104dSAndroid Build Coastguard Worker   /* Due to the stupid format of the long name table entry (which are not
783*7304104dSAndroid Build Coastguard Worker      NUL terminted) we have to provide an appropriate representation anyhow.
784*7304104dSAndroid Build Coastguard Worker      Therefore we always make a copy which has the appropriate form.  */
785*7304104dSAndroid Build Coastguard Worker   newp = malloc (len);
786*7304104dSAndroid Build Coastguard Worker   if (newp != NULL)
787*7304104dSAndroid Build Coastguard Worker     {
788*7304104dSAndroid Build Coastguard Worker       char *runp;
789*7304104dSAndroid Build Coastguard Worker 
790*7304104dSAndroid Build Coastguard Worker       if (elf->map_address != NULL)
791*7304104dSAndroid Build Coastguard Worker 	{
792*7304104dSAndroid Build Coastguard Worker 	  /* Simply copy it over.  */
793*7304104dSAndroid Build Coastguard Worker 	  elf->state.ar.long_names = (char *) memcpy (newp,
794*7304104dSAndroid Build Coastguard Worker 						      elf->map_address + offset
795*7304104dSAndroid Build Coastguard Worker 						      + sizeof (struct ar_hdr),
796*7304104dSAndroid Build Coastguard Worker 						      len);
797*7304104dSAndroid Build Coastguard Worker 	}
798*7304104dSAndroid Build Coastguard Worker       else
799*7304104dSAndroid Build Coastguard Worker 	{
800*7304104dSAndroid Build Coastguard Worker 	  if (unlikely ((size_t) pread_retry (elf->fildes, newp, len,
801*7304104dSAndroid Build Coastguard Worker 					      elf->start_offset + offset
802*7304104dSAndroid Build Coastguard Worker 					      + sizeof (struct ar_hdr))
803*7304104dSAndroid Build Coastguard Worker 			!= len))
804*7304104dSAndroid Build Coastguard Worker 	    {
805*7304104dSAndroid Build Coastguard Worker 	      /* We were not able to read all data.  */
806*7304104dSAndroid Build Coastguard Worker 	      free (newp);
807*7304104dSAndroid Build Coastguard Worker 	      elf->state.ar.long_names = NULL;
808*7304104dSAndroid Build Coastguard Worker 	      return NULL;
809*7304104dSAndroid Build Coastguard Worker 	    }
810*7304104dSAndroid Build Coastguard Worker 	  elf->state.ar.long_names = newp;
811*7304104dSAndroid Build Coastguard Worker 	}
812*7304104dSAndroid Build Coastguard Worker 
813*7304104dSAndroid Build Coastguard Worker       elf->state.ar.long_names_len = len;
814*7304104dSAndroid Build Coastguard Worker 
815*7304104dSAndroid Build Coastguard Worker       /* Now NUL-terminate the strings.  */
816*7304104dSAndroid Build Coastguard Worker       runp = newp;
817*7304104dSAndroid Build Coastguard Worker       while (1)
818*7304104dSAndroid Build Coastguard Worker         {
819*7304104dSAndroid Build Coastguard Worker 	  char *startp = runp;
820*7304104dSAndroid Build Coastguard Worker 	  runp = (char *) memchr (runp, '/', newp + len - runp);
821*7304104dSAndroid Build Coastguard Worker 	  if (runp == NULL)
822*7304104dSAndroid Build Coastguard Worker 	    {
823*7304104dSAndroid Build Coastguard Worker 	      /* This was the last entry.  Clear any left overs.  */
824*7304104dSAndroid Build Coastguard Worker 	      memset (startp, '\0', newp + len - startp);
825*7304104dSAndroid Build Coastguard Worker 	      break;
826*7304104dSAndroid Build Coastguard Worker 	    }
827*7304104dSAndroid Build Coastguard Worker 
828*7304104dSAndroid Build Coastguard Worker 	  /* NUL-terminate the string.  */
829*7304104dSAndroid Build Coastguard Worker 	  *runp++ = '\0';
830*7304104dSAndroid Build Coastguard Worker 
831*7304104dSAndroid Build Coastguard Worker 	  /* A sanity check.  Somebody might have generated invalid
832*7304104dSAndroid Build Coastguard Worker 	     archive.  */
833*7304104dSAndroid Build Coastguard Worker 	  if (runp >= newp + len)
834*7304104dSAndroid Build Coastguard Worker 	    break;
835*7304104dSAndroid Build Coastguard Worker 	}
836*7304104dSAndroid Build Coastguard Worker     }
837*7304104dSAndroid Build Coastguard Worker 
838*7304104dSAndroid Build Coastguard Worker   return newp;
839*7304104dSAndroid Build Coastguard Worker }
840*7304104dSAndroid Build Coastguard Worker 
841*7304104dSAndroid Build Coastguard Worker 
842*7304104dSAndroid Build Coastguard Worker /* Read the next archive header.  */
843*7304104dSAndroid Build Coastguard Worker int
844*7304104dSAndroid Build Coastguard Worker internal_function
__libelf_next_arhdr_wrlock(Elf * elf)845*7304104dSAndroid Build Coastguard Worker __libelf_next_arhdr_wrlock (Elf *elf)
846*7304104dSAndroid Build Coastguard Worker {
847*7304104dSAndroid Build Coastguard Worker   struct ar_hdr *ar_hdr;
848*7304104dSAndroid Build Coastguard Worker   Elf_Arhdr *elf_ar_hdr;
849*7304104dSAndroid Build Coastguard Worker 
850*7304104dSAndroid Build Coastguard Worker   if (elf->map_address != NULL)
851*7304104dSAndroid Build Coastguard Worker     {
852*7304104dSAndroid Build Coastguard Worker       /* See whether this entry is in the file.  */
853*7304104dSAndroid Build Coastguard Worker       if (unlikely ((size_t) elf->state.ar.offset
854*7304104dSAndroid Build Coastguard Worker 		    > elf->start_offset + elf->maximum_size
855*7304104dSAndroid Build Coastguard Worker 		    || (elf->start_offset + elf->maximum_size
856*7304104dSAndroid Build Coastguard Worker 			- elf->state.ar.offset) < sizeof (struct ar_hdr)))
857*7304104dSAndroid Build Coastguard Worker 	{
858*7304104dSAndroid Build Coastguard Worker 	  /* This record is not anymore in the file.  */
859*7304104dSAndroid Build Coastguard Worker 	  __libelf_seterrno (ELF_E_RANGE);
860*7304104dSAndroid Build Coastguard Worker 	  return -1;
861*7304104dSAndroid Build Coastguard Worker 	}
862*7304104dSAndroid Build Coastguard Worker       ar_hdr = (struct ar_hdr *) (elf->map_address + elf->state.ar.offset);
863*7304104dSAndroid Build Coastguard Worker     }
864*7304104dSAndroid Build Coastguard Worker   else
865*7304104dSAndroid Build Coastguard Worker     {
866*7304104dSAndroid Build Coastguard Worker       ar_hdr = &elf->state.ar.ar_hdr;
867*7304104dSAndroid Build Coastguard Worker 
868*7304104dSAndroid Build Coastguard Worker       if (unlikely (pread_retry (elf->fildes, ar_hdr, sizeof (struct ar_hdr),
869*7304104dSAndroid Build Coastguard Worker 				 elf->state.ar.offset)
870*7304104dSAndroid Build Coastguard Worker 		    != sizeof (struct ar_hdr)))
871*7304104dSAndroid Build Coastguard Worker 	{
872*7304104dSAndroid Build Coastguard Worker 	  /* Something went wrong while reading the file.  */
873*7304104dSAndroid Build Coastguard Worker 	  __libelf_seterrno (ELF_E_RANGE);
874*7304104dSAndroid Build Coastguard Worker 	  return -1;
875*7304104dSAndroid Build Coastguard Worker 	}
876*7304104dSAndroid Build Coastguard Worker     }
877*7304104dSAndroid Build Coastguard Worker 
878*7304104dSAndroid Build Coastguard Worker   /* One little consistency check.  */
879*7304104dSAndroid Build Coastguard Worker   if (unlikely (memcmp (ar_hdr->ar_fmag, ARFMAG, 2) != 0))
880*7304104dSAndroid Build Coastguard Worker     {
881*7304104dSAndroid Build Coastguard Worker       /* This is no valid archive.  */
882*7304104dSAndroid Build Coastguard Worker       __libelf_seterrno (ELF_E_ARCHIVE_FMAG);
883*7304104dSAndroid Build Coastguard Worker       return -1;
884*7304104dSAndroid Build Coastguard Worker     }
885*7304104dSAndroid Build Coastguard Worker 
886*7304104dSAndroid Build Coastguard Worker   /* Copy the raw name over to a NUL terminated buffer.  */
887*7304104dSAndroid Build Coastguard Worker   *((char *) mempcpy (elf->state.ar.raw_name, ar_hdr->ar_name, 16)) = '\0';
888*7304104dSAndroid Build Coastguard Worker 
889*7304104dSAndroid Build Coastguard Worker   elf_ar_hdr = &elf->state.ar.elf_ar_hdr;
890*7304104dSAndroid Build Coastguard Worker 
891*7304104dSAndroid Build Coastguard Worker   /* Now convert the `struct ar_hdr' into `Elf_Arhdr'.
892*7304104dSAndroid Build Coastguard Worker      Determine whether this is a special entry.  */
893*7304104dSAndroid Build Coastguard Worker   if (ar_hdr->ar_name[0] == '/')
894*7304104dSAndroid Build Coastguard Worker     {
895*7304104dSAndroid Build Coastguard Worker       if (ar_hdr->ar_name[1] == ' '
896*7304104dSAndroid Build Coastguard Worker 	  && memcmp (ar_hdr->ar_name, "/               ", 16) == 0)
897*7304104dSAndroid Build Coastguard Worker 	/* This is the index.  */
898*7304104dSAndroid Build Coastguard Worker 	elf_ar_hdr->ar_name = memcpy (elf->state.ar.ar_name, "/", 2);
899*7304104dSAndroid Build Coastguard Worker       else if (ar_hdr->ar_name[1] == 'S'
900*7304104dSAndroid Build Coastguard Worker 	       && memcmp (ar_hdr->ar_name, "/SYM64/         ", 16) == 0)
901*7304104dSAndroid Build Coastguard Worker 	/* 64-bit index.  */
902*7304104dSAndroid Build Coastguard Worker 	elf_ar_hdr->ar_name = memcpy (elf->state.ar.ar_name, "/SYM64/", 8);
903*7304104dSAndroid Build Coastguard Worker       else if (ar_hdr->ar_name[1] == '/'
904*7304104dSAndroid Build Coastguard Worker 	       && memcmp (ar_hdr->ar_name, "//              ", 16) == 0)
905*7304104dSAndroid Build Coastguard Worker 	/* This is the array with the long names.  */
906*7304104dSAndroid Build Coastguard Worker 	elf_ar_hdr->ar_name = memcpy (elf->state.ar.ar_name, "//", 3);
907*7304104dSAndroid Build Coastguard Worker       else if (likely  (isdigit (ar_hdr->ar_name[1])))
908*7304104dSAndroid Build Coastguard Worker 	{
909*7304104dSAndroid Build Coastguard Worker 	  size_t offset;
910*7304104dSAndroid Build Coastguard Worker 
911*7304104dSAndroid Build Coastguard Worker 	  /* This is a long name.  First we have to read the long name
912*7304104dSAndroid Build Coastguard Worker 	     table, if this hasn't happened already.  */
913*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (elf->state.ar.long_names == NULL
914*7304104dSAndroid Build Coastguard Worker 			&& read_long_names (elf) == NULL))
915*7304104dSAndroid Build Coastguard Worker 	    {
916*7304104dSAndroid Build Coastguard Worker 	      /* No long name table although it is reference.  The archive is
917*7304104dSAndroid Build Coastguard Worker 		 broken.  */
918*7304104dSAndroid Build Coastguard Worker 	      __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
919*7304104dSAndroid Build Coastguard Worker 	      return -1;
920*7304104dSAndroid Build Coastguard Worker 	    }
921*7304104dSAndroid Build Coastguard Worker 
922*7304104dSAndroid Build Coastguard Worker 	  offset = atol (ar_hdr->ar_name + 1);
923*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (offset >= elf->state.ar.long_names_len))
924*7304104dSAndroid Build Coastguard Worker 	    {
925*7304104dSAndroid Build Coastguard Worker 	      /* The index in the long name table is larger than the table.  */
926*7304104dSAndroid Build Coastguard Worker 	      __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
927*7304104dSAndroid Build Coastguard Worker 	      return -1;
928*7304104dSAndroid Build Coastguard Worker 	    }
929*7304104dSAndroid Build Coastguard Worker 	  elf_ar_hdr->ar_name = elf->state.ar.long_names + offset;
930*7304104dSAndroid Build Coastguard Worker 	}
931*7304104dSAndroid Build Coastguard Worker       else
932*7304104dSAndroid Build Coastguard Worker 	{
933*7304104dSAndroid Build Coastguard Worker 	  /* This is none of the known special entries.  */
934*7304104dSAndroid Build Coastguard Worker 	  __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
935*7304104dSAndroid Build Coastguard Worker 	  return -1;
936*7304104dSAndroid Build Coastguard Worker 	}
937*7304104dSAndroid Build Coastguard Worker     }
938*7304104dSAndroid Build Coastguard Worker   else
939*7304104dSAndroid Build Coastguard Worker     {
940*7304104dSAndroid Build Coastguard Worker       char *endp;
941*7304104dSAndroid Build Coastguard Worker 
942*7304104dSAndroid Build Coastguard Worker       /* It is a normal entry.  Copy over the name.  */
943*7304104dSAndroid Build Coastguard Worker       endp = (char *) memccpy (elf->state.ar.ar_name, ar_hdr->ar_name,
944*7304104dSAndroid Build Coastguard Worker 			       '/', 16);
945*7304104dSAndroid Build Coastguard Worker       if (endp != NULL)
946*7304104dSAndroid Build Coastguard Worker 	endp[-1] = '\0';
947*7304104dSAndroid Build Coastguard Worker       else
948*7304104dSAndroid Build Coastguard Worker 	{
949*7304104dSAndroid Build Coastguard Worker 	  /* In the old BSD style of archive, there is no / terminator.
950*7304104dSAndroid Build Coastguard Worker 	     Instead, there is space padding at the end of the name.  */
951*7304104dSAndroid Build Coastguard Worker 	  size_t i = 15;
952*7304104dSAndroid Build Coastguard Worker 	  do
953*7304104dSAndroid Build Coastguard Worker 	    elf->state.ar.ar_name[i] = '\0';
954*7304104dSAndroid Build Coastguard Worker 	  while (i > 0 && elf->state.ar.ar_name[--i] == ' ');
955*7304104dSAndroid Build Coastguard Worker 	}
956*7304104dSAndroid Build Coastguard Worker 
957*7304104dSAndroid Build Coastguard Worker       elf_ar_hdr->ar_name = elf->state.ar.ar_name;
958*7304104dSAndroid Build Coastguard Worker     }
959*7304104dSAndroid Build Coastguard Worker 
960*7304104dSAndroid Build Coastguard Worker   if (unlikely (ar_hdr->ar_size[0] == ' '))
961*7304104dSAndroid Build Coastguard Worker     /* Something is really wrong.  We cannot live without a size for
962*7304104dSAndroid Build Coastguard Worker        the member since it will not be possible to find the next
963*7304104dSAndroid Build Coastguard Worker        archive member.  */
964*7304104dSAndroid Build Coastguard Worker     {
965*7304104dSAndroid Build Coastguard Worker       __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
966*7304104dSAndroid Build Coastguard Worker       return -1;
967*7304104dSAndroid Build Coastguard Worker     }
968*7304104dSAndroid Build Coastguard Worker 
969*7304104dSAndroid Build Coastguard Worker   /* Since there are no specialized functions to convert ASCII to
970*7304104dSAndroid Build Coastguard Worker      time_t, uid_t, gid_t, mode_t, and off_t we use either atol or
971*7304104dSAndroid Build Coastguard Worker      atoll depending on the size of the types.  We are also prepared
972*7304104dSAndroid Build Coastguard Worker      for the case where the whole field in the `struct ar_hdr' is
973*7304104dSAndroid Build Coastguard Worker      filled in which case we cannot simply use atol/l but instead have
974*7304104dSAndroid Build Coastguard Worker      to create a temporary copy.  Note that all fields use decimal
975*7304104dSAndroid Build Coastguard Worker      encoding, except ar_mode which uses octal.  */
976*7304104dSAndroid Build Coastguard Worker 
977*7304104dSAndroid Build Coastguard Worker #define INT_FIELD(FIELD)						      \
978*7304104dSAndroid Build Coastguard Worker   do									      \
979*7304104dSAndroid Build Coastguard Worker     {									      \
980*7304104dSAndroid Build Coastguard Worker       char buf[sizeof (ar_hdr->FIELD) + 1];				      \
981*7304104dSAndroid Build Coastguard Worker       const char *string = ar_hdr->FIELD;				      \
982*7304104dSAndroid Build Coastguard Worker       if (ar_hdr->FIELD[sizeof (ar_hdr->FIELD) - 1] != ' ')		      \
983*7304104dSAndroid Build Coastguard Worker 	{								      \
984*7304104dSAndroid Build Coastguard Worker 	  *((char *) mempcpy (buf, ar_hdr->FIELD, sizeof (ar_hdr->FIELD)))  \
985*7304104dSAndroid Build Coastguard Worker 	    = '\0';							      \
986*7304104dSAndroid Build Coastguard Worker 	  string = buf;							      \
987*7304104dSAndroid Build Coastguard Worker 	}								      \
988*7304104dSAndroid Build Coastguard Worker       if (sizeof (elf_ar_hdr->FIELD) <= sizeof (long int))		      \
989*7304104dSAndroid Build Coastguard Worker 	elf_ar_hdr->FIELD = (__typeof (elf_ar_hdr->FIELD)) atol (string);     \
990*7304104dSAndroid Build Coastguard Worker       else								      \
991*7304104dSAndroid Build Coastguard Worker 	elf_ar_hdr->FIELD = (__typeof (elf_ar_hdr->FIELD)) atoll (string);    \
992*7304104dSAndroid Build Coastguard Worker     }									      \
993*7304104dSAndroid Build Coastguard Worker   while (0)
994*7304104dSAndroid Build Coastguard Worker 
995*7304104dSAndroid Build Coastguard Worker #define OCT_FIELD(FIELD)						      \
996*7304104dSAndroid Build Coastguard Worker   do									      \
997*7304104dSAndroid Build Coastguard Worker     {									      \
998*7304104dSAndroid Build Coastguard Worker       char buf[sizeof (ar_hdr->FIELD) + 1];				      \
999*7304104dSAndroid Build Coastguard Worker       const char *string = ar_hdr->FIELD;				      \
1000*7304104dSAndroid Build Coastguard Worker       if (ar_hdr->FIELD[sizeof (ar_hdr->FIELD) - 1] != ' ')		      \
1001*7304104dSAndroid Build Coastguard Worker 	{								      \
1002*7304104dSAndroid Build Coastguard Worker 	  *((char *) mempcpy (buf, ar_hdr->FIELD, sizeof (ar_hdr->FIELD)))  \
1003*7304104dSAndroid Build Coastguard Worker 	    = '\0';							      \
1004*7304104dSAndroid Build Coastguard Worker 	  string = buf;							      \
1005*7304104dSAndroid Build Coastguard Worker 	}								      \
1006*7304104dSAndroid Build Coastguard Worker       if (sizeof (elf_ar_hdr->FIELD) <= sizeof (long int))		      \
1007*7304104dSAndroid Build Coastguard Worker 	elf_ar_hdr->FIELD						      \
1008*7304104dSAndroid Build Coastguard Worker 	  = (__typeof (elf_ar_hdr->FIELD)) strtol (string, NULL, 8);	      \
1009*7304104dSAndroid Build Coastguard Worker       else								      \
1010*7304104dSAndroid Build Coastguard Worker 	elf_ar_hdr->FIELD						      \
1011*7304104dSAndroid Build Coastguard Worker 	  = (__typeof (elf_ar_hdr->FIELD)) strtoll (string, NULL, 8);	      \
1012*7304104dSAndroid Build Coastguard Worker     }									      \
1013*7304104dSAndroid Build Coastguard Worker   while (0)
1014*7304104dSAndroid Build Coastguard Worker 
1015*7304104dSAndroid Build Coastguard Worker   INT_FIELD (ar_date);
1016*7304104dSAndroid Build Coastguard Worker   INT_FIELD (ar_uid);
1017*7304104dSAndroid Build Coastguard Worker   INT_FIELD (ar_gid);
1018*7304104dSAndroid Build Coastguard Worker   OCT_FIELD (ar_mode);
1019*7304104dSAndroid Build Coastguard Worker   INT_FIELD (ar_size);
1020*7304104dSAndroid Build Coastguard Worker 
1021*7304104dSAndroid Build Coastguard Worker   if (elf_ar_hdr->ar_size < 0)
1022*7304104dSAndroid Build Coastguard Worker     {
1023*7304104dSAndroid Build Coastguard Worker       __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
1024*7304104dSAndroid Build Coastguard Worker       return -1;
1025*7304104dSAndroid Build Coastguard Worker     }
1026*7304104dSAndroid Build Coastguard Worker 
1027*7304104dSAndroid Build Coastguard Worker   /* Truncated file?  */
1028*7304104dSAndroid Build Coastguard Worker   size_t maxsize;
1029*7304104dSAndroid Build Coastguard Worker   maxsize = (elf->start_offset + elf->maximum_size
1030*7304104dSAndroid Build Coastguard Worker 	     - elf->state.ar.offset - sizeof (struct ar_hdr));
1031*7304104dSAndroid Build Coastguard Worker   if ((size_t) elf_ar_hdr->ar_size > maxsize)
1032*7304104dSAndroid Build Coastguard Worker     elf_ar_hdr->ar_size = maxsize;
1033*7304104dSAndroid Build Coastguard Worker 
1034*7304104dSAndroid Build Coastguard Worker   return 0;
1035*7304104dSAndroid Build Coastguard Worker }
1036*7304104dSAndroid Build Coastguard Worker 
1037*7304104dSAndroid Build Coastguard Worker 
1038*7304104dSAndroid Build Coastguard Worker /* We were asked to return a clone of an existing descriptor.  This
1039*7304104dSAndroid Build Coastguard Worker    function must be called with the lock on the parent descriptor
1040*7304104dSAndroid Build Coastguard Worker    being held. */
1041*7304104dSAndroid Build Coastguard Worker static Elf *
dup_elf(int fildes,Elf_Cmd cmd,Elf * ref)1042*7304104dSAndroid Build Coastguard Worker dup_elf (int fildes, Elf_Cmd cmd, Elf *ref)
1043*7304104dSAndroid Build Coastguard Worker {
1044*7304104dSAndroid Build Coastguard Worker   struct Elf *result;
1045*7304104dSAndroid Build Coastguard Worker 
1046*7304104dSAndroid Build Coastguard Worker   if (fildes == -1)
1047*7304104dSAndroid Build Coastguard Worker     /* Allow the user to pass -1 as the file descriptor for the new file.  */
1048*7304104dSAndroid Build Coastguard Worker     fildes = ref->fildes;
1049*7304104dSAndroid Build Coastguard Worker   /* The file descriptor better should be the same.  If it was disconnected
1050*7304104dSAndroid Build Coastguard Worker      already (using `elf_cntl') we do not test it.  */
1051*7304104dSAndroid Build Coastguard Worker   else if (unlikely (ref->fildes != -1 && fildes != ref->fildes))
1052*7304104dSAndroid Build Coastguard Worker     {
1053*7304104dSAndroid Build Coastguard Worker       __libelf_seterrno (ELF_E_FD_MISMATCH);
1054*7304104dSAndroid Build Coastguard Worker       return NULL;
1055*7304104dSAndroid Build Coastguard Worker     }
1056*7304104dSAndroid Build Coastguard Worker 
1057*7304104dSAndroid Build Coastguard Worker   /* The mode must allow reading.  I.e., a descriptor creating with a
1058*7304104dSAndroid Build Coastguard Worker      command different then ELF_C_READ, ELF_C_WRITE and ELF_C_RDWR is
1059*7304104dSAndroid Build Coastguard Worker      not allowed.  */
1060*7304104dSAndroid Build Coastguard Worker   if (unlikely (ref->cmd != ELF_C_READ && ref->cmd != ELF_C_READ_MMAP
1061*7304104dSAndroid Build Coastguard Worker 		&& ref->cmd != ELF_C_WRITE && ref->cmd != ELF_C_WRITE_MMAP
1062*7304104dSAndroid Build Coastguard Worker 		&& ref->cmd != ELF_C_RDWR && ref->cmd != ELF_C_RDWR_MMAP
1063*7304104dSAndroid Build Coastguard Worker 		&& ref->cmd != ELF_C_READ_MMAP_PRIVATE))
1064*7304104dSAndroid Build Coastguard Worker     {
1065*7304104dSAndroid Build Coastguard Worker       __libelf_seterrno (ELF_E_INVALID_OP);
1066*7304104dSAndroid Build Coastguard Worker       return NULL;
1067*7304104dSAndroid Build Coastguard Worker     }
1068*7304104dSAndroid Build Coastguard Worker 
1069*7304104dSAndroid Build Coastguard Worker   /* Now it is time to distinguish between reading normal files and
1070*7304104dSAndroid Build Coastguard Worker      archives.  Normal files can easily be handled be incrementing the
1071*7304104dSAndroid Build Coastguard Worker      reference counter and return the same descriptor.  */
1072*7304104dSAndroid Build Coastguard Worker   if (ref->kind != ELF_K_AR)
1073*7304104dSAndroid Build Coastguard Worker     {
1074*7304104dSAndroid Build Coastguard Worker       ++ref->ref_count;
1075*7304104dSAndroid Build Coastguard Worker       return ref;
1076*7304104dSAndroid Build Coastguard Worker     }
1077*7304104dSAndroid Build Coastguard Worker 
1078*7304104dSAndroid Build Coastguard Worker   /* This is an archive.  We must create a descriptor for the archive
1079*7304104dSAndroid Build Coastguard Worker      member the internal pointer of the archive file descriptor is
1080*7304104dSAndroid Build Coastguard Worker      pointing to.  First read the header of the next member if this
1081*7304104dSAndroid Build Coastguard Worker      has not happened already.  */
1082*7304104dSAndroid Build Coastguard Worker   if (ref->state.ar.elf_ar_hdr.ar_name == NULL
1083*7304104dSAndroid Build Coastguard Worker       && __libelf_next_arhdr_wrlock (ref) != 0)
1084*7304104dSAndroid Build Coastguard Worker     /* Something went wrong.  Maybe there is no member left.  */
1085*7304104dSAndroid Build Coastguard Worker     return NULL;
1086*7304104dSAndroid Build Coastguard Worker 
1087*7304104dSAndroid Build Coastguard Worker   /* We have all the information we need about the next archive member.
1088*7304104dSAndroid Build Coastguard Worker      Now create a descriptor for it.  */
1089*7304104dSAndroid Build Coastguard Worker   result = read_file (fildes, ref->state.ar.offset + sizeof (struct ar_hdr),
1090*7304104dSAndroid Build Coastguard Worker 		      ref->state.ar.elf_ar_hdr.ar_size, cmd, ref);
1091*7304104dSAndroid Build Coastguard Worker 
1092*7304104dSAndroid Build Coastguard Worker   /* Enlist this new descriptor in the list of children.  */
1093*7304104dSAndroid Build Coastguard Worker   if (result != NULL)
1094*7304104dSAndroid Build Coastguard Worker     {
1095*7304104dSAndroid Build Coastguard Worker       result->next = ref->state.ar.children;
1096*7304104dSAndroid Build Coastguard Worker       ref->state.ar.children = result;
1097*7304104dSAndroid Build Coastguard Worker     }
1098*7304104dSAndroid Build Coastguard Worker 
1099*7304104dSAndroid Build Coastguard Worker   return result;
1100*7304104dSAndroid Build Coastguard Worker }
1101*7304104dSAndroid Build Coastguard Worker 
1102*7304104dSAndroid Build Coastguard Worker 
1103*7304104dSAndroid Build Coastguard Worker /* Return descriptor for empty file ready for writing.  */
1104*7304104dSAndroid Build Coastguard Worker static struct Elf *
write_file(int fd,Elf_Cmd cmd)1105*7304104dSAndroid Build Coastguard Worker write_file (int fd, Elf_Cmd cmd)
1106*7304104dSAndroid Build Coastguard Worker {
1107*7304104dSAndroid Build Coastguard Worker   /* We simply create an empty `Elf' structure.  */
1108*7304104dSAndroid Build Coastguard Worker #define NSCNSALLOC	10
1109*7304104dSAndroid Build Coastguard Worker   Elf *result = allocate_elf (fd, NULL, 0, 0, cmd, NULL, ELF_K_ELF,
1110*7304104dSAndroid Build Coastguard Worker 			      NSCNSALLOC * sizeof (Elf_Scn));
1111*7304104dSAndroid Build Coastguard Worker 
1112*7304104dSAndroid Build Coastguard Worker   if (result != NULL)
1113*7304104dSAndroid Build Coastguard Worker     {
1114*7304104dSAndroid Build Coastguard Worker       /* We have to write to the file in any case.  */
1115*7304104dSAndroid Build Coastguard Worker       result->flags = ELF_F_DIRTY;
1116*7304104dSAndroid Build Coastguard Worker 
1117*7304104dSAndroid Build Coastguard Worker       /* Some more or less arbitrary value.  */
1118*7304104dSAndroid Build Coastguard Worker       result->state.elf.scnincr = NSCNSALLOC;
1119*7304104dSAndroid Build Coastguard Worker 
1120*7304104dSAndroid Build Coastguard Worker       /* We have allocated room for some sections.  */
1121*7304104dSAndroid Build Coastguard Worker       assert (offsetof (struct Elf, state.elf32.scns)
1122*7304104dSAndroid Build Coastguard Worker 	      == offsetof (struct Elf, state.elf64.scns));
1123*7304104dSAndroid Build Coastguard Worker       result->state.elf.scns_last = &result->state.elf32.scns;
1124*7304104dSAndroid Build Coastguard Worker       result->state.elf32.scns.max = NSCNSALLOC;
1125*7304104dSAndroid Build Coastguard Worker     }
1126*7304104dSAndroid Build Coastguard Worker 
1127*7304104dSAndroid Build Coastguard Worker   return result;
1128*7304104dSAndroid Build Coastguard Worker }
1129*7304104dSAndroid Build Coastguard Worker 
1130*7304104dSAndroid Build Coastguard Worker /* Lock if necessary before dup an archive.  */
1131*7304104dSAndroid Build Coastguard Worker static inline Elf *
lock_dup_elf(int fildes,Elf_Cmd cmd,Elf * ref)1132*7304104dSAndroid Build Coastguard Worker lock_dup_elf (int fildes, Elf_Cmd cmd, Elf *ref)
1133*7304104dSAndroid Build Coastguard Worker {
1134*7304104dSAndroid Build Coastguard Worker   /* We need wrlock to dup an archive.  */
1135*7304104dSAndroid Build Coastguard Worker   if (ref->kind == ELF_K_AR)
1136*7304104dSAndroid Build Coastguard Worker     {
1137*7304104dSAndroid Build Coastguard Worker       rwlock_unlock (ref->lock);
1138*7304104dSAndroid Build Coastguard Worker       rwlock_wrlock (ref->lock);
1139*7304104dSAndroid Build Coastguard Worker     }
1140*7304104dSAndroid Build Coastguard Worker     /* Duplicate the descriptor.  */
1141*7304104dSAndroid Build Coastguard Worker   return dup_elf (fildes, cmd, ref);
1142*7304104dSAndroid Build Coastguard Worker }
1143*7304104dSAndroid Build Coastguard Worker 
1144*7304104dSAndroid Build Coastguard Worker /* Return a descriptor for the file belonging to FILDES.  */
1145*7304104dSAndroid Build Coastguard Worker Elf *
elf_begin(int fildes,Elf_Cmd cmd,Elf * ref)1146*7304104dSAndroid Build Coastguard Worker elf_begin (int fildes, Elf_Cmd cmd, Elf *ref)
1147*7304104dSAndroid Build Coastguard Worker {
1148*7304104dSAndroid Build Coastguard Worker   Elf *retval;
1149*7304104dSAndroid Build Coastguard Worker 
1150*7304104dSAndroid Build Coastguard Worker   if (unlikely (__libelf_version != EV_CURRENT))
1151*7304104dSAndroid Build Coastguard Worker     {
1152*7304104dSAndroid Build Coastguard Worker       /* Version wasn't set so far.  */
1153*7304104dSAndroid Build Coastguard Worker       __libelf_seterrno (ELF_E_NO_VERSION);
1154*7304104dSAndroid Build Coastguard Worker       return NULL;
1155*7304104dSAndroid Build Coastguard Worker     }
1156*7304104dSAndroid Build Coastguard Worker 
1157*7304104dSAndroid Build Coastguard Worker   if (ref != NULL)
1158*7304104dSAndroid Build Coastguard Worker     /* Make sure the descriptor is not suddenly going away.  */
1159*7304104dSAndroid Build Coastguard Worker     rwlock_rdlock (ref->lock);
1160*7304104dSAndroid Build Coastguard Worker   else if (unlikely (fcntl (fildes, F_GETFD) == -1 && errno == EBADF))
1161*7304104dSAndroid Build Coastguard Worker     {
1162*7304104dSAndroid Build Coastguard Worker       /* We cannot do anything productive without a file descriptor.  */
1163*7304104dSAndroid Build Coastguard Worker       __libelf_seterrno (ELF_E_INVALID_FILE);
1164*7304104dSAndroid Build Coastguard Worker       return NULL;
1165*7304104dSAndroid Build Coastguard Worker     }
1166*7304104dSAndroid Build Coastguard Worker 
1167*7304104dSAndroid Build Coastguard Worker   switch (cmd)
1168*7304104dSAndroid Build Coastguard Worker     {
1169*7304104dSAndroid Build Coastguard Worker     case ELF_C_NULL:
1170*7304104dSAndroid Build Coastguard Worker       /* We simply return a NULL pointer.  */
1171*7304104dSAndroid Build Coastguard Worker       retval = NULL;
1172*7304104dSAndroid Build Coastguard Worker       break;
1173*7304104dSAndroid Build Coastguard Worker 
1174*7304104dSAndroid Build Coastguard Worker     case ELF_C_READ_MMAP_PRIVATE:
1175*7304104dSAndroid Build Coastguard Worker       /* If we have a reference it must also be opened this way.  */
1176*7304104dSAndroid Build Coastguard Worker       if (unlikely (ref != NULL && ref->cmd != ELF_C_READ_MMAP_PRIVATE))
1177*7304104dSAndroid Build Coastguard Worker 	{
1178*7304104dSAndroid Build Coastguard Worker 	  __libelf_seterrno (ELF_E_INVALID_CMD);
1179*7304104dSAndroid Build Coastguard Worker 	  retval = NULL;
1180*7304104dSAndroid Build Coastguard Worker 	  break;
1181*7304104dSAndroid Build Coastguard Worker 	}
1182*7304104dSAndroid Build Coastguard Worker       FALLTHROUGH;
1183*7304104dSAndroid Build Coastguard Worker 
1184*7304104dSAndroid Build Coastguard Worker     case ELF_C_READ:
1185*7304104dSAndroid Build Coastguard Worker     case ELF_C_READ_MMAP:
1186*7304104dSAndroid Build Coastguard Worker       if (ref != NULL)
1187*7304104dSAndroid Build Coastguard Worker 	retval = lock_dup_elf (fildes, cmd, ref);
1188*7304104dSAndroid Build Coastguard Worker       else
1189*7304104dSAndroid Build Coastguard Worker 	/* Create descriptor for existing file.  */
1190*7304104dSAndroid Build Coastguard Worker 	retval = read_file (fildes, 0, ~((size_t) 0), cmd, NULL);
1191*7304104dSAndroid Build Coastguard Worker       break;
1192*7304104dSAndroid Build Coastguard Worker 
1193*7304104dSAndroid Build Coastguard Worker     case ELF_C_RDWR:
1194*7304104dSAndroid Build Coastguard Worker     case ELF_C_RDWR_MMAP:
1195*7304104dSAndroid Build Coastguard Worker       /* If we have a REF object it must also be opened using this
1196*7304104dSAndroid Build Coastguard Worker 	 command.  */
1197*7304104dSAndroid Build Coastguard Worker       if (ref != NULL)
1198*7304104dSAndroid Build Coastguard Worker 	{
1199*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (ref->cmd != ELF_C_RDWR && ref->cmd != ELF_C_RDWR_MMAP
1200*7304104dSAndroid Build Coastguard Worker 			&& ref->cmd != ELF_C_WRITE
1201*7304104dSAndroid Build Coastguard Worker 			&& ref->cmd != ELF_C_WRITE_MMAP))
1202*7304104dSAndroid Build Coastguard Worker 	    {
1203*7304104dSAndroid Build Coastguard Worker 	      /* This is not ok.  REF must also be opened for writing.  */
1204*7304104dSAndroid Build Coastguard Worker 	      __libelf_seterrno (ELF_E_INVALID_CMD);
1205*7304104dSAndroid Build Coastguard Worker 	      retval = NULL;
1206*7304104dSAndroid Build Coastguard Worker 	    }
1207*7304104dSAndroid Build Coastguard Worker 	  else
1208*7304104dSAndroid Build Coastguard Worker 	    retval = lock_dup_elf (fildes, cmd, ref);
1209*7304104dSAndroid Build Coastguard Worker 	}
1210*7304104dSAndroid Build Coastguard Worker       else
1211*7304104dSAndroid Build Coastguard Worker 	/* Create descriptor for existing file.  */
1212*7304104dSAndroid Build Coastguard Worker 	retval = read_file (fildes, 0, ~((size_t) 0), cmd, NULL);
1213*7304104dSAndroid Build Coastguard Worker       break;
1214*7304104dSAndroid Build Coastguard Worker 
1215*7304104dSAndroid Build Coastguard Worker     case ELF_C_WRITE:
1216*7304104dSAndroid Build Coastguard Worker     case ELF_C_WRITE_MMAP:
1217*7304104dSAndroid Build Coastguard Worker       /* We ignore REF and prepare a descriptor to write a new file.  */
1218*7304104dSAndroid Build Coastguard Worker       retval = write_file (fildes, cmd);
1219*7304104dSAndroid Build Coastguard Worker       break;
1220*7304104dSAndroid Build Coastguard Worker 
1221*7304104dSAndroid Build Coastguard Worker     default:
1222*7304104dSAndroid Build Coastguard Worker       __libelf_seterrno (ELF_E_INVALID_CMD);
1223*7304104dSAndroid Build Coastguard Worker       retval = NULL;
1224*7304104dSAndroid Build Coastguard Worker       break;
1225*7304104dSAndroid Build Coastguard Worker     }
1226*7304104dSAndroid Build Coastguard Worker 
1227*7304104dSAndroid Build Coastguard Worker   /* Release the lock.  */
1228*7304104dSAndroid Build Coastguard Worker   if (ref != NULL)
1229*7304104dSAndroid Build Coastguard Worker     rwlock_unlock (ref->lock);
1230*7304104dSAndroid Build Coastguard Worker 
1231*7304104dSAndroid Build Coastguard Worker   return retval;
1232*7304104dSAndroid Build Coastguard Worker }
1233*7304104dSAndroid Build Coastguard Worker INTDEF(elf_begin)
1234