xref: /aosp_15_r20/external/elfutils/libelf/elf_getarsym.c (revision 7304104da70ce23c86437a01be71edd1a2d7f37e)
1*7304104dSAndroid Build Coastguard Worker /* Return symbol table of archive.
2*7304104dSAndroid Build Coastguard Worker    Copyright (C) 1998-2000, 2002, 2005, 2009, 2012, 2014, 2015 Red Hat, Inc.
3*7304104dSAndroid Build Coastguard Worker    This file is part of elfutils.
4*7304104dSAndroid Build Coastguard Worker    Written by Ulrich Drepper <[email protected]>, 1998.
5*7304104dSAndroid Build Coastguard Worker 
6*7304104dSAndroid Build Coastguard Worker    This file is free software; you can redistribute it and/or modify
7*7304104dSAndroid Build Coastguard Worker    it under the terms of either
8*7304104dSAndroid Build Coastguard Worker 
9*7304104dSAndroid Build Coastguard Worker      * the GNU Lesser General Public License as published by the Free
10*7304104dSAndroid Build Coastguard Worker        Software Foundation; either version 3 of the License, or (at
11*7304104dSAndroid Build Coastguard Worker        your option) any later version
12*7304104dSAndroid Build Coastguard Worker 
13*7304104dSAndroid Build Coastguard Worker    or
14*7304104dSAndroid Build Coastguard Worker 
15*7304104dSAndroid Build Coastguard Worker      * the GNU General Public License as published by the Free
16*7304104dSAndroid Build Coastguard Worker        Software Foundation; either version 2 of the License, or (at
17*7304104dSAndroid Build Coastguard Worker        your option) any later version
18*7304104dSAndroid Build Coastguard Worker 
19*7304104dSAndroid Build Coastguard Worker    or both in parallel, as here.
20*7304104dSAndroid Build Coastguard Worker 
21*7304104dSAndroid Build Coastguard Worker    elfutils is distributed in the hope that it will be useful, but
22*7304104dSAndroid Build Coastguard Worker    WITHOUT ANY WARRANTY; without even the implied warranty of
23*7304104dSAndroid Build Coastguard Worker    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24*7304104dSAndroid Build Coastguard Worker    General Public License for more details.
25*7304104dSAndroid Build Coastguard Worker 
26*7304104dSAndroid Build Coastguard Worker    You should have received copies of the GNU General Public License and
27*7304104dSAndroid Build Coastguard Worker    the GNU Lesser General Public License along with this program.  If
28*7304104dSAndroid Build Coastguard Worker    not, see <http://www.gnu.org/licenses/>.  */
29*7304104dSAndroid Build Coastguard Worker 
30*7304104dSAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
31*7304104dSAndroid Build Coastguard Worker # include <config.h>
32*7304104dSAndroid Build Coastguard Worker #endif
33*7304104dSAndroid Build Coastguard Worker 
34*7304104dSAndroid Build Coastguard Worker #include <assert.h>
35*7304104dSAndroid Build Coastguard Worker #include <errno.h>
36*7304104dSAndroid Build Coastguard Worker #include <stdbool.h>
37*7304104dSAndroid Build Coastguard Worker #include <stdint.h>
38*7304104dSAndroid Build Coastguard Worker #include <stdlib.h>
39*7304104dSAndroid Build Coastguard Worker #include <string.h>
40*7304104dSAndroid Build Coastguard Worker 
41*7304104dSAndroid Build Coastguard Worker #include <dl-hash.h>
42*7304104dSAndroid Build Coastguard Worker #include "libelfP.h"
43*7304104dSAndroid Build Coastguard Worker 
44*7304104dSAndroid Build Coastguard Worker 
45*7304104dSAndroid Build Coastguard Worker static int
read_number_entries(uint64_t * nump,Elf * elf,size_t * offp,bool index64_p)46*7304104dSAndroid Build Coastguard Worker read_number_entries (uint64_t *nump, Elf *elf, size_t *offp, bool index64_p)
47*7304104dSAndroid Build Coastguard Worker {
48*7304104dSAndroid Build Coastguard Worker   union u
49*7304104dSAndroid Build Coastguard Worker   {
50*7304104dSAndroid Build Coastguard Worker     uint64_t ret64;
51*7304104dSAndroid Build Coastguard Worker     uint32_t ret32;
52*7304104dSAndroid Build Coastguard Worker   } u;
53*7304104dSAndroid Build Coastguard Worker 
54*7304104dSAndroid Build Coastguard Worker   size_t w = index64_p ? 8 : 4;
55*7304104dSAndroid Build Coastguard Worker   if (elf->map_address != NULL)
56*7304104dSAndroid Build Coastguard Worker     /* Use memcpy instead of pointer dereference so as not to assume the
57*7304104dSAndroid Build Coastguard Worker        field is naturally aligned within the file.  */
58*7304104dSAndroid Build Coastguard Worker     memcpy (&u, elf->map_address + *offp, sizeof u);
59*7304104dSAndroid Build Coastguard Worker   else if ((size_t) pread_retry (elf->fildes, &u, w, *offp) != w)
60*7304104dSAndroid Build Coastguard Worker     return -1;
61*7304104dSAndroid Build Coastguard Worker 
62*7304104dSAndroid Build Coastguard Worker   *offp += w;
63*7304104dSAndroid Build Coastguard Worker 
64*7304104dSAndroid Build Coastguard Worker   if (BYTE_ORDER == LITTLE_ENDIAN)
65*7304104dSAndroid Build Coastguard Worker     *nump = index64_p ? bswap_64 (u.ret64) : bswap_32 (u.ret32);
66*7304104dSAndroid Build Coastguard Worker   else
67*7304104dSAndroid Build Coastguard Worker     *nump = index64_p ? u.ret64 : u.ret32;
68*7304104dSAndroid Build Coastguard Worker 
69*7304104dSAndroid Build Coastguard Worker   return 0;
70*7304104dSAndroid Build Coastguard Worker }
71*7304104dSAndroid Build Coastguard Worker 
72*7304104dSAndroid Build Coastguard Worker Elf_Arsym *
elf_getarsym(Elf * elf,size_t * ptr)73*7304104dSAndroid Build Coastguard Worker elf_getarsym (Elf *elf, size_t *ptr)
74*7304104dSAndroid Build Coastguard Worker {
75*7304104dSAndroid Build Coastguard Worker   if (elf->kind != ELF_K_AR)
76*7304104dSAndroid Build Coastguard Worker     {
77*7304104dSAndroid Build Coastguard Worker       /* This is no archive.  */
78*7304104dSAndroid Build Coastguard Worker       __libelf_seterrno (ELF_E_NO_ARCHIVE);
79*7304104dSAndroid Build Coastguard Worker       return NULL;
80*7304104dSAndroid Build Coastguard Worker     }
81*7304104dSAndroid Build Coastguard Worker 
82*7304104dSAndroid Build Coastguard Worker   if (ptr != NULL)
83*7304104dSAndroid Build Coastguard Worker     /* In case of an error or when we know the value store the expected
84*7304104dSAndroid Build Coastguard Worker        value now.  Doing this allows us easier exits in an error case.  */
85*7304104dSAndroid Build Coastguard Worker     *ptr = elf->state.ar.ar_sym_num;
86*7304104dSAndroid Build Coastguard Worker 
87*7304104dSAndroid Build Coastguard Worker   if (elf->state.ar.ar_sym == (Elf_Arsym *) -1l)
88*7304104dSAndroid Build Coastguard Worker     {
89*7304104dSAndroid Build Coastguard Worker       /* There is no index.  */
90*7304104dSAndroid Build Coastguard Worker       __libelf_seterrno (ELF_E_NO_INDEX);
91*7304104dSAndroid Build Coastguard Worker       return NULL;
92*7304104dSAndroid Build Coastguard Worker     }
93*7304104dSAndroid Build Coastguard Worker 
94*7304104dSAndroid Build Coastguard Worker   Elf_Arsym *result = elf->state.ar.ar_sym;
95*7304104dSAndroid Build Coastguard Worker   if (result == NULL)
96*7304104dSAndroid Build Coastguard Worker     {
97*7304104dSAndroid Build Coastguard Worker       /* We have not yet read the index.  */
98*7304104dSAndroid Build Coastguard Worker       rwlock_wrlock (elf->lock);
99*7304104dSAndroid Build Coastguard Worker 
100*7304104dSAndroid Build Coastguard Worker       /* In case we find no index remember this for the next call.  */
101*7304104dSAndroid Build Coastguard Worker       elf->state.ar.ar_sym = (Elf_Arsym *) -1l;
102*7304104dSAndroid Build Coastguard Worker 
103*7304104dSAndroid Build Coastguard Worker       /* We might have to allocate some temporary data for reading.  */
104*7304104dSAndroid Build Coastguard Worker       void *temp_data = NULL;
105*7304104dSAndroid Build Coastguard Worker 
106*7304104dSAndroid Build Coastguard Worker       struct ar_hdr *index_hdr;
107*7304104dSAndroid Build Coastguard Worker       if (elf->map_address == NULL)
108*7304104dSAndroid Build Coastguard Worker 	{
109*7304104dSAndroid Build Coastguard Worker 	  /* We must read index from the file.  */
110*7304104dSAndroid Build Coastguard Worker 	  assert (elf->fildes != -1);
111*7304104dSAndroid Build Coastguard Worker 	  if (pread_retry (elf->fildes, &elf->state.ar.ar_hdr,
112*7304104dSAndroid Build Coastguard Worker 			   sizeof (struct ar_hdr), elf->start_offset + SARMAG)
113*7304104dSAndroid Build Coastguard Worker 	      != sizeof (struct ar_hdr))
114*7304104dSAndroid Build Coastguard Worker 	    {
115*7304104dSAndroid Build Coastguard Worker 	      /* It is not possible to read the index.  Maybe it does not
116*7304104dSAndroid Build Coastguard Worker 		 exist.  */
117*7304104dSAndroid Build Coastguard Worker 	      __libelf_seterrno (ELF_E_READ_ERROR);
118*7304104dSAndroid Build Coastguard Worker 	      goto out;
119*7304104dSAndroid Build Coastguard Worker 	    }
120*7304104dSAndroid Build Coastguard Worker 
121*7304104dSAndroid Build Coastguard Worker 	  index_hdr = &elf->state.ar.ar_hdr;
122*7304104dSAndroid Build Coastguard Worker 	}
123*7304104dSAndroid Build Coastguard Worker       else
124*7304104dSAndroid Build Coastguard Worker 	{
125*7304104dSAndroid Build Coastguard Worker 	  if (SARMAG + sizeof (struct ar_hdr) > elf->maximum_size)
126*7304104dSAndroid Build Coastguard Worker 	    {
127*7304104dSAndroid Build Coastguard Worker 	      /* There is no room for the full archive.  */
128*7304104dSAndroid Build Coastguard Worker 	      __libelf_seterrno (ELF_E_NO_INDEX);
129*7304104dSAndroid Build Coastguard Worker 	      goto out;
130*7304104dSAndroid Build Coastguard Worker 	    }
131*7304104dSAndroid Build Coastguard Worker 
132*7304104dSAndroid Build Coastguard Worker 	  index_hdr = (struct ar_hdr *) (elf->map_address
133*7304104dSAndroid Build Coastguard Worker 					 + elf->start_offset + SARMAG);
134*7304104dSAndroid Build Coastguard Worker 	}
135*7304104dSAndroid Build Coastguard Worker 
136*7304104dSAndroid Build Coastguard Worker       /* Now test whether this really is an archive.  */
137*7304104dSAndroid Build Coastguard Worker       if (memcmp (index_hdr->ar_fmag, ARFMAG, 2) != 0)
138*7304104dSAndroid Build Coastguard Worker 	{
139*7304104dSAndroid Build Coastguard Worker 	  /* Invalid magic bytes.  */
140*7304104dSAndroid Build Coastguard Worker 	  __libelf_seterrno (ELF_E_ARCHIVE_FMAG);
141*7304104dSAndroid Build Coastguard Worker 	  goto out;
142*7304104dSAndroid Build Coastguard Worker 	}
143*7304104dSAndroid Build Coastguard Worker 
144*7304104dSAndroid Build Coastguard Worker       bool index64_p;
145*7304104dSAndroid Build Coastguard Worker       /* Now test whether this is the index.  If the name is "/", this
146*7304104dSAndroid Build Coastguard Worker 	 is 32-bit index, if it's "/SYM64/", it's 64-bit index.
147*7304104dSAndroid Build Coastguard Worker 
148*7304104dSAndroid Build Coastguard Worker 	 XXX This is not entirely true.  There are some more forms.
149*7304104dSAndroid Build Coastguard Worker 	 Which of them shall we handle?  */
150*7304104dSAndroid Build Coastguard Worker       if (memcmp (index_hdr->ar_name, "/               ", 16) == 0)
151*7304104dSAndroid Build Coastguard Worker 	index64_p = false;
152*7304104dSAndroid Build Coastguard Worker       else if (memcmp (index_hdr->ar_name, "/SYM64/         ", 16) == 0)
153*7304104dSAndroid Build Coastguard Worker 	index64_p = true;
154*7304104dSAndroid Build Coastguard Worker       else
155*7304104dSAndroid Build Coastguard Worker 	{
156*7304104dSAndroid Build Coastguard Worker 	  /* If the index is not the first entry, there is no index.
157*7304104dSAndroid Build Coastguard Worker 
158*7304104dSAndroid Build Coastguard Worker 	     XXX Is this true?  */
159*7304104dSAndroid Build Coastguard Worker 	  __libelf_seterrno (ELF_E_NO_INDEX);
160*7304104dSAndroid Build Coastguard Worker 	  goto out;
161*7304104dSAndroid Build Coastguard Worker 	}
162*7304104dSAndroid Build Coastguard Worker       int w = index64_p ? 8 : 4;
163*7304104dSAndroid Build Coastguard Worker 
164*7304104dSAndroid Build Coastguard Worker       /* We have an archive.  The first word in there is the number of
165*7304104dSAndroid Build Coastguard Worker 	 entries in the table.  */
166*7304104dSAndroid Build Coastguard Worker       uint64_t n = 0;
167*7304104dSAndroid Build Coastguard Worker       size_t off = elf->start_offset + SARMAG + sizeof (struct ar_hdr);
168*7304104dSAndroid Build Coastguard Worker       if (read_number_entries (&n, elf, &off, index64_p) < 0)
169*7304104dSAndroid Build Coastguard Worker 	{
170*7304104dSAndroid Build Coastguard Worker 	  /* Cannot read the number of entries.  */
171*7304104dSAndroid Build Coastguard Worker 	  __libelf_seterrno (ELF_E_NO_INDEX);
172*7304104dSAndroid Build Coastguard Worker 	  goto out;
173*7304104dSAndroid Build Coastguard Worker 	}
174*7304104dSAndroid Build Coastguard Worker 
175*7304104dSAndroid Build Coastguard Worker       /* Now we can perform some first tests on whether all the data
176*7304104dSAndroid Build Coastguard Worker 	 needed for the index is available.  */
177*7304104dSAndroid Build Coastguard Worker       char tmpbuf[17];
178*7304104dSAndroid Build Coastguard Worker       memcpy (tmpbuf, index_hdr->ar_size, 10);
179*7304104dSAndroid Build Coastguard Worker       tmpbuf[10] = '\0';
180*7304104dSAndroid Build Coastguard Worker       size_t index_size = atol (tmpbuf);
181*7304104dSAndroid Build Coastguard Worker 
182*7304104dSAndroid Build Coastguard Worker       if (index_size > elf->maximum_size
183*7304104dSAndroid Build Coastguard Worker 	  || elf->maximum_size - index_size < SARMAG + sizeof (struct ar_hdr)
184*7304104dSAndroid Build Coastguard Worker #if SIZE_MAX <= 4294967295U
185*7304104dSAndroid Build Coastguard Worker 	  || n >= SIZE_MAX / sizeof (Elf_Arsym)
186*7304104dSAndroid Build Coastguard Worker #endif
187*7304104dSAndroid Build Coastguard Worker 	  || n > index_size / w)
188*7304104dSAndroid Build Coastguard Worker 	{
189*7304104dSAndroid Build Coastguard Worker 	  /* This index table cannot be right since it does not fit into
190*7304104dSAndroid Build Coastguard Worker 	     the file.  */
191*7304104dSAndroid Build Coastguard Worker 	  __libelf_seterrno (ELF_E_NO_INDEX);
192*7304104dSAndroid Build Coastguard Worker 	  goto out;
193*7304104dSAndroid Build Coastguard Worker 	}
194*7304104dSAndroid Build Coastguard Worker 
195*7304104dSAndroid Build Coastguard Worker       /* Now we can allocate the arrays needed to store the index.  */
196*7304104dSAndroid Build Coastguard Worker       size_t ar_sym_len = (n + 1) * sizeof (Elf_Arsym);
197*7304104dSAndroid Build Coastguard Worker       elf->state.ar.ar_sym = malloc (ar_sym_len);
198*7304104dSAndroid Build Coastguard Worker       if (elf->state.ar.ar_sym != NULL)
199*7304104dSAndroid Build Coastguard Worker 	{
200*7304104dSAndroid Build Coastguard Worker 	  void *file_data; /* unit32_t[n] or uint64_t[n] */
201*7304104dSAndroid Build Coastguard Worker 	  char *str_data;
202*7304104dSAndroid Build Coastguard Worker 	  size_t sz = n * w;
203*7304104dSAndroid Build Coastguard Worker 
204*7304104dSAndroid Build Coastguard Worker 	  if (elf->map_address == NULL)
205*7304104dSAndroid Build Coastguard Worker 	    {
206*7304104dSAndroid Build Coastguard Worker 	      temp_data = malloc (sz);
207*7304104dSAndroid Build Coastguard Worker 	      if (unlikely (temp_data == NULL))
208*7304104dSAndroid Build Coastguard Worker 		{
209*7304104dSAndroid Build Coastguard Worker 		  __libelf_seterrno (ELF_E_NOMEM);
210*7304104dSAndroid Build Coastguard Worker 		  goto out;
211*7304104dSAndroid Build Coastguard Worker 		}
212*7304104dSAndroid Build Coastguard Worker 	      file_data = temp_data;
213*7304104dSAndroid Build Coastguard Worker 
214*7304104dSAndroid Build Coastguard Worker 	      ar_sym_len += index_size - n * w;
215*7304104dSAndroid Build Coastguard Worker 	      Elf_Arsym *newp = realloc (elf->state.ar.ar_sym, ar_sym_len);
216*7304104dSAndroid Build Coastguard Worker 	      if (newp == NULL)
217*7304104dSAndroid Build Coastguard Worker 		{
218*7304104dSAndroid Build Coastguard Worker 		  free (elf->state.ar.ar_sym);
219*7304104dSAndroid Build Coastguard Worker 		  elf->state.ar.ar_sym = NULL;
220*7304104dSAndroid Build Coastguard Worker 		  __libelf_seterrno (ELF_E_NOMEM);
221*7304104dSAndroid Build Coastguard Worker 		  goto out;
222*7304104dSAndroid Build Coastguard Worker 		}
223*7304104dSAndroid Build Coastguard Worker 	      elf->state.ar.ar_sym = newp;
224*7304104dSAndroid Build Coastguard Worker 
225*7304104dSAndroid Build Coastguard Worker 	      char *new_str = (char *) (elf->state.ar.ar_sym + n + 1);
226*7304104dSAndroid Build Coastguard Worker 
227*7304104dSAndroid Build Coastguard Worker 	      /* Now read the data from the file.  */
228*7304104dSAndroid Build Coastguard Worker 	      if ((size_t) pread_retry (elf->fildes, file_data, sz, off) != sz
229*7304104dSAndroid Build Coastguard Worker 		  || ((size_t) pread_retry (elf->fildes, new_str,
230*7304104dSAndroid Build Coastguard Worker 					    index_size - sz, off + sz)
231*7304104dSAndroid Build Coastguard Worker 		      != index_size - sz))
232*7304104dSAndroid Build Coastguard Worker 		{
233*7304104dSAndroid Build Coastguard Worker 		  /* We were not able to read the data.  */
234*7304104dSAndroid Build Coastguard Worker 		  free (elf->state.ar.ar_sym);
235*7304104dSAndroid Build Coastguard Worker 		  elf->state.ar.ar_sym = NULL;
236*7304104dSAndroid Build Coastguard Worker 		  __libelf_seterrno (ELF_E_NO_INDEX);
237*7304104dSAndroid Build Coastguard Worker 		  goto out;
238*7304104dSAndroid Build Coastguard Worker 		}
239*7304104dSAndroid Build Coastguard Worker 
240*7304104dSAndroid Build Coastguard Worker 	      str_data = (char *) new_str;
241*7304104dSAndroid Build Coastguard Worker 	    }
242*7304104dSAndroid Build Coastguard Worker 	  else
243*7304104dSAndroid Build Coastguard Worker 	    {
244*7304104dSAndroid Build Coastguard Worker 	      file_data = (void *) (elf->map_address + off);
245*7304104dSAndroid Build Coastguard Worker 	      if (!ALLOW_UNALIGNED
246*7304104dSAndroid Build Coastguard Worker 		  && ((uintptr_t) file_data & -(uintptr_t) n) != 0)
247*7304104dSAndroid Build Coastguard Worker 		{
248*7304104dSAndroid Build Coastguard Worker 		  temp_data = malloc (sz);
249*7304104dSAndroid Build Coastguard Worker 		  if (unlikely (temp_data == NULL))
250*7304104dSAndroid Build Coastguard Worker 		    {
251*7304104dSAndroid Build Coastguard Worker 		      __libelf_seterrno (ELF_E_NOMEM);
252*7304104dSAndroid Build Coastguard Worker 		      goto out;
253*7304104dSAndroid Build Coastguard Worker 		    }
254*7304104dSAndroid Build Coastguard Worker 		  file_data = memcpy (temp_data, elf->map_address + off, sz);
255*7304104dSAndroid Build Coastguard Worker 		}
256*7304104dSAndroid Build Coastguard Worker 	      str_data = (char *) (elf->map_address + off + sz);
257*7304104dSAndroid Build Coastguard Worker 	    }
258*7304104dSAndroid Build Coastguard Worker 
259*7304104dSAndroid Build Coastguard Worker 	  /* Now we can build the data structure.  */
260*7304104dSAndroid Build Coastguard Worker 	  Elf_Arsym *arsym = elf->state.ar.ar_sym;
261*7304104dSAndroid Build Coastguard Worker 	  uint64_t (*u64)[n] = file_data;
262*7304104dSAndroid Build Coastguard Worker 	  uint32_t (*u32)[n] = file_data;
263*7304104dSAndroid Build Coastguard Worker 	  for (size_t cnt = 0; cnt < n; ++cnt)
264*7304104dSAndroid Build Coastguard Worker 	    {
265*7304104dSAndroid Build Coastguard Worker 	      arsym[cnt].as_name = str_data;
266*7304104dSAndroid Build Coastguard Worker 	      if (index64_p)
267*7304104dSAndroid Build Coastguard Worker 		{
268*7304104dSAndroid Build Coastguard Worker 		  uint64_t tmp = (*u64)[cnt];
269*7304104dSAndroid Build Coastguard Worker 		  if (BYTE_ORDER == LITTLE_ENDIAN)
270*7304104dSAndroid Build Coastguard Worker 		    tmp = bswap_64 (tmp);
271*7304104dSAndroid Build Coastguard Worker 
272*7304104dSAndroid Build Coastguard Worker 		  arsym[cnt].as_off = tmp;
273*7304104dSAndroid Build Coastguard Worker 
274*7304104dSAndroid Build Coastguard Worker 		  /* Check whether 64-bit offset fits into 32-bit
275*7304104dSAndroid Build Coastguard Worker 		     size_t.  */
276*7304104dSAndroid Build Coastguard Worker 		  if (sizeof (arsym[cnt].as_off) < 8
277*7304104dSAndroid Build Coastguard Worker 		      && arsym[cnt].as_off != tmp)
278*7304104dSAndroid Build Coastguard Worker 		    {
279*7304104dSAndroid Build Coastguard Worker 		      if (elf->map_address == NULL)
280*7304104dSAndroid Build Coastguard Worker 			{
281*7304104dSAndroid Build Coastguard Worker 			  free (elf->state.ar.ar_sym);
282*7304104dSAndroid Build Coastguard Worker 			  elf->state.ar.ar_sym = NULL;
283*7304104dSAndroid Build Coastguard Worker 			}
284*7304104dSAndroid Build Coastguard Worker 
285*7304104dSAndroid Build Coastguard Worker 		      __libelf_seterrno (ELF_E_RANGE);
286*7304104dSAndroid Build Coastguard Worker 		      goto out;
287*7304104dSAndroid Build Coastguard Worker 		    }
288*7304104dSAndroid Build Coastguard Worker 		}
289*7304104dSAndroid Build Coastguard Worker 	      else if (BYTE_ORDER == LITTLE_ENDIAN)
290*7304104dSAndroid Build Coastguard Worker 		arsym[cnt].as_off = bswap_32 ((*u32)[cnt]);
291*7304104dSAndroid Build Coastguard Worker 	      else
292*7304104dSAndroid Build Coastguard Worker 		arsym[cnt].as_off = (*u32)[cnt];
293*7304104dSAndroid Build Coastguard Worker 
294*7304104dSAndroid Build Coastguard Worker 	      arsym[cnt].as_hash = _dl_elf_hash (str_data);
295*7304104dSAndroid Build Coastguard Worker #if HAVE_DECL_RAWMEMCHR
296*7304104dSAndroid Build Coastguard Worker 	      str_data = rawmemchr (str_data, '\0') + 1;
297*7304104dSAndroid Build Coastguard Worker #else
298*7304104dSAndroid Build Coastguard Worker 	      char c;
299*7304104dSAndroid Build Coastguard Worker 	      do {
300*7304104dSAndroid Build Coastguard Worker 		c = *str_data;
301*7304104dSAndroid Build Coastguard Worker 		str_data++;
302*7304104dSAndroid Build Coastguard Worker 	      } while (c);
303*7304104dSAndroid Build Coastguard Worker #endif
304*7304104dSAndroid Build Coastguard Worker 	    }
305*7304104dSAndroid Build Coastguard Worker 
306*7304104dSAndroid Build Coastguard Worker 	  /* At the end a special entry.  */
307*7304104dSAndroid Build Coastguard Worker 	  arsym[n].as_name = NULL;
308*7304104dSAndroid Build Coastguard Worker 	  arsym[n].as_off = 0;
309*7304104dSAndroid Build Coastguard Worker 	  arsym[n].as_hash = ~0UL;
310*7304104dSAndroid Build Coastguard Worker 
311*7304104dSAndroid Build Coastguard Worker 	  /* Tell the caller how many entries we have.  */
312*7304104dSAndroid Build Coastguard Worker 	  elf->state.ar.ar_sym_num = n + 1;
313*7304104dSAndroid Build Coastguard Worker 	}
314*7304104dSAndroid Build Coastguard Worker 
315*7304104dSAndroid Build Coastguard Worker       result = elf->state.ar.ar_sym;
316*7304104dSAndroid Build Coastguard Worker 
317*7304104dSAndroid Build Coastguard Worker     out:
318*7304104dSAndroid Build Coastguard Worker       free (temp_data);
319*7304104dSAndroid Build Coastguard Worker       rwlock_unlock (elf->lock);
320*7304104dSAndroid Build Coastguard Worker     }
321*7304104dSAndroid Build Coastguard Worker 
322*7304104dSAndroid Build Coastguard Worker   if (ptr != NULL)
323*7304104dSAndroid Build Coastguard Worker     *ptr = elf->state.ar.ar_sym_num;
324*7304104dSAndroid Build Coastguard Worker 
325*7304104dSAndroid Build Coastguard Worker   return result;
326*7304104dSAndroid Build Coastguard Worker }
327