xref: /dflybsd-src/contrib/gdb-7/bfd/archive.c (revision a45ae5f869d9cfcb3e41dbab486e10bfa9e336bf)
15796c8dcSSimon Schubert /* BFD back-end for archive files (libraries).
25796c8dcSSimon Schubert    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3c50c785cSJohn Marino    2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
45796c8dcSSimon Schubert    Free Software Foundation, Inc.
55796c8dcSSimon Schubert    Written by Cygnus Support.  Mostly Gumby Henkel-Wallace's fault.
65796c8dcSSimon Schubert 
75796c8dcSSimon Schubert    This file is part of BFD, the Binary File Descriptor library.
85796c8dcSSimon Schubert 
95796c8dcSSimon Schubert    This program is free software; you can redistribute it and/or modify
105796c8dcSSimon Schubert    it under the terms of the GNU General Public License as published by
115796c8dcSSimon Schubert    the Free Software Foundation; either version 3 of the License, or
125796c8dcSSimon Schubert    (at your option) any later version.
135796c8dcSSimon Schubert 
145796c8dcSSimon Schubert    This program is distributed in the hope that it will be useful,
155796c8dcSSimon Schubert    but WITHOUT ANY WARRANTY; without even the implied warranty of
165796c8dcSSimon Schubert    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
175796c8dcSSimon Schubert    GNU General Public License for more details.
185796c8dcSSimon Schubert 
195796c8dcSSimon Schubert    You should have received a copy of the GNU General Public License
205796c8dcSSimon Schubert    along with this program; if not, write to the Free Software
215796c8dcSSimon Schubert    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
225796c8dcSSimon Schubert 
235796c8dcSSimon Schubert /*
245796c8dcSSimon Schubert @setfilename archive-info
255796c8dcSSimon Schubert SECTION
265796c8dcSSimon Schubert 	Archives
275796c8dcSSimon Schubert 
285796c8dcSSimon Schubert DESCRIPTION
295796c8dcSSimon Schubert 	An archive (or library) is just another BFD.  It has a symbol
305796c8dcSSimon Schubert 	table, although there's not much a user program will do with it.
315796c8dcSSimon Schubert 
325796c8dcSSimon Schubert 	The big difference between an archive BFD and an ordinary BFD
335796c8dcSSimon Schubert 	is that the archive doesn't have sections.  Instead it has a
345796c8dcSSimon Schubert 	chain of BFDs that are considered its contents.  These BFDs can
355796c8dcSSimon Schubert 	be manipulated like any other.  The BFDs contained in an
365796c8dcSSimon Schubert 	archive opened for reading will all be opened for reading.  You
375796c8dcSSimon Schubert 	may put either input or output BFDs into an archive opened for
385796c8dcSSimon Schubert 	output; they will be handled correctly when the archive is closed.
395796c8dcSSimon Schubert 
405796c8dcSSimon Schubert 	Use <<bfd_openr_next_archived_file>> to step through
415796c8dcSSimon Schubert 	the contents of an archive opened for input.  You don't
425796c8dcSSimon Schubert 	have to read the entire archive if you don't want
435796c8dcSSimon Schubert 	to!  Read it until you find what you want.
445796c8dcSSimon Schubert 
455796c8dcSSimon Schubert 	Archive contents of output BFDs are chained through the
465796c8dcSSimon Schubert 	<<next>> pointer in a BFD.  The first one is findable through
475796c8dcSSimon Schubert 	the <<archive_head>> slot of the archive.  Set it with
485796c8dcSSimon Schubert 	<<bfd_set_archive_head>> (q.v.).  A given BFD may be in only one
495796c8dcSSimon Schubert 	open output archive at a time.
505796c8dcSSimon Schubert 
515796c8dcSSimon Schubert 	As expected, the BFD archive code is more general than the
525796c8dcSSimon Schubert 	archive code of any given environment.  BFD archives may
535796c8dcSSimon Schubert 	contain files of different formats (e.g., a.out and coff) and
545796c8dcSSimon Schubert 	even different architectures.  You may even place archives
555796c8dcSSimon Schubert 	recursively into archives!
565796c8dcSSimon Schubert 
575796c8dcSSimon Schubert 	This can cause unexpected confusion, since some archive
585796c8dcSSimon Schubert 	formats are more expressive than others.  For instance, Intel
595796c8dcSSimon Schubert 	COFF archives can preserve long filenames; SunOS a.out archives
605796c8dcSSimon Schubert 	cannot.  If you move a file from the first to the second
615796c8dcSSimon Schubert 	format and back again, the filename may be truncated.
625796c8dcSSimon Schubert 	Likewise, different a.out environments have different
635796c8dcSSimon Schubert 	conventions as to how they truncate filenames, whether they
645796c8dcSSimon Schubert 	preserve directory names in filenames, etc.  When
655796c8dcSSimon Schubert 	interoperating with native tools, be sure your files are
665796c8dcSSimon Schubert 	homogeneous.
675796c8dcSSimon Schubert 
685796c8dcSSimon Schubert 	Beware: most of these formats do not react well to the
695796c8dcSSimon Schubert 	presence of spaces in filenames.  We do the best we can, but
705796c8dcSSimon Schubert 	can't always handle this case due to restrictions in the format of
715796c8dcSSimon Schubert 	archives.  Many Unix utilities are braindead in regards to
725796c8dcSSimon Schubert 	spaces and such in filenames anyway, so this shouldn't be much
735796c8dcSSimon Schubert 	of a restriction.
745796c8dcSSimon Schubert 
755796c8dcSSimon Schubert 	Archives are supported in BFD in <<archive.c>>.
765796c8dcSSimon Schubert 
775796c8dcSSimon Schubert SUBSECTION
785796c8dcSSimon Schubert 	Archive functions
795796c8dcSSimon Schubert */
805796c8dcSSimon Schubert 
815796c8dcSSimon Schubert /* Assumes:
825796c8dcSSimon Schubert    o - all archive elements start on an even boundary, newline padded;
835796c8dcSSimon Schubert    o - all arch headers are char *;
845796c8dcSSimon Schubert    o - all arch headers are the same size (across architectures).
855796c8dcSSimon Schubert */
865796c8dcSSimon Schubert 
875796c8dcSSimon Schubert /* Some formats provide a way to cram a long filename into the short
885796c8dcSSimon Schubert    (16 chars) space provided by a BSD archive.  The trick is: make a
895796c8dcSSimon Schubert    special "file" in the front of the archive, sort of like the SYMDEF
905796c8dcSSimon Schubert    entry.  If the filename is too long to fit, put it in the extended
915796c8dcSSimon Schubert    name table, and use its index as the filename.  To prevent
925796c8dcSSimon Schubert    confusion prepend the index with a space.  This means you can't
935796c8dcSSimon Schubert    have filenames that start with a space, but then again, many Unix
945796c8dcSSimon Schubert    utilities can't handle that anyway.
955796c8dcSSimon Schubert 
965796c8dcSSimon Schubert    This scheme unfortunately requires that you stand on your head in
975796c8dcSSimon Schubert    order to write an archive since you need to put a magic file at the
985796c8dcSSimon Schubert    front, and need to touch every entry to do so.  C'est la vie.
995796c8dcSSimon Schubert 
1005796c8dcSSimon Schubert    We support two variants of this idea:
1015796c8dcSSimon Schubert    The SVR4 format (extended name table is named "//"),
1025796c8dcSSimon Schubert    and an extended pseudo-BSD variant (extended name table is named
1035796c8dcSSimon Schubert    "ARFILENAMES/").  The origin of the latter format is uncertain.
1045796c8dcSSimon Schubert 
1055796c8dcSSimon Schubert    BSD 4.4 uses a third scheme:  It writes a long filename
1065796c8dcSSimon Schubert    directly after the header.  This allows 'ar q' to work.
1075796c8dcSSimon Schubert */
1085796c8dcSSimon Schubert 
1095796c8dcSSimon Schubert /* Summary of archive member names:
1105796c8dcSSimon Schubert 
1115796c8dcSSimon Schubert  Symbol table (must be first):
1125796c8dcSSimon Schubert  "__.SYMDEF       " - Symbol table, Berkeley style, produced by ranlib.
1135796c8dcSSimon Schubert  "/               " - Symbol table, system 5 style.
1145796c8dcSSimon Schubert 
1155796c8dcSSimon Schubert  Long name table (must be before regular file members):
1165796c8dcSSimon Schubert  "//              " - Long name table, System 5 R4 style.
1175796c8dcSSimon Schubert  "ARFILENAMES/    " - Long name table, non-standard extended BSD (not BSD 4.4).
1185796c8dcSSimon Schubert 
1195796c8dcSSimon Schubert  Regular file members with short names:
1205796c8dcSSimon Schubert  "filename.o/     " - Regular file, System 5 style (embedded spaces ok).
1215796c8dcSSimon Schubert  "filename.o      " - Regular file, Berkeley style (no embedded spaces).
1225796c8dcSSimon Schubert 
1235796c8dcSSimon Schubert  Regular files with long names (or embedded spaces, for BSD variants):
1245796c8dcSSimon Schubert  "/18             " - SVR4 style, name at offset 18 in name table.
1255796c8dcSSimon Schubert  "#1/23           " - Long name (or embedded spaces) 23 characters long,
1265796c8dcSSimon Schubert 		      BSD 4.4 style, full name follows header.
1275796c8dcSSimon Schubert  " 18             " - Long name 18 characters long, extended pseudo-BSD.
1285796c8dcSSimon Schubert  */
1295796c8dcSSimon Schubert 
1305796c8dcSSimon Schubert #include "sysdep.h"
1315796c8dcSSimon Schubert #include "bfd.h"
1325796c8dcSSimon Schubert #include "libiberty.h"
1335796c8dcSSimon Schubert #include "libbfd.h"
1345796c8dcSSimon Schubert #include "aout/ar.h"
1355796c8dcSSimon Schubert #include "aout/ranlib.h"
1365796c8dcSSimon Schubert #include "safe-ctype.h"
1375796c8dcSSimon Schubert #include "hashtab.h"
1385796c8dcSSimon Schubert #include "filenames.h"
1395796c8dcSSimon Schubert 
1405796c8dcSSimon Schubert #ifndef errno
1415796c8dcSSimon Schubert extern int errno;
1425796c8dcSSimon Schubert #endif
1435796c8dcSSimon Schubert 
1445796c8dcSSimon Schubert /* We keep a cache of archive filepointers to archive elements to
1455796c8dcSSimon Schubert    speed up searching the archive by filepos.  We only add an entry to
1465796c8dcSSimon Schubert    the cache when we actually read one.  We also don't sort the cache;
1475796c8dcSSimon Schubert    it's generally short enough to search linearly.
1485796c8dcSSimon Schubert    Note that the pointers here point to the front of the ar_hdr, not
1495796c8dcSSimon Schubert    to the front of the contents!  */
1505796c8dcSSimon Schubert struct ar_cache {
1515796c8dcSSimon Schubert   file_ptr ptr;
1525796c8dcSSimon Schubert   bfd *arbfd;
1535796c8dcSSimon Schubert };
1545796c8dcSSimon Schubert 
1555796c8dcSSimon Schubert #define ar_padchar(abfd) ((abfd)->xvec->ar_pad_char)
1565796c8dcSSimon Schubert #define ar_maxnamelen(abfd) ((abfd)->xvec->ar_max_namelen)
1575796c8dcSSimon Schubert 
1585796c8dcSSimon Schubert #define arch_eltdata(bfd) ((struct areltdata *) ((bfd)->arelt_data))
1595796c8dcSSimon Schubert #define arch_hdr(bfd) ((struct ar_hdr *) arch_eltdata (bfd)->arch_header)
160cf7f2e2dSJohn Marino 
161cf7f2e2dSJohn Marino /* True iff NAME designated a BSD 4.4 extended name.  */
162cf7f2e2dSJohn Marino 
163cf7f2e2dSJohn Marino #define is_bsd44_extended_name(NAME) \
164cf7f2e2dSJohn Marino   (NAME[0] == '#'  && NAME[1] == '1' && NAME[2] == '/' && ISDIGIT (NAME[3]))
1655796c8dcSSimon Schubert 
1665796c8dcSSimon Schubert void
1675796c8dcSSimon Schubert _bfd_ar_spacepad (char *p, size_t n, const char *fmt, long val)
1685796c8dcSSimon Schubert {
1695796c8dcSSimon Schubert   static char buf[20];
1705796c8dcSSimon Schubert   size_t len;
1715796c8dcSSimon Schubert   snprintf (buf, sizeof (buf), fmt, val);
1725796c8dcSSimon Schubert   len = strlen (buf);
1735796c8dcSSimon Schubert   if (len < n)
1745796c8dcSSimon Schubert     {
1755796c8dcSSimon Schubert       memcpy (p, buf, len);
1765796c8dcSSimon Schubert       memset (p + len, ' ', n - len);
1775796c8dcSSimon Schubert     }
1785796c8dcSSimon Schubert   else
1795796c8dcSSimon Schubert     memcpy (p, buf, n);
1805796c8dcSSimon Schubert }
1815796c8dcSSimon Schubert 
1825796c8dcSSimon Schubert bfd_boolean
1835796c8dcSSimon Schubert _bfd_generic_mkarchive (bfd *abfd)
1845796c8dcSSimon Schubert {
1855796c8dcSSimon Schubert   bfd_size_type amt = sizeof (struct artdata);
1865796c8dcSSimon Schubert 
1875796c8dcSSimon Schubert   abfd->tdata.aout_ar_data = (struct artdata *) bfd_zalloc (abfd, amt);
1885796c8dcSSimon Schubert   if (bfd_ardata (abfd) == NULL)
1895796c8dcSSimon Schubert     return FALSE;
1905796c8dcSSimon Schubert 
1915796c8dcSSimon Schubert   /* Already cleared by bfd_zalloc above.
1925796c8dcSSimon Schubert      bfd_ardata (abfd)->cache = NULL;
1935796c8dcSSimon Schubert      bfd_ardata (abfd)->archive_head = NULL;
1945796c8dcSSimon Schubert      bfd_ardata (abfd)->symdefs = NULL;
1955796c8dcSSimon Schubert      bfd_ardata (abfd)->extended_names = NULL;
1965796c8dcSSimon Schubert      bfd_ardata (abfd)->extended_names_size = 0;
1975796c8dcSSimon Schubert      bfd_ardata (abfd)->tdata = NULL;  */
1985796c8dcSSimon Schubert 
1995796c8dcSSimon Schubert   return TRUE;
2005796c8dcSSimon Schubert }
2015796c8dcSSimon Schubert 
2025796c8dcSSimon Schubert /*
2035796c8dcSSimon Schubert FUNCTION
2045796c8dcSSimon Schubert 	bfd_get_next_mapent
2055796c8dcSSimon Schubert 
2065796c8dcSSimon Schubert SYNOPSIS
2075796c8dcSSimon Schubert 	symindex bfd_get_next_mapent
2085796c8dcSSimon Schubert 	  (bfd *abfd, symindex previous, carsym **sym);
2095796c8dcSSimon Schubert 
2105796c8dcSSimon Schubert DESCRIPTION
2115796c8dcSSimon Schubert 	Step through archive @var{abfd}'s symbol table (if it
2125796c8dcSSimon Schubert 	has one).  Successively update @var{sym} with the next symbol's
2135796c8dcSSimon Schubert 	information, returning that symbol's (internal) index into the
2145796c8dcSSimon Schubert 	symbol table.
2155796c8dcSSimon Schubert 
2165796c8dcSSimon Schubert 	Supply <<BFD_NO_MORE_SYMBOLS>> as the @var{previous} entry to get
2175796c8dcSSimon Schubert 	the first one; returns <<BFD_NO_MORE_SYMBOLS>> when you've already
2185796c8dcSSimon Schubert 	got the last one.
2195796c8dcSSimon Schubert 
2205796c8dcSSimon Schubert 	A <<carsym>> is a canonical archive symbol.  The only
2215796c8dcSSimon Schubert 	user-visible element is its name, a null-terminated string.
2225796c8dcSSimon Schubert */
2235796c8dcSSimon Schubert 
2245796c8dcSSimon Schubert symindex
2255796c8dcSSimon Schubert bfd_get_next_mapent (bfd *abfd, symindex prev, carsym **entry)
2265796c8dcSSimon Schubert {
2275796c8dcSSimon Schubert   if (!bfd_has_map (abfd))
2285796c8dcSSimon Schubert     {
2295796c8dcSSimon Schubert       bfd_set_error (bfd_error_invalid_operation);
2305796c8dcSSimon Schubert       return BFD_NO_MORE_SYMBOLS;
2315796c8dcSSimon Schubert     }
2325796c8dcSSimon Schubert 
2335796c8dcSSimon Schubert   if (prev == BFD_NO_MORE_SYMBOLS)
2345796c8dcSSimon Schubert     prev = 0;
2355796c8dcSSimon Schubert   else
2365796c8dcSSimon Schubert     ++prev;
2375796c8dcSSimon Schubert   if (prev >= bfd_ardata (abfd)->symdef_count)
2385796c8dcSSimon Schubert     return BFD_NO_MORE_SYMBOLS;
2395796c8dcSSimon Schubert 
2405796c8dcSSimon Schubert   *entry = (bfd_ardata (abfd)->symdefs + prev);
2415796c8dcSSimon Schubert   return prev;
2425796c8dcSSimon Schubert }
2435796c8dcSSimon Schubert 
2445796c8dcSSimon Schubert /* To be called by backends only.  */
2455796c8dcSSimon Schubert 
2465796c8dcSSimon Schubert bfd *
2475796c8dcSSimon Schubert _bfd_create_empty_archive_element_shell (bfd *obfd)
2485796c8dcSSimon Schubert {
2495796c8dcSSimon Schubert   return _bfd_new_bfd_contained_in (obfd);
2505796c8dcSSimon Schubert }
2515796c8dcSSimon Schubert 
2525796c8dcSSimon Schubert /*
2535796c8dcSSimon Schubert FUNCTION
2545796c8dcSSimon Schubert 	bfd_set_archive_head
2555796c8dcSSimon Schubert 
2565796c8dcSSimon Schubert SYNOPSIS
2575796c8dcSSimon Schubert 	bfd_boolean bfd_set_archive_head (bfd *output, bfd *new_head);
2585796c8dcSSimon Schubert 
2595796c8dcSSimon Schubert DESCRIPTION
2605796c8dcSSimon Schubert 	Set the head of the chain of
2615796c8dcSSimon Schubert 	BFDs contained in the archive @var{output} to @var{new_head}.
2625796c8dcSSimon Schubert */
2635796c8dcSSimon Schubert 
2645796c8dcSSimon Schubert bfd_boolean
2655796c8dcSSimon Schubert bfd_set_archive_head (bfd *output_archive, bfd *new_head)
2665796c8dcSSimon Schubert {
2675796c8dcSSimon Schubert   output_archive->archive_head = new_head;
2685796c8dcSSimon Schubert   return TRUE;
2695796c8dcSSimon Schubert }
2705796c8dcSSimon Schubert 
2715796c8dcSSimon Schubert bfd *
2725796c8dcSSimon Schubert _bfd_look_for_bfd_in_cache (bfd *arch_bfd, file_ptr filepos)
2735796c8dcSSimon Schubert {
2745796c8dcSSimon Schubert   htab_t hash_table = bfd_ardata (arch_bfd)->cache;
2755796c8dcSSimon Schubert   struct ar_cache m;
2765796c8dcSSimon Schubert   m.ptr = filepos;
2775796c8dcSSimon Schubert 
2785796c8dcSSimon Schubert   if (hash_table)
2795796c8dcSSimon Schubert     {
2805796c8dcSSimon Schubert       struct ar_cache *entry = (struct ar_cache *) htab_find (hash_table, &m);
2815796c8dcSSimon Schubert       if (!entry)
2825796c8dcSSimon Schubert 	return NULL;
2835796c8dcSSimon Schubert       else
2845796c8dcSSimon Schubert 	return entry->arbfd;
2855796c8dcSSimon Schubert     }
2865796c8dcSSimon Schubert   else
2875796c8dcSSimon Schubert     return NULL;
2885796c8dcSSimon Schubert }
2895796c8dcSSimon Schubert 
2905796c8dcSSimon Schubert static hashval_t
2915796c8dcSSimon Schubert hash_file_ptr (const PTR p)
2925796c8dcSSimon Schubert {
2935796c8dcSSimon Schubert   return (hashval_t) (((struct ar_cache *) p)->ptr);
2945796c8dcSSimon Schubert }
2955796c8dcSSimon Schubert 
2965796c8dcSSimon Schubert /* Returns non-zero if P1 and P2 are equal.  */
2975796c8dcSSimon Schubert 
2985796c8dcSSimon Schubert static int
2995796c8dcSSimon Schubert eq_file_ptr (const PTR p1, const PTR p2)
3005796c8dcSSimon Schubert {
3015796c8dcSSimon Schubert   struct ar_cache *arc1 = (struct ar_cache *) p1;
3025796c8dcSSimon Schubert   struct ar_cache *arc2 = (struct ar_cache *) p2;
3035796c8dcSSimon Schubert   return arc1->ptr == arc2->ptr;
3045796c8dcSSimon Schubert }
3055796c8dcSSimon Schubert 
306cf7f2e2dSJohn Marino /* The calloc function doesn't always take size_t (e.g. on VMS)
307cf7f2e2dSJohn Marino    so wrap it to avoid a compile time warning.   */
308cf7f2e2dSJohn Marino 
309cf7f2e2dSJohn Marino static void *
310cf7f2e2dSJohn Marino _bfd_calloc_wrapper (size_t a, size_t b)
311cf7f2e2dSJohn Marino {
312cf7f2e2dSJohn Marino   return calloc (a, b);
313cf7f2e2dSJohn Marino }
314cf7f2e2dSJohn Marino 
3155796c8dcSSimon Schubert /* Kind of stupid to call cons for each one, but we don't do too many.  */
3165796c8dcSSimon Schubert 
3175796c8dcSSimon Schubert bfd_boolean
3185796c8dcSSimon Schubert _bfd_add_bfd_to_archive_cache (bfd *arch_bfd, file_ptr filepos, bfd *new_elt)
3195796c8dcSSimon Schubert {
3205796c8dcSSimon Schubert   struct ar_cache *cache;
3215796c8dcSSimon Schubert   htab_t hash_table = bfd_ardata (arch_bfd)->cache;
3225796c8dcSSimon Schubert 
3235796c8dcSSimon Schubert   /* If the hash table hasn't been created, create it.  */
3245796c8dcSSimon Schubert   if (hash_table == NULL)
3255796c8dcSSimon Schubert     {
3265796c8dcSSimon Schubert       hash_table = htab_create_alloc (16, hash_file_ptr, eq_file_ptr,
327cf7f2e2dSJohn Marino 				      NULL, _bfd_calloc_wrapper, free);
3285796c8dcSSimon Schubert       if (hash_table == NULL)
3295796c8dcSSimon Schubert 	return FALSE;
3305796c8dcSSimon Schubert       bfd_ardata (arch_bfd)->cache = hash_table;
3315796c8dcSSimon Schubert     }
3325796c8dcSSimon Schubert 
3335796c8dcSSimon Schubert   /* Insert new_elt into the hash table by filepos.  */
3345796c8dcSSimon Schubert   cache = (struct ar_cache *) bfd_zalloc (arch_bfd, sizeof (struct ar_cache));
3355796c8dcSSimon Schubert   cache->ptr = filepos;
3365796c8dcSSimon Schubert   cache->arbfd = new_elt;
3375796c8dcSSimon Schubert   *htab_find_slot (hash_table, (const void *) cache, INSERT) = cache;
3385796c8dcSSimon Schubert 
3395796c8dcSSimon Schubert   return TRUE;
3405796c8dcSSimon Schubert }
3415796c8dcSSimon Schubert 
3425796c8dcSSimon Schubert static bfd *
3435796c8dcSSimon Schubert _bfd_find_nested_archive (bfd *arch_bfd, const char *filename)
3445796c8dcSSimon Schubert {
3455796c8dcSSimon Schubert   bfd *abfd;
346*a45ae5f8SJohn Marino   const char *target;
3475796c8dcSSimon Schubert 
3485796c8dcSSimon Schubert   for (abfd = arch_bfd->nested_archives;
3495796c8dcSSimon Schubert        abfd != NULL;
3505796c8dcSSimon Schubert        abfd = abfd->archive_next)
3515796c8dcSSimon Schubert     {
352c50c785cSJohn Marino       if (filename_cmp (filename, abfd->filename) == 0)
3535796c8dcSSimon Schubert         return abfd;
3545796c8dcSSimon Schubert     }
355*a45ae5f8SJohn Marino   target = NULL;
356*a45ae5f8SJohn Marino   if (!arch_bfd->target_defaulted)
357*a45ae5f8SJohn Marino     target = arch_bfd->xvec->name;
358*a45ae5f8SJohn Marino   abfd = bfd_openr (filename, target);
3595796c8dcSSimon Schubert   if (abfd)
3605796c8dcSSimon Schubert     {
3615796c8dcSSimon Schubert       abfd->archive_next = arch_bfd->nested_archives;
3625796c8dcSSimon Schubert       arch_bfd->nested_archives = abfd;
3635796c8dcSSimon Schubert     }
3645796c8dcSSimon Schubert   return abfd;
3655796c8dcSSimon Schubert }
3665796c8dcSSimon Schubert 
3675796c8dcSSimon Schubert /* The name begins with space.  Hence the rest of the name is an index into
3685796c8dcSSimon Schubert    the string table.  */
3695796c8dcSSimon Schubert 
3705796c8dcSSimon Schubert static char *
3715796c8dcSSimon Schubert get_extended_arelt_filename (bfd *arch, const char *name, file_ptr *originp)
3725796c8dcSSimon Schubert {
373cf7f2e2dSJohn Marino   unsigned long table_index = 0;
3745796c8dcSSimon Schubert   const char *endp;
3755796c8dcSSimon Schubert 
3765796c8dcSSimon Schubert   /* Should extract string so that I can guarantee not to overflow into
3775796c8dcSSimon Schubert      the next region, but I'm too lazy.  */
3785796c8dcSSimon Schubert   errno = 0;
3795796c8dcSSimon Schubert   /* Skip first char, which is '/' in SVR4 or ' ' in some other variants.  */
380cf7f2e2dSJohn Marino   table_index = strtol (name + 1, (char **) &endp, 10);
381cf7f2e2dSJohn Marino   if (errno != 0 || table_index >= bfd_ardata (arch)->extended_names_size)
3825796c8dcSSimon Schubert     {
3835796c8dcSSimon Schubert       bfd_set_error (bfd_error_malformed_archive);
3845796c8dcSSimon Schubert       return NULL;
3855796c8dcSSimon Schubert     }
3865796c8dcSSimon Schubert   /* In a thin archive, a member of an archive-within-an-archive
3875796c8dcSSimon Schubert      will have the offset in the inner archive encoded here.  */
3885796c8dcSSimon Schubert   if (bfd_is_thin_archive (arch) && endp != NULL && *endp == ':')
3895796c8dcSSimon Schubert     {
3905796c8dcSSimon Schubert       file_ptr origin = strtol (endp + 1, NULL, 10);
3915796c8dcSSimon Schubert 
3925796c8dcSSimon Schubert       if (errno != 0)
3935796c8dcSSimon Schubert         {
3945796c8dcSSimon Schubert           bfd_set_error (bfd_error_malformed_archive);
3955796c8dcSSimon Schubert           return NULL;
3965796c8dcSSimon Schubert         }
3975796c8dcSSimon Schubert       *originp = origin;
3985796c8dcSSimon Schubert     }
3995796c8dcSSimon Schubert   else
4005796c8dcSSimon Schubert     *originp = 0;
4015796c8dcSSimon Schubert 
402cf7f2e2dSJohn Marino   return bfd_ardata (arch)->extended_names + table_index;
4035796c8dcSSimon Schubert }
4045796c8dcSSimon Schubert 
4055796c8dcSSimon Schubert /* This functions reads an arch header and returns an areltdata pointer, or
4065796c8dcSSimon Schubert    NULL on error.
4075796c8dcSSimon Schubert 
4085796c8dcSSimon Schubert    Presumes the file pointer is already in the right place (ie pointing
4095796c8dcSSimon Schubert    to the ar_hdr in the file).   Moves the file pointer; on success it
4105796c8dcSSimon Schubert    should be pointing to the front of the file contents; on failure it
4115796c8dcSSimon Schubert    could have been moved arbitrarily.  */
4125796c8dcSSimon Schubert 
4135796c8dcSSimon Schubert void *
4145796c8dcSSimon Schubert _bfd_generic_read_ar_hdr (bfd *abfd)
4155796c8dcSSimon Schubert {
4165796c8dcSSimon Schubert   return _bfd_generic_read_ar_hdr_mag (abfd, NULL);
4175796c8dcSSimon Schubert }
4185796c8dcSSimon Schubert 
4195796c8dcSSimon Schubert /* Alpha ECOFF uses an optional different ARFMAG value, so we have a
4205796c8dcSSimon Schubert    variant of _bfd_generic_read_ar_hdr which accepts a magic string.  */
4215796c8dcSSimon Schubert 
4225796c8dcSSimon Schubert void *
4235796c8dcSSimon Schubert _bfd_generic_read_ar_hdr_mag (bfd *abfd, const char *mag)
4245796c8dcSSimon Schubert {
4255796c8dcSSimon Schubert   struct ar_hdr hdr;
4265796c8dcSSimon Schubert   char *hdrp = (char *) &hdr;
4275796c8dcSSimon Schubert   size_t parsed_size;
4285796c8dcSSimon Schubert   struct areltdata *ared;
4295796c8dcSSimon Schubert   char *filename = NULL;
4305796c8dcSSimon Schubert   bfd_size_type namelen = 0;
4315796c8dcSSimon Schubert   bfd_size_type allocsize = sizeof (struct areltdata) + sizeof (struct ar_hdr);
4325796c8dcSSimon Schubert   char *allocptr = 0;
4335796c8dcSSimon Schubert   file_ptr origin = 0;
434cf7f2e2dSJohn Marino   unsigned int extra_size = 0;
4355796c8dcSSimon Schubert 
4365796c8dcSSimon Schubert   if (bfd_bread (hdrp, sizeof (struct ar_hdr), abfd) != sizeof (struct ar_hdr))
4375796c8dcSSimon Schubert     {
4385796c8dcSSimon Schubert       if (bfd_get_error () != bfd_error_system_call)
4395796c8dcSSimon Schubert 	bfd_set_error (bfd_error_no_more_archived_files);
4405796c8dcSSimon Schubert       return NULL;
4415796c8dcSSimon Schubert     }
4425796c8dcSSimon Schubert   if (strncmp (hdr.ar_fmag, ARFMAG, 2) != 0
4435796c8dcSSimon Schubert       && (mag == NULL
4445796c8dcSSimon Schubert 	  || strncmp (hdr.ar_fmag, mag, 2) != 0))
4455796c8dcSSimon Schubert     {
4465796c8dcSSimon Schubert       bfd_set_error (bfd_error_malformed_archive);
4475796c8dcSSimon Schubert       return NULL;
4485796c8dcSSimon Schubert     }
4495796c8dcSSimon Schubert 
4505796c8dcSSimon Schubert   errno = 0;
4515796c8dcSSimon Schubert   parsed_size = strtol (hdr.ar_size, NULL, 10);
4525796c8dcSSimon Schubert   if (errno != 0)
4535796c8dcSSimon Schubert     {
4545796c8dcSSimon Schubert       bfd_set_error (bfd_error_malformed_archive);
4555796c8dcSSimon Schubert       return NULL;
4565796c8dcSSimon Schubert     }
4575796c8dcSSimon Schubert 
4585796c8dcSSimon Schubert   /* Extract the filename from the archive - there are two ways to
4595796c8dcSSimon Schubert      specify an extended name table, either the first char of the
4605796c8dcSSimon Schubert      name is a space, or it's a slash.  */
4615796c8dcSSimon Schubert   if ((hdr.ar_name[0] == '/'
4625796c8dcSSimon Schubert        || (hdr.ar_name[0] == ' '
4635796c8dcSSimon Schubert 	   && memchr (hdr.ar_name, '/', ar_maxnamelen (abfd)) == NULL))
4645796c8dcSSimon Schubert       && bfd_ardata (abfd)->extended_names != NULL)
4655796c8dcSSimon Schubert     {
4665796c8dcSSimon Schubert       filename = get_extended_arelt_filename (abfd, hdr.ar_name, &origin);
4675796c8dcSSimon Schubert       if (filename == NULL)
4685796c8dcSSimon Schubert 	return NULL;
4695796c8dcSSimon Schubert     }
470cf7f2e2dSJohn Marino   /* BSD4.4-style long filename.  */
471cf7f2e2dSJohn Marino   else if (is_bsd44_extended_name (hdr.ar_name))
4725796c8dcSSimon Schubert     {
4735796c8dcSSimon Schubert       /* BSD-4.4 extended name */
4745796c8dcSSimon Schubert       namelen = atoi (&hdr.ar_name[3]);
4755796c8dcSSimon Schubert       allocsize += namelen + 1;
4765796c8dcSSimon Schubert       parsed_size -= namelen;
477cf7f2e2dSJohn Marino       extra_size = namelen;
4785796c8dcSSimon Schubert 
4795796c8dcSSimon Schubert       allocptr = (char *) bfd_zalloc (abfd, allocsize);
4805796c8dcSSimon Schubert       if (allocptr == NULL)
4815796c8dcSSimon Schubert 	return NULL;
4825796c8dcSSimon Schubert       filename = (allocptr
4835796c8dcSSimon Schubert 		  + sizeof (struct areltdata)
4845796c8dcSSimon Schubert 		  + sizeof (struct ar_hdr));
4855796c8dcSSimon Schubert       if (bfd_bread (filename, namelen, abfd) != namelen)
4865796c8dcSSimon Schubert 	{
4875796c8dcSSimon Schubert 	  if (bfd_get_error () != bfd_error_system_call)
4885796c8dcSSimon Schubert 	    bfd_set_error (bfd_error_no_more_archived_files);
4895796c8dcSSimon Schubert 	  return NULL;
4905796c8dcSSimon Schubert 	}
4915796c8dcSSimon Schubert       filename[namelen] = '\0';
4925796c8dcSSimon Schubert     }
4935796c8dcSSimon Schubert   else
4945796c8dcSSimon Schubert     {
4955796c8dcSSimon Schubert       /* We judge the end of the name by looking for '/' or ' '.
4965796c8dcSSimon Schubert 	 Note:  The SYSV format (terminated by '/') allows embedded
4975796c8dcSSimon Schubert 	 spaces, so only look for ' ' if we don't find '/'.  */
4985796c8dcSSimon Schubert 
4995796c8dcSSimon Schubert       char *e;
5005796c8dcSSimon Schubert       e = (char *) memchr (hdr.ar_name, '\0', ar_maxnamelen (abfd));
5015796c8dcSSimon Schubert       if (e == NULL)
5025796c8dcSSimon Schubert 	{
5035796c8dcSSimon Schubert 	  e = (char *) memchr (hdr.ar_name, '/', ar_maxnamelen (abfd));
5045796c8dcSSimon Schubert 	  if (e == NULL)
5055796c8dcSSimon Schubert 	    e = (char *) memchr (hdr.ar_name, ' ', ar_maxnamelen (abfd));
5065796c8dcSSimon Schubert 	}
5075796c8dcSSimon Schubert 
5085796c8dcSSimon Schubert       if (e != NULL)
5095796c8dcSSimon Schubert 	namelen = e - hdr.ar_name;
5105796c8dcSSimon Schubert       else
5115796c8dcSSimon Schubert 	{
5125796c8dcSSimon Schubert 	  /* If we didn't find a termination character, then the name
5135796c8dcSSimon Schubert 	     must be the entire field.  */
5145796c8dcSSimon Schubert 	  namelen = ar_maxnamelen (abfd);
5155796c8dcSSimon Schubert 	}
5165796c8dcSSimon Schubert 
5175796c8dcSSimon Schubert       allocsize += namelen + 1;
5185796c8dcSSimon Schubert     }
5195796c8dcSSimon Schubert 
5205796c8dcSSimon Schubert   if (!allocptr)
5215796c8dcSSimon Schubert     {
5225796c8dcSSimon Schubert       allocptr = (char *) bfd_zalloc (abfd, allocsize);
5235796c8dcSSimon Schubert       if (allocptr == NULL)
5245796c8dcSSimon Schubert 	return NULL;
5255796c8dcSSimon Schubert     }
5265796c8dcSSimon Schubert 
5275796c8dcSSimon Schubert   ared = (struct areltdata *) allocptr;
5285796c8dcSSimon Schubert 
5295796c8dcSSimon Schubert   ared->arch_header = allocptr + sizeof (struct areltdata);
5305796c8dcSSimon Schubert   memcpy (ared->arch_header, &hdr, sizeof (struct ar_hdr));
5315796c8dcSSimon Schubert   ared->parsed_size = parsed_size;
532cf7f2e2dSJohn Marino   ared->extra_size = extra_size;
5335796c8dcSSimon Schubert   ared->origin = origin;
5345796c8dcSSimon Schubert 
5355796c8dcSSimon Schubert   if (filename != NULL)
5365796c8dcSSimon Schubert     ared->filename = filename;
5375796c8dcSSimon Schubert   else
5385796c8dcSSimon Schubert     {
5395796c8dcSSimon Schubert       ared->filename = allocptr + (sizeof (struct areltdata) +
5405796c8dcSSimon Schubert 				   sizeof (struct ar_hdr));
5415796c8dcSSimon Schubert       if (namelen)
5425796c8dcSSimon Schubert 	memcpy (ared->filename, hdr.ar_name, namelen);
5435796c8dcSSimon Schubert       ared->filename[namelen] = '\0';
5445796c8dcSSimon Schubert     }
5455796c8dcSSimon Schubert 
5465796c8dcSSimon Schubert   return ared;
5475796c8dcSSimon Schubert }
5485796c8dcSSimon Schubert 
5495796c8dcSSimon Schubert /* Append the relative pathname for a member of the thin archive
5505796c8dcSSimon Schubert    to the pathname of the directory containing the archive.  */
5515796c8dcSSimon Schubert 
552cf7f2e2dSJohn Marino char *
553cf7f2e2dSJohn Marino _bfd_append_relative_path (bfd *arch, char *elt_name)
5545796c8dcSSimon Schubert {
5555796c8dcSSimon Schubert   const char *arch_name = arch->filename;
5565796c8dcSSimon Schubert   const char *base_name = lbasename (arch_name);
5575796c8dcSSimon Schubert   size_t prefix_len;
5585796c8dcSSimon Schubert   char *filename;
5595796c8dcSSimon Schubert 
5605796c8dcSSimon Schubert   if (base_name == arch_name)
5615796c8dcSSimon Schubert     return elt_name;
5625796c8dcSSimon Schubert 
5635796c8dcSSimon Schubert   prefix_len = base_name - arch_name;
5645796c8dcSSimon Schubert   filename = (char *) bfd_alloc (arch, prefix_len + strlen (elt_name) + 1);
5655796c8dcSSimon Schubert   if (filename == NULL)
5665796c8dcSSimon Schubert     return NULL;
5675796c8dcSSimon Schubert 
5685796c8dcSSimon Schubert   strncpy (filename, arch_name, prefix_len);
5695796c8dcSSimon Schubert   strcpy (filename + prefix_len, elt_name);
5705796c8dcSSimon Schubert   return filename;
5715796c8dcSSimon Schubert }
5725796c8dcSSimon Schubert 
5735796c8dcSSimon Schubert /* This is an internal function; it's mainly used when indexing
5745796c8dcSSimon Schubert    through the archive symbol table, but also used to get the next
5755796c8dcSSimon Schubert    element, since it handles the bookkeeping so nicely for us.  */
5765796c8dcSSimon Schubert 
5775796c8dcSSimon Schubert bfd *
5785796c8dcSSimon Schubert _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos)
5795796c8dcSSimon Schubert {
5805796c8dcSSimon Schubert   struct areltdata *new_areldata;
5815796c8dcSSimon Schubert   bfd *n_nfd;
5825796c8dcSSimon Schubert   char *filename;
5835796c8dcSSimon Schubert 
5845796c8dcSSimon Schubert   if (archive->my_archive)
5855796c8dcSSimon Schubert     {
5865796c8dcSSimon Schubert       filepos += archive->origin;
5875796c8dcSSimon Schubert       archive = archive->my_archive;
5885796c8dcSSimon Schubert     }
5895796c8dcSSimon Schubert 
5905796c8dcSSimon Schubert   n_nfd = _bfd_look_for_bfd_in_cache (archive, filepos);
5915796c8dcSSimon Schubert   if (n_nfd)
5925796c8dcSSimon Schubert     return n_nfd;
5935796c8dcSSimon Schubert 
5945796c8dcSSimon Schubert   if (0 > bfd_seek (archive, filepos, SEEK_SET))
5955796c8dcSSimon Schubert     return NULL;
5965796c8dcSSimon Schubert 
5975796c8dcSSimon Schubert   if ((new_areldata = (struct areltdata *) _bfd_read_ar_hdr (archive)) == NULL)
5985796c8dcSSimon Schubert     return NULL;
5995796c8dcSSimon Schubert 
6005796c8dcSSimon Schubert   filename = new_areldata->filename;
6015796c8dcSSimon Schubert 
6025796c8dcSSimon Schubert   if (bfd_is_thin_archive (archive))
6035796c8dcSSimon Schubert     {
604*a45ae5f8SJohn Marino       const char *target;
605*a45ae5f8SJohn Marino 
6065796c8dcSSimon Schubert       /* This is a proxy entry for an external file.  */
6075796c8dcSSimon Schubert       if (! IS_ABSOLUTE_PATH (filename))
6085796c8dcSSimon Schubert         {
609cf7f2e2dSJohn Marino           filename = _bfd_append_relative_path (archive, filename);
6105796c8dcSSimon Schubert           if (filename == NULL)
6115796c8dcSSimon Schubert             return NULL;
6125796c8dcSSimon Schubert         }
6135796c8dcSSimon Schubert 
6145796c8dcSSimon Schubert       if (new_areldata->origin > 0)
6155796c8dcSSimon Schubert         {
6165796c8dcSSimon Schubert           /* This proxy entry refers to an element of a nested archive.
6175796c8dcSSimon Schubert              Locate the member of that archive and return a bfd for it.  */
6185796c8dcSSimon Schubert           bfd *ext_arch = _bfd_find_nested_archive (archive, filename);
6195796c8dcSSimon Schubert 
6205796c8dcSSimon Schubert           if (ext_arch == NULL
6215796c8dcSSimon Schubert               || ! bfd_check_format (ext_arch, bfd_archive))
6225796c8dcSSimon Schubert             {
6235796c8dcSSimon Schubert               bfd_release (archive, new_areldata);
6245796c8dcSSimon Schubert               return NULL;
6255796c8dcSSimon Schubert             }
6265796c8dcSSimon Schubert           n_nfd = _bfd_get_elt_at_filepos (ext_arch, new_areldata->origin);
6275796c8dcSSimon Schubert           if (n_nfd == NULL)
6285796c8dcSSimon Schubert             {
6295796c8dcSSimon Schubert               bfd_release (archive, new_areldata);
6305796c8dcSSimon Schubert               return NULL;
6315796c8dcSSimon Schubert             }
6325796c8dcSSimon Schubert           n_nfd->proxy_origin = bfd_tell (archive);
6335796c8dcSSimon Schubert           return n_nfd;
6345796c8dcSSimon Schubert         }
6355796c8dcSSimon Schubert       /* It's not an element of a nested archive;
6365796c8dcSSimon Schubert          open the external file as a bfd.  */
637*a45ae5f8SJohn Marino       target = NULL;
638*a45ae5f8SJohn Marino       if (!archive->target_defaulted)
639*a45ae5f8SJohn Marino 	target = archive->xvec->name;
640*a45ae5f8SJohn Marino       n_nfd = bfd_openr (filename, target);
641*a45ae5f8SJohn Marino       if (n_nfd == NULL)
642*a45ae5f8SJohn Marino 	bfd_set_error (bfd_error_malformed_archive);
6435796c8dcSSimon Schubert     }
6445796c8dcSSimon Schubert   else
6455796c8dcSSimon Schubert     {
6465796c8dcSSimon Schubert       n_nfd = _bfd_create_empty_archive_element_shell (archive);
6475796c8dcSSimon Schubert     }
6485796c8dcSSimon Schubert 
6495796c8dcSSimon Schubert   if (n_nfd == NULL)
6505796c8dcSSimon Schubert     {
6515796c8dcSSimon Schubert       bfd_release (archive, new_areldata);
6525796c8dcSSimon Schubert       return NULL;
6535796c8dcSSimon Schubert     }
6545796c8dcSSimon Schubert 
6555796c8dcSSimon Schubert   n_nfd->proxy_origin = bfd_tell (archive);
6565796c8dcSSimon Schubert 
6575796c8dcSSimon Schubert   if (bfd_is_thin_archive (archive))
6585796c8dcSSimon Schubert     {
6595796c8dcSSimon Schubert       n_nfd->origin = 0;
6605796c8dcSSimon Schubert     }
6615796c8dcSSimon Schubert   else
6625796c8dcSSimon Schubert     {
6635796c8dcSSimon Schubert       n_nfd->origin = n_nfd->proxy_origin;
6645796c8dcSSimon Schubert       n_nfd->filename = filename;
6655796c8dcSSimon Schubert     }
6665796c8dcSSimon Schubert 
6675796c8dcSSimon Schubert   n_nfd->arelt_data = new_areldata;
6685796c8dcSSimon Schubert 
669c50c785cSJohn Marino   /* Copy BFD_COMPRESS and BFD_DECOMPRESS flags.  */
670c50c785cSJohn Marino   n_nfd->flags |= archive->flags & (BFD_COMPRESS | BFD_DECOMPRESS);
671c50c785cSJohn Marino 
6725796c8dcSSimon Schubert   if (_bfd_add_bfd_to_archive_cache (archive, filepos, n_nfd))
6735796c8dcSSimon Schubert     return n_nfd;
6745796c8dcSSimon Schubert 
6755796c8dcSSimon Schubert   bfd_release (archive, new_areldata);
6765796c8dcSSimon Schubert   return NULL;
6775796c8dcSSimon Schubert }
6785796c8dcSSimon Schubert 
6795796c8dcSSimon Schubert /* Return the BFD which is referenced by the symbol in ABFD indexed by
680cf7f2e2dSJohn Marino    SYM_INDEX.  SYM_INDEX should have been returned by bfd_get_next_mapent.  */
6815796c8dcSSimon Schubert 
6825796c8dcSSimon Schubert bfd *
683cf7f2e2dSJohn Marino _bfd_generic_get_elt_at_index (bfd *abfd, symindex sym_index)
6845796c8dcSSimon Schubert {
6855796c8dcSSimon Schubert   carsym *entry;
6865796c8dcSSimon Schubert 
687cf7f2e2dSJohn Marino   entry = bfd_ardata (abfd)->symdefs + sym_index;
6885796c8dcSSimon Schubert   return _bfd_get_elt_at_filepos (abfd, entry->file_offset);
6895796c8dcSSimon Schubert }
6905796c8dcSSimon Schubert 
6915796c8dcSSimon Schubert /*
6925796c8dcSSimon Schubert FUNCTION
6935796c8dcSSimon Schubert 	bfd_openr_next_archived_file
6945796c8dcSSimon Schubert 
6955796c8dcSSimon Schubert SYNOPSIS
6965796c8dcSSimon Schubert 	bfd *bfd_openr_next_archived_file (bfd *archive, bfd *previous);
6975796c8dcSSimon Schubert 
6985796c8dcSSimon Schubert DESCRIPTION
6995796c8dcSSimon Schubert 	Provided a BFD, @var{archive}, containing an archive and NULL, open
7005796c8dcSSimon Schubert 	an input BFD on the first contained element and returns that.
7015796c8dcSSimon Schubert 	Subsequent calls should pass
7025796c8dcSSimon Schubert 	the archive and the previous return value to return a created
7035796c8dcSSimon Schubert 	BFD to the next contained element. NULL is returned when there
7045796c8dcSSimon Schubert 	are no more.
7055796c8dcSSimon Schubert */
7065796c8dcSSimon Schubert 
7075796c8dcSSimon Schubert bfd *
7085796c8dcSSimon Schubert bfd_openr_next_archived_file (bfd *archive, bfd *last_file)
7095796c8dcSSimon Schubert {
7105796c8dcSSimon Schubert   if ((bfd_get_format (archive) != bfd_archive)
7115796c8dcSSimon Schubert       || (archive->direction == write_direction))
7125796c8dcSSimon Schubert     {
7135796c8dcSSimon Schubert       bfd_set_error (bfd_error_invalid_operation);
7145796c8dcSSimon Schubert       return NULL;
7155796c8dcSSimon Schubert     }
7165796c8dcSSimon Schubert 
7175796c8dcSSimon Schubert   return BFD_SEND (archive,
7185796c8dcSSimon Schubert 		   openr_next_archived_file, (archive, last_file));
7195796c8dcSSimon Schubert }
7205796c8dcSSimon Schubert 
7215796c8dcSSimon Schubert bfd *
7225796c8dcSSimon Schubert bfd_generic_openr_next_archived_file (bfd *archive, bfd *last_file)
7235796c8dcSSimon Schubert {
7245796c8dcSSimon Schubert   file_ptr filestart;
7255796c8dcSSimon Schubert 
7265796c8dcSSimon Schubert   if (!last_file)
7275796c8dcSSimon Schubert     filestart = bfd_ardata (archive)->first_file_filepos;
7285796c8dcSSimon Schubert   else
7295796c8dcSSimon Schubert     {
7305796c8dcSSimon Schubert       unsigned int size = arelt_size (last_file);
731*a45ae5f8SJohn Marino 
7325796c8dcSSimon Schubert       filestart = last_file->proxy_origin;
7335796c8dcSSimon Schubert       if (! bfd_is_thin_archive (archive))
7345796c8dcSSimon Schubert         filestart += size;
7355796c8dcSSimon Schubert       if (archive->my_archive)
7365796c8dcSSimon Schubert 	filestart -= archive->origin;
7375796c8dcSSimon Schubert       /* Pad to an even boundary...
7385796c8dcSSimon Schubert 	 Note that last_file->origin can be odd in the case of
7395796c8dcSSimon Schubert 	 BSD-4.4-style element with a long odd size.  */
7405796c8dcSSimon Schubert       filestart += filestart % 2;
7415796c8dcSSimon Schubert     }
7425796c8dcSSimon Schubert 
7435796c8dcSSimon Schubert   return _bfd_get_elt_at_filepos (archive, filestart);
7445796c8dcSSimon Schubert }
7455796c8dcSSimon Schubert 
7465796c8dcSSimon Schubert const bfd_target *
7475796c8dcSSimon Schubert bfd_generic_archive_p (bfd *abfd)
7485796c8dcSSimon Schubert {
7495796c8dcSSimon Schubert   struct artdata *tdata_hold;
7505796c8dcSSimon Schubert   char armag[SARMAG + 1];
7515796c8dcSSimon Schubert   bfd_size_type amt;
7525796c8dcSSimon Schubert 
7535796c8dcSSimon Schubert   if (bfd_bread (armag, SARMAG, abfd) != SARMAG)
7545796c8dcSSimon Schubert     {
7555796c8dcSSimon Schubert       if (bfd_get_error () != bfd_error_system_call)
7565796c8dcSSimon Schubert 	bfd_set_error (bfd_error_wrong_format);
7575796c8dcSSimon Schubert       return NULL;
7585796c8dcSSimon Schubert     }
7595796c8dcSSimon Schubert 
7605796c8dcSSimon Schubert   bfd_is_thin_archive (abfd) = (strncmp (armag, ARMAGT, SARMAG) == 0);
7615796c8dcSSimon Schubert 
7625796c8dcSSimon Schubert   if (strncmp (armag, ARMAG, SARMAG) != 0
7635796c8dcSSimon Schubert       && strncmp (armag, ARMAGB, SARMAG) != 0
7645796c8dcSSimon Schubert       && ! bfd_is_thin_archive (abfd))
765*a45ae5f8SJohn Marino     return NULL;
7665796c8dcSSimon Schubert 
7675796c8dcSSimon Schubert   tdata_hold = bfd_ardata (abfd);
7685796c8dcSSimon Schubert 
7695796c8dcSSimon Schubert   amt = sizeof (struct artdata);
7705796c8dcSSimon Schubert   bfd_ardata (abfd) = (struct artdata *) bfd_zalloc (abfd, amt);
7715796c8dcSSimon Schubert   if (bfd_ardata (abfd) == NULL)
7725796c8dcSSimon Schubert     {
7735796c8dcSSimon Schubert       bfd_ardata (abfd) = tdata_hold;
7745796c8dcSSimon Schubert       return NULL;
7755796c8dcSSimon Schubert     }
7765796c8dcSSimon Schubert 
7775796c8dcSSimon Schubert   bfd_ardata (abfd)->first_file_filepos = SARMAG;
7785796c8dcSSimon Schubert   /* Cleared by bfd_zalloc above.
7795796c8dcSSimon Schubert      bfd_ardata (abfd)->cache = NULL;
7805796c8dcSSimon Schubert      bfd_ardata (abfd)->archive_head = NULL;
7815796c8dcSSimon Schubert      bfd_ardata (abfd)->symdefs = NULL;
7825796c8dcSSimon Schubert      bfd_ardata (abfd)->extended_names = NULL;
7835796c8dcSSimon Schubert      bfd_ardata (abfd)->extended_names_size = 0;
7845796c8dcSSimon Schubert      bfd_ardata (abfd)->tdata = NULL;  */
7855796c8dcSSimon Schubert 
7865796c8dcSSimon Schubert   if (!BFD_SEND (abfd, _bfd_slurp_armap, (abfd))
7875796c8dcSSimon Schubert       || !BFD_SEND (abfd, _bfd_slurp_extended_name_table, (abfd)))
7885796c8dcSSimon Schubert     {
7895796c8dcSSimon Schubert       if (bfd_get_error () != bfd_error_system_call)
7905796c8dcSSimon Schubert 	bfd_set_error (bfd_error_wrong_format);
7915796c8dcSSimon Schubert       bfd_release (abfd, bfd_ardata (abfd));
7925796c8dcSSimon Schubert       bfd_ardata (abfd) = tdata_hold;
7935796c8dcSSimon Schubert       return NULL;
7945796c8dcSSimon Schubert     }
7955796c8dcSSimon Schubert 
796*a45ae5f8SJohn Marino   if (abfd->target_defaulted && bfd_has_map (abfd))
7975796c8dcSSimon Schubert     {
7985796c8dcSSimon Schubert       bfd *first;
7995796c8dcSSimon Schubert 
8005796c8dcSSimon Schubert       /* This archive has a map, so we may presume that the contents
8015796c8dcSSimon Schubert 	 are object files.  Make sure that if the first file in the
8025796c8dcSSimon Schubert 	 archive can be recognized as an object file, it is for this
8035796c8dcSSimon Schubert 	 target.  If not, assume that this is the wrong format.  If
8045796c8dcSSimon Schubert 	 the first file is not an object file, somebody is doing
8055796c8dcSSimon Schubert 	 something weird, and we permit it so that ar -t will work.
8065796c8dcSSimon Schubert 
8075796c8dcSSimon Schubert 	 This is done because any normal format will recognize any
8085796c8dcSSimon Schubert 	 normal archive, regardless of the format of the object files.
8095796c8dcSSimon Schubert 	 We do accept an empty archive.  */
8105796c8dcSSimon Schubert 
8115796c8dcSSimon Schubert       first = bfd_openr_next_archived_file (abfd, NULL);
8125796c8dcSSimon Schubert       if (first != NULL)
8135796c8dcSSimon Schubert 	{
8145796c8dcSSimon Schubert 	  first->target_defaulted = FALSE;
8155796c8dcSSimon Schubert 	  if (bfd_check_format (first, bfd_object)
8165796c8dcSSimon Schubert 	      && first->xvec != abfd->xvec)
8175796c8dcSSimon Schubert 	    {
8185796c8dcSSimon Schubert 	      bfd_set_error (bfd_error_wrong_object_format);
8195796c8dcSSimon Schubert 	      bfd_ardata (abfd) = tdata_hold;
8205796c8dcSSimon Schubert 	      return NULL;
8215796c8dcSSimon Schubert 	    }
8225796c8dcSSimon Schubert 	  /* And we ought to close `first' here too.  */
8235796c8dcSSimon Schubert 	}
8245796c8dcSSimon Schubert     }
8255796c8dcSSimon Schubert 
8265796c8dcSSimon Schubert   return abfd->xvec;
8275796c8dcSSimon Schubert }
8285796c8dcSSimon Schubert 
8295796c8dcSSimon Schubert /* Some constants for a 32 bit BSD archive structure.  We do not
8305796c8dcSSimon Schubert    support 64 bit archives presently; so far as I know, none actually
8315796c8dcSSimon Schubert    exist.  Supporting them would require changing these constants, and
8325796c8dcSSimon Schubert    changing some H_GET_32 to H_GET_64.  */
8335796c8dcSSimon Schubert 
8345796c8dcSSimon Schubert /* The size of an external symdef structure.  */
8355796c8dcSSimon Schubert #define BSD_SYMDEF_SIZE 8
8365796c8dcSSimon Schubert 
8375796c8dcSSimon Schubert /* The offset from the start of a symdef structure to the file offset.  */
8385796c8dcSSimon Schubert #define BSD_SYMDEF_OFFSET_SIZE 4
8395796c8dcSSimon Schubert 
8405796c8dcSSimon Schubert /* The size of the symdef count.  */
8415796c8dcSSimon Schubert #define BSD_SYMDEF_COUNT_SIZE 4
8425796c8dcSSimon Schubert 
8435796c8dcSSimon Schubert /* The size of the string count.  */
8445796c8dcSSimon Schubert #define BSD_STRING_COUNT_SIZE 4
8455796c8dcSSimon Schubert 
8465796c8dcSSimon Schubert /* Read a BSD-style archive symbol table.  Returns FALSE on error,
8475796c8dcSSimon Schubert    TRUE otherwise.  */
8485796c8dcSSimon Schubert 
8495796c8dcSSimon Schubert static bfd_boolean
8505796c8dcSSimon Schubert do_slurp_bsd_armap (bfd *abfd)
8515796c8dcSSimon Schubert {
8525796c8dcSSimon Schubert   struct areltdata *mapdata;
8535796c8dcSSimon Schubert   unsigned int counter;
8545796c8dcSSimon Schubert   bfd_byte *raw_armap, *rbase;
8555796c8dcSSimon Schubert   struct artdata *ardata = bfd_ardata (abfd);
8565796c8dcSSimon Schubert   char *stringbase;
8575796c8dcSSimon Schubert   bfd_size_type parsed_size, amt;
8585796c8dcSSimon Schubert   carsym *set;
8595796c8dcSSimon Schubert 
8605796c8dcSSimon Schubert   mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd);
8615796c8dcSSimon Schubert   if (mapdata == NULL)
8625796c8dcSSimon Schubert     return FALSE;
8635796c8dcSSimon Schubert   parsed_size = mapdata->parsed_size;
8645796c8dcSSimon Schubert   bfd_release (abfd, mapdata);	/* Don't need it any more.  */
8655796c8dcSSimon Schubert 
8665796c8dcSSimon Schubert   raw_armap = (bfd_byte *) bfd_zalloc (abfd, parsed_size);
8675796c8dcSSimon Schubert   if (raw_armap == NULL)
8685796c8dcSSimon Schubert     return FALSE;
8695796c8dcSSimon Schubert 
8705796c8dcSSimon Schubert   if (bfd_bread (raw_armap, parsed_size, abfd) != parsed_size)
8715796c8dcSSimon Schubert     {
8725796c8dcSSimon Schubert       if (bfd_get_error () != bfd_error_system_call)
8735796c8dcSSimon Schubert 	bfd_set_error (bfd_error_malformed_archive);
8745796c8dcSSimon Schubert     byebye:
8755796c8dcSSimon Schubert       bfd_release (abfd, raw_armap);
8765796c8dcSSimon Schubert       return FALSE;
8775796c8dcSSimon Schubert     }
8785796c8dcSSimon Schubert 
8795796c8dcSSimon Schubert   ardata->symdef_count = H_GET_32 (abfd, raw_armap) / BSD_SYMDEF_SIZE;
8805796c8dcSSimon Schubert 
8815796c8dcSSimon Schubert   if (ardata->symdef_count * BSD_SYMDEF_SIZE >
8825796c8dcSSimon Schubert       parsed_size - BSD_SYMDEF_COUNT_SIZE)
8835796c8dcSSimon Schubert     {
8845796c8dcSSimon Schubert       /* Probably we're using the wrong byte ordering.  */
8855796c8dcSSimon Schubert       bfd_set_error (bfd_error_wrong_format);
8865796c8dcSSimon Schubert       goto byebye;
8875796c8dcSSimon Schubert     }
8885796c8dcSSimon Schubert 
8895796c8dcSSimon Schubert   ardata->cache = 0;
8905796c8dcSSimon Schubert   rbase = raw_armap + BSD_SYMDEF_COUNT_SIZE;
8915796c8dcSSimon Schubert   stringbase = ((char *) rbase
8925796c8dcSSimon Schubert 		+ ardata->symdef_count * BSD_SYMDEF_SIZE
8935796c8dcSSimon Schubert 		+ BSD_STRING_COUNT_SIZE);
8945796c8dcSSimon Schubert   amt = ardata->symdef_count * sizeof (carsym);
8955796c8dcSSimon Schubert   ardata->symdefs = (struct carsym *) bfd_alloc (abfd, amt);
8965796c8dcSSimon Schubert   if (!ardata->symdefs)
8975796c8dcSSimon Schubert     return FALSE;
8985796c8dcSSimon Schubert 
8995796c8dcSSimon Schubert   for (counter = 0, set = ardata->symdefs;
9005796c8dcSSimon Schubert        counter < ardata->symdef_count;
9015796c8dcSSimon Schubert        counter++, set++, rbase += BSD_SYMDEF_SIZE)
9025796c8dcSSimon Schubert     {
9035796c8dcSSimon Schubert       set->name = H_GET_32 (abfd, rbase) + stringbase;
9045796c8dcSSimon Schubert       set->file_offset = H_GET_32 (abfd, rbase + BSD_SYMDEF_OFFSET_SIZE);
9055796c8dcSSimon Schubert     }
9065796c8dcSSimon Schubert 
9075796c8dcSSimon Schubert   ardata->first_file_filepos = bfd_tell (abfd);
9085796c8dcSSimon Schubert   /* Pad to an even boundary if you have to.  */
9095796c8dcSSimon Schubert   ardata->first_file_filepos += (ardata->first_file_filepos) % 2;
9105796c8dcSSimon Schubert   /* FIXME, we should provide some way to free raw_ardata when
9115796c8dcSSimon Schubert      we are done using the strings from it.  For now, it seems
9125796c8dcSSimon Schubert      to be allocated on an objalloc anyway...  */
9135796c8dcSSimon Schubert   bfd_has_map (abfd) = TRUE;
9145796c8dcSSimon Schubert   return TRUE;
9155796c8dcSSimon Schubert }
9165796c8dcSSimon Schubert 
9175796c8dcSSimon Schubert /* Read a COFF archive symbol table.  Returns FALSE on error, TRUE
9185796c8dcSSimon Schubert    otherwise.  */
9195796c8dcSSimon Schubert 
9205796c8dcSSimon Schubert static bfd_boolean
9215796c8dcSSimon Schubert do_slurp_coff_armap (bfd *abfd)
9225796c8dcSSimon Schubert {
9235796c8dcSSimon Schubert   struct areltdata *mapdata;
9245796c8dcSSimon Schubert   int *raw_armap, *rawptr;
9255796c8dcSSimon Schubert   struct artdata *ardata = bfd_ardata (abfd);
9265796c8dcSSimon Schubert   char *stringbase;
9275796c8dcSSimon Schubert   bfd_size_type stringsize;
9285796c8dcSSimon Schubert   unsigned int parsed_size;
9295796c8dcSSimon Schubert   carsym *carsyms;
9305796c8dcSSimon Schubert   bfd_size_type nsymz;		/* Number of symbols in armap.  */
9315796c8dcSSimon Schubert   bfd_vma (*swap) (const void *);
9325796c8dcSSimon Schubert   char int_buf[sizeof (long)];
9335796c8dcSSimon Schubert   bfd_size_type carsym_size, ptrsize;
9345796c8dcSSimon Schubert   unsigned int i;
9355796c8dcSSimon Schubert 
9365796c8dcSSimon Schubert   mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd);
9375796c8dcSSimon Schubert   if (mapdata == NULL)
9385796c8dcSSimon Schubert     return FALSE;
9395796c8dcSSimon Schubert   parsed_size = mapdata->parsed_size;
9405796c8dcSSimon Schubert   bfd_release (abfd, mapdata);	/* Don't need it any more.  */
9415796c8dcSSimon Schubert 
9425796c8dcSSimon Schubert   if (bfd_bread (int_buf, 4, abfd) != 4)
9435796c8dcSSimon Schubert     {
9445796c8dcSSimon Schubert       if (bfd_get_error () != bfd_error_system_call)
9455796c8dcSSimon Schubert 	bfd_set_error (bfd_error_malformed_archive);
9465796c8dcSSimon Schubert       return FALSE;
9475796c8dcSSimon Schubert     }
9485796c8dcSSimon Schubert   /* It seems that all numeric information in a coff archive is always
9495796c8dcSSimon Schubert      in big endian format, nomatter the host or target.  */
9505796c8dcSSimon Schubert   swap = bfd_getb32;
9515796c8dcSSimon Schubert   nsymz = bfd_getb32 (int_buf);
9525796c8dcSSimon Schubert   stringsize = parsed_size - (4 * nsymz) - 4;
9535796c8dcSSimon Schubert 
9545796c8dcSSimon Schubert   /* ... except that some archive formats are broken, and it may be our
9555796c8dcSSimon Schubert      fault - the i960 little endian coff sometimes has big and sometimes
9565796c8dcSSimon Schubert      little, because our tools changed.  Here's a horrible hack to clean
9575796c8dcSSimon Schubert      up the crap.  */
9585796c8dcSSimon Schubert 
9595796c8dcSSimon Schubert   if (stringsize > 0xfffff
9605796c8dcSSimon Schubert       && bfd_get_arch (abfd) == bfd_arch_i960
9615796c8dcSSimon Schubert       && bfd_get_flavour (abfd) == bfd_target_coff_flavour)
9625796c8dcSSimon Schubert     {
9635796c8dcSSimon Schubert       /* This looks dangerous, let's do it the other way around.  */
9645796c8dcSSimon Schubert       nsymz = bfd_getl32 (int_buf);
9655796c8dcSSimon Schubert       stringsize = parsed_size - (4 * nsymz) - 4;
9665796c8dcSSimon Schubert       swap = bfd_getl32;
9675796c8dcSSimon Schubert     }
9685796c8dcSSimon Schubert 
9695796c8dcSSimon Schubert   /* The coff armap must be read sequentially.  So we construct a
9705796c8dcSSimon Schubert      bsd-style one in core all at once, for simplicity.  */
9715796c8dcSSimon Schubert 
9725796c8dcSSimon Schubert   if (nsymz > ~ (bfd_size_type) 0 / sizeof (carsym))
9735796c8dcSSimon Schubert     return FALSE;
9745796c8dcSSimon Schubert 
9755796c8dcSSimon Schubert   carsym_size = (nsymz * sizeof (carsym));
9765796c8dcSSimon Schubert   ptrsize = (4 * nsymz);
9775796c8dcSSimon Schubert 
9785796c8dcSSimon Schubert   if (carsym_size + stringsize + 1 <= carsym_size)
9795796c8dcSSimon Schubert     return FALSE;
9805796c8dcSSimon Schubert 
9815796c8dcSSimon Schubert   ardata->symdefs = (struct carsym *) bfd_zalloc (abfd,
9825796c8dcSSimon Schubert                                                   carsym_size + stringsize + 1);
9835796c8dcSSimon Schubert   if (ardata->symdefs == NULL)
9845796c8dcSSimon Schubert     return FALSE;
9855796c8dcSSimon Schubert   carsyms = ardata->symdefs;
9865796c8dcSSimon Schubert   stringbase = ((char *) ardata->symdefs) + carsym_size;
9875796c8dcSSimon Schubert 
9885796c8dcSSimon Schubert   /* Allocate and read in the raw offsets.  */
9895796c8dcSSimon Schubert   raw_armap = (int *) bfd_alloc (abfd, ptrsize);
9905796c8dcSSimon Schubert   if (raw_armap == NULL)
9915796c8dcSSimon Schubert     goto release_symdefs;
9925796c8dcSSimon Schubert   if (bfd_bread (raw_armap, ptrsize, abfd) != ptrsize
9935796c8dcSSimon Schubert       || (bfd_bread (stringbase, stringsize, abfd) != stringsize))
9945796c8dcSSimon Schubert     {
9955796c8dcSSimon Schubert       if (bfd_get_error () != bfd_error_system_call)
9965796c8dcSSimon Schubert 	bfd_set_error (bfd_error_malformed_archive);
9975796c8dcSSimon Schubert       goto release_raw_armap;
9985796c8dcSSimon Schubert     }
9995796c8dcSSimon Schubert 
10005796c8dcSSimon Schubert   /* OK, build the carsyms.  */
10015796c8dcSSimon Schubert   for (i = 0; i < nsymz; i++)
10025796c8dcSSimon Schubert     {
10035796c8dcSSimon Schubert       rawptr = raw_armap + i;
10045796c8dcSSimon Schubert       carsyms->file_offset = swap ((bfd_byte *) rawptr);
10055796c8dcSSimon Schubert       carsyms->name = stringbase;
10065796c8dcSSimon Schubert       stringbase += strlen (stringbase) + 1;
10075796c8dcSSimon Schubert       carsyms++;
10085796c8dcSSimon Schubert     }
10095796c8dcSSimon Schubert   *stringbase = 0;
10105796c8dcSSimon Schubert 
10115796c8dcSSimon Schubert   ardata->symdef_count = nsymz;
10125796c8dcSSimon Schubert   ardata->first_file_filepos = bfd_tell (abfd);
10135796c8dcSSimon Schubert   /* Pad to an even boundary if you have to.  */
10145796c8dcSSimon Schubert   ardata->first_file_filepos += (ardata->first_file_filepos) % 2;
10155796c8dcSSimon Schubert 
10165796c8dcSSimon Schubert   bfd_has_map (abfd) = TRUE;
10175796c8dcSSimon Schubert   bfd_release (abfd, raw_armap);
10185796c8dcSSimon Schubert 
10195796c8dcSSimon Schubert   /* Check for a second archive header (as used by PE).  */
10205796c8dcSSimon Schubert   {
10215796c8dcSSimon Schubert     struct areltdata *tmp;
10225796c8dcSSimon Schubert 
10235796c8dcSSimon Schubert     bfd_seek (abfd, ardata->first_file_filepos, SEEK_SET);
10245796c8dcSSimon Schubert     tmp = (struct areltdata *) _bfd_read_ar_hdr (abfd);
10255796c8dcSSimon Schubert     if (tmp != NULL)
10265796c8dcSSimon Schubert       {
10275796c8dcSSimon Schubert 	if (tmp->arch_header[0] == '/'
10285796c8dcSSimon Schubert 	    && tmp->arch_header[1] == ' ')
10295796c8dcSSimon Schubert 	  {
10305796c8dcSSimon Schubert 	    ardata->first_file_filepos +=
10315796c8dcSSimon Schubert 	      (tmp->parsed_size + sizeof (struct ar_hdr) + 1) & ~(unsigned) 1;
10325796c8dcSSimon Schubert 	  }
10335796c8dcSSimon Schubert 	bfd_release (abfd, tmp);
10345796c8dcSSimon Schubert       }
10355796c8dcSSimon Schubert   }
10365796c8dcSSimon Schubert 
10375796c8dcSSimon Schubert   return TRUE;
10385796c8dcSSimon Schubert 
10395796c8dcSSimon Schubert release_raw_armap:
10405796c8dcSSimon Schubert   bfd_release (abfd, raw_armap);
10415796c8dcSSimon Schubert release_symdefs:
10425796c8dcSSimon Schubert   bfd_release (abfd, (ardata)->symdefs);
10435796c8dcSSimon Schubert   return FALSE;
10445796c8dcSSimon Schubert }
10455796c8dcSSimon Schubert 
10465796c8dcSSimon Schubert /* This routine can handle either coff-style or bsd-style armaps
10475796c8dcSSimon Schubert    (archive symbol table).  Returns FALSE on error, TRUE otherwise */
10485796c8dcSSimon Schubert 
10495796c8dcSSimon Schubert bfd_boolean
10505796c8dcSSimon Schubert bfd_slurp_armap (bfd *abfd)
10515796c8dcSSimon Schubert {
10525796c8dcSSimon Schubert   char nextname[17];
10535796c8dcSSimon Schubert   int i = bfd_bread (nextname, 16, abfd);
10545796c8dcSSimon Schubert 
10555796c8dcSSimon Schubert   if (i == 0)
10565796c8dcSSimon Schubert     return TRUE;
10575796c8dcSSimon Schubert   if (i != 16)
10585796c8dcSSimon Schubert     return FALSE;
10595796c8dcSSimon Schubert 
10605796c8dcSSimon Schubert   if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0)
10615796c8dcSSimon Schubert     return FALSE;
10625796c8dcSSimon Schubert 
10635796c8dcSSimon Schubert   if (CONST_STRNEQ (nextname, "__.SYMDEF       ")
10645796c8dcSSimon Schubert       || CONST_STRNEQ (nextname, "__.SYMDEF/      ")) /* Old Linux archives.  */
10655796c8dcSSimon Schubert     return do_slurp_bsd_armap (abfd);
10665796c8dcSSimon Schubert   else if (CONST_STRNEQ (nextname, "/               "))
10675796c8dcSSimon Schubert     return do_slurp_coff_armap (abfd);
10685796c8dcSSimon Schubert   else if (CONST_STRNEQ (nextname, "/SYM64/         "))
10695796c8dcSSimon Schubert     {
10705796c8dcSSimon Schubert       /* 64bit ELF (Irix 6) archive.  */
10715796c8dcSSimon Schubert #ifdef BFD64
10725796c8dcSSimon Schubert       extern bfd_boolean bfd_elf64_archive_slurp_armap (bfd *);
10735796c8dcSSimon Schubert       return bfd_elf64_archive_slurp_armap (abfd);
10745796c8dcSSimon Schubert #else
10755796c8dcSSimon Schubert       bfd_set_error (bfd_error_wrong_format);
10765796c8dcSSimon Schubert       return FALSE;
10775796c8dcSSimon Schubert #endif
10785796c8dcSSimon Schubert     }
1079cf7f2e2dSJohn Marino   else if (CONST_STRNEQ (nextname, "#1/20           "))
1080cf7f2e2dSJohn Marino     {
1081cf7f2e2dSJohn Marino       /* Mach-O has a special name for armap when the map is sorted by name.
1082cf7f2e2dSJohn Marino          However because this name has a space it is slightly more difficult
1083cf7f2e2dSJohn Marino          to check it.  */
1084cf7f2e2dSJohn Marino       struct ar_hdr hdr;
1085cf7f2e2dSJohn Marino       char extname[21];
1086cf7f2e2dSJohn Marino 
1087cf7f2e2dSJohn Marino       if (bfd_bread (&hdr, sizeof (hdr), abfd) != sizeof (hdr))
1088cf7f2e2dSJohn Marino         return FALSE;
1089cf7f2e2dSJohn Marino       /* Read the extended name.  We know its length.  */
1090cf7f2e2dSJohn Marino       if (bfd_bread (extname, 20, abfd) != 20)
1091cf7f2e2dSJohn Marino         return FALSE;
1092cf7f2e2dSJohn Marino       if (bfd_seek (abfd, (file_ptr) -(sizeof (hdr) + 20), SEEK_CUR) != 0)
1093cf7f2e2dSJohn Marino         return FALSE;
1094cf7f2e2dSJohn Marino       if (CONST_STRNEQ (extname, "__.SYMDEF SORTED")
1095cf7f2e2dSJohn Marino           || CONST_STRNEQ (extname, "__.SYMDEF"))
1096cf7f2e2dSJohn Marino         return do_slurp_bsd_armap (abfd);
1097cf7f2e2dSJohn Marino     }
10985796c8dcSSimon Schubert 
10995796c8dcSSimon Schubert   bfd_has_map (abfd) = FALSE;
11005796c8dcSSimon Schubert   return TRUE;
11015796c8dcSSimon Schubert }
11025796c8dcSSimon Schubert 
11035796c8dcSSimon Schubert /* Returns FALSE on error, TRUE otherwise.  */
11045796c8dcSSimon Schubert /* Flavor 2 of a bsd armap, similar to bfd_slurp_bsd_armap except the
11055796c8dcSSimon Schubert    header is in a slightly different order and the map name is '/'.
11065796c8dcSSimon Schubert    This flavour is used by hp300hpux.  */
11075796c8dcSSimon Schubert 
11085796c8dcSSimon Schubert #define HPUX_SYMDEF_COUNT_SIZE 2
11095796c8dcSSimon Schubert 
11105796c8dcSSimon Schubert bfd_boolean
11115796c8dcSSimon Schubert bfd_slurp_bsd_armap_f2 (bfd *abfd)
11125796c8dcSSimon Schubert {
11135796c8dcSSimon Schubert   struct areltdata *mapdata;
11145796c8dcSSimon Schubert   char nextname[17];
11155796c8dcSSimon Schubert   unsigned int counter;
11165796c8dcSSimon Schubert   bfd_byte *raw_armap, *rbase;
11175796c8dcSSimon Schubert   struct artdata *ardata = bfd_ardata (abfd);
11185796c8dcSSimon Schubert   char *stringbase;
11195796c8dcSSimon Schubert   unsigned int stringsize;
1120c50c785cSJohn Marino   unsigned int left;
11215796c8dcSSimon Schubert   bfd_size_type amt;
11225796c8dcSSimon Schubert   carsym *set;
11235796c8dcSSimon Schubert   int i = bfd_bread (nextname, 16, abfd);
11245796c8dcSSimon Schubert 
11255796c8dcSSimon Schubert   if (i == 0)
11265796c8dcSSimon Schubert     return TRUE;
11275796c8dcSSimon Schubert   if (i != 16)
11285796c8dcSSimon Schubert     return FALSE;
11295796c8dcSSimon Schubert 
11305796c8dcSSimon Schubert   /* The archive has at least 16 bytes in it.  */
11315796c8dcSSimon Schubert   if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0)
11325796c8dcSSimon Schubert     return FALSE;
11335796c8dcSSimon Schubert 
11345796c8dcSSimon Schubert   if (CONST_STRNEQ (nextname, "__.SYMDEF       ")
11355796c8dcSSimon Schubert       || CONST_STRNEQ (nextname, "__.SYMDEF/      ")) /* Old Linux archives.  */
11365796c8dcSSimon Schubert     return do_slurp_bsd_armap (abfd);
11375796c8dcSSimon Schubert 
11385796c8dcSSimon Schubert   if (! CONST_STRNEQ (nextname, "/               "))
11395796c8dcSSimon Schubert     {
11405796c8dcSSimon Schubert       bfd_has_map (abfd) = FALSE;
11415796c8dcSSimon Schubert       return TRUE;
11425796c8dcSSimon Schubert     }
11435796c8dcSSimon Schubert 
11445796c8dcSSimon Schubert   mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd);
11455796c8dcSSimon Schubert   if (mapdata == NULL)
11465796c8dcSSimon Schubert     return FALSE;
11475796c8dcSSimon Schubert 
1148c50c785cSJohn Marino   if (mapdata->parsed_size < HPUX_SYMDEF_COUNT_SIZE + BSD_STRING_COUNT_SIZE)
11495796c8dcSSimon Schubert     {
1150c50c785cSJohn Marino     wrong_format:
1151c50c785cSJohn Marino       bfd_set_error (bfd_error_wrong_format);
11525796c8dcSSimon Schubert     byebye:
11535796c8dcSSimon Schubert       bfd_release (abfd, mapdata);
11545796c8dcSSimon Schubert       return FALSE;
11555796c8dcSSimon Schubert     }
1156c50c785cSJohn Marino   left = mapdata->parsed_size - HPUX_SYMDEF_COUNT_SIZE - BSD_STRING_COUNT_SIZE;
1157c50c785cSJohn Marino 
1158c50c785cSJohn Marino   amt = mapdata->parsed_size;
1159c50c785cSJohn Marino   raw_armap = (bfd_byte *) bfd_zalloc (abfd, amt);
1160c50c785cSJohn Marino   if (raw_armap == NULL)
1161c50c785cSJohn Marino     goto byebye;
11625796c8dcSSimon Schubert 
11635796c8dcSSimon Schubert   if (bfd_bread (raw_armap, amt, abfd) != amt)
11645796c8dcSSimon Schubert     {
11655796c8dcSSimon Schubert       if (bfd_get_error () != bfd_error_system_call)
11665796c8dcSSimon Schubert 	bfd_set_error (bfd_error_malformed_archive);
11675796c8dcSSimon Schubert       goto byebye;
11685796c8dcSSimon Schubert     }
11695796c8dcSSimon Schubert 
11705796c8dcSSimon Schubert   ardata->symdef_count = H_GET_16 (abfd, raw_armap);
11715796c8dcSSimon Schubert 
11725796c8dcSSimon Schubert   ardata->cache = 0;
11735796c8dcSSimon Schubert 
11745796c8dcSSimon Schubert   stringsize = H_GET_32 (abfd, raw_armap + HPUX_SYMDEF_COUNT_SIZE);
1175c50c785cSJohn Marino   if (stringsize > left)
1176c50c785cSJohn Marino     goto wrong_format;
1177c50c785cSJohn Marino   left -= stringsize;
1178c50c785cSJohn Marino 
11795796c8dcSSimon Schubert   /* Skip sym count and string sz.  */
11805796c8dcSSimon Schubert   stringbase = ((char *) raw_armap
11815796c8dcSSimon Schubert 		+ HPUX_SYMDEF_COUNT_SIZE
11825796c8dcSSimon Schubert 		+ BSD_STRING_COUNT_SIZE);
11835796c8dcSSimon Schubert   rbase = (bfd_byte *) stringbase + stringsize;
11845796c8dcSSimon Schubert   amt = ardata->symdef_count * BSD_SYMDEF_SIZE;
1185c50c785cSJohn Marino   if (amt > left)
1186c50c785cSJohn Marino     goto wrong_format;
1187c50c785cSJohn Marino 
11885796c8dcSSimon Schubert   ardata->symdefs = (struct carsym *) bfd_alloc (abfd, amt);
11895796c8dcSSimon Schubert   if (!ardata->symdefs)
11905796c8dcSSimon Schubert     return FALSE;
11915796c8dcSSimon Schubert 
11925796c8dcSSimon Schubert   for (counter = 0, set = ardata->symdefs;
11935796c8dcSSimon Schubert        counter < ardata->symdef_count;
11945796c8dcSSimon Schubert        counter++, set++, rbase += BSD_SYMDEF_SIZE)
11955796c8dcSSimon Schubert     {
11965796c8dcSSimon Schubert       set->name = H_GET_32 (abfd, rbase) + stringbase;
11975796c8dcSSimon Schubert       set->file_offset = H_GET_32 (abfd, rbase + BSD_SYMDEF_OFFSET_SIZE);
11985796c8dcSSimon Schubert     }
11995796c8dcSSimon Schubert 
12005796c8dcSSimon Schubert   ardata->first_file_filepos = bfd_tell (abfd);
12015796c8dcSSimon Schubert   /* Pad to an even boundary if you have to.  */
12025796c8dcSSimon Schubert   ardata->first_file_filepos += (ardata->first_file_filepos) % 2;
12035796c8dcSSimon Schubert   /* FIXME, we should provide some way to free raw_ardata when
12045796c8dcSSimon Schubert      we are done using the strings from it.  For now, it seems
12055796c8dcSSimon Schubert      to be allocated on an objalloc anyway...  */
12065796c8dcSSimon Schubert   bfd_has_map (abfd) = TRUE;
12075796c8dcSSimon Schubert   return TRUE;
12085796c8dcSSimon Schubert }
12095796c8dcSSimon Schubert 
12105796c8dcSSimon Schubert /** Extended name table.
12115796c8dcSSimon Schubert 
12125796c8dcSSimon Schubert   Normally archives support only 14-character filenames.
12135796c8dcSSimon Schubert 
12145796c8dcSSimon Schubert   Intel has extended the format: longer names are stored in a special
12155796c8dcSSimon Schubert   element (the first in the archive, or second if there is an armap);
12165796c8dcSSimon Schubert   the name in the ar_hdr is replaced by <space><index into filename
12175796c8dcSSimon Schubert   element>.  Index is the P.R. of an int (decimal).  Data General have
12185796c8dcSSimon Schubert   extended the format by using the prefix // for the special element.  */
12195796c8dcSSimon Schubert 
12205796c8dcSSimon Schubert /* Returns FALSE on error, TRUE otherwise.  */
12215796c8dcSSimon Schubert 
12225796c8dcSSimon Schubert bfd_boolean
12235796c8dcSSimon Schubert _bfd_slurp_extended_name_table (bfd *abfd)
12245796c8dcSSimon Schubert {
12255796c8dcSSimon Schubert   char nextname[17];
12265796c8dcSSimon Schubert   struct areltdata *namedata;
12275796c8dcSSimon Schubert   bfd_size_type amt;
12285796c8dcSSimon Schubert 
12295796c8dcSSimon Schubert   /* FIXME:  Formatting sucks here, and in case of failure of BFD_READ,
12305796c8dcSSimon Schubert      we probably don't want to return TRUE.  */
1231c50c785cSJohn Marino   if (bfd_seek (abfd, bfd_ardata (abfd)->first_file_filepos, SEEK_SET) != 0)
1232c50c785cSJohn Marino     return FALSE;
1233c50c785cSJohn Marino 
12345796c8dcSSimon Schubert   if (bfd_bread (nextname, 16, abfd) == 16)
12355796c8dcSSimon Schubert     {
12365796c8dcSSimon Schubert       if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0)
12375796c8dcSSimon Schubert 	return FALSE;
12385796c8dcSSimon Schubert 
12395796c8dcSSimon Schubert       if (! CONST_STRNEQ (nextname, "ARFILENAMES/    ")
12405796c8dcSSimon Schubert 	  && ! CONST_STRNEQ (nextname, "//              "))
12415796c8dcSSimon Schubert 	{
12425796c8dcSSimon Schubert 	  bfd_ardata (abfd)->extended_names = NULL;
12435796c8dcSSimon Schubert 	  bfd_ardata (abfd)->extended_names_size = 0;
12445796c8dcSSimon Schubert 	  return TRUE;
12455796c8dcSSimon Schubert 	}
12465796c8dcSSimon Schubert 
12475796c8dcSSimon Schubert       namedata = (struct areltdata *) _bfd_read_ar_hdr (abfd);
12485796c8dcSSimon Schubert       if (namedata == NULL)
12495796c8dcSSimon Schubert 	return FALSE;
12505796c8dcSSimon Schubert 
12515796c8dcSSimon Schubert       amt = namedata->parsed_size;
12525796c8dcSSimon Schubert       if (amt + 1 == 0)
12535796c8dcSSimon Schubert         goto byebye;
12545796c8dcSSimon Schubert 
12555796c8dcSSimon Schubert       bfd_ardata (abfd)->extended_names_size = amt;
12565796c8dcSSimon Schubert       bfd_ardata (abfd)->extended_names = (char *) bfd_zalloc (abfd, amt + 1);
12575796c8dcSSimon Schubert       if (bfd_ardata (abfd)->extended_names == NULL)
12585796c8dcSSimon Schubert 	{
12595796c8dcSSimon Schubert 	byebye:
12605796c8dcSSimon Schubert 	  bfd_release (abfd, namedata);
12615796c8dcSSimon Schubert 	  return FALSE;
12625796c8dcSSimon Schubert 	}
12635796c8dcSSimon Schubert 
12645796c8dcSSimon Schubert       if (bfd_bread (bfd_ardata (abfd)->extended_names, amt, abfd) != amt)
12655796c8dcSSimon Schubert 	{
12665796c8dcSSimon Schubert 	  if (bfd_get_error () != bfd_error_system_call)
12675796c8dcSSimon Schubert 	    bfd_set_error (bfd_error_malformed_archive);
12685796c8dcSSimon Schubert 	  bfd_release (abfd, (bfd_ardata (abfd)->extended_names));
12695796c8dcSSimon Schubert 	  bfd_ardata (abfd)->extended_names = NULL;
12705796c8dcSSimon Schubert 	  goto byebye;
12715796c8dcSSimon Schubert 	}
12725796c8dcSSimon Schubert 
12735796c8dcSSimon Schubert       /* Since the archive is supposed to be printable if it contains
12745796c8dcSSimon Schubert 	 text, the entries in the list are newline-padded, not null
12755796c8dcSSimon Schubert 	 padded. In SVR4-style archives, the names also have a
12765796c8dcSSimon Schubert 	 trailing '/'.  DOS/NT created archive often have \ in them
12775796c8dcSSimon Schubert 	 We'll fix all problems here..  */
12785796c8dcSSimon Schubert       {
12795796c8dcSSimon Schubert         char *ext_names = bfd_ardata (abfd)->extended_names;
12805796c8dcSSimon Schubert 	char *temp = ext_names;
12815796c8dcSSimon Schubert 	char *limit = temp + namedata->parsed_size;
12825796c8dcSSimon Schubert 	for (; temp < limit; ++temp)
12835796c8dcSSimon Schubert 	  {
12845796c8dcSSimon Schubert 	    if (*temp == ARFMAG[1])
12855796c8dcSSimon Schubert 	      temp[temp > ext_names && temp[-1] == '/' ? -1 : 0] = '\0';
12865796c8dcSSimon Schubert 	    if (*temp == '\\')
12875796c8dcSSimon Schubert 	      *temp = '/';
12885796c8dcSSimon Schubert 	  }
12895796c8dcSSimon Schubert 	*limit = '\0';
12905796c8dcSSimon Schubert       }
12915796c8dcSSimon Schubert 
12925796c8dcSSimon Schubert       /* Pad to an even boundary if you have to.  */
12935796c8dcSSimon Schubert       bfd_ardata (abfd)->first_file_filepos = bfd_tell (abfd);
12945796c8dcSSimon Schubert       bfd_ardata (abfd)->first_file_filepos +=
12955796c8dcSSimon Schubert 	(bfd_ardata (abfd)->first_file_filepos) % 2;
12965796c8dcSSimon Schubert 
12975796c8dcSSimon Schubert       /* FIXME, we can't release namedata here because it was allocated
12985796c8dcSSimon Schubert 	 below extended_names on the objalloc...  */
12995796c8dcSSimon Schubert     }
13005796c8dcSSimon Schubert   return TRUE;
13015796c8dcSSimon Schubert }
13025796c8dcSSimon Schubert 
13035796c8dcSSimon Schubert #ifdef VMS
13045796c8dcSSimon Schubert 
13055796c8dcSSimon Schubert /* Return a copy of the stuff in the filename between any :]> and a
13065796c8dcSSimon Schubert    semicolon.  */
13075796c8dcSSimon Schubert 
13085796c8dcSSimon Schubert static const char *
13095796c8dcSSimon Schubert normalize (bfd *abfd, const char *file)
13105796c8dcSSimon Schubert {
13115796c8dcSSimon Schubert   const char *first;
13125796c8dcSSimon Schubert   const char *last;
13135796c8dcSSimon Schubert   char *copy;
13145796c8dcSSimon Schubert 
13155796c8dcSSimon Schubert   first = file + strlen (file) - 1;
13165796c8dcSSimon Schubert   last = first + 1;
13175796c8dcSSimon Schubert 
13185796c8dcSSimon Schubert   while (first != file)
13195796c8dcSSimon Schubert     {
13205796c8dcSSimon Schubert       if (*first == ';')
13215796c8dcSSimon Schubert 	last = first;
13225796c8dcSSimon Schubert       if (*first == ':' || *first == ']' || *first == '>')
13235796c8dcSSimon Schubert 	{
13245796c8dcSSimon Schubert 	  first++;
13255796c8dcSSimon Schubert 	  break;
13265796c8dcSSimon Schubert 	}
13275796c8dcSSimon Schubert       first--;
13285796c8dcSSimon Schubert     }
13295796c8dcSSimon Schubert 
13305796c8dcSSimon Schubert   copy = bfd_alloc (abfd, last - first + 1);
13315796c8dcSSimon Schubert   if (copy == NULL)
13325796c8dcSSimon Schubert     return NULL;
13335796c8dcSSimon Schubert 
13345796c8dcSSimon Schubert   memcpy (copy, first, last - first);
13355796c8dcSSimon Schubert   copy[last - first] = 0;
13365796c8dcSSimon Schubert 
13375796c8dcSSimon Schubert   return copy;
13385796c8dcSSimon Schubert }
13395796c8dcSSimon Schubert 
13405796c8dcSSimon Schubert #else
13415796c8dcSSimon Schubert static const char *
13425796c8dcSSimon Schubert normalize (bfd *abfd ATTRIBUTE_UNUSED, const char *file)
13435796c8dcSSimon Schubert {
1344cf7f2e2dSJohn Marino   return lbasename (file);
13455796c8dcSSimon Schubert }
13465796c8dcSSimon Schubert #endif
13475796c8dcSSimon Schubert 
1348*a45ae5f8SJohn Marino /* Adjust a relative path name based on the reference path.
1349*a45ae5f8SJohn Marino    For example:
1350*a45ae5f8SJohn Marino 
1351*a45ae5f8SJohn Marino      Relative path  Reference path  Result
1352*a45ae5f8SJohn Marino      -------------  --------------  ------
1353*a45ae5f8SJohn Marino      bar.o          lib.a           bar.o
1354*a45ae5f8SJohn Marino      foo/bar.o      lib.a           foo/bar.o
1355*a45ae5f8SJohn Marino      bar.o          foo/lib.a       ../bar.o
1356*a45ae5f8SJohn Marino      foo/bar.o      baz/lib.a       ../foo/bar.o
1357*a45ae5f8SJohn Marino      bar.o          ../lib.a        <parent of current dir>/bar.o
1358*a45ae5f8SJohn Marino    ; ../bar.o       ../lib.a        bar.o
1359*a45ae5f8SJohn Marino    ; ../bar.o       lib.a           ../bar.o
1360*a45ae5f8SJohn Marino      foo/bar.o      ../lib.a        <parent of current dir>/foo/bar.o
1361*a45ae5f8SJohn Marino      bar.o          ../../lib.a     <grandparent>/<parent>/bar.o
1362*a45ae5f8SJohn Marino      bar.o          foo/baz/lib.a   ../../bar.o
1363*a45ae5f8SJohn Marino 
1364*a45ae5f8SJohn Marino    Note - the semicolons above are there to prevent the BFD chew
1365*a45ae5f8SJohn Marino    utility from interpreting those lines as prototypes to put into
1366*a45ae5f8SJohn Marino    the autogenerated bfd.h header...
1367*a45ae5f8SJohn Marino 
1368*a45ae5f8SJohn Marino    Note - the string is returned in a static buffer.  */
13695796c8dcSSimon Schubert 
13705796c8dcSSimon Schubert static const char *
13715796c8dcSSimon Schubert adjust_relative_path (const char * path, const char * ref_path)
13725796c8dcSSimon Schubert {
13735796c8dcSSimon Schubert   static char *pathbuf = NULL;
1374*a45ae5f8SJohn Marino   static unsigned int pathbuf_len = 0;
1375*a45ae5f8SJohn Marino   const char *pathp;
1376*a45ae5f8SJohn Marino   const char *refp;
1377*a45ae5f8SJohn Marino   char * lpath;
1378*a45ae5f8SJohn Marino   char * rpath;
1379*a45ae5f8SJohn Marino   unsigned int len;
1380*a45ae5f8SJohn Marino   unsigned int dir_up = 0;
1381*a45ae5f8SJohn Marino   unsigned int dir_down = 0;
13825796c8dcSSimon Schubert   char *newp;
1383*a45ae5f8SJohn Marino   char * pwd = getpwd ();
1384*a45ae5f8SJohn Marino   const char * down;
1385*a45ae5f8SJohn Marino 
1386*a45ae5f8SJohn Marino   /* Remove symlinks, '.' and '..' from the paths, if possible.  */
1387*a45ae5f8SJohn Marino   lpath = lrealpath (path);
1388*a45ae5f8SJohn Marino   pathp = lpath == NULL ? path : lpath;
1389*a45ae5f8SJohn Marino 
1390*a45ae5f8SJohn Marino   rpath = lrealpath (ref_path);
1391*a45ae5f8SJohn Marino   refp = rpath == NULL ? ref_path : rpath;
13925796c8dcSSimon Schubert 
13935796c8dcSSimon Schubert   /* Remove common leading path elements.  */
13945796c8dcSSimon Schubert   for (;;)
13955796c8dcSSimon Schubert     {
13965796c8dcSSimon Schubert       const char *e1 = pathp;
13975796c8dcSSimon Schubert       const char *e2 = refp;
13985796c8dcSSimon Schubert 
13995796c8dcSSimon Schubert       while (*e1 && ! IS_DIR_SEPARATOR (*e1))
14005796c8dcSSimon Schubert 	++e1;
14015796c8dcSSimon Schubert       while (*e2 && ! IS_DIR_SEPARATOR (*e2))
14025796c8dcSSimon Schubert 	++e2;
14035796c8dcSSimon Schubert       if (*e1 == '\0' || *e2 == '\0' || e1 - pathp != e2 - refp
1404c50c785cSJohn Marino 	  || filename_ncmp (pathp, refp, e1 - pathp) != 0)
14055796c8dcSSimon Schubert 	break;
14065796c8dcSSimon Schubert       pathp = e1 + 1;
14075796c8dcSSimon Schubert       refp = e2 + 1;
14085796c8dcSSimon Schubert     }
14095796c8dcSSimon Schubert 
1410*a45ae5f8SJohn Marino   len = strlen (pathp) + 1;
14115796c8dcSSimon Schubert   /* For each leading path element in the reference path,
14125796c8dcSSimon Schubert      insert "../" into the path.  */
14135796c8dcSSimon Schubert   for (; *refp; ++refp)
14145796c8dcSSimon Schubert     if (IS_DIR_SEPARATOR (*refp))
1415*a45ae5f8SJohn Marino       {
1416*a45ae5f8SJohn Marino 	/* PR 12710:  If the path element is "../" then instead of
1417*a45ae5f8SJohn Marino 	   inserting "../" we need to insert the name of the directory
1418*a45ae5f8SJohn Marino 	   at the current level.  */
1419*a45ae5f8SJohn Marino 	if (refp > ref_path + 1
1420*a45ae5f8SJohn Marino 	    && refp[-1] == '.'
1421*a45ae5f8SJohn Marino 	    && refp[-2] == '.')
1422*a45ae5f8SJohn Marino 	  dir_down ++;
1423*a45ae5f8SJohn Marino 	else
1424*a45ae5f8SJohn Marino 	  dir_up ++;
1425*a45ae5f8SJohn Marino       }
1426*a45ae5f8SJohn Marino 
1427*a45ae5f8SJohn Marino   /* If the lrealpath calls above succeeded then we should never
1428*a45ae5f8SJohn Marino      see dir_up and dir_down both being non-zero.  */
1429*a45ae5f8SJohn Marino 
1430*a45ae5f8SJohn Marino   len += 3 * dir_up;
1431*a45ae5f8SJohn Marino 
1432*a45ae5f8SJohn Marino   if (dir_down)
1433*a45ae5f8SJohn Marino     {
1434*a45ae5f8SJohn Marino       down = pwd + strlen (pwd) - 1;
1435*a45ae5f8SJohn Marino 
1436*a45ae5f8SJohn Marino       while (dir_down && down > pwd)
1437*a45ae5f8SJohn Marino 	{
1438*a45ae5f8SJohn Marino 	  if (IS_DIR_SEPARATOR (*down))
1439*a45ae5f8SJohn Marino 	    --dir_down;
1440*a45ae5f8SJohn Marino 	}
1441*a45ae5f8SJohn Marino       BFD_ASSERT (dir_down == 0);
1442*a45ae5f8SJohn Marino       len += strlen (down) + 1;
1443*a45ae5f8SJohn Marino     }
1444*a45ae5f8SJohn Marino   else
1445*a45ae5f8SJohn Marino     down = NULL;
14465796c8dcSSimon Schubert 
14475796c8dcSSimon Schubert   if (len > pathbuf_len)
14485796c8dcSSimon Schubert     {
14495796c8dcSSimon Schubert       if (pathbuf != NULL)
14505796c8dcSSimon Schubert 	free (pathbuf);
14515796c8dcSSimon Schubert       pathbuf_len = 0;
14525796c8dcSSimon Schubert       pathbuf = (char *) bfd_malloc (len);
14535796c8dcSSimon Schubert       if (pathbuf == NULL)
1454*a45ae5f8SJohn Marino 	goto out;
14555796c8dcSSimon Schubert       pathbuf_len = len;
14565796c8dcSSimon Schubert     }
14575796c8dcSSimon Schubert 
14585796c8dcSSimon Schubert   newp = pathbuf;
1459*a45ae5f8SJohn Marino   while (dir_up-- > 0)
14605796c8dcSSimon Schubert     {
14615796c8dcSSimon Schubert       /* FIXME: Support Windows style path separators as well.  */
14625796c8dcSSimon Schubert       strcpy (newp, "../");
14635796c8dcSSimon Schubert       newp += 3;
14645796c8dcSSimon Schubert     }
1465*a45ae5f8SJohn Marino 
1466*a45ae5f8SJohn Marino   if (down)
1467*a45ae5f8SJohn Marino     sprintf (newp, "%s/%s", down, pathp);
1468*a45ae5f8SJohn Marino   else
14695796c8dcSSimon Schubert     strcpy (newp, pathp);
14705796c8dcSSimon Schubert 
1471*a45ae5f8SJohn Marino  out:
1472*a45ae5f8SJohn Marino   free (lpath);
1473*a45ae5f8SJohn Marino   free (rpath);
14745796c8dcSSimon Schubert   return pathbuf;
14755796c8dcSSimon Schubert }
14765796c8dcSSimon Schubert 
14775796c8dcSSimon Schubert /* Build a BFD style extended name table.  */
14785796c8dcSSimon Schubert 
14795796c8dcSSimon Schubert bfd_boolean
14805796c8dcSSimon Schubert _bfd_archive_bsd_construct_extended_name_table (bfd *abfd,
14815796c8dcSSimon Schubert 						char **tabloc,
14825796c8dcSSimon Schubert 						bfd_size_type *tablen,
14835796c8dcSSimon Schubert 						const char **name)
14845796c8dcSSimon Schubert {
14855796c8dcSSimon Schubert   *name = "ARFILENAMES/";
14865796c8dcSSimon Schubert   return _bfd_construct_extended_name_table (abfd, FALSE, tabloc, tablen);
14875796c8dcSSimon Schubert }
14885796c8dcSSimon Schubert 
14895796c8dcSSimon Schubert /* Build an SVR4 style extended name table.  */
14905796c8dcSSimon Schubert 
14915796c8dcSSimon Schubert bfd_boolean
14925796c8dcSSimon Schubert _bfd_archive_coff_construct_extended_name_table (bfd *abfd,
14935796c8dcSSimon Schubert 						 char **tabloc,
14945796c8dcSSimon Schubert 						 bfd_size_type *tablen,
14955796c8dcSSimon Schubert 						 const char **name)
14965796c8dcSSimon Schubert {
14975796c8dcSSimon Schubert   *name = "//";
14985796c8dcSSimon Schubert   return _bfd_construct_extended_name_table (abfd, TRUE, tabloc, tablen);
14995796c8dcSSimon Schubert }
15005796c8dcSSimon Schubert 
15015796c8dcSSimon Schubert /* Follows archive_head and produces an extended name table if
15025796c8dcSSimon Schubert    necessary.  Returns (in tabloc) a pointer to an extended name
15035796c8dcSSimon Schubert    table, and in tablen the length of the table.  If it makes an entry
15045796c8dcSSimon Schubert    it clobbers the filename so that the element may be written without
15055796c8dcSSimon Schubert    further massage.  Returns TRUE if it ran successfully, FALSE if
15065796c8dcSSimon Schubert    something went wrong.  A successful return may still involve a
15075796c8dcSSimon Schubert    zero-length tablen!  */
15085796c8dcSSimon Schubert 
15095796c8dcSSimon Schubert bfd_boolean
15105796c8dcSSimon Schubert _bfd_construct_extended_name_table (bfd *abfd,
15115796c8dcSSimon Schubert 				    bfd_boolean trailing_slash,
15125796c8dcSSimon Schubert 				    char **tabloc,
15135796c8dcSSimon Schubert 				    bfd_size_type *tablen)
15145796c8dcSSimon Schubert {
1515*a45ae5f8SJohn Marino   unsigned int maxname = ar_maxnamelen (abfd);
15165796c8dcSSimon Schubert   bfd_size_type total_namelen = 0;
15175796c8dcSSimon Schubert   bfd *current;
15185796c8dcSSimon Schubert   char *strptr;
15195796c8dcSSimon Schubert   const char *last_filename;
15205796c8dcSSimon Schubert   long last_stroff;
15215796c8dcSSimon Schubert 
15225796c8dcSSimon Schubert   *tablen = 0;
15235796c8dcSSimon Schubert   last_filename = NULL;
15245796c8dcSSimon Schubert 
15255796c8dcSSimon Schubert   /* Figure out how long the table should be.  */
15265796c8dcSSimon Schubert   for (current = abfd->archive_head;
15275796c8dcSSimon Schubert        current != NULL;
15285796c8dcSSimon Schubert        current = current->archive_next)
15295796c8dcSSimon Schubert     {
15305796c8dcSSimon Schubert       const char *normal;
15315796c8dcSSimon Schubert       unsigned int thislen;
15325796c8dcSSimon Schubert 
15335796c8dcSSimon Schubert       if (bfd_is_thin_archive (abfd))
15345796c8dcSSimon Schubert         {
15355796c8dcSSimon Schubert           const char *filename = current->filename;
15365796c8dcSSimon Schubert 
15375796c8dcSSimon Schubert           /* If the element being added is a member of another archive
15385796c8dcSSimon Schubert              (i.e., we are flattening), use the containing archive's name.  */
15395796c8dcSSimon Schubert           if (current->my_archive
15405796c8dcSSimon Schubert               && ! bfd_is_thin_archive (current->my_archive))
15415796c8dcSSimon Schubert             filename = current->my_archive->filename;
15425796c8dcSSimon Schubert 
15435796c8dcSSimon Schubert           /* If the path is the same as the previous path seen,
15445796c8dcSSimon Schubert              reuse it.  This can happen when flattening a thin
15455796c8dcSSimon Schubert              archive that contains other archives.  */
1546c50c785cSJohn Marino           if (last_filename && filename_cmp (last_filename, filename) == 0)
15475796c8dcSSimon Schubert             continue;
15485796c8dcSSimon Schubert 
15495796c8dcSSimon Schubert           last_filename = filename;
15505796c8dcSSimon Schubert 
15515796c8dcSSimon Schubert           /* If the path is relative, adjust it relative to
15525796c8dcSSimon Schubert              the containing archive. */
15535796c8dcSSimon Schubert           if (! IS_ABSOLUTE_PATH (filename)
15545796c8dcSSimon Schubert               && ! IS_ABSOLUTE_PATH (abfd->filename))
15555796c8dcSSimon Schubert             normal = adjust_relative_path (filename, abfd->filename);
15565796c8dcSSimon Schubert           else
15575796c8dcSSimon Schubert             normal = filename;
15585796c8dcSSimon Schubert 
15595796c8dcSSimon Schubert           /* In a thin archive, always store the full pathname
15605796c8dcSSimon Schubert              in the extended name table.  */
15615796c8dcSSimon Schubert           total_namelen += strlen (normal) + 1;
15625796c8dcSSimon Schubert 	  if (trailing_slash)
15635796c8dcSSimon Schubert 	    /* Leave room for trailing slash.  */
15645796c8dcSSimon Schubert 	    ++total_namelen;
15655796c8dcSSimon Schubert 
15665796c8dcSSimon Schubert           continue;
15675796c8dcSSimon Schubert         }
15685796c8dcSSimon Schubert 
15695796c8dcSSimon Schubert       normal = normalize (current, current->filename);
15705796c8dcSSimon Schubert       if (normal == NULL)
15715796c8dcSSimon Schubert 	return FALSE;
15725796c8dcSSimon Schubert 
15735796c8dcSSimon Schubert       thislen = strlen (normal);
15745796c8dcSSimon Schubert 
15755796c8dcSSimon Schubert       if (thislen > maxname
15765796c8dcSSimon Schubert 	  && (bfd_get_file_flags (abfd) & BFD_TRADITIONAL_FORMAT) != 0)
15775796c8dcSSimon Schubert 	thislen = maxname;
15785796c8dcSSimon Schubert 
15795796c8dcSSimon Schubert       if (thislen > maxname)
15805796c8dcSSimon Schubert 	{
15815796c8dcSSimon Schubert 	  /* Add one to leave room for \n.  */
15825796c8dcSSimon Schubert 	  total_namelen += thislen + 1;
15835796c8dcSSimon Schubert 	  if (trailing_slash)
15845796c8dcSSimon Schubert 	    {
15855796c8dcSSimon Schubert 	      /* Leave room for trailing slash.  */
15865796c8dcSSimon Schubert 	      ++total_namelen;
15875796c8dcSSimon Schubert 	    }
15885796c8dcSSimon Schubert 	}
15895796c8dcSSimon Schubert       else
15905796c8dcSSimon Schubert 	{
15915796c8dcSSimon Schubert 	  struct ar_hdr *hdr = arch_hdr (current);
1592c50c785cSJohn Marino 	  if (filename_ncmp (normal, hdr->ar_name, thislen) != 0
15935796c8dcSSimon Schubert 	      || (thislen < sizeof hdr->ar_name
15945796c8dcSSimon Schubert 		  && hdr->ar_name[thislen] != ar_padchar (current)))
15955796c8dcSSimon Schubert 	    {
15965796c8dcSSimon Schubert 	      /* Must have been using extended format even though it
15975796c8dcSSimon Schubert 	         didn't need to.  Fix it to use normal format.  */
15985796c8dcSSimon Schubert 	      memcpy (hdr->ar_name, normal, thislen);
15995796c8dcSSimon Schubert 	      if (thislen < maxname
16005796c8dcSSimon Schubert 		  || (thislen == maxname && thislen < sizeof hdr->ar_name))
16015796c8dcSSimon Schubert 		hdr->ar_name[thislen] = ar_padchar (current);
16025796c8dcSSimon Schubert 	    }
16035796c8dcSSimon Schubert 	}
16045796c8dcSSimon Schubert     }
16055796c8dcSSimon Schubert 
16065796c8dcSSimon Schubert   if (total_namelen == 0)
16075796c8dcSSimon Schubert     return TRUE;
16085796c8dcSSimon Schubert 
16095796c8dcSSimon Schubert   *tabloc = (char *) bfd_zalloc (abfd, total_namelen);
16105796c8dcSSimon Schubert   if (*tabloc == NULL)
16115796c8dcSSimon Schubert     return FALSE;
16125796c8dcSSimon Schubert 
16135796c8dcSSimon Schubert   *tablen = total_namelen;
16145796c8dcSSimon Schubert   strptr = *tabloc;
16155796c8dcSSimon Schubert 
16165796c8dcSSimon Schubert   last_filename = NULL;
16175796c8dcSSimon Schubert   last_stroff = 0;
16185796c8dcSSimon Schubert 
16195796c8dcSSimon Schubert   for (current = abfd->archive_head;
16205796c8dcSSimon Schubert        current != NULL;
16215796c8dcSSimon Schubert        current = current->archive_next)
16225796c8dcSSimon Schubert     {
16235796c8dcSSimon Schubert       const char *normal;
16245796c8dcSSimon Schubert       unsigned int thislen;
16255796c8dcSSimon Schubert       long stroff;
16265796c8dcSSimon Schubert       const char *filename = current->filename;
16275796c8dcSSimon Schubert 
16285796c8dcSSimon Schubert       if (bfd_is_thin_archive (abfd))
16295796c8dcSSimon Schubert         {
16305796c8dcSSimon Schubert           /* If the element being added is a member of another archive
16315796c8dcSSimon Schubert              (i.e., we are flattening), use the containing archive's name.  */
16325796c8dcSSimon Schubert           if (current->my_archive
16335796c8dcSSimon Schubert               && ! bfd_is_thin_archive (current->my_archive))
16345796c8dcSSimon Schubert             filename = current->my_archive->filename;
16355796c8dcSSimon Schubert           /* If the path is the same as the previous path seen,
16365796c8dcSSimon Schubert              reuse it.  This can happen when flattening a thin
16375796c8dcSSimon Schubert              archive that contains other archives.
16385796c8dcSSimon Schubert              If the path is relative, adjust it relative to
16395796c8dcSSimon Schubert              the containing archive.  */
1640c50c785cSJohn Marino           if (last_filename && filename_cmp (last_filename, filename) == 0)
16415796c8dcSSimon Schubert             normal = last_filename;
16425796c8dcSSimon Schubert           else if (! IS_ABSOLUTE_PATH (filename)
16435796c8dcSSimon Schubert                    && ! IS_ABSOLUTE_PATH (abfd->filename))
16445796c8dcSSimon Schubert             normal = adjust_relative_path (filename, abfd->filename);
16455796c8dcSSimon Schubert           else
16465796c8dcSSimon Schubert             normal = filename;
16475796c8dcSSimon Schubert         }
16485796c8dcSSimon Schubert       else
16495796c8dcSSimon Schubert         {
16505796c8dcSSimon Schubert           normal = normalize (current, filename);
16515796c8dcSSimon Schubert           if (normal == NULL)
16525796c8dcSSimon Schubert             return FALSE;
16535796c8dcSSimon Schubert         }
16545796c8dcSSimon Schubert 
16555796c8dcSSimon Schubert       thislen = strlen (normal);
16565796c8dcSSimon Schubert       if (thislen > maxname || bfd_is_thin_archive (abfd))
16575796c8dcSSimon Schubert 	{
16585796c8dcSSimon Schubert 	  /* Works for now; may need to be re-engineered if we
16595796c8dcSSimon Schubert 	     encounter an oddball archive format and want to
16605796c8dcSSimon Schubert 	     generalise this hack.  */
16615796c8dcSSimon Schubert 	  struct ar_hdr *hdr = arch_hdr (current);
16625796c8dcSSimon Schubert 	  if (normal == last_filename)
16635796c8dcSSimon Schubert 	    stroff = last_stroff;
16645796c8dcSSimon Schubert           else
16655796c8dcSSimon Schubert             {
16665796c8dcSSimon Schubert 	      strcpy (strptr, normal);
16675796c8dcSSimon Schubert 	      if (! trailing_slash)
16685796c8dcSSimon Schubert 	        strptr[thislen] = ARFMAG[1];
16695796c8dcSSimon Schubert 	      else
16705796c8dcSSimon Schubert 	        {
16715796c8dcSSimon Schubert 	          strptr[thislen] = '/';
16725796c8dcSSimon Schubert 	          strptr[thislen + 1] = ARFMAG[1];
16735796c8dcSSimon Schubert 	        }
16745796c8dcSSimon Schubert 	      stroff = strptr - *tabloc;
16755796c8dcSSimon Schubert 	      last_stroff = stroff;
16765796c8dcSSimon Schubert 	    }
16775796c8dcSSimon Schubert 	  hdr->ar_name[0] = ar_padchar (current);
16785796c8dcSSimon Schubert 	  if (bfd_is_thin_archive (abfd) && current->origin > 0)
16795796c8dcSSimon Schubert 	    {
16805796c8dcSSimon Schubert 	      int len = snprintf (hdr->ar_name + 1, maxname - 1, "%-ld:",
16815796c8dcSSimon Schubert 	                          stroff);
16825796c8dcSSimon Schubert 	      _bfd_ar_spacepad (hdr->ar_name + 1 + len, maxname - 1 - len,
16835796c8dcSSimon Schubert                                 "%-ld",
16845796c8dcSSimon Schubert                                 current->origin - sizeof (struct ar_hdr));
16855796c8dcSSimon Schubert 	    }
16865796c8dcSSimon Schubert 	  else
16875796c8dcSSimon Schubert             _bfd_ar_spacepad (hdr->ar_name + 1, maxname - 1, "%-ld", stroff);
16885796c8dcSSimon Schubert           if (normal != last_filename)
16895796c8dcSSimon Schubert             {
16905796c8dcSSimon Schubert 	      strptr += thislen + 1;
16915796c8dcSSimon Schubert 	      if (trailing_slash)
16925796c8dcSSimon Schubert 	        ++strptr;
16935796c8dcSSimon Schubert               last_filename = filename;
16945796c8dcSSimon Schubert 	    }
16955796c8dcSSimon Schubert 	}
16965796c8dcSSimon Schubert     }
16975796c8dcSSimon Schubert 
16985796c8dcSSimon Schubert   return TRUE;
16995796c8dcSSimon Schubert }
1700cf7f2e2dSJohn Marino 
1701cf7f2e2dSJohn Marino /* Do not construct an extended name table but transforms name field into
1702cf7f2e2dSJohn Marino    its extended form.  */
1703cf7f2e2dSJohn Marino 
1704cf7f2e2dSJohn Marino bfd_boolean
1705cf7f2e2dSJohn Marino _bfd_archive_bsd44_construct_extended_name_table (bfd *abfd,
1706cf7f2e2dSJohn Marino                                                   char **tabloc,
1707cf7f2e2dSJohn Marino                                                   bfd_size_type *tablen,
1708cf7f2e2dSJohn Marino                                                   const char **name)
1709cf7f2e2dSJohn Marino {
1710*a45ae5f8SJohn Marino   unsigned int maxname = ar_maxnamelen (abfd);
1711cf7f2e2dSJohn Marino   bfd *current;
1712cf7f2e2dSJohn Marino 
1713cf7f2e2dSJohn Marino   *tablen = 0;
1714cf7f2e2dSJohn Marino   *tabloc = NULL;
1715cf7f2e2dSJohn Marino   *name = NULL;
1716cf7f2e2dSJohn Marino 
1717cf7f2e2dSJohn Marino   for (current = abfd->archive_head;
1718cf7f2e2dSJohn Marino        current != NULL;
1719cf7f2e2dSJohn Marino        current = current->archive_next)
1720cf7f2e2dSJohn Marino     {
1721cf7f2e2dSJohn Marino       const char *normal = normalize (current, current->filename);
1722cf7f2e2dSJohn Marino       int has_space = 0;
1723cf7f2e2dSJohn Marino       unsigned int len;
1724cf7f2e2dSJohn Marino 
1725cf7f2e2dSJohn Marino       if (normal == NULL)
1726cf7f2e2dSJohn Marino 	return FALSE;
1727cf7f2e2dSJohn Marino 
1728cf7f2e2dSJohn Marino       for (len = 0; normal[len]; len++)
1729cf7f2e2dSJohn Marino         if (normal[len] == ' ')
1730cf7f2e2dSJohn Marino           has_space = 1;
1731cf7f2e2dSJohn Marino 
1732cf7f2e2dSJohn Marino       if (len > maxname || has_space)
1733cf7f2e2dSJohn Marino 	{
1734cf7f2e2dSJohn Marino           struct ar_hdr *hdr = arch_hdr (current);
1735cf7f2e2dSJohn Marino 
1736cf7f2e2dSJohn Marino           len = (len + 3) & ~3;
1737cf7f2e2dSJohn Marino           arch_eltdata (current)->extra_size = len;
1738c50c785cSJohn Marino           _bfd_ar_spacepad (hdr->ar_name, maxname, "#1/%lu", len);
1739cf7f2e2dSJohn Marino 	}
1740cf7f2e2dSJohn Marino     }
1741cf7f2e2dSJohn Marino 
1742cf7f2e2dSJohn Marino   return TRUE;
1743cf7f2e2dSJohn Marino }
1744cf7f2e2dSJohn Marino 
1745cf7f2e2dSJohn Marino /* Write an archive header.  */
1746cf7f2e2dSJohn Marino 
1747cf7f2e2dSJohn Marino bfd_boolean
1748cf7f2e2dSJohn Marino _bfd_generic_write_ar_hdr (bfd *archive, bfd *abfd)
1749cf7f2e2dSJohn Marino {
1750cf7f2e2dSJohn Marino   struct ar_hdr *hdr = arch_hdr (abfd);
1751cf7f2e2dSJohn Marino 
1752cf7f2e2dSJohn Marino   if (bfd_bwrite (hdr, sizeof (*hdr), archive) != sizeof (*hdr))
1753cf7f2e2dSJohn Marino     return FALSE;
1754cf7f2e2dSJohn Marino   return TRUE;
1755cf7f2e2dSJohn Marino }
1756cf7f2e2dSJohn Marino 
1757cf7f2e2dSJohn Marino /* Write an archive header using BSD4.4 convention.  */
1758cf7f2e2dSJohn Marino 
1759cf7f2e2dSJohn Marino bfd_boolean
1760cf7f2e2dSJohn Marino _bfd_bsd44_write_ar_hdr (bfd *archive, bfd *abfd)
1761cf7f2e2dSJohn Marino {
1762cf7f2e2dSJohn Marino   struct ar_hdr *hdr = arch_hdr (abfd);
1763cf7f2e2dSJohn Marino 
1764cf7f2e2dSJohn Marino   if (is_bsd44_extended_name (hdr->ar_name))
1765cf7f2e2dSJohn Marino     {
1766cf7f2e2dSJohn Marino       /* This is a BSD 4.4 extended name.  */
1767cf7f2e2dSJohn Marino       const char *fullname = normalize (abfd, abfd->filename);
1768cf7f2e2dSJohn Marino       unsigned int len = strlen (fullname);
1769cf7f2e2dSJohn Marino       unsigned int padded_len = (len + 3) & ~3;
1770cf7f2e2dSJohn Marino 
1771cf7f2e2dSJohn Marino       BFD_ASSERT (padded_len == arch_eltdata (abfd)->extra_size);
1772cf7f2e2dSJohn Marino 
1773cf7f2e2dSJohn Marino       _bfd_ar_spacepad (hdr->ar_size, sizeof (hdr->ar_size), "%-10ld",
1774cf7f2e2dSJohn Marino                         arch_eltdata (abfd)->parsed_size + padded_len);
1775cf7f2e2dSJohn Marino 
1776cf7f2e2dSJohn Marino       if (bfd_bwrite (hdr, sizeof (*hdr), archive) != sizeof (*hdr))
1777cf7f2e2dSJohn Marino         return FALSE;
1778cf7f2e2dSJohn Marino 
1779cf7f2e2dSJohn Marino       if (bfd_bwrite (fullname, len, archive) != len)
1780cf7f2e2dSJohn Marino         return FALSE;
1781cf7f2e2dSJohn Marino       if (len & 3)
1782cf7f2e2dSJohn Marino         {
1783cf7f2e2dSJohn Marino           static const char pad[3] = { 0, 0, 0 };
1784cf7f2e2dSJohn Marino 
1785cf7f2e2dSJohn Marino           len = 4 - (len & 3);
1786cf7f2e2dSJohn Marino           if (bfd_bwrite (pad, len, archive) != len)
1787cf7f2e2dSJohn Marino             return FALSE;
1788cf7f2e2dSJohn Marino         }
1789cf7f2e2dSJohn Marino     }
1790cf7f2e2dSJohn Marino   else
1791cf7f2e2dSJohn Marino     {
1792cf7f2e2dSJohn Marino       if (bfd_bwrite (hdr, sizeof (*hdr), archive) != sizeof (*hdr))
1793cf7f2e2dSJohn Marino         return FALSE;
1794cf7f2e2dSJohn Marino     }
1795cf7f2e2dSJohn Marino   return TRUE;
1796cf7f2e2dSJohn Marino }
17975796c8dcSSimon Schubert 
17985796c8dcSSimon Schubert /* A couple of functions for creating ar_hdrs.  */
17995796c8dcSSimon Schubert 
18005796c8dcSSimon Schubert #ifdef HPUX_LARGE_AR_IDS
18015796c8dcSSimon Schubert /* Function to encode large UID/GID values according to HP.  */
18025796c8dcSSimon Schubert 
18035796c8dcSSimon Schubert static void
18045796c8dcSSimon Schubert hpux_uid_gid_encode (char str[6], long int id)
18055796c8dcSSimon Schubert {
18065796c8dcSSimon Schubert   int cnt;
18075796c8dcSSimon Schubert 
18085796c8dcSSimon Schubert   str[5] = '@' + (id & 3);
18095796c8dcSSimon Schubert   id >>= 2;
18105796c8dcSSimon Schubert 
18115796c8dcSSimon Schubert   for (cnt = 4; cnt >= 0; --cnt, id >>= 6)
18125796c8dcSSimon Schubert     str[cnt] = ' ' + (id & 0x3f);
18135796c8dcSSimon Schubert }
18145796c8dcSSimon Schubert #endif	/* HPUX_LARGE_AR_IDS */
18155796c8dcSSimon Schubert 
18165796c8dcSSimon Schubert #ifndef HAVE_GETUID
18175796c8dcSSimon Schubert #define getuid() 0
18185796c8dcSSimon Schubert #endif
18195796c8dcSSimon Schubert 
18205796c8dcSSimon Schubert #ifndef HAVE_GETGID
18215796c8dcSSimon Schubert #define getgid() 0
18225796c8dcSSimon Schubert #endif
18235796c8dcSSimon Schubert 
18245796c8dcSSimon Schubert /* Takes a filename, returns an arelt_data for it, or NULL if it can't
18255796c8dcSSimon Schubert    make one.  The filename must refer to a filename in the filesystem.
18265796c8dcSSimon Schubert    The filename field of the ar_hdr will NOT be initialized.  If member
18275796c8dcSSimon Schubert    is set, and it's an in-memory bfd, we fake it.  */
18285796c8dcSSimon Schubert 
18295796c8dcSSimon Schubert static struct areltdata *
18305796c8dcSSimon Schubert bfd_ar_hdr_from_filesystem (bfd *abfd, const char *filename, bfd *member)
18315796c8dcSSimon Schubert {
18325796c8dcSSimon Schubert   struct stat status;
18335796c8dcSSimon Schubert   struct areltdata *ared;
18345796c8dcSSimon Schubert   struct ar_hdr *hdr;
18355796c8dcSSimon Schubert   bfd_size_type amt;
18365796c8dcSSimon Schubert 
18375796c8dcSSimon Schubert   if (member && (member->flags & BFD_IN_MEMORY) != 0)
18385796c8dcSSimon Schubert     {
18395796c8dcSSimon Schubert       /* Assume we just "made" the member, and fake it.  */
18405796c8dcSSimon Schubert       struct bfd_in_memory *bim = (struct bfd_in_memory *) member->iostream;
18415796c8dcSSimon Schubert       time (&status.st_mtime);
18425796c8dcSSimon Schubert       status.st_uid = getuid ();
18435796c8dcSSimon Schubert       status.st_gid = getgid ();
18445796c8dcSSimon Schubert       status.st_mode = 0644;
18455796c8dcSSimon Schubert       status.st_size = bim->size;
18465796c8dcSSimon Schubert     }
18475796c8dcSSimon Schubert   else if (stat (filename, &status) != 0)
18485796c8dcSSimon Schubert     {
18495796c8dcSSimon Schubert       bfd_set_error (bfd_error_system_call);
18505796c8dcSSimon Schubert       return NULL;
18515796c8dcSSimon Schubert     }
18525796c8dcSSimon Schubert 
18535796c8dcSSimon Schubert   /* If the caller requested that the BFD generate deterministic output,
18545796c8dcSSimon Schubert      fake values for modification time, UID, GID, and file mode.  */
18555796c8dcSSimon Schubert   if ((abfd->flags & BFD_DETERMINISTIC_OUTPUT) != 0)
18565796c8dcSSimon Schubert     {
18575796c8dcSSimon Schubert       status.st_mtime = 0;
18585796c8dcSSimon Schubert       status.st_uid = 0;
18595796c8dcSSimon Schubert       status.st_gid = 0;
18605796c8dcSSimon Schubert       status.st_mode = 0644;
18615796c8dcSSimon Schubert     }
18625796c8dcSSimon Schubert 
18635796c8dcSSimon Schubert   amt = sizeof (struct ar_hdr) + sizeof (struct areltdata);
18645796c8dcSSimon Schubert   ared = (struct areltdata *) bfd_zalloc (abfd, amt);
18655796c8dcSSimon Schubert   if (ared == NULL)
18665796c8dcSSimon Schubert     return NULL;
18675796c8dcSSimon Schubert   hdr = (struct ar_hdr *) (((char *) ared) + sizeof (struct areltdata));
18685796c8dcSSimon Schubert 
18695796c8dcSSimon Schubert   /* ar headers are space padded, not null padded!  */
18705796c8dcSSimon Schubert   memset (hdr, ' ', sizeof (struct ar_hdr));
18715796c8dcSSimon Schubert 
18725796c8dcSSimon Schubert   _bfd_ar_spacepad (hdr->ar_date, sizeof (hdr->ar_date), "%-12ld",
18735796c8dcSSimon Schubert                     status.st_mtime);
18745796c8dcSSimon Schubert #ifdef HPUX_LARGE_AR_IDS
18755796c8dcSSimon Schubert   /* HP has a very "special" way to handle UID/GID's with numeric values
18765796c8dcSSimon Schubert      > 99999.  */
18775796c8dcSSimon Schubert   if (status.st_uid > 99999)
18785796c8dcSSimon Schubert     hpux_uid_gid_encode (hdr->ar_uid, (long) status.st_uid);
18795796c8dcSSimon Schubert   else
18805796c8dcSSimon Schubert #endif
18815796c8dcSSimon Schubert     _bfd_ar_spacepad (hdr->ar_uid, sizeof (hdr->ar_uid), "%ld",
18825796c8dcSSimon Schubert                       status.st_uid);
18835796c8dcSSimon Schubert #ifdef HPUX_LARGE_AR_IDS
18845796c8dcSSimon Schubert   /* HP has a very "special" way to handle UID/GID's with numeric values
18855796c8dcSSimon Schubert      > 99999.  */
18865796c8dcSSimon Schubert   if (status.st_gid > 99999)
18875796c8dcSSimon Schubert     hpux_uid_gid_encode (hdr->ar_gid, (long) status.st_gid);
18885796c8dcSSimon Schubert   else
18895796c8dcSSimon Schubert #endif
18905796c8dcSSimon Schubert     _bfd_ar_spacepad (hdr->ar_gid, sizeof (hdr->ar_gid), "%ld",
18915796c8dcSSimon Schubert                       status.st_gid);
18925796c8dcSSimon Schubert   _bfd_ar_spacepad (hdr->ar_mode, sizeof (hdr->ar_mode), "%-8lo",
18935796c8dcSSimon Schubert                     status.st_mode);
18945796c8dcSSimon Schubert   _bfd_ar_spacepad (hdr->ar_size, sizeof (hdr->ar_size), "%-10ld",
18955796c8dcSSimon Schubert                     status.st_size);
18965796c8dcSSimon Schubert   memcpy (hdr->ar_fmag, ARFMAG, 2);
18975796c8dcSSimon Schubert   ared->parsed_size = status.st_size;
18985796c8dcSSimon Schubert   ared->arch_header = (char *) hdr;
18995796c8dcSSimon Schubert 
19005796c8dcSSimon Schubert   return ared;
19015796c8dcSSimon Schubert }
19025796c8dcSSimon Schubert 
19035796c8dcSSimon Schubert /* Analogous to stat call.  */
19045796c8dcSSimon Schubert 
19055796c8dcSSimon Schubert int
19065796c8dcSSimon Schubert bfd_generic_stat_arch_elt (bfd *abfd, struct stat *buf)
19075796c8dcSSimon Schubert {
19085796c8dcSSimon Schubert   struct ar_hdr *hdr;
19095796c8dcSSimon Schubert   char *aloser;
19105796c8dcSSimon Schubert 
19115796c8dcSSimon Schubert   if (abfd->arelt_data == NULL)
19125796c8dcSSimon Schubert     {
19135796c8dcSSimon Schubert       bfd_set_error (bfd_error_invalid_operation);
19145796c8dcSSimon Schubert       return -1;
19155796c8dcSSimon Schubert     }
19165796c8dcSSimon Schubert 
19175796c8dcSSimon Schubert   hdr = arch_hdr (abfd);
19185796c8dcSSimon Schubert 
19195796c8dcSSimon Schubert #define foo(arelt, stelt, size)				\
19205796c8dcSSimon Schubert   buf->stelt = strtol (hdr->arelt, &aloser, size);	\
19215796c8dcSSimon Schubert   if (aloser == hdr->arelt)	      			\
19225796c8dcSSimon Schubert     return -1;
19235796c8dcSSimon Schubert 
19245796c8dcSSimon Schubert   /* Some platforms support special notations for large IDs.  */
19255796c8dcSSimon Schubert #ifdef HPUX_LARGE_AR_IDS
19265796c8dcSSimon Schubert # define foo2(arelt, stelt, size)					\
19275796c8dcSSimon Schubert   if (hdr->arelt[5] == ' ')						\
19285796c8dcSSimon Schubert     {									\
19295796c8dcSSimon Schubert       foo (arelt, stelt, size);						\
19305796c8dcSSimon Schubert     }									\
19315796c8dcSSimon Schubert   else									\
19325796c8dcSSimon Schubert     {									\
19335796c8dcSSimon Schubert       int cnt;								\
19345796c8dcSSimon Schubert       for (buf->stelt = cnt = 0; cnt < 5; ++cnt)			\
19355796c8dcSSimon Schubert 	{								\
19365796c8dcSSimon Schubert 	  if (hdr->arelt[cnt] < ' ' || hdr->arelt[cnt] > ' ' + 0x3f)	\
19375796c8dcSSimon Schubert 	    return -1;							\
19385796c8dcSSimon Schubert 	  buf->stelt <<= 6;						\
19395796c8dcSSimon Schubert 	  buf->stelt += hdr->arelt[cnt] - ' ';				\
19405796c8dcSSimon Schubert 	}								\
19415796c8dcSSimon Schubert       if (hdr->arelt[5] < '@' || hdr->arelt[5] > '@' + 3)		\
19425796c8dcSSimon Schubert 	return -1;							\
19435796c8dcSSimon Schubert       buf->stelt <<= 2;							\
19445796c8dcSSimon Schubert       buf->stelt += hdr->arelt[5] - '@';				\
19455796c8dcSSimon Schubert     }
19465796c8dcSSimon Schubert #else
19475796c8dcSSimon Schubert # define foo2(arelt, stelt, size) foo (arelt, stelt, size)
19485796c8dcSSimon Schubert #endif
19495796c8dcSSimon Schubert 
19505796c8dcSSimon Schubert   foo (ar_date, st_mtime, 10);
19515796c8dcSSimon Schubert   foo2 (ar_uid, st_uid, 10);
19525796c8dcSSimon Schubert   foo2 (ar_gid, st_gid, 10);
19535796c8dcSSimon Schubert   foo (ar_mode, st_mode, 8);
19545796c8dcSSimon Schubert 
19555796c8dcSSimon Schubert   buf->st_size = arch_eltdata (abfd)->parsed_size;
19565796c8dcSSimon Schubert 
19575796c8dcSSimon Schubert   return 0;
19585796c8dcSSimon Schubert }
19595796c8dcSSimon Schubert 
19605796c8dcSSimon Schubert void
19615796c8dcSSimon Schubert bfd_dont_truncate_arname (bfd *abfd, const char *pathname, char *arhdr)
19625796c8dcSSimon Schubert {
19635796c8dcSSimon Schubert   /* FIXME: This interacts unpleasantly with ar's quick-append option.
19645796c8dcSSimon Schubert      Fortunately ic960 users will never use that option.  Fixing this
19655796c8dcSSimon Schubert      is very hard; fortunately I know how to do it and will do so once
19665796c8dcSSimon Schubert      intel's release is out the door.  */
19675796c8dcSSimon Schubert 
19685796c8dcSSimon Schubert   struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
19695796c8dcSSimon Schubert   size_t length;
19705796c8dcSSimon Schubert   const char *filename;
19715796c8dcSSimon Schubert   size_t maxlen = ar_maxnamelen (abfd);
19725796c8dcSSimon Schubert 
19735796c8dcSSimon Schubert   if ((bfd_get_file_flags (abfd) & BFD_TRADITIONAL_FORMAT) != 0)
19745796c8dcSSimon Schubert     {
19755796c8dcSSimon Schubert       bfd_bsd_truncate_arname (abfd, pathname, arhdr);
19765796c8dcSSimon Schubert       return;
19775796c8dcSSimon Schubert     }
19785796c8dcSSimon Schubert 
19795796c8dcSSimon Schubert   filename = normalize (abfd, pathname);
19805796c8dcSSimon Schubert   if (filename == NULL)
19815796c8dcSSimon Schubert     {
19825796c8dcSSimon Schubert       /* FIXME */
19835796c8dcSSimon Schubert       abort ();
19845796c8dcSSimon Schubert     }
19855796c8dcSSimon Schubert 
19865796c8dcSSimon Schubert   length = strlen (filename);
19875796c8dcSSimon Schubert 
19885796c8dcSSimon Schubert   if (length <= maxlen)
19895796c8dcSSimon Schubert     memcpy (hdr->ar_name, filename, length);
19905796c8dcSSimon Schubert 
19915796c8dcSSimon Schubert   /* Add the padding character if there is room for it.  */
19925796c8dcSSimon Schubert   if (length < maxlen
19935796c8dcSSimon Schubert       || (length == maxlen && length < sizeof hdr->ar_name))
19945796c8dcSSimon Schubert     (hdr->ar_name)[length] = ar_padchar (abfd);
19955796c8dcSSimon Schubert }
19965796c8dcSSimon Schubert 
19975796c8dcSSimon Schubert void
19985796c8dcSSimon Schubert bfd_bsd_truncate_arname (bfd *abfd, const char *pathname, char *arhdr)
19995796c8dcSSimon Schubert {
20005796c8dcSSimon Schubert   struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
20015796c8dcSSimon Schubert   size_t length;
2002cf7f2e2dSJohn Marino   const char *filename = lbasename (pathname);
20035796c8dcSSimon Schubert   size_t maxlen = ar_maxnamelen (abfd);
20045796c8dcSSimon Schubert 
20055796c8dcSSimon Schubert   length = strlen (filename);
20065796c8dcSSimon Schubert 
20075796c8dcSSimon Schubert   if (length <= maxlen)
20085796c8dcSSimon Schubert     memcpy (hdr->ar_name, filename, length);
20095796c8dcSSimon Schubert   else
20105796c8dcSSimon Schubert     {
20115796c8dcSSimon Schubert       /* pathname: meet procrustes */
20125796c8dcSSimon Schubert       memcpy (hdr->ar_name, filename, maxlen);
20135796c8dcSSimon Schubert       length = maxlen;
20145796c8dcSSimon Schubert     }
20155796c8dcSSimon Schubert 
20165796c8dcSSimon Schubert   if (length < maxlen)
20175796c8dcSSimon Schubert     (hdr->ar_name)[length] = ar_padchar (abfd);
20185796c8dcSSimon Schubert }
20195796c8dcSSimon Schubert 
20205796c8dcSSimon Schubert /* Store name into ar header.  Truncates the name to fit.
20215796c8dcSSimon Schubert    1> strip pathname to be just the basename.
20225796c8dcSSimon Schubert    2> if it's short enuf to fit, stuff it in.
20235796c8dcSSimon Schubert    3> If it doesn't end with .o, truncate it to fit
20245796c8dcSSimon Schubert    4> truncate it before the .o, append .o, stuff THAT in.  */
20255796c8dcSSimon Schubert 
20265796c8dcSSimon Schubert /* This is what gnu ar does.  It's better but incompatible with the
20275796c8dcSSimon Schubert    bsd ar.  */
20285796c8dcSSimon Schubert 
20295796c8dcSSimon Schubert void
20305796c8dcSSimon Schubert bfd_gnu_truncate_arname (bfd *abfd, const char *pathname, char *arhdr)
20315796c8dcSSimon Schubert {
20325796c8dcSSimon Schubert   struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
20335796c8dcSSimon Schubert   size_t length;
2034cf7f2e2dSJohn Marino   const char *filename = lbasename (pathname);
20355796c8dcSSimon Schubert   size_t maxlen = ar_maxnamelen (abfd);
20365796c8dcSSimon Schubert 
20375796c8dcSSimon Schubert   length = strlen (filename);
20385796c8dcSSimon Schubert 
20395796c8dcSSimon Schubert   if (length <= maxlen)
20405796c8dcSSimon Schubert     memcpy (hdr->ar_name, filename, length);
20415796c8dcSSimon Schubert   else
20425796c8dcSSimon Schubert     {
20435796c8dcSSimon Schubert       /* pathname: meet procrustes.  */
20445796c8dcSSimon Schubert       memcpy (hdr->ar_name, filename, maxlen);
20455796c8dcSSimon Schubert       if ((filename[length - 2] == '.') && (filename[length - 1] == 'o'))
20465796c8dcSSimon Schubert 	{
20475796c8dcSSimon Schubert 	  hdr->ar_name[maxlen - 2] = '.';
20485796c8dcSSimon Schubert 	  hdr->ar_name[maxlen - 1] = 'o';
20495796c8dcSSimon Schubert 	}
20505796c8dcSSimon Schubert       length = maxlen;
20515796c8dcSSimon Schubert     }
20525796c8dcSSimon Schubert 
20535796c8dcSSimon Schubert   if (length < 16)
20545796c8dcSSimon Schubert     (hdr->ar_name)[length] = ar_padchar (abfd);
20555796c8dcSSimon Schubert }
20565796c8dcSSimon Schubert 
20575796c8dcSSimon Schubert /* The BFD is open for write and has its format set to bfd_archive.  */
20585796c8dcSSimon Schubert 
20595796c8dcSSimon Schubert bfd_boolean
20605796c8dcSSimon Schubert _bfd_write_archive_contents (bfd *arch)
20615796c8dcSSimon Schubert {
20625796c8dcSSimon Schubert   bfd *current;
20635796c8dcSSimon Schubert   char *etable = NULL;
20645796c8dcSSimon Schubert   bfd_size_type elength = 0;
20655796c8dcSSimon Schubert   const char *ename = NULL;
20665796c8dcSSimon Schubert   bfd_boolean makemap = bfd_has_map (arch);
20675796c8dcSSimon Schubert   /* If no .o's, don't bother to make a map.  */
20685796c8dcSSimon Schubert   bfd_boolean hasobjects = FALSE;
20695796c8dcSSimon Schubert   bfd_size_type wrote;
20705796c8dcSSimon Schubert   int tries;
20715796c8dcSSimon Schubert   char *armag;
20725796c8dcSSimon Schubert 
20735796c8dcSSimon Schubert   /* Verify the viability of all entries; if any of them live in the
20745796c8dcSSimon Schubert      filesystem (as opposed to living in an archive open for input)
20755796c8dcSSimon Schubert      then construct a fresh ar_hdr for them.  */
20765796c8dcSSimon Schubert   for (current = arch->archive_head;
20775796c8dcSSimon Schubert        current != NULL;
20785796c8dcSSimon Schubert        current = current->archive_next)
20795796c8dcSSimon Schubert     {
20805796c8dcSSimon Schubert       /* This check is checking the bfds for the objects we're reading
20815796c8dcSSimon Schubert 	 from (which are usually either an object file or archive on
20825796c8dcSSimon Schubert 	 disk), not the archive entries we're writing to.  We don't
20835796c8dcSSimon Schubert 	 actually create bfds for the archive members, we just copy
20845796c8dcSSimon Schubert 	 them byte-wise when we write out the archive.  */
20855796c8dcSSimon Schubert       if (bfd_write_p (current))
20865796c8dcSSimon Schubert 	{
20875796c8dcSSimon Schubert 	  bfd_set_error (bfd_error_invalid_operation);
20885796c8dcSSimon Schubert 	  goto input_err;
20895796c8dcSSimon Schubert 	}
20905796c8dcSSimon Schubert       if (!current->arelt_data)
20915796c8dcSSimon Schubert 	{
20925796c8dcSSimon Schubert 	  current->arelt_data =
20935796c8dcSSimon Schubert 	    bfd_ar_hdr_from_filesystem (arch, current->filename, current);
20945796c8dcSSimon Schubert 	  if (!current->arelt_data)
20955796c8dcSSimon Schubert 	    goto input_err;
20965796c8dcSSimon Schubert 
20975796c8dcSSimon Schubert 	  /* Put in the file name.  */
20985796c8dcSSimon Schubert 	  BFD_SEND (arch, _bfd_truncate_arname,
20995796c8dcSSimon Schubert 		    (arch, current->filename, (char *) arch_hdr (current)));
21005796c8dcSSimon Schubert 	}
21015796c8dcSSimon Schubert 
21025796c8dcSSimon Schubert       if (makemap && ! hasobjects)
21035796c8dcSSimon Schubert 	{			/* Don't bother if we won't make a map!  */
21045796c8dcSSimon Schubert 	  if ((bfd_check_format (current, bfd_object)))
21055796c8dcSSimon Schubert 	    hasobjects = TRUE;
21065796c8dcSSimon Schubert 	}
21075796c8dcSSimon Schubert     }
21085796c8dcSSimon Schubert 
21095796c8dcSSimon Schubert   if (!BFD_SEND (arch, _bfd_construct_extended_name_table,
21105796c8dcSSimon Schubert 		 (arch, &etable, &elength, &ename)))
21115796c8dcSSimon Schubert     return FALSE;
21125796c8dcSSimon Schubert 
21135796c8dcSSimon Schubert   if (bfd_seek (arch, (file_ptr) 0, SEEK_SET) != 0)
21145796c8dcSSimon Schubert     return FALSE;
21155796c8dcSSimon Schubert   armag = ARMAG;
21165796c8dcSSimon Schubert   if (bfd_is_thin_archive (arch))
21175796c8dcSSimon Schubert     armag = ARMAGT;
21185796c8dcSSimon Schubert   wrote = bfd_bwrite (armag, SARMAG, arch);
21195796c8dcSSimon Schubert   if (wrote != SARMAG)
21205796c8dcSSimon Schubert     return FALSE;
21215796c8dcSSimon Schubert 
21225796c8dcSSimon Schubert   if (makemap && hasobjects)
21235796c8dcSSimon Schubert     {
21245796c8dcSSimon Schubert       if (! _bfd_compute_and_write_armap (arch, (unsigned int) elength))
21255796c8dcSSimon Schubert 	return FALSE;
21265796c8dcSSimon Schubert     }
21275796c8dcSSimon Schubert 
21285796c8dcSSimon Schubert   if (elength != 0)
21295796c8dcSSimon Schubert     {
21305796c8dcSSimon Schubert       struct ar_hdr hdr;
21315796c8dcSSimon Schubert 
21325796c8dcSSimon Schubert       memset (&hdr, ' ', sizeof (struct ar_hdr));
21335796c8dcSSimon Schubert       memcpy (hdr.ar_name, ename, strlen (ename));
21345796c8dcSSimon Schubert       /* Round size up to even number in archive header.  */
21355796c8dcSSimon Schubert       _bfd_ar_spacepad (hdr.ar_size, sizeof (hdr.ar_size), "%-10ld",
21365796c8dcSSimon Schubert                         (elength + 1) & ~(bfd_size_type) 1);
21375796c8dcSSimon Schubert       memcpy (hdr.ar_fmag, ARFMAG, 2);
21385796c8dcSSimon Schubert       if ((bfd_bwrite (&hdr, sizeof (struct ar_hdr), arch)
21395796c8dcSSimon Schubert 	   != sizeof (struct ar_hdr))
21405796c8dcSSimon Schubert 	  || bfd_bwrite (etable, elength, arch) != elength)
21415796c8dcSSimon Schubert 	return FALSE;
21425796c8dcSSimon Schubert       if ((elength % 2) == 1)
21435796c8dcSSimon Schubert 	{
21445796c8dcSSimon Schubert 	  if (bfd_bwrite (&ARFMAG[1], 1, arch) != 1)
21455796c8dcSSimon Schubert 	    return FALSE;
21465796c8dcSSimon Schubert 	}
21475796c8dcSSimon Schubert     }
21485796c8dcSSimon Schubert 
21495796c8dcSSimon Schubert   for (current = arch->archive_head;
21505796c8dcSSimon Schubert        current != NULL;
21515796c8dcSSimon Schubert        current = current->archive_next)
21525796c8dcSSimon Schubert     {
21535796c8dcSSimon Schubert       char buffer[DEFAULT_BUFFERSIZE];
21545796c8dcSSimon Schubert       unsigned int remaining = arelt_size (current);
21555796c8dcSSimon Schubert 
21565796c8dcSSimon Schubert       /* Write ar header.  */
2157cf7f2e2dSJohn Marino       if (!_bfd_write_ar_hdr (arch, current))
21585796c8dcSSimon Schubert         return FALSE;
21595796c8dcSSimon Schubert       if (bfd_is_thin_archive (arch))
21605796c8dcSSimon Schubert         continue;
21615796c8dcSSimon Schubert       if (bfd_seek (current, (file_ptr) 0, SEEK_SET) != 0)
21625796c8dcSSimon Schubert 	goto input_err;
21635796c8dcSSimon Schubert 
21645796c8dcSSimon Schubert       while (remaining)
21655796c8dcSSimon Schubert 	{
21665796c8dcSSimon Schubert 	  unsigned int amt = DEFAULT_BUFFERSIZE;
21675796c8dcSSimon Schubert 
21685796c8dcSSimon Schubert 	  if (amt > remaining)
21695796c8dcSSimon Schubert 	    amt = remaining;
21705796c8dcSSimon Schubert 	  errno = 0;
21715796c8dcSSimon Schubert 	  if (bfd_bread (buffer, amt, current) != amt)
21725796c8dcSSimon Schubert 	    {
21735796c8dcSSimon Schubert 	      if (bfd_get_error () != bfd_error_system_call)
21745796c8dcSSimon Schubert 		bfd_set_error (bfd_error_file_truncated);
21755796c8dcSSimon Schubert 	      goto input_err;
21765796c8dcSSimon Schubert 	    }
21775796c8dcSSimon Schubert 	  if (bfd_bwrite (buffer, amt, arch) != amt)
21785796c8dcSSimon Schubert 	    return FALSE;
21795796c8dcSSimon Schubert 	  remaining -= amt;
21805796c8dcSSimon Schubert 	}
21815796c8dcSSimon Schubert 
21825796c8dcSSimon Schubert       if ((arelt_size (current) % 2) == 1)
21835796c8dcSSimon Schubert 	{
21845796c8dcSSimon Schubert 	  if (bfd_bwrite (&ARFMAG[1], 1, arch) != 1)
21855796c8dcSSimon Schubert 	    return FALSE;
21865796c8dcSSimon Schubert 	}
21875796c8dcSSimon Schubert     }
21885796c8dcSSimon Schubert 
21895796c8dcSSimon Schubert   if (makemap && hasobjects)
21905796c8dcSSimon Schubert     {
21915796c8dcSSimon Schubert       /* Verify the timestamp in the archive file.  If it would not be
21925796c8dcSSimon Schubert 	 accepted by the linker, rewrite it until it would be.  If
21935796c8dcSSimon Schubert 	 anything odd happens, break out and just return.  (The
21945796c8dcSSimon Schubert 	 Berkeley linker checks the timestamp and refuses to read the
21955796c8dcSSimon Schubert 	 table-of-contents if it is >60 seconds less than the file's
21965796c8dcSSimon Schubert 	 modified-time.  That painful hack requires this painful hack.  */
21975796c8dcSSimon Schubert       tries = 1;
21985796c8dcSSimon Schubert       do
21995796c8dcSSimon Schubert 	{
22005796c8dcSSimon Schubert 	  if (bfd_update_armap_timestamp (arch))
22015796c8dcSSimon Schubert 	    break;
22025796c8dcSSimon Schubert 	  (*_bfd_error_handler)
22035796c8dcSSimon Schubert 	    (_("Warning: writing archive was slow: rewriting timestamp\n"));
22045796c8dcSSimon Schubert 	}
22055796c8dcSSimon Schubert       while (++tries < 6);
22065796c8dcSSimon Schubert     }
22075796c8dcSSimon Schubert 
22085796c8dcSSimon Schubert   return TRUE;
22095796c8dcSSimon Schubert 
22105796c8dcSSimon Schubert  input_err:
22115796c8dcSSimon Schubert   bfd_set_error (bfd_error_on_input, current, bfd_get_error ());
22125796c8dcSSimon Schubert   return FALSE;
22135796c8dcSSimon Schubert }
22145796c8dcSSimon Schubert 
22155796c8dcSSimon Schubert /* Note that the namidx for the first symbol is 0.  */
22165796c8dcSSimon Schubert 
22175796c8dcSSimon Schubert bfd_boolean
22185796c8dcSSimon Schubert _bfd_compute_and_write_armap (bfd *arch, unsigned int elength)
22195796c8dcSSimon Schubert {
22205796c8dcSSimon Schubert   char *first_name = NULL;
22215796c8dcSSimon Schubert   bfd *current;
22225796c8dcSSimon Schubert   file_ptr elt_no = 0;
22235796c8dcSSimon Schubert   struct orl *map = NULL;
22245796c8dcSSimon Schubert   unsigned int orl_max = 1024;		/* Fine initial default.  */
22255796c8dcSSimon Schubert   unsigned int orl_count = 0;
22265796c8dcSSimon Schubert   int stridx = 0;
22275796c8dcSSimon Schubert   asymbol **syms = NULL;
22285796c8dcSSimon Schubert   long syms_max = 0;
22295796c8dcSSimon Schubert   bfd_boolean ret;
22305796c8dcSSimon Schubert   bfd_size_type amt;
22315796c8dcSSimon Schubert 
22325796c8dcSSimon Schubert   /* Dunno if this is the best place for this info...  */
22335796c8dcSSimon Schubert   if (elength != 0)
22345796c8dcSSimon Schubert     elength += sizeof (struct ar_hdr);
22355796c8dcSSimon Schubert   elength += elength % 2;
22365796c8dcSSimon Schubert 
22375796c8dcSSimon Schubert   amt = orl_max * sizeof (struct orl);
22385796c8dcSSimon Schubert   map = (struct orl *) bfd_malloc (amt);
22395796c8dcSSimon Schubert   if (map == NULL)
22405796c8dcSSimon Schubert     goto error_return;
22415796c8dcSSimon Schubert 
22425796c8dcSSimon Schubert   /* We put the symbol names on the arch objalloc, and then discard
22435796c8dcSSimon Schubert      them when done.  */
22445796c8dcSSimon Schubert   first_name = (char *) bfd_alloc (arch, 1);
22455796c8dcSSimon Schubert   if (first_name == NULL)
22465796c8dcSSimon Schubert     goto error_return;
22475796c8dcSSimon Schubert 
22485796c8dcSSimon Schubert   /* Drop all the files called __.SYMDEF, we're going to make our own.  */
22495796c8dcSSimon Schubert   while (arch->archive_head
22505796c8dcSSimon Schubert 	 && strcmp (arch->archive_head->filename, "__.SYMDEF") == 0)
22515796c8dcSSimon Schubert     arch->archive_head = arch->archive_head->archive_next;
22525796c8dcSSimon Schubert 
22535796c8dcSSimon Schubert   /* Map over each element.  */
22545796c8dcSSimon Schubert   for (current = arch->archive_head;
22555796c8dcSSimon Schubert        current != NULL;
22565796c8dcSSimon Schubert        current = current->archive_next, elt_no++)
22575796c8dcSSimon Schubert     {
22585796c8dcSSimon Schubert       if (bfd_check_format (current, bfd_object)
22595796c8dcSSimon Schubert 	  && (bfd_get_file_flags (current) & HAS_SYMS) != 0)
22605796c8dcSSimon Schubert 	{
22615796c8dcSSimon Schubert 	  long storage;
22625796c8dcSSimon Schubert 	  long symcount;
22635796c8dcSSimon Schubert 	  long src_count;
22645796c8dcSSimon Schubert 
22655796c8dcSSimon Schubert 	  storage = bfd_get_symtab_upper_bound (current);
22665796c8dcSSimon Schubert 	  if (storage < 0)
22675796c8dcSSimon Schubert 	    goto error_return;
22685796c8dcSSimon Schubert 
22695796c8dcSSimon Schubert 	  if (storage != 0)
22705796c8dcSSimon Schubert 	    {
22715796c8dcSSimon Schubert 	      if (storage > syms_max)
22725796c8dcSSimon Schubert 		{
22735796c8dcSSimon Schubert 		  if (syms_max > 0)
22745796c8dcSSimon Schubert 		    free (syms);
22755796c8dcSSimon Schubert 		  syms_max = storage;
22765796c8dcSSimon Schubert 		  syms = (asymbol **) bfd_malloc (syms_max);
22775796c8dcSSimon Schubert 		  if (syms == NULL)
22785796c8dcSSimon Schubert 		    goto error_return;
22795796c8dcSSimon Schubert 		}
22805796c8dcSSimon Schubert 	      symcount = bfd_canonicalize_symtab (current, syms);
22815796c8dcSSimon Schubert 	      if (symcount < 0)
22825796c8dcSSimon Schubert 		goto error_return;
22835796c8dcSSimon Schubert 
22845796c8dcSSimon Schubert 	      /* Now map over all the symbols, picking out the ones we
22855796c8dcSSimon Schubert                  want.  */
22865796c8dcSSimon Schubert 	      for (src_count = 0; src_count < symcount; src_count++)
22875796c8dcSSimon Schubert 		{
22885796c8dcSSimon Schubert 		  flagword flags = (syms[src_count])->flags;
22895796c8dcSSimon Schubert 		  asection *sec = syms[src_count]->section;
22905796c8dcSSimon Schubert 
22915796c8dcSSimon Schubert 		  if ((flags & BSF_GLOBAL
22925796c8dcSSimon Schubert 		       || flags & BSF_WEAK
22935796c8dcSSimon Schubert 		       || flags & BSF_INDIRECT
2294cf7f2e2dSJohn Marino 		       || flags & BSF_GNU_UNIQUE
22955796c8dcSSimon Schubert 		       || bfd_is_com_section (sec))
22965796c8dcSSimon Schubert 		      && ! bfd_is_und_section (sec))
22975796c8dcSSimon Schubert 		    {
22985796c8dcSSimon Schubert 		      bfd_size_type namelen;
22995796c8dcSSimon Schubert 		      struct orl *new_map;
23005796c8dcSSimon Schubert 
23015796c8dcSSimon Schubert 		      /* This symbol will go into the archive header.  */
23025796c8dcSSimon Schubert 		      if (orl_count == orl_max)
23035796c8dcSSimon Schubert 			{
23045796c8dcSSimon Schubert 			  orl_max *= 2;
23055796c8dcSSimon Schubert 			  amt = orl_max * sizeof (struct orl);
23065796c8dcSSimon Schubert 			  new_map = (struct orl *) bfd_realloc (map, amt);
23075796c8dcSSimon Schubert 			  if (new_map == NULL)
23085796c8dcSSimon Schubert 			    goto error_return;
23095796c8dcSSimon Schubert 
23105796c8dcSSimon Schubert 			  map = new_map;
23115796c8dcSSimon Schubert 			}
23125796c8dcSSimon Schubert 
23135796c8dcSSimon Schubert 		      namelen = strlen (syms[src_count]->name);
23145796c8dcSSimon Schubert 		      amt = sizeof (char *);
23155796c8dcSSimon Schubert 		      map[orl_count].name = (char **) bfd_alloc (arch, amt);
23165796c8dcSSimon Schubert 		      if (map[orl_count].name == NULL)
23175796c8dcSSimon Schubert 			goto error_return;
23185796c8dcSSimon Schubert 		      *(map[orl_count].name) = (char *) bfd_alloc (arch,
23195796c8dcSSimon Schubert                                                                    namelen + 1);
23205796c8dcSSimon Schubert 		      if (*(map[orl_count].name) == NULL)
23215796c8dcSSimon Schubert 			goto error_return;
23225796c8dcSSimon Schubert 		      strcpy (*(map[orl_count].name), syms[src_count]->name);
23235796c8dcSSimon Schubert 		      map[orl_count].u.abfd = current;
23245796c8dcSSimon Schubert 		      map[orl_count].namidx = stridx;
23255796c8dcSSimon Schubert 
23265796c8dcSSimon Schubert 		      stridx += namelen + 1;
23275796c8dcSSimon Schubert 		      ++orl_count;
23285796c8dcSSimon Schubert 		    }
23295796c8dcSSimon Schubert 		}
23305796c8dcSSimon Schubert 	    }
23315796c8dcSSimon Schubert 
23325796c8dcSSimon Schubert 	  /* Now ask the BFD to free up any cached information, so we
23335796c8dcSSimon Schubert 	     don't fill all of memory with symbol tables.  */
23345796c8dcSSimon Schubert 	  if (! bfd_free_cached_info (current))
23355796c8dcSSimon Schubert 	    goto error_return;
23365796c8dcSSimon Schubert 	}
23375796c8dcSSimon Schubert     }
23385796c8dcSSimon Schubert 
23395796c8dcSSimon Schubert   /* OK, now we have collected all the data, let's write them out.  */
23405796c8dcSSimon Schubert   ret = BFD_SEND (arch, write_armap,
23415796c8dcSSimon Schubert 		  (arch, elength, map, orl_count, stridx));
23425796c8dcSSimon Schubert 
23435796c8dcSSimon Schubert   if (syms_max > 0)
23445796c8dcSSimon Schubert     free (syms);
23455796c8dcSSimon Schubert   if (map != NULL)
23465796c8dcSSimon Schubert     free (map);
23475796c8dcSSimon Schubert   if (first_name != NULL)
23485796c8dcSSimon Schubert     bfd_release (arch, first_name);
23495796c8dcSSimon Schubert 
23505796c8dcSSimon Schubert   return ret;
23515796c8dcSSimon Schubert 
23525796c8dcSSimon Schubert  error_return:
23535796c8dcSSimon Schubert   if (syms_max > 0)
23545796c8dcSSimon Schubert     free (syms);
23555796c8dcSSimon Schubert   if (map != NULL)
23565796c8dcSSimon Schubert     free (map);
23575796c8dcSSimon Schubert   if (first_name != NULL)
23585796c8dcSSimon Schubert     bfd_release (arch, first_name);
23595796c8dcSSimon Schubert 
23605796c8dcSSimon Schubert   return FALSE;
23615796c8dcSSimon Schubert }
23625796c8dcSSimon Schubert 
23635796c8dcSSimon Schubert bfd_boolean
23645796c8dcSSimon Schubert bsd_write_armap (bfd *arch,
23655796c8dcSSimon Schubert 		 unsigned int elength,
23665796c8dcSSimon Schubert 		 struct orl *map,
23675796c8dcSSimon Schubert 		 unsigned int orl_count,
23685796c8dcSSimon Schubert 		 int stridx)
23695796c8dcSSimon Schubert {
23705796c8dcSSimon Schubert   int padit = stridx & 1;
23715796c8dcSSimon Schubert   unsigned int ranlibsize = orl_count * BSD_SYMDEF_SIZE;
23725796c8dcSSimon Schubert   unsigned int stringsize = stridx + padit;
23735796c8dcSSimon Schubert   /* Include 8 bytes to store ranlibsize and stringsize in output.  */
23745796c8dcSSimon Schubert   unsigned int mapsize = ranlibsize + stringsize + 8;
23755796c8dcSSimon Schubert   file_ptr firstreal;
23765796c8dcSSimon Schubert   bfd *current = arch->archive_head;
23775796c8dcSSimon Schubert   bfd *last_elt = current;	/* Last element arch seen.  */
23785796c8dcSSimon Schubert   bfd_byte temp[4];
23795796c8dcSSimon Schubert   unsigned int count;
23805796c8dcSSimon Schubert   struct ar_hdr hdr;
23815796c8dcSSimon Schubert   long uid, gid;
23825796c8dcSSimon Schubert 
23835796c8dcSSimon Schubert   firstreal = mapsize + elength + sizeof (struct ar_hdr) + SARMAG;
23845796c8dcSSimon Schubert 
23855796c8dcSSimon Schubert   /* If deterministic, we use 0 as the timestamp in the map.
23865796c8dcSSimon Schubert      Some linkers may require that the archive filesystem modification
23875796c8dcSSimon Schubert      time is less than (or near to) the archive map timestamp.  Those
23885796c8dcSSimon Schubert      linkers should not be used with deterministic mode.  (GNU ld and
23895796c8dcSSimon Schubert      Gold do not have this restriction.)  */
23905796c8dcSSimon Schubert   bfd_ardata (arch)->armap_timestamp = 0;
23915796c8dcSSimon Schubert   uid = 0;
23925796c8dcSSimon Schubert   gid = 0;
2393c50c785cSJohn Marino   if ((arch->flags & BFD_DETERMINISTIC_OUTPUT) == 0)
2394c50c785cSJohn Marino     {
2395c50c785cSJohn Marino       struct stat statbuf;
2396c50c785cSJohn Marino 
2397c50c785cSJohn Marino       if (stat (arch->filename, &statbuf) == 0)
2398c50c785cSJohn Marino 	bfd_ardata (arch)->armap_timestamp = (statbuf.st_mtime
2399c50c785cSJohn Marino 					      + ARMAP_TIME_OFFSET);
2400c50c785cSJohn Marino       uid = getuid();
2401c50c785cSJohn Marino       gid = getgid();
24025796c8dcSSimon Schubert     }
24035796c8dcSSimon Schubert 
24045796c8dcSSimon Schubert   memset (&hdr, ' ', sizeof (struct ar_hdr));
24055796c8dcSSimon Schubert   memcpy (hdr.ar_name, RANLIBMAG, strlen (RANLIBMAG));
24065796c8dcSSimon Schubert   bfd_ardata (arch)->armap_datepos = (SARMAG
24075796c8dcSSimon Schubert 				      + offsetof (struct ar_hdr, ar_date[0]));
24085796c8dcSSimon Schubert   _bfd_ar_spacepad (hdr.ar_date, sizeof (hdr.ar_date), "%ld",
24095796c8dcSSimon Schubert                     bfd_ardata (arch)->armap_timestamp);
24105796c8dcSSimon Schubert   _bfd_ar_spacepad (hdr.ar_uid, sizeof (hdr.ar_uid), "%ld", uid);
24115796c8dcSSimon Schubert   _bfd_ar_spacepad (hdr.ar_gid, sizeof (hdr.ar_gid), "%ld", gid);
24125796c8dcSSimon Schubert   _bfd_ar_spacepad (hdr.ar_size, sizeof (hdr.ar_size), "%-10ld", mapsize);
24135796c8dcSSimon Schubert   memcpy (hdr.ar_fmag, ARFMAG, 2);
24145796c8dcSSimon Schubert   if (bfd_bwrite (&hdr, sizeof (struct ar_hdr), arch)
24155796c8dcSSimon Schubert       != sizeof (struct ar_hdr))
24165796c8dcSSimon Schubert     return FALSE;
24175796c8dcSSimon Schubert   H_PUT_32 (arch, ranlibsize, temp);
24185796c8dcSSimon Schubert   if (bfd_bwrite (temp, sizeof (temp), arch) != sizeof (temp))
24195796c8dcSSimon Schubert     return FALSE;
24205796c8dcSSimon Schubert 
24215796c8dcSSimon Schubert   for (count = 0; count < orl_count; count++)
24225796c8dcSSimon Schubert     {
24235796c8dcSSimon Schubert       bfd_byte buf[BSD_SYMDEF_SIZE];
24245796c8dcSSimon Schubert 
24255796c8dcSSimon Schubert       if (map[count].u.abfd != last_elt)
24265796c8dcSSimon Schubert 	{
24275796c8dcSSimon Schubert 	  do
24285796c8dcSSimon Schubert 	    {
2429cf7f2e2dSJohn Marino               struct areltdata *ared = arch_eltdata (current);
2430cf7f2e2dSJohn Marino 
2431cf7f2e2dSJohn Marino 	      firstreal += (ared->parsed_size + ared->extra_size
2432cf7f2e2dSJohn Marino                             + sizeof (struct ar_hdr));
24335796c8dcSSimon Schubert 	      firstreal += firstreal % 2;
24345796c8dcSSimon Schubert 	      current = current->archive_next;
24355796c8dcSSimon Schubert 	    }
24365796c8dcSSimon Schubert 	  while (current != map[count].u.abfd);
24375796c8dcSSimon Schubert 	}
24385796c8dcSSimon Schubert 
24395796c8dcSSimon Schubert       last_elt = current;
24405796c8dcSSimon Schubert       H_PUT_32 (arch, map[count].namidx, buf);
24415796c8dcSSimon Schubert       H_PUT_32 (arch, firstreal, buf + BSD_SYMDEF_OFFSET_SIZE);
24425796c8dcSSimon Schubert       if (bfd_bwrite (buf, BSD_SYMDEF_SIZE, arch)
24435796c8dcSSimon Schubert 	  != BSD_SYMDEF_SIZE)
24445796c8dcSSimon Schubert 	return FALSE;
24455796c8dcSSimon Schubert     }
24465796c8dcSSimon Schubert 
24475796c8dcSSimon Schubert   /* Now write the strings themselves.  */
24485796c8dcSSimon Schubert   H_PUT_32 (arch, stringsize, temp);
24495796c8dcSSimon Schubert   if (bfd_bwrite (temp, sizeof (temp), arch) != sizeof (temp))
24505796c8dcSSimon Schubert     return FALSE;
24515796c8dcSSimon Schubert   for (count = 0; count < orl_count; count++)
24525796c8dcSSimon Schubert     {
24535796c8dcSSimon Schubert       size_t len = strlen (*map[count].name) + 1;
24545796c8dcSSimon Schubert 
24555796c8dcSSimon Schubert       if (bfd_bwrite (*map[count].name, len, arch) != len)
24565796c8dcSSimon Schubert 	return FALSE;
24575796c8dcSSimon Schubert     }
24585796c8dcSSimon Schubert 
24595796c8dcSSimon Schubert   /* The spec sez this should be a newline.  But in order to be
24605796c8dcSSimon Schubert      bug-compatible for sun's ar we use a null.  */
24615796c8dcSSimon Schubert   if (padit)
24625796c8dcSSimon Schubert     {
24635796c8dcSSimon Schubert       if (bfd_bwrite ("", 1, arch) != 1)
24645796c8dcSSimon Schubert 	return FALSE;
24655796c8dcSSimon Schubert     }
24665796c8dcSSimon Schubert 
24675796c8dcSSimon Schubert   return TRUE;
24685796c8dcSSimon Schubert }
24695796c8dcSSimon Schubert 
24705796c8dcSSimon Schubert /* At the end of archive file handling, update the timestamp in the
24715796c8dcSSimon Schubert    file, so the linker will accept it.
24725796c8dcSSimon Schubert 
24735796c8dcSSimon Schubert    Return TRUE if the timestamp was OK, or an unusual problem happened.
24745796c8dcSSimon Schubert    Return FALSE if we updated the timestamp.  */
24755796c8dcSSimon Schubert 
24765796c8dcSSimon Schubert bfd_boolean
24775796c8dcSSimon Schubert _bfd_archive_bsd_update_armap_timestamp (bfd *arch)
24785796c8dcSSimon Schubert {
24795796c8dcSSimon Schubert   struct stat archstat;
24805796c8dcSSimon Schubert   struct ar_hdr hdr;
24815796c8dcSSimon Schubert 
24825796c8dcSSimon Schubert   /* If creating deterministic archives, just leave the timestamp as-is.  */
24835796c8dcSSimon Schubert   if ((arch->flags & BFD_DETERMINISTIC_OUTPUT) != 0)
24845796c8dcSSimon Schubert     return TRUE;
24855796c8dcSSimon Schubert 
24865796c8dcSSimon Schubert   /* Flush writes, get last-write timestamp from file, and compare it
24875796c8dcSSimon Schubert      to the timestamp IN the file.  */
24885796c8dcSSimon Schubert   bfd_flush (arch);
24895796c8dcSSimon Schubert   if (bfd_stat (arch, &archstat) == -1)
24905796c8dcSSimon Schubert     {
24915796c8dcSSimon Schubert       bfd_perror (_("Reading archive file mod timestamp"));
24925796c8dcSSimon Schubert 
24935796c8dcSSimon Schubert       /* Can't read mod time for some reason.  */
24945796c8dcSSimon Schubert       return TRUE;
24955796c8dcSSimon Schubert     }
24965796c8dcSSimon Schubert   if (((long) archstat.st_mtime) <= bfd_ardata (arch)->armap_timestamp)
24975796c8dcSSimon Schubert     /* OK by the linker's rules.  */
24985796c8dcSSimon Schubert     return TRUE;
24995796c8dcSSimon Schubert 
25005796c8dcSSimon Schubert   /* Update the timestamp.  */
25015796c8dcSSimon Schubert   bfd_ardata (arch)->armap_timestamp = archstat.st_mtime + ARMAP_TIME_OFFSET;
25025796c8dcSSimon Schubert 
25035796c8dcSSimon Schubert   /* Prepare an ASCII version suitable for writing.  */
25045796c8dcSSimon Schubert   memset (hdr.ar_date, ' ', sizeof (hdr.ar_date));
25055796c8dcSSimon Schubert   _bfd_ar_spacepad (hdr.ar_date, sizeof (hdr.ar_date), "%ld",
25065796c8dcSSimon Schubert                     bfd_ardata (arch)->armap_timestamp);
25075796c8dcSSimon Schubert 
25085796c8dcSSimon Schubert   /* Write it into the file.  */
25095796c8dcSSimon Schubert   bfd_ardata (arch)->armap_datepos = (SARMAG
25105796c8dcSSimon Schubert 				      + offsetof (struct ar_hdr, ar_date[0]));
25115796c8dcSSimon Schubert   if (bfd_seek (arch, bfd_ardata (arch)->armap_datepos, SEEK_SET) != 0
25125796c8dcSSimon Schubert       || (bfd_bwrite (hdr.ar_date, sizeof (hdr.ar_date), arch)
25135796c8dcSSimon Schubert 	  != sizeof (hdr.ar_date)))
25145796c8dcSSimon Schubert     {
25155796c8dcSSimon Schubert       bfd_perror (_("Writing updated armap timestamp"));
25165796c8dcSSimon Schubert 
25175796c8dcSSimon Schubert       /* Some error while writing.  */
25185796c8dcSSimon Schubert       return TRUE;
25195796c8dcSSimon Schubert     }
25205796c8dcSSimon Schubert 
25215796c8dcSSimon Schubert   /* We updated the timestamp successfully.  */
25225796c8dcSSimon Schubert   return FALSE;
25235796c8dcSSimon Schubert }
25245796c8dcSSimon Schubert 
25255796c8dcSSimon Schubert /* A coff armap looks like :
25265796c8dcSSimon Schubert    lARMAG
25275796c8dcSSimon Schubert    struct ar_hdr with name = '/'
25285796c8dcSSimon Schubert    number of symbols
25295796c8dcSSimon Schubert    offset of file for symbol 0
25305796c8dcSSimon Schubert    offset of file for symbol 1
25315796c8dcSSimon Schubert 
25325796c8dcSSimon Schubert    offset of file for symbol n-1
25335796c8dcSSimon Schubert    symbol name 0
25345796c8dcSSimon Schubert    symbol name 1
25355796c8dcSSimon Schubert 
25365796c8dcSSimon Schubert    symbol name n-1  */
25375796c8dcSSimon Schubert 
25385796c8dcSSimon Schubert bfd_boolean
25395796c8dcSSimon Schubert coff_write_armap (bfd *arch,
25405796c8dcSSimon Schubert 		  unsigned int elength,
25415796c8dcSSimon Schubert 		  struct orl *map,
25425796c8dcSSimon Schubert 		  unsigned int symbol_count,
25435796c8dcSSimon Schubert 		  int stridx)
25445796c8dcSSimon Schubert {
25455796c8dcSSimon Schubert   /* The size of the ranlib is the number of exported symbols in the
25465796c8dcSSimon Schubert      archive * the number of bytes in an int, + an int for the count.  */
25475796c8dcSSimon Schubert   unsigned int ranlibsize = (symbol_count * 4) + 4;
25485796c8dcSSimon Schubert   unsigned int stringsize = stridx;
25495796c8dcSSimon Schubert   unsigned int mapsize = stringsize + ranlibsize;
25505796c8dcSSimon Schubert   unsigned int archive_member_file_ptr;
25515796c8dcSSimon Schubert   bfd *current = arch->archive_head;
25525796c8dcSSimon Schubert   unsigned int count;
25535796c8dcSSimon Schubert   struct ar_hdr hdr;
25545796c8dcSSimon Schubert   int padit = mapsize & 1;
25555796c8dcSSimon Schubert 
25565796c8dcSSimon Schubert   if (padit)
25575796c8dcSSimon Schubert     mapsize++;
25585796c8dcSSimon Schubert 
25595796c8dcSSimon Schubert   /* Work out where the first object file will go in the archive.  */
25605796c8dcSSimon Schubert   archive_member_file_ptr = (mapsize
25615796c8dcSSimon Schubert 			     + elength
25625796c8dcSSimon Schubert 			     + sizeof (struct ar_hdr)
25635796c8dcSSimon Schubert 			     + SARMAG);
25645796c8dcSSimon Schubert 
25655796c8dcSSimon Schubert   memset (&hdr, ' ', sizeof (struct ar_hdr));
25665796c8dcSSimon Schubert   hdr.ar_name[0] = '/';
25675796c8dcSSimon Schubert   _bfd_ar_spacepad (hdr.ar_size, sizeof (hdr.ar_size), "%-10ld",
25685796c8dcSSimon Schubert                     mapsize);
25695796c8dcSSimon Schubert   _bfd_ar_spacepad (hdr.ar_date, sizeof (hdr.ar_date), "%ld",
25705796c8dcSSimon Schubert                     ((arch->flags & BFD_DETERMINISTIC_OUTPUT) == 0
25715796c8dcSSimon Schubert                      ? time (NULL) : 0));
25725796c8dcSSimon Schubert   /* This, at least, is what Intel coff sets the values to.  */
25735796c8dcSSimon Schubert   _bfd_ar_spacepad (hdr.ar_uid, sizeof (hdr.ar_uid), "%ld", 0);
25745796c8dcSSimon Schubert   _bfd_ar_spacepad (hdr.ar_gid, sizeof (hdr.ar_gid), "%ld", 0);
25755796c8dcSSimon Schubert   _bfd_ar_spacepad (hdr.ar_mode, sizeof (hdr.ar_mode), "%-7lo", 0);
25765796c8dcSSimon Schubert   memcpy (hdr.ar_fmag, ARFMAG, 2);
25775796c8dcSSimon Schubert 
25785796c8dcSSimon Schubert   /* Write the ar header for this item and the number of symbols.  */
25795796c8dcSSimon Schubert   if (bfd_bwrite (&hdr, sizeof (struct ar_hdr), arch)
25805796c8dcSSimon Schubert       != sizeof (struct ar_hdr))
25815796c8dcSSimon Schubert     return FALSE;
25825796c8dcSSimon Schubert 
25835796c8dcSSimon Schubert   if (!bfd_write_bigendian_4byte_int (arch, symbol_count))
25845796c8dcSSimon Schubert     return FALSE;
25855796c8dcSSimon Schubert 
25865796c8dcSSimon Schubert   /* Two passes, first write the file offsets for each symbol -
25875796c8dcSSimon Schubert      remembering that each offset is on a two byte boundary.  */
25885796c8dcSSimon Schubert 
25895796c8dcSSimon Schubert   /* Write out the file offset for the file associated with each
25905796c8dcSSimon Schubert      symbol, and remember to keep the offsets padded out.  */
25915796c8dcSSimon Schubert 
25925796c8dcSSimon Schubert   current = arch->archive_head;
25935796c8dcSSimon Schubert   count = 0;
25945796c8dcSSimon Schubert   while (current != NULL && count < symbol_count)
25955796c8dcSSimon Schubert     {
25965796c8dcSSimon Schubert       /* For each symbol which is used defined in this object, write
25975796c8dcSSimon Schubert 	 out the object file's address in the archive.  */
25985796c8dcSSimon Schubert 
25995796c8dcSSimon Schubert       while (count < symbol_count && map[count].u.abfd == current)
26005796c8dcSSimon Schubert 	{
26015796c8dcSSimon Schubert 	  if (!bfd_write_bigendian_4byte_int (arch, archive_member_file_ptr))
26025796c8dcSSimon Schubert 	    return FALSE;
26035796c8dcSSimon Schubert 	  count++;
26045796c8dcSSimon Schubert 	}
26055796c8dcSSimon Schubert       archive_member_file_ptr += sizeof (struct ar_hdr);
26065796c8dcSSimon Schubert       if (! bfd_is_thin_archive (arch))
26075796c8dcSSimon Schubert         {
26085796c8dcSSimon Schubert           /* Add size of this archive entry.  */
26095796c8dcSSimon Schubert           archive_member_file_ptr += arelt_size (current);
26105796c8dcSSimon Schubert           /* Remember about the even alignment.  */
26115796c8dcSSimon Schubert           archive_member_file_ptr += archive_member_file_ptr % 2;
26125796c8dcSSimon Schubert         }
26135796c8dcSSimon Schubert       current = current->archive_next;
26145796c8dcSSimon Schubert     }
26155796c8dcSSimon Schubert 
26165796c8dcSSimon Schubert   /* Now write the strings themselves.  */
26175796c8dcSSimon Schubert   for (count = 0; count < symbol_count; count++)
26185796c8dcSSimon Schubert     {
26195796c8dcSSimon Schubert       size_t len = strlen (*map[count].name) + 1;
26205796c8dcSSimon Schubert 
26215796c8dcSSimon Schubert       if (bfd_bwrite (*map[count].name, len, arch) != len)
26225796c8dcSSimon Schubert 	return FALSE;
26235796c8dcSSimon Schubert     }
26245796c8dcSSimon Schubert 
26255796c8dcSSimon Schubert   /* The spec sez this should be a newline.  But in order to be
26265796c8dcSSimon Schubert      bug-compatible for arc960 we use a null.  */
26275796c8dcSSimon Schubert   if (padit)
26285796c8dcSSimon Schubert     {
26295796c8dcSSimon Schubert       if (bfd_bwrite ("", 1, arch) != 1)
26305796c8dcSSimon Schubert 	return FALSE;
26315796c8dcSSimon Schubert     }
26325796c8dcSSimon Schubert 
26335796c8dcSSimon Schubert   return TRUE;
26345796c8dcSSimon Schubert }
2635