4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
27 * Copyright (c) 1988 AT&T
45 * When processing an archive member, two things can happen
46 * that are a little tricky.
49 * Sliding support is left in for backward compatibility and for
50 * support of Archives produced on other systems. The bundled
51 * ar(1) produces archives with all members on a 4 byte boundry,
52 * so current archives should need no sliding.
54 * Archive members that are only 2-byte aligned within the file will
55 * be slid. To reuse the file's memory image, the library slides an
56 * archive member into its header to align the bytes. This means
57 * the header must be disposable.
60 * Because the library can trample the header, it must be preserved to
61 * avoid restrictions on archive member reuse. That is, if the member
62 * header changes, the library may see garbage the next time it looks
63 * at the header. After extracting the original header, the library
64 * appends it to the parents `ed_memlist' list, thus future lookups first
65 * check this list to determine if a member has previously been processed
66 * and whether sliding occured.
72 * If the header is too small, the following generates a negative
73 * subscript for x.x and fails to compile.
75 * The check is based on sizeof (Elf64) because that's always going
76 * to be at least as big as Elf32.
81 char x
[sizeof (struct ar_hdr
) - 3 * sizeof (Elf64
) - 1];
86 static const char fmag
[] = ARFMAG
;
90 * Convert a string starting at 'p' and ending at 'end' into
91 * an integer. Base is the base of the number being converted
94 * Returns the converted integer of the string being scaned.
97 _elf_number(char *p
, char *end
, int base
)
100 register unsigned long n
= 0;
103 if ((c
= *p
- '0') >= base
) {
118 * Convert ar_hdr to Member
119 * Converts ascii file representation to the binary memory values.
122 _elf_armem(Elf
*elf
, char *file
, size_t fsz
)
124 register struct ar_hdr
*f
= (struct ar_hdr
*)file
;
126 register Memlist
*l
, * ol
;
127 register Memident
*i
;
129 if (fsz
< sizeof (struct ar_hdr
)) {
130 _elf_seterr(EFMT_ARHDRSZ
, 0);
135 * Determine in this member has already been processed
137 for (l
= elf
->ed_memlist
, ol
= l
; l
; ol
= l
, l
= l
->m_next
)
138 for (i
= (Memident
*)(l
+ 1); i
< l
->m_free
; i
++)
139 if (i
->m_offset
== file
)
140 return (i
->m_member
);
142 if (f
->ar_fmag
[0] != fmag
[0] || f
->ar_fmag
[1] != fmag
[1]) {
143 _elf_seterr(EFMT_ARFMAG
, 0);
148 * Allocate a new member structure and assign it to the next free
149 * free memlist ident.
151 if ((m
= (Member
*)malloc(sizeof (Member
))) == 0) {
152 _elf_seterr(EMEM_ARMEM
, errno
);
155 if ((elf
->ed_memlist
== 0) || (ol
->m_free
== ol
->m_end
)) {
156 if ((l
= (Memlist
*)malloc(sizeof (Memlist
) +
157 (sizeof (Memident
) * MEMIDENTNO
))) == 0) {
158 _elf_seterr(EMEM_ARMEM
, errno
);
162 l
->m_free
= (Memident
*)(l
+ 1);
163 l
->m_end
= (Memident
*)((uintptr_t)l
->m_free
+
164 (sizeof (Memident
) * MEMIDENTNO
));
166 if (elf
->ed_memlist
== 0)
172 ol
->m_free
->m_offset
= file
;
173 ol
->m_free
->m_member
= m
;
177 (void) memcpy(m
->m_name
, f
->ar_name
, ARSZ(ar_name
));
178 m
->m_name
[ARSZ(ar_name
)] = '\0';
179 m
->m_hdr
.ar_name
= m
->m_name
;
180 (void) memcpy(m
->m_raw
, f
->ar_name
, ARSZ(ar_name
));
181 m
->m_raw
[ARSZ(ar_name
)] = '\0';
182 m
->m_hdr
.ar_rawname
= m
->m_raw
;
186 * Classify file name.
187 * If a name error occurs, delay until getarhdr().
190 if (f
->ar_name
[0] != '/') { /* regular name */
193 p
= &m
->m_name
[sizeof (m
->m_name
)];
198 } else if (f
->ar_name
[1] >= '0' && f
->ar_name
[1] <= '9') { /* strtab */
199 register unsigned long j
;
201 j
= _elf_number(&f
->ar_name
[1],
202 &f
->ar_name
[ARSZ(ar_name
)], 10);
203 if (j
< elf
->ed_arstrsz
)
204 m
->m_hdr
.ar_name
= elf
->ed_arstr
+ j
;
206 m
->m_hdr
.ar_name
= 0;
207 /*LINTED*/ /* MSG_INTL(EFMT_ARSTRNM) */
208 m
->m_err
= (int)EFMT_ARSTRNM
;
210 } else if (f
->ar_name
[1] == ' ') /* "/" */
212 else if (f
->ar_name
[1] == '/' && f
->ar_name
[2] == ' ') /* "//" */
214 else if (f
->ar_name
[1] == 'S' && f
->ar_name
[2] == 'Y' &&
215 f
->ar_name
[3] == 'M' && f
->ar_name
[4] == '6' &&
216 f
->ar_name
[5] == '4' && f
->ar_name
[6] == '/' &&
217 f
->ar_name
[7] == ' ') /* "/SYM64/" */
220 m
->m_hdr
.ar_name
= 0;
221 /*LINTED*/ /* MSG_INTL(EFMT_ARUNKNM) */
222 m
->m_err
= (int)EFMT_ARUNKNM
;
225 m
->m_hdr
.ar_date
= (time_t)_elf_number(f
->ar_date
,
226 &f
->ar_date
[ARSZ(ar_date
)], 10);
228 m
->m_hdr
.ar_uid
= (uid_t
)_elf_number(f
->ar_uid
,
229 &f
->ar_uid
[ARSZ(ar_uid
)], 10);
231 m
->m_hdr
.ar_gid
= (gid_t
)_elf_number(f
->ar_gid
,
232 &f
->ar_gid
[ARSZ(ar_gid
)], 10);
234 m
->m_hdr
.ar_mode
= (mode_t
)_elf_number(f
->ar_mode
,
235 &f
->ar_mode
[ARSZ(ar_mode
)], 8);
236 m
->m_hdr
.ar_size
= (off_t
)_elf_number(f
->ar_size
,
237 &f
->ar_size
[ARSZ(ar_size
)], 10);
244 * Initial archive processing
245 * An archive may have two special members.
247 * A symbol table, named / or /SYM64/, must be first if it is present.
248 * Both forms use the same layout differing in the width of the
249 * integer type used (32 or 64-bit respectively).
251 * A long name string table, named //, must precede all "normal"
252 * members. This string table is used to hold the names of archive
253 * members with names that are longer than 15 characters. It should not
254 * be confused with the string table found at the end of the symbol
255 * table, which is used to hold symbol names.
257 * This code "peeks" at headers but doesn't change them.
258 * Later processing wants original headers.
260 * String table is converted, changing '/' name terminators
261 * to nulls. The last byte in the string table, which should
262 * be '\n', is set to nil, guaranteeing null termination. That
263 * byte should be '\n', but this code doesn't check.
265 * The symbol table conversion is delayed until needed.
268 _elf_arinit(Elf
* elf
)
270 char *base
= elf
->ed_ident
;
271 register char *end
= base
+ elf
->ed_fsz
;
272 register struct ar_hdr
*a
;
273 register char *hdr
= base
+ SARMAG
;
278 elf
->ed_status
= ES_COOKED
;
279 elf
->ed_nextoff
= SARMAG
;
280 for (j
= 0; j
< 2; ++j
) { /* 2 special members */
283 if (((end
- hdr
) < sizeof (struct ar_hdr
)) ||
284 (_elf_vm(elf
, (size_t)(SARMAG
),
285 sizeof (struct ar_hdr
)) != OK_YES
))
288 a
= (struct ar_hdr
*)hdr
;
289 mem
= (char *)a
+ sizeof (struct ar_hdr
);
290 n
= _elf_number(a
->ar_size
, &a
->ar_size
[ARSZ(ar_size
)], 10);
291 if ((end
- mem
< n
) || (a
->ar_name
[0] != '/') ||
297 if (a
->ar_name
[1] == ' ') { /* 32-bit symbol table */
299 elf
->ed_arsymsz
= sz
;
300 elf
->ed_arsymoff
= (char *)a
- base
;
301 } else if (a
->ar_name
[1] == '/' && a
->ar_name
[2] == ' ') {
302 /* Long name string table */
305 if (_elf_vm(elf
, (size_t)(mem
- elf
->ed_ident
),
308 if (elf
->ed_vm
== 0) {
310 if ((nmem
= malloc(sz
)) == 0) {
311 _elf_seterr(EMEM_ARSTR
, errno
);
314 (void) memcpy(nmem
, mem
, sz
);
315 elf
->ed_myflags
|= EDF_ASTRALLOC
;
320 elf
->ed_arstrsz
= sz
;
321 elf
->ed_arstroff
= (char *)a
- base
;
322 for (k
= 0; k
< sz
; k
++) {
328 } else if (a
->ar_name
[1] == 'S' && a
->ar_name
[2] == 'Y' &&
329 a
->ar_name
[3] == 'M' && a
->ar_name
[4] == '6' &&
330 a
->ar_name
[5] == '4' && a
->ar_name
[6] == '/' &&
331 a
->ar_name
[7] == ' ') {
332 /* 64-bit symbol table */
334 elf
->ed_arsymsz
= sz
;
335 elf
->ed_arsymoff
= (char *)a
- base
;
336 elf
->ed_myflags
|= EDF_ARSYM64
;