• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Return symbol table of archive.
2    Copyright (C) 1998, 1999, 2000, 2002 Red Hat, Inc.
3    Written by Ulrich Drepper <drepper@redhat.com>, 1998.
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation, version 2.
8 
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software Foundation,
16    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
17 
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21 
22 #include <assert.h>
23 //#include <byteswap.h>
24 //#include <endian.h>
25 #include <stdint.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29 
30 #include <dl-hash.h>
31 #include "libelfP.h"
32 
33 
34 Elf_Arsym *
elf_getarsym(elf,ptr)35 elf_getarsym (elf, ptr)
36      Elf *elf;
37      size_t *ptr;
38 {
39   Elf_Arsym *result;
40 
41   if (elf->kind != ELF_K_AR)
42     {
43       /* This is no archive.  */
44       __libelf_seterrno (ELF_E_NO_ARCHIVE);
45       return NULL;
46     }
47 
48   if (ptr != NULL)
49     /* In case of an error or when we know the value store the expected
50        value now.  Doing this allows us easier exits in an error case.  */
51     *ptr = elf->state.ar.ar_sym_num;
52 
53   if (elf->state.ar.ar_sym == (Elf_Arsym *) -1l)
54     {
55       /* There is no index.  */
56       __libelf_seterrno (ELF_E_NO_INDEX);
57       return NULL;
58     }
59 
60   result = elf->state.ar.ar_sym;
61   if (result == NULL)
62     {
63       /* We have not yet read the index.  */
64       struct ar_hdr *index_hdr;
65       uint32_t n;
66       size_t index_size;
67       char tmpbuf[17];
68       size_t ar_sym_len;
69       Elf_Arsym *arsym;
70       size_t cnt;
71 
72       rwlock_wrlock (elf->lock);
73 
74       /* In case we find no index remember this for the next call.  */
75       elf->state.ar.ar_sym = (Elf_Arsym *) -1l;
76 
77       if (elf->map_address == NULL)
78 	{
79 	  /* We must read index from the file.  */
80 	  assert (elf->fildes != -1);
81 	  if (pread (elf->fildes, &elf->state.ar.ar_hdr,
82 		     sizeof (struct ar_hdr), elf->start_offset + SARMAG)
83 	      != sizeof (struct ar_hdr))
84 	    {
85 	      /* It is not possible to read the index.  Maybe it does not
86 		 exist.  */
87 	      __libelf_seterrno (ELF_E_READ_ERROR);
88 	      goto out;
89 	    }
90 
91 	  index_hdr = &elf->state.ar.ar_hdr;
92 	}
93       else
94 	{
95 	  if (SARMAG + sizeof (struct ar_hdr) > elf->maximum_size)
96 	    {
97 	      /* There is no room for the full archive.  */
98 	      __libelf_seterrno (ELF_E_NO_INDEX);
99 	      goto out;
100 	    }
101 
102 	  index_hdr = (struct ar_hdr *) (elf->map_address
103 					 + elf->start_offset + SARMAG);
104 	}
105 
106       /* Now test whether this really is an archive.  */
107       if (memcmp (index_hdr->ar_fmag, ARFMAG, 2) != 0)
108 	{
109 	  /* Invalid magic bytes.  */
110 	  __libelf_seterrno (ELF_E_ARCHIVE_FMAG);
111 	  goto out;
112 	}
113 
114       /* Now test whether this is the index.  It is denoted by the
115 	 name being "/ ".
116 	 XXX This is not entirely true.  There are some more forms.
117 	 Which of them shall we handle?  */
118       if (memcmp (index_hdr->ar_name, "/               ", 16) != 0)
119 	{
120 	  /* If the index is not the first entry, there is no index.
121 
122 	     XXX Is this true?  */
123 	  __libelf_seterrno (ELF_E_NO_INDEX);
124 	  goto out;
125 	}
126 
127       /* We have an archive.  The first word in there is the number of
128 	 entries in the table.  */
129       if (elf->map_address == NULL)
130 	{
131 	  if (pread (elf->fildes, &n, sizeof (n),
132 		     elf->start_offset + SARMAG + sizeof (struct ar_hdr))
133 	      != sizeof (n))
134 	    {
135 	      /* Cannot read the number of entries.  */
136 	      __libelf_seterrno (ELF_E_NO_INDEX);
137 	      goto out;
138 	    }
139 	}
140       else
141 	n = *(uint32_t *) (elf->map_address + elf->start_offset
142 			   + SARMAG + sizeof (struct ar_hdr));
143 
144       if (__BYTE_ORDER == __LITTLE_ENDIAN)
145 	n = bswap_32 (n);
146 
147       /* Now we can perform some first tests on whether all the data
148 	 needed for the index is available.  */
149       memcpy (tmpbuf, index_hdr->ar_size, 10);
150       tmpbuf[10] = '\0';
151       index_size = atol (tmpbuf);
152 
153       if (SARMAG + sizeof (struct ar_hdr) + index_size > elf->maximum_size
154 	  || n * sizeof (uint32_t) > index_size)
155 	{
156 	  /* This index table cannot be right since it does not fit into
157 	     the file.  */
158 	  __libelf_seterrno (ELF_E_NO_INDEX);
159 	  goto out;
160 	}
161 
162       /* Now we can allocate the arrays needed to store the index.  */
163       ar_sym_len = (n + 1) * sizeof (Elf_Arsym);
164       elf->state.ar.ar_sym = (Elf_Arsym *) malloc (ar_sym_len);
165       if (elf->state.ar.ar_sym != NULL)
166 	{
167 	  uint32_t *file_data;
168 	  char *str_data;
169 
170 	  if (elf->map_address == NULL)
171 	    {
172 	      char *new_str;
173 	      Elf_Arsym *newp;
174 
175 	      file_data = (uint32_t *) alloca (n * sizeof (uint32_t));
176 
177 	      ar_sym_len += index_size - n * sizeof (uint32_t);
178 	      newp = (Elf_Arsym *) realloc (elf->state.ar.ar_sym,
179 					    ar_sym_len);
180 	      if (newp == NULL)
181 		{
182 		  free (elf->state.ar.ar_sym);
183 		  elf->state.ar.ar_sym = NULL;
184 		  __libelf_seterrno (ELF_E_NOMEM);
185 		  goto out;
186 		}
187 	      elf->state.ar.ar_sym = newp;
188 
189 	      new_str = (char *) (elf->state.ar.ar_sym + n + 1);
190 
191 	      /* Now read the data from the file.  */
192 	      if ((size_t) pread (elf->fildes, file_data,
193 				  n * sizeof (uint32_t), elf->start_offset
194 				  + SARMAG + sizeof (struct ar_hdr)
195 				  + sizeof (uint32_t)) != n * sizeof (uint32_t)
196 		  || ((size_t) pread (elf->fildes, new_str,
197 				      index_size - n * sizeof (uint32_t),
198 				      elf->start_offset
199 				      + SARMAG + sizeof (struct ar_hdr)
200 				      + (n + 1) * sizeof (uint32_t))
201 		      != index_size - n * sizeof (uint32_t)))
202 		{
203 		  /* We were not able to read the data.  */
204 		  free (elf->state.ar.ar_sym);
205 		  elf->state.ar.ar_sym = NULL;
206 		  __libelf_seterrno (ELF_E_NO_INDEX);
207 		  goto out;
208 		}
209 
210 	      str_data = (char *) new_str;
211 	    }
212 	  else
213 	    {
214 	      file_data = (uint32_t *) (elf->map_address + elf->start_offset
215 					+ SARMAG + sizeof (struct ar_hdr)
216 					+ sizeof (uint32_t));
217 	      str_data = (char *) &file_data[n];
218 	    }
219 
220 	  /* Now we can build the data structure.  */
221 	  arsym = elf->state.ar.ar_sym;
222 	  for (cnt = 0; cnt < n; ++cnt)
223 	    {
224 	      arsym[cnt].as_name = str_data;
225 	      if (__BYTE_ORDER == __LITTLE_ENDIAN)
226 		arsym[cnt].as_off = bswap_32 (file_data[cnt]);
227 	      else
228 		arsym[cnt].as_off = file_data[cnt];
229 	      arsym[cnt].as_hash = _dl_elf_hash (str_data);
230 	      str_data = rawmemchr (str_data, '\0') + 1;
231 	    }
232 	  /* At the end a special entry.  */
233 	  arsym[n].as_name = NULL;
234 	  arsym[n].as_off = 0;
235 	  arsym[n].as_hash = ~0UL;
236 
237 	  /* Tell the caller how many entries we have.  */
238 	  elf->state.ar.ar_sym_num = n + 1;
239 	}
240 
241       result = elf->state.ar.ar_sym;
242 
243     out:
244       rwlock_unlock (elf->lock);
245     }
246 
247   if (ptr != NULL)
248     *ptr = elf->state.ar.ar_sym_num;
249 
250   return result;
251 }
252