1 /* Return symbol table of archive.
2 Copyright (C) 1998-2000, 2002, 2005, 2012 Red Hat, Inc.
3 This file is part of elfutils.
4 Written by Ulrich Drepper <drepper@redhat.com>, 1998.
6 This file is free software; you can redistribute it and/or modify
7 it under the terms of either
9 * the GNU Lesser General Public License as published by the Free
10 Software Foundation; either version 3 of the License, or (at
11 your option) any later version
15 * the GNU General Public License as published by the Free
16 Software Foundation; either version 2 of the License, or (at
17 your option) any later version
19 or both in parallel, as here.
21 elfutils is distributed in the hope that it will be useful, but
22 WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 General Public License for more details.
26 You should have received copies of the GNU General Public License and
27 the GNU Lesser General Public License along with this program. If
28 not, see <http://www.gnu.org/licenses/>. */
50 read_number_entries (uint64_t *nump, Elf *elf, size_t *offp, bool index64_p)
58 size_t w = index64_p ? 8 : 4;
59 if (elf->map_address != NULL)
60 u = *(union u *) (elf->map_address + *offp);
61 else if ((size_t) pread_retry (elf->fildes, &u, w, *offp) != w)
66 if (__BYTE_ORDER == __LITTLE_ENDIAN)
67 *nump = index64_p ? bswap_64 (u.ret64) : bswap_32 (u.ret32);
69 *nump = index64_p ? u.ret64 : u.ret32;
75 elf_getarsym (elf, ptr)
79 if (elf->kind != ELF_K_AR)
81 /* This is no archive. */
82 __libelf_seterrno (ELF_E_NO_ARCHIVE);
87 /* In case of an error or when we know the value store the expected
88 value now. Doing this allows us easier exits in an error case. */
89 *ptr = elf->state.ar.ar_sym_num;
91 if (elf->state.ar.ar_sym == (Elf_Arsym *) -1l)
93 /* There is no index. */
94 __libelf_seterrno (ELF_E_NO_INDEX);
98 Elf_Arsym *result = elf->state.ar.ar_sym;
101 /* We have not yet read the index. */
102 rwlock_wrlock (elf->lock);
104 /* In case we find no index remember this for the next call. */
105 elf->state.ar.ar_sym = (Elf_Arsym *) -1l;
107 struct ar_hdr *index_hdr;
108 if (elf->map_address == NULL)
110 /* We must read index from the file. */
111 assert (elf->fildes != -1);
112 if (pread_retry (elf->fildes, &elf->state.ar.ar_hdr,
113 sizeof (struct ar_hdr), elf->start_offset + SARMAG)
114 != sizeof (struct ar_hdr))
116 /* It is not possible to read the index. Maybe it does not
118 __libelf_seterrno (ELF_E_READ_ERROR);
122 index_hdr = &elf->state.ar.ar_hdr;
126 if (SARMAG + sizeof (struct ar_hdr) > elf->maximum_size)
128 /* There is no room for the full archive. */
129 __libelf_seterrno (ELF_E_NO_INDEX);
133 index_hdr = (struct ar_hdr *) (elf->map_address
134 + elf->start_offset + SARMAG);
137 /* Now test whether this really is an archive. */
138 if (memcmp (index_hdr->ar_fmag, ARFMAG, 2) != 0)
140 /* Invalid magic bytes. */
141 __libelf_seterrno (ELF_E_ARCHIVE_FMAG);
146 /* Now test whether this is the index. If the name is "/", this
147 is 32-bit index, if it's "/SYM64/", it's 64-bit index.
149 XXX This is not entirely true. There are some more forms.
150 Which of them shall we handle? */
151 if (memcmp (index_hdr->ar_name, "/ ", 16) == 0)
153 else if (memcmp (index_hdr->ar_name, "/SYM64/ ", 16) == 0)
157 /* If the index is not the first entry, there is no index.
160 __libelf_seterrno (ELF_E_NO_INDEX);
163 int w = index64_p ? 8 : 4;
165 /* We have an archive. The first word in there is the number of
166 entries in the table. */
168 size_t off = elf->start_offset + SARMAG + sizeof (struct ar_hdr);
169 if (read_number_entries (&n, elf, &off, index64_p) < 0)
171 /* Cannot read the number of entries. */
172 __libelf_seterrno (ELF_E_NO_INDEX);
176 /* Now we can perform some first tests on whether all the data
177 needed for the index is available. */
179 memcpy (tmpbuf, index_hdr->ar_size, 10);
181 size_t index_size = atol (tmpbuf);
183 if (SARMAG + sizeof (struct ar_hdr) + index_size > elf->maximum_size
184 || n * w > index_size)
186 /* This index table cannot be right since it does not fit into
188 __libelf_seterrno (ELF_E_NO_INDEX);
192 /* Now we can allocate the arrays needed to store the index. */
193 size_t ar_sym_len = (n + 1) * sizeof (Elf_Arsym);
194 elf->state.ar.ar_sym = (Elf_Arsym *) malloc (ar_sym_len);
195 if (elf->state.ar.ar_sym != NULL)
205 if (elf->map_address == NULL)
207 file_data = alloca (sz);
209 ar_sym_len += index_size - n * w;
210 Elf_Arsym *newp = (Elf_Arsym *) realloc (elf->state.ar.ar_sym,
214 free (elf->state.ar.ar_sym);
215 elf->state.ar.ar_sym = NULL;
216 __libelf_seterrno (ELF_E_NOMEM);
219 elf->state.ar.ar_sym = newp;
221 char *new_str = (char *) (elf->state.ar.ar_sym + n + 1);
223 /* Now read the data from the file. */
224 if ((size_t) pread_retry (elf->fildes, file_data, sz, off) != sz
225 || ((size_t) pread_retry (elf->fildes, new_str,
226 index_size - sz, off + sz)
229 /* We were not able to read the data. */
230 free (elf->state.ar.ar_sym);
231 elf->state.ar.ar_sym = NULL;
232 __libelf_seterrno (ELF_E_NO_INDEX);
236 str_data = (char *) new_str;
240 file_data = (void *) (elf->map_address + off);
241 str_data = (char *) (elf->map_address + off + sz);
244 /* Now we can build the data structure. */
245 Elf_Arsym *arsym = elf->state.ar.ar_sym;
246 for (size_t cnt = 0; cnt < n; ++cnt)
248 arsym[cnt].as_name = str_data;
251 uint64_t tmp = file_data->u64[cnt];
252 if (__BYTE_ORDER == __LITTLE_ENDIAN)
253 tmp = bswap_64 (tmp);
255 arsym[cnt].as_off = tmp;
257 /* Check whether 64-bit offset fits into 32-bit
259 if (sizeof (arsym[cnt].as_off) < 8
260 && arsym[cnt].as_off != tmp)
262 if (elf->map_address == NULL)
264 free (elf->state.ar.ar_sym);
265 elf->state.ar.ar_sym = NULL;
268 __libelf_seterrno (ELF_E_RANGE);
272 else if (__BYTE_ORDER == __LITTLE_ENDIAN)
273 arsym[cnt].as_off = bswap_32 (file_data->u32[cnt]);
275 arsym[cnt].as_off = file_data->u32[cnt];
277 arsym[cnt].as_hash = _dl_elf_hash (str_data);
278 str_data = rawmemchr (str_data, '\0') + 1;
281 /* At the end a special entry. */
282 arsym[n].as_name = NULL;
284 arsym[n].as_hash = ~0UL;
286 /* Tell the caller how many entries we have. */
287 elf->state.ar.ar_sym_num = n + 1;
290 result = elf->state.ar.ar_sym;
293 rwlock_unlock (elf->lock);
297 *ptr = elf->state.ar.ar_sym_num;