Print this page
3451 archive libraries with no symbols shouldn't require a string table
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/sgs/libelf/common/getarsym.c
+++ new/usr/src/cmd/sgs/libelf/common/getarsym.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 */
25 25
26 26 /* Copyright (c) 1988 AT&T */
27 27 /* All Rights Reserved */
28 28
29 29 #include <stdlib.h>
30 30 #include <errno.h>
31 31 #include <libelf.h>
32 32 #include "decl.h"
33 33 #include "msg.h"
34 34
35 35
36 36 /*
37 37 * Convert archive symbol table to memory format
38 38 *
39 39 * This takes a pointer to file's archive symbol table, alignment
40 40 * unconstrained. Returns null terminated vector of Elf_Arsym
41 41 * structures. Elf_Arsym uses size_t to represent offsets, which
42 42 * will be 32-bit in 32-bit versions, and 64-bits otherwise.
43 43 *
44 44 * There are two forms of archive symbol table, the original 32-bit
45 45 * form, and a 64-bit form originally found in IRIX64. The two formats
46 46 * differ only in the width of the integer word:
47 47 *
48 48 * # offsets 4/8-byte word
49 49 * offset[0...] 4/8-byte word each
50 50 * strings null-terminated, for offset[x]
51 51 *
52 52 * By default, the 64-bit form is only used when the archive exceeds
53 53 * the limits of 32-bits (4GB) in size. However, this is not required,
54 54 * and the ar -S option can be used to create a 64-bit symbol table in
55 55 * an archive that is under 4GB.
56 56 *
57 57 * Both 32 and 64-bit versions of libelf can read the 32-bit format
58 58 * without loss of information. Similarly, a 64-bit version of libelf
59 59 * will have no problem reading a 64-bit symbol table. This leaves the
60 60 * case where a 32-bit libelf reads a 64-bit symbol table, which requires
61 61 * some explanation. The offsets in a 64-bit symbol table will have zeros
62 62 * in the upper half of the words until the size of the archive exceeds 4GB.
63 63 * However, 32-bit libelf is unable to read any files larger than 2GB
64 64 * (see comments in update.c). As such, any archive that the 32-bit version
65 65 * of this code will encounter will be under 4GB in size. The upper 4
66 66 * bytes of each word will be zero, and can be safely ignored.
67 67 */
68 68
69 69
70 70 /*
71 71 * Offsets in archive headers are written in MSB (large endian) order
72 72 * on all platforms, regardless of native byte order. These macros read
73 73 * 4 and 8 byte values from unaligned memory.
74 74 *
75 75 * note:
76 76 * - The get8() macro for 32-bit code can ignore the first 4 bytes of
77 77 * of the word, because they are known to be 0.
78 78 *
79 79 * - The inner most value in these macros is cast to an unsigned integer
80 80 * of the final width in order to prevent the C comilier from doing
81 81 * unwanted sign extension when the topmost bit of a byte is set.
82 82 */
83 83 #define get4(p) (((((((uint32_t)p[0]<<8)+p[1])<<8)+p[2])<<8)+p[3])
84 84
85 85 #ifdef _LP64
86 86 #define get8(p) (((((((((((((((uint64_t)p[0]<<8)+p[1])<<8)+p[2])<<8)+ \
87 87 p[3])<<8)+p[4])<<8)+p[5])<<8)+p[6])<<8)+p[7])
88 88 #else
89 89 #define get8(p) (((((((uint64_t)p[4]<<8)+p[5])<<8)+p[6])<<8)+p[7])
90 90 #endif
91 91
92 92
93 93 static Elf_Void *
94 94 arsym(Byte *off, size_t sz, size_t *e, int is64)
95 95 {
96 96 char *endstr = (char *)off + sz;
97 97 register char *str;
↓ open down ↓ |
97 lines elided |
↑ open up ↑ |
98 98 Byte *endoff;
99 99 Elf_Void *oas;
100 100 size_t eltsize = is64 ? 8 : 4;
101 101
102 102 {
103 103 register size_t n;
104 104
105 105 if (is64) {
106 106 if (sz < 8 || (sz - 8) / 8 < (n = get8(off))) {
107 107 _elf_seterr(EFMT_ARSYMSZ, 0);
108 - return (0);
108 + return (NULL);
109 109 }
110 110 } else {
111 111 if (sz < 4 || (sz - 4) / 4 < (n = get4(off))) {
112 112 _elf_seterr(EFMT_ARSYMSZ, 0);
113 - return (0);
113 + return (NULL);
114 114 }
115 115 }
116 116 off += eltsize;
117 117 endoff = off + n * eltsize;
118 118
119 119 /*
120 - * string table must be present, null terminated
120 + * If there are symbols in the symbol table, a
121 + * string table must be present and NULL terminated.
122 + *
123 + * The format dictates that the string table must always be
124 + * present, however in the case of an archive containing no
125 + * symbols GNU ar will not create one. We are permissive for
126 + * the sake of compatibility.
121 127 */
122 -
123 - if (((str = (char *)endoff) >= endstr) ||
124 - (*(endstr - 1) != '\0')) {
128 + if ((n > 0) && (((str = (char *)endoff) >= endstr) ||
129 + (*(endstr - 1) != '\0'))) {
125 130 _elf_seterr(EFMT_ARSYM, 0);
126 - return (0);
131 + return (NULL);
127 132 }
128 133
129 134 /*
135 + * There is always at least one entry returned if a symtab
136 + * exists since the table's last entry is an artificial one
137 + * with a NULL as_name, but is included in the count.
138 + *
130 139 * overflow can occur here, but not likely
131 140 */
132 -
133 141 *e = n + 1;
134 - n = sizeof (Elf_Arsym) * (n + 1);
135 - if ((oas = malloc(n)) == 0) {
142 + if ((oas = calloc(n + 1, sizeof (Elf_Arsym))) == NULL) {
136 143 _elf_seterr(EMEM_ARSYM, errno);
137 - return (0);
144 + return (NULL);
138 145 }
139 146 }
140 147 {
141 148 register Elf_Arsym *as = (Elf_Arsym *)oas;
142 149
143 150 while (off < endoff) {
144 151 if (str >= endstr) {
145 152 _elf_seterr(EFMT_ARSYMSTR, 0);
146 153 free(oas);
147 - return (0);
154 + return (NULL);
148 155 }
149 156 if (is64)
150 157 as->as_off = get8(off);
151 158 else
152 159 as->as_off = get4(off);
153 160 as->as_name = str;
154 161 as->as_hash = elf_hash(str);
155 162 ++as;
156 163 off += eltsize;
157 164 while (*str++ != '\0')
158 165 /* LINTED */
159 166 ;
160 167 }
161 - as->as_name = 0;
168 + as->as_name = NULL;
162 169 as->as_off = 0;
163 170 as->as_hash = ~(unsigned long)0L;
164 171 }
165 172 return (oas);
166 173 }
167 174
168 175
169 176 Elf_Arsym *
170 177 elf_getarsym(Elf *elf, size_t *ptr)
171 178 {
172 179 Byte *as;
173 180 size_t sz;
174 181 Elf_Arsym *rc;
175 182 int is64;
176 183
177 184 if (ptr != 0)
178 185 *ptr = 0;
179 186 if (elf == NULL)
180 187 return (0);
181 188 ELFRLOCK(elf);
182 189 if (elf->ed_kind != ELF_K_AR) {
183 190 ELFUNLOCK(elf);
184 191 _elf_seterr(EREQ_AR, 0);
185 192 return (0);
186 193 }
187 194 if ((as = (Byte *)elf->ed_arsym) == 0) {
188 195 ELFUNLOCK(elf);
189 196 return (0);
190 197 }
191 198 if (elf->ed_myflags & EDF_ASALLOC) {
192 199 if (ptr != 0)
193 200 *ptr = elf->ed_arsymsz;
194 201 ELFUNLOCK(elf);
195 202 /* LINTED */
196 203 return ((Elf_Arsym *)as);
197 204 }
198 205 is64 = (elf->ed_myflags & EDF_ARSYM64) != 0;
199 206
200 207 /*
201 208 * We're gonna need a write lock.
202 209 */
203 210 ELFUNLOCK(elf)
204 211 ELFWLOCK(elf)
205 212 sz = elf->ed_arsymsz;
206 213 if (_elf_vm(elf, (size_t)(as - (Byte *)elf->ed_ident), sz) !=
207 214 OK_YES) {
208 215 ELFUNLOCK(elf);
209 216 return (0);
210 217 }
211 218 if ((elf->ed_arsym = arsym(as, sz, &elf->ed_arsymsz, is64)) == 0) {
212 219 ELFUNLOCK(elf);
213 220 return (0);
214 221 }
215 222 elf->ed_myflags |= EDF_ASALLOC;
216 223 if (ptr != 0)
217 224 *ptr = elf->ed_arsymsz;
218 225 rc = (Elf_Arsym *)elf->ed_arsym;
219 226 ELFUNLOCK(elf);
220 227 return (rc);
221 228 }
222 229
223 230 /*
224 231 * Private function to obtain the value sizeof() would return
225 232 * for a word from the symbol table from the given archive. Normally,
226 233 * this is an unimportant implementation detail hidden within
227 234 * elf_getarsym(). However, it is useful to elfdump for formatting the
228 235 * output correctly, and for the file command.
229 236 *
230 237 * exit:
231 238 * Returns 4 (32-bit) or 8 (64-bit) if a symbol table is present.
232 239 * Returns 0 in all other cases.
233 240 */
234 241 size_t
235 242 _elf_getarsymwordsize(Elf *elf)
236 243 {
237 244 size_t size;
238 245
239 246 if (elf == NULL)
240 247 return (0);
241 248
242 249 ELFRLOCK(elf);
243 250 if ((elf->ed_kind == ELF_K_AR) && (elf->ed_arsym != 0))
244 251 size = (elf->ed_myflags & EDF_ARSYM64) ? 8 : 4;
245 252 else
246 253 size = 0;
247 254 ELFUNLOCK(elf);
248 255
249 256 return (size);
250 257 }
↓ open down ↓ |
79 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX