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