|
1 /* |
|
2 * getarsym.c - implementation of the elf_getarsym(3) function. |
|
3 * Copyright (C) 1995 - 1998, 2004 Michael Riepe |
|
4 * |
|
5 * This library is free software; you can redistribute it and/or |
|
6 * modify it under the terms of the GNU Library General Public |
|
7 * License as published by the Free Software Foundation; either |
|
8 * version 2 of the License, or (at your option) any later version. |
|
9 * |
|
10 * This library is distributed in the hope that it will be useful, |
|
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
13 * Library General Public License for more details. |
|
14 * |
|
15 * You should have received a copy of the GNU Library General Public |
|
16 * License along with this library; if not, write to the Free Software |
|
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
18 */ |
|
19 |
|
20 #include <private.h> |
|
21 #include <byteswap.h> |
|
22 |
|
23 #ifndef lint |
|
24 static const char rcsid[] = "@(#) $Id: getarsym.c,v 1.8 2005/05/21 15:39:23 michael Exp $"; |
|
25 #endif /* lint */ |
|
26 |
|
27 Elf_Arsym* |
|
28 elf_getarsym(Elf *elf, size_t *ptr) { |
|
29 Elf_Arsym *syms; |
|
30 size_t count; |
|
31 size_t tmp; |
|
32 size_t i; |
|
33 char *s; |
|
34 char *e; |
|
35 |
|
36 if (!ptr) { |
|
37 ptr = &tmp; |
|
38 } |
|
39 *ptr = 0; |
|
40 if (!elf) { |
|
41 return NULL; |
|
42 } |
|
43 elf_assert(elf->e_magic == ELF_MAGIC); |
|
44 if (elf->e_kind != ELF_K_AR) { |
|
45 seterr(ERROR_NOTARCHIVE); |
|
46 return NULL; |
|
47 } |
|
48 if (elf->e_symtab && !elf->e_free_syms) { |
|
49 if (elf->e_symlen < 4) { |
|
50 seterr(ERROR_SIZE_ARSYMTAB); |
|
51 return NULL; |
|
52 } |
|
53 count = __load_u32M(elf->e_symtab); |
|
54 if (elf->e_symlen < 4 * (count + 1)) { |
|
55 seterr(ERROR_SIZE_ARSYMTAB); |
|
56 return NULL; |
|
57 } |
|
58 if (!(syms = (Elf_Arsym*)malloc((count + 1) * sizeof(*syms)))) { |
|
59 seterr(ERROR_MEM_ARSYMTAB); |
|
60 return NULL; |
|
61 } |
|
62 s = elf->e_symtab + 4 * (count + 1); |
|
63 e = elf->e_symtab + elf->e_symlen; |
|
64 for (i = 0; i < count; i++, s++) { |
|
65 syms[i].as_name = s; |
|
66 while (s < e && *s) { |
|
67 s++; |
|
68 } |
|
69 if (s >= e) { |
|
70 seterr(ERROR_SIZE_ARSYMTAB); |
|
71 free(syms); |
|
72 return NULL; |
|
73 } |
|
74 elf_assert(!*s); |
|
75 syms[i].as_hash = elf_hash((unsigned char*)syms[i].as_name); |
|
76 syms[i].as_off = __load_u32M(elf->e_symtab + 4 * (i + 1)); |
|
77 } |
|
78 syms[count].as_name = NULL; |
|
79 syms[count].as_hash = ~0UL; |
|
80 syms[count].as_off = 0; |
|
81 elf->e_symtab = (char*)syms; |
|
82 elf->e_symlen = count + 1; |
|
83 elf->e_free_syms = 1; |
|
84 } |
|
85 *ptr = elf->e_symlen; |
|
86 return (Elf_Arsym*)elf->e_symtab; |
|
87 } |