xref: /dflybsd-src/contrib/gdb-7/bfd/archive.c (revision de8e141f24382815c10a4012d209bbbf7abf1112)
15796c8dcSSimon Schubert /* BFD back-end for archive files (libraries).
2*ef5ccd6cSJohn Marino    Copyright 1990-2013 Free Software Foundation, Inc.
35796c8dcSSimon Schubert    Written by Cygnus Support.  Mostly Gumby Henkel-Wallace's fault.
45796c8dcSSimon Schubert 
55796c8dcSSimon Schubert    This file is part of BFD, the Binary File Descriptor library.
65796c8dcSSimon Schubert 
75796c8dcSSimon Schubert    This program is free software; you can redistribute it and/or modify
85796c8dcSSimon Schubert    it under the terms of the GNU General Public License as published by
95796c8dcSSimon Schubert    the Free Software Foundation; either version 3 of the License, or
105796c8dcSSimon Schubert    (at your option) any later version.
115796c8dcSSimon Schubert 
125796c8dcSSimon Schubert    This program is distributed in the hope that it will be useful,
135796c8dcSSimon Schubert    but WITHOUT ANY WARRANTY; without even the implied warranty of
145796c8dcSSimon Schubert    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
155796c8dcSSimon Schubert    GNU General Public License for more details.
165796c8dcSSimon Schubert 
175796c8dcSSimon Schubert    You should have received a copy of the GNU General Public License
185796c8dcSSimon Schubert    along with this program; if not, write to the Free Software
195796c8dcSSimon Schubert    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
205796c8dcSSimon Schubert 
215796c8dcSSimon Schubert /*
225796c8dcSSimon Schubert @setfilename archive-info
235796c8dcSSimon Schubert SECTION
245796c8dcSSimon Schubert 	Archives
255796c8dcSSimon Schubert 
265796c8dcSSimon Schubert DESCRIPTION
275796c8dcSSimon Schubert 	An archive (or library) is just another BFD.  It has a symbol
285796c8dcSSimon Schubert 	table, although there's not much a user program will do with it.
295796c8dcSSimon Schubert 
305796c8dcSSimon Schubert 	The big difference between an archive BFD and an ordinary BFD
315796c8dcSSimon Schubert 	is that the archive doesn't have sections.  Instead it has a
325796c8dcSSimon Schubert 	chain of BFDs that are considered its contents.  These BFDs can
335796c8dcSSimon Schubert 	be manipulated like any other.  The BFDs contained in an
345796c8dcSSimon Schubert 	archive opened for reading will all be opened for reading.  You
355796c8dcSSimon Schubert 	may put either input or output BFDs into an archive opened for
365796c8dcSSimon Schubert 	output; they will be handled correctly when the archive is closed.
375796c8dcSSimon Schubert 
385796c8dcSSimon Schubert 	Use <<bfd_openr_next_archived_file>> to step through
395796c8dcSSimon Schubert 	the contents of an archive opened for input.  You don't
405796c8dcSSimon Schubert 	have to read the entire archive if you don't want
415796c8dcSSimon Schubert 	to!  Read it until you find what you want.
425796c8dcSSimon Schubert 
43*ef5ccd6cSJohn Marino 	A BFD returned by <<bfd_openr_next_archived_file>> can be
44*ef5ccd6cSJohn Marino 	closed manually with <<bfd_close>>.  If you do not close it,
45*ef5ccd6cSJohn Marino 	then a second iteration through the members of an archive may
46*ef5ccd6cSJohn Marino 	return the same BFD.  If you close the archive BFD, then all
47*ef5ccd6cSJohn Marino 	the member BFDs will automatically be closed as well.
48*ef5ccd6cSJohn Marino 
495796c8dcSSimon Schubert 	Archive contents of output BFDs are chained through the
50*ef5ccd6cSJohn Marino 	<<archive_next>> pointer in a BFD.  The first one is findable
51*ef5ccd6cSJohn Marino 	through the <<archive_head>> slot of the archive.  Set it with
52*ef5ccd6cSJohn Marino 	<<bfd_set_archive_head>> (q.v.).  A given BFD may be in only
53*ef5ccd6cSJohn Marino 	one open output archive at a time.
545796c8dcSSimon Schubert 
555796c8dcSSimon Schubert 	As expected, the BFD archive code is more general than the
565796c8dcSSimon Schubert 	archive code of any given environment.  BFD archives may
575796c8dcSSimon Schubert 	contain files of different formats (e.g., a.out and coff) and
585796c8dcSSimon Schubert 	even different architectures.  You may even place archives
595796c8dcSSimon Schubert 	recursively into archives!
605796c8dcSSimon Schubert 
615796c8dcSSimon Schubert 	This can cause unexpected confusion, since some archive
625796c8dcSSimon Schubert 	formats are more expressive than others.  For instance, Intel
635796c8dcSSimon Schubert 	COFF archives can preserve long filenames; SunOS a.out archives
645796c8dcSSimon Schubert 	cannot.  If you move a file from the first to the second
655796c8dcSSimon Schubert 	format and back again, the filename may be truncated.
665796c8dcSSimon Schubert 	Likewise, different a.out environments have different
675796c8dcSSimon Schubert 	conventions as to how they truncate filenames, whether they
685796c8dcSSimon Schubert 	preserve directory names in filenames, etc.  When
695796c8dcSSimon Schubert 	interoperating with native tools, be sure your files are
705796c8dcSSimon Schubert 	homogeneous.
715796c8dcSSimon Schubert 
725796c8dcSSimon Schubert 	Beware: most of these formats do not react well to the
735796c8dcSSimon Schubert 	presence of spaces in filenames.  We do the best we can, but
745796c8dcSSimon Schubert 	can't always handle this case due to restrictions in the format of
755796c8dcSSimon Schubert 	archives.  Many Unix utilities are braindead in regards to
765796c8dcSSimon Schubert 	spaces and such in filenames anyway, so this shouldn't be much
775796c8dcSSimon Schubert 	of a restriction.
785796c8dcSSimon Schubert 
795796c8dcSSimon Schubert 	Archives are supported in BFD in <<archive.c>>.
805796c8dcSSimon Schubert 
815796c8dcSSimon Schubert SUBSECTION
825796c8dcSSimon Schubert 	Archive functions
835796c8dcSSimon Schubert */
845796c8dcSSimon Schubert 
855796c8dcSSimon Schubert /* Assumes:
865796c8dcSSimon Schubert    o - all archive elements start on an even boundary, newline padded;
875796c8dcSSimon Schubert    o - all arch headers are char *;
885796c8dcSSimon Schubert    o - all arch headers are the same size (across architectures).
895796c8dcSSimon Schubert */
905796c8dcSSimon Schubert 
915796c8dcSSimon Schubert /* Some formats provide a way to cram a long filename into the short
925796c8dcSSimon Schubert    (16 chars) space provided by a BSD archive.  The trick is: make a
935796c8dcSSimon Schubert    special "file" in the front of the archive, sort of like the SYMDEF
945796c8dcSSimon Schubert    entry.  If the filename is too long to fit, put it in the extended
955796c8dcSSimon Schubert    name table, and use its index as the filename.  To prevent
965796c8dcSSimon Schubert    confusion prepend the index with a space.  This means you can't
975796c8dcSSimon Schubert    have filenames that start with a space, but then again, many Unix
985796c8dcSSimon Schubert    utilities can't handle that anyway.
995796c8dcSSimon Schubert 
1005796c8dcSSimon Schubert    This scheme unfortunately requires that you stand on your head in
1015796c8dcSSimon Schubert    order to write an archive since you need to put a magic file at the
1025796c8dcSSimon Schubert    front, and need to touch every entry to do so.  C'est la vie.
1035796c8dcSSimon Schubert 
1045796c8dcSSimon Schubert    We support two variants of this idea:
1055796c8dcSSimon Schubert    The SVR4 format (extended name table is named "//"),
1065796c8dcSSimon Schubert    and an extended pseudo-BSD variant (extended name table is named
1075796c8dcSSimon Schubert    "ARFILENAMES/").  The origin of the latter format is uncertain.
1085796c8dcSSimon Schubert 
1095796c8dcSSimon Schubert    BSD 4.4 uses a third scheme:  It writes a long filename
1105796c8dcSSimon Schubert    directly after the header.  This allows 'ar q' to work.
1115796c8dcSSimon Schubert */
1125796c8dcSSimon Schubert 
1135796c8dcSSimon Schubert /* Summary of archive member names:
1145796c8dcSSimon Schubert 
1155796c8dcSSimon Schubert  Symbol table (must be first):
1165796c8dcSSimon Schubert  "__.SYMDEF       " - Symbol table, Berkeley style, produced by ranlib.
1175796c8dcSSimon Schubert  "/               " - Symbol table, system 5 style.
1185796c8dcSSimon Schubert 
1195796c8dcSSimon Schubert  Long name table (must be before regular file members):
1205796c8dcSSimon Schubert  "//              " - Long name table, System 5 R4 style.
1215796c8dcSSimon Schubert  "ARFILENAMES/    " - Long name table, non-standard extended BSD (not BSD 4.4).
1225796c8dcSSimon Schubert 
1235796c8dcSSimon Schubert  Regular file members with short names:
1245796c8dcSSimon Schubert  "filename.o/     " - Regular file, System 5 style (embedded spaces ok).
1255796c8dcSSimon Schubert  "filename.o      " - Regular file, Berkeley style (no embedded spaces).
1265796c8dcSSimon Schubert 
1275796c8dcSSimon Schubert  Regular files with long names (or embedded spaces, for BSD variants):
1285796c8dcSSimon Schubert  "/18             " - SVR4 style, name at offset 18 in name table.
1295796c8dcSSimon Schubert  "#1/23           " - Long name (or embedded spaces) 23 characters long,
1305796c8dcSSimon Schubert 		      BSD 4.4 style, full name follows header.
1315796c8dcSSimon Schubert  " 18             " - Long name 18 characters long, extended pseudo-BSD.
1325796c8dcSSimon Schubert  */
1335796c8dcSSimon Schubert 
1345796c8dcSSimon Schubert #include "sysdep.h"
1355796c8dcSSimon Schubert #include "bfd.h"
1365796c8dcSSimon Schubert #include "libiberty.h"
1375796c8dcSSimon Schubert #include "libbfd.h"
1385796c8dcSSimon Schubert #include "aout/ar.h"
1395796c8dcSSimon Schubert #include "aout/ranlib.h"
1405796c8dcSSimon Schubert #include "safe-ctype.h"
1415796c8dcSSimon Schubert #include "hashtab.h"
1425796c8dcSSimon Schubert #include "filenames.h"
1435796c8dcSSimon Schubert 
1445796c8dcSSimon Schubert #ifndef errno
1455796c8dcSSimon Schubert extern int errno;
1465796c8dcSSimon Schubert #endif
1475796c8dcSSimon Schubert 
1485796c8dcSSimon Schubert /* We keep a cache of archive filepointers to archive elements to
1495796c8dcSSimon Schubert    speed up searching the archive by filepos.  We only add an entry to
1505796c8dcSSimon Schubert    the cache when we actually read one.  We also don't sort the cache;
1515796c8dcSSimon Schubert    it's generally short enough to search linearly.
1525796c8dcSSimon Schubert    Note that the pointers here point to the front of the ar_hdr, not
1535796c8dcSSimon Schubert    to the front of the contents!  */
154*ef5ccd6cSJohn Marino struct ar_cache
155*ef5ccd6cSJohn Marino {
1565796c8dcSSimon Schubert   file_ptr ptr;
1575796c8dcSSimon Schubert   bfd *arbfd;
1585796c8dcSSimon Schubert };
1595796c8dcSSimon Schubert 
1605796c8dcSSimon Schubert #define ar_padchar(abfd) ((abfd)->xvec->ar_pad_char)
1615796c8dcSSimon Schubert #define ar_maxnamelen(abfd) ((abfd)->xvec->ar_max_namelen)
1625796c8dcSSimon Schubert 
1635796c8dcSSimon Schubert #define arch_eltdata(bfd) ((struct areltdata *) ((bfd)->arelt_data))
1645796c8dcSSimon Schubert #define arch_hdr(bfd) ((struct ar_hdr *) arch_eltdata (bfd)->arch_header)
165cf7f2e2dSJohn Marino 
166cf7f2e2dSJohn Marino /* True iff NAME designated a BSD 4.4 extended name.  */
167cf7f2e2dSJohn Marino 
168cf7f2e2dSJohn Marino #define is_bsd44_extended_name(NAME) \
169cf7f2e2dSJohn Marino   (NAME[0] == '#'  && NAME[1] == '1' && NAME[2] == '/' && ISDIGIT (NAME[3]))
1705796c8dcSSimon Schubert 
1715796c8dcSSimon Schubert void
_bfd_ar_spacepad(char * p,size_t n,const char * fmt,long val)1725796c8dcSSimon Schubert _bfd_ar_spacepad (char *p, size_t n, const char *fmt, long val)
1735796c8dcSSimon Schubert {
1745796c8dcSSimon Schubert   static char buf[20];
1755796c8dcSSimon Schubert   size_t len;
176*ef5ccd6cSJohn Marino 
1775796c8dcSSimon Schubert   snprintf (buf, sizeof (buf), fmt, val);
1785796c8dcSSimon Schubert   len = strlen (buf);
1795796c8dcSSimon Schubert   if (len < n)
1805796c8dcSSimon Schubert     {
1815796c8dcSSimon Schubert       memcpy (p, buf, len);
1825796c8dcSSimon Schubert       memset (p + len, ' ', n - len);
1835796c8dcSSimon Schubert     }
1845796c8dcSSimon Schubert   else
1855796c8dcSSimon Schubert     memcpy (p, buf, n);
1865796c8dcSSimon Schubert }
187*ef5ccd6cSJohn Marino 
188*ef5ccd6cSJohn Marino bfd_boolean
_bfd_ar_sizepad(char * p,size_t n,bfd_size_type size)189*ef5ccd6cSJohn Marino _bfd_ar_sizepad (char *p, size_t n, bfd_size_type size)
190*ef5ccd6cSJohn Marino {
191*ef5ccd6cSJohn Marino   static char buf[21];
192*ef5ccd6cSJohn Marino   size_t len;
193*ef5ccd6cSJohn Marino 
194*ef5ccd6cSJohn Marino   snprintf (buf, sizeof (buf), "%-10" BFD_VMA_FMT "u", size);
195*ef5ccd6cSJohn Marino   len = strlen (buf);
196*ef5ccd6cSJohn Marino   if (len > n)
197*ef5ccd6cSJohn Marino     {
198*ef5ccd6cSJohn Marino       bfd_set_error (bfd_error_file_too_big);
199*ef5ccd6cSJohn Marino       return FALSE;
200*ef5ccd6cSJohn Marino     }
201*ef5ccd6cSJohn Marino   if (len < n)
202*ef5ccd6cSJohn Marino     {
203*ef5ccd6cSJohn Marino       memcpy (p, buf, len);
204*ef5ccd6cSJohn Marino       memset (p + len, ' ', n - len);
205*ef5ccd6cSJohn Marino     }
206*ef5ccd6cSJohn Marino   else
207*ef5ccd6cSJohn Marino     memcpy (p, buf, n);
208*ef5ccd6cSJohn Marino   return TRUE;
209*ef5ccd6cSJohn Marino }
2105796c8dcSSimon Schubert 
2115796c8dcSSimon Schubert bfd_boolean
_bfd_generic_mkarchive(bfd * abfd)2125796c8dcSSimon Schubert _bfd_generic_mkarchive (bfd *abfd)
2135796c8dcSSimon Schubert {
2145796c8dcSSimon Schubert   bfd_size_type amt = sizeof (struct artdata);
2155796c8dcSSimon Schubert 
2165796c8dcSSimon Schubert   abfd->tdata.aout_ar_data = (struct artdata *) bfd_zalloc (abfd, amt);
2175796c8dcSSimon Schubert   if (bfd_ardata (abfd) == NULL)
2185796c8dcSSimon Schubert     return FALSE;
2195796c8dcSSimon Schubert 
2205796c8dcSSimon Schubert   /* Already cleared by bfd_zalloc above.
2215796c8dcSSimon Schubert      bfd_ardata (abfd)->cache = NULL;
2225796c8dcSSimon Schubert      bfd_ardata (abfd)->archive_head = NULL;
2235796c8dcSSimon Schubert      bfd_ardata (abfd)->symdefs = NULL;
2245796c8dcSSimon Schubert      bfd_ardata (abfd)->extended_names = NULL;
2255796c8dcSSimon Schubert      bfd_ardata (abfd)->extended_names_size = 0;
2265796c8dcSSimon Schubert      bfd_ardata (abfd)->tdata = NULL;  */
2275796c8dcSSimon Schubert 
2285796c8dcSSimon Schubert   return TRUE;
2295796c8dcSSimon Schubert }
2305796c8dcSSimon Schubert 
2315796c8dcSSimon Schubert /*
2325796c8dcSSimon Schubert FUNCTION
2335796c8dcSSimon Schubert 	bfd_get_next_mapent
2345796c8dcSSimon Schubert 
2355796c8dcSSimon Schubert SYNOPSIS
2365796c8dcSSimon Schubert 	symindex bfd_get_next_mapent
2375796c8dcSSimon Schubert 	  (bfd *abfd, symindex previous, carsym **sym);
2385796c8dcSSimon Schubert 
2395796c8dcSSimon Schubert DESCRIPTION
2405796c8dcSSimon Schubert 	Step through archive @var{abfd}'s symbol table (if it
2415796c8dcSSimon Schubert 	has one).  Successively update @var{sym} with the next symbol's
2425796c8dcSSimon Schubert 	information, returning that symbol's (internal) index into the
2435796c8dcSSimon Schubert 	symbol table.
2445796c8dcSSimon Schubert 
2455796c8dcSSimon Schubert 	Supply <<BFD_NO_MORE_SYMBOLS>> as the @var{previous} entry to get
2465796c8dcSSimon Schubert 	the first one; returns <<BFD_NO_MORE_SYMBOLS>> when you've already
2475796c8dcSSimon Schubert 	got the last one.
2485796c8dcSSimon Schubert 
2495796c8dcSSimon Schubert 	A <<carsym>> is a canonical archive symbol.  The only
2505796c8dcSSimon Schubert 	user-visible element is its name, a null-terminated string.
2515796c8dcSSimon Schubert */
2525796c8dcSSimon Schubert 
2535796c8dcSSimon Schubert symindex
bfd_get_next_mapent(bfd * abfd,symindex prev,carsym ** entry)2545796c8dcSSimon Schubert bfd_get_next_mapent (bfd *abfd, symindex prev, carsym **entry)
2555796c8dcSSimon Schubert {
2565796c8dcSSimon Schubert   if (!bfd_has_map (abfd))
2575796c8dcSSimon Schubert     {
2585796c8dcSSimon Schubert       bfd_set_error (bfd_error_invalid_operation);
2595796c8dcSSimon Schubert       return BFD_NO_MORE_SYMBOLS;
2605796c8dcSSimon Schubert     }
2615796c8dcSSimon Schubert 
2625796c8dcSSimon Schubert   if (prev == BFD_NO_MORE_SYMBOLS)
2635796c8dcSSimon Schubert     prev = 0;
2645796c8dcSSimon Schubert   else
2655796c8dcSSimon Schubert     ++prev;
2665796c8dcSSimon Schubert   if (prev >= bfd_ardata (abfd)->symdef_count)
2675796c8dcSSimon Schubert     return BFD_NO_MORE_SYMBOLS;
2685796c8dcSSimon Schubert 
2695796c8dcSSimon Schubert   *entry = (bfd_ardata (abfd)->symdefs + prev);
2705796c8dcSSimon Schubert   return prev;
2715796c8dcSSimon Schubert }
2725796c8dcSSimon Schubert 
2735796c8dcSSimon Schubert /* To be called by backends only.  */
2745796c8dcSSimon Schubert 
2755796c8dcSSimon Schubert bfd *
_bfd_create_empty_archive_element_shell(bfd * obfd)2765796c8dcSSimon Schubert _bfd_create_empty_archive_element_shell (bfd *obfd)
2775796c8dcSSimon Schubert {
2785796c8dcSSimon Schubert   return _bfd_new_bfd_contained_in (obfd);
2795796c8dcSSimon Schubert }
2805796c8dcSSimon Schubert 
2815796c8dcSSimon Schubert /*
2825796c8dcSSimon Schubert FUNCTION
2835796c8dcSSimon Schubert 	bfd_set_archive_head
2845796c8dcSSimon Schubert 
2855796c8dcSSimon Schubert SYNOPSIS
2865796c8dcSSimon Schubert 	bfd_boolean bfd_set_archive_head (bfd *output, bfd *new_head);
2875796c8dcSSimon Schubert 
2885796c8dcSSimon Schubert DESCRIPTION
2895796c8dcSSimon Schubert 	Set the head of the chain of
2905796c8dcSSimon Schubert 	BFDs contained in the archive @var{output} to @var{new_head}.
2915796c8dcSSimon Schubert */
2925796c8dcSSimon Schubert 
2935796c8dcSSimon Schubert bfd_boolean
bfd_set_archive_head(bfd * output_archive,bfd * new_head)2945796c8dcSSimon Schubert bfd_set_archive_head (bfd *output_archive, bfd *new_head)
2955796c8dcSSimon Schubert {
2965796c8dcSSimon Schubert   output_archive->archive_head = new_head;
2975796c8dcSSimon Schubert   return TRUE;
2985796c8dcSSimon Schubert }
2995796c8dcSSimon Schubert 
3005796c8dcSSimon Schubert bfd *
_bfd_look_for_bfd_in_cache(bfd * arch_bfd,file_ptr filepos)3015796c8dcSSimon Schubert _bfd_look_for_bfd_in_cache (bfd *arch_bfd, file_ptr filepos)
3025796c8dcSSimon Schubert {
3035796c8dcSSimon Schubert   htab_t hash_table = bfd_ardata (arch_bfd)->cache;
3045796c8dcSSimon Schubert   struct ar_cache m;
305*ef5ccd6cSJohn Marino 
3065796c8dcSSimon Schubert   m.ptr = filepos;
3075796c8dcSSimon Schubert 
3085796c8dcSSimon Schubert   if (hash_table)
3095796c8dcSSimon Schubert     {
3105796c8dcSSimon Schubert       struct ar_cache *entry = (struct ar_cache *) htab_find (hash_table, &m);
3115796c8dcSSimon Schubert       if (!entry)
3125796c8dcSSimon Schubert 	return NULL;
3135796c8dcSSimon Schubert       else
3145796c8dcSSimon Schubert 	return entry->arbfd;
3155796c8dcSSimon Schubert     }
3165796c8dcSSimon Schubert   else
3175796c8dcSSimon Schubert     return NULL;
3185796c8dcSSimon Schubert }
3195796c8dcSSimon Schubert 
3205796c8dcSSimon Schubert static hashval_t
hash_file_ptr(const void * p)321*ef5ccd6cSJohn Marino hash_file_ptr (const void * p)
3225796c8dcSSimon Schubert {
3235796c8dcSSimon Schubert   return (hashval_t) (((struct ar_cache *) p)->ptr);
3245796c8dcSSimon Schubert }
3255796c8dcSSimon Schubert 
3265796c8dcSSimon Schubert /* Returns non-zero if P1 and P2 are equal.  */
3275796c8dcSSimon Schubert 
3285796c8dcSSimon Schubert static int
eq_file_ptr(const void * p1,const void * p2)329*ef5ccd6cSJohn Marino eq_file_ptr (const void * p1, const void * p2)
3305796c8dcSSimon Schubert {
3315796c8dcSSimon Schubert   struct ar_cache *arc1 = (struct ar_cache *) p1;
3325796c8dcSSimon Schubert   struct ar_cache *arc2 = (struct ar_cache *) p2;
3335796c8dcSSimon Schubert   return arc1->ptr == arc2->ptr;
3345796c8dcSSimon Schubert }
3355796c8dcSSimon Schubert 
336cf7f2e2dSJohn Marino /* The calloc function doesn't always take size_t (e.g. on VMS)
337cf7f2e2dSJohn Marino    so wrap it to avoid a compile time warning.   */
338cf7f2e2dSJohn Marino 
339cf7f2e2dSJohn Marino static void *
_bfd_calloc_wrapper(size_t a,size_t b)340cf7f2e2dSJohn Marino _bfd_calloc_wrapper (size_t a, size_t b)
341cf7f2e2dSJohn Marino {
342cf7f2e2dSJohn Marino   return calloc (a, b);
343cf7f2e2dSJohn Marino }
344cf7f2e2dSJohn Marino 
3455796c8dcSSimon Schubert /* Kind of stupid to call cons for each one, but we don't do too many.  */
3465796c8dcSSimon Schubert 
3475796c8dcSSimon Schubert bfd_boolean
_bfd_add_bfd_to_archive_cache(bfd * arch_bfd,file_ptr filepos,bfd * new_elt)3485796c8dcSSimon Schubert _bfd_add_bfd_to_archive_cache (bfd *arch_bfd, file_ptr filepos, bfd *new_elt)
3495796c8dcSSimon Schubert {
3505796c8dcSSimon Schubert   struct ar_cache *cache;
3515796c8dcSSimon Schubert   htab_t hash_table = bfd_ardata (arch_bfd)->cache;
3525796c8dcSSimon Schubert 
3535796c8dcSSimon Schubert   /* If the hash table hasn't been created, create it.  */
3545796c8dcSSimon Schubert   if (hash_table == NULL)
3555796c8dcSSimon Schubert     {
3565796c8dcSSimon Schubert       hash_table = htab_create_alloc (16, hash_file_ptr, eq_file_ptr,
357cf7f2e2dSJohn Marino 				      NULL, _bfd_calloc_wrapper, free);
3585796c8dcSSimon Schubert       if (hash_table == NULL)
3595796c8dcSSimon Schubert 	return FALSE;
3605796c8dcSSimon Schubert       bfd_ardata (arch_bfd)->cache = hash_table;
3615796c8dcSSimon Schubert     }
3625796c8dcSSimon Schubert 
3635796c8dcSSimon Schubert   /* Insert new_elt into the hash table by filepos.  */
3645796c8dcSSimon Schubert   cache = (struct ar_cache *) bfd_zalloc (arch_bfd, sizeof (struct ar_cache));
3655796c8dcSSimon Schubert   cache->ptr = filepos;
3665796c8dcSSimon Schubert   cache->arbfd = new_elt;
3675796c8dcSSimon Schubert   *htab_find_slot (hash_table, (const void *) cache, INSERT) = cache;
3685796c8dcSSimon Schubert 
369*ef5ccd6cSJohn Marino   /* Provide a means of accessing this from child.  */
370*ef5ccd6cSJohn Marino   arch_eltdata (new_elt)->parent_cache = hash_table;
371*ef5ccd6cSJohn Marino   arch_eltdata (new_elt)->key = filepos;
372*ef5ccd6cSJohn Marino 
3735796c8dcSSimon Schubert   return TRUE;
3745796c8dcSSimon Schubert }
3755796c8dcSSimon Schubert 
3765796c8dcSSimon Schubert static bfd *
_bfd_find_nested_archive(bfd * arch_bfd,const char * filename)3775796c8dcSSimon Schubert _bfd_find_nested_archive (bfd *arch_bfd, const char *filename)
3785796c8dcSSimon Schubert {
3795796c8dcSSimon Schubert   bfd *abfd;
380a45ae5f8SJohn Marino   const char *target;
3815796c8dcSSimon Schubert 
382*ef5ccd6cSJohn Marino   /* PR 15140: Don't allow a nested archive pointing to itself.  */
383*ef5ccd6cSJohn Marino   if (filename_cmp (filename, arch_bfd->filename) == 0)
384*ef5ccd6cSJohn Marino     {
385*ef5ccd6cSJohn Marino       bfd_set_error (bfd_error_malformed_archive);
386*ef5ccd6cSJohn Marino       return NULL;
387*ef5ccd6cSJohn Marino     }
388*ef5ccd6cSJohn Marino 
3895796c8dcSSimon Schubert   for (abfd = arch_bfd->nested_archives;
3905796c8dcSSimon Schubert        abfd != NULL;
3915796c8dcSSimon Schubert        abfd = abfd->archive_next)
3925796c8dcSSimon Schubert     {
393c50c785cSJohn Marino       if (filename_cmp (filename, abfd->filename) == 0)
3945796c8dcSSimon Schubert 	return abfd;
3955796c8dcSSimon Schubert     }
396a45ae5f8SJohn Marino   target = NULL;
397a45ae5f8SJohn Marino   if (!arch_bfd->target_defaulted)
398a45ae5f8SJohn Marino     target = arch_bfd->xvec->name;
399a45ae5f8SJohn Marino   abfd = bfd_openr (filename, target);
4005796c8dcSSimon Schubert   if (abfd)
4015796c8dcSSimon Schubert     {
4025796c8dcSSimon Schubert       abfd->archive_next = arch_bfd->nested_archives;
4035796c8dcSSimon Schubert       arch_bfd->nested_archives = abfd;
4045796c8dcSSimon Schubert     }
4055796c8dcSSimon Schubert   return abfd;
4065796c8dcSSimon Schubert }
4075796c8dcSSimon Schubert 
4085796c8dcSSimon Schubert /* The name begins with space.  Hence the rest of the name is an index into
4095796c8dcSSimon Schubert    the string table.  */
4105796c8dcSSimon Schubert 
4115796c8dcSSimon Schubert static char *
get_extended_arelt_filename(bfd * arch,const char * name,file_ptr * originp)4125796c8dcSSimon Schubert get_extended_arelt_filename (bfd *arch, const char *name, file_ptr *originp)
4135796c8dcSSimon Schubert {
414cf7f2e2dSJohn Marino   unsigned long table_index = 0;
4155796c8dcSSimon Schubert   const char *endp;
4165796c8dcSSimon Schubert 
4175796c8dcSSimon Schubert   /* Should extract string so that I can guarantee not to overflow into
4185796c8dcSSimon Schubert      the next region, but I'm too lazy.  */
4195796c8dcSSimon Schubert   errno = 0;
4205796c8dcSSimon Schubert   /* Skip first char, which is '/' in SVR4 or ' ' in some other variants.  */
421cf7f2e2dSJohn Marino   table_index = strtol (name + 1, (char **) &endp, 10);
422cf7f2e2dSJohn Marino   if (errno != 0 || table_index >= bfd_ardata (arch)->extended_names_size)
4235796c8dcSSimon Schubert     {
4245796c8dcSSimon Schubert       bfd_set_error (bfd_error_malformed_archive);
4255796c8dcSSimon Schubert       return NULL;
4265796c8dcSSimon Schubert     }
4275796c8dcSSimon Schubert   /* In a thin archive, a member of an archive-within-an-archive
4285796c8dcSSimon Schubert      will have the offset in the inner archive encoded here.  */
4295796c8dcSSimon Schubert   if (bfd_is_thin_archive (arch) && endp != NULL && *endp == ':')
4305796c8dcSSimon Schubert     {
4315796c8dcSSimon Schubert       file_ptr origin = strtol (endp + 1, NULL, 10);
4325796c8dcSSimon Schubert 
4335796c8dcSSimon Schubert       if (errno != 0)
4345796c8dcSSimon Schubert 	{
4355796c8dcSSimon Schubert 	  bfd_set_error (bfd_error_malformed_archive);
4365796c8dcSSimon Schubert 	  return NULL;
4375796c8dcSSimon Schubert 	}
4385796c8dcSSimon Schubert       *originp = origin;
4395796c8dcSSimon Schubert     }
4405796c8dcSSimon Schubert   else
4415796c8dcSSimon Schubert     *originp = 0;
4425796c8dcSSimon Schubert 
443cf7f2e2dSJohn Marino   return bfd_ardata (arch)->extended_names + table_index;
4445796c8dcSSimon Schubert }
4455796c8dcSSimon Schubert 
4465796c8dcSSimon Schubert /* This functions reads an arch header and returns an areltdata pointer, or
4475796c8dcSSimon Schubert    NULL on error.
4485796c8dcSSimon Schubert 
4495796c8dcSSimon Schubert    Presumes the file pointer is already in the right place (ie pointing
4505796c8dcSSimon Schubert    to the ar_hdr in the file).   Moves the file pointer; on success it
4515796c8dcSSimon Schubert    should be pointing to the front of the file contents; on failure it
4525796c8dcSSimon Schubert    could have been moved arbitrarily.  */
4535796c8dcSSimon Schubert 
4545796c8dcSSimon Schubert void *
_bfd_generic_read_ar_hdr(bfd * abfd)4555796c8dcSSimon Schubert _bfd_generic_read_ar_hdr (bfd *abfd)
4565796c8dcSSimon Schubert {
4575796c8dcSSimon Schubert   return _bfd_generic_read_ar_hdr_mag (abfd, NULL);
4585796c8dcSSimon Schubert }
4595796c8dcSSimon Schubert 
4605796c8dcSSimon Schubert /* Alpha ECOFF uses an optional different ARFMAG value, so we have a
4615796c8dcSSimon Schubert    variant of _bfd_generic_read_ar_hdr which accepts a magic string.  */
4625796c8dcSSimon Schubert 
4635796c8dcSSimon Schubert void *
_bfd_generic_read_ar_hdr_mag(bfd * abfd,const char * mag)4645796c8dcSSimon Schubert _bfd_generic_read_ar_hdr_mag (bfd *abfd, const char *mag)
4655796c8dcSSimon Schubert {
4665796c8dcSSimon Schubert   struct ar_hdr hdr;
4675796c8dcSSimon Schubert   char *hdrp = (char *) &hdr;
468*ef5ccd6cSJohn Marino   bfd_size_type parsed_size;
4695796c8dcSSimon Schubert   struct areltdata *ared;
4705796c8dcSSimon Schubert   char *filename = NULL;
4715796c8dcSSimon Schubert   bfd_size_type namelen = 0;
4725796c8dcSSimon Schubert   bfd_size_type allocsize = sizeof (struct areltdata) + sizeof (struct ar_hdr);
4735796c8dcSSimon Schubert   char *allocptr = 0;
4745796c8dcSSimon Schubert   file_ptr origin = 0;
475cf7f2e2dSJohn Marino   unsigned int extra_size = 0;
476*ef5ccd6cSJohn Marino   char fmag_save;
477*ef5ccd6cSJohn Marino   int scan;
4785796c8dcSSimon Schubert 
4795796c8dcSSimon Schubert   if (bfd_bread (hdrp, sizeof (struct ar_hdr), abfd) != sizeof (struct ar_hdr))
4805796c8dcSSimon Schubert     {
4815796c8dcSSimon Schubert       if (bfd_get_error () != bfd_error_system_call)
4825796c8dcSSimon Schubert 	bfd_set_error (bfd_error_no_more_archived_files);
4835796c8dcSSimon Schubert       return NULL;
4845796c8dcSSimon Schubert     }
4855796c8dcSSimon Schubert   if (strncmp (hdr.ar_fmag, ARFMAG, 2) != 0
4865796c8dcSSimon Schubert       && (mag == NULL
4875796c8dcSSimon Schubert 	  || strncmp (hdr.ar_fmag, mag, 2) != 0))
4885796c8dcSSimon Schubert     {
4895796c8dcSSimon Schubert       bfd_set_error (bfd_error_malformed_archive);
4905796c8dcSSimon Schubert       return NULL;
4915796c8dcSSimon Schubert     }
4925796c8dcSSimon Schubert 
4935796c8dcSSimon Schubert   errno = 0;
494*ef5ccd6cSJohn Marino   fmag_save = hdr.ar_fmag[0];
495*ef5ccd6cSJohn Marino   hdr.ar_fmag[0] = 0;
496*ef5ccd6cSJohn Marino   scan = sscanf (hdr.ar_size, "%" BFD_VMA_FMT "u", &parsed_size);
497*ef5ccd6cSJohn Marino   hdr.ar_fmag[0] = fmag_save;
498*ef5ccd6cSJohn Marino   if (scan != 1)
4995796c8dcSSimon Schubert     {
5005796c8dcSSimon Schubert       bfd_set_error (bfd_error_malformed_archive);
5015796c8dcSSimon Schubert       return NULL;
5025796c8dcSSimon Schubert     }
5035796c8dcSSimon Schubert 
5045796c8dcSSimon Schubert   /* Extract the filename from the archive - there are two ways to
5055796c8dcSSimon Schubert      specify an extended name table, either the first char of the
5065796c8dcSSimon Schubert      name is a space, or it's a slash.  */
5075796c8dcSSimon Schubert   if ((hdr.ar_name[0] == '/'
5085796c8dcSSimon Schubert        || (hdr.ar_name[0] == ' '
5095796c8dcSSimon Schubert 	   && memchr (hdr.ar_name, '/', ar_maxnamelen (abfd)) == NULL))
5105796c8dcSSimon Schubert       && bfd_ardata (abfd)->extended_names != NULL)
5115796c8dcSSimon Schubert     {
5125796c8dcSSimon Schubert       filename = get_extended_arelt_filename (abfd, hdr.ar_name, &origin);
5135796c8dcSSimon Schubert       if (filename == NULL)
5145796c8dcSSimon Schubert 	return NULL;
5155796c8dcSSimon Schubert     }
516cf7f2e2dSJohn Marino   /* BSD4.4-style long filename.  */
517cf7f2e2dSJohn Marino   else if (is_bsd44_extended_name (hdr.ar_name))
5185796c8dcSSimon Schubert     {
5195796c8dcSSimon Schubert       /* BSD-4.4 extended name */
5205796c8dcSSimon Schubert       namelen = atoi (&hdr.ar_name[3]);
5215796c8dcSSimon Schubert       allocsize += namelen + 1;
5225796c8dcSSimon Schubert       parsed_size -= namelen;
523cf7f2e2dSJohn Marino       extra_size = namelen;
5245796c8dcSSimon Schubert 
525*ef5ccd6cSJohn Marino       allocptr = (char *) bfd_zmalloc (allocsize);
5265796c8dcSSimon Schubert       if (allocptr == NULL)
5275796c8dcSSimon Schubert 	return NULL;
5285796c8dcSSimon Schubert       filename = (allocptr
5295796c8dcSSimon Schubert 		  + sizeof (struct areltdata)
5305796c8dcSSimon Schubert 		  + sizeof (struct ar_hdr));
5315796c8dcSSimon Schubert       if (bfd_bread (filename, namelen, abfd) != namelen)
5325796c8dcSSimon Schubert 	{
533*ef5ccd6cSJohn Marino 	  free (allocptr);
5345796c8dcSSimon Schubert 	  if (bfd_get_error () != bfd_error_system_call)
5355796c8dcSSimon Schubert 	    bfd_set_error (bfd_error_no_more_archived_files);
5365796c8dcSSimon Schubert 	  return NULL;
5375796c8dcSSimon Schubert 	}
5385796c8dcSSimon Schubert       filename[namelen] = '\0';
5395796c8dcSSimon Schubert     }
5405796c8dcSSimon Schubert   else
5415796c8dcSSimon Schubert     {
5425796c8dcSSimon Schubert       /* We judge the end of the name by looking for '/' or ' '.
5435796c8dcSSimon Schubert 	 Note:  The SYSV format (terminated by '/') allows embedded
5445796c8dcSSimon Schubert 	 spaces, so only look for ' ' if we don't find '/'.  */
5455796c8dcSSimon Schubert 
5465796c8dcSSimon Schubert       char *e;
5475796c8dcSSimon Schubert       e = (char *) memchr (hdr.ar_name, '\0', ar_maxnamelen (abfd));
5485796c8dcSSimon Schubert       if (e == NULL)
5495796c8dcSSimon Schubert 	{
5505796c8dcSSimon Schubert 	  e = (char *) memchr (hdr.ar_name, '/', ar_maxnamelen (abfd));
5515796c8dcSSimon Schubert 	  if (e == NULL)
5525796c8dcSSimon Schubert 	    e = (char *) memchr (hdr.ar_name, ' ', ar_maxnamelen (abfd));
5535796c8dcSSimon Schubert 	}
5545796c8dcSSimon Schubert 
5555796c8dcSSimon Schubert       if (e != NULL)
5565796c8dcSSimon Schubert 	namelen = e - hdr.ar_name;
5575796c8dcSSimon Schubert       else
5585796c8dcSSimon Schubert 	{
5595796c8dcSSimon Schubert 	  /* If we didn't find a termination character, then the name
5605796c8dcSSimon Schubert 	     must be the entire field.  */
5615796c8dcSSimon Schubert 	  namelen = ar_maxnamelen (abfd);
5625796c8dcSSimon Schubert 	}
5635796c8dcSSimon Schubert 
5645796c8dcSSimon Schubert       allocsize += namelen + 1;
5655796c8dcSSimon Schubert     }
5665796c8dcSSimon Schubert 
5675796c8dcSSimon Schubert   if (!allocptr)
5685796c8dcSSimon Schubert     {
569*ef5ccd6cSJohn Marino       allocptr = (char *) bfd_zmalloc (allocsize);
5705796c8dcSSimon Schubert       if (allocptr == NULL)
5715796c8dcSSimon Schubert 	return NULL;
5725796c8dcSSimon Schubert     }
5735796c8dcSSimon Schubert 
5745796c8dcSSimon Schubert   ared = (struct areltdata *) allocptr;
5755796c8dcSSimon Schubert 
5765796c8dcSSimon Schubert   ared->arch_header = allocptr + sizeof (struct areltdata);
5775796c8dcSSimon Schubert   memcpy (ared->arch_header, &hdr, sizeof (struct ar_hdr));
5785796c8dcSSimon Schubert   ared->parsed_size = parsed_size;
579cf7f2e2dSJohn Marino   ared->extra_size = extra_size;
5805796c8dcSSimon Schubert   ared->origin = origin;
5815796c8dcSSimon Schubert 
5825796c8dcSSimon Schubert   if (filename != NULL)
5835796c8dcSSimon Schubert     ared->filename = filename;
5845796c8dcSSimon Schubert   else
5855796c8dcSSimon Schubert     {
5865796c8dcSSimon Schubert       ared->filename = allocptr + (sizeof (struct areltdata) +
5875796c8dcSSimon Schubert 				   sizeof (struct ar_hdr));
5885796c8dcSSimon Schubert       if (namelen)
5895796c8dcSSimon Schubert 	memcpy (ared->filename, hdr.ar_name, namelen);
5905796c8dcSSimon Schubert       ared->filename[namelen] = '\0';
5915796c8dcSSimon Schubert     }
5925796c8dcSSimon Schubert 
5935796c8dcSSimon Schubert   return ared;
5945796c8dcSSimon Schubert }
5955796c8dcSSimon Schubert 
5965796c8dcSSimon Schubert /* Append the relative pathname for a member of the thin archive
5975796c8dcSSimon Schubert    to the pathname of the directory containing the archive.  */
5985796c8dcSSimon Schubert 
599cf7f2e2dSJohn Marino char *
_bfd_append_relative_path(bfd * arch,char * elt_name)600cf7f2e2dSJohn Marino _bfd_append_relative_path (bfd *arch, char *elt_name)
6015796c8dcSSimon Schubert {
6025796c8dcSSimon Schubert   const char *arch_name = arch->filename;
6035796c8dcSSimon Schubert   const char *base_name = lbasename (arch_name);
6045796c8dcSSimon Schubert   size_t prefix_len;
6055796c8dcSSimon Schubert   char *filename;
6065796c8dcSSimon Schubert 
6075796c8dcSSimon Schubert   if (base_name == arch_name)
6085796c8dcSSimon Schubert     return elt_name;
6095796c8dcSSimon Schubert 
6105796c8dcSSimon Schubert   prefix_len = base_name - arch_name;
6115796c8dcSSimon Schubert   filename = (char *) bfd_alloc (arch, prefix_len + strlen (elt_name) + 1);
6125796c8dcSSimon Schubert   if (filename == NULL)
6135796c8dcSSimon Schubert     return NULL;
6145796c8dcSSimon Schubert 
6155796c8dcSSimon Schubert   strncpy (filename, arch_name, prefix_len);
6165796c8dcSSimon Schubert   strcpy (filename + prefix_len, elt_name);
6175796c8dcSSimon Schubert   return filename;
6185796c8dcSSimon Schubert }
6195796c8dcSSimon Schubert 
6205796c8dcSSimon Schubert /* This is an internal function; it's mainly used when indexing
6215796c8dcSSimon Schubert    through the archive symbol table, but also used to get the next
6225796c8dcSSimon Schubert    element, since it handles the bookkeeping so nicely for us.  */
6235796c8dcSSimon Schubert 
6245796c8dcSSimon Schubert bfd *
_bfd_get_elt_at_filepos(bfd * archive,file_ptr filepos)6255796c8dcSSimon Schubert _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos)
6265796c8dcSSimon Schubert {
6275796c8dcSSimon Schubert   struct areltdata *new_areldata;
6285796c8dcSSimon Schubert   bfd *n_nfd;
6295796c8dcSSimon Schubert   char *filename;
6305796c8dcSSimon Schubert 
6315796c8dcSSimon Schubert   n_nfd = _bfd_look_for_bfd_in_cache (archive, filepos);
6325796c8dcSSimon Schubert   if (n_nfd)
6335796c8dcSSimon Schubert     return n_nfd;
6345796c8dcSSimon Schubert 
6355796c8dcSSimon Schubert   if (0 > bfd_seek (archive, filepos, SEEK_SET))
6365796c8dcSSimon Schubert     return NULL;
6375796c8dcSSimon Schubert 
6385796c8dcSSimon Schubert   if ((new_areldata = (struct areltdata *) _bfd_read_ar_hdr (archive)) == NULL)
6395796c8dcSSimon Schubert     return NULL;
6405796c8dcSSimon Schubert 
6415796c8dcSSimon Schubert   filename = new_areldata->filename;
6425796c8dcSSimon Schubert 
6435796c8dcSSimon Schubert   if (bfd_is_thin_archive (archive))
6445796c8dcSSimon Schubert     {
645a45ae5f8SJohn Marino       const char *target;
646a45ae5f8SJohn Marino 
6475796c8dcSSimon Schubert       /* This is a proxy entry for an external file.  */
6485796c8dcSSimon Schubert       if (! IS_ABSOLUTE_PATH (filename))
6495796c8dcSSimon Schubert 	{
650cf7f2e2dSJohn Marino 	  filename = _bfd_append_relative_path (archive, filename);
6515796c8dcSSimon Schubert 	  if (filename == NULL)
652*ef5ccd6cSJohn Marino 	    {
653*ef5ccd6cSJohn Marino 	      free (new_areldata);
6545796c8dcSSimon Schubert 	      return NULL;
6555796c8dcSSimon Schubert 	    }
656*ef5ccd6cSJohn Marino 	}
6575796c8dcSSimon Schubert 
6585796c8dcSSimon Schubert       if (new_areldata->origin > 0)
6595796c8dcSSimon Schubert 	{
6605796c8dcSSimon Schubert 	  /* This proxy entry refers to an element of a nested archive.
6615796c8dcSSimon Schubert 	     Locate the member of that archive and return a bfd for it.  */
6625796c8dcSSimon Schubert 	  bfd *ext_arch = _bfd_find_nested_archive (archive, filename);
6635796c8dcSSimon Schubert 
6645796c8dcSSimon Schubert 	  if (ext_arch == NULL
6655796c8dcSSimon Schubert 	      || ! bfd_check_format (ext_arch, bfd_archive))
6665796c8dcSSimon Schubert 	    {
667*ef5ccd6cSJohn Marino 	      free (new_areldata);
6685796c8dcSSimon Schubert 	      return NULL;
6695796c8dcSSimon Schubert 	    }
6705796c8dcSSimon Schubert 	  n_nfd = _bfd_get_elt_at_filepos (ext_arch, new_areldata->origin);
6715796c8dcSSimon Schubert 	  if (n_nfd == NULL)
6725796c8dcSSimon Schubert 	    {
673*ef5ccd6cSJohn Marino 	      free (new_areldata);
6745796c8dcSSimon Schubert 	      return NULL;
6755796c8dcSSimon Schubert 	    }
6765796c8dcSSimon Schubert 	  n_nfd->proxy_origin = bfd_tell (archive);
6775796c8dcSSimon Schubert 	  return n_nfd;
6785796c8dcSSimon Schubert 	}
6795796c8dcSSimon Schubert       /* It's not an element of a nested archive;
6805796c8dcSSimon Schubert 	 open the external file as a bfd.  */
681a45ae5f8SJohn Marino       target = NULL;
682a45ae5f8SJohn Marino       if (!archive->target_defaulted)
683a45ae5f8SJohn Marino 	target = archive->xvec->name;
684a45ae5f8SJohn Marino       n_nfd = bfd_openr (filename, target);
685a45ae5f8SJohn Marino       if (n_nfd == NULL)
686a45ae5f8SJohn Marino 	bfd_set_error (bfd_error_malformed_archive);
6875796c8dcSSimon Schubert     }
6885796c8dcSSimon Schubert   else
6895796c8dcSSimon Schubert     {
6905796c8dcSSimon Schubert       n_nfd = _bfd_create_empty_archive_element_shell (archive);
6915796c8dcSSimon Schubert     }
6925796c8dcSSimon Schubert 
6935796c8dcSSimon Schubert   if (n_nfd == NULL)
6945796c8dcSSimon Schubert     {
695*ef5ccd6cSJohn Marino       free (new_areldata);
6965796c8dcSSimon Schubert       return NULL;
6975796c8dcSSimon Schubert     }
6985796c8dcSSimon Schubert 
6995796c8dcSSimon Schubert   n_nfd->proxy_origin = bfd_tell (archive);
7005796c8dcSSimon Schubert 
7015796c8dcSSimon Schubert   if (bfd_is_thin_archive (archive))
7025796c8dcSSimon Schubert     {
7035796c8dcSSimon Schubert       n_nfd->origin = 0;
7045796c8dcSSimon Schubert     }
7055796c8dcSSimon Schubert   else
7065796c8dcSSimon Schubert     {
7075796c8dcSSimon Schubert       n_nfd->origin = n_nfd->proxy_origin;
7085796c8dcSSimon Schubert       n_nfd->filename = filename;
7095796c8dcSSimon Schubert     }
7105796c8dcSSimon Schubert 
7115796c8dcSSimon Schubert   n_nfd->arelt_data = new_areldata;
7125796c8dcSSimon Schubert 
713c50c785cSJohn Marino   /* Copy BFD_COMPRESS and BFD_DECOMPRESS flags.  */
714c50c785cSJohn Marino   n_nfd->flags |= archive->flags & (BFD_COMPRESS | BFD_DECOMPRESS);
715c50c785cSJohn Marino 
7165796c8dcSSimon Schubert   if (_bfd_add_bfd_to_archive_cache (archive, filepos, n_nfd))
7175796c8dcSSimon Schubert     return n_nfd;
7185796c8dcSSimon Schubert 
719*ef5ccd6cSJohn Marino   free (new_areldata);
720*ef5ccd6cSJohn Marino   n_nfd->arelt_data = NULL;
7215796c8dcSSimon Schubert   return NULL;
7225796c8dcSSimon Schubert }
7235796c8dcSSimon Schubert 
7245796c8dcSSimon Schubert /* Return the BFD which is referenced by the symbol in ABFD indexed by
725cf7f2e2dSJohn Marino    SYM_INDEX.  SYM_INDEX should have been returned by bfd_get_next_mapent.  */
7265796c8dcSSimon Schubert 
7275796c8dcSSimon Schubert bfd *
_bfd_generic_get_elt_at_index(bfd * abfd,symindex sym_index)728cf7f2e2dSJohn Marino _bfd_generic_get_elt_at_index (bfd *abfd, symindex sym_index)
7295796c8dcSSimon Schubert {
7305796c8dcSSimon Schubert   carsym *entry;
7315796c8dcSSimon Schubert 
732cf7f2e2dSJohn Marino   entry = bfd_ardata (abfd)->symdefs + sym_index;
7335796c8dcSSimon Schubert   return _bfd_get_elt_at_filepos (abfd, entry->file_offset);
7345796c8dcSSimon Schubert }
7355796c8dcSSimon Schubert 
7365796c8dcSSimon Schubert /*
7375796c8dcSSimon Schubert FUNCTION
7385796c8dcSSimon Schubert 	bfd_openr_next_archived_file
7395796c8dcSSimon Schubert 
7405796c8dcSSimon Schubert SYNOPSIS
7415796c8dcSSimon Schubert 	bfd *bfd_openr_next_archived_file (bfd *archive, bfd *previous);
7425796c8dcSSimon Schubert 
7435796c8dcSSimon Schubert DESCRIPTION
7445796c8dcSSimon Schubert 	Provided a BFD, @var{archive}, containing an archive and NULL, open
7455796c8dcSSimon Schubert 	an input BFD on the first contained element and returns that.
7465796c8dcSSimon Schubert 	Subsequent calls should pass
7475796c8dcSSimon Schubert 	the archive and the previous return value to return a created
7485796c8dcSSimon Schubert 	BFD to the next contained element. NULL is returned when there
7495796c8dcSSimon Schubert 	are no more.
7505796c8dcSSimon Schubert */
7515796c8dcSSimon Schubert 
7525796c8dcSSimon Schubert bfd *
bfd_openr_next_archived_file(bfd * archive,bfd * last_file)7535796c8dcSSimon Schubert bfd_openr_next_archived_file (bfd *archive, bfd *last_file)
7545796c8dcSSimon Schubert {
7555796c8dcSSimon Schubert   if ((bfd_get_format (archive) != bfd_archive)
7565796c8dcSSimon Schubert       || (archive->direction == write_direction))
7575796c8dcSSimon Schubert     {
7585796c8dcSSimon Schubert       bfd_set_error (bfd_error_invalid_operation);
7595796c8dcSSimon Schubert       return NULL;
7605796c8dcSSimon Schubert     }
7615796c8dcSSimon Schubert 
7625796c8dcSSimon Schubert   return BFD_SEND (archive,
7635796c8dcSSimon Schubert 		   openr_next_archived_file, (archive, last_file));
7645796c8dcSSimon Schubert }
7655796c8dcSSimon Schubert 
7665796c8dcSSimon Schubert bfd *
bfd_generic_openr_next_archived_file(bfd * archive,bfd * last_file)7675796c8dcSSimon Schubert bfd_generic_openr_next_archived_file (bfd *archive, bfd *last_file)
7685796c8dcSSimon Schubert {
7695796c8dcSSimon Schubert   file_ptr filestart;
7705796c8dcSSimon Schubert 
7715796c8dcSSimon Schubert   if (!last_file)
7725796c8dcSSimon Schubert     filestart = bfd_ardata (archive)->first_file_filepos;
7735796c8dcSSimon Schubert   else
7745796c8dcSSimon Schubert     {
775*ef5ccd6cSJohn Marino       bfd_size_type size = arelt_size (last_file);
776a45ae5f8SJohn Marino 
7775796c8dcSSimon Schubert       filestart = last_file->proxy_origin;
7785796c8dcSSimon Schubert       if (! bfd_is_thin_archive (archive))
7795796c8dcSSimon Schubert 	filestart += size;
7805796c8dcSSimon Schubert       /* Pad to an even boundary...
7815796c8dcSSimon Schubert 	 Note that last_file->origin can be odd in the case of
7825796c8dcSSimon Schubert 	 BSD-4.4-style element with a long odd size.  */
7835796c8dcSSimon Schubert       filestart += filestart % 2;
7845796c8dcSSimon Schubert     }
7855796c8dcSSimon Schubert 
7865796c8dcSSimon Schubert   return _bfd_get_elt_at_filepos (archive, filestart);
7875796c8dcSSimon Schubert }
7885796c8dcSSimon Schubert 
7895796c8dcSSimon Schubert const bfd_target *
bfd_generic_archive_p(bfd * abfd)7905796c8dcSSimon Schubert bfd_generic_archive_p (bfd *abfd)
7915796c8dcSSimon Schubert {
7925796c8dcSSimon Schubert   struct artdata *tdata_hold;
7935796c8dcSSimon Schubert   char armag[SARMAG + 1];
7945796c8dcSSimon Schubert   bfd_size_type amt;
7955796c8dcSSimon Schubert 
7965796c8dcSSimon Schubert   if (bfd_bread (armag, SARMAG, abfd) != SARMAG)
7975796c8dcSSimon Schubert     {
7985796c8dcSSimon Schubert       if (bfd_get_error () != bfd_error_system_call)
7995796c8dcSSimon Schubert 	bfd_set_error (bfd_error_wrong_format);
8005796c8dcSSimon Schubert       return NULL;
8015796c8dcSSimon Schubert     }
8025796c8dcSSimon Schubert 
8035796c8dcSSimon Schubert   bfd_is_thin_archive (abfd) = (strncmp (armag, ARMAGT, SARMAG) == 0);
8045796c8dcSSimon Schubert 
8055796c8dcSSimon Schubert   if (strncmp (armag, ARMAG, SARMAG) != 0
8065796c8dcSSimon Schubert       && strncmp (armag, ARMAGB, SARMAG) != 0
8075796c8dcSSimon Schubert       && ! bfd_is_thin_archive (abfd))
808a45ae5f8SJohn Marino     return NULL;
8095796c8dcSSimon Schubert 
8105796c8dcSSimon Schubert   tdata_hold = bfd_ardata (abfd);
8115796c8dcSSimon Schubert 
8125796c8dcSSimon Schubert   amt = sizeof (struct artdata);
8135796c8dcSSimon Schubert   bfd_ardata (abfd) = (struct artdata *) bfd_zalloc (abfd, amt);
8145796c8dcSSimon Schubert   if (bfd_ardata (abfd) == NULL)
8155796c8dcSSimon Schubert     {
8165796c8dcSSimon Schubert       bfd_ardata (abfd) = tdata_hold;
8175796c8dcSSimon Schubert       return NULL;
8185796c8dcSSimon Schubert     }
8195796c8dcSSimon Schubert 
8205796c8dcSSimon Schubert   bfd_ardata (abfd)->first_file_filepos = SARMAG;
8215796c8dcSSimon Schubert   /* Cleared by bfd_zalloc above.
8225796c8dcSSimon Schubert      bfd_ardata (abfd)->cache = NULL;
8235796c8dcSSimon Schubert      bfd_ardata (abfd)->archive_head = NULL;
8245796c8dcSSimon Schubert      bfd_ardata (abfd)->symdefs = NULL;
8255796c8dcSSimon Schubert      bfd_ardata (abfd)->extended_names = NULL;
8265796c8dcSSimon Schubert      bfd_ardata (abfd)->extended_names_size = 0;
8275796c8dcSSimon Schubert      bfd_ardata (abfd)->tdata = NULL;  */
8285796c8dcSSimon Schubert 
8295796c8dcSSimon Schubert   if (!BFD_SEND (abfd, _bfd_slurp_armap, (abfd))
8305796c8dcSSimon Schubert       || !BFD_SEND (abfd, _bfd_slurp_extended_name_table, (abfd)))
8315796c8dcSSimon Schubert     {
8325796c8dcSSimon Schubert       if (bfd_get_error () != bfd_error_system_call)
8335796c8dcSSimon Schubert 	bfd_set_error (bfd_error_wrong_format);
8345796c8dcSSimon Schubert       bfd_release (abfd, bfd_ardata (abfd));
8355796c8dcSSimon Schubert       bfd_ardata (abfd) = tdata_hold;
8365796c8dcSSimon Schubert       return NULL;
8375796c8dcSSimon Schubert     }
8385796c8dcSSimon Schubert 
839a45ae5f8SJohn Marino   if (abfd->target_defaulted && bfd_has_map (abfd))
8405796c8dcSSimon Schubert     {
8415796c8dcSSimon Schubert       bfd *first;
8425796c8dcSSimon Schubert 
8435796c8dcSSimon Schubert       /* This archive has a map, so we may presume that the contents
8445796c8dcSSimon Schubert 	 are object files.  Make sure that if the first file in the
8455796c8dcSSimon Schubert 	 archive can be recognized as an object file, it is for this
8465796c8dcSSimon Schubert 	 target.  If not, assume that this is the wrong format.  If
8475796c8dcSSimon Schubert 	 the first file is not an object file, somebody is doing
8485796c8dcSSimon Schubert 	 something weird, and we permit it so that ar -t will work.
8495796c8dcSSimon Schubert 
8505796c8dcSSimon Schubert 	 This is done because any normal format will recognize any
8515796c8dcSSimon Schubert 	 normal archive, regardless of the format of the object files.
8525796c8dcSSimon Schubert 	 We do accept an empty archive.  */
8535796c8dcSSimon Schubert 
8545796c8dcSSimon Schubert       first = bfd_openr_next_archived_file (abfd, NULL);
8555796c8dcSSimon Schubert       if (first != NULL)
8565796c8dcSSimon Schubert 	{
8575796c8dcSSimon Schubert 	  first->target_defaulted = FALSE;
8585796c8dcSSimon Schubert 	  if (bfd_check_format (first, bfd_object)
8595796c8dcSSimon Schubert 	      && first->xvec != abfd->xvec)
8605796c8dcSSimon Schubert 	    bfd_set_error (bfd_error_wrong_object_format);
8615796c8dcSSimon Schubert 	  /* And we ought to close `first' here too.  */
8625796c8dcSSimon Schubert 	}
8635796c8dcSSimon Schubert     }
8645796c8dcSSimon Schubert 
8655796c8dcSSimon Schubert   return abfd->xvec;
8665796c8dcSSimon Schubert }
8675796c8dcSSimon Schubert 
8685796c8dcSSimon Schubert /* Some constants for a 32 bit BSD archive structure.  We do not
8695796c8dcSSimon Schubert    support 64 bit archives presently; so far as I know, none actually
8705796c8dcSSimon Schubert    exist.  Supporting them would require changing these constants, and
8715796c8dcSSimon Schubert    changing some H_GET_32 to H_GET_64.  */
8725796c8dcSSimon Schubert 
8735796c8dcSSimon Schubert /* The size of an external symdef structure.  */
8745796c8dcSSimon Schubert #define BSD_SYMDEF_SIZE 8
8755796c8dcSSimon Schubert 
8765796c8dcSSimon Schubert /* The offset from the start of a symdef structure to the file offset.  */
8775796c8dcSSimon Schubert #define BSD_SYMDEF_OFFSET_SIZE 4
8785796c8dcSSimon Schubert 
8795796c8dcSSimon Schubert /* The size of the symdef count.  */
8805796c8dcSSimon Schubert #define BSD_SYMDEF_COUNT_SIZE 4
8815796c8dcSSimon Schubert 
8825796c8dcSSimon Schubert /* The size of the string count.  */
8835796c8dcSSimon Schubert #define BSD_STRING_COUNT_SIZE 4
8845796c8dcSSimon Schubert 
8855796c8dcSSimon Schubert /* Read a BSD-style archive symbol table.  Returns FALSE on error,
8865796c8dcSSimon Schubert    TRUE otherwise.  */
8875796c8dcSSimon Schubert 
8885796c8dcSSimon Schubert static bfd_boolean
do_slurp_bsd_armap(bfd * abfd)8895796c8dcSSimon Schubert do_slurp_bsd_armap (bfd *abfd)
8905796c8dcSSimon Schubert {
8915796c8dcSSimon Schubert   struct areltdata *mapdata;
8925796c8dcSSimon Schubert   unsigned int counter;
8935796c8dcSSimon Schubert   bfd_byte *raw_armap, *rbase;
8945796c8dcSSimon Schubert   struct artdata *ardata = bfd_ardata (abfd);
8955796c8dcSSimon Schubert   char *stringbase;
8965796c8dcSSimon Schubert   bfd_size_type parsed_size, amt;
8975796c8dcSSimon Schubert   carsym *set;
8985796c8dcSSimon Schubert 
8995796c8dcSSimon Schubert   mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd);
9005796c8dcSSimon Schubert   if (mapdata == NULL)
9015796c8dcSSimon Schubert     return FALSE;
9025796c8dcSSimon Schubert   parsed_size = mapdata->parsed_size;
903*ef5ccd6cSJohn Marino   free (mapdata);
9045796c8dcSSimon Schubert 
9055796c8dcSSimon Schubert   raw_armap = (bfd_byte *) bfd_zalloc (abfd, parsed_size);
9065796c8dcSSimon Schubert   if (raw_armap == NULL)
9075796c8dcSSimon Schubert     return FALSE;
9085796c8dcSSimon Schubert 
9095796c8dcSSimon Schubert   if (bfd_bread (raw_armap, parsed_size, abfd) != parsed_size)
9105796c8dcSSimon Schubert     {
9115796c8dcSSimon Schubert       if (bfd_get_error () != bfd_error_system_call)
9125796c8dcSSimon Schubert 	bfd_set_error (bfd_error_malformed_archive);
9135796c8dcSSimon Schubert     byebye:
9145796c8dcSSimon Schubert       bfd_release (abfd, raw_armap);
9155796c8dcSSimon Schubert       return FALSE;
9165796c8dcSSimon Schubert     }
9175796c8dcSSimon Schubert 
9185796c8dcSSimon Schubert   ardata->symdef_count = H_GET_32 (abfd, raw_armap) / BSD_SYMDEF_SIZE;
9195796c8dcSSimon Schubert 
9205796c8dcSSimon Schubert   if (ardata->symdef_count * BSD_SYMDEF_SIZE >
9215796c8dcSSimon Schubert       parsed_size - BSD_SYMDEF_COUNT_SIZE)
9225796c8dcSSimon Schubert     {
9235796c8dcSSimon Schubert       /* Probably we're using the wrong byte ordering.  */
9245796c8dcSSimon Schubert       bfd_set_error (bfd_error_wrong_format);
9255796c8dcSSimon Schubert       goto byebye;
9265796c8dcSSimon Schubert     }
9275796c8dcSSimon Schubert 
9285796c8dcSSimon Schubert   ardata->cache = 0;
9295796c8dcSSimon Schubert   rbase = raw_armap + BSD_SYMDEF_COUNT_SIZE;
9305796c8dcSSimon Schubert   stringbase = ((char *) rbase
9315796c8dcSSimon Schubert 		+ ardata->symdef_count * BSD_SYMDEF_SIZE
9325796c8dcSSimon Schubert 		+ BSD_STRING_COUNT_SIZE);
9335796c8dcSSimon Schubert   amt = ardata->symdef_count * sizeof (carsym);
9345796c8dcSSimon Schubert   ardata->symdefs = (struct carsym *) bfd_alloc (abfd, amt);
9355796c8dcSSimon Schubert   if (!ardata->symdefs)
9365796c8dcSSimon Schubert     return FALSE;
9375796c8dcSSimon Schubert 
9385796c8dcSSimon Schubert   for (counter = 0, set = ardata->symdefs;
9395796c8dcSSimon Schubert        counter < ardata->symdef_count;
9405796c8dcSSimon Schubert        counter++, set++, rbase += BSD_SYMDEF_SIZE)
9415796c8dcSSimon Schubert     {
9425796c8dcSSimon Schubert       set->name = H_GET_32 (abfd, rbase) + stringbase;
9435796c8dcSSimon Schubert       set->file_offset = H_GET_32 (abfd, rbase + BSD_SYMDEF_OFFSET_SIZE);
9445796c8dcSSimon Schubert     }
9455796c8dcSSimon Schubert 
9465796c8dcSSimon Schubert   ardata->first_file_filepos = bfd_tell (abfd);
9475796c8dcSSimon Schubert   /* Pad to an even boundary if you have to.  */
9485796c8dcSSimon Schubert   ardata->first_file_filepos += (ardata->first_file_filepos) % 2;
9495796c8dcSSimon Schubert   /* FIXME, we should provide some way to free raw_ardata when
9505796c8dcSSimon Schubert      we are done using the strings from it.  For now, it seems
9515796c8dcSSimon Schubert      to be allocated on an objalloc anyway...  */
9525796c8dcSSimon Schubert   bfd_has_map (abfd) = TRUE;
9535796c8dcSSimon Schubert   return TRUE;
9545796c8dcSSimon Schubert }
9555796c8dcSSimon Schubert 
9565796c8dcSSimon Schubert /* Read a COFF archive symbol table.  Returns FALSE on error, TRUE
9575796c8dcSSimon Schubert    otherwise.  */
9585796c8dcSSimon Schubert 
9595796c8dcSSimon Schubert static bfd_boolean
do_slurp_coff_armap(bfd * abfd)9605796c8dcSSimon Schubert do_slurp_coff_armap (bfd *abfd)
9615796c8dcSSimon Schubert {
9625796c8dcSSimon Schubert   struct areltdata *mapdata;
9635796c8dcSSimon Schubert   int *raw_armap, *rawptr;
9645796c8dcSSimon Schubert   struct artdata *ardata = bfd_ardata (abfd);
9655796c8dcSSimon Schubert   char *stringbase;
9665796c8dcSSimon Schubert   bfd_size_type stringsize;
967*ef5ccd6cSJohn Marino   bfd_size_type parsed_size;
9685796c8dcSSimon Schubert   carsym *carsyms;
9695796c8dcSSimon Schubert   bfd_size_type nsymz;		/* Number of symbols in armap.  */
9705796c8dcSSimon Schubert   bfd_vma (*swap) (const void *);
9715796c8dcSSimon Schubert   char int_buf[sizeof (long)];
9725796c8dcSSimon Schubert   bfd_size_type carsym_size, ptrsize;
9735796c8dcSSimon Schubert   unsigned int i;
9745796c8dcSSimon Schubert 
9755796c8dcSSimon Schubert   mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd);
9765796c8dcSSimon Schubert   if (mapdata == NULL)
9775796c8dcSSimon Schubert     return FALSE;
9785796c8dcSSimon Schubert   parsed_size = mapdata->parsed_size;
979*ef5ccd6cSJohn Marino   free (mapdata);
9805796c8dcSSimon Schubert 
9815796c8dcSSimon Schubert   if (bfd_bread (int_buf, 4, abfd) != 4)
9825796c8dcSSimon Schubert     {
9835796c8dcSSimon Schubert       if (bfd_get_error () != bfd_error_system_call)
9845796c8dcSSimon Schubert 	bfd_set_error (bfd_error_malformed_archive);
9855796c8dcSSimon Schubert       return FALSE;
9865796c8dcSSimon Schubert     }
9875796c8dcSSimon Schubert   /* It seems that all numeric information in a coff archive is always
9885796c8dcSSimon Schubert      in big endian format, nomatter the host or target.  */
9895796c8dcSSimon Schubert   swap = bfd_getb32;
9905796c8dcSSimon Schubert   nsymz = bfd_getb32 (int_buf);
9915796c8dcSSimon Schubert   stringsize = parsed_size - (4 * nsymz) - 4;
9925796c8dcSSimon Schubert 
9935796c8dcSSimon Schubert   /* ... except that some archive formats are broken, and it may be our
9945796c8dcSSimon Schubert      fault - the i960 little endian coff sometimes has big and sometimes
9955796c8dcSSimon Schubert      little, because our tools changed.  Here's a horrible hack to clean
9965796c8dcSSimon Schubert      up the crap.  */
9975796c8dcSSimon Schubert 
9985796c8dcSSimon Schubert   if (stringsize > 0xfffff
9995796c8dcSSimon Schubert       && bfd_get_arch (abfd) == bfd_arch_i960
10005796c8dcSSimon Schubert       && bfd_get_flavour (abfd) == bfd_target_coff_flavour)
10015796c8dcSSimon Schubert     {
10025796c8dcSSimon Schubert       /* This looks dangerous, let's do it the other way around.  */
10035796c8dcSSimon Schubert       nsymz = bfd_getl32 (int_buf);
10045796c8dcSSimon Schubert       stringsize = parsed_size - (4 * nsymz) - 4;
10055796c8dcSSimon Schubert       swap = bfd_getl32;
10065796c8dcSSimon Schubert     }
10075796c8dcSSimon Schubert 
10085796c8dcSSimon Schubert   /* The coff armap must be read sequentially.  So we construct a
10095796c8dcSSimon Schubert      bsd-style one in core all at once, for simplicity.  */
10105796c8dcSSimon Schubert 
10115796c8dcSSimon Schubert   if (nsymz > ~ (bfd_size_type) 0 / sizeof (carsym))
10125796c8dcSSimon Schubert     return FALSE;
10135796c8dcSSimon Schubert 
10145796c8dcSSimon Schubert   carsym_size = (nsymz * sizeof (carsym));
10155796c8dcSSimon Schubert   ptrsize = (4 * nsymz);
10165796c8dcSSimon Schubert 
10175796c8dcSSimon Schubert   if (carsym_size + stringsize + 1 <= carsym_size)
10185796c8dcSSimon Schubert     return FALSE;
10195796c8dcSSimon Schubert 
10205796c8dcSSimon Schubert   ardata->symdefs = (struct carsym *) bfd_zalloc (abfd,
10215796c8dcSSimon Schubert 						  carsym_size + stringsize + 1);
10225796c8dcSSimon Schubert   if (ardata->symdefs == NULL)
10235796c8dcSSimon Schubert     return FALSE;
10245796c8dcSSimon Schubert   carsyms = ardata->symdefs;
10255796c8dcSSimon Schubert   stringbase = ((char *) ardata->symdefs) + carsym_size;
10265796c8dcSSimon Schubert 
10275796c8dcSSimon Schubert   /* Allocate and read in the raw offsets.  */
10285796c8dcSSimon Schubert   raw_armap = (int *) bfd_alloc (abfd, ptrsize);
10295796c8dcSSimon Schubert   if (raw_armap == NULL)
10305796c8dcSSimon Schubert     goto release_symdefs;
10315796c8dcSSimon Schubert   if (bfd_bread (raw_armap, ptrsize, abfd) != ptrsize
10325796c8dcSSimon Schubert       || (bfd_bread (stringbase, stringsize, abfd) != stringsize))
10335796c8dcSSimon Schubert     {
10345796c8dcSSimon Schubert       if (bfd_get_error () != bfd_error_system_call)
10355796c8dcSSimon Schubert 	bfd_set_error (bfd_error_malformed_archive);
10365796c8dcSSimon Schubert       goto release_raw_armap;
10375796c8dcSSimon Schubert     }
10385796c8dcSSimon Schubert 
10395796c8dcSSimon Schubert   /* OK, build the carsyms.  */
10405796c8dcSSimon Schubert   for (i = 0; i < nsymz; i++)
10415796c8dcSSimon Schubert     {
10425796c8dcSSimon Schubert       rawptr = raw_armap + i;
10435796c8dcSSimon Schubert       carsyms->file_offset = swap ((bfd_byte *) rawptr);
10445796c8dcSSimon Schubert       carsyms->name = stringbase;
10455796c8dcSSimon Schubert       stringbase += strlen (stringbase) + 1;
10465796c8dcSSimon Schubert       carsyms++;
10475796c8dcSSimon Schubert     }
10485796c8dcSSimon Schubert   *stringbase = 0;
10495796c8dcSSimon Schubert 
10505796c8dcSSimon Schubert   ardata->symdef_count = nsymz;
10515796c8dcSSimon Schubert   ardata->first_file_filepos = bfd_tell (abfd);
10525796c8dcSSimon Schubert   /* Pad to an even boundary if you have to.  */
10535796c8dcSSimon Schubert   ardata->first_file_filepos += (ardata->first_file_filepos) % 2;
10545796c8dcSSimon Schubert 
10555796c8dcSSimon Schubert   bfd_has_map (abfd) = TRUE;
10565796c8dcSSimon Schubert   bfd_release (abfd, raw_armap);
10575796c8dcSSimon Schubert 
10585796c8dcSSimon Schubert   /* Check for a second archive header (as used by PE).  */
10595796c8dcSSimon Schubert   {
10605796c8dcSSimon Schubert     struct areltdata *tmp;
10615796c8dcSSimon Schubert 
10625796c8dcSSimon Schubert     bfd_seek (abfd, ardata->first_file_filepos, SEEK_SET);
10635796c8dcSSimon Schubert     tmp = (struct areltdata *) _bfd_read_ar_hdr (abfd);
10645796c8dcSSimon Schubert     if (tmp != NULL)
10655796c8dcSSimon Schubert       {
10665796c8dcSSimon Schubert 	if (tmp->arch_header[0] == '/'
10675796c8dcSSimon Schubert 	    && tmp->arch_header[1] == ' ')
10685796c8dcSSimon Schubert 	  {
10695796c8dcSSimon Schubert 	    ardata->first_file_filepos +=
10705796c8dcSSimon Schubert 	      (tmp->parsed_size + sizeof (struct ar_hdr) + 1) & ~(unsigned) 1;
10715796c8dcSSimon Schubert 	  }
1072*ef5ccd6cSJohn Marino 	free (tmp);
10735796c8dcSSimon Schubert       }
10745796c8dcSSimon Schubert   }
10755796c8dcSSimon Schubert 
10765796c8dcSSimon Schubert   return TRUE;
10775796c8dcSSimon Schubert 
10785796c8dcSSimon Schubert release_raw_armap:
10795796c8dcSSimon Schubert   bfd_release (abfd, raw_armap);
10805796c8dcSSimon Schubert release_symdefs:
10815796c8dcSSimon Schubert   bfd_release (abfd, (ardata)->symdefs);
10825796c8dcSSimon Schubert   return FALSE;
10835796c8dcSSimon Schubert }
10845796c8dcSSimon Schubert 
10855796c8dcSSimon Schubert /* This routine can handle either coff-style or bsd-style armaps
10865796c8dcSSimon Schubert    (archive symbol table).  Returns FALSE on error, TRUE otherwise */
10875796c8dcSSimon Schubert 
10885796c8dcSSimon Schubert bfd_boolean
bfd_slurp_armap(bfd * abfd)10895796c8dcSSimon Schubert bfd_slurp_armap (bfd *abfd)
10905796c8dcSSimon Schubert {
10915796c8dcSSimon Schubert   char nextname[17];
10925796c8dcSSimon Schubert   int i = bfd_bread (nextname, 16, abfd);
10935796c8dcSSimon Schubert 
10945796c8dcSSimon Schubert   if (i == 0)
10955796c8dcSSimon Schubert     return TRUE;
10965796c8dcSSimon Schubert   if (i != 16)
10975796c8dcSSimon Schubert     return FALSE;
10985796c8dcSSimon Schubert 
10995796c8dcSSimon Schubert   if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0)
11005796c8dcSSimon Schubert     return FALSE;
11015796c8dcSSimon Schubert 
11025796c8dcSSimon Schubert   if (CONST_STRNEQ (nextname, "__.SYMDEF       ")
11035796c8dcSSimon Schubert       || CONST_STRNEQ (nextname, "__.SYMDEF/      ")) /* Old Linux archives.  */
11045796c8dcSSimon Schubert     return do_slurp_bsd_armap (abfd);
11055796c8dcSSimon Schubert   else if (CONST_STRNEQ (nextname, "/               "))
11065796c8dcSSimon Schubert     return do_slurp_coff_armap (abfd);
11075796c8dcSSimon Schubert   else if (CONST_STRNEQ (nextname, "/SYM64/         "))
11085796c8dcSSimon Schubert     {
11095796c8dcSSimon Schubert       /* 64bit ELF (Irix 6) archive.  */
11105796c8dcSSimon Schubert #ifdef BFD64
11115796c8dcSSimon Schubert       extern bfd_boolean bfd_elf64_archive_slurp_armap (bfd *);
11125796c8dcSSimon Schubert       return bfd_elf64_archive_slurp_armap (abfd);
11135796c8dcSSimon Schubert #else
11145796c8dcSSimon Schubert       bfd_set_error (bfd_error_wrong_format);
11155796c8dcSSimon Schubert       return FALSE;
11165796c8dcSSimon Schubert #endif
11175796c8dcSSimon Schubert     }
1118cf7f2e2dSJohn Marino   else if (CONST_STRNEQ (nextname, "#1/20           "))
1119cf7f2e2dSJohn Marino     {
1120cf7f2e2dSJohn Marino       /* Mach-O has a special name for armap when the map is sorted by name.
1121cf7f2e2dSJohn Marino 	 However because this name has a space it is slightly more difficult
1122cf7f2e2dSJohn Marino 	 to check it.  */
1123cf7f2e2dSJohn Marino       struct ar_hdr hdr;
1124cf7f2e2dSJohn Marino       char extname[21];
1125cf7f2e2dSJohn Marino 
1126cf7f2e2dSJohn Marino       if (bfd_bread (&hdr, sizeof (hdr), abfd) != sizeof (hdr))
1127cf7f2e2dSJohn Marino 	return FALSE;
1128cf7f2e2dSJohn Marino       /* Read the extended name.  We know its length.  */
1129cf7f2e2dSJohn Marino       if (bfd_bread (extname, 20, abfd) != 20)
1130cf7f2e2dSJohn Marino 	return FALSE;
1131*ef5ccd6cSJohn Marino       if (bfd_seek (abfd, -(file_ptr) (sizeof (hdr) + 20), SEEK_CUR) != 0)
1132cf7f2e2dSJohn Marino 	return FALSE;
1133cf7f2e2dSJohn Marino       if (CONST_STRNEQ (extname, "__.SYMDEF SORTED")
1134cf7f2e2dSJohn Marino 	  || CONST_STRNEQ (extname, "__.SYMDEF"))
1135cf7f2e2dSJohn Marino 	return do_slurp_bsd_armap (abfd);
1136cf7f2e2dSJohn Marino     }
11375796c8dcSSimon Schubert 
11385796c8dcSSimon Schubert   bfd_has_map (abfd) = FALSE;
11395796c8dcSSimon Schubert   return TRUE;
11405796c8dcSSimon Schubert }
11415796c8dcSSimon Schubert 
11425796c8dcSSimon Schubert /* Returns FALSE on error, TRUE otherwise.  */
11435796c8dcSSimon Schubert /* Flavor 2 of a bsd armap, similar to bfd_slurp_bsd_armap except the
11445796c8dcSSimon Schubert    header is in a slightly different order and the map name is '/'.
11455796c8dcSSimon Schubert    This flavour is used by hp300hpux.  */
11465796c8dcSSimon Schubert 
11475796c8dcSSimon Schubert #define HPUX_SYMDEF_COUNT_SIZE 2
11485796c8dcSSimon Schubert 
11495796c8dcSSimon Schubert bfd_boolean
bfd_slurp_bsd_armap_f2(bfd * abfd)11505796c8dcSSimon Schubert bfd_slurp_bsd_armap_f2 (bfd *abfd)
11515796c8dcSSimon Schubert {
11525796c8dcSSimon Schubert   struct areltdata *mapdata;
11535796c8dcSSimon Schubert   char nextname[17];
11545796c8dcSSimon Schubert   unsigned int counter;
11555796c8dcSSimon Schubert   bfd_byte *raw_armap, *rbase;
11565796c8dcSSimon Schubert   struct artdata *ardata = bfd_ardata (abfd);
11575796c8dcSSimon Schubert   char *stringbase;
11585796c8dcSSimon Schubert   unsigned int stringsize;
1159c50c785cSJohn Marino   unsigned int left;
11605796c8dcSSimon Schubert   bfd_size_type amt;
11615796c8dcSSimon Schubert   carsym *set;
11625796c8dcSSimon Schubert   int i = bfd_bread (nextname, 16, abfd);
11635796c8dcSSimon Schubert 
11645796c8dcSSimon Schubert   if (i == 0)
11655796c8dcSSimon Schubert     return TRUE;
11665796c8dcSSimon Schubert   if (i != 16)
11675796c8dcSSimon Schubert     return FALSE;
11685796c8dcSSimon Schubert 
11695796c8dcSSimon Schubert   /* The archive has at least 16 bytes in it.  */
11705796c8dcSSimon Schubert   if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0)
11715796c8dcSSimon Schubert     return FALSE;
11725796c8dcSSimon Schubert 
11735796c8dcSSimon Schubert   if (CONST_STRNEQ (nextname, "__.SYMDEF       ")
11745796c8dcSSimon Schubert       || CONST_STRNEQ (nextname, "__.SYMDEF/      ")) /* Old Linux archives.  */
11755796c8dcSSimon Schubert     return do_slurp_bsd_armap (abfd);
11765796c8dcSSimon Schubert 
11775796c8dcSSimon Schubert   if (! CONST_STRNEQ (nextname, "/               "))
11785796c8dcSSimon Schubert     {
11795796c8dcSSimon Schubert       bfd_has_map (abfd) = FALSE;
11805796c8dcSSimon Schubert       return TRUE;
11815796c8dcSSimon Schubert     }
11825796c8dcSSimon Schubert 
11835796c8dcSSimon Schubert   mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd);
11845796c8dcSSimon Schubert   if (mapdata == NULL)
11855796c8dcSSimon Schubert     return FALSE;
11865796c8dcSSimon Schubert 
1187c50c785cSJohn Marino   if (mapdata->parsed_size < HPUX_SYMDEF_COUNT_SIZE + BSD_STRING_COUNT_SIZE)
11885796c8dcSSimon Schubert     {
1189*ef5ccd6cSJohn Marino       free (mapdata);
1190c50c785cSJohn Marino     wrong_format:
1191c50c785cSJohn Marino       bfd_set_error (bfd_error_wrong_format);
11925796c8dcSSimon Schubert     byebye:
11935796c8dcSSimon Schubert       return FALSE;
11945796c8dcSSimon Schubert     }
1195c50c785cSJohn Marino   left = mapdata->parsed_size - HPUX_SYMDEF_COUNT_SIZE - BSD_STRING_COUNT_SIZE;
1196c50c785cSJohn Marino 
1197c50c785cSJohn Marino   amt = mapdata->parsed_size;
1198*ef5ccd6cSJohn Marino   free (mapdata);
1199*ef5ccd6cSJohn Marino 
1200c50c785cSJohn Marino   raw_armap = (bfd_byte *) bfd_zalloc (abfd, amt);
1201c50c785cSJohn Marino   if (raw_armap == NULL)
1202c50c785cSJohn Marino     goto byebye;
12035796c8dcSSimon Schubert 
12045796c8dcSSimon Schubert   if (bfd_bread (raw_armap, amt, abfd) != amt)
12055796c8dcSSimon Schubert     {
12065796c8dcSSimon Schubert       if (bfd_get_error () != bfd_error_system_call)
12075796c8dcSSimon Schubert 	bfd_set_error (bfd_error_malformed_archive);
12085796c8dcSSimon Schubert       goto byebye;
12095796c8dcSSimon Schubert     }
12105796c8dcSSimon Schubert 
12115796c8dcSSimon Schubert   ardata->symdef_count = H_GET_16 (abfd, raw_armap);
12125796c8dcSSimon Schubert 
12135796c8dcSSimon Schubert   ardata->cache = 0;
12145796c8dcSSimon Schubert 
12155796c8dcSSimon Schubert   stringsize = H_GET_32 (abfd, raw_armap + HPUX_SYMDEF_COUNT_SIZE);
1216c50c785cSJohn Marino   if (stringsize > left)
1217c50c785cSJohn Marino     goto wrong_format;
1218c50c785cSJohn Marino   left -= stringsize;
1219c50c785cSJohn Marino 
12205796c8dcSSimon Schubert   /* Skip sym count and string sz.  */
12215796c8dcSSimon Schubert   stringbase = ((char *) raw_armap
12225796c8dcSSimon Schubert 		+ HPUX_SYMDEF_COUNT_SIZE
12235796c8dcSSimon Schubert 		+ BSD_STRING_COUNT_SIZE);
12245796c8dcSSimon Schubert   rbase = (bfd_byte *) stringbase + stringsize;
12255796c8dcSSimon Schubert   amt = ardata->symdef_count * BSD_SYMDEF_SIZE;
1226c50c785cSJohn Marino   if (amt > left)
1227c50c785cSJohn Marino     goto wrong_format;
1228c50c785cSJohn Marino 
12295796c8dcSSimon Schubert   ardata->symdefs = (struct carsym *) bfd_alloc (abfd, amt);
12305796c8dcSSimon Schubert   if (!ardata->symdefs)
12315796c8dcSSimon Schubert     return FALSE;
12325796c8dcSSimon Schubert 
12335796c8dcSSimon Schubert   for (counter = 0, set = ardata->symdefs;
12345796c8dcSSimon Schubert        counter < ardata->symdef_count;
12355796c8dcSSimon Schubert        counter++, set++, rbase += BSD_SYMDEF_SIZE)
12365796c8dcSSimon Schubert     {
12375796c8dcSSimon Schubert       set->name = H_GET_32 (abfd, rbase) + stringbase;
12385796c8dcSSimon Schubert       set->file_offset = H_GET_32 (abfd, rbase + BSD_SYMDEF_OFFSET_SIZE);
12395796c8dcSSimon Schubert     }
12405796c8dcSSimon Schubert 
12415796c8dcSSimon Schubert   ardata->first_file_filepos = bfd_tell (abfd);
12425796c8dcSSimon Schubert   /* Pad to an even boundary if you have to.  */
12435796c8dcSSimon Schubert   ardata->first_file_filepos += (ardata->first_file_filepos) % 2;
12445796c8dcSSimon Schubert   /* FIXME, we should provide some way to free raw_ardata when
12455796c8dcSSimon Schubert      we are done using the strings from it.  For now, it seems
12465796c8dcSSimon Schubert      to be allocated on an objalloc anyway...  */
12475796c8dcSSimon Schubert   bfd_has_map (abfd) = TRUE;
12485796c8dcSSimon Schubert   return TRUE;
12495796c8dcSSimon Schubert }
12505796c8dcSSimon Schubert 
12515796c8dcSSimon Schubert /** Extended name table.
12525796c8dcSSimon Schubert 
12535796c8dcSSimon Schubert   Normally archives support only 14-character filenames.
12545796c8dcSSimon Schubert 
12555796c8dcSSimon Schubert   Intel has extended the format: longer names are stored in a special
12565796c8dcSSimon Schubert   element (the first in the archive, or second if there is an armap);
12575796c8dcSSimon Schubert   the name in the ar_hdr is replaced by <space><index into filename
12585796c8dcSSimon Schubert   element>.  Index is the P.R. of an int (decimal).  Data General have
12595796c8dcSSimon Schubert   extended the format by using the prefix // for the special element.  */
12605796c8dcSSimon Schubert 
12615796c8dcSSimon Schubert /* Returns FALSE on error, TRUE otherwise.  */
12625796c8dcSSimon Schubert 
12635796c8dcSSimon Schubert bfd_boolean
_bfd_slurp_extended_name_table(bfd * abfd)12645796c8dcSSimon Schubert _bfd_slurp_extended_name_table (bfd *abfd)
12655796c8dcSSimon Schubert {
12665796c8dcSSimon Schubert   char nextname[17];
12675796c8dcSSimon Schubert   struct areltdata *namedata;
12685796c8dcSSimon Schubert   bfd_size_type amt;
12695796c8dcSSimon Schubert 
12705796c8dcSSimon Schubert   /* FIXME:  Formatting sucks here, and in case of failure of BFD_READ,
12715796c8dcSSimon Schubert      we probably don't want to return TRUE.  */
1272c50c785cSJohn Marino   if (bfd_seek (abfd, bfd_ardata (abfd)->first_file_filepos, SEEK_SET) != 0)
1273c50c785cSJohn Marino     return FALSE;
1274c50c785cSJohn Marino 
12755796c8dcSSimon Schubert   if (bfd_bread (nextname, 16, abfd) == 16)
12765796c8dcSSimon Schubert     {
12775796c8dcSSimon Schubert       if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0)
12785796c8dcSSimon Schubert 	return FALSE;
12795796c8dcSSimon Schubert 
12805796c8dcSSimon Schubert       if (! CONST_STRNEQ (nextname, "ARFILENAMES/    ")
12815796c8dcSSimon Schubert 	  && ! CONST_STRNEQ (nextname, "//              "))
12825796c8dcSSimon Schubert 	{
12835796c8dcSSimon Schubert 	  bfd_ardata (abfd)->extended_names = NULL;
12845796c8dcSSimon Schubert 	  bfd_ardata (abfd)->extended_names_size = 0;
12855796c8dcSSimon Schubert 	  return TRUE;
12865796c8dcSSimon Schubert 	}
12875796c8dcSSimon Schubert 
12885796c8dcSSimon Schubert       namedata = (struct areltdata *) _bfd_read_ar_hdr (abfd);
12895796c8dcSSimon Schubert       if (namedata == NULL)
12905796c8dcSSimon Schubert 	return FALSE;
12915796c8dcSSimon Schubert 
12925796c8dcSSimon Schubert       amt = namedata->parsed_size;
12935796c8dcSSimon Schubert       if (amt + 1 == 0)
12945796c8dcSSimon Schubert 	goto byebye;
12955796c8dcSSimon Schubert 
12965796c8dcSSimon Schubert       bfd_ardata (abfd)->extended_names_size = amt;
12975796c8dcSSimon Schubert       bfd_ardata (abfd)->extended_names = (char *) bfd_zalloc (abfd, amt + 1);
12985796c8dcSSimon Schubert       if (bfd_ardata (abfd)->extended_names == NULL)
12995796c8dcSSimon Schubert 	{
13005796c8dcSSimon Schubert 	byebye:
1301*ef5ccd6cSJohn Marino 	  free (namedata);
13025796c8dcSSimon Schubert 	  return FALSE;
13035796c8dcSSimon Schubert 	}
13045796c8dcSSimon Schubert 
13055796c8dcSSimon Schubert       if (bfd_bread (bfd_ardata (abfd)->extended_names, amt, abfd) != amt)
13065796c8dcSSimon Schubert 	{
13075796c8dcSSimon Schubert 	  if (bfd_get_error () != bfd_error_system_call)
13085796c8dcSSimon Schubert 	    bfd_set_error (bfd_error_malformed_archive);
13095796c8dcSSimon Schubert 	  bfd_release (abfd, (bfd_ardata (abfd)->extended_names));
13105796c8dcSSimon Schubert 	  bfd_ardata (abfd)->extended_names = NULL;
13115796c8dcSSimon Schubert 	  goto byebye;
13125796c8dcSSimon Schubert 	}
13135796c8dcSSimon Schubert 
13145796c8dcSSimon Schubert       /* Since the archive is supposed to be printable if it contains
13155796c8dcSSimon Schubert 	 text, the entries in the list are newline-padded, not null
13165796c8dcSSimon Schubert 	 padded. In SVR4-style archives, the names also have a
13175796c8dcSSimon Schubert 	 trailing '/'.  DOS/NT created archive often have \ in them
13185796c8dcSSimon Schubert 	 We'll fix all problems here..  */
13195796c8dcSSimon Schubert       {
13205796c8dcSSimon Schubert 	char *ext_names = bfd_ardata (abfd)->extended_names;
13215796c8dcSSimon Schubert 	char *temp = ext_names;
13225796c8dcSSimon Schubert 	char *limit = temp + namedata->parsed_size;
13235796c8dcSSimon Schubert 	for (; temp < limit; ++temp)
13245796c8dcSSimon Schubert 	  {
13255796c8dcSSimon Schubert 	    if (*temp == ARFMAG[1])
13265796c8dcSSimon Schubert 	      temp[temp > ext_names && temp[-1] == '/' ? -1 : 0] = '\0';
13275796c8dcSSimon Schubert 	    if (*temp == '\\')
13285796c8dcSSimon Schubert 	      *temp = '/';
13295796c8dcSSimon Schubert 	  }
13305796c8dcSSimon Schubert 	*limit = '\0';
13315796c8dcSSimon Schubert       }
13325796c8dcSSimon Schubert 
13335796c8dcSSimon Schubert       /* Pad to an even boundary if you have to.  */
13345796c8dcSSimon Schubert       bfd_ardata (abfd)->first_file_filepos = bfd_tell (abfd);
13355796c8dcSSimon Schubert       bfd_ardata (abfd)->first_file_filepos +=
13365796c8dcSSimon Schubert 	(bfd_ardata (abfd)->first_file_filepos) % 2;
13375796c8dcSSimon Schubert 
1338*ef5ccd6cSJohn Marino       free (namedata);
13395796c8dcSSimon Schubert     }
13405796c8dcSSimon Schubert   return TRUE;
13415796c8dcSSimon Schubert }
13425796c8dcSSimon Schubert 
13435796c8dcSSimon Schubert #ifdef VMS
13445796c8dcSSimon Schubert 
13455796c8dcSSimon Schubert /* Return a copy of the stuff in the filename between any :]> and a
13465796c8dcSSimon Schubert    semicolon.  */
13475796c8dcSSimon Schubert 
13485796c8dcSSimon Schubert static const char *
normalize(bfd * abfd,const char * file)13495796c8dcSSimon Schubert normalize (bfd *abfd, const char *file)
13505796c8dcSSimon Schubert {
13515796c8dcSSimon Schubert   const char *first;
13525796c8dcSSimon Schubert   const char *last;
13535796c8dcSSimon Schubert   char *copy;
13545796c8dcSSimon Schubert 
13555796c8dcSSimon Schubert   first = file + strlen (file) - 1;
13565796c8dcSSimon Schubert   last = first + 1;
13575796c8dcSSimon Schubert 
13585796c8dcSSimon Schubert   while (first != file)
13595796c8dcSSimon Schubert     {
13605796c8dcSSimon Schubert       if (*first == ';')
13615796c8dcSSimon Schubert 	last = first;
13625796c8dcSSimon Schubert       if (*first == ':' || *first == ']' || *first == '>')
13635796c8dcSSimon Schubert 	{
13645796c8dcSSimon Schubert 	  first++;
13655796c8dcSSimon Schubert 	  break;
13665796c8dcSSimon Schubert 	}
13675796c8dcSSimon Schubert       first--;
13685796c8dcSSimon Schubert     }
13695796c8dcSSimon Schubert 
13705796c8dcSSimon Schubert   copy = bfd_alloc (abfd, last - first + 1);
13715796c8dcSSimon Schubert   if (copy == NULL)
13725796c8dcSSimon Schubert     return NULL;
13735796c8dcSSimon Schubert 
13745796c8dcSSimon Schubert   memcpy (copy, first, last - first);
13755796c8dcSSimon Schubert   copy[last - first] = 0;
13765796c8dcSSimon Schubert 
13775796c8dcSSimon Schubert   return copy;
13785796c8dcSSimon Schubert }
13795796c8dcSSimon Schubert 
13805796c8dcSSimon Schubert #else
13815796c8dcSSimon Schubert static const char *
normalize(bfd * abfd ATTRIBUTE_UNUSED,const char * file)13825796c8dcSSimon Schubert normalize (bfd *abfd ATTRIBUTE_UNUSED, const char *file)
13835796c8dcSSimon Schubert {
1384cf7f2e2dSJohn Marino   return lbasename (file);
13855796c8dcSSimon Schubert }
13865796c8dcSSimon Schubert #endif
13875796c8dcSSimon Schubert 
1388a45ae5f8SJohn Marino /* Adjust a relative path name based on the reference path.
1389a45ae5f8SJohn Marino    For example:
1390a45ae5f8SJohn Marino 
1391a45ae5f8SJohn Marino      Relative path  Reference path  Result
1392a45ae5f8SJohn Marino      -------------  --------------  ------
1393a45ae5f8SJohn Marino      bar.o          lib.a           bar.o
1394a45ae5f8SJohn Marino      foo/bar.o      lib.a           foo/bar.o
1395a45ae5f8SJohn Marino      bar.o          foo/lib.a       ../bar.o
1396a45ae5f8SJohn Marino      foo/bar.o      baz/lib.a       ../foo/bar.o
1397a45ae5f8SJohn Marino      bar.o          ../lib.a        <parent of current dir>/bar.o
1398a45ae5f8SJohn Marino    ; ../bar.o       ../lib.a        bar.o
1399a45ae5f8SJohn Marino    ; ../bar.o       lib.a           ../bar.o
1400a45ae5f8SJohn Marino      foo/bar.o      ../lib.a        <parent of current dir>/foo/bar.o
1401a45ae5f8SJohn Marino      bar.o          ../../lib.a     <grandparent>/<parent>/bar.o
1402a45ae5f8SJohn Marino      bar.o          foo/baz/lib.a   ../../bar.o
1403a45ae5f8SJohn Marino 
1404a45ae5f8SJohn Marino    Note - the semicolons above are there to prevent the BFD chew
1405a45ae5f8SJohn Marino    utility from interpreting those lines as prototypes to put into
1406a45ae5f8SJohn Marino    the autogenerated bfd.h header...
1407a45ae5f8SJohn Marino 
1408a45ae5f8SJohn Marino    Note - the string is returned in a static buffer.  */
14095796c8dcSSimon Schubert 
14105796c8dcSSimon Schubert static const char *
adjust_relative_path(const char * path,const char * ref_path)14115796c8dcSSimon Schubert adjust_relative_path (const char * path, const char * ref_path)
14125796c8dcSSimon Schubert {
14135796c8dcSSimon Schubert   static char *pathbuf = NULL;
1414a45ae5f8SJohn Marino   static unsigned int pathbuf_len = 0;
1415a45ae5f8SJohn Marino   const char *pathp;
1416a45ae5f8SJohn Marino   const char *refp;
1417a45ae5f8SJohn Marino   char * lpath;
1418a45ae5f8SJohn Marino   char * rpath;
1419a45ae5f8SJohn Marino   unsigned int len;
1420a45ae5f8SJohn Marino   unsigned int dir_up = 0;
1421a45ae5f8SJohn Marino   unsigned int dir_down = 0;
14225796c8dcSSimon Schubert   char *newp;
1423a45ae5f8SJohn Marino   char * pwd = getpwd ();
1424a45ae5f8SJohn Marino   const char * down;
1425a45ae5f8SJohn Marino 
1426a45ae5f8SJohn Marino   /* Remove symlinks, '.' and '..' from the paths, if possible.  */
1427a45ae5f8SJohn Marino   lpath = lrealpath (path);
1428a45ae5f8SJohn Marino   pathp = lpath == NULL ? path : lpath;
1429a45ae5f8SJohn Marino 
1430a45ae5f8SJohn Marino   rpath = lrealpath (ref_path);
1431a45ae5f8SJohn Marino   refp = rpath == NULL ? ref_path : rpath;
14325796c8dcSSimon Schubert 
14335796c8dcSSimon Schubert   /* Remove common leading path elements.  */
14345796c8dcSSimon Schubert   for (;;)
14355796c8dcSSimon Schubert     {
14365796c8dcSSimon Schubert       const char *e1 = pathp;
14375796c8dcSSimon Schubert       const char *e2 = refp;
14385796c8dcSSimon Schubert 
14395796c8dcSSimon Schubert       while (*e1 && ! IS_DIR_SEPARATOR (*e1))
14405796c8dcSSimon Schubert 	++e1;
14415796c8dcSSimon Schubert       while (*e2 && ! IS_DIR_SEPARATOR (*e2))
14425796c8dcSSimon Schubert 	++e2;
14435796c8dcSSimon Schubert       if (*e1 == '\0' || *e2 == '\0' || e1 - pathp != e2 - refp
1444c50c785cSJohn Marino 	  || filename_ncmp (pathp, refp, e1 - pathp) != 0)
14455796c8dcSSimon Schubert 	break;
14465796c8dcSSimon Schubert       pathp = e1 + 1;
14475796c8dcSSimon Schubert       refp = e2 + 1;
14485796c8dcSSimon Schubert     }
14495796c8dcSSimon Schubert 
1450a45ae5f8SJohn Marino   len = strlen (pathp) + 1;
14515796c8dcSSimon Schubert   /* For each leading path element in the reference path,
14525796c8dcSSimon Schubert      insert "../" into the path.  */
14535796c8dcSSimon Schubert   for (; *refp; ++refp)
14545796c8dcSSimon Schubert     if (IS_DIR_SEPARATOR (*refp))
1455a45ae5f8SJohn Marino       {
1456a45ae5f8SJohn Marino 	/* PR 12710:  If the path element is "../" then instead of
1457a45ae5f8SJohn Marino 	   inserting "../" we need to insert the name of the directory
1458a45ae5f8SJohn Marino 	   at the current level.  */
1459a45ae5f8SJohn Marino 	if (refp > ref_path + 1
1460a45ae5f8SJohn Marino 	    && refp[-1] == '.'
1461a45ae5f8SJohn Marino 	    && refp[-2] == '.')
1462a45ae5f8SJohn Marino 	  dir_down ++;
1463a45ae5f8SJohn Marino 	else
1464a45ae5f8SJohn Marino 	  dir_up ++;
1465a45ae5f8SJohn Marino       }
1466a45ae5f8SJohn Marino 
1467a45ae5f8SJohn Marino   /* If the lrealpath calls above succeeded then we should never
1468a45ae5f8SJohn Marino      see dir_up and dir_down both being non-zero.  */
1469a45ae5f8SJohn Marino 
1470a45ae5f8SJohn Marino   len += 3 * dir_up;
1471a45ae5f8SJohn Marino 
1472a45ae5f8SJohn Marino   if (dir_down)
1473a45ae5f8SJohn Marino     {
1474a45ae5f8SJohn Marino       down = pwd + strlen (pwd) - 1;
1475a45ae5f8SJohn Marino 
1476a45ae5f8SJohn Marino       while (dir_down && down > pwd)
1477a45ae5f8SJohn Marino 	{
1478a45ae5f8SJohn Marino 	  if (IS_DIR_SEPARATOR (*down))
1479a45ae5f8SJohn Marino 	    --dir_down;
1480a45ae5f8SJohn Marino 	}
1481a45ae5f8SJohn Marino       BFD_ASSERT (dir_down == 0);
1482a45ae5f8SJohn Marino       len += strlen (down) + 1;
1483a45ae5f8SJohn Marino     }
1484a45ae5f8SJohn Marino   else
1485a45ae5f8SJohn Marino     down = NULL;
14865796c8dcSSimon Schubert 
14875796c8dcSSimon Schubert   if (len > pathbuf_len)
14885796c8dcSSimon Schubert     {
14895796c8dcSSimon Schubert       if (pathbuf != NULL)
14905796c8dcSSimon Schubert 	free (pathbuf);
14915796c8dcSSimon Schubert       pathbuf_len = 0;
14925796c8dcSSimon Schubert       pathbuf = (char *) bfd_malloc (len);
14935796c8dcSSimon Schubert       if (pathbuf == NULL)
1494a45ae5f8SJohn Marino 	goto out;
14955796c8dcSSimon Schubert       pathbuf_len = len;
14965796c8dcSSimon Schubert     }
14975796c8dcSSimon Schubert 
14985796c8dcSSimon Schubert   newp = pathbuf;
1499a45ae5f8SJohn Marino   while (dir_up-- > 0)
15005796c8dcSSimon Schubert     {
15015796c8dcSSimon Schubert       /* FIXME: Support Windows style path separators as well.  */
15025796c8dcSSimon Schubert       strcpy (newp, "../");
15035796c8dcSSimon Schubert       newp += 3;
15045796c8dcSSimon Schubert     }
1505a45ae5f8SJohn Marino 
1506a45ae5f8SJohn Marino   if (down)
1507a45ae5f8SJohn Marino     sprintf (newp, "%s/%s", down, pathp);
1508a45ae5f8SJohn Marino   else
15095796c8dcSSimon Schubert     strcpy (newp, pathp);
15105796c8dcSSimon Schubert 
1511a45ae5f8SJohn Marino  out:
1512a45ae5f8SJohn Marino   free (lpath);
1513a45ae5f8SJohn Marino   free (rpath);
15145796c8dcSSimon Schubert   return pathbuf;
15155796c8dcSSimon Schubert }
15165796c8dcSSimon Schubert 
15175796c8dcSSimon Schubert /* Build a BFD style extended name table.  */
15185796c8dcSSimon Schubert 
15195796c8dcSSimon Schubert bfd_boolean
_bfd_archive_bsd_construct_extended_name_table(bfd * abfd,char ** tabloc,bfd_size_type * tablen,const char ** name)15205796c8dcSSimon Schubert _bfd_archive_bsd_construct_extended_name_table (bfd *abfd,
15215796c8dcSSimon Schubert 						char **tabloc,
15225796c8dcSSimon Schubert 						bfd_size_type *tablen,
15235796c8dcSSimon Schubert 						const char **name)
15245796c8dcSSimon Schubert {
15255796c8dcSSimon Schubert   *name = "ARFILENAMES/";
15265796c8dcSSimon Schubert   return _bfd_construct_extended_name_table (abfd, FALSE, tabloc, tablen);
15275796c8dcSSimon Schubert }
15285796c8dcSSimon Schubert 
15295796c8dcSSimon Schubert /* Build an SVR4 style extended name table.  */
15305796c8dcSSimon Schubert 
15315796c8dcSSimon Schubert bfd_boolean
_bfd_archive_coff_construct_extended_name_table(bfd * abfd,char ** tabloc,bfd_size_type * tablen,const char ** name)15325796c8dcSSimon Schubert _bfd_archive_coff_construct_extended_name_table (bfd *abfd,
15335796c8dcSSimon Schubert 						 char **tabloc,
15345796c8dcSSimon Schubert 						 bfd_size_type *tablen,
15355796c8dcSSimon Schubert 						 const char **name)
15365796c8dcSSimon Schubert {
15375796c8dcSSimon Schubert   *name = "//";
15385796c8dcSSimon Schubert   return _bfd_construct_extended_name_table (abfd, TRUE, tabloc, tablen);
15395796c8dcSSimon Schubert }
15405796c8dcSSimon Schubert 
15415796c8dcSSimon Schubert /* Follows archive_head and produces an extended name table if
15425796c8dcSSimon Schubert    necessary.  Returns (in tabloc) a pointer to an extended name
15435796c8dcSSimon Schubert    table, and in tablen the length of the table.  If it makes an entry
15445796c8dcSSimon Schubert    it clobbers the filename so that the element may be written without
15455796c8dcSSimon Schubert    further massage.  Returns TRUE if it ran successfully, FALSE if
15465796c8dcSSimon Schubert    something went wrong.  A successful return may still involve a
15475796c8dcSSimon Schubert    zero-length tablen!  */
15485796c8dcSSimon Schubert 
15495796c8dcSSimon Schubert bfd_boolean
_bfd_construct_extended_name_table(bfd * abfd,bfd_boolean trailing_slash,char ** tabloc,bfd_size_type * tablen)15505796c8dcSSimon Schubert _bfd_construct_extended_name_table (bfd *abfd,
15515796c8dcSSimon Schubert 				    bfd_boolean trailing_slash,
15525796c8dcSSimon Schubert 				    char **tabloc,
15535796c8dcSSimon Schubert 				    bfd_size_type *tablen)
15545796c8dcSSimon Schubert {
1555a45ae5f8SJohn Marino   unsigned int maxname = ar_maxnamelen (abfd);
15565796c8dcSSimon Schubert   bfd_size_type total_namelen = 0;
15575796c8dcSSimon Schubert   bfd *current;
15585796c8dcSSimon Schubert   char *strptr;
15595796c8dcSSimon Schubert   const char *last_filename;
15605796c8dcSSimon Schubert   long last_stroff;
15615796c8dcSSimon Schubert 
15625796c8dcSSimon Schubert   *tablen = 0;
15635796c8dcSSimon Schubert   last_filename = NULL;
15645796c8dcSSimon Schubert 
15655796c8dcSSimon Schubert   /* Figure out how long the table should be.  */
15665796c8dcSSimon Schubert   for (current = abfd->archive_head;
15675796c8dcSSimon Schubert        current != NULL;
15685796c8dcSSimon Schubert        current = current->archive_next)
15695796c8dcSSimon Schubert     {
15705796c8dcSSimon Schubert       const char *normal;
15715796c8dcSSimon Schubert       unsigned int thislen;
15725796c8dcSSimon Schubert 
15735796c8dcSSimon Schubert       if (bfd_is_thin_archive (abfd))
15745796c8dcSSimon Schubert 	{
15755796c8dcSSimon Schubert 	  const char *filename = current->filename;
15765796c8dcSSimon Schubert 
15775796c8dcSSimon Schubert 	  /* If the element being added is a member of another archive
15785796c8dcSSimon Schubert 	     (i.e., we are flattening), use the containing archive's name.  */
15795796c8dcSSimon Schubert 	  if (current->my_archive
15805796c8dcSSimon Schubert 	      && ! bfd_is_thin_archive (current->my_archive))
15815796c8dcSSimon Schubert 	    filename = current->my_archive->filename;
15825796c8dcSSimon Schubert 
15835796c8dcSSimon Schubert 	  /* If the path is the same as the previous path seen,
15845796c8dcSSimon Schubert 	     reuse it.  This can happen when flattening a thin
15855796c8dcSSimon Schubert 	     archive that contains other archives.  */
1586c50c785cSJohn Marino 	  if (last_filename && filename_cmp (last_filename, filename) == 0)
15875796c8dcSSimon Schubert 	    continue;
15885796c8dcSSimon Schubert 
15895796c8dcSSimon Schubert 	  last_filename = filename;
15905796c8dcSSimon Schubert 
15915796c8dcSSimon Schubert 	  /* If the path is relative, adjust it relative to
15925796c8dcSSimon Schubert 	     the containing archive. */
15935796c8dcSSimon Schubert 	  if (! IS_ABSOLUTE_PATH (filename)
15945796c8dcSSimon Schubert 	      && ! IS_ABSOLUTE_PATH (abfd->filename))
15955796c8dcSSimon Schubert 	    normal = adjust_relative_path (filename, abfd->filename);
15965796c8dcSSimon Schubert 	  else
15975796c8dcSSimon Schubert 	    normal = filename;
15985796c8dcSSimon Schubert 
15995796c8dcSSimon Schubert 	  /* In a thin archive, always store the full pathname
16005796c8dcSSimon Schubert 	     in the extended name table.  */
16015796c8dcSSimon Schubert 	  total_namelen += strlen (normal) + 1;
16025796c8dcSSimon Schubert 	  if (trailing_slash)
16035796c8dcSSimon Schubert 	    /* Leave room for trailing slash.  */
16045796c8dcSSimon Schubert 	    ++total_namelen;
16055796c8dcSSimon Schubert 
16065796c8dcSSimon Schubert 	  continue;
16075796c8dcSSimon Schubert 	}
16085796c8dcSSimon Schubert 
16095796c8dcSSimon Schubert       normal = normalize (current, current->filename);
16105796c8dcSSimon Schubert       if (normal == NULL)
16115796c8dcSSimon Schubert 	return FALSE;
16125796c8dcSSimon Schubert 
16135796c8dcSSimon Schubert       thislen = strlen (normal);
16145796c8dcSSimon Schubert 
16155796c8dcSSimon Schubert       if (thislen > maxname
16165796c8dcSSimon Schubert 	  && (bfd_get_file_flags (abfd) & BFD_TRADITIONAL_FORMAT) != 0)
16175796c8dcSSimon Schubert 	thislen = maxname;
16185796c8dcSSimon Schubert 
16195796c8dcSSimon Schubert       if (thislen > maxname)
16205796c8dcSSimon Schubert 	{
16215796c8dcSSimon Schubert 	  /* Add one to leave room for \n.  */
16225796c8dcSSimon Schubert 	  total_namelen += thislen + 1;
16235796c8dcSSimon Schubert 	  if (trailing_slash)
16245796c8dcSSimon Schubert 	    {
16255796c8dcSSimon Schubert 	      /* Leave room for trailing slash.  */
16265796c8dcSSimon Schubert 	      ++total_namelen;
16275796c8dcSSimon Schubert 	    }
16285796c8dcSSimon Schubert 	}
16295796c8dcSSimon Schubert       else
16305796c8dcSSimon Schubert 	{
16315796c8dcSSimon Schubert 	  struct ar_hdr *hdr = arch_hdr (current);
1632c50c785cSJohn Marino 	  if (filename_ncmp (normal, hdr->ar_name, thislen) != 0
16335796c8dcSSimon Schubert 	      || (thislen < sizeof hdr->ar_name
16345796c8dcSSimon Schubert 		  && hdr->ar_name[thislen] != ar_padchar (current)))
16355796c8dcSSimon Schubert 	    {
16365796c8dcSSimon Schubert 	      /* Must have been using extended format even though it
16375796c8dcSSimon Schubert 		 didn't need to.  Fix it to use normal format.  */
16385796c8dcSSimon Schubert 	      memcpy (hdr->ar_name, normal, thislen);
16395796c8dcSSimon Schubert 	      if (thislen < maxname
16405796c8dcSSimon Schubert 		  || (thislen == maxname && thislen < sizeof hdr->ar_name))
16415796c8dcSSimon Schubert 		hdr->ar_name[thislen] = ar_padchar (current);
16425796c8dcSSimon Schubert 	    }
16435796c8dcSSimon Schubert 	}
16445796c8dcSSimon Schubert     }
16455796c8dcSSimon Schubert 
16465796c8dcSSimon Schubert   if (total_namelen == 0)
16475796c8dcSSimon Schubert     return TRUE;
16485796c8dcSSimon Schubert 
16495796c8dcSSimon Schubert   *tabloc = (char *) bfd_zalloc (abfd, total_namelen);
16505796c8dcSSimon Schubert   if (*tabloc == NULL)
16515796c8dcSSimon Schubert     return FALSE;
16525796c8dcSSimon Schubert 
16535796c8dcSSimon Schubert   *tablen = total_namelen;
16545796c8dcSSimon Schubert   strptr = *tabloc;
16555796c8dcSSimon Schubert 
16565796c8dcSSimon Schubert   last_filename = NULL;
16575796c8dcSSimon Schubert   last_stroff = 0;
16585796c8dcSSimon Schubert 
16595796c8dcSSimon Schubert   for (current = abfd->archive_head;
16605796c8dcSSimon Schubert        current != NULL;
16615796c8dcSSimon Schubert        current = current->archive_next)
16625796c8dcSSimon Schubert     {
16635796c8dcSSimon Schubert       const char *normal;
16645796c8dcSSimon Schubert       unsigned int thislen;
16655796c8dcSSimon Schubert       long stroff;
16665796c8dcSSimon Schubert       const char *filename = current->filename;
16675796c8dcSSimon Schubert 
16685796c8dcSSimon Schubert       if (bfd_is_thin_archive (abfd))
16695796c8dcSSimon Schubert 	{
16705796c8dcSSimon Schubert 	  /* If the element being added is a member of another archive
16715796c8dcSSimon Schubert 	     (i.e., we are flattening), use the containing archive's name.  */
16725796c8dcSSimon Schubert 	  if (current->my_archive
16735796c8dcSSimon Schubert 	      && ! bfd_is_thin_archive (current->my_archive))
16745796c8dcSSimon Schubert 	    filename = current->my_archive->filename;
16755796c8dcSSimon Schubert 	  /* If the path is the same as the previous path seen,
16765796c8dcSSimon Schubert 	     reuse it.  This can happen when flattening a thin
16775796c8dcSSimon Schubert 	     archive that contains other archives.
16785796c8dcSSimon Schubert 	     If the path is relative, adjust it relative to
16795796c8dcSSimon Schubert 	     the containing archive.  */
1680c50c785cSJohn Marino 	  if (last_filename && filename_cmp (last_filename, filename) == 0)
16815796c8dcSSimon Schubert 	    normal = last_filename;
16825796c8dcSSimon Schubert 	  else if (! IS_ABSOLUTE_PATH (filename)
16835796c8dcSSimon Schubert 		   && ! IS_ABSOLUTE_PATH (abfd->filename))
16845796c8dcSSimon Schubert 	    normal = adjust_relative_path (filename, abfd->filename);
16855796c8dcSSimon Schubert 	  else
16865796c8dcSSimon Schubert 	    normal = filename;
16875796c8dcSSimon Schubert 	}
16885796c8dcSSimon Schubert       else
16895796c8dcSSimon Schubert 	{
16905796c8dcSSimon Schubert 	  normal = normalize (current, filename);
16915796c8dcSSimon Schubert 	  if (normal == NULL)
16925796c8dcSSimon Schubert 	    return FALSE;
16935796c8dcSSimon Schubert 	}
16945796c8dcSSimon Schubert 
16955796c8dcSSimon Schubert       thislen = strlen (normal);
16965796c8dcSSimon Schubert       if (thislen > maxname || bfd_is_thin_archive (abfd))
16975796c8dcSSimon Schubert 	{
16985796c8dcSSimon Schubert 	  /* Works for now; may need to be re-engineered if we
16995796c8dcSSimon Schubert 	     encounter an oddball archive format and want to
17005796c8dcSSimon Schubert 	     generalise this hack.  */
17015796c8dcSSimon Schubert 	  struct ar_hdr *hdr = arch_hdr (current);
17025796c8dcSSimon Schubert 	  if (normal == last_filename)
17035796c8dcSSimon Schubert 	    stroff = last_stroff;
17045796c8dcSSimon Schubert 	  else
17055796c8dcSSimon Schubert 	    {
17065796c8dcSSimon Schubert 	      strcpy (strptr, normal);
17075796c8dcSSimon Schubert 	      if (! trailing_slash)
17085796c8dcSSimon Schubert 		strptr[thislen] = ARFMAG[1];
17095796c8dcSSimon Schubert 	      else
17105796c8dcSSimon Schubert 		{
17115796c8dcSSimon Schubert 		  strptr[thislen] = '/';
17125796c8dcSSimon Schubert 		  strptr[thislen + 1] = ARFMAG[1];
17135796c8dcSSimon Schubert 		}
17145796c8dcSSimon Schubert 	      stroff = strptr - *tabloc;
17155796c8dcSSimon Schubert 	      last_stroff = stroff;
17165796c8dcSSimon Schubert 	    }
17175796c8dcSSimon Schubert 	  hdr->ar_name[0] = ar_padchar (current);
17185796c8dcSSimon Schubert 	  if (bfd_is_thin_archive (abfd) && current->origin > 0)
17195796c8dcSSimon Schubert 	    {
17205796c8dcSSimon Schubert 	      int len = snprintf (hdr->ar_name + 1, maxname - 1, "%-ld:",
17215796c8dcSSimon Schubert 				  stroff);
17225796c8dcSSimon Schubert 	      _bfd_ar_spacepad (hdr->ar_name + 1 + len, maxname - 1 - len,
17235796c8dcSSimon Schubert 				"%-ld",
17245796c8dcSSimon Schubert 				current->origin - sizeof (struct ar_hdr));
17255796c8dcSSimon Schubert 	    }
17265796c8dcSSimon Schubert 	  else
17275796c8dcSSimon Schubert 	    _bfd_ar_spacepad (hdr->ar_name + 1, maxname - 1, "%-ld", stroff);
17285796c8dcSSimon Schubert 	  if (normal != last_filename)
17295796c8dcSSimon Schubert 	    {
17305796c8dcSSimon Schubert 	      strptr += thislen + 1;
17315796c8dcSSimon Schubert 	      if (trailing_slash)
17325796c8dcSSimon Schubert 		++strptr;
17335796c8dcSSimon Schubert 	      last_filename = filename;
17345796c8dcSSimon Schubert 	    }
17355796c8dcSSimon Schubert 	}
17365796c8dcSSimon Schubert     }
17375796c8dcSSimon Schubert 
17385796c8dcSSimon Schubert   return TRUE;
17395796c8dcSSimon Schubert }
1740cf7f2e2dSJohn Marino 
1741cf7f2e2dSJohn Marino /* Do not construct an extended name table but transforms name field into
1742cf7f2e2dSJohn Marino    its extended form.  */
1743cf7f2e2dSJohn Marino 
1744cf7f2e2dSJohn Marino bfd_boolean
_bfd_archive_bsd44_construct_extended_name_table(bfd * abfd,char ** tabloc,bfd_size_type * tablen,const char ** name)1745cf7f2e2dSJohn Marino _bfd_archive_bsd44_construct_extended_name_table (bfd *abfd,
1746cf7f2e2dSJohn Marino 						  char **tabloc,
1747cf7f2e2dSJohn Marino 						  bfd_size_type *tablen,
1748cf7f2e2dSJohn Marino 						  const char **name)
1749cf7f2e2dSJohn Marino {
1750a45ae5f8SJohn Marino   unsigned int maxname = ar_maxnamelen (abfd);
1751cf7f2e2dSJohn Marino   bfd *current;
1752cf7f2e2dSJohn Marino 
1753cf7f2e2dSJohn Marino   *tablen = 0;
1754cf7f2e2dSJohn Marino   *tabloc = NULL;
1755cf7f2e2dSJohn Marino   *name = NULL;
1756cf7f2e2dSJohn Marino 
1757cf7f2e2dSJohn Marino   for (current = abfd->archive_head;
1758cf7f2e2dSJohn Marino        current != NULL;
1759cf7f2e2dSJohn Marino        current = current->archive_next)
1760cf7f2e2dSJohn Marino     {
1761cf7f2e2dSJohn Marino       const char *normal = normalize (current, current->filename);
1762cf7f2e2dSJohn Marino       int has_space = 0;
1763cf7f2e2dSJohn Marino       unsigned int len;
1764cf7f2e2dSJohn Marino 
1765cf7f2e2dSJohn Marino       if (normal == NULL)
1766cf7f2e2dSJohn Marino 	return FALSE;
1767cf7f2e2dSJohn Marino 
1768cf7f2e2dSJohn Marino       for (len = 0; normal[len]; len++)
1769cf7f2e2dSJohn Marino 	if (normal[len] == ' ')
1770cf7f2e2dSJohn Marino 	  has_space = 1;
1771cf7f2e2dSJohn Marino 
1772cf7f2e2dSJohn Marino       if (len > maxname || has_space)
1773cf7f2e2dSJohn Marino 	{
1774cf7f2e2dSJohn Marino 	  struct ar_hdr *hdr = arch_hdr (current);
1775cf7f2e2dSJohn Marino 
1776cf7f2e2dSJohn Marino 	  len = (len + 3) & ~3;
1777cf7f2e2dSJohn Marino 	  arch_eltdata (current)->extra_size = len;
1778c50c785cSJohn Marino 	  _bfd_ar_spacepad (hdr->ar_name, maxname, "#1/%lu", len);
1779cf7f2e2dSJohn Marino 	}
1780cf7f2e2dSJohn Marino     }
1781cf7f2e2dSJohn Marino 
1782cf7f2e2dSJohn Marino   return TRUE;
1783cf7f2e2dSJohn Marino }
1784cf7f2e2dSJohn Marino 
1785cf7f2e2dSJohn Marino /* Write an archive header.  */
1786cf7f2e2dSJohn Marino 
1787cf7f2e2dSJohn Marino bfd_boolean
_bfd_generic_write_ar_hdr(bfd * archive,bfd * abfd)1788cf7f2e2dSJohn Marino _bfd_generic_write_ar_hdr (bfd *archive, bfd *abfd)
1789cf7f2e2dSJohn Marino {
1790cf7f2e2dSJohn Marino   struct ar_hdr *hdr = arch_hdr (abfd);
1791cf7f2e2dSJohn Marino 
1792cf7f2e2dSJohn Marino   if (bfd_bwrite (hdr, sizeof (*hdr), archive) != sizeof (*hdr))
1793cf7f2e2dSJohn Marino     return FALSE;
1794cf7f2e2dSJohn Marino   return TRUE;
1795cf7f2e2dSJohn Marino }
1796cf7f2e2dSJohn Marino 
1797cf7f2e2dSJohn Marino /* Write an archive header using BSD4.4 convention.  */
1798cf7f2e2dSJohn Marino 
1799cf7f2e2dSJohn Marino bfd_boolean
_bfd_bsd44_write_ar_hdr(bfd * archive,bfd * abfd)1800cf7f2e2dSJohn Marino _bfd_bsd44_write_ar_hdr (bfd *archive, bfd *abfd)
1801cf7f2e2dSJohn Marino {
1802cf7f2e2dSJohn Marino   struct ar_hdr *hdr = arch_hdr (abfd);
1803cf7f2e2dSJohn Marino 
1804cf7f2e2dSJohn Marino   if (is_bsd44_extended_name (hdr->ar_name))
1805cf7f2e2dSJohn Marino     {
1806cf7f2e2dSJohn Marino       /* This is a BSD 4.4 extended name.  */
1807cf7f2e2dSJohn Marino       const char *fullname = normalize (abfd, abfd->filename);
1808cf7f2e2dSJohn Marino       unsigned int len = strlen (fullname);
1809cf7f2e2dSJohn Marino       unsigned int padded_len = (len + 3) & ~3;
1810cf7f2e2dSJohn Marino 
1811cf7f2e2dSJohn Marino       BFD_ASSERT (padded_len == arch_eltdata (abfd)->extra_size);
1812cf7f2e2dSJohn Marino 
1813*ef5ccd6cSJohn Marino       if (!_bfd_ar_sizepad (hdr->ar_size, sizeof (hdr->ar_size),
1814*ef5ccd6cSJohn Marino 			    arch_eltdata (abfd)->parsed_size + padded_len))
1815*ef5ccd6cSJohn Marino 	return FALSE;
1816cf7f2e2dSJohn Marino 
1817cf7f2e2dSJohn Marino       if (bfd_bwrite (hdr, sizeof (*hdr), archive) != sizeof (*hdr))
1818cf7f2e2dSJohn Marino 	return FALSE;
1819cf7f2e2dSJohn Marino 
1820cf7f2e2dSJohn Marino       if (bfd_bwrite (fullname, len, archive) != len)
1821cf7f2e2dSJohn Marino 	return FALSE;
1822*ef5ccd6cSJohn Marino 
1823cf7f2e2dSJohn Marino       if (len & 3)
1824cf7f2e2dSJohn Marino 	{
1825cf7f2e2dSJohn Marino 	  static const char pad[3] = { 0, 0, 0 };
1826cf7f2e2dSJohn Marino 
1827cf7f2e2dSJohn Marino 	  len = 4 - (len & 3);
1828cf7f2e2dSJohn Marino 	  if (bfd_bwrite (pad, len, archive) != len)
1829cf7f2e2dSJohn Marino 	    return FALSE;
1830cf7f2e2dSJohn Marino 	}
1831cf7f2e2dSJohn Marino     }
1832cf7f2e2dSJohn Marino   else
1833cf7f2e2dSJohn Marino     {
1834cf7f2e2dSJohn Marino       if (bfd_bwrite (hdr, sizeof (*hdr), archive) != sizeof (*hdr))
1835cf7f2e2dSJohn Marino 	return FALSE;
1836cf7f2e2dSJohn Marino     }
1837cf7f2e2dSJohn Marino   return TRUE;
1838cf7f2e2dSJohn Marino }
18395796c8dcSSimon Schubert 
18405796c8dcSSimon Schubert /* A couple of functions for creating ar_hdrs.  */
18415796c8dcSSimon Schubert 
18425796c8dcSSimon Schubert #ifdef HPUX_LARGE_AR_IDS
18435796c8dcSSimon Schubert /* Function to encode large UID/GID values according to HP.  */
18445796c8dcSSimon Schubert 
18455796c8dcSSimon Schubert static void
hpux_uid_gid_encode(char str[6],long int id)18465796c8dcSSimon Schubert hpux_uid_gid_encode (char str[6], long int id)
18475796c8dcSSimon Schubert {
18485796c8dcSSimon Schubert   int cnt;
18495796c8dcSSimon Schubert 
18505796c8dcSSimon Schubert   str[5] = '@' + (id & 3);
18515796c8dcSSimon Schubert   id >>= 2;
18525796c8dcSSimon Schubert 
18535796c8dcSSimon Schubert   for (cnt = 4; cnt >= 0; --cnt, id >>= 6)
18545796c8dcSSimon Schubert     str[cnt] = ' ' + (id & 0x3f);
18555796c8dcSSimon Schubert }
18565796c8dcSSimon Schubert #endif	/* HPUX_LARGE_AR_IDS */
18575796c8dcSSimon Schubert 
18585796c8dcSSimon Schubert #ifndef HAVE_GETUID
18595796c8dcSSimon Schubert #define getuid() 0
18605796c8dcSSimon Schubert #endif
18615796c8dcSSimon Schubert 
18625796c8dcSSimon Schubert #ifndef HAVE_GETGID
18635796c8dcSSimon Schubert #define getgid() 0
18645796c8dcSSimon Schubert #endif
18655796c8dcSSimon Schubert 
18665796c8dcSSimon Schubert /* Takes a filename, returns an arelt_data for it, or NULL if it can't
18675796c8dcSSimon Schubert    make one.  The filename must refer to a filename in the filesystem.
18685796c8dcSSimon Schubert    The filename field of the ar_hdr will NOT be initialized.  If member
18695796c8dcSSimon Schubert    is set, and it's an in-memory bfd, we fake it.  */
18705796c8dcSSimon Schubert 
18715796c8dcSSimon Schubert static struct areltdata *
bfd_ar_hdr_from_filesystem(bfd * abfd,const char * filename,bfd * member)18725796c8dcSSimon Schubert bfd_ar_hdr_from_filesystem (bfd *abfd, const char *filename, bfd *member)
18735796c8dcSSimon Schubert {
18745796c8dcSSimon Schubert   struct stat status;
18755796c8dcSSimon Schubert   struct areltdata *ared;
18765796c8dcSSimon Schubert   struct ar_hdr *hdr;
18775796c8dcSSimon Schubert   bfd_size_type amt;
18785796c8dcSSimon Schubert 
18795796c8dcSSimon Schubert   if (member && (member->flags & BFD_IN_MEMORY) != 0)
18805796c8dcSSimon Schubert     {
18815796c8dcSSimon Schubert       /* Assume we just "made" the member, and fake it.  */
18825796c8dcSSimon Schubert       struct bfd_in_memory *bim = (struct bfd_in_memory *) member->iostream;
18835796c8dcSSimon Schubert       time (&status.st_mtime);
18845796c8dcSSimon Schubert       status.st_uid = getuid ();
18855796c8dcSSimon Schubert       status.st_gid = getgid ();
18865796c8dcSSimon Schubert       status.st_mode = 0644;
18875796c8dcSSimon Schubert       status.st_size = bim->size;
18885796c8dcSSimon Schubert     }
18895796c8dcSSimon Schubert   else if (stat (filename, &status) != 0)
18905796c8dcSSimon Schubert     {
18915796c8dcSSimon Schubert       bfd_set_error (bfd_error_system_call);
18925796c8dcSSimon Schubert       return NULL;
18935796c8dcSSimon Schubert     }
18945796c8dcSSimon Schubert 
18955796c8dcSSimon Schubert   /* If the caller requested that the BFD generate deterministic output,
18965796c8dcSSimon Schubert      fake values for modification time, UID, GID, and file mode.  */
18975796c8dcSSimon Schubert   if ((abfd->flags & BFD_DETERMINISTIC_OUTPUT) != 0)
18985796c8dcSSimon Schubert     {
18995796c8dcSSimon Schubert       status.st_mtime = 0;
19005796c8dcSSimon Schubert       status.st_uid = 0;
19015796c8dcSSimon Schubert       status.st_gid = 0;
19025796c8dcSSimon Schubert       status.st_mode = 0644;
19035796c8dcSSimon Schubert     }
19045796c8dcSSimon Schubert 
19055796c8dcSSimon Schubert   amt = sizeof (struct ar_hdr) + sizeof (struct areltdata);
1906*ef5ccd6cSJohn Marino   ared = (struct areltdata *) bfd_zmalloc (amt);
19075796c8dcSSimon Schubert   if (ared == NULL)
19085796c8dcSSimon Schubert     return NULL;
19095796c8dcSSimon Schubert   hdr = (struct ar_hdr *) (((char *) ared) + sizeof (struct areltdata));
19105796c8dcSSimon Schubert 
19115796c8dcSSimon Schubert   /* ar headers are space padded, not null padded!  */
19125796c8dcSSimon Schubert   memset (hdr, ' ', sizeof (struct ar_hdr));
19135796c8dcSSimon Schubert 
19145796c8dcSSimon Schubert   _bfd_ar_spacepad (hdr->ar_date, sizeof (hdr->ar_date), "%-12ld",
19155796c8dcSSimon Schubert 		    status.st_mtime);
19165796c8dcSSimon Schubert #ifdef HPUX_LARGE_AR_IDS
19175796c8dcSSimon Schubert   /* HP has a very "special" way to handle UID/GID's with numeric values
19185796c8dcSSimon Schubert      > 99999.  */
19195796c8dcSSimon Schubert   if (status.st_uid > 99999)
19205796c8dcSSimon Schubert     hpux_uid_gid_encode (hdr->ar_uid, (long) status.st_uid);
19215796c8dcSSimon Schubert   else
19225796c8dcSSimon Schubert #endif
19235796c8dcSSimon Schubert     _bfd_ar_spacepad (hdr->ar_uid, sizeof (hdr->ar_uid), "%ld",
19245796c8dcSSimon Schubert 		      status.st_uid);
19255796c8dcSSimon Schubert #ifdef HPUX_LARGE_AR_IDS
19265796c8dcSSimon Schubert   /* HP has a very "special" way to handle UID/GID's with numeric values
19275796c8dcSSimon Schubert      > 99999.  */
19285796c8dcSSimon Schubert   if (status.st_gid > 99999)
19295796c8dcSSimon Schubert     hpux_uid_gid_encode (hdr->ar_gid, (long) status.st_gid);
19305796c8dcSSimon Schubert   else
19315796c8dcSSimon Schubert #endif
19325796c8dcSSimon Schubert     _bfd_ar_spacepad (hdr->ar_gid, sizeof (hdr->ar_gid), "%ld",
19335796c8dcSSimon Schubert 		      status.st_gid);
19345796c8dcSSimon Schubert   _bfd_ar_spacepad (hdr->ar_mode, sizeof (hdr->ar_mode), "%-8lo",
19355796c8dcSSimon Schubert 		    status.st_mode);
1936*ef5ccd6cSJohn Marino   if (!_bfd_ar_sizepad (hdr->ar_size, sizeof (hdr->ar_size), status.st_size))
1937*ef5ccd6cSJohn Marino     {
1938*ef5ccd6cSJohn Marino       free (ared);
1939*ef5ccd6cSJohn Marino       return NULL;
1940*ef5ccd6cSJohn Marino     }
19415796c8dcSSimon Schubert   memcpy (hdr->ar_fmag, ARFMAG, 2);
19425796c8dcSSimon Schubert   ared->parsed_size = status.st_size;
19435796c8dcSSimon Schubert   ared->arch_header = (char *) hdr;
19445796c8dcSSimon Schubert 
19455796c8dcSSimon Schubert   return ared;
19465796c8dcSSimon Schubert }
19475796c8dcSSimon Schubert 
19485796c8dcSSimon Schubert /* Analogous to stat call.  */
19495796c8dcSSimon Schubert 
19505796c8dcSSimon Schubert int
bfd_generic_stat_arch_elt(bfd * abfd,struct stat * buf)19515796c8dcSSimon Schubert bfd_generic_stat_arch_elt (bfd *abfd, struct stat *buf)
19525796c8dcSSimon Schubert {
19535796c8dcSSimon Schubert   struct ar_hdr *hdr;
19545796c8dcSSimon Schubert   char *aloser;
19555796c8dcSSimon Schubert 
19565796c8dcSSimon Schubert   if (abfd->arelt_data == NULL)
19575796c8dcSSimon Schubert     {
19585796c8dcSSimon Schubert       bfd_set_error (bfd_error_invalid_operation);
19595796c8dcSSimon Schubert       return -1;
19605796c8dcSSimon Schubert     }
19615796c8dcSSimon Schubert 
19625796c8dcSSimon Schubert   hdr = arch_hdr (abfd);
19635796c8dcSSimon Schubert 
19645796c8dcSSimon Schubert #define foo(arelt, stelt, size)				\
19655796c8dcSSimon Schubert   buf->stelt = strtol (hdr->arelt, &aloser, size);	\
19665796c8dcSSimon Schubert   if (aloser == hdr->arelt)	      			\
19675796c8dcSSimon Schubert     return -1;
19685796c8dcSSimon Schubert 
19695796c8dcSSimon Schubert   /* Some platforms support special notations for large IDs.  */
19705796c8dcSSimon Schubert #ifdef HPUX_LARGE_AR_IDS
19715796c8dcSSimon Schubert # define foo2(arelt, stelt, size)					\
19725796c8dcSSimon Schubert   if (hdr->arelt[5] == ' ')						\
19735796c8dcSSimon Schubert     {									\
19745796c8dcSSimon Schubert       foo (arelt, stelt, size);						\
19755796c8dcSSimon Schubert     }									\
19765796c8dcSSimon Schubert   else									\
19775796c8dcSSimon Schubert     {									\
19785796c8dcSSimon Schubert       int cnt;								\
19795796c8dcSSimon Schubert       for (buf->stelt = cnt = 0; cnt < 5; ++cnt)			\
19805796c8dcSSimon Schubert 	{								\
19815796c8dcSSimon Schubert 	  if (hdr->arelt[cnt] < ' ' || hdr->arelt[cnt] > ' ' + 0x3f)	\
19825796c8dcSSimon Schubert 	    return -1;							\
19835796c8dcSSimon Schubert 	  buf->stelt <<= 6;						\
19845796c8dcSSimon Schubert 	  buf->stelt += hdr->arelt[cnt] - ' ';				\
19855796c8dcSSimon Schubert 	}								\
19865796c8dcSSimon Schubert       if (hdr->arelt[5] < '@' || hdr->arelt[5] > '@' + 3)		\
19875796c8dcSSimon Schubert 	return -1;							\
19885796c8dcSSimon Schubert       buf->stelt <<= 2;							\
19895796c8dcSSimon Schubert       buf->stelt += hdr->arelt[5] - '@';				\
19905796c8dcSSimon Schubert     }
19915796c8dcSSimon Schubert #else
19925796c8dcSSimon Schubert # define foo2(arelt, stelt, size) foo (arelt, stelt, size)
19935796c8dcSSimon Schubert #endif
19945796c8dcSSimon Schubert 
19955796c8dcSSimon Schubert   foo (ar_date, st_mtime, 10);
19965796c8dcSSimon Schubert   foo2 (ar_uid, st_uid, 10);
19975796c8dcSSimon Schubert   foo2 (ar_gid, st_gid, 10);
19985796c8dcSSimon Schubert   foo (ar_mode, st_mode, 8);
19995796c8dcSSimon Schubert 
20005796c8dcSSimon Schubert   buf->st_size = arch_eltdata (abfd)->parsed_size;
20015796c8dcSSimon Schubert 
20025796c8dcSSimon Schubert   return 0;
20035796c8dcSSimon Schubert }
20045796c8dcSSimon Schubert 
20055796c8dcSSimon Schubert void
bfd_dont_truncate_arname(bfd * abfd,const char * pathname,char * arhdr)20065796c8dcSSimon Schubert bfd_dont_truncate_arname (bfd *abfd, const char *pathname, char *arhdr)
20075796c8dcSSimon Schubert {
20085796c8dcSSimon Schubert   /* FIXME: This interacts unpleasantly with ar's quick-append option.
20095796c8dcSSimon Schubert      Fortunately ic960 users will never use that option.  Fixing this
20105796c8dcSSimon Schubert      is very hard; fortunately I know how to do it and will do so once
20115796c8dcSSimon Schubert      intel's release is out the door.  */
20125796c8dcSSimon Schubert 
20135796c8dcSSimon Schubert   struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
20145796c8dcSSimon Schubert   size_t length;
20155796c8dcSSimon Schubert   const char *filename;
20165796c8dcSSimon Schubert   size_t maxlen = ar_maxnamelen (abfd);
20175796c8dcSSimon Schubert 
20185796c8dcSSimon Schubert   if ((bfd_get_file_flags (abfd) & BFD_TRADITIONAL_FORMAT) != 0)
20195796c8dcSSimon Schubert     {
20205796c8dcSSimon Schubert       bfd_bsd_truncate_arname (abfd, pathname, arhdr);
20215796c8dcSSimon Schubert       return;
20225796c8dcSSimon Schubert     }
20235796c8dcSSimon Schubert 
20245796c8dcSSimon Schubert   filename = normalize (abfd, pathname);
20255796c8dcSSimon Schubert   if (filename == NULL)
20265796c8dcSSimon Schubert     {
20275796c8dcSSimon Schubert       /* FIXME */
20285796c8dcSSimon Schubert       abort ();
20295796c8dcSSimon Schubert     }
20305796c8dcSSimon Schubert 
20315796c8dcSSimon Schubert   length = strlen (filename);
20325796c8dcSSimon Schubert 
20335796c8dcSSimon Schubert   if (length <= maxlen)
20345796c8dcSSimon Schubert     memcpy (hdr->ar_name, filename, length);
20355796c8dcSSimon Schubert 
20365796c8dcSSimon Schubert   /* Add the padding character if there is room for it.  */
20375796c8dcSSimon Schubert   if (length < maxlen
20385796c8dcSSimon Schubert       || (length == maxlen && length < sizeof hdr->ar_name))
20395796c8dcSSimon Schubert     (hdr->ar_name)[length] = ar_padchar (abfd);
20405796c8dcSSimon Schubert }
20415796c8dcSSimon Schubert 
20425796c8dcSSimon Schubert void
bfd_bsd_truncate_arname(bfd * abfd,const char * pathname,char * arhdr)20435796c8dcSSimon Schubert bfd_bsd_truncate_arname (bfd *abfd, const char *pathname, char *arhdr)
20445796c8dcSSimon Schubert {
20455796c8dcSSimon Schubert   struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
20465796c8dcSSimon Schubert   size_t length;
2047cf7f2e2dSJohn Marino   const char *filename = lbasename (pathname);
20485796c8dcSSimon Schubert   size_t maxlen = ar_maxnamelen (abfd);
20495796c8dcSSimon Schubert 
20505796c8dcSSimon Schubert   length = strlen (filename);
20515796c8dcSSimon Schubert 
20525796c8dcSSimon Schubert   if (length <= maxlen)
20535796c8dcSSimon Schubert     memcpy (hdr->ar_name, filename, length);
20545796c8dcSSimon Schubert   else
20555796c8dcSSimon Schubert     {
20565796c8dcSSimon Schubert       /* pathname: meet procrustes */
20575796c8dcSSimon Schubert       memcpy (hdr->ar_name, filename, maxlen);
20585796c8dcSSimon Schubert       length = maxlen;
20595796c8dcSSimon Schubert     }
20605796c8dcSSimon Schubert 
20615796c8dcSSimon Schubert   if (length < maxlen)
20625796c8dcSSimon Schubert     (hdr->ar_name)[length] = ar_padchar (abfd);
20635796c8dcSSimon Schubert }
20645796c8dcSSimon Schubert 
20655796c8dcSSimon Schubert /* Store name into ar header.  Truncates the name to fit.
20665796c8dcSSimon Schubert    1> strip pathname to be just the basename.
20675796c8dcSSimon Schubert    2> if it's short enuf to fit, stuff it in.
20685796c8dcSSimon Schubert    3> If it doesn't end with .o, truncate it to fit
20695796c8dcSSimon Schubert    4> truncate it before the .o, append .o, stuff THAT in.  */
20705796c8dcSSimon Schubert 
20715796c8dcSSimon Schubert /* This is what gnu ar does.  It's better but incompatible with the
20725796c8dcSSimon Schubert    bsd ar.  */
20735796c8dcSSimon Schubert 
20745796c8dcSSimon Schubert void
bfd_gnu_truncate_arname(bfd * abfd,const char * pathname,char * arhdr)20755796c8dcSSimon Schubert bfd_gnu_truncate_arname (bfd *abfd, const char *pathname, char *arhdr)
20765796c8dcSSimon Schubert {
20775796c8dcSSimon Schubert   struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
20785796c8dcSSimon Schubert   size_t length;
2079cf7f2e2dSJohn Marino   const char *filename = lbasename (pathname);
20805796c8dcSSimon Schubert   size_t maxlen = ar_maxnamelen (abfd);
20815796c8dcSSimon Schubert 
20825796c8dcSSimon Schubert   length = strlen (filename);
20835796c8dcSSimon Schubert 
20845796c8dcSSimon Schubert   if (length <= maxlen)
20855796c8dcSSimon Schubert     memcpy (hdr->ar_name, filename, length);
20865796c8dcSSimon Schubert   else
20875796c8dcSSimon Schubert     {
20885796c8dcSSimon Schubert       /* pathname: meet procrustes.  */
20895796c8dcSSimon Schubert       memcpy (hdr->ar_name, filename, maxlen);
20905796c8dcSSimon Schubert       if ((filename[length - 2] == '.') && (filename[length - 1] == 'o'))
20915796c8dcSSimon Schubert 	{
20925796c8dcSSimon Schubert 	  hdr->ar_name[maxlen - 2] = '.';
20935796c8dcSSimon Schubert 	  hdr->ar_name[maxlen - 1] = 'o';
20945796c8dcSSimon Schubert 	}
20955796c8dcSSimon Schubert       length = maxlen;
20965796c8dcSSimon Schubert     }
20975796c8dcSSimon Schubert 
20985796c8dcSSimon Schubert   if (length < 16)
20995796c8dcSSimon Schubert     (hdr->ar_name)[length] = ar_padchar (abfd);
21005796c8dcSSimon Schubert }
21015796c8dcSSimon Schubert 
21025796c8dcSSimon Schubert /* The BFD is open for write and has its format set to bfd_archive.  */
21035796c8dcSSimon Schubert 
21045796c8dcSSimon Schubert bfd_boolean
_bfd_write_archive_contents(bfd * arch)21055796c8dcSSimon Schubert _bfd_write_archive_contents (bfd *arch)
21065796c8dcSSimon Schubert {
21075796c8dcSSimon Schubert   bfd *current;
21085796c8dcSSimon Schubert   char *etable = NULL;
21095796c8dcSSimon Schubert   bfd_size_type elength = 0;
21105796c8dcSSimon Schubert   const char *ename = NULL;
21115796c8dcSSimon Schubert   bfd_boolean makemap = bfd_has_map (arch);
21125796c8dcSSimon Schubert   /* If no .o's, don't bother to make a map.  */
21135796c8dcSSimon Schubert   bfd_boolean hasobjects = FALSE;
21145796c8dcSSimon Schubert   bfd_size_type wrote;
21155796c8dcSSimon Schubert   int tries;
21165796c8dcSSimon Schubert   char *armag;
21175796c8dcSSimon Schubert 
21185796c8dcSSimon Schubert   /* Verify the viability of all entries; if any of them live in the
21195796c8dcSSimon Schubert      filesystem (as opposed to living in an archive open for input)
21205796c8dcSSimon Schubert      then construct a fresh ar_hdr for them.  */
21215796c8dcSSimon Schubert   for (current = arch->archive_head;
21225796c8dcSSimon Schubert        current != NULL;
21235796c8dcSSimon Schubert        current = current->archive_next)
21245796c8dcSSimon Schubert     {
21255796c8dcSSimon Schubert       /* This check is checking the bfds for the objects we're reading
21265796c8dcSSimon Schubert 	 from (which are usually either an object file or archive on
21275796c8dcSSimon Schubert 	 disk), not the archive entries we're writing to.  We don't
21285796c8dcSSimon Schubert 	 actually create bfds for the archive members, we just copy
21295796c8dcSSimon Schubert 	 them byte-wise when we write out the archive.  */
21305796c8dcSSimon Schubert       if (bfd_write_p (current))
21315796c8dcSSimon Schubert 	{
21325796c8dcSSimon Schubert 	  bfd_set_error (bfd_error_invalid_operation);
21335796c8dcSSimon Schubert 	  goto input_err;
21345796c8dcSSimon Schubert 	}
21355796c8dcSSimon Schubert       if (!current->arelt_data)
21365796c8dcSSimon Schubert 	{
21375796c8dcSSimon Schubert 	  current->arelt_data =
21385796c8dcSSimon Schubert 	    bfd_ar_hdr_from_filesystem (arch, current->filename, current);
21395796c8dcSSimon Schubert 	  if (!current->arelt_data)
21405796c8dcSSimon Schubert 	    goto input_err;
21415796c8dcSSimon Schubert 
21425796c8dcSSimon Schubert 	  /* Put in the file name.  */
21435796c8dcSSimon Schubert 	  BFD_SEND (arch, _bfd_truncate_arname,
21445796c8dcSSimon Schubert 		    (arch, current->filename, (char *) arch_hdr (current)));
21455796c8dcSSimon Schubert 	}
21465796c8dcSSimon Schubert 
21475796c8dcSSimon Schubert       if (makemap && ! hasobjects)
21485796c8dcSSimon Schubert 	{			/* Don't bother if we won't make a map!  */
21495796c8dcSSimon Schubert 	  if ((bfd_check_format (current, bfd_object)))
21505796c8dcSSimon Schubert 	    hasobjects = TRUE;
21515796c8dcSSimon Schubert 	}
21525796c8dcSSimon Schubert     }
21535796c8dcSSimon Schubert 
21545796c8dcSSimon Schubert   if (!BFD_SEND (arch, _bfd_construct_extended_name_table,
21555796c8dcSSimon Schubert 		 (arch, &etable, &elength, &ename)))
21565796c8dcSSimon Schubert     return FALSE;
21575796c8dcSSimon Schubert 
21585796c8dcSSimon Schubert   if (bfd_seek (arch, (file_ptr) 0, SEEK_SET) != 0)
21595796c8dcSSimon Schubert     return FALSE;
21605796c8dcSSimon Schubert   armag = ARMAG;
21615796c8dcSSimon Schubert   if (bfd_is_thin_archive (arch))
21625796c8dcSSimon Schubert     armag = ARMAGT;
21635796c8dcSSimon Schubert   wrote = bfd_bwrite (armag, SARMAG, arch);
21645796c8dcSSimon Schubert   if (wrote != SARMAG)
21655796c8dcSSimon Schubert     return FALSE;
21665796c8dcSSimon Schubert 
21675796c8dcSSimon Schubert   if (makemap && hasobjects)
21685796c8dcSSimon Schubert     {
21695796c8dcSSimon Schubert       if (! _bfd_compute_and_write_armap (arch, (unsigned int) elength))
21705796c8dcSSimon Schubert 	return FALSE;
21715796c8dcSSimon Schubert     }
21725796c8dcSSimon Schubert 
21735796c8dcSSimon Schubert   if (elength != 0)
21745796c8dcSSimon Schubert     {
21755796c8dcSSimon Schubert       struct ar_hdr hdr;
21765796c8dcSSimon Schubert 
21775796c8dcSSimon Schubert       memset (&hdr, ' ', sizeof (struct ar_hdr));
21785796c8dcSSimon Schubert       memcpy (hdr.ar_name, ename, strlen (ename));
21795796c8dcSSimon Schubert       /* Round size up to even number in archive header.  */
2180*ef5ccd6cSJohn Marino       if (!_bfd_ar_sizepad (hdr.ar_size, sizeof (hdr.ar_size),
2181*ef5ccd6cSJohn Marino 			    (elength + 1) & ~(bfd_size_type) 1))
2182*ef5ccd6cSJohn Marino 	return FALSE;
21835796c8dcSSimon Schubert       memcpy (hdr.ar_fmag, ARFMAG, 2);
21845796c8dcSSimon Schubert       if ((bfd_bwrite (&hdr, sizeof (struct ar_hdr), arch)
21855796c8dcSSimon Schubert 	   != sizeof (struct ar_hdr))
21865796c8dcSSimon Schubert 	  || bfd_bwrite (etable, elength, arch) != elength)
21875796c8dcSSimon Schubert 	return FALSE;
21885796c8dcSSimon Schubert       if ((elength % 2) == 1)
21895796c8dcSSimon Schubert 	{
21905796c8dcSSimon Schubert 	  if (bfd_bwrite (&ARFMAG[1], 1, arch) != 1)
21915796c8dcSSimon Schubert 	    return FALSE;
21925796c8dcSSimon Schubert 	}
21935796c8dcSSimon Schubert     }
21945796c8dcSSimon Schubert 
21955796c8dcSSimon Schubert   for (current = arch->archive_head;
21965796c8dcSSimon Schubert        current != NULL;
21975796c8dcSSimon Schubert        current = current->archive_next)
21985796c8dcSSimon Schubert     {
21995796c8dcSSimon Schubert       char buffer[DEFAULT_BUFFERSIZE];
2200*ef5ccd6cSJohn Marino       bfd_size_type remaining = arelt_size (current);
22015796c8dcSSimon Schubert 
22025796c8dcSSimon Schubert       /* Write ar header.  */
2203cf7f2e2dSJohn Marino       if (!_bfd_write_ar_hdr (arch, current))
22045796c8dcSSimon Schubert 	return FALSE;
22055796c8dcSSimon Schubert       if (bfd_is_thin_archive (arch))
22065796c8dcSSimon Schubert 	continue;
22075796c8dcSSimon Schubert       if (bfd_seek (current, (file_ptr) 0, SEEK_SET) != 0)
22085796c8dcSSimon Schubert 	goto input_err;
22095796c8dcSSimon Schubert 
22105796c8dcSSimon Schubert       while (remaining)
22115796c8dcSSimon Schubert 	{
22125796c8dcSSimon Schubert 	  unsigned int amt = DEFAULT_BUFFERSIZE;
22135796c8dcSSimon Schubert 
22145796c8dcSSimon Schubert 	  if (amt > remaining)
22155796c8dcSSimon Schubert 	    amt = remaining;
22165796c8dcSSimon Schubert 	  errno = 0;
22175796c8dcSSimon Schubert 	  if (bfd_bread (buffer, amt, current) != amt)
22185796c8dcSSimon Schubert 	    {
22195796c8dcSSimon Schubert 	      if (bfd_get_error () != bfd_error_system_call)
22205796c8dcSSimon Schubert 		bfd_set_error (bfd_error_file_truncated);
22215796c8dcSSimon Schubert 	      goto input_err;
22225796c8dcSSimon Schubert 	    }
22235796c8dcSSimon Schubert 	  if (bfd_bwrite (buffer, amt, arch) != amt)
22245796c8dcSSimon Schubert 	    return FALSE;
22255796c8dcSSimon Schubert 	  remaining -= amt;
22265796c8dcSSimon Schubert 	}
22275796c8dcSSimon Schubert 
22285796c8dcSSimon Schubert       if ((arelt_size (current) % 2) == 1)
22295796c8dcSSimon Schubert 	{
22305796c8dcSSimon Schubert 	  if (bfd_bwrite (&ARFMAG[1], 1, arch) != 1)
22315796c8dcSSimon Schubert 	    return FALSE;
22325796c8dcSSimon Schubert 	}
22335796c8dcSSimon Schubert     }
22345796c8dcSSimon Schubert 
22355796c8dcSSimon Schubert   if (makemap && hasobjects)
22365796c8dcSSimon Schubert     {
22375796c8dcSSimon Schubert       /* Verify the timestamp in the archive file.  If it would not be
22385796c8dcSSimon Schubert 	 accepted by the linker, rewrite it until it would be.  If
22395796c8dcSSimon Schubert 	 anything odd happens, break out and just return.  (The
22405796c8dcSSimon Schubert 	 Berkeley linker checks the timestamp and refuses to read the
22415796c8dcSSimon Schubert 	 table-of-contents if it is >60 seconds less than the file's
22425796c8dcSSimon Schubert 	 modified-time.  That painful hack requires this painful hack.  */
22435796c8dcSSimon Schubert       tries = 1;
22445796c8dcSSimon Schubert       do
22455796c8dcSSimon Schubert 	{
22465796c8dcSSimon Schubert 	  if (bfd_update_armap_timestamp (arch))
22475796c8dcSSimon Schubert 	    break;
22485796c8dcSSimon Schubert 	  (*_bfd_error_handler)
22495796c8dcSSimon Schubert 	    (_("Warning: writing archive was slow: rewriting timestamp\n"));
22505796c8dcSSimon Schubert 	}
22515796c8dcSSimon Schubert       while (++tries < 6);
22525796c8dcSSimon Schubert     }
22535796c8dcSSimon Schubert 
22545796c8dcSSimon Schubert   return TRUE;
22555796c8dcSSimon Schubert 
22565796c8dcSSimon Schubert  input_err:
22575796c8dcSSimon Schubert   bfd_set_error (bfd_error_on_input, current, bfd_get_error ());
22585796c8dcSSimon Schubert   return FALSE;
22595796c8dcSSimon Schubert }
22605796c8dcSSimon Schubert 
22615796c8dcSSimon Schubert /* Note that the namidx for the first symbol is 0.  */
22625796c8dcSSimon Schubert 
22635796c8dcSSimon Schubert bfd_boolean
_bfd_compute_and_write_armap(bfd * arch,unsigned int elength)22645796c8dcSSimon Schubert _bfd_compute_and_write_armap (bfd *arch, unsigned int elength)
22655796c8dcSSimon Schubert {
22665796c8dcSSimon Schubert   char *first_name = NULL;
22675796c8dcSSimon Schubert   bfd *current;
22685796c8dcSSimon Schubert   file_ptr elt_no = 0;
22695796c8dcSSimon Schubert   struct orl *map = NULL;
22705796c8dcSSimon Schubert   unsigned int orl_max = 1024;		/* Fine initial default.  */
22715796c8dcSSimon Schubert   unsigned int orl_count = 0;
22725796c8dcSSimon Schubert   int stridx = 0;
22735796c8dcSSimon Schubert   asymbol **syms = NULL;
22745796c8dcSSimon Schubert   long syms_max = 0;
22755796c8dcSSimon Schubert   bfd_boolean ret;
22765796c8dcSSimon Schubert   bfd_size_type amt;
22775796c8dcSSimon Schubert 
22785796c8dcSSimon Schubert   /* Dunno if this is the best place for this info...  */
22795796c8dcSSimon Schubert   if (elength != 0)
22805796c8dcSSimon Schubert     elength += sizeof (struct ar_hdr);
22815796c8dcSSimon Schubert   elength += elength % 2;
22825796c8dcSSimon Schubert 
22835796c8dcSSimon Schubert   amt = orl_max * sizeof (struct orl);
22845796c8dcSSimon Schubert   map = (struct orl *) bfd_malloc (amt);
22855796c8dcSSimon Schubert   if (map == NULL)
22865796c8dcSSimon Schubert     goto error_return;
22875796c8dcSSimon Schubert 
22885796c8dcSSimon Schubert   /* We put the symbol names on the arch objalloc, and then discard
22895796c8dcSSimon Schubert      them when done.  */
22905796c8dcSSimon Schubert   first_name = (char *) bfd_alloc (arch, 1);
22915796c8dcSSimon Schubert   if (first_name == NULL)
22925796c8dcSSimon Schubert     goto error_return;
22935796c8dcSSimon Schubert 
22945796c8dcSSimon Schubert   /* Drop all the files called __.SYMDEF, we're going to make our own.  */
22955796c8dcSSimon Schubert   while (arch->archive_head
22965796c8dcSSimon Schubert 	 && strcmp (arch->archive_head->filename, "__.SYMDEF") == 0)
22975796c8dcSSimon Schubert     arch->archive_head = arch->archive_head->archive_next;
22985796c8dcSSimon Schubert 
22995796c8dcSSimon Schubert   /* Map over each element.  */
23005796c8dcSSimon Schubert   for (current = arch->archive_head;
23015796c8dcSSimon Schubert        current != NULL;
23025796c8dcSSimon Schubert        current = current->archive_next, elt_no++)
23035796c8dcSSimon Schubert     {
23045796c8dcSSimon Schubert       if (bfd_check_format (current, bfd_object)
23055796c8dcSSimon Schubert 	  && (bfd_get_file_flags (current) & HAS_SYMS) != 0)
23065796c8dcSSimon Schubert 	{
23075796c8dcSSimon Schubert 	  long storage;
23085796c8dcSSimon Schubert 	  long symcount;
23095796c8dcSSimon Schubert 	  long src_count;
23105796c8dcSSimon Schubert 
23115796c8dcSSimon Schubert 	  storage = bfd_get_symtab_upper_bound (current);
23125796c8dcSSimon Schubert 	  if (storage < 0)
23135796c8dcSSimon Schubert 	    goto error_return;
23145796c8dcSSimon Schubert 
23155796c8dcSSimon Schubert 	  if (storage != 0)
23165796c8dcSSimon Schubert 	    {
23175796c8dcSSimon Schubert 	      if (storage > syms_max)
23185796c8dcSSimon Schubert 		{
23195796c8dcSSimon Schubert 		  if (syms_max > 0)
23205796c8dcSSimon Schubert 		    free (syms);
23215796c8dcSSimon Schubert 		  syms_max = storage;
23225796c8dcSSimon Schubert 		  syms = (asymbol **) bfd_malloc (syms_max);
23235796c8dcSSimon Schubert 		  if (syms == NULL)
23245796c8dcSSimon Schubert 		    goto error_return;
23255796c8dcSSimon Schubert 		}
23265796c8dcSSimon Schubert 	      symcount = bfd_canonicalize_symtab (current, syms);
23275796c8dcSSimon Schubert 	      if (symcount < 0)
23285796c8dcSSimon Schubert 		goto error_return;
23295796c8dcSSimon Schubert 
23305796c8dcSSimon Schubert 	      /* Now map over all the symbols, picking out the ones we
23315796c8dcSSimon Schubert 		 want.  */
23325796c8dcSSimon Schubert 	      for (src_count = 0; src_count < symcount; src_count++)
23335796c8dcSSimon Schubert 		{
23345796c8dcSSimon Schubert 		  flagword flags = (syms[src_count])->flags;
23355796c8dcSSimon Schubert 		  asection *sec = syms[src_count]->section;
23365796c8dcSSimon Schubert 
2337*ef5ccd6cSJohn Marino 		  if (((flags & (BSF_GLOBAL
2338*ef5ccd6cSJohn Marino 				 | BSF_WEAK
2339*ef5ccd6cSJohn Marino 				 | BSF_INDIRECT
2340*ef5ccd6cSJohn Marino 				 | BSF_GNU_UNIQUE)) != 0
23415796c8dcSSimon Schubert 		       || bfd_is_com_section (sec))
23425796c8dcSSimon Schubert 		      && ! bfd_is_und_section (sec))
23435796c8dcSSimon Schubert 		    {
23445796c8dcSSimon Schubert 		      bfd_size_type namelen;
23455796c8dcSSimon Schubert 		      struct orl *new_map;
23465796c8dcSSimon Schubert 
23475796c8dcSSimon Schubert 		      /* This symbol will go into the archive header.  */
23485796c8dcSSimon Schubert 		      if (orl_count == orl_max)
23495796c8dcSSimon Schubert 			{
23505796c8dcSSimon Schubert 			  orl_max *= 2;
23515796c8dcSSimon Schubert 			  amt = orl_max * sizeof (struct orl);
23525796c8dcSSimon Schubert 			  new_map = (struct orl *) bfd_realloc (map, amt);
23535796c8dcSSimon Schubert 			  if (new_map == NULL)
23545796c8dcSSimon Schubert 			    goto error_return;
23555796c8dcSSimon Schubert 
23565796c8dcSSimon Schubert 			  map = new_map;
23575796c8dcSSimon Schubert 			}
23585796c8dcSSimon Schubert 
23595796c8dcSSimon Schubert 		      namelen = strlen (syms[src_count]->name);
23605796c8dcSSimon Schubert 		      amt = sizeof (char *);
23615796c8dcSSimon Schubert 		      map[orl_count].name = (char **) bfd_alloc (arch, amt);
23625796c8dcSSimon Schubert 		      if (map[orl_count].name == NULL)
23635796c8dcSSimon Schubert 			goto error_return;
23645796c8dcSSimon Schubert 		      *(map[orl_count].name) = (char *) bfd_alloc (arch,
23655796c8dcSSimon Schubert 								   namelen + 1);
23665796c8dcSSimon Schubert 		      if (*(map[orl_count].name) == NULL)
23675796c8dcSSimon Schubert 			goto error_return;
23685796c8dcSSimon Schubert 		      strcpy (*(map[orl_count].name), syms[src_count]->name);
23695796c8dcSSimon Schubert 		      map[orl_count].u.abfd = current;
23705796c8dcSSimon Schubert 		      map[orl_count].namidx = stridx;
23715796c8dcSSimon Schubert 
23725796c8dcSSimon Schubert 		      stridx += namelen + 1;
23735796c8dcSSimon Schubert 		      ++orl_count;
23745796c8dcSSimon Schubert 		    }
23755796c8dcSSimon Schubert 		}
23765796c8dcSSimon Schubert 	    }
23775796c8dcSSimon Schubert 
23785796c8dcSSimon Schubert 	  /* Now ask the BFD to free up any cached information, so we
23795796c8dcSSimon Schubert 	     don't fill all of memory with symbol tables.  */
23805796c8dcSSimon Schubert 	  if (! bfd_free_cached_info (current))
23815796c8dcSSimon Schubert 	    goto error_return;
23825796c8dcSSimon Schubert 	}
23835796c8dcSSimon Schubert     }
23845796c8dcSSimon Schubert 
23855796c8dcSSimon Schubert   /* OK, now we have collected all the data, let's write them out.  */
23865796c8dcSSimon Schubert   ret = BFD_SEND (arch, write_armap,
23875796c8dcSSimon Schubert 		  (arch, elength, map, orl_count, stridx));
23885796c8dcSSimon Schubert 
23895796c8dcSSimon Schubert   if (syms_max > 0)
23905796c8dcSSimon Schubert     free (syms);
23915796c8dcSSimon Schubert   if (map != NULL)
23925796c8dcSSimon Schubert     free (map);
23935796c8dcSSimon Schubert   if (first_name != NULL)
23945796c8dcSSimon Schubert     bfd_release (arch, first_name);
23955796c8dcSSimon Schubert 
23965796c8dcSSimon Schubert   return ret;
23975796c8dcSSimon Schubert 
23985796c8dcSSimon Schubert  error_return:
23995796c8dcSSimon Schubert   if (syms_max > 0)
24005796c8dcSSimon Schubert     free (syms);
24015796c8dcSSimon Schubert   if (map != NULL)
24025796c8dcSSimon Schubert     free (map);
24035796c8dcSSimon Schubert   if (first_name != NULL)
24045796c8dcSSimon Schubert     bfd_release (arch, first_name);
24055796c8dcSSimon Schubert 
24065796c8dcSSimon Schubert   return FALSE;
24075796c8dcSSimon Schubert }
24085796c8dcSSimon Schubert 
24095796c8dcSSimon Schubert bfd_boolean
bsd_write_armap(bfd * arch,unsigned int elength,struct orl * map,unsigned int orl_count,int stridx)24105796c8dcSSimon Schubert bsd_write_armap (bfd *arch,
24115796c8dcSSimon Schubert 		 unsigned int elength,
24125796c8dcSSimon Schubert 		 struct orl *map,
24135796c8dcSSimon Schubert 		 unsigned int orl_count,
24145796c8dcSSimon Schubert 		 int stridx)
24155796c8dcSSimon Schubert {
24165796c8dcSSimon Schubert   int padit = stridx & 1;
24175796c8dcSSimon Schubert   unsigned int ranlibsize = orl_count * BSD_SYMDEF_SIZE;
24185796c8dcSSimon Schubert   unsigned int stringsize = stridx + padit;
24195796c8dcSSimon Schubert   /* Include 8 bytes to store ranlibsize and stringsize in output.  */
24205796c8dcSSimon Schubert   unsigned int mapsize = ranlibsize + stringsize + 8;
24215796c8dcSSimon Schubert   file_ptr firstreal;
24225796c8dcSSimon Schubert   bfd *current = arch->archive_head;
24235796c8dcSSimon Schubert   bfd *last_elt = current;	/* Last element arch seen.  */
24245796c8dcSSimon Schubert   bfd_byte temp[4];
24255796c8dcSSimon Schubert   unsigned int count;
24265796c8dcSSimon Schubert   struct ar_hdr hdr;
24275796c8dcSSimon Schubert   long uid, gid;
24285796c8dcSSimon Schubert 
24295796c8dcSSimon Schubert   firstreal = mapsize + elength + sizeof (struct ar_hdr) + SARMAG;
24305796c8dcSSimon Schubert 
24315796c8dcSSimon Schubert   /* If deterministic, we use 0 as the timestamp in the map.
24325796c8dcSSimon Schubert      Some linkers may require that the archive filesystem modification
24335796c8dcSSimon Schubert      time is less than (or near to) the archive map timestamp.  Those
24345796c8dcSSimon Schubert      linkers should not be used with deterministic mode.  (GNU ld and
24355796c8dcSSimon Schubert      Gold do not have this restriction.)  */
24365796c8dcSSimon Schubert   bfd_ardata (arch)->armap_timestamp = 0;
24375796c8dcSSimon Schubert   uid = 0;
24385796c8dcSSimon Schubert   gid = 0;
2439c50c785cSJohn Marino   if ((arch->flags & BFD_DETERMINISTIC_OUTPUT) == 0)
2440c50c785cSJohn Marino     {
2441c50c785cSJohn Marino       struct stat statbuf;
2442c50c785cSJohn Marino 
2443c50c785cSJohn Marino       if (stat (arch->filename, &statbuf) == 0)
2444c50c785cSJohn Marino 	bfd_ardata (arch)->armap_timestamp = (statbuf.st_mtime
2445c50c785cSJohn Marino 					      + ARMAP_TIME_OFFSET);
2446c50c785cSJohn Marino       uid = getuid();
2447c50c785cSJohn Marino       gid = getgid();
24485796c8dcSSimon Schubert     }
24495796c8dcSSimon Schubert 
24505796c8dcSSimon Schubert   memset (&hdr, ' ', sizeof (struct ar_hdr));
24515796c8dcSSimon Schubert   memcpy (hdr.ar_name, RANLIBMAG, strlen (RANLIBMAG));
24525796c8dcSSimon Schubert   bfd_ardata (arch)->armap_datepos = (SARMAG
24535796c8dcSSimon Schubert 				      + offsetof (struct ar_hdr, ar_date[0]));
24545796c8dcSSimon Schubert   _bfd_ar_spacepad (hdr.ar_date, sizeof (hdr.ar_date), "%ld",
24555796c8dcSSimon Schubert 		    bfd_ardata (arch)->armap_timestamp);
24565796c8dcSSimon Schubert   _bfd_ar_spacepad (hdr.ar_uid, sizeof (hdr.ar_uid), "%ld", uid);
24575796c8dcSSimon Schubert   _bfd_ar_spacepad (hdr.ar_gid, sizeof (hdr.ar_gid), "%ld", gid);
2458*ef5ccd6cSJohn Marino   if (!_bfd_ar_sizepad (hdr.ar_size, sizeof (hdr.ar_size), mapsize))
2459*ef5ccd6cSJohn Marino     return FALSE;
24605796c8dcSSimon Schubert   memcpy (hdr.ar_fmag, ARFMAG, 2);
24615796c8dcSSimon Schubert   if (bfd_bwrite (&hdr, sizeof (struct ar_hdr), arch)
24625796c8dcSSimon Schubert       != sizeof (struct ar_hdr))
24635796c8dcSSimon Schubert     return FALSE;
24645796c8dcSSimon Schubert   H_PUT_32 (arch, ranlibsize, temp);
24655796c8dcSSimon Schubert   if (bfd_bwrite (temp, sizeof (temp), arch) != sizeof (temp))
24665796c8dcSSimon Schubert     return FALSE;
24675796c8dcSSimon Schubert 
24685796c8dcSSimon Schubert   for (count = 0; count < orl_count; count++)
24695796c8dcSSimon Schubert     {
2470*ef5ccd6cSJohn Marino       unsigned int offset;
24715796c8dcSSimon Schubert       bfd_byte buf[BSD_SYMDEF_SIZE];
24725796c8dcSSimon Schubert 
24735796c8dcSSimon Schubert       if (map[count].u.abfd != last_elt)
24745796c8dcSSimon Schubert 	{
24755796c8dcSSimon Schubert 	  do
24765796c8dcSSimon Schubert 	    {
2477cf7f2e2dSJohn Marino 	      struct areltdata *ared = arch_eltdata (current);
2478cf7f2e2dSJohn Marino 
2479cf7f2e2dSJohn Marino 	      firstreal += (ared->parsed_size + ared->extra_size
2480cf7f2e2dSJohn Marino 			    + sizeof (struct ar_hdr));
24815796c8dcSSimon Schubert 	      firstreal += firstreal % 2;
24825796c8dcSSimon Schubert 	      current = current->archive_next;
24835796c8dcSSimon Schubert 	    }
24845796c8dcSSimon Schubert 	  while (current != map[count].u.abfd);
24855796c8dcSSimon Schubert 	}
24865796c8dcSSimon Schubert 
2487*ef5ccd6cSJohn Marino       /* The archive file format only has 4 bytes to store the offset
2488*ef5ccd6cSJohn Marino 	 of the member.  Check to make sure that firstreal has not grown
2489*ef5ccd6cSJohn Marino 	 too big.  */
2490*ef5ccd6cSJohn Marino       offset = (unsigned int) firstreal;
2491*ef5ccd6cSJohn Marino       if (firstreal != (file_ptr) offset)
2492*ef5ccd6cSJohn Marino 	{
2493*ef5ccd6cSJohn Marino 	  bfd_set_error (bfd_error_file_truncated);
2494*ef5ccd6cSJohn Marino 	  return FALSE;
2495*ef5ccd6cSJohn Marino 	}
2496*ef5ccd6cSJohn Marino 
24975796c8dcSSimon Schubert       last_elt = current;
24985796c8dcSSimon Schubert       H_PUT_32 (arch, map[count].namidx, buf);
24995796c8dcSSimon Schubert       H_PUT_32 (arch, firstreal, buf + BSD_SYMDEF_OFFSET_SIZE);
25005796c8dcSSimon Schubert       if (bfd_bwrite (buf, BSD_SYMDEF_SIZE, arch)
25015796c8dcSSimon Schubert 	  != BSD_SYMDEF_SIZE)
25025796c8dcSSimon Schubert 	return FALSE;
25035796c8dcSSimon Schubert     }
25045796c8dcSSimon Schubert 
25055796c8dcSSimon Schubert   /* Now write the strings themselves.  */
25065796c8dcSSimon Schubert   H_PUT_32 (arch, stringsize, temp);
25075796c8dcSSimon Schubert   if (bfd_bwrite (temp, sizeof (temp), arch) != sizeof (temp))
25085796c8dcSSimon Schubert     return FALSE;
25095796c8dcSSimon Schubert   for (count = 0; count < orl_count; count++)
25105796c8dcSSimon Schubert     {
25115796c8dcSSimon Schubert       size_t len = strlen (*map[count].name) + 1;
25125796c8dcSSimon Schubert 
25135796c8dcSSimon Schubert       if (bfd_bwrite (*map[count].name, len, arch) != len)
25145796c8dcSSimon Schubert 	return FALSE;
25155796c8dcSSimon Schubert     }
25165796c8dcSSimon Schubert 
25175796c8dcSSimon Schubert   /* The spec sez this should be a newline.  But in order to be
25185796c8dcSSimon Schubert      bug-compatible for sun's ar we use a null.  */
25195796c8dcSSimon Schubert   if (padit)
25205796c8dcSSimon Schubert     {
25215796c8dcSSimon Schubert       if (bfd_bwrite ("", 1, arch) != 1)
25225796c8dcSSimon Schubert 	return FALSE;
25235796c8dcSSimon Schubert     }
25245796c8dcSSimon Schubert 
25255796c8dcSSimon Schubert   return TRUE;
25265796c8dcSSimon Schubert }
25275796c8dcSSimon Schubert 
25285796c8dcSSimon Schubert /* At the end of archive file handling, update the timestamp in the
25295796c8dcSSimon Schubert    file, so the linker will accept it.
25305796c8dcSSimon Schubert 
25315796c8dcSSimon Schubert    Return TRUE if the timestamp was OK, or an unusual problem happened.
25325796c8dcSSimon Schubert    Return FALSE if we updated the timestamp.  */
25335796c8dcSSimon Schubert 
25345796c8dcSSimon Schubert bfd_boolean
_bfd_archive_bsd_update_armap_timestamp(bfd * arch)25355796c8dcSSimon Schubert _bfd_archive_bsd_update_armap_timestamp (bfd *arch)
25365796c8dcSSimon Schubert {
25375796c8dcSSimon Schubert   struct stat archstat;
25385796c8dcSSimon Schubert   struct ar_hdr hdr;
25395796c8dcSSimon Schubert 
25405796c8dcSSimon Schubert   /* If creating deterministic archives, just leave the timestamp as-is.  */
25415796c8dcSSimon Schubert   if ((arch->flags & BFD_DETERMINISTIC_OUTPUT) != 0)
25425796c8dcSSimon Schubert     return TRUE;
25435796c8dcSSimon Schubert 
25445796c8dcSSimon Schubert   /* Flush writes, get last-write timestamp from file, and compare it
25455796c8dcSSimon Schubert      to the timestamp IN the file.  */
25465796c8dcSSimon Schubert   bfd_flush (arch);
25475796c8dcSSimon Schubert   if (bfd_stat (arch, &archstat) == -1)
25485796c8dcSSimon Schubert     {
25495796c8dcSSimon Schubert       bfd_perror (_("Reading archive file mod timestamp"));
25505796c8dcSSimon Schubert 
25515796c8dcSSimon Schubert       /* Can't read mod time for some reason.  */
25525796c8dcSSimon Schubert       return TRUE;
25535796c8dcSSimon Schubert     }
25545796c8dcSSimon Schubert   if (((long) archstat.st_mtime) <= bfd_ardata (arch)->armap_timestamp)
25555796c8dcSSimon Schubert     /* OK by the linker's rules.  */
25565796c8dcSSimon Schubert     return TRUE;
25575796c8dcSSimon Schubert 
25585796c8dcSSimon Schubert   /* Update the timestamp.  */
25595796c8dcSSimon Schubert   bfd_ardata (arch)->armap_timestamp = archstat.st_mtime + ARMAP_TIME_OFFSET;
25605796c8dcSSimon Schubert 
25615796c8dcSSimon Schubert   /* Prepare an ASCII version suitable for writing.  */
25625796c8dcSSimon Schubert   memset (hdr.ar_date, ' ', sizeof (hdr.ar_date));
25635796c8dcSSimon Schubert   _bfd_ar_spacepad (hdr.ar_date, sizeof (hdr.ar_date), "%ld",
25645796c8dcSSimon Schubert 		    bfd_ardata (arch)->armap_timestamp);
25655796c8dcSSimon Schubert 
25665796c8dcSSimon Schubert   /* Write it into the file.  */
25675796c8dcSSimon Schubert   bfd_ardata (arch)->armap_datepos = (SARMAG
25685796c8dcSSimon Schubert 				      + offsetof (struct ar_hdr, ar_date[0]));
25695796c8dcSSimon Schubert   if (bfd_seek (arch, bfd_ardata (arch)->armap_datepos, SEEK_SET) != 0
25705796c8dcSSimon Schubert       || (bfd_bwrite (hdr.ar_date, sizeof (hdr.ar_date), arch)
25715796c8dcSSimon Schubert 	  != sizeof (hdr.ar_date)))
25725796c8dcSSimon Schubert     {
25735796c8dcSSimon Schubert       bfd_perror (_("Writing updated armap timestamp"));
25745796c8dcSSimon Schubert 
25755796c8dcSSimon Schubert       /* Some error while writing.  */
25765796c8dcSSimon Schubert       return TRUE;
25775796c8dcSSimon Schubert     }
25785796c8dcSSimon Schubert 
25795796c8dcSSimon Schubert   /* We updated the timestamp successfully.  */
25805796c8dcSSimon Schubert   return FALSE;
25815796c8dcSSimon Schubert }
25825796c8dcSSimon Schubert 
25835796c8dcSSimon Schubert /* A coff armap looks like :
25845796c8dcSSimon Schubert    lARMAG
25855796c8dcSSimon Schubert    struct ar_hdr with name = '/'
25865796c8dcSSimon Schubert    number of symbols
25875796c8dcSSimon Schubert    offset of file for symbol 0
25885796c8dcSSimon Schubert    offset of file for symbol 1
25895796c8dcSSimon Schubert 
25905796c8dcSSimon Schubert    offset of file for symbol n-1
25915796c8dcSSimon Schubert    symbol name 0
25925796c8dcSSimon Schubert    symbol name 1
25935796c8dcSSimon Schubert 
25945796c8dcSSimon Schubert    symbol name n-1  */
25955796c8dcSSimon Schubert 
25965796c8dcSSimon Schubert bfd_boolean
coff_write_armap(bfd * arch,unsigned int elength,struct orl * map,unsigned int symbol_count,int stridx)25975796c8dcSSimon Schubert coff_write_armap (bfd *arch,
25985796c8dcSSimon Schubert 		  unsigned int elength,
25995796c8dcSSimon Schubert 		  struct orl *map,
26005796c8dcSSimon Schubert 		  unsigned int symbol_count,
26015796c8dcSSimon Schubert 		  int stridx)
26025796c8dcSSimon Schubert {
26035796c8dcSSimon Schubert   /* The size of the ranlib is the number of exported symbols in the
26045796c8dcSSimon Schubert      archive * the number of bytes in an int, + an int for the count.  */
26055796c8dcSSimon Schubert   unsigned int ranlibsize = (symbol_count * 4) + 4;
26065796c8dcSSimon Schubert   unsigned int stringsize = stridx;
26075796c8dcSSimon Schubert   unsigned int mapsize = stringsize + ranlibsize;
2608*ef5ccd6cSJohn Marino   file_ptr archive_member_file_ptr;
26095796c8dcSSimon Schubert   bfd *current = arch->archive_head;
26105796c8dcSSimon Schubert   unsigned int count;
26115796c8dcSSimon Schubert   struct ar_hdr hdr;
26125796c8dcSSimon Schubert   int padit = mapsize & 1;
26135796c8dcSSimon Schubert 
26145796c8dcSSimon Schubert   if (padit)
26155796c8dcSSimon Schubert     mapsize++;
26165796c8dcSSimon Schubert 
26175796c8dcSSimon Schubert   /* Work out where the first object file will go in the archive.  */
26185796c8dcSSimon Schubert   archive_member_file_ptr = (mapsize
26195796c8dcSSimon Schubert 			     + elength
26205796c8dcSSimon Schubert 			     + sizeof (struct ar_hdr)
26215796c8dcSSimon Schubert 			     + SARMAG);
26225796c8dcSSimon Schubert 
26235796c8dcSSimon Schubert   memset (&hdr, ' ', sizeof (struct ar_hdr));
26245796c8dcSSimon Schubert   hdr.ar_name[0] = '/';
2625*ef5ccd6cSJohn Marino   if (!_bfd_ar_sizepad (hdr.ar_size, sizeof (hdr.ar_size), mapsize))
2626*ef5ccd6cSJohn Marino     return FALSE;
26275796c8dcSSimon Schubert   _bfd_ar_spacepad (hdr.ar_date, sizeof (hdr.ar_date), "%ld",
26285796c8dcSSimon Schubert 		    ((arch->flags & BFD_DETERMINISTIC_OUTPUT) == 0
26295796c8dcSSimon Schubert 		     ? time (NULL) : 0));
26305796c8dcSSimon Schubert   /* This, at least, is what Intel coff sets the values to.  */
26315796c8dcSSimon Schubert   _bfd_ar_spacepad (hdr.ar_uid, sizeof (hdr.ar_uid), "%ld", 0);
26325796c8dcSSimon Schubert   _bfd_ar_spacepad (hdr.ar_gid, sizeof (hdr.ar_gid), "%ld", 0);
26335796c8dcSSimon Schubert   _bfd_ar_spacepad (hdr.ar_mode, sizeof (hdr.ar_mode), "%-7lo", 0);
26345796c8dcSSimon Schubert   memcpy (hdr.ar_fmag, ARFMAG, 2);
26355796c8dcSSimon Schubert 
26365796c8dcSSimon Schubert   /* Write the ar header for this item and the number of symbols.  */
26375796c8dcSSimon Schubert   if (bfd_bwrite (&hdr, sizeof (struct ar_hdr), arch)
26385796c8dcSSimon Schubert       != sizeof (struct ar_hdr))
26395796c8dcSSimon Schubert     return FALSE;
26405796c8dcSSimon Schubert 
26415796c8dcSSimon Schubert   if (!bfd_write_bigendian_4byte_int (arch, symbol_count))
26425796c8dcSSimon Schubert     return FALSE;
26435796c8dcSSimon Schubert 
26445796c8dcSSimon Schubert   /* Two passes, first write the file offsets for each symbol -
26455796c8dcSSimon Schubert      remembering that each offset is on a two byte boundary.  */
26465796c8dcSSimon Schubert 
26475796c8dcSSimon Schubert   /* Write out the file offset for the file associated with each
26485796c8dcSSimon Schubert      symbol, and remember to keep the offsets padded out.  */
26495796c8dcSSimon Schubert 
26505796c8dcSSimon Schubert   current = arch->archive_head;
26515796c8dcSSimon Schubert   count = 0;
26525796c8dcSSimon Schubert   while (current != NULL && count < symbol_count)
26535796c8dcSSimon Schubert     {
26545796c8dcSSimon Schubert       /* For each symbol which is used defined in this object, write
26555796c8dcSSimon Schubert 	 out the object file's address in the archive.  */
26565796c8dcSSimon Schubert 
26575796c8dcSSimon Schubert       while (count < symbol_count && map[count].u.abfd == current)
26585796c8dcSSimon Schubert 	{
2659*ef5ccd6cSJohn Marino 	  unsigned int offset = (unsigned int) archive_member_file_ptr;
2660*ef5ccd6cSJohn Marino 
2661*ef5ccd6cSJohn Marino 	  /* Catch an attempt to grow an archive past its 4Gb limit.  */
2662*ef5ccd6cSJohn Marino 	  if (archive_member_file_ptr != (file_ptr) offset)
2663*ef5ccd6cSJohn Marino 	    {
2664*ef5ccd6cSJohn Marino 	      bfd_set_error (bfd_error_file_truncated);
2665*ef5ccd6cSJohn Marino 	      return FALSE;
2666*ef5ccd6cSJohn Marino 	    }
2667*ef5ccd6cSJohn Marino 	  if (!bfd_write_bigendian_4byte_int (arch, offset))
26685796c8dcSSimon Schubert 	    return FALSE;
26695796c8dcSSimon Schubert 	  count++;
26705796c8dcSSimon Schubert 	}
26715796c8dcSSimon Schubert       archive_member_file_ptr += sizeof (struct ar_hdr);
26725796c8dcSSimon Schubert       if (! bfd_is_thin_archive (arch))
26735796c8dcSSimon Schubert 	{
26745796c8dcSSimon Schubert 	  /* Add size of this archive entry.  */
26755796c8dcSSimon Schubert 	  archive_member_file_ptr += arelt_size (current);
26765796c8dcSSimon Schubert 	  /* Remember about the even alignment.  */
26775796c8dcSSimon Schubert 	  archive_member_file_ptr += archive_member_file_ptr % 2;
26785796c8dcSSimon Schubert 	}
26795796c8dcSSimon Schubert       current = current->archive_next;
26805796c8dcSSimon Schubert     }
26815796c8dcSSimon Schubert 
26825796c8dcSSimon Schubert   /* Now write the strings themselves.  */
26835796c8dcSSimon Schubert   for (count = 0; count < symbol_count; count++)
26845796c8dcSSimon Schubert     {
26855796c8dcSSimon Schubert       size_t len = strlen (*map[count].name) + 1;
26865796c8dcSSimon Schubert 
26875796c8dcSSimon Schubert       if (bfd_bwrite (*map[count].name, len, arch) != len)
26885796c8dcSSimon Schubert 	return FALSE;
26895796c8dcSSimon Schubert     }
26905796c8dcSSimon Schubert 
26915796c8dcSSimon Schubert   /* The spec sez this should be a newline.  But in order to be
26925796c8dcSSimon Schubert      bug-compatible for arc960 we use a null.  */
26935796c8dcSSimon Schubert   if (padit)
26945796c8dcSSimon Schubert     {
26955796c8dcSSimon Schubert       if (bfd_bwrite ("", 1, arch) != 1)
26965796c8dcSSimon Schubert 	return FALSE;
26975796c8dcSSimon Schubert     }
26985796c8dcSSimon Schubert 
26995796c8dcSSimon Schubert   return TRUE;
27005796c8dcSSimon Schubert }
2701*ef5ccd6cSJohn Marino 
2702*ef5ccd6cSJohn Marino static int
archive_close_worker(void ** slot,void * inf ATTRIBUTE_UNUSED)2703*ef5ccd6cSJohn Marino archive_close_worker (void **slot, void *inf ATTRIBUTE_UNUSED)
2704*ef5ccd6cSJohn Marino {
2705*ef5ccd6cSJohn Marino   struct ar_cache *ent = (struct ar_cache *) *slot;
2706*ef5ccd6cSJohn Marino 
2707*ef5ccd6cSJohn Marino   bfd_close_all_done (ent->arbfd);
2708*ef5ccd6cSJohn Marino   return 1;
2709*ef5ccd6cSJohn Marino }
2710*ef5ccd6cSJohn Marino 
2711*ef5ccd6cSJohn Marino bfd_boolean
_bfd_archive_close_and_cleanup(bfd * abfd)2712*ef5ccd6cSJohn Marino _bfd_archive_close_and_cleanup (bfd *abfd)
2713*ef5ccd6cSJohn Marino {
2714*ef5ccd6cSJohn Marino   if (bfd_read_p (abfd) && abfd->format == bfd_archive)
2715*ef5ccd6cSJohn Marino     {
2716*ef5ccd6cSJohn Marino       bfd *nbfd;
2717*ef5ccd6cSJohn Marino       bfd *next;
2718*ef5ccd6cSJohn Marino       htab_t htab;
2719*ef5ccd6cSJohn Marino 
2720*ef5ccd6cSJohn Marino       /* Close nested archives (if this bfd is a thin archive).  */
2721*ef5ccd6cSJohn Marino       for (nbfd = abfd->nested_archives; nbfd; nbfd = next)
2722*ef5ccd6cSJohn Marino 	{
2723*ef5ccd6cSJohn Marino 	  next = nbfd->archive_next;
2724*ef5ccd6cSJohn Marino 	  bfd_close (nbfd);
2725*ef5ccd6cSJohn Marino 	}
2726*ef5ccd6cSJohn Marino 
2727*ef5ccd6cSJohn Marino       htab = bfd_ardata (abfd)->cache;
2728*ef5ccd6cSJohn Marino       if (htab)
2729*ef5ccd6cSJohn Marino 	{
2730*ef5ccd6cSJohn Marino 	  htab_traverse_noresize (htab, archive_close_worker, NULL);
2731*ef5ccd6cSJohn Marino 	  htab_delete (htab);
2732*ef5ccd6cSJohn Marino 	  bfd_ardata (abfd)->cache = NULL;
2733*ef5ccd6cSJohn Marino 	}
2734*ef5ccd6cSJohn Marino     }
2735*ef5ccd6cSJohn Marino   else if (arch_eltdata (abfd) != NULL)
2736*ef5ccd6cSJohn Marino     {
2737*ef5ccd6cSJohn Marino       struct areltdata *ared = arch_eltdata (abfd);
2738*ef5ccd6cSJohn Marino       htab_t htab = (htab_t) ared->parent_cache;
2739*ef5ccd6cSJohn Marino 
2740*ef5ccd6cSJohn Marino       if (htab)
2741*ef5ccd6cSJohn Marino 	{
2742*ef5ccd6cSJohn Marino 	  struct ar_cache ent;
2743*ef5ccd6cSJohn Marino 	  void **slot;
2744*ef5ccd6cSJohn Marino 
2745*ef5ccd6cSJohn Marino 	  ent.ptr = ared->key;
2746*ef5ccd6cSJohn Marino 	  slot = htab_find_slot (htab, &ent, NO_INSERT);
2747*ef5ccd6cSJohn Marino 	  if (slot != NULL)
2748*ef5ccd6cSJohn Marino 	    {
2749*ef5ccd6cSJohn Marino 	      BFD_ASSERT (((struct ar_cache *) *slot)->arbfd == abfd);
2750*ef5ccd6cSJohn Marino 	      htab_clear_slot (htab, slot);
2751*ef5ccd6cSJohn Marino 	    }
2752*ef5ccd6cSJohn Marino 	}
2753*ef5ccd6cSJohn Marino     }
2754*ef5ccd6cSJohn Marino   return TRUE;
2755*ef5ccd6cSJohn Marino }
2756