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