xref: /minix3/external/bsd/elftoolchain/dist/libelf/libelf_ar_util.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: libelf_ar_util.c,v 1.2 2014/03/09 16:58:04 christos Exp $	*/
2*0a6a1f1dSLionel Sambuc 
3*0a6a1f1dSLionel Sambuc /*-
4*0a6a1f1dSLionel Sambuc  * Copyright (c) 2006,2009,2010 Joseph Koshy
5*0a6a1f1dSLionel Sambuc  * All rights reserved.
6*0a6a1f1dSLionel Sambuc  *
7*0a6a1f1dSLionel Sambuc  * Redistribution and use in source and binary forms, with or without
8*0a6a1f1dSLionel Sambuc  * modification, are permitted provided that the following conditions
9*0a6a1f1dSLionel Sambuc  * are met:
10*0a6a1f1dSLionel Sambuc  * 1. Redistributions of source code must retain the above copyright
11*0a6a1f1dSLionel Sambuc  *    notice, this list of conditions and the following disclaimer.
12*0a6a1f1dSLionel Sambuc  * 2. Redistributions in binary form must reproduce the above copyright
13*0a6a1f1dSLionel Sambuc  *    notice, this list of conditions and the following disclaimer in the
14*0a6a1f1dSLionel Sambuc  *    documentation and/or other materials provided with the distribution.
15*0a6a1f1dSLionel Sambuc  *
16*0a6a1f1dSLionel Sambuc  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS `AS IS' AND
17*0a6a1f1dSLionel Sambuc  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18*0a6a1f1dSLionel Sambuc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19*0a6a1f1dSLionel Sambuc  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20*0a6a1f1dSLionel Sambuc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21*0a6a1f1dSLionel Sambuc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22*0a6a1f1dSLionel Sambuc  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23*0a6a1f1dSLionel Sambuc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24*0a6a1f1dSLionel Sambuc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25*0a6a1f1dSLionel Sambuc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26*0a6a1f1dSLionel Sambuc  * SUCH DAMAGE.
27*0a6a1f1dSLionel Sambuc  */
28*0a6a1f1dSLionel Sambuc 
29*0a6a1f1dSLionel Sambuc #if HAVE_NBTOOL_CONFIG_H
30*0a6a1f1dSLionel Sambuc # include "nbtool_config.h"
31*0a6a1f1dSLionel Sambuc #endif
32*0a6a1f1dSLionel Sambuc 
33*0a6a1f1dSLionel Sambuc #include <sys/cdefs.h>
34*0a6a1f1dSLionel Sambuc 
35*0a6a1f1dSLionel Sambuc #include <assert.h>
36*0a6a1f1dSLionel Sambuc #include <libelf.h>
37*0a6a1f1dSLionel Sambuc #include <stdlib.h>
38*0a6a1f1dSLionel Sambuc #include <string.h>
39*0a6a1f1dSLionel Sambuc 
40*0a6a1f1dSLionel Sambuc #include "_libelf.h"
41*0a6a1f1dSLionel Sambuc #include "_libelf_ar.h"
42*0a6a1f1dSLionel Sambuc 
43*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: libelf_ar_util.c,v 1.2 2014/03/09 16:58:04 christos Exp $");
44*0a6a1f1dSLionel Sambuc ELFTC_VCSID("Id: libelf_ar_util.c 2365 2011-12-29 04:36:44Z jkoshy ");
45*0a6a1f1dSLionel Sambuc 
46*0a6a1f1dSLionel Sambuc /*
47*0a6a1f1dSLionel Sambuc  * Convert a string bounded by `start' and `start+sz' (exclusive) to a
48*0a6a1f1dSLionel Sambuc  * number in the specified base.
49*0a6a1f1dSLionel Sambuc  */
50*0a6a1f1dSLionel Sambuc int
_libelf_ar_get_number(const char * s,size_t sz,int base,size_t * ret)51*0a6a1f1dSLionel Sambuc _libelf_ar_get_number(const char *s, size_t sz, int base, size_t *ret)
52*0a6a1f1dSLionel Sambuc {
53*0a6a1f1dSLionel Sambuc 	int c, v;
54*0a6a1f1dSLionel Sambuc 	size_t r;
55*0a6a1f1dSLionel Sambuc 	const char *e;
56*0a6a1f1dSLionel Sambuc 
57*0a6a1f1dSLionel Sambuc 	assert(base <= 10);
58*0a6a1f1dSLionel Sambuc 
59*0a6a1f1dSLionel Sambuc 	e = s + sz;
60*0a6a1f1dSLionel Sambuc 
61*0a6a1f1dSLionel Sambuc 	/* skip leading blanks */
62*0a6a1f1dSLionel Sambuc 	for (;s < e && (c = *s) == ' '; s++)
63*0a6a1f1dSLionel Sambuc 		;
64*0a6a1f1dSLionel Sambuc 
65*0a6a1f1dSLionel Sambuc 	r = 0L;
66*0a6a1f1dSLionel Sambuc 	for (;s < e; s++) {
67*0a6a1f1dSLionel Sambuc 		if ((c = *s) == ' ')
68*0a6a1f1dSLionel Sambuc 			break;
69*0a6a1f1dSLionel Sambuc 		if (c < '0' || c > '9')
70*0a6a1f1dSLionel Sambuc 			return (0);
71*0a6a1f1dSLionel Sambuc 		v = c - '0';
72*0a6a1f1dSLionel Sambuc 		if (v >= base)		/* Illegal digit. */
73*0a6a1f1dSLionel Sambuc 			break;
74*0a6a1f1dSLionel Sambuc 		r *= base;
75*0a6a1f1dSLionel Sambuc 		r += v;
76*0a6a1f1dSLionel Sambuc 	}
77*0a6a1f1dSLionel Sambuc 
78*0a6a1f1dSLionel Sambuc 	*ret = r;
79*0a6a1f1dSLionel Sambuc 
80*0a6a1f1dSLionel Sambuc 	return (1);
81*0a6a1f1dSLionel Sambuc }
82*0a6a1f1dSLionel Sambuc 
83*0a6a1f1dSLionel Sambuc /*
84*0a6a1f1dSLionel Sambuc  * Return the translated name for an archive member.
85*0a6a1f1dSLionel Sambuc  */
86*0a6a1f1dSLionel Sambuc char *
_libelf_ar_get_translated_name(const struct ar_hdr * arh,Elf * ar)87*0a6a1f1dSLionel Sambuc _libelf_ar_get_translated_name(const struct ar_hdr *arh, Elf *ar)
88*0a6a1f1dSLionel Sambuc {
89*0a6a1f1dSLionel Sambuc 	char c, *s;
90*0a6a1f1dSLionel Sambuc 	size_t len, offset;
91*0a6a1f1dSLionel Sambuc 	const char *buf, *p, *q, *r;
92*0a6a1f1dSLionel Sambuc 	const size_t bufsize = sizeof(arh->ar_name);
93*0a6a1f1dSLionel Sambuc 
94*0a6a1f1dSLionel Sambuc 	assert(arh != NULL);
95*0a6a1f1dSLionel Sambuc 	assert(ar->e_kind == ELF_K_AR);
96*0a6a1f1dSLionel Sambuc 	assert((const char *) arh >= ar->e_rawfile &&
97*0a6a1f1dSLionel Sambuc 	    (const char *) arh < ar->e_rawfile + ar->e_rawsize);
98*0a6a1f1dSLionel Sambuc 
99*0a6a1f1dSLionel Sambuc 	buf = arh->ar_name;
100*0a6a1f1dSLionel Sambuc 
101*0a6a1f1dSLionel Sambuc 	/*
102*0a6a1f1dSLionel Sambuc 	 * Check for extended naming.
103*0a6a1f1dSLionel Sambuc 	 *
104*0a6a1f1dSLionel Sambuc 	 * If the name matches the pattern "^/[0-9]+", it is an
105*0a6a1f1dSLionel Sambuc 	 * SVR4-style extended name.  If the name matches the pattern
106*0a6a1f1dSLionel Sambuc 	 * "#1/[0-9]+", the entry uses BSD style extended naming.
107*0a6a1f1dSLionel Sambuc 	 */
108*0a6a1f1dSLionel Sambuc 	if (buf[0] == '/' && (c = buf[1]) >= '0' && c <= '9') {
109*0a6a1f1dSLionel Sambuc 		/*
110*0a6a1f1dSLionel Sambuc 		 * The value in field ar_name is a decimal offset into
111*0a6a1f1dSLionel Sambuc 		 * the archive string table where the actual name
112*0a6a1f1dSLionel Sambuc 		 * resides.
113*0a6a1f1dSLionel Sambuc 		 */
114*0a6a1f1dSLionel Sambuc 		if (_libelf_ar_get_number(buf + 1, bufsize - 1, 10,
115*0a6a1f1dSLionel Sambuc 			&offset) == 0) {
116*0a6a1f1dSLionel Sambuc 			LIBELF_SET_ERROR(ARCHIVE, 0);
117*0a6a1f1dSLionel Sambuc 			return (NULL);
118*0a6a1f1dSLionel Sambuc 		}
119*0a6a1f1dSLionel Sambuc 
120*0a6a1f1dSLionel Sambuc 		if (offset > ar->e_u.e_ar.e_rawstrtabsz) {
121*0a6a1f1dSLionel Sambuc 			LIBELF_SET_ERROR(ARCHIVE, 0);
122*0a6a1f1dSLionel Sambuc 			return (NULL);
123*0a6a1f1dSLionel Sambuc 		}
124*0a6a1f1dSLionel Sambuc 
125*0a6a1f1dSLionel Sambuc 		p = q = ar->e_u.e_ar.e_rawstrtab + offset;
126*0a6a1f1dSLionel Sambuc 		r = ar->e_u.e_ar.e_rawstrtab + ar->e_u.e_ar.e_rawstrtabsz;
127*0a6a1f1dSLionel Sambuc 
128*0a6a1f1dSLionel Sambuc 		for (; p < r && *p != '/'; p++)
129*0a6a1f1dSLionel Sambuc 			;
130*0a6a1f1dSLionel Sambuc 		len = p - q + 1; /* space for the trailing NUL */
131*0a6a1f1dSLionel Sambuc 
132*0a6a1f1dSLionel Sambuc 		if ((s = malloc(len)) == NULL) {
133*0a6a1f1dSLionel Sambuc 			LIBELF_SET_ERROR(RESOURCE, 0);
134*0a6a1f1dSLionel Sambuc 			return (NULL);
135*0a6a1f1dSLionel Sambuc 		}
136*0a6a1f1dSLionel Sambuc 
137*0a6a1f1dSLionel Sambuc 		(void) strncpy(s, q, len - 1);
138*0a6a1f1dSLionel Sambuc 		s[len - 1] = '\0';
139*0a6a1f1dSLionel Sambuc 
140*0a6a1f1dSLionel Sambuc 		return (s);
141*0a6a1f1dSLionel Sambuc 	} else if (IS_EXTENDED_BSD_NAME(buf)) {
142*0a6a1f1dSLionel Sambuc 		r = buf + LIBELF_AR_BSD_EXTENDED_NAME_PREFIX_SIZE;
143*0a6a1f1dSLionel Sambuc 
144*0a6a1f1dSLionel Sambuc 		if (_libelf_ar_get_number(r, bufsize -
145*0a6a1f1dSLionel Sambuc 			LIBELF_AR_BSD_EXTENDED_NAME_PREFIX_SIZE, 10,
146*0a6a1f1dSLionel Sambuc 			&len) == 0) {
147*0a6a1f1dSLionel Sambuc 			LIBELF_SET_ERROR(ARCHIVE, 0);
148*0a6a1f1dSLionel Sambuc 			return (NULL);
149*0a6a1f1dSLionel Sambuc 		}
150*0a6a1f1dSLionel Sambuc 
151*0a6a1f1dSLionel Sambuc 		/*
152*0a6a1f1dSLionel Sambuc 		 * Allocate space for the file name plus a
153*0a6a1f1dSLionel Sambuc 		 * trailing NUL.
154*0a6a1f1dSLionel Sambuc 		 */
155*0a6a1f1dSLionel Sambuc 		if ((s = malloc(len + 1)) == NULL) {
156*0a6a1f1dSLionel Sambuc 			LIBELF_SET_ERROR(RESOURCE, 0);
157*0a6a1f1dSLionel Sambuc 			return (NULL);
158*0a6a1f1dSLionel Sambuc 		}
159*0a6a1f1dSLionel Sambuc 
160*0a6a1f1dSLionel Sambuc 		/*
161*0a6a1f1dSLionel Sambuc 		 * The file name follows the archive header.
162*0a6a1f1dSLionel Sambuc 		 */
163*0a6a1f1dSLionel Sambuc 		q = (const char *) (arh + 1);
164*0a6a1f1dSLionel Sambuc 
165*0a6a1f1dSLionel Sambuc 		(void) strncpy(s, q, len);
166*0a6a1f1dSLionel Sambuc 		s[len] = '\0';
167*0a6a1f1dSLionel Sambuc 
168*0a6a1f1dSLionel Sambuc 		return (s);
169*0a6a1f1dSLionel Sambuc 	}
170*0a6a1f1dSLionel Sambuc 
171*0a6a1f1dSLionel Sambuc 	/*
172*0a6a1f1dSLionel Sambuc 	 * A 'normal' name.
173*0a6a1f1dSLionel Sambuc 	 *
174*0a6a1f1dSLionel Sambuc 	 * Skip back over trailing blanks from the end of the field.
175*0a6a1f1dSLionel Sambuc 	 * In the SVR4 format, a '/' is used as a terminator for
176*0a6a1f1dSLionel Sambuc 	 * non-special names.
177*0a6a1f1dSLionel Sambuc 	 */
178*0a6a1f1dSLionel Sambuc 	for (q = buf + bufsize - 1; q >= buf && *q == ' '; --q)
179*0a6a1f1dSLionel Sambuc 		;
180*0a6a1f1dSLionel Sambuc 
181*0a6a1f1dSLionel Sambuc 	if (q >= buf) {
182*0a6a1f1dSLionel Sambuc 		if (*q == '/') {
183*0a6a1f1dSLionel Sambuc 			/*
184*0a6a1f1dSLionel Sambuc 			 * SVR4 style names: ignore the trailing
185*0a6a1f1dSLionel Sambuc 			 * character '/', but only if the name is not
186*0a6a1f1dSLionel Sambuc 			 * one of the special names "/" and "//".
187*0a6a1f1dSLionel Sambuc 			 */
188*0a6a1f1dSLionel Sambuc 			if (q > buf + 1 ||
189*0a6a1f1dSLionel Sambuc 			    (q == (buf + 1) && *buf != '/'))
190*0a6a1f1dSLionel Sambuc 				q--;
191*0a6a1f1dSLionel Sambuc 		}
192*0a6a1f1dSLionel Sambuc 
193*0a6a1f1dSLionel Sambuc 		len = q - buf + 2; /* Add space for a trailing NUL. */
194*0a6a1f1dSLionel Sambuc 	} else {
195*0a6a1f1dSLionel Sambuc 		/* The buffer only had blanks. */
196*0a6a1f1dSLionel Sambuc 		buf = "";
197*0a6a1f1dSLionel Sambuc 		len = 1;
198*0a6a1f1dSLionel Sambuc 	}
199*0a6a1f1dSLionel Sambuc 
200*0a6a1f1dSLionel Sambuc 	if ((s = malloc(len)) == NULL) {
201*0a6a1f1dSLionel Sambuc 		LIBELF_SET_ERROR(RESOURCE, 0);
202*0a6a1f1dSLionel Sambuc 		return (NULL);
203*0a6a1f1dSLionel Sambuc 	}
204*0a6a1f1dSLionel Sambuc 
205*0a6a1f1dSLionel Sambuc 	(void) strncpy(s, buf, len - 1);
206*0a6a1f1dSLionel Sambuc 	s[len - 1] = '\0';
207*0a6a1f1dSLionel Sambuc 
208*0a6a1f1dSLionel Sambuc 	return (s);
209*0a6a1f1dSLionel Sambuc }
210*0a6a1f1dSLionel Sambuc 
211*0a6a1f1dSLionel Sambuc /*
212*0a6a1f1dSLionel Sambuc  * Return the raw name for an archive member, inclusive of any
213*0a6a1f1dSLionel Sambuc  * formatting characters.
214*0a6a1f1dSLionel Sambuc  */
215*0a6a1f1dSLionel Sambuc char *
_libelf_ar_get_raw_name(const struct ar_hdr * arh)216*0a6a1f1dSLionel Sambuc _libelf_ar_get_raw_name(const struct ar_hdr *arh)
217*0a6a1f1dSLionel Sambuc {
218*0a6a1f1dSLionel Sambuc 	char *rawname;
219*0a6a1f1dSLionel Sambuc 	const size_t namesz = sizeof(arh->ar_name);
220*0a6a1f1dSLionel Sambuc 
221*0a6a1f1dSLionel Sambuc 	if ((rawname = malloc(namesz + 1)) == NULL) {
222*0a6a1f1dSLionel Sambuc 		LIBELF_SET_ERROR(RESOURCE, 0);
223*0a6a1f1dSLionel Sambuc 		return (NULL);
224*0a6a1f1dSLionel Sambuc 	}
225*0a6a1f1dSLionel Sambuc 
226*0a6a1f1dSLionel Sambuc 	(void) strncpy(rawname, arh->ar_name, namesz);
227*0a6a1f1dSLionel Sambuc 	rawname[namesz] = '\0';
228*0a6a1f1dSLionel Sambuc 	return (rawname);
229*0a6a1f1dSLionel Sambuc }
230*0a6a1f1dSLionel Sambuc 
231*0a6a1f1dSLionel Sambuc /*
232*0a6a1f1dSLionel Sambuc  * Open an 'ar' archive.
233*0a6a1f1dSLionel Sambuc  */
234*0a6a1f1dSLionel Sambuc Elf *
_libelf_ar_open(Elf * e,int reporterror)235*0a6a1f1dSLionel Sambuc _libelf_ar_open(Elf *e, int reporterror)
236*0a6a1f1dSLionel Sambuc {
237*0a6a1f1dSLionel Sambuc 	size_t sz;
238*0a6a1f1dSLionel Sambuc 	int scanahead;
239*0a6a1f1dSLionel Sambuc 	char *s, *end;
240*0a6a1f1dSLionel Sambuc 	struct ar_hdr arh;
241*0a6a1f1dSLionel Sambuc 
242*0a6a1f1dSLionel Sambuc 	_libelf_init_elf(e, ELF_K_AR);
243*0a6a1f1dSLionel Sambuc 
244*0a6a1f1dSLionel Sambuc 	e->e_u.e_ar.e_nchildren = 0;
245*0a6a1f1dSLionel Sambuc 	e->e_u.e_ar.e_next = (off_t) -1;
246*0a6a1f1dSLionel Sambuc 
247*0a6a1f1dSLionel Sambuc 	/*
248*0a6a1f1dSLionel Sambuc 	 * Look for special members.
249*0a6a1f1dSLionel Sambuc 	 */
250*0a6a1f1dSLionel Sambuc 
251*0a6a1f1dSLionel Sambuc 	s = e->e_rawfile + SARMAG;
252*0a6a1f1dSLionel Sambuc 	end = e->e_rawfile + e->e_rawsize;
253*0a6a1f1dSLionel Sambuc 
254*0a6a1f1dSLionel Sambuc 	assert(e->e_rawsize > 0);
255*0a6a1f1dSLionel Sambuc 
256*0a6a1f1dSLionel Sambuc 	/*
257*0a6a1f1dSLionel Sambuc 	 * We use heuristics to determine the flavor of the archive we
258*0a6a1f1dSLionel Sambuc 	 * are examining.
259*0a6a1f1dSLionel Sambuc 	 *
260*0a6a1f1dSLionel Sambuc 	 * SVR4 flavor archives use the name "/ " and "// " for
261*0a6a1f1dSLionel Sambuc 	 * special members.
262*0a6a1f1dSLionel Sambuc 	 *
263*0a6a1f1dSLionel Sambuc 	 * In BSD flavor archives the symbol table, if present, is the
264*0a6a1f1dSLionel Sambuc 	 * first archive with name "__.SYMDEF".
265*0a6a1f1dSLionel Sambuc 	 */
266*0a6a1f1dSLionel Sambuc 
267*0a6a1f1dSLionel Sambuc #define	READ_AR_HEADER(S, ARH, SZ, END)					\
268*0a6a1f1dSLionel Sambuc 	do {								\
269*0a6a1f1dSLionel Sambuc 		if ((S) + sizeof((ARH)) > (END))			\
270*0a6a1f1dSLionel Sambuc 		        goto error;					\
271*0a6a1f1dSLionel Sambuc 		(void) memcpy(&(ARH), (S), sizeof((ARH)));		\
272*0a6a1f1dSLionel Sambuc 		if ((ARH).ar_fmag[0] != '`' || (ARH).ar_fmag[1] != '\n') \
273*0a6a1f1dSLionel Sambuc 			goto error;					\
274*0a6a1f1dSLionel Sambuc 		if (_libelf_ar_get_number((ARH).ar_size,		\
275*0a6a1f1dSLionel Sambuc 		    sizeof((ARH).ar_size), 10, &(SZ)) == 0)		\
276*0a6a1f1dSLionel Sambuc 			goto error;					\
277*0a6a1f1dSLionel Sambuc 	} while (0)
278*0a6a1f1dSLionel Sambuc 
279*0a6a1f1dSLionel Sambuc 	READ_AR_HEADER(s, arh, sz, end);
280*0a6a1f1dSLionel Sambuc 
281*0a6a1f1dSLionel Sambuc 	/*
282*0a6a1f1dSLionel Sambuc 	 * Handle special archive members for the SVR4 format.
283*0a6a1f1dSLionel Sambuc 	 */
284*0a6a1f1dSLionel Sambuc 	if (arh.ar_name[0] == '/') {
285*0a6a1f1dSLionel Sambuc 
286*0a6a1f1dSLionel Sambuc 		assert(sz > 0);
287*0a6a1f1dSLionel Sambuc 
288*0a6a1f1dSLionel Sambuc 		e->e_flags |= LIBELF_F_AR_VARIANT_SVR4;
289*0a6a1f1dSLionel Sambuc 
290*0a6a1f1dSLionel Sambuc 		scanahead = 0;
291*0a6a1f1dSLionel Sambuc 
292*0a6a1f1dSLionel Sambuc 		/*
293*0a6a1f1dSLionel Sambuc 		 * The symbol table (file name "/ ") always comes before the
294*0a6a1f1dSLionel Sambuc 		 * string table (file name "// ").
295*0a6a1f1dSLionel Sambuc 		 */
296*0a6a1f1dSLionel Sambuc 		if (arh.ar_name[1] == ' ') {
297*0a6a1f1dSLionel Sambuc 			/* "/ " => symbol table. */
298*0a6a1f1dSLionel Sambuc 			scanahead = 1;	/* The string table to follow. */
299*0a6a1f1dSLionel Sambuc 
300*0a6a1f1dSLionel Sambuc 			s += sizeof(arh);
301*0a6a1f1dSLionel Sambuc 			e->e_u.e_ar.e_rawsymtab = s;
302*0a6a1f1dSLionel Sambuc 			e->e_u.e_ar.e_rawsymtabsz = sz;
303*0a6a1f1dSLionel Sambuc 
304*0a6a1f1dSLionel Sambuc 			sz = LIBELF_ADJUST_AR_SIZE(sz);
305*0a6a1f1dSLionel Sambuc 			s += sz;
306*0a6a1f1dSLionel Sambuc 
307*0a6a1f1dSLionel Sambuc 		} else if (arh.ar_name[1] == '/' && arh.ar_name[2] == ' ') {
308*0a6a1f1dSLionel Sambuc 			/* "// " => string table for long file names. */
309*0a6a1f1dSLionel Sambuc 			s += sizeof(arh);
310*0a6a1f1dSLionel Sambuc 			e->e_u.e_ar.e_rawstrtab = s;
311*0a6a1f1dSLionel Sambuc 			e->e_u.e_ar.e_rawstrtabsz = sz;
312*0a6a1f1dSLionel Sambuc 
313*0a6a1f1dSLionel Sambuc 			sz = LIBELF_ADJUST_AR_SIZE(sz);
314*0a6a1f1dSLionel Sambuc 			s += sz;
315*0a6a1f1dSLionel Sambuc 		}
316*0a6a1f1dSLionel Sambuc 
317*0a6a1f1dSLionel Sambuc 		/*
318*0a6a1f1dSLionel Sambuc 		 * If the string table hasn't been seen yet, look for
319*0a6a1f1dSLionel Sambuc 		 * it in the next member.
320*0a6a1f1dSLionel Sambuc 		 */
321*0a6a1f1dSLionel Sambuc 		if (scanahead) {
322*0a6a1f1dSLionel Sambuc 			READ_AR_HEADER(s, arh, sz, end);
323*0a6a1f1dSLionel Sambuc 
324*0a6a1f1dSLionel Sambuc 			/* "// " => string table for long file names. */
325*0a6a1f1dSLionel Sambuc 			if (arh.ar_name[0] == '/' && arh.ar_name[1] == '/' &&
326*0a6a1f1dSLionel Sambuc 			    arh.ar_name[2] == ' ') {
327*0a6a1f1dSLionel Sambuc 
328*0a6a1f1dSLionel Sambuc 				s += sizeof(arh);
329*0a6a1f1dSLionel Sambuc 
330*0a6a1f1dSLionel Sambuc 				e->e_u.e_ar.e_rawstrtab = s;
331*0a6a1f1dSLionel Sambuc 				e->e_u.e_ar.e_rawstrtabsz = sz;
332*0a6a1f1dSLionel Sambuc 
333*0a6a1f1dSLionel Sambuc 				sz = LIBELF_ADJUST_AR_SIZE(sz);
334*0a6a1f1dSLionel Sambuc 				s += sz;
335*0a6a1f1dSLionel Sambuc 			}
336*0a6a1f1dSLionel Sambuc 		}
337*0a6a1f1dSLionel Sambuc 	} else if (strncmp(arh.ar_name, LIBELF_AR_BSD_SYMTAB_NAME,
338*0a6a1f1dSLionel Sambuc 		sizeof(LIBELF_AR_BSD_SYMTAB_NAME) - 1) == 0) {
339*0a6a1f1dSLionel Sambuc 		/*
340*0a6a1f1dSLionel Sambuc 		 * BSD style archive symbol table.
341*0a6a1f1dSLionel Sambuc 		 */
342*0a6a1f1dSLionel Sambuc 		s += sizeof(arh);
343*0a6a1f1dSLionel Sambuc 		e->e_u.e_ar.e_rawsymtab = s;
344*0a6a1f1dSLionel Sambuc 		e->e_u.e_ar.e_rawsymtabsz = sz;
345*0a6a1f1dSLionel Sambuc 
346*0a6a1f1dSLionel Sambuc 		sz = LIBELF_ADJUST_AR_SIZE(sz);
347*0a6a1f1dSLionel Sambuc 		s += sz;
348*0a6a1f1dSLionel Sambuc 	}
349*0a6a1f1dSLionel Sambuc 
350*0a6a1f1dSLionel Sambuc 	/*
351*0a6a1f1dSLionel Sambuc 	 * Update the 'next' offset, so that a subsequent elf_begin()
352*0a6a1f1dSLionel Sambuc 	 * works as expected.
353*0a6a1f1dSLionel Sambuc 	 */
354*0a6a1f1dSLionel Sambuc 	e->e_u.e_ar.e_next = (off_t) (s - e->e_rawfile);
355*0a6a1f1dSLionel Sambuc 
356*0a6a1f1dSLionel Sambuc 	return (e);
357*0a6a1f1dSLionel Sambuc 
358*0a6a1f1dSLionel Sambuc error:
359*0a6a1f1dSLionel Sambuc 	if (!reporterror) {
360*0a6a1f1dSLionel Sambuc 		e->e_kind = ELF_K_NONE;
361*0a6a1f1dSLionel Sambuc 		return (e);
362*0a6a1f1dSLionel Sambuc 	}
363*0a6a1f1dSLionel Sambuc 
364*0a6a1f1dSLionel Sambuc 	LIBELF_SET_ERROR(ARCHIVE, 0);
365*0a6a1f1dSLionel Sambuc 	return (NULL);
366*0a6a1f1dSLionel Sambuc }
367