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