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 34Elf_Arsym * 35elf_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