133965Sjdp/* BFD back-end for archive files (libraries).
278828Sobrien   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3218822Sdim   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
438889Sjdp   Free Software Foundation, Inc.
533965Sjdp   Written by Cygnus Support.  Mostly Gumby Henkel-Wallace's fault.
633965Sjdp
7218822Sdim   This file is part of BFD, the Binary File Descriptor library.
833965Sjdp
9218822Sdim   This program is free software; you can redistribute it and/or modify
10218822Sdim   it under the terms of the GNU General Public License as published by
11218822Sdim   the Free Software Foundation; either version 2 of the License, or
12218822Sdim   (at your option) any later version.
1333965Sjdp
14218822Sdim   This program is distributed in the hope that it will be useful,
15218822Sdim   but WITHOUT ANY WARRANTY; without even the implied warranty of
16218822Sdim   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17218822Sdim   GNU General Public License for more details.
1833965Sjdp
19218822Sdim   You should have received a copy of the GNU General Public License
20218822Sdim   along with this program; if not, write to the Free Software
21218822Sdim   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
2233965Sjdp
2333965Sjdp/*
2433965Sjdp@setfilename archive-info
2533965SjdpSECTION
2633965Sjdp	Archives
2733965Sjdp
2833965SjdpDESCRIPTION
2933965Sjdp	An archive (or library) is just another BFD.  It has a symbol
3033965Sjdp	table, although there's not much a user program will do with it.
3133965Sjdp
3233965Sjdp	The big difference between an archive BFD and an ordinary BFD
3333965Sjdp	is that the archive doesn't have sections.  Instead it has a
3433965Sjdp	chain of BFDs that are considered its contents.  These BFDs can
3533965Sjdp	be manipulated like any other.  The BFDs contained in an
3633965Sjdp	archive opened for reading will all be opened for reading.  You
3733965Sjdp	may put either input or output BFDs into an archive opened for
3833965Sjdp	output; they will be handled correctly when the archive is closed.
3933965Sjdp
4033965Sjdp	Use <<bfd_openr_next_archived_file>> to step through
4133965Sjdp	the contents of an archive opened for input.  You don't
4233965Sjdp	have to read the entire archive if you don't want
4333965Sjdp	to!  Read it until you find what you want.
4433965Sjdp
4533965Sjdp	Archive contents of output BFDs are chained through the
4633965Sjdp	<<next>> pointer in a BFD.  The first one is findable through
4733965Sjdp	the <<archive_head>> slot of the archive.  Set it with
4833965Sjdp	<<bfd_set_archive_head>> (q.v.).  A given BFD may be in only one
4933965Sjdp	open output archive at a time.
5033965Sjdp
5133965Sjdp	As expected, the BFD archive code is more general than the
5233965Sjdp	archive code of any given environment.  BFD archives may
5333965Sjdp	contain files of different formats (e.g., a.out and coff) and
5433965Sjdp	even different architectures.  You may even place archives
5533965Sjdp	recursively into archives!
5633965Sjdp
5733965Sjdp	This can cause unexpected confusion, since some archive
5833965Sjdp	formats are more expressive than others.  For instance, Intel
5933965Sjdp	COFF archives can preserve long filenames; SunOS a.out archives
6033965Sjdp	cannot.  If you move a file from the first to the second
6133965Sjdp	format and back again, the filename may be truncated.
6233965Sjdp	Likewise, different a.out environments have different
6333965Sjdp	conventions as to how they truncate filenames, whether they
6433965Sjdp	preserve directory names in filenames, etc.  When
6533965Sjdp	interoperating with native tools, be sure your files are
6633965Sjdp	homogeneous.
6733965Sjdp
6833965Sjdp	Beware: most of these formats do not react well to the
6933965Sjdp	presence of spaces in filenames.  We do the best we can, but
7033965Sjdp	can't always handle this case due to restrictions in the format of
7133965Sjdp	archives.  Many Unix utilities are braindead in regards to
7233965Sjdp	spaces and such in filenames anyway, so this shouldn't be much
7333965Sjdp	of a restriction.
7433965Sjdp
7533965Sjdp	Archives are supported in BFD in <<archive.c>>.
7633965Sjdp
77218822SdimSUBSECTION
78218822Sdim	Archive functions
7933965Sjdp*/
8033965Sjdp
8133965Sjdp/* Assumes:
8233965Sjdp   o - all archive elements start on an even boundary, newline padded;
8333965Sjdp   o - all arch headers are char *;
8433965Sjdp   o - all arch headers are the same size (across architectures).
8533965Sjdp*/
8633965Sjdp
8733965Sjdp/* Some formats provide a way to cram a long filename into the short
8833965Sjdp   (16 chars) space provided by a BSD archive.  The trick is: make a
8933965Sjdp   special "file" in the front of the archive, sort of like the SYMDEF
9033965Sjdp   entry.  If the filename is too long to fit, put it in the extended
9133965Sjdp   name table, and use its index as the filename.  To prevent
9233965Sjdp   confusion prepend the index with a space.  This means you can't
9333965Sjdp   have filenames that start with a space, but then again, many Unix
9433965Sjdp   utilities can't handle that anyway.
9533965Sjdp
9633965Sjdp   This scheme unfortunately requires that you stand on your head in
9733965Sjdp   order to write an archive since you need to put a magic file at the
9833965Sjdp   front, and need to touch every entry to do so.  C'est la vie.
9933965Sjdp
10033965Sjdp   We support two variants of this idea:
10133965Sjdp   The SVR4 format (extended name table is named "//"),
10233965Sjdp   and an extended pseudo-BSD variant (extended name table is named
10333965Sjdp   "ARFILENAMES/").  The origin of the latter format is uncertain.
10433965Sjdp
10533965Sjdp   BSD 4.4 uses a third scheme:  It writes a long filename
10633965Sjdp   directly after the header.  This allows 'ar q' to work.
10733965Sjdp   We currently can read BSD 4.4 archives, but not write them.
10833965Sjdp*/
10933965Sjdp
11033965Sjdp/* Summary of archive member names:
11133965Sjdp
11233965Sjdp Symbol table (must be first):
11333965Sjdp "__.SYMDEF       " - Symbol table, Berkeley style, produced by ranlib.
11433965Sjdp "/               " - Symbol table, system 5 style.
11533965Sjdp
11633965Sjdp Long name table (must be before regular file members):
11733965Sjdp "//              " - Long name table, System 5 R4 style.
11833965Sjdp "ARFILENAMES/    " - Long name table, non-standard extended BSD (not BSD 4.4).
11933965Sjdp
12033965Sjdp Regular file members with short names:
12133965Sjdp "filename.o/     " - Regular file, System 5 style (embedded spaces ok).
12233965Sjdp "filename.o      " - Regular file, Berkeley style (no embedded spaces).
12333965Sjdp
12433965Sjdp Regular files with long names (or embedded spaces, for BSD variants):
12533965Sjdp "/18             " - SVR4 style, name at offset 18 in name table.
126218822Sdim "#1/23           " - Long name (or embedded spaces) 23 characters long,
12733965Sjdp		      BSD 4.4 style, full name follows header.
12833965Sjdp		      Implemented for reading, not writing.
12933965Sjdp " 18             " - Long name 18 characters long, extended pseudo-BSD.
13033965Sjdp */
13133965Sjdp
132218822Sdim#include "sysdep.h"
13333965Sjdp#include "bfd.h"
134218822Sdim#include "libiberty.h"
13533965Sjdp#include "libbfd.h"
13633965Sjdp#include "aout/ar.h"
13733965Sjdp#include "aout/ranlib.h"
13889857Sobrien#include "safe-ctype.h"
139218822Sdim#include "hashtab.h"
14033965Sjdp
14133965Sjdp#ifndef errno
14233965Sjdpextern int errno;
14333965Sjdp#endif
14433965Sjdp
14533965Sjdp/* We keep a cache of archive filepointers to archive elements to
14633965Sjdp   speed up searching the archive by filepos.  We only add an entry to
14733965Sjdp   the cache when we actually read one.  We also don't sort the cache;
14833965Sjdp   it's generally short enough to search linearly.
14933965Sjdp   Note that the pointers here point to the front of the ar_hdr, not
15077298Sobrien   to the front of the contents!  */
15177298Sobrienstruct ar_cache {
15233965Sjdp  file_ptr ptr;
153218822Sdim  bfd *arbfd;
15433965Sjdp};
15533965Sjdp
15633965Sjdp#define ar_padchar(abfd) ((abfd)->xvec->ar_pad_char)
15733965Sjdp#define ar_maxnamelen(abfd) ((abfd)->xvec->ar_max_namelen)
15833965Sjdp
15977298Sobrien#define arch_eltdata(bfd) ((struct areltdata *) ((bfd)->arelt_data))
160130561Sobrien#define arch_hdr(bfd) ((struct ar_hdr *) arch_eltdata(bfd)->arch_header)
16133965Sjdp
162218822Sdimvoid
163218822Sdim_bfd_ar_spacepad (char *p, size_t n, const char *fmt, long val)
164218822Sdim{
165218822Sdim  static char buf[20];
166218822Sdim  size_t len;
167218822Sdim  snprintf (buf, sizeof (buf), fmt, val);
168218822Sdim  len = strlen (buf);
169218822Sdim  if (len < n)
170218822Sdim    {
171218822Sdim      memcpy (p, buf, len);
172218822Sdim      memset (p + len, ' ', n - len);
173218822Sdim    }
174218822Sdim  else
175218822Sdim    memcpy (p, buf, n);
176218822Sdim}
177218822Sdim
178130561Sobrienbfd_boolean
179130561Sobrien_bfd_generic_mkarchive (bfd *abfd)
18033965Sjdp{
18189857Sobrien  bfd_size_type amt = sizeof (struct artdata);
18233965Sjdp
183130561Sobrien  abfd->tdata.aout_ar_data = bfd_zalloc (abfd, amt);
18433965Sjdp  if (bfd_ardata (abfd) == NULL)
185130561Sobrien    return FALSE;
18633965Sjdp
187218822Sdim  /* Already cleared by bfd_zalloc above.
188218822Sdim     bfd_ardata (abfd)->cache = NULL;
189218822Sdim     bfd_ardata (abfd)->archive_head = NULL;
190218822Sdim     bfd_ardata (abfd)->symdefs = NULL;
191218822Sdim     bfd_ardata (abfd)->extended_names = NULL;
192218822Sdim     bfd_ardata (abfd)->extended_names_size = 0;
193218822Sdim     bfd_ardata (abfd)->tdata = NULL;  */
19433965Sjdp
195130561Sobrien  return TRUE;
19633965Sjdp}
19733965Sjdp
19833965Sjdp/*
19933965SjdpFUNCTION
20033965Sjdp	bfd_get_next_mapent
20133965Sjdp
20233965SjdpSYNOPSIS
203130561Sobrien	symindex bfd_get_next_mapent
204130561Sobrien	  (bfd *abfd, symindex previous, carsym **sym);
20533965Sjdp
20633965SjdpDESCRIPTION
20733965Sjdp	Step through archive @var{abfd}'s symbol table (if it
20833965Sjdp	has one).  Successively update @var{sym} with the next symbol's
20933965Sjdp	information, returning that symbol's (internal) index into the
21033965Sjdp	symbol table.
21133965Sjdp
21233965Sjdp	Supply <<BFD_NO_MORE_SYMBOLS>> as the @var{previous} entry to get
21333965Sjdp	the first one; returns <<BFD_NO_MORE_SYMBOLS>> when you've already
21433965Sjdp	got the last one.
21533965Sjdp
21633965Sjdp	A <<carsym>> is a canonical archive symbol.  The only
21733965Sjdp	user-visible element is its name, a null-terminated string.
21833965Sjdp*/
21933965Sjdp
22033965Sjdpsymindex
221130561Sobrienbfd_get_next_mapent (bfd *abfd, symindex prev, carsym **entry)
22233965Sjdp{
22333965Sjdp  if (!bfd_has_map (abfd))
22433965Sjdp    {
22533965Sjdp      bfd_set_error (bfd_error_invalid_operation);
22633965Sjdp      return BFD_NO_MORE_SYMBOLS;
22733965Sjdp    }
22833965Sjdp
22933965Sjdp  if (prev == BFD_NO_MORE_SYMBOLS)
23033965Sjdp    prev = 0;
23133965Sjdp  else
23233965Sjdp    ++prev;
23333965Sjdp  if (prev >= bfd_ardata (abfd)->symdef_count)
23433965Sjdp    return BFD_NO_MORE_SYMBOLS;
23533965Sjdp
23633965Sjdp  *entry = (bfd_ardata (abfd)->symdefs + prev);
23733965Sjdp  return prev;
23833965Sjdp}
23933965Sjdp
240218822Sdim/* To be called by backends only.  */
24133965Sjdp
24233965Sjdpbfd *
243130561Sobrien_bfd_create_empty_archive_element_shell (bfd *obfd)
24433965Sjdp{
24533965Sjdp  return _bfd_new_bfd_contained_in (obfd);
24633965Sjdp}
24733965Sjdp
24833965Sjdp/*
24933965SjdpFUNCTION
25033965Sjdp	bfd_set_archive_head
25133965Sjdp
25233965SjdpSYNOPSIS
253130561Sobrien	bfd_boolean bfd_set_archive_head (bfd *output, bfd *new_head);
25433965Sjdp
25533965SjdpDESCRIPTION
25633965Sjdp	Set the head of the chain of
25733965Sjdp	BFDs contained in the archive @var{output} to @var{new_head}.
25833965Sjdp*/
25933965Sjdp
260130561Sobrienbfd_boolean
261130561Sobrienbfd_set_archive_head (bfd *output_archive, bfd *new_head)
26233965Sjdp{
26333965Sjdp  output_archive->archive_head = new_head;
264130561Sobrien  return TRUE;
26533965Sjdp}
26633965Sjdp
26733965Sjdpbfd *
268130561Sobrien_bfd_look_for_bfd_in_cache (bfd *arch_bfd, file_ptr filepos)
26933965Sjdp{
270218822Sdim  htab_t hash_table = bfd_ardata (arch_bfd)->cache;
271218822Sdim  struct ar_cache m;
272218822Sdim  m.ptr = filepos;
27333965Sjdp
274218822Sdim  if (hash_table)
275218822Sdim    {
276218822Sdim      struct ar_cache *entry = (struct ar_cache *) htab_find (hash_table, &m);
277218822Sdim      if (!entry)
278218822Sdim	return NULL;
279218822Sdim      else
280218822Sdim	return entry->arbfd;
281218822Sdim    }
282218822Sdim  else
283218822Sdim    return NULL;
284218822Sdim}
28533965Sjdp
286218822Sdimstatic hashval_t
287218822Sdimhash_file_ptr (const PTR p)
288218822Sdim{
289218822Sdim  return (hashval_t) (((struct ar_cache *) p)->ptr);
29033965Sjdp}
29133965Sjdp
292218822Sdim/* Returns non-zero if P1 and P2 are equal.  */
293218822Sdim
294218822Sdimstatic int
295218822Sdimeq_file_ptr (const PTR p1, const PTR p2)
296218822Sdim{
297218822Sdim  struct ar_cache *arc1 = (struct ar_cache *) p1;
298218822Sdim  struct ar_cache *arc2 = (struct ar_cache *) p2;
299218822Sdim  return arc1->ptr == arc2->ptr;
300218822Sdim}
301218822Sdim
302218822Sdim/* Kind of stupid to call cons for each one, but we don't do too many.  */
303218822Sdim
304130561Sobrienbfd_boolean
305130561Sobrien_bfd_add_bfd_to_archive_cache (bfd *arch_bfd, file_ptr filepos, bfd *new_elt)
30633965Sjdp{
307218822Sdim  struct ar_cache *cache;
308218822Sdim  htab_t hash_table = bfd_ardata (arch_bfd)->cache;
30933965Sjdp
310218822Sdim  /* If the hash table hasn't been created, create it.  */
311218822Sdim  if (hash_table == NULL)
31233965Sjdp    {
313218822Sdim      hash_table = htab_create_alloc (16, hash_file_ptr, eq_file_ptr,
314218822Sdim				      NULL, calloc, free);
315218822Sdim      if (hash_table == NULL)
316218822Sdim	return FALSE;
317218822Sdim      bfd_ardata (arch_bfd)->cache = hash_table;
31833965Sjdp    }
31933965Sjdp
320218822Sdim  /* Insert new_elt into the hash table by filepos.  */
321218822Sdim  cache = bfd_zalloc (arch_bfd, sizeof (struct ar_cache));
322218822Sdim  cache->ptr = filepos;
323218822Sdim  cache->arbfd = new_elt;
324218822Sdim  *htab_find_slot (hash_table, (const void *) cache, INSERT) = cache;
325218822Sdim
326130561Sobrien  return TRUE;
32733965Sjdp}
32833965Sjdp
32933965Sjdp/* The name begins with space.  Hence the rest of the name is an index into
33077298Sobrien   the string table.  */
33133965Sjdp
33233965Sjdpstatic char *
333130561Sobrienget_extended_arelt_filename (bfd *arch, const char *name)
33433965Sjdp{
33533965Sjdp  unsigned long index = 0;
33633965Sjdp
33733965Sjdp  /* Should extract string so that I can guarantee not to overflow into
33877298Sobrien     the next region, but I'm too lazy.  */
33933965Sjdp  errno = 0;
34077298Sobrien  /* Skip first char, which is '/' in SVR4 or ' ' in some other variants.  */
34133965Sjdp  index = strtol (name + 1, NULL, 10);
342218822Sdim  if (errno != 0 || index >= bfd_ardata (arch)->extended_names_size)
34333965Sjdp    {
34433965Sjdp      bfd_set_error (bfd_error_malformed_archive);
34533965Sjdp      return NULL;
34633965Sjdp    }
34733965Sjdp
34833965Sjdp  return bfd_ardata (arch)->extended_names + index;
34933965Sjdp}
35033965Sjdp
35133965Sjdp/* This functions reads an arch header and returns an areltdata pointer, or
35233965Sjdp   NULL on error.
35333965Sjdp
35433965Sjdp   Presumes the file pointer is already in the right place (ie pointing
35533965Sjdp   to the ar_hdr in the file).   Moves the file pointer; on success it
35633965Sjdp   should be pointing to the front of the file contents; on failure it
357218822Sdim   could have been moved arbitrarily.  */
35833965Sjdp
359130561Sobrienvoid *
360130561Sobrien_bfd_generic_read_ar_hdr (bfd *abfd)
36133965Sjdp{
362130561Sobrien  return _bfd_generic_read_ar_hdr_mag (abfd, NULL);
36333965Sjdp}
36433965Sjdp
36533965Sjdp/* Alpha ECOFF uses an optional different ARFMAG value, so we have a
36633965Sjdp   variant of _bfd_generic_read_ar_hdr which accepts a magic string.  */
36733965Sjdp
368130561Sobrienvoid *
369130561Sobrien_bfd_generic_read_ar_hdr_mag (bfd *abfd, const char *mag)
37033965Sjdp{
37133965Sjdp  struct ar_hdr hdr;
37233965Sjdp  char *hdrp = (char *) &hdr;
37389857Sobrien  size_t parsed_size;
37433965Sjdp  struct areltdata *ared;
37533965Sjdp  char *filename = NULL;
37689857Sobrien  bfd_size_type namelen = 0;
37789857Sobrien  bfd_size_type allocsize = sizeof (struct areltdata) + sizeof (struct ar_hdr);
37833965Sjdp  char *allocptr = 0;
37933965Sjdp
380130561Sobrien  if (bfd_bread (hdrp, sizeof (struct ar_hdr), abfd) != sizeof (struct ar_hdr))
38133965Sjdp    {
38233965Sjdp      if (bfd_get_error () != bfd_error_system_call)
38333965Sjdp	bfd_set_error (bfd_error_no_more_archived_files);
38433965Sjdp      return NULL;
38533965Sjdp    }
38633965Sjdp  if (strncmp (hdr.ar_fmag, ARFMAG, 2) != 0
38733965Sjdp      && (mag == NULL
38833965Sjdp	  || strncmp (hdr.ar_fmag, mag, 2) != 0))
38933965Sjdp    {
39033965Sjdp      bfd_set_error (bfd_error_malformed_archive);
39133965Sjdp      return NULL;
39233965Sjdp    }
39333965Sjdp
39433965Sjdp  errno = 0;
39533965Sjdp  parsed_size = strtol (hdr.ar_size, NULL, 10);
39633965Sjdp  if (errno != 0)
39733965Sjdp    {
39833965Sjdp      bfd_set_error (bfd_error_malformed_archive);
39933965Sjdp      return NULL;
40033965Sjdp    }
40133965Sjdp
40233965Sjdp  /* Extract the filename from the archive - there are two ways to
40360484Sobrien     specify an extended name table, either the first char of the
40433965Sjdp     name is a space, or it's a slash.  */
40533965Sjdp  if ((hdr.ar_name[0] == '/'
40633965Sjdp       || (hdr.ar_name[0] == ' '
40733965Sjdp	   && memchr (hdr.ar_name, '/', ar_maxnamelen (abfd)) == NULL))
40833965Sjdp      && bfd_ardata (abfd)->extended_names != NULL)
40933965Sjdp    {
41033965Sjdp      filename = get_extended_arelt_filename (abfd, hdr.ar_name);
41133965Sjdp      if (filename == NULL)
412218822Sdim	return NULL;
41333965Sjdp    }
41433965Sjdp  /* BSD4.4-style long filename.
41577298Sobrien     Only implemented for reading, so far!  */
41638889Sjdp  else if (hdr.ar_name[0] == '#'
41738889Sjdp	   && hdr.ar_name[1] == '1'
41838889Sjdp	   && hdr.ar_name[2] == '/'
41989857Sobrien	   && ISDIGIT (hdr.ar_name[3]))
42033965Sjdp    {
42133965Sjdp      /* BSD-4.4 extended name */
42233965Sjdp      namelen = atoi (&hdr.ar_name[3]);
42333965Sjdp      allocsize += namelen + 1;
42433965Sjdp      parsed_size -= namelen;
42533965Sjdp
42633965Sjdp      allocptr = bfd_zalloc (abfd, allocsize);
42733965Sjdp      if (allocptr == NULL)
42833965Sjdp	return NULL;
42933965Sjdp      filename = (allocptr
43033965Sjdp		  + sizeof (struct areltdata)
43133965Sjdp		  + sizeof (struct ar_hdr));
43289857Sobrien      if (bfd_bread (filename, namelen, abfd) != namelen)
43333965Sjdp	{
43433965Sjdp	  if (bfd_get_error () != bfd_error_system_call)
43533965Sjdp	    bfd_set_error (bfd_error_no_more_archived_files);
43633965Sjdp	  return NULL;
43733965Sjdp	}
43833965Sjdp      filename[namelen] = '\0';
43933965Sjdp    }
44033965Sjdp  else
44133965Sjdp    {
44233965Sjdp      /* We judge the end of the name by looking for '/' or ' '.
44333965Sjdp	 Note:  The SYSV format (terminated by '/') allows embedded
44477298Sobrien	 spaces, so only look for ' ' if we don't find '/'.  */
44533965Sjdp
44660484Sobrien      char *e;
447130561Sobrien      e = memchr (hdr.ar_name, '\0', ar_maxnamelen (abfd));
44860484Sobrien      if (e == NULL)
44933965Sjdp	{
450130561Sobrien	  e = memchr (hdr.ar_name, '/', ar_maxnamelen (abfd));
45160484Sobrien	  if (e == NULL)
452130561Sobrien	    e = memchr (hdr.ar_name, ' ', ar_maxnamelen (abfd));
45333965Sjdp	}
45433965Sjdp
45560484Sobrien      if (e != NULL)
45660484Sobrien	namelen = e - hdr.ar_name;
45760484Sobrien      else
45860484Sobrien	{
45960484Sobrien	  /* If we didn't find a termination character, then the name
46060484Sobrien	     must be the entire field.  */
46160484Sobrien	  namelen = ar_maxnamelen (abfd);
46260484Sobrien	}
46360484Sobrien
46433965Sjdp      allocsize += namelen + 1;
46533965Sjdp    }
46633965Sjdp
46733965Sjdp  if (!allocptr)
46833965Sjdp    {
46933965Sjdp      allocptr = bfd_zalloc (abfd, allocsize);
47033965Sjdp      if (allocptr == NULL)
47133965Sjdp	return NULL;
47233965Sjdp    }
47333965Sjdp
47433965Sjdp  ared = (struct areltdata *) allocptr;
47533965Sjdp
47633965Sjdp  ared->arch_header = allocptr + sizeof (struct areltdata);
477130561Sobrien  memcpy (ared->arch_header, &hdr, sizeof (struct ar_hdr));
47833965Sjdp  ared->parsed_size = parsed_size;
47933965Sjdp
48033965Sjdp  if (filename != NULL)
48133965Sjdp    ared->filename = filename;
48233965Sjdp  else
48333965Sjdp    {
48433965Sjdp      ared->filename = allocptr + (sizeof (struct areltdata) +
48533965Sjdp				   sizeof (struct ar_hdr));
48633965Sjdp      if (namelen)
487130561Sobrien	memcpy (ared->filename, hdr.ar_name, namelen);
48833965Sjdp      ared->filename[namelen] = '\0';
48933965Sjdp    }
49033965Sjdp
491130561Sobrien  return ared;
49233965Sjdp}
49333965Sjdp
49433965Sjdp/* This is an internal function; it's mainly used when indexing
49533965Sjdp   through the archive symbol table, but also used to get the next
49633965Sjdp   element, since it handles the bookkeeping so nicely for us.  */
49733965Sjdp
49833965Sjdpbfd *
499130561Sobrien_bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos)
50033965Sjdp{
50133965Sjdp  struct areltdata *new_areldata;
50233965Sjdp  bfd *n_nfd;
50333965Sjdp
504218822Sdim  if (archive->my_archive)
505218822Sdim    {
506218822Sdim      filepos += archive->origin;
507218822Sdim      archive = archive->my_archive;
508218822Sdim    }
509218822Sdim
51033965Sjdp  n_nfd = _bfd_look_for_bfd_in_cache (archive, filepos);
51133965Sjdp  if (n_nfd)
51233965Sjdp    return n_nfd;
51333965Sjdp
51433965Sjdp  if (0 > bfd_seek (archive, filepos, SEEK_SET))
51533965Sjdp    return NULL;
51633965Sjdp
517130561Sobrien  if ((new_areldata = _bfd_read_ar_hdr (archive)) == NULL)
51833965Sjdp    return NULL;
51933965Sjdp
52033965Sjdp  n_nfd = _bfd_create_empty_archive_element_shell (archive);
52133965Sjdp  if (n_nfd == NULL)
52233965Sjdp    {
523130561Sobrien      bfd_release (archive, new_areldata);
52433965Sjdp      return NULL;
52533965Sjdp    }
52633965Sjdp
52733965Sjdp  n_nfd->origin = bfd_tell (archive);
528130561Sobrien  n_nfd->arelt_data = new_areldata;
52933965Sjdp  n_nfd->filename = new_areldata->filename;
53033965Sjdp
53133965Sjdp  if (_bfd_add_bfd_to_archive_cache (archive, filepos, n_nfd))
53233965Sjdp    return n_nfd;
53333965Sjdp
53477298Sobrien  /* Huh?  */
535130561Sobrien  bfd_release (archive, n_nfd);
536130561Sobrien  bfd_release (archive, new_areldata);
53733965Sjdp  return NULL;
53833965Sjdp}
53933965Sjdp
54033965Sjdp/* Return the BFD which is referenced by the symbol in ABFD indexed by
54133965Sjdp   INDEX.  INDEX should have been returned by bfd_get_next_mapent.  */
54233965Sjdp
54333965Sjdpbfd *
544130561Sobrien_bfd_generic_get_elt_at_index (bfd *abfd, symindex index)
54533965Sjdp{
54633965Sjdp  carsym *entry;
54733965Sjdp
54833965Sjdp  entry = bfd_ardata (abfd)->symdefs + index;
54933965Sjdp  return _bfd_get_elt_at_filepos (abfd, entry->file_offset);
55033965Sjdp}
55133965Sjdp
55233965Sjdp/*
55333965SjdpFUNCTION
55433965Sjdp	bfd_openr_next_archived_file
55533965Sjdp
55633965SjdpSYNOPSIS
557130561Sobrien	bfd *bfd_openr_next_archived_file (bfd *archive, bfd *previous);
55833965Sjdp
55933965SjdpDESCRIPTION
56033965Sjdp	Provided a BFD, @var{archive}, containing an archive and NULL, open
56133965Sjdp	an input BFD on the first contained element and returns that.
56233965Sjdp	Subsequent calls should pass
56333965Sjdp	the archive and the previous return value to return a created
56433965Sjdp	BFD to the next contained element. NULL is returned when there
56533965Sjdp	are no more.
56633965Sjdp*/
56733965Sjdp
56833965Sjdpbfd *
569130561Sobrienbfd_openr_next_archived_file (bfd *archive, bfd *last_file)
57033965Sjdp{
57133965Sjdp  if ((bfd_get_format (archive) != bfd_archive) ||
57233965Sjdp      (archive->direction == write_direction))
57333965Sjdp    {
57433965Sjdp      bfd_set_error (bfd_error_invalid_operation);
57533965Sjdp      return NULL;
57633965Sjdp    }
57733965Sjdp
57833965Sjdp  return BFD_SEND (archive,
579130561Sobrien		   openr_next_archived_file, (archive, last_file));
58033965Sjdp}
58133965Sjdp
58233965Sjdpbfd *
583130561Sobrienbfd_generic_openr_next_archived_file (bfd *archive, bfd *last_file)
58433965Sjdp{
58533965Sjdp  file_ptr filestart;
58633965Sjdp
58733965Sjdp  if (!last_file)
58833965Sjdp    filestart = bfd_ardata (archive)->first_file_filepos;
58933965Sjdp  else
59033965Sjdp    {
59133965Sjdp      unsigned int size = arelt_size (last_file);
592218822Sdim      filestart = last_file->origin + size;
593218822Sdim      if (archive->my_archive)
594218822Sdim	filestart -= archive->origin;
59533965Sjdp      /* Pad to an even boundary...
59633965Sjdp	 Note that last_file->origin can be odd in the case of
59777298Sobrien	 BSD-4.4-style element with a long odd size.  */
59833965Sjdp      filestart += filestart % 2;
59933965Sjdp    }
60033965Sjdp
60133965Sjdp  return _bfd_get_elt_at_filepos (archive, filestart);
60233965Sjdp}
60333965Sjdp
60433965Sjdpconst bfd_target *
605130561Sobrienbfd_generic_archive_p (bfd *abfd)
60633965Sjdp{
60733965Sjdp  struct artdata *tdata_hold;
60833965Sjdp  char armag[SARMAG + 1];
60989857Sobrien  bfd_size_type amt;
61033965Sjdp
611130561Sobrien  if (bfd_bread (armag, SARMAG, abfd) != SARMAG)
61233965Sjdp    {
61333965Sjdp      if (bfd_get_error () != bfd_error_system_call)
61433965Sjdp	bfd_set_error (bfd_error_wrong_format);
61533965Sjdp      return NULL;
61633965Sjdp    }
61733965Sjdp
61833965Sjdp  if (strncmp (armag, ARMAG, SARMAG) != 0 &&
61933965Sjdp      strncmp (armag, ARMAGB, SARMAG) != 0)
62033965Sjdp    return 0;
62133965Sjdp
622104834Sobrien  tdata_hold = bfd_ardata (abfd);
623104834Sobrien
62489857Sobrien  amt = sizeof (struct artdata);
625130561Sobrien  bfd_ardata (abfd) = bfd_zalloc (abfd, amt);
62633965Sjdp  if (bfd_ardata (abfd) == NULL)
627104834Sobrien    {
628104834Sobrien      bfd_ardata (abfd) = tdata_hold;
629104834Sobrien      return NULL;
630104834Sobrien    }
63133965Sjdp
63233965Sjdp  bfd_ardata (abfd)->first_file_filepos = SARMAG;
633218822Sdim  /* Cleared by bfd_zalloc above.
634218822Sdim     bfd_ardata (abfd)->cache = NULL;
635218822Sdim     bfd_ardata (abfd)->archive_head = NULL;
636218822Sdim     bfd_ardata (abfd)->symdefs = NULL;
637218822Sdim     bfd_ardata (abfd)->extended_names = NULL;
638218822Sdim     bfd_ardata (abfd)->extended_names_size = 0;
639218822Sdim     bfd_ardata (abfd)->tdata = NULL;  */
64033965Sjdp
641104834Sobrien  if (!BFD_SEND (abfd, _bfd_slurp_armap, (abfd))
642104834Sobrien      || !BFD_SEND (abfd, _bfd_slurp_extended_name_table, (abfd)))
64333965Sjdp    {
64438889Sjdp      if (bfd_get_error () != bfd_error_system_call)
64538889Sjdp	bfd_set_error (bfd_error_wrong_format);
64633965Sjdp      bfd_release (abfd, bfd_ardata (abfd));
647104834Sobrien      bfd_ardata (abfd) = tdata_hold;
64833965Sjdp      return NULL;
64933965Sjdp    }
65033965Sjdp
65133965Sjdp  if (bfd_has_map (abfd))
65233965Sjdp    {
65333965Sjdp      bfd *first;
65433965Sjdp
65533965Sjdp      /* This archive has a map, so we may presume that the contents
65633965Sjdp	 are object files.  Make sure that if the first file in the
65733965Sjdp	 archive can be recognized as an object file, it is for this
65833965Sjdp	 target.  If not, assume that this is the wrong format.  If
65933965Sjdp	 the first file is not an object file, somebody is doing
66033965Sjdp	 something weird, and we permit it so that ar -t will work.
66133965Sjdp
66233965Sjdp	 This is done because any normal format will recognize any
66333965Sjdp	 normal archive, regardless of the format of the object files.
66433965Sjdp	 We do accept an empty archive.  */
66533965Sjdp
666130561Sobrien      first = bfd_openr_next_archived_file (abfd, NULL);
66733965Sjdp      if (first != NULL)
66833965Sjdp	{
669130561Sobrien	  first->target_defaulted = FALSE;
67033965Sjdp	  if (bfd_check_format (first, bfd_object)
67133965Sjdp	      && first->xvec != abfd->xvec)
67233965Sjdp	    {
67389857Sobrien	      bfd_set_error (bfd_error_wrong_object_format);
674104834Sobrien	      bfd_ardata (abfd) = tdata_hold;
67533965Sjdp	      return NULL;
67633965Sjdp	    }
67789857Sobrien	  /* And we ought to close `first' here too.  */
67833965Sjdp	}
67933965Sjdp    }
68033965Sjdp
68133965Sjdp  return abfd->xvec;
68233965Sjdp}
68333965Sjdp
68433965Sjdp/* Some constants for a 32 bit BSD archive structure.  We do not
68533965Sjdp   support 64 bit archives presently; so far as I know, none actually
68633965Sjdp   exist.  Supporting them would require changing these constants, and
68789857Sobrien   changing some H_GET_32 to H_GET_64.  */
68833965Sjdp
68933965Sjdp/* The size of an external symdef structure.  */
69033965Sjdp#define BSD_SYMDEF_SIZE 8
69133965Sjdp
69233965Sjdp/* The offset from the start of a symdef structure to the file offset.  */
69333965Sjdp#define BSD_SYMDEF_OFFSET_SIZE 4
69433965Sjdp
69533965Sjdp/* The size of the symdef count.  */
69633965Sjdp#define BSD_SYMDEF_COUNT_SIZE 4
69733965Sjdp
69833965Sjdp/* The size of the string count.  */
69933965Sjdp#define BSD_STRING_COUNT_SIZE 4
70033965Sjdp
701218822Sdim/* Returns FALSE on error, TRUE otherwise.  */
70233965Sjdp
703130561Sobrienstatic bfd_boolean
704130561Sobriendo_slurp_bsd_armap (bfd *abfd)
70533965Sjdp{
70633965Sjdp  struct areltdata *mapdata;
70733965Sjdp  unsigned int counter;
70833965Sjdp  bfd_byte *raw_armap, *rbase;
70933965Sjdp  struct artdata *ardata = bfd_ardata (abfd);
71033965Sjdp  char *stringbase;
71189857Sobrien  bfd_size_type parsed_size, amt;
71233965Sjdp  carsym *set;
71333965Sjdp
714130561Sobrien  mapdata = _bfd_read_ar_hdr (abfd);
71533965Sjdp  if (mapdata == NULL)
716130561Sobrien    return FALSE;
71733965Sjdp  parsed_size = mapdata->parsed_size;
718130561Sobrien  bfd_release (abfd, mapdata);	/* Don't need it any more.  */
71933965Sjdp
720130561Sobrien  raw_armap = bfd_zalloc (abfd, parsed_size);
721130561Sobrien  if (raw_armap == NULL)
722130561Sobrien    return FALSE;
72333965Sjdp
724130561Sobrien  if (bfd_bread (raw_armap, parsed_size, abfd) != parsed_size)
72533965Sjdp    {
72633965Sjdp      if (bfd_get_error () != bfd_error_system_call)
72733965Sjdp	bfd_set_error (bfd_error_malformed_archive);
72833965Sjdp    byebye:
729130561Sobrien      bfd_release (abfd, raw_armap);
730130561Sobrien      return FALSE;
73133965Sjdp    }
73233965Sjdp
73389857Sobrien  ardata->symdef_count = H_GET_32 (abfd, raw_armap) / BSD_SYMDEF_SIZE;
73433965Sjdp
73533965Sjdp  if (ardata->symdef_count * BSD_SYMDEF_SIZE >
73633965Sjdp      parsed_size - BSD_SYMDEF_COUNT_SIZE)
73733965Sjdp    {
73833965Sjdp      /* Probably we're using the wrong byte ordering.  */
73933965Sjdp      bfd_set_error (bfd_error_wrong_format);
74033965Sjdp      goto byebye;
74133965Sjdp    }
74233965Sjdp
74333965Sjdp  ardata->cache = 0;
74433965Sjdp  rbase = raw_armap + BSD_SYMDEF_COUNT_SIZE;
74533965Sjdp  stringbase = ((char *) rbase
74633965Sjdp		+ ardata->symdef_count * BSD_SYMDEF_SIZE
74733965Sjdp		+ BSD_STRING_COUNT_SIZE);
748130561Sobrien  amt = ardata->symdef_count * sizeof (carsym);
749130561Sobrien  ardata->symdefs = bfd_alloc (abfd, amt);
75033965Sjdp  if (!ardata->symdefs)
751130561Sobrien    return FALSE;
75233965Sjdp
75333965Sjdp  for (counter = 0, set = ardata->symdefs;
75433965Sjdp       counter < ardata->symdef_count;
75533965Sjdp       counter++, set++, rbase += BSD_SYMDEF_SIZE)
75633965Sjdp    {
75789857Sobrien      set->name = H_GET_32 (abfd, rbase) + stringbase;
75889857Sobrien      set->file_offset = H_GET_32 (abfd, rbase + BSD_SYMDEF_OFFSET_SIZE);
75933965Sjdp    }
76033965Sjdp
76133965Sjdp  ardata->first_file_filepos = bfd_tell (abfd);
76277298Sobrien  /* Pad to an even boundary if you have to.  */
76333965Sjdp  ardata->first_file_filepos += (ardata->first_file_filepos) % 2;
76433965Sjdp  /* FIXME, we should provide some way to free raw_ardata when
76533965Sjdp     we are done using the strings from it.  For now, it seems
76677298Sobrien     to be allocated on an objalloc anyway...  */
767130561Sobrien  bfd_has_map (abfd) = TRUE;
768130561Sobrien  return TRUE;
76933965Sjdp}
77033965Sjdp
771130561Sobrien/* Returns FALSE on error, TRUE otherwise.  */
77277298Sobrien
773130561Sobrienstatic bfd_boolean
774130561Sobriendo_slurp_coff_armap (bfd *abfd)
77533965Sjdp{
77633965Sjdp  struct areltdata *mapdata;
77733965Sjdp  int *raw_armap, *rawptr;
77833965Sjdp  struct artdata *ardata = bfd_ardata (abfd);
77933965Sjdp  char *stringbase;
78089857Sobrien  bfd_size_type stringsize;
78133965Sjdp  unsigned int parsed_size;
78233965Sjdp  carsym *carsyms;
78389857Sobrien  bfd_size_type nsymz;		/* Number of symbols in armap.  */
784130561Sobrien  bfd_vma (*swap) (const void *);
78533965Sjdp  char int_buf[sizeof (long)];
78689857Sobrien  bfd_size_type carsym_size, ptrsize;
78789857Sobrien  unsigned int i;
78833965Sjdp
789130561Sobrien  mapdata = _bfd_read_ar_hdr (abfd);
79033965Sjdp  if (mapdata == NULL)
791130561Sobrien    return FALSE;
79233965Sjdp  parsed_size = mapdata->parsed_size;
793130561Sobrien  bfd_release (abfd, mapdata);	/* Don't need it any more.  */
79433965Sjdp
795130561Sobrien  if (bfd_bread (int_buf, 4, abfd) != 4)
79633965Sjdp    {
79733965Sjdp      if (bfd_get_error () != bfd_error_system_call)
79833965Sjdp	bfd_set_error (bfd_error_malformed_archive);
799130561Sobrien      return FALSE;
80033965Sjdp    }
80133965Sjdp  /* It seems that all numeric information in a coff archive is always
80277298Sobrien     in big endian format, nomatter the host or target.  */
80333965Sjdp  swap = bfd_getb32;
804130561Sobrien  nsymz = bfd_getb32 (int_buf);
80533965Sjdp  stringsize = parsed_size - (4 * nsymz) - 4;
80633965Sjdp
80733965Sjdp  /* ... except that some archive formats are broken, and it may be our
80833965Sjdp     fault - the i960 little endian coff sometimes has big and sometimes
80933965Sjdp     little, because our tools changed.  Here's a horrible hack to clean
81033965Sjdp     up the crap.  */
81133965Sjdp
81233965Sjdp  if (stringsize > 0xfffff
81333965Sjdp      && bfd_get_arch (abfd) == bfd_arch_i960
81433965Sjdp      && bfd_get_flavour (abfd) == bfd_target_coff_flavour)
81533965Sjdp    {
81677298Sobrien      /* This looks dangerous, let's do it the other way around.  */
817130561Sobrien      nsymz = bfd_getl32 (int_buf);
81833965Sjdp      stringsize = parsed_size - (4 * nsymz) - 4;
81933965Sjdp      swap = bfd_getl32;
82033965Sjdp    }
82133965Sjdp
82233965Sjdp  /* The coff armap must be read sequentially.  So we construct a
82377298Sobrien     bsd-style one in core all at once, for simplicity.  */
82433965Sjdp
825218822Sdim  if (nsymz > ~ (bfd_size_type) 0 / sizeof (carsym))
826218822Sdim    return FALSE;
827218822Sdim
82833965Sjdp  carsym_size = (nsymz * sizeof (carsym));
82933965Sjdp  ptrsize = (4 * nsymz);
83033965Sjdp
831218822Sdim  if (carsym_size + stringsize + 1 <= carsym_size)
832218822Sdim    return FALSE;
833218822Sdim
834130561Sobrien  ardata->symdefs = bfd_zalloc (abfd, carsym_size + stringsize + 1);
83533965Sjdp  if (ardata->symdefs == NULL)
836130561Sobrien    return FALSE;
83733965Sjdp  carsyms = ardata->symdefs;
83833965Sjdp  stringbase = ((char *) ardata->symdefs) + carsym_size;
83933965Sjdp
84077298Sobrien  /* Allocate and read in the raw offsets.  */
841130561Sobrien  raw_armap = bfd_alloc (abfd, ptrsize);
84233965Sjdp  if (raw_armap == NULL)
84333965Sjdp    goto release_symdefs;
844130561Sobrien  if (bfd_bread (raw_armap, ptrsize, abfd) != ptrsize
845130561Sobrien      || (bfd_bread (stringbase, stringsize, abfd) != stringsize))
84633965Sjdp    {
84733965Sjdp      if (bfd_get_error () != bfd_error_system_call)
84833965Sjdp	bfd_set_error (bfd_error_malformed_archive);
84933965Sjdp      goto release_raw_armap;
85033965Sjdp    }
85133965Sjdp
85277298Sobrien  /* OK, build the carsyms.  */
85333965Sjdp  for (i = 0; i < nsymz; i++)
85433965Sjdp    {
85533965Sjdp      rawptr = raw_armap + i;
856130561Sobrien      carsyms->file_offset = swap ((bfd_byte *) rawptr);
85733965Sjdp      carsyms->name = stringbase;
85833965Sjdp      stringbase += strlen (stringbase) + 1;
85933965Sjdp      carsyms++;
86033965Sjdp    }
86133965Sjdp  *stringbase = 0;
86233965Sjdp
86333965Sjdp  ardata->symdef_count = nsymz;
86433965Sjdp  ardata->first_file_filepos = bfd_tell (abfd);
86577298Sobrien  /* Pad to an even boundary if you have to.  */
86633965Sjdp  ardata->first_file_filepos += (ardata->first_file_filepos) % 2;
86733965Sjdp
868130561Sobrien  bfd_has_map (abfd) = TRUE;
869130561Sobrien  bfd_release (abfd, raw_armap);
87033965Sjdp
87177298Sobrien  /* Check for a second archive header (as used by PE).  */
87233965Sjdp  {
87333965Sjdp    struct areltdata *tmp;
87433965Sjdp
87589857Sobrien    bfd_seek (abfd, ardata->first_file_filepos, SEEK_SET);
876130561Sobrien    tmp = _bfd_read_ar_hdr (abfd);
87777298Sobrien    if (tmp != NULL)
87833965Sjdp      {
87933965Sjdp	if (tmp->arch_header[0] == '/'
88077298Sobrien	    && tmp->arch_header[1] == ' ')
88133965Sjdp	  {
88233965Sjdp	    ardata->first_file_filepos +=
88389857Sobrien	      (tmp->parsed_size + sizeof (struct ar_hdr) + 1) & ~(unsigned) 1;
88433965Sjdp	  }
88533965Sjdp	bfd_release (abfd, tmp);
88633965Sjdp      }
88733965Sjdp  }
88833965Sjdp
889130561Sobrien  return TRUE;
89033965Sjdp
89133965Sjdprelease_raw_armap:
892130561Sobrien  bfd_release (abfd, raw_armap);
89333965Sjdprelease_symdefs:
894130561Sobrien  bfd_release (abfd, (ardata)->symdefs);
895130561Sobrien  return FALSE;
89633965Sjdp}
89733965Sjdp
89833965Sjdp/* This routine can handle either coff-style or bsd-style armaps.
899130561Sobrien   Returns FALSE on error, TRUE otherwise */
90033965Sjdp
901130561Sobrienbfd_boolean
902130561Sobrienbfd_slurp_armap (bfd *abfd)
90333965Sjdp{
90433965Sjdp  char nextname[17];
905130561Sobrien  int i = bfd_bread (nextname, 16, abfd);
90633965Sjdp
90733965Sjdp  if (i == 0)
908130561Sobrien    return TRUE;
90933965Sjdp  if (i != 16)
910130561Sobrien    return FALSE;
91133965Sjdp
91289857Sobrien  if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0)
913130561Sobrien    return FALSE;
91433965Sjdp
915218822Sdim  if (CONST_STRNEQ (nextname, "__.SYMDEF       ")
916218822Sdim      || CONST_STRNEQ (nextname, "__.SYMDEF/      ")) /* Old Linux archives.  */
91733965Sjdp    return do_slurp_bsd_armap (abfd);
918218822Sdim  else if (CONST_STRNEQ (nextname, "/               "))
91933965Sjdp    return do_slurp_coff_armap (abfd);
920218822Sdim  else if (CONST_STRNEQ (nextname, "/SYM64/         "))
92133965Sjdp    {
92289857Sobrien      /* 64bit ELF (Irix 6) archive.  */
92389857Sobrien#ifdef BFD64
924130561Sobrien      extern bfd_boolean bfd_elf64_archive_slurp_armap (bfd *);
92589857Sobrien      return bfd_elf64_archive_slurp_armap (abfd);
92689857Sobrien#else
92733965Sjdp      bfd_set_error (bfd_error_wrong_format);
928130561Sobrien      return FALSE;
92989857Sobrien#endif
93033965Sjdp    }
93133965Sjdp
932130561Sobrien  bfd_has_map (abfd) = FALSE;
933130561Sobrien  return TRUE;
93433965Sjdp}
93533965Sjdp
936218822Sdim/* Returns FALSE on error, TRUE otherwise.  */
937218822Sdim/* Flavor 2 of a bsd armap, similar to bfd_slurp_bsd_armap except the
93833965Sjdp   header is in a slightly different order and the map name is '/'.
93977298Sobrien   This flavour is used by hp300hpux.  */
94033965Sjdp
94133965Sjdp#define HPUX_SYMDEF_COUNT_SIZE 2
94233965Sjdp
943130561Sobrienbfd_boolean
944130561Sobrienbfd_slurp_bsd_armap_f2 (bfd *abfd)
94533965Sjdp{
94633965Sjdp  struct areltdata *mapdata;
94733965Sjdp  char nextname[17];
94833965Sjdp  unsigned int counter;
94933965Sjdp  bfd_byte *raw_armap, *rbase;
95033965Sjdp  struct artdata *ardata = bfd_ardata (abfd);
95133965Sjdp  char *stringbase;
95233965Sjdp  unsigned int stringsize;
95389857Sobrien  bfd_size_type amt;
95433965Sjdp  carsym *set;
955130561Sobrien  int i = bfd_bread (nextname, 16, abfd);
95633965Sjdp
95733965Sjdp  if (i == 0)
958130561Sobrien    return TRUE;
95933965Sjdp  if (i != 16)
960130561Sobrien    return FALSE;
96133965Sjdp
96277298Sobrien  /* The archive has at least 16 bytes in it.  */
96389857Sobrien  if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0)
964130561Sobrien    return FALSE;
96533965Sjdp
966218822Sdim  if (CONST_STRNEQ (nextname, "__.SYMDEF       ")
967218822Sdim      || CONST_STRNEQ (nextname, "__.SYMDEF/      ")) /* Old Linux archives.  */
96833965Sjdp    return do_slurp_bsd_armap (abfd);
96933965Sjdp
970218822Sdim  if (! CONST_STRNEQ (nextname, "/               "))
97133965Sjdp    {
972130561Sobrien      bfd_has_map (abfd) = FALSE;
973130561Sobrien      return TRUE;
97433965Sjdp    }
97533965Sjdp
976130561Sobrien  mapdata = _bfd_read_ar_hdr (abfd);
97733965Sjdp  if (mapdata == NULL)
978130561Sobrien    return FALSE;
97933965Sjdp
98089857Sobrien  amt = mapdata->parsed_size;
981130561Sobrien  raw_armap = bfd_zalloc (abfd, amt);
98233965Sjdp  if (raw_armap == NULL)
98333965Sjdp    {
98433965Sjdp    byebye:
985130561Sobrien      bfd_release (abfd, mapdata);
986130561Sobrien      return FALSE;
98733965Sjdp    }
98833965Sjdp
989130561Sobrien  if (bfd_bread (raw_armap, amt, abfd) != amt)
99033965Sjdp    {
99133965Sjdp      if (bfd_get_error () != bfd_error_system_call)
99233965Sjdp	bfd_set_error (bfd_error_malformed_archive);
99333965Sjdp    byebyebye:
994130561Sobrien      bfd_release (abfd, raw_armap);
99533965Sjdp      goto byebye;
99633965Sjdp    }
99733965Sjdp
998130561Sobrien  ardata->symdef_count = H_GET_16 (abfd, raw_armap);
99933965Sjdp
100033965Sjdp  if (ardata->symdef_count * BSD_SYMDEF_SIZE
100133965Sjdp      > mapdata->parsed_size - HPUX_SYMDEF_COUNT_SIZE)
100233965Sjdp    {
100333965Sjdp      /* Probably we're using the wrong byte ordering.  */
100433965Sjdp      bfd_set_error (bfd_error_wrong_format);
100533965Sjdp      goto byebyebye;
100633965Sjdp    }
100733965Sjdp
100833965Sjdp  ardata->cache = 0;
100933965Sjdp
101089857Sobrien  stringsize = H_GET_32 (abfd, raw_armap + HPUX_SYMDEF_COUNT_SIZE);
101177298Sobrien  /* Skip sym count and string sz.  */
101233965Sjdp  stringbase = ((char *) raw_armap
101333965Sjdp		+ HPUX_SYMDEF_COUNT_SIZE
101433965Sjdp		+ BSD_STRING_COUNT_SIZE);
101533965Sjdp  rbase = (bfd_byte *) stringbase + stringsize;
1016130561Sobrien  amt = ardata->symdef_count * BSD_SYMDEF_SIZE;
1017130561Sobrien  ardata->symdefs = bfd_alloc (abfd, amt);
101833965Sjdp  if (!ardata->symdefs)
1019130561Sobrien    return FALSE;
102033965Sjdp
102133965Sjdp  for (counter = 0, set = ardata->symdefs;
102233965Sjdp       counter < ardata->symdef_count;
102333965Sjdp       counter++, set++, rbase += BSD_SYMDEF_SIZE)
102433965Sjdp    {
102589857Sobrien      set->name = H_GET_32 (abfd, rbase) + stringbase;
102689857Sobrien      set->file_offset = H_GET_32 (abfd, rbase + BSD_SYMDEF_OFFSET_SIZE);
102733965Sjdp    }
102833965Sjdp
102933965Sjdp  ardata->first_file_filepos = bfd_tell (abfd);
103077298Sobrien  /* Pad to an even boundary if you have to.  */
103133965Sjdp  ardata->first_file_filepos += (ardata->first_file_filepos) % 2;
103233965Sjdp  /* FIXME, we should provide some way to free raw_ardata when
103333965Sjdp     we are done using the strings from it.  For now, it seems
103477298Sobrien     to be allocated on an objalloc anyway...  */
1035130561Sobrien  bfd_has_map (abfd) = TRUE;
1036130561Sobrien  return TRUE;
103733965Sjdp}
103833965Sjdp
103933965Sjdp/** Extended name table.
104033965Sjdp
104133965Sjdp  Normally archives support only 14-character filenames.
104233965Sjdp
104333965Sjdp  Intel has extended the format: longer names are stored in a special
104433965Sjdp  element (the first in the archive, or second if there is an armap);
104533965Sjdp  the name in the ar_hdr is replaced by <space><index into filename
104633965Sjdp  element>.  Index is the P.R. of an int (decimal).  Data General have
104777298Sobrien  extended the format by using the prefix // for the special element.  */
104833965Sjdp
1049130561Sobrien/* Returns FALSE on error, TRUE otherwise.  */
105077298Sobrien
1051130561Sobrienbfd_boolean
1052130561Sobrien_bfd_slurp_extended_name_table (bfd *abfd)
105333965Sjdp{
105433965Sjdp  char nextname[17];
105533965Sjdp  struct areltdata *namedata;
105689857Sobrien  bfd_size_type amt;
105733965Sjdp
105833965Sjdp  /* FIXME:  Formatting sucks here, and in case of failure of BFD_READ,
1059130561Sobrien     we probably don't want to return TRUE.  */
106033965Sjdp  bfd_seek (abfd, bfd_ardata (abfd)->first_file_filepos, SEEK_SET);
1061130561Sobrien  if (bfd_bread (nextname, 16, abfd) == 16)
106233965Sjdp    {
106389857Sobrien      if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0)
1064130561Sobrien	return FALSE;
106533965Sjdp
1066218822Sdim      if (! CONST_STRNEQ (nextname, "ARFILENAMES/    ")
1067218822Sdim	  && ! CONST_STRNEQ (nextname, "//              "))
106833965Sjdp	{
106933965Sjdp	  bfd_ardata (abfd)->extended_names = NULL;
1070218822Sdim	  bfd_ardata (abfd)->extended_names_size = 0;
1071130561Sobrien	  return TRUE;
107233965Sjdp	}
107333965Sjdp
1074130561Sobrien      namedata = _bfd_read_ar_hdr (abfd);
107533965Sjdp      if (namedata == NULL)
1076130561Sobrien	return FALSE;
107733965Sjdp
107889857Sobrien      amt = namedata->parsed_size;
1079218822Sdim      if (amt + 1 == 0)
1080218822Sdim        goto byebye;
1081218822Sdim
1082218822Sdim      bfd_ardata (abfd)->extended_names_size = amt;
1083218822Sdim      bfd_ardata (abfd)->extended_names = bfd_zalloc (abfd, amt + 1);
108433965Sjdp      if (bfd_ardata (abfd)->extended_names == NULL)
108533965Sjdp	{
108633965Sjdp	byebye:
1087130561Sobrien	  bfd_release (abfd, namedata);
1088130561Sobrien	  return FALSE;
108933965Sjdp	}
109033965Sjdp
1091130561Sobrien      if (bfd_bread (bfd_ardata (abfd)->extended_names, amt, abfd) != amt)
109233965Sjdp	{
109333965Sjdp	  if (bfd_get_error () != bfd_error_system_call)
109433965Sjdp	    bfd_set_error (bfd_error_malformed_archive);
1095130561Sobrien	  bfd_release (abfd, (bfd_ardata (abfd)->extended_names));
109633965Sjdp	  bfd_ardata (abfd)->extended_names = NULL;
109733965Sjdp	  goto byebye;
109833965Sjdp	}
109933965Sjdp
110033965Sjdp      /* Since the archive is supposed to be printable if it contains
110133965Sjdp	 text, the entries in the list are newline-padded, not null
110233965Sjdp	 padded. In SVR4-style archives, the names also have a
110333965Sjdp	 trailing '/'.  DOS/NT created archive often have \ in them
110433965Sjdp	 We'll fix all problems here..  */
110533965Sjdp      {
1106218822Sdim        char *ext_names = bfd_ardata (abfd)->extended_names;
1107218822Sdim	char *temp = ext_names;
110833965Sjdp	char *limit = temp + namedata->parsed_size;
110977298Sobrien	for (; temp < limit; ++temp)
111077298Sobrien	  {
111177298Sobrien	    if (*temp == '\012')
1112218822Sdim	      temp[temp > ext_names && temp[-1] == '/' ? -1 : 0] = '\0';
111377298Sobrien	    if (*temp == '\\')
111477298Sobrien	      *temp = '/';
111577298Sobrien	  }
1116218822Sdim	*limit = '\0';
111733965Sjdp      }
111833965Sjdp
111977298Sobrien      /* Pad to an even boundary if you have to.  */
112033965Sjdp      bfd_ardata (abfd)->first_file_filepos = bfd_tell (abfd);
112133965Sjdp      bfd_ardata (abfd)->first_file_filepos +=
112233965Sjdp	(bfd_ardata (abfd)->first_file_filepos) % 2;
112333965Sjdp
112433965Sjdp      /* FIXME, we can't release namedata here because it was allocated
112577298Sobrien	 below extended_names on the objalloc...  */
112633965Sjdp    }
1127130561Sobrien  return TRUE;
112833965Sjdp}
112933965Sjdp
113033965Sjdp#ifdef VMS
113133965Sjdp
113233965Sjdp/* Return a copy of the stuff in the filename between any :]> and a
113377298Sobrien   semicolon.  */
113477298Sobrien
113533965Sjdpstatic const char *
1136130561Sobriennormalize (bfd *abfd, const char *file)
113733965Sjdp{
113889857Sobrien  const char *first;
113989857Sobrien  const char *last;
114033965Sjdp  char *copy;
114133965Sjdp
114233965Sjdp  first = file + strlen (file) - 1;
114333965Sjdp  last = first + 1;
114433965Sjdp
114533965Sjdp  while (first != file)
114633965Sjdp    {
114733965Sjdp      if (*first == ';')
114833965Sjdp	last = first;
114933965Sjdp      if (*first == ':' || *first == ']' || *first == '>')
115033965Sjdp	{
115133965Sjdp	  first++;
115233965Sjdp	  break;
115333965Sjdp	}
115433965Sjdp      first--;
115533965Sjdp    }
115633965Sjdp
1157130561Sobrien  copy = bfd_alloc (abfd, last - first + 1);
115833965Sjdp  if (copy == NULL)
115933965Sjdp    return NULL;
116033965Sjdp
116133965Sjdp  memcpy (copy, first, last - first);
116233965Sjdp  copy[last - first] = 0;
116333965Sjdp
116433965Sjdp  return copy;
116533965Sjdp}
116633965Sjdp
116733965Sjdp#else
116833965Sjdpstatic const char *
1169130561Sobriennormalize (bfd *abfd ATTRIBUTE_UNUSED, const char *file)
117033965Sjdp{
117133965Sjdp  const char *filename = strrchr (file, '/');
117233965Sjdp
117361843Sobrien#ifdef HAVE_DOS_BASED_FILE_SYSTEM
117461843Sobrien  {
117561843Sobrien    /* We could have foo/bar\\baz, or foo\\bar, or d:bar.  */
117661843Sobrien    char *bslash = strrchr (file, '\\');
117777298Sobrien    if (filename == NULL || (bslash != NULL && bslash > filename))
117861843Sobrien      filename = bslash;
117961843Sobrien    if (filename == NULL && file[0] != '\0' && file[1] == ':')
118061843Sobrien      filename = file + 1;
118161843Sobrien  }
118261843Sobrien#endif
1183130561Sobrien  if (filename != NULL)
118433965Sjdp    filename++;
118533965Sjdp  else
118633965Sjdp    filename = file;
118733965Sjdp  return filename;
118833965Sjdp}
118933965Sjdp#endif
119033965Sjdp
119133965Sjdp/* Build a BFD style extended name table.  */
119233965Sjdp
1193130561Sobrienbfd_boolean
1194130561Sobrien_bfd_archive_bsd_construct_extended_name_table (bfd *abfd,
1195130561Sobrien						char **tabloc,
1196130561Sobrien						bfd_size_type *tablen,
1197130561Sobrien						const char **name)
119833965Sjdp{
119933965Sjdp  *name = "ARFILENAMES/";
1200130561Sobrien  return _bfd_construct_extended_name_table (abfd, FALSE, tabloc, tablen);
120133965Sjdp}
120233965Sjdp
120333965Sjdp/* Build an SVR4 style extended name table.  */
120433965Sjdp
1205130561Sobrienbfd_boolean
1206130561Sobrien_bfd_archive_coff_construct_extended_name_table (bfd *abfd,
1207130561Sobrien						 char **tabloc,
1208130561Sobrien						 bfd_size_type *tablen,
1209130561Sobrien						 const char **name)
121033965Sjdp{
121133965Sjdp  *name = "//";
1212130561Sobrien  return _bfd_construct_extended_name_table (abfd, TRUE, tabloc, tablen);
121333965Sjdp}
121433965Sjdp
121533965Sjdp/* Follows archive_head and produces an extended name table if
121633965Sjdp   necessary.  Returns (in tabloc) a pointer to an extended name
121733965Sjdp   table, and in tablen the length of the table.  If it makes an entry
121833965Sjdp   it clobbers the filename so that the element may be written without
1219130561Sobrien   further massage.  Returns TRUE if it ran successfully, FALSE if
122033965Sjdp   something went wrong.  A successful return may still involve a
122133965Sjdp   zero-length tablen!  */
122233965Sjdp
1223130561Sobrienbfd_boolean
1224130561Sobrien_bfd_construct_extended_name_table (bfd *abfd,
1225130561Sobrien				    bfd_boolean trailing_slash,
1226130561Sobrien				    char **tabloc,
1227130561Sobrien				    bfd_size_type *tablen)
122833965Sjdp{
122933965Sjdp  unsigned int maxname = abfd->xvec->ar_max_namelen;
123089857Sobrien  bfd_size_type total_namelen = 0;
123133965Sjdp  bfd *current;
123233965Sjdp  char *strptr;
123333965Sjdp
123433965Sjdp  *tablen = 0;
123533965Sjdp
123677298Sobrien  /* Figure out how long the table should be.  */
1237218822Sdim  for (current = abfd->archive_head;
1238218822Sdim       current != NULL;
1239218822Sdim       current = current->archive_next)
124033965Sjdp    {
124133965Sjdp      const char *normal;
124233965Sjdp      unsigned int thislen;
124333965Sjdp
124433965Sjdp      normal = normalize (current, current->filename);
124533965Sjdp      if (normal == NULL)
1246130561Sobrien	return FALSE;
124733965Sjdp
124833965Sjdp      thislen = strlen (normal);
124933965Sjdp
125033965Sjdp      if (thislen > maxname
125133965Sjdp	  && (bfd_get_file_flags (abfd) & BFD_TRADITIONAL_FORMAT) != 0)
125233965Sjdp	thislen = maxname;
125333965Sjdp
125433965Sjdp      if (thislen > maxname)
125533965Sjdp	{
125633965Sjdp	  /* Add one to leave room for \n.  */
125733965Sjdp	  total_namelen += thislen + 1;
125833965Sjdp	  if (trailing_slash)
125933965Sjdp	    {
126033965Sjdp	      /* Leave room for trailing slash.  */
126133965Sjdp	      ++total_namelen;
126233965Sjdp	    }
126333965Sjdp	}
126433965Sjdp      else
126533965Sjdp	{
126633965Sjdp	  struct ar_hdr *hdr = arch_hdr (current);
126733965Sjdp	  if (strncmp (normal, hdr->ar_name, thislen) != 0
126833965Sjdp	      || (thislen < sizeof hdr->ar_name
126933965Sjdp		  && hdr->ar_name[thislen] != ar_padchar (current)))
127033965Sjdp	    {
127133965Sjdp	      /* Must have been using extended format even though it
127233965Sjdp	         didn't need to.  Fix it to use normal format.  */
127333965Sjdp	      memcpy (hdr->ar_name, normal, thislen);
127433965Sjdp	      if (thislen < maxname
127533965Sjdp		  || (thislen == maxname && thislen < sizeof hdr->ar_name))
127633965Sjdp		hdr->ar_name[thislen] = ar_padchar (current);
127733965Sjdp	    }
127833965Sjdp	}
127933965Sjdp    }
128033965Sjdp
128133965Sjdp  if (total_namelen == 0)
1282130561Sobrien    return TRUE;
128333965Sjdp
128433965Sjdp  *tabloc = bfd_zalloc (abfd, total_namelen);
128533965Sjdp  if (*tabloc == NULL)
1286130561Sobrien    return FALSE;
128733965Sjdp
128833965Sjdp  *tablen = total_namelen;
128933965Sjdp  strptr = *tabloc;
129033965Sjdp
1291218822Sdim  for (current = abfd->archive_head;
1292218822Sdim       current != NULL;
1293218822Sdim       current = current->archive_next)
129433965Sjdp    {
129533965Sjdp      const char *normal;
129633965Sjdp      unsigned int thislen;
129733965Sjdp
129833965Sjdp      normal = normalize (current, current->filename);
129933965Sjdp      if (normal == NULL)
1300130561Sobrien	return FALSE;
130133965Sjdp
130233965Sjdp      thislen = strlen (normal);
130333965Sjdp      if (thislen > maxname)
130433965Sjdp	{
130533965Sjdp	  /* Works for now; may need to be re-engineered if we
130633965Sjdp	     encounter an oddball archive format and want to
130777298Sobrien	     generalise this hack.  */
130833965Sjdp	  struct ar_hdr *hdr = arch_hdr (current);
130933965Sjdp	  strcpy (strptr, normal);
131033965Sjdp	  if (! trailing_slash)
131133965Sjdp	    strptr[thislen] = '\012';
131233965Sjdp	  else
131333965Sjdp	    {
131433965Sjdp	      strptr[thislen] = '/';
131533965Sjdp	      strptr[thislen + 1] = '\012';
131633965Sjdp	    }
131733965Sjdp	  hdr->ar_name[0] = ar_padchar (current);
1318218822Sdim          _bfd_ar_spacepad (hdr->ar_name + 1, maxname - 1, "%-ld",
1319218822Sdim                            strptr - *tabloc);
132033965Sjdp	  strptr += thislen + 1;
132133965Sjdp	  if (trailing_slash)
132233965Sjdp	    ++strptr;
132333965Sjdp	}
132433965Sjdp    }
132533965Sjdp
1326130561Sobrien  return TRUE;
132733965Sjdp}
132833965Sjdp
1329218822Sdim/* A couple of functions for creating ar_hdrs.  */
133033965Sjdp
133177298Sobrien#ifdef HPUX_LARGE_AR_IDS
133277298Sobrien/* Function to encode large UID/GID values according to HP.  */
133377298Sobrien
133477298Sobrienstatic void
1335130561Sobrienhpux_uid_gid_encode (char str[6], long int id)
133677298Sobrien{
133777298Sobrien  int cnt;
133877298Sobrien
133977298Sobrien  str[5] = '@' + (id & 3);
134077298Sobrien  id >>= 2;
134177298Sobrien
1342218822Sdim  for (cnt = 4; cnt >= 0; --cnt, id >>= 6)
134377298Sobrien    str[cnt] = ' ' + (id & 0x3f);
134477298Sobrien}
134577298Sobrien#endif	/* HPUX_LARGE_AR_IDS */
134677298Sobrien
134760484Sobrien#ifndef HAVE_GETUID
134860484Sobrien#define getuid() 0
134960484Sobrien#endif
135060484Sobrien
135160484Sobrien#ifndef HAVE_GETGID
135260484Sobrien#define getgid() 0
135360484Sobrien#endif
135460484Sobrien
135533965Sjdp/* Takes a filename, returns an arelt_data for it, or NULL if it can't
135633965Sjdp   make one.  The filename must refer to a filename in the filesystem.
135760484Sobrien   The filename field of the ar_hdr will NOT be initialized.  If member
135877298Sobrien   is set, and it's an in-memory bfd, we fake it.  */
135933965Sjdp
136033965Sjdpstatic struct areltdata *
1361130561Sobrienbfd_ar_hdr_from_filesystem (bfd *abfd, const char *filename, bfd *member)
136233965Sjdp{
136333965Sjdp  struct stat status;
136433965Sjdp  struct areltdata *ared;
136533965Sjdp  struct ar_hdr *hdr;
136689857Sobrien  bfd_size_type amt;
136733965Sjdp
136860484Sobrien  if (member && (member->flags & BFD_IN_MEMORY) != 0)
136933965Sjdp    {
137077298Sobrien      /* Assume we just "made" the member, and fake it.  */
1371130561Sobrien      struct bfd_in_memory *bim = member->iostream;
137277298Sobrien      time (&status.st_mtime);
137377298Sobrien      status.st_uid = getuid ();
137477298Sobrien      status.st_gid = getgid ();
137560484Sobrien      status.st_mode = 0644;
137660484Sobrien      status.st_size = bim->size;
137760484Sobrien    }
137860484Sobrien  else if (stat (filename, &status) != 0)
137960484Sobrien    {
138033965Sjdp      bfd_set_error (bfd_error_system_call);
138133965Sjdp      return NULL;
138233965Sjdp    }
138333965Sjdp
138489857Sobrien  amt = sizeof (struct ar_hdr) + sizeof (struct areltdata);
1385130561Sobrien  ared = bfd_zalloc (abfd, amt);
138633965Sjdp  if (ared == NULL)
138733965Sjdp    return NULL;
138833965Sjdp  hdr = (struct ar_hdr *) (((char *) ared) + sizeof (struct areltdata));
138933965Sjdp
139077298Sobrien  /* ar headers are space padded, not null padded!  */
1391130561Sobrien  memset (hdr, ' ', sizeof (struct ar_hdr));
139233965Sjdp
1393251227Spfg  _bfd_ar_spacepad (hdr->ar_date, sizeof (hdr->ar_date), "%-12ld",
1394251227Spfg                    status.st_mtime);
139577298Sobrien#ifdef HPUX_LARGE_AR_IDS
139677298Sobrien  /* HP has a very "special" way to handle UID/GID's with numeric values
139777298Sobrien     > 99999.  */
139877298Sobrien  if (status.st_uid > 99999)
1399218822Sdim    hpux_uid_gid_encode (hdr->ar_uid, (long) status.st_uid);
140077298Sobrien  else
140177298Sobrien#endif
1402218822Sdim    _bfd_ar_spacepad (hdr->ar_uid, sizeof (hdr->ar_uid), "%ld",
1403218822Sdim                      status.st_uid);
140477298Sobrien#ifdef HPUX_LARGE_AR_IDS
140577298Sobrien  /* HP has a very "special" way to handle UID/GID's with numeric values
140677298Sobrien     > 99999.  */
140777298Sobrien  if (status.st_gid > 99999)
1408218822Sdim    hpux_uid_gid_encode (hdr->ar_gid, (long) status.st_gid);
140977298Sobrien  else
141077298Sobrien#endif
1411218822Sdim    _bfd_ar_spacepad (hdr->ar_gid, sizeof (hdr->ar_gid), "%ld",
1412218822Sdim                      status.st_gid);
1413218822Sdim  _bfd_ar_spacepad (hdr->ar_mode, sizeof (hdr->ar_mode), "%-8lo",
1414218822Sdim                    status.st_mode);
1415218822Sdim  _bfd_ar_spacepad (hdr->ar_size, sizeof (hdr->ar_size), "%-10ld",
1416218822Sdim                    status.st_size);
1417218822Sdim  memcpy (hdr->ar_fmag, ARFMAG, 2);
141833965Sjdp  ared->parsed_size = status.st_size;
141933965Sjdp  ared->arch_header = (char *) hdr;
142033965Sjdp
142133965Sjdp  return ared;
142233965Sjdp}
142333965Sjdp
142433965Sjdp/* This is magic required by the "ar" program.  Since it's
142577298Sobrien   undocumented, it's undocumented.  You may think that it would take
142677298Sobrien   a strong stomach to write this, and it does, but it takes even a
142777298Sobrien   stronger stomach to try to code around such a thing!  */
142833965Sjdp
1429130561Sobrienstruct ar_hdr *bfd_special_undocumented_glue (bfd *, const char *);
143038889Sjdp
143133965Sjdpstruct ar_hdr *
1432130561Sobrienbfd_special_undocumented_glue (bfd *abfd, const char *filename)
143333965Sjdp{
143460484Sobrien  struct areltdata *ar_elt = bfd_ar_hdr_from_filesystem (abfd, filename, 0);
143533965Sjdp  if (ar_elt == NULL)
143633965Sjdp    return NULL;
143733965Sjdp  return (struct ar_hdr *) ar_elt->arch_header;
143833965Sjdp}
143933965Sjdp
144077298Sobrien/* Analogous to stat call.  */
144133965Sjdp
144233965Sjdpint
1443130561Sobrienbfd_generic_stat_arch_elt (bfd *abfd, struct stat *buf)
144433965Sjdp{
144533965Sjdp  struct ar_hdr *hdr;
144633965Sjdp  char *aloser;
144733965Sjdp
144833965Sjdp  if (abfd->arelt_data == NULL)
144933965Sjdp    {
145033965Sjdp      bfd_set_error (bfd_error_invalid_operation);
145133965Sjdp      return -1;
145233965Sjdp    }
145333965Sjdp
145433965Sjdp  hdr = arch_hdr (abfd);
145533965Sjdp
145677298Sobrien#define foo(arelt, stelt, size)				\
145777298Sobrien  buf->stelt = strtol (hdr->arelt, &aloser, size);	\
145877298Sobrien  if (aloser == hdr->arelt)	      			\
145977298Sobrien    return -1;
146033965Sjdp
146177298Sobrien  /* Some platforms support special notations for large IDs.  */
146277298Sobrien#ifdef HPUX_LARGE_AR_IDS
146377298Sobrien# define foo2(arelt, stelt, size)					\
146477298Sobrien  if (hdr->arelt[5] == ' ')						\
146577298Sobrien    {									\
146677298Sobrien      foo (arelt, stelt, size);						\
146777298Sobrien    }									\
146877298Sobrien  else									\
146977298Sobrien    {									\
147077298Sobrien      int cnt;								\
147177298Sobrien      for (buf->stelt = cnt = 0; cnt < 5; ++cnt)			\
147277298Sobrien	{								\
147377298Sobrien	  if (hdr->arelt[cnt] < ' ' || hdr->arelt[cnt] > ' ' + 0x3f)	\
147477298Sobrien	    return -1;							\
147577298Sobrien	  buf->stelt <<= 6;						\
147677298Sobrien	  buf->stelt += hdr->arelt[cnt] - ' ';				\
147777298Sobrien	}								\
147877298Sobrien      if (hdr->arelt[5] < '@' || hdr->arelt[5] > '@' + 3)		\
147977298Sobrien	return -1;							\
148077298Sobrien      buf->stelt <<= 2;							\
148177298Sobrien      buf->stelt += hdr->arelt[5] - '@';				\
148277298Sobrien    }
148377298Sobrien#else
148477298Sobrien# define foo2(arelt, stelt, size) foo (arelt, stelt, size)
148577298Sobrien#endif
148677298Sobrien
1487251227Spfg  foo (ar_date, st_mtime, 10);
148877298Sobrien  foo2 (ar_uid, st_uid, 10);
148977298Sobrien  foo2 (ar_gid, st_gid, 10);
149033965Sjdp  foo (ar_mode, st_mode, 8);
149133965Sjdp
149233965Sjdp  buf->st_size = arch_eltdata (abfd)->parsed_size;
149333965Sjdp
149433965Sjdp  return 0;
149533965Sjdp}
149633965Sjdp
149733965Sjdpvoid
1498130561Sobrienbfd_dont_truncate_arname (bfd *abfd, const char *pathname, char *arhdr)
149933965Sjdp{
150033965Sjdp  /* FIXME: This interacts unpleasantly with ar's quick-append option.
150133965Sjdp     Fortunately ic960 users will never use that option.  Fixing this
150233965Sjdp     is very hard; fortunately I know how to do it and will do so once
150377298Sobrien     intel's release is out the door.  */
150433965Sjdp
150533965Sjdp  struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
150633965Sjdp  size_t length;
150733965Sjdp  const char *filename;
150833965Sjdp  size_t maxlen = ar_maxnamelen (abfd);
150933965Sjdp
151033965Sjdp  if ((bfd_get_file_flags (abfd) & BFD_TRADITIONAL_FORMAT) != 0)
151133965Sjdp    {
151233965Sjdp      bfd_bsd_truncate_arname (abfd, pathname, arhdr);
151333965Sjdp      return;
151433965Sjdp    }
151533965Sjdp
151633965Sjdp  filename = normalize (abfd, pathname);
151733965Sjdp  if (filename == NULL)
151833965Sjdp    {
151933965Sjdp      /* FIXME */
152033965Sjdp      abort ();
152133965Sjdp    }
152233965Sjdp
152333965Sjdp  length = strlen (filename);
152433965Sjdp
152533965Sjdp  if (length <= maxlen)
152633965Sjdp    memcpy (hdr->ar_name, filename, length);
152733965Sjdp
152833965Sjdp  /* Add the padding character if there is room for it.  */
152933965Sjdp  if (length < maxlen
153033965Sjdp      || (length == maxlen && length < sizeof hdr->ar_name))
153133965Sjdp    (hdr->ar_name)[length] = ar_padchar (abfd);
153233965Sjdp}
153333965Sjdp
153433965Sjdpvoid
1535130561Sobrienbfd_bsd_truncate_arname (bfd *abfd, const char *pathname, char *arhdr)
153633965Sjdp{
153733965Sjdp  struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
153889857Sobrien  size_t length;
153989857Sobrien  const char *filename = strrchr (pathname, '/');
154089857Sobrien  size_t maxlen = ar_maxnamelen (abfd);
154133965Sjdp
154261843Sobrien#ifdef HAVE_DOS_BASED_FILE_SYSTEM
154361843Sobrien  {
154461843Sobrien    /* We could have foo/bar\\baz, or foo\\bar, or d:bar.  */
154561843Sobrien    char *bslash = strrchr (pathname, '\\');
154677298Sobrien    if (filename == NULL || (bslash != NULL && bslash > filename))
154761843Sobrien      filename = bslash;
154861843Sobrien    if (filename == NULL && pathname[0] != '\0' && pathname[1] == ':')
154961843Sobrien      filename = pathname + 1;
155061843Sobrien  }
155161843Sobrien#endif
155261843Sobrien
155333965Sjdp  if (filename == NULL)
155433965Sjdp    filename = pathname;
155533965Sjdp  else
155633965Sjdp    ++filename;
155733965Sjdp
155833965Sjdp  length = strlen (filename);
155933965Sjdp
156033965Sjdp  if (length <= maxlen)
156133965Sjdp    memcpy (hdr->ar_name, filename, length);
156233965Sjdp  else
156333965Sjdp    {
156433965Sjdp      /* pathname: meet procrustes */
156533965Sjdp      memcpy (hdr->ar_name, filename, maxlen);
156633965Sjdp      length = maxlen;
156733965Sjdp    }
156833965Sjdp
156933965Sjdp  if (length < maxlen)
157033965Sjdp    (hdr->ar_name)[length] = ar_padchar (abfd);
157133965Sjdp}
157233965Sjdp
157333965Sjdp/* Store name into ar header.  Truncates the name to fit.
157433965Sjdp   1> strip pathname to be just the basename.
157533965Sjdp   2> if it's short enuf to fit, stuff it in.
157633965Sjdp   3> If it doesn't end with .o, truncate it to fit
157733965Sjdp   4> truncate it before the .o, append .o, stuff THAT in.  */
157833965Sjdp
157933965Sjdp/* This is what gnu ar does.  It's better but incompatible with the
158077298Sobrien   bsd ar.  */
158133965Sjdp
158233965Sjdpvoid
1583130561Sobrienbfd_gnu_truncate_arname (bfd *abfd, const char *pathname, char *arhdr)
158433965Sjdp{
158533965Sjdp  struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
158689857Sobrien  size_t length;
158789857Sobrien  const char *filename = strrchr (pathname, '/');
158889857Sobrien  size_t maxlen = ar_maxnamelen (abfd);
158933965Sjdp
159061843Sobrien#ifdef HAVE_DOS_BASED_FILE_SYSTEM
159161843Sobrien  {
159261843Sobrien    /* We could have foo/bar\\baz, or foo\\bar, or d:bar.  */
159361843Sobrien    char *bslash = strrchr (pathname, '\\');
159477298Sobrien    if (filename == NULL || (bslash != NULL && bslash > filename))
159561843Sobrien      filename = bslash;
159661843Sobrien    if (filename == NULL && pathname[0] != '\0' && pathname[1] == ':')
159761843Sobrien      filename = pathname + 1;
159861843Sobrien  }
159961843Sobrien#endif
160061843Sobrien
160133965Sjdp  if (filename == NULL)
160233965Sjdp    filename = pathname;
160333965Sjdp  else
160433965Sjdp    ++filename;
160533965Sjdp
160633965Sjdp  length = strlen (filename);
160733965Sjdp
160833965Sjdp  if (length <= maxlen)
160933965Sjdp    memcpy (hdr->ar_name, filename, length);
161033965Sjdp  else
161133965Sjdp    {				/* pathname: meet procrustes */
161233965Sjdp      memcpy (hdr->ar_name, filename, maxlen);
161333965Sjdp      if ((filename[length - 2] == '.') && (filename[length - 1] == 'o'))
161433965Sjdp	{
161533965Sjdp	  hdr->ar_name[maxlen - 2] = '.';
161633965Sjdp	  hdr->ar_name[maxlen - 1] = 'o';
161733965Sjdp	}
161833965Sjdp      length = maxlen;
161933965Sjdp    }
162033965Sjdp
162133965Sjdp  if (length < 16)
162233965Sjdp    (hdr->ar_name)[length] = ar_padchar (abfd);
162333965Sjdp}
162433965Sjdp
162577298Sobrien/* The BFD is open for write and has its format set to bfd_archive.  */
162633965Sjdp
1627130561Sobrienbfd_boolean
1628130561Sobrien_bfd_write_archive_contents (bfd *arch)
162933965Sjdp{
163033965Sjdp  bfd *current;
163133965Sjdp  char *etable = NULL;
163233965Sjdp  bfd_size_type elength = 0;
163333965Sjdp  const char *ename = NULL;
1634130561Sobrien  bfd_boolean makemap = bfd_has_map (arch);
1635130561Sobrien  /* If no .o's, don't bother to make a map.  */
1636130561Sobrien  bfd_boolean hasobjects = FALSE;
163733965Sjdp  bfd_size_type wrote;
163833965Sjdp  int tries;
163933965Sjdp
164033965Sjdp  /* Verify the viability of all entries; if any of them live in the
164133965Sjdp     filesystem (as opposed to living in an archive open for input)
164233965Sjdp     then construct a fresh ar_hdr for them.  */
1643218822Sdim  for (current = arch->archive_head;
1644218822Sdim       current != NULL;
1645218822Sdim       current = current->archive_next)
164633965Sjdp    {
164777298Sobrien      /* This check is checking the bfds for the objects we're reading
164877298Sobrien	 from (which are usually either an object file or archive on
164977298Sobrien	 disk), not the archive entries we're writing to.  We don't
165077298Sobrien	 actually create bfds for the archive members, we just copy
165177298Sobrien	 them byte-wise when we write out the archive.  */
165233965Sjdp      if (bfd_write_p (current))
165333965Sjdp	{
165433965Sjdp	  bfd_set_error (bfd_error_invalid_operation);
1655218822Sdim	  goto input_err;
165633965Sjdp	}
165733965Sjdp      if (!current->arelt_data)
165833965Sjdp	{
165933965Sjdp	  current->arelt_data =
1660130561Sobrien	    bfd_ar_hdr_from_filesystem (arch, current->filename, current);
166133965Sjdp	  if (!current->arelt_data)
1662218822Sdim	    goto input_err;
166333965Sjdp
166477298Sobrien	  /* Put in the file name.  */
1665130561Sobrien	  BFD_SEND (arch, _bfd_truncate_arname,
1666130561Sobrien		    (arch, current->filename, (char *) arch_hdr (current)));
166733965Sjdp	}
166833965Sjdp
166933965Sjdp      if (makemap && ! hasobjects)
167077298Sobrien	{			/* Don't bother if we won't make a map!  */
1671218822Sdim	  if ((bfd_check_format (current, bfd_object)))
1672130561Sobrien	    hasobjects = TRUE;
167333965Sjdp	}
167433965Sjdp    }
167533965Sjdp
167633965Sjdp  if (!BFD_SEND (arch, _bfd_construct_extended_name_table,
167733965Sjdp		 (arch, &etable, &elength, &ename)))
1678130561Sobrien    return FALSE;
167933965Sjdp
168033965Sjdp  if (bfd_seek (arch, (file_ptr) 0, SEEK_SET) != 0)
1681130561Sobrien    return FALSE;
1682130561Sobrien  wrote = bfd_bwrite (ARMAG, SARMAG, arch);
168333965Sjdp  if (wrote != SARMAG)
1684130561Sobrien    return FALSE;
168533965Sjdp
168633965Sjdp  if (makemap && hasobjects)
168733965Sjdp    {
1688104834Sobrien      if (! _bfd_compute_and_write_armap (arch, (unsigned int) elength))
1689130561Sobrien	return FALSE;
169033965Sjdp    }
169133965Sjdp
169233965Sjdp  if (elength != 0)
169333965Sjdp    {
169433965Sjdp      struct ar_hdr hdr;
169533965Sjdp
1696218822Sdim      memset (&hdr, ' ', sizeof (struct ar_hdr));
1697218822Sdim      memcpy (hdr.ar_name, ename, strlen (ename));
169833965Sjdp      /* Round size up to even number in archive header.  */
1699218822Sdim      _bfd_ar_spacepad (hdr.ar_size, sizeof (hdr.ar_size), "%-10ld",
1700218822Sdim                        (elength + 1) & ~(bfd_size_type) 1);
1701218822Sdim      memcpy (hdr.ar_fmag, ARFMAG, 2);
1702130561Sobrien      if ((bfd_bwrite (&hdr, sizeof (struct ar_hdr), arch)
170333965Sjdp	   != sizeof (struct ar_hdr))
170489857Sobrien	  || bfd_bwrite (etable, elength, arch) != elength)
1705130561Sobrien	return FALSE;
170633965Sjdp      if ((elength % 2) == 1)
170733965Sjdp	{
1708130561Sobrien	  if (bfd_bwrite ("\012", 1, arch) != 1)
1709130561Sobrien	    return FALSE;
171033965Sjdp	}
171133965Sjdp    }
171233965Sjdp
1713218822Sdim  for (current = arch->archive_head;
1714218822Sdim       current != NULL;
1715218822Sdim       current = current->archive_next)
171633965Sjdp    {
171733965Sjdp      char buffer[DEFAULT_BUFFERSIZE];
171833965Sjdp      unsigned int remaining = arelt_size (current);
171933965Sjdp      struct ar_hdr *hdr = arch_hdr (current);
172033965Sjdp
172177298Sobrien      /* Write ar header.  */
1722130561Sobrien      if (bfd_bwrite (hdr, sizeof (*hdr), arch)
172389857Sobrien	  != sizeof (*hdr))
1724130561Sobrien	return FALSE;
172533965Sjdp      if (bfd_seek (current, (file_ptr) 0, SEEK_SET) != 0)
1726218822Sdim	goto input_err;
172733965Sjdp      while (remaining)
172833965Sjdp	{
172933965Sjdp	  unsigned int amt = DEFAULT_BUFFERSIZE;
173033965Sjdp	  if (amt > remaining)
173133965Sjdp	    amt = remaining;
173233965Sjdp	  errno = 0;
1733130561Sobrien	  if (bfd_bread (buffer, amt, current) != amt)
173433965Sjdp	    {
173533965Sjdp	      if (bfd_get_error () != bfd_error_system_call)
1736218822Sdim		bfd_set_error (bfd_error_file_truncated);
1737218822Sdim	      goto input_err;
173833965Sjdp	    }
1739130561Sobrien	  if (bfd_bwrite (buffer, amt, arch) != amt)
1740130561Sobrien	    return FALSE;
174133965Sjdp	  remaining -= amt;
174233965Sjdp	}
174333965Sjdp      if ((arelt_size (current) % 2) == 1)
174433965Sjdp	{
1745130561Sobrien	  if (bfd_bwrite ("\012", 1, arch) != 1)
1746130561Sobrien	    return FALSE;
174733965Sjdp	}
174833965Sjdp    }
174933965Sjdp
175033965Sjdp  if (makemap && hasobjects)
175133965Sjdp    {
175233965Sjdp      /* Verify the timestamp in the archive file.  If it would not be
175333965Sjdp	 accepted by the linker, rewrite it until it would be.  If
175433965Sjdp	 anything odd happens, break out and just return.  (The
175533965Sjdp	 Berkeley linker checks the timestamp and refuses to read the
175633965Sjdp	 table-of-contents if it is >60 seconds less than the file's
175733965Sjdp	 modified-time.  That painful hack requires this painful hack.  */
175833965Sjdp      tries = 1;
175933965Sjdp      do
176033965Sjdp	{
176133965Sjdp	  if (bfd_update_armap_timestamp (arch))
176233965Sjdp	    break;
176333965Sjdp	  (*_bfd_error_handler)
176460484Sobrien	    (_("Warning: writing archive was slow: rewriting timestamp\n"));
176533965Sjdp	}
176633965Sjdp      while (++tries < 6);
176733965Sjdp    }
176833965Sjdp
1769130561Sobrien  return TRUE;
1770218822Sdim
1771218822Sdim input_err:
1772218822Sdim  bfd_set_error (bfd_error_on_input, current, bfd_get_error ());
1773218822Sdim  return FALSE;
177433965Sjdp}
177533965Sjdp
177677298Sobrien/* Note that the namidx for the first symbol is 0.  */
177733965Sjdp
1778130561Sobrienbfd_boolean
1779130561Sobrien_bfd_compute_and_write_armap (bfd *arch, unsigned int elength)
178033965Sjdp{
178133965Sjdp  char *first_name = NULL;
178233965Sjdp  bfd *current;
178333965Sjdp  file_ptr elt_no = 0;
178433965Sjdp  struct orl *map = NULL;
1785218822Sdim  unsigned int orl_max = 1024;		/* Fine initial default.  */
178689857Sobrien  unsigned int orl_count = 0;
1787218822Sdim  int stridx = 0;
178833965Sjdp  asymbol **syms = NULL;
178933965Sjdp  long syms_max = 0;
1790130561Sobrien  bfd_boolean ret;
179189857Sobrien  bfd_size_type amt;
179233965Sjdp
179377298Sobrien  /* Dunno if this is the best place for this info...  */
179433965Sjdp  if (elength != 0)
179533965Sjdp    elength += sizeof (struct ar_hdr);
179633965Sjdp  elength += elength % 2;
179733965Sjdp
1798130561Sobrien  amt = orl_max * sizeof (struct orl);
1799130561Sobrien  map = bfd_malloc (amt);
180033965Sjdp  if (map == NULL)
180133965Sjdp    goto error_return;
180233965Sjdp
180333965Sjdp  /* We put the symbol names on the arch objalloc, and then discard
180433965Sjdp     them when done.  */
1805130561Sobrien  first_name = bfd_alloc (arch, 1);
180633965Sjdp  if (first_name == NULL)
180733965Sjdp    goto error_return;
180833965Sjdp
180977298Sobrien  /* Drop all the files called __.SYMDEF, we're going to make our own.  */
181033965Sjdp  while (arch->archive_head &&
181133965Sjdp	 strcmp (arch->archive_head->filename, "__.SYMDEF") == 0)
1812218822Sdim    arch->archive_head = arch->archive_head->archive_next;
181333965Sjdp
181477298Sobrien  /* Map over each element.  */
181533965Sjdp  for (current = arch->archive_head;
1816130561Sobrien       current != NULL;
1817218822Sdim       current = current->archive_next, elt_no++)
181833965Sjdp    {
1819104834Sobrien      if (bfd_check_format (current, bfd_object)
1820104834Sobrien	  && (bfd_get_file_flags (current) & HAS_SYMS) != 0)
182133965Sjdp	{
182233965Sjdp	  long storage;
182333965Sjdp	  long symcount;
182433965Sjdp	  long src_count;
182533965Sjdp
182633965Sjdp	  storage = bfd_get_symtab_upper_bound (current);
182733965Sjdp	  if (storage < 0)
182833965Sjdp	    goto error_return;
182933965Sjdp
183033965Sjdp	  if (storage != 0)
183133965Sjdp	    {
183233965Sjdp	      if (storage > syms_max)
183333965Sjdp		{
183433965Sjdp		  if (syms_max > 0)
183533965Sjdp		    free (syms);
183633965Sjdp		  syms_max = storage;
1837130561Sobrien		  syms = bfd_malloc (syms_max);
183833965Sjdp		  if (syms == NULL)
183933965Sjdp		    goto error_return;
184033965Sjdp		}
184133965Sjdp	      symcount = bfd_canonicalize_symtab (current, syms);
184233965Sjdp	      if (symcount < 0)
184333965Sjdp		goto error_return;
184433965Sjdp
184577298Sobrien	      /* Now map over all the symbols, picking out the ones we
184677298Sobrien                 want.  */
184733965Sjdp	      for (src_count = 0; src_count < symcount; src_count++)
184833965Sjdp		{
184933965Sjdp		  flagword flags = (syms[src_count])->flags;
185033965Sjdp		  asection *sec = syms[src_count]->section;
185133965Sjdp
185233965Sjdp		  if ((flags & BSF_GLOBAL ||
185333965Sjdp		       flags & BSF_WEAK ||
185433965Sjdp		       flags & BSF_INDIRECT ||
185533965Sjdp		       bfd_is_com_section (sec))
185633965Sjdp		      && ! bfd_is_und_section (sec))
185733965Sjdp		    {
185889857Sobrien		      bfd_size_type namelen;
185933965Sjdp		      struct orl *new_map;
186033965Sjdp
186177298Sobrien		      /* This symbol will go into the archive header.  */
186233965Sjdp		      if (orl_count == orl_max)
186333965Sjdp			{
186433965Sjdp			  orl_max *= 2;
1865130561Sobrien			  amt = orl_max * sizeof (struct orl);
1866130561Sobrien			  new_map = bfd_realloc (map, amt);
1867130561Sobrien			  if (new_map == NULL)
186833965Sjdp			    goto error_return;
186933965Sjdp
187033965Sjdp			  map = new_map;
187133965Sjdp			}
187233965Sjdp
187333965Sjdp		      namelen = strlen (syms[src_count]->name);
187489857Sobrien		      amt = sizeof (char *);
1875130561Sobrien		      map[orl_count].name = bfd_alloc (arch, amt);
187633965Sjdp		      if (map[orl_count].name == NULL)
187733965Sjdp			goto error_return;
187833965Sjdp		      *(map[orl_count].name) = bfd_alloc (arch, namelen + 1);
187933965Sjdp		      if (*(map[orl_count].name) == NULL)
188033965Sjdp			goto error_return;
188133965Sjdp		      strcpy (*(map[orl_count].name), syms[src_count]->name);
188289857Sobrien		      map[orl_count].u.abfd = current;
188389857Sobrien		      map[orl_count].namidx = stridx;
188433965Sjdp
188533965Sjdp		      stridx += namelen + 1;
188633965Sjdp		      ++orl_count;
188733965Sjdp		    }
188833965Sjdp		}
188933965Sjdp	    }
189033965Sjdp
189133965Sjdp	  /* Now ask the BFD to free up any cached information, so we
189233965Sjdp	     don't fill all of memory with symbol tables.  */
189333965Sjdp	  if (! bfd_free_cached_info (current))
189433965Sjdp	    goto error_return;
189533965Sjdp	}
189633965Sjdp    }
189733965Sjdp
189877298Sobrien  /* OK, now we have collected all the data, let's write them out.  */
189933965Sjdp  ret = BFD_SEND (arch, write_armap,
190033965Sjdp		  (arch, elength, map, orl_count, stridx));
190133965Sjdp
190233965Sjdp  if (syms_max > 0)
190333965Sjdp    free (syms);
190433965Sjdp  if (map != NULL)
190533965Sjdp    free (map);
190633965Sjdp  if (first_name != NULL)
190733965Sjdp    bfd_release (arch, first_name);
190833965Sjdp
190933965Sjdp  return ret;
191033965Sjdp
191133965Sjdp error_return:
191233965Sjdp  if (syms_max > 0)
191333965Sjdp    free (syms);
191433965Sjdp  if (map != NULL)
191533965Sjdp    free (map);
191633965Sjdp  if (first_name != NULL)
191733965Sjdp    bfd_release (arch, first_name);
191833965Sjdp
1919130561Sobrien  return FALSE;
192033965Sjdp}
192133965Sjdp
1922130561Sobrienbfd_boolean
1923130561Sobrienbsd_write_armap (bfd *arch,
1924130561Sobrien		 unsigned int elength,
1925130561Sobrien		 struct orl *map,
1926130561Sobrien		 unsigned int orl_count,
1927130561Sobrien		 int stridx)
192833965Sjdp{
192933965Sjdp  int padit = stridx & 1;
193033965Sjdp  unsigned int ranlibsize = orl_count * BSD_SYMDEF_SIZE;
193133965Sjdp  unsigned int stringsize = stridx + padit;
193277298Sobrien  /* Include 8 bytes to store ranlibsize and stringsize in output.  */
193333965Sjdp  unsigned int mapsize = ranlibsize + stringsize + 8;
193433965Sjdp  file_ptr firstreal;
193533965Sjdp  bfd *current = arch->archive_head;
1936218822Sdim  bfd *last_elt = current;	/* Last element arch seen.  */
193733965Sjdp  bfd_byte temp[4];
193833965Sjdp  unsigned int count;
193933965Sjdp  struct ar_hdr hdr;
194033965Sjdp  struct stat statbuf;
194133965Sjdp
194233965Sjdp  firstreal = mapsize + elength + sizeof (struct ar_hdr) + SARMAG;
194333965Sjdp
194433965Sjdp  stat (arch->filename, &statbuf);
1945218822Sdim  memset (&hdr, ' ', sizeof (struct ar_hdr));
1946218822Sdim  memcpy (hdr.ar_name, RANLIBMAG, strlen (RANLIBMAG));
194733965Sjdp  /* Remember the timestamp, to keep it holy.  But fudge it a little.  */
194833965Sjdp  bfd_ardata (arch)->armap_timestamp = statbuf.st_mtime + ARMAP_TIME_OFFSET;
194933965Sjdp  bfd_ardata (arch)->armap_datepos = (SARMAG
195033965Sjdp				      + offsetof (struct ar_hdr, ar_date[0]));
1951218822Sdim  _bfd_ar_spacepad (hdr.ar_date, sizeof (hdr.ar_date), "%ld",
1952218822Sdim                    bfd_ardata (arch)->armap_timestamp);
1953218822Sdim  _bfd_ar_spacepad (hdr.ar_uid, sizeof (hdr.ar_uid), "%ld", getuid ());
1954218822Sdim  _bfd_ar_spacepad (hdr.ar_gid, sizeof (hdr.ar_gid), "%ld", getgid ());
1955218822Sdim  _bfd_ar_spacepad (hdr.ar_size, sizeof (hdr.ar_size), "%-10ld", mapsize);
1956218822Sdim  memcpy (hdr.ar_fmag, ARFMAG, 2);
1957130561Sobrien  if (bfd_bwrite (&hdr, sizeof (struct ar_hdr), arch)
195833965Sjdp      != sizeof (struct ar_hdr))
1959130561Sobrien    return FALSE;
196089857Sobrien  H_PUT_32 (arch, ranlibsize, temp);
1961130561Sobrien  if (bfd_bwrite (temp, sizeof (temp), arch) != sizeof (temp))
1962130561Sobrien    return FALSE;
196333965Sjdp
196433965Sjdp  for (count = 0; count < orl_count; count++)
196533965Sjdp    {
196633965Sjdp      bfd_byte buf[BSD_SYMDEF_SIZE];
196733965Sjdp
196889857Sobrien      if (map[count].u.abfd != last_elt)
196933965Sjdp	{
197033965Sjdp	  do
197133965Sjdp	    {
197233965Sjdp	      firstreal += arelt_size (current) + sizeof (struct ar_hdr);
197333965Sjdp	      firstreal += firstreal % 2;
1974218822Sdim	      current = current->archive_next;
197533965Sjdp	    }
197689857Sobrien	  while (current != map[count].u.abfd);
1977218822Sdim	}
197833965Sjdp
197933965Sjdp      last_elt = current;
198089857Sobrien      H_PUT_32 (arch, map[count].namidx, buf);
198189857Sobrien      H_PUT_32 (arch, firstreal, buf + BSD_SYMDEF_OFFSET_SIZE);
1982130561Sobrien      if (bfd_bwrite (buf, BSD_SYMDEF_SIZE, arch)
198389857Sobrien	  != BSD_SYMDEF_SIZE)
1984130561Sobrien	return FALSE;
198533965Sjdp    }
198633965Sjdp
198777298Sobrien  /* Now write the strings themselves.  */
198889857Sobrien  H_PUT_32 (arch, stringsize, temp);
1989130561Sobrien  if (bfd_bwrite (temp, sizeof (temp), arch) != sizeof (temp))
1990130561Sobrien    return FALSE;
199133965Sjdp  for (count = 0; count < orl_count; count++)
199233965Sjdp    {
199333965Sjdp      size_t len = strlen (*map[count].name) + 1;
199433965Sjdp
1995130561Sobrien      if (bfd_bwrite (*map[count].name, len, arch) != len)
1996130561Sobrien	return FALSE;
199733965Sjdp    }
199833965Sjdp
199933965Sjdp  /* The spec sez this should be a newline.  But in order to be
200077298Sobrien     bug-compatible for sun's ar we use a null.  */
200133965Sjdp  if (padit)
200233965Sjdp    {
2003130561Sobrien      if (bfd_bwrite ("", 1, arch) != 1)
2004130561Sobrien	return FALSE;
200533965Sjdp    }
200633965Sjdp
2007130561Sobrien  return TRUE;
200833965Sjdp}
200933965Sjdp
201033965Sjdp/* At the end of archive file handling, update the timestamp in the
201133965Sjdp   file, so the linker will accept it.
201233965Sjdp
2013130561Sobrien   Return TRUE if the timestamp was OK, or an unusual problem happened.
2014130561Sobrien   Return FALSE if we updated the timestamp.  */
201533965Sjdp
2016130561Sobrienbfd_boolean
2017130561Sobrien_bfd_archive_bsd_update_armap_timestamp (bfd *arch)
201833965Sjdp{
201933965Sjdp  struct stat archstat;
202033965Sjdp  struct ar_hdr hdr;
202133965Sjdp
202233965Sjdp  /* Flush writes, get last-write timestamp from file, and compare it
202333965Sjdp     to the timestamp IN the file.  */
202433965Sjdp  bfd_flush (arch);
202533965Sjdp  if (bfd_stat (arch, &archstat) == -1)
202633965Sjdp    {
2027130561Sobrien      bfd_perror (_("Reading archive file mod timestamp"));
202877298Sobrien
202977298Sobrien      /* Can't read mod time for some reason.  */
2030130561Sobrien      return TRUE;
203133965Sjdp    }
203233965Sjdp  if (archstat.st_mtime <= bfd_ardata (arch)->armap_timestamp)
203377298Sobrien    /* OK by the linker's rules.  */
2034130561Sobrien    return TRUE;
203533965Sjdp
203633965Sjdp  /* Update the timestamp.  */
203733965Sjdp  bfd_ardata (arch)->armap_timestamp = archstat.st_mtime + ARMAP_TIME_OFFSET;
203833965Sjdp
203933965Sjdp  /* Prepare an ASCII version suitable for writing.  */
2040218822Sdim  memset (hdr.ar_date, ' ', sizeof (hdr.ar_date));
2041218822Sdim  _bfd_ar_spacepad (hdr.ar_date, sizeof (hdr.ar_date), "%ld",
2042218822Sdim                    bfd_ardata (arch)->armap_timestamp);
204333965Sjdp
204433965Sjdp  /* Write it into the file.  */
204533965Sjdp  bfd_ardata (arch)->armap_datepos = (SARMAG
204633965Sjdp				      + offsetof (struct ar_hdr, ar_date[0]));
204733965Sjdp  if (bfd_seek (arch, bfd_ardata (arch)->armap_datepos, SEEK_SET) != 0
2048130561Sobrien      || (bfd_bwrite (hdr.ar_date, sizeof (hdr.ar_date), arch)
204933965Sjdp	  != sizeof (hdr.ar_date)))
205033965Sjdp    {
2051130561Sobrien      bfd_perror (_("Writing updated armap timestamp"));
205277298Sobrien
205377298Sobrien      /* Some error while writing.  */
2054130561Sobrien      return TRUE;
205533965Sjdp    }
205633965Sjdp
205777298Sobrien  /* We updated the timestamp successfully.  */
2058130561Sobrien  return FALSE;
205933965Sjdp}
206033965Sjdp
206133965Sjdp/* A coff armap looks like :
206233965Sjdp   lARMAG
206333965Sjdp   struct ar_hdr with name = '/'
206433965Sjdp   number of symbols
206533965Sjdp   offset of file for symbol 0
206633965Sjdp   offset of file for symbol 1
206733965Sjdp
206833965Sjdp   offset of file for symbol n-1
206933965Sjdp   symbol name 0
207033965Sjdp   symbol name 1
207133965Sjdp
2072218822Sdim   symbol name n-1  */
207333965Sjdp
2074130561Sobrienbfd_boolean
2075130561Sobriencoff_write_armap (bfd *arch,
2076130561Sobrien		  unsigned int elength,
2077130561Sobrien		  struct orl *map,
2078130561Sobrien		  unsigned int symbol_count,
2079130561Sobrien		  int stridx)
208033965Sjdp{
208133965Sjdp  /* The size of the ranlib is the number of exported symbols in the
208289857Sobrien     archive * the number of bytes in an int, + an int for the count.  */
208333965Sjdp  unsigned int ranlibsize = (symbol_count * 4) + 4;
208433965Sjdp  unsigned int stringsize = stridx;
208533965Sjdp  unsigned int mapsize = stringsize + ranlibsize;
208689857Sobrien  unsigned int archive_member_file_ptr;
208733965Sjdp  bfd *current = arch->archive_head;
208833965Sjdp  unsigned int count;
208933965Sjdp  struct ar_hdr hdr;
209033965Sjdp  int padit = mapsize & 1;
209133965Sjdp
209233965Sjdp  if (padit)
209333965Sjdp    mapsize++;
209433965Sjdp
209577298Sobrien  /* Work out where the first object file will go in the archive.  */
209633965Sjdp  archive_member_file_ptr = (mapsize
209733965Sjdp			     + elength
209833965Sjdp			     + sizeof (struct ar_hdr)
209933965Sjdp			     + SARMAG);
210033965Sjdp
2101218822Sdim  memset (&hdr, ' ', sizeof (struct ar_hdr));
210233965Sjdp  hdr.ar_name[0] = '/';
2103218822Sdim  _bfd_ar_spacepad (hdr.ar_size, sizeof (hdr.ar_size), "%-10ld",
2104218822Sdim                    mapsize);
2105218822Sdim  _bfd_ar_spacepad (hdr.ar_date, sizeof (hdr.ar_date), "%ld",
2106218822Sdim                    time (NULL));
210777298Sobrien  /* This, at least, is what Intel coff sets the values to.  */
2108218822Sdim  _bfd_ar_spacepad (hdr.ar_uid, sizeof (hdr.ar_uid), "%ld", 0);
2109218822Sdim  _bfd_ar_spacepad (hdr.ar_gid, sizeof (hdr.ar_gid), "%ld", 0);
2110218822Sdim  _bfd_ar_spacepad (hdr.ar_mode, sizeof (hdr.ar_mode), "%-7lo", 0);
2111218822Sdim  memcpy (hdr.ar_fmag, ARFMAG, 2);
211233965Sjdp
211377298Sobrien  /* Write the ar header for this item and the number of symbols.  */
2114130561Sobrien  if (bfd_bwrite (&hdr, sizeof (struct ar_hdr), arch)
211533965Sjdp      != sizeof (struct ar_hdr))
2116130561Sobrien    return FALSE;
211733965Sjdp
211894536Sobrien  if (!bfd_write_bigendian_4byte_int (arch, symbol_count))
2119130561Sobrien    return FALSE;
212033965Sjdp
212133965Sjdp  /* Two passes, first write the file offsets for each symbol -
212233965Sjdp     remembering that each offset is on a two byte boundary.  */
212333965Sjdp
212433965Sjdp  /* Write out the file offset for the file associated with each
212533965Sjdp     symbol, and remember to keep the offsets padded out.  */
212633965Sjdp
212733965Sjdp  current = arch->archive_head;
212833965Sjdp  count = 0;
2129130561Sobrien  while (current != NULL && count < symbol_count)
213033965Sjdp    {
213177298Sobrien      /* For each symbol which is used defined in this object, write
213277298Sobrien	 out the object file's address in the archive.  */
213333965Sjdp
213489857Sobrien      while (count < symbol_count && map[count].u.abfd == current)
213533965Sjdp	{
213694536Sobrien	  if (!bfd_write_bigendian_4byte_int (arch, archive_member_file_ptr))
2137130561Sobrien	    return FALSE;
213833965Sjdp	  count++;
213933965Sjdp	}
214077298Sobrien      /* Add size of this archive entry.  */
2141130561Sobrien      archive_member_file_ptr += arelt_size (current) + sizeof (struct ar_hdr);
214277298Sobrien      /* Remember aboout the even alignment.  */
214333965Sjdp      archive_member_file_ptr += archive_member_file_ptr % 2;
2144218822Sdim      current = current->archive_next;
214533965Sjdp    }
214633965Sjdp
214777298Sobrien  /* Now write the strings themselves.  */
214833965Sjdp  for (count = 0; count < symbol_count; count++)
214933965Sjdp    {
215033965Sjdp      size_t len = strlen (*map[count].name) + 1;
215133965Sjdp
2152130561Sobrien      if (bfd_bwrite (*map[count].name, len, arch) != len)
2153130561Sobrien	return FALSE;
215433965Sjdp    }
215533965Sjdp
215633965Sjdp  /* The spec sez this should be a newline.  But in order to be
215777298Sobrien     bug-compatible for arc960 we use a null.  */
215833965Sjdp  if (padit)
215933965Sjdp    {
2160130561Sobrien      if (bfd_bwrite ("", 1, arch) != 1)
2161130561Sobrien	return FALSE;
216233965Sjdp    }
216333965Sjdp
2164130561Sobrien  return TRUE;
216533965Sjdp}
2166