12159047fSniklas /* BFD back-end for archive files (libraries).
2b55d4692Sfgsch Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3007c2a45Smiod 2000, 2001, 2002, 2003
4b305b0f1Sespie Free Software Foundation, Inc.
52159047fSniklas Written by Cygnus Support. Mostly Gumby Henkel-Wallace's fault.
62159047fSniklas
72159047fSniklas This file is part of BFD, the Binary File Descriptor library.
82159047fSniklas
92159047fSniklas This program is free software; you can redistribute it and/or modify
102159047fSniklas it under the terms of the GNU General Public License as published by
112159047fSniklas the Free Software Foundation; either version 2 of the License, or
122159047fSniklas (at your option) any later version.
132159047fSniklas
142159047fSniklas This program is distributed in the hope that it will be useful,
152159047fSniklas but WITHOUT ANY WARRANTY; without even the implied warranty of
162159047fSniklas MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
172159047fSniklas GNU General Public License for more details.
182159047fSniklas
192159047fSniklas You should have received a copy of the GNU General Public License
202159047fSniklas along with this program; if not, write to the Free Software
212159047fSniklas Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
222159047fSniklas
232159047fSniklas /*
242159047fSniklas @setfilename archive-info
252159047fSniklas SECTION
262159047fSniklas Archives
272159047fSniklas
282159047fSniklas DESCRIPTION
292159047fSniklas An archive (or library) is just another BFD. It has a symbol
302159047fSniklas table, although there's not much a user program will do with it.
312159047fSniklas
322159047fSniklas The big difference between an archive BFD and an ordinary BFD
332159047fSniklas is that the archive doesn't have sections. Instead it has a
342159047fSniklas chain of BFDs that are considered its contents. These BFDs can
352159047fSniklas be manipulated like any other. The BFDs contained in an
362159047fSniklas archive opened for reading will all be opened for reading. You
372159047fSniklas may put either input or output BFDs into an archive opened for
382159047fSniklas output; they will be handled correctly when the archive is closed.
392159047fSniklas
402159047fSniklas Use <<bfd_openr_next_archived_file>> to step through
412159047fSniklas the contents of an archive opened for input. You don't
422159047fSniklas have to read the entire archive if you don't want
432159047fSniklas to! Read it until you find what you want.
442159047fSniklas
452159047fSniklas Archive contents of output BFDs are chained through the
462159047fSniklas <<next>> pointer in a BFD. The first one is findable through
472159047fSniklas the <<archive_head>> slot of the archive. Set it with
482159047fSniklas <<bfd_set_archive_head>> (q.v.). A given BFD may be in only one
492159047fSniklas open output archive at a time.
502159047fSniklas
512159047fSniklas As expected, the BFD archive code is more general than the
522159047fSniklas archive code of any given environment. BFD archives may
532159047fSniklas contain files of different formats (e.g., a.out and coff) and
542159047fSniklas even different architectures. You may even place archives
552159047fSniklas recursively into archives!
562159047fSniklas
572159047fSniklas This can cause unexpected confusion, since some archive
582159047fSniklas formats are more expressive than others. For instance, Intel
592159047fSniklas COFF archives can preserve long filenames; SunOS a.out archives
602159047fSniklas cannot. If you move a file from the first to the second
612159047fSniklas format and back again, the filename may be truncated.
622159047fSniklas Likewise, different a.out environments have different
632159047fSniklas conventions as to how they truncate filenames, whether they
642159047fSniklas preserve directory names in filenames, etc. When
652159047fSniklas interoperating with native tools, be sure your files are
662159047fSniklas homogeneous.
672159047fSniklas
682159047fSniklas Beware: most of these formats do not react well to the
692159047fSniklas presence of spaces in filenames. We do the best we can, but
702159047fSniklas can't always handle this case due to restrictions in the format of
712159047fSniklas archives. Many Unix utilities are braindead in regards to
722159047fSniklas spaces and such in filenames anyway, so this shouldn't be much
732159047fSniklas of a restriction.
742159047fSniklas
752159047fSniklas Archives are supported in BFD in <<archive.c>>.
762159047fSniklas
772159047fSniklas */
782159047fSniklas
792159047fSniklas /* Assumes:
802159047fSniklas o - all archive elements start on an even boundary, newline padded;
812159047fSniklas o - all arch headers are char *;
822159047fSniklas o - all arch headers are the same size (across architectures).
832159047fSniklas */
842159047fSniklas
852159047fSniklas /* Some formats provide a way to cram a long filename into the short
862159047fSniklas (16 chars) space provided by a BSD archive. The trick is: make a
872159047fSniklas special "file" in the front of the archive, sort of like the SYMDEF
882159047fSniklas entry. If the filename is too long to fit, put it in the extended
892159047fSniklas name table, and use its index as the filename. To prevent
902159047fSniklas confusion prepend the index with a space. This means you can't
912159047fSniklas have filenames that start with a space, but then again, many Unix
922159047fSniklas utilities can't handle that anyway.
932159047fSniklas
942159047fSniklas This scheme unfortunately requires that you stand on your head in
952159047fSniklas order to write an archive since you need to put a magic file at the
962159047fSniklas front, and need to touch every entry to do so. C'est la vie.
972159047fSniklas
982159047fSniklas We support two variants of this idea:
992159047fSniklas The SVR4 format (extended name table is named "//"),
1002159047fSniklas and an extended pseudo-BSD variant (extended name table is named
1012159047fSniklas "ARFILENAMES/"). The origin of the latter format is uncertain.
1022159047fSniklas
1032159047fSniklas BSD 4.4 uses a third scheme: It writes a long filename
1042159047fSniklas directly after the header. This allows 'ar q' to work.
1052159047fSniklas We currently can read BSD 4.4 archives, but not write them.
1062159047fSniklas */
1072159047fSniklas
1082159047fSniklas /* Summary of archive member names:
1092159047fSniklas
1102159047fSniklas Symbol table (must be first):
1112159047fSniklas "__.SYMDEF " - Symbol table, Berkeley style, produced by ranlib.
1122159047fSniklas "/ " - Symbol table, system 5 style.
1132159047fSniklas
1142159047fSniklas Long name table (must be before regular file members):
1152159047fSniklas "// " - Long name table, System 5 R4 style.
1162159047fSniklas "ARFILENAMES/ " - Long name table, non-standard extended BSD (not BSD 4.4).
1172159047fSniklas
1182159047fSniklas Regular file members with short names:
1192159047fSniklas "filename.o/ " - Regular file, System 5 style (embedded spaces ok).
1202159047fSniklas "filename.o " - Regular file, Berkeley style (no embedded spaces).
1212159047fSniklas
1222159047fSniklas Regular files with long names (or embedded spaces, for BSD variants):
1232159047fSniklas "/18 " - SVR4 style, name at offset 18 in name table.
1242159047fSniklas "#1/23 " - Long name (or embedded paces) 23 characters long,
1252159047fSniklas BSD 4.4 style, full name follows header.
1262159047fSniklas Implemented for reading, not writing.
1272159047fSniklas " 18 " - Long name 18 characters long, extended pseudo-BSD.
1282159047fSniklas */
1292159047fSniklas
1302159047fSniklas #include "bfd.h"
1312159047fSniklas #include "sysdep.h"
1322159047fSniklas #include "libbfd.h"
1332159047fSniklas #include "aout/ar.h"
1342159047fSniklas #include "aout/ranlib.h"
135c074d1c9Sdrahn #include "safe-ctype.h"
1362159047fSniklas
1372159047fSniklas #ifndef errno
1382159047fSniklas extern int errno;
1392159047fSniklas #endif
1402159047fSniklas
1412159047fSniklas #ifdef GNU960
1422159047fSniklas #define BFD_GNU960_ARMAG(abfd) (BFD_COFF_FILE_P((abfd)) ? ARMAG : ARMAGB)
1432159047fSniklas #endif
1442159047fSniklas
1452159047fSniklas /* We keep a cache of archive filepointers to archive elements to
1462159047fSniklas speed up searching the archive by filepos. We only add an entry to
1472159047fSniklas the cache when we actually read one. We also don't sort the cache;
1482159047fSniklas it's generally short enough to search linearly.
1492159047fSniklas Note that the pointers here point to the front of the ar_hdr, not
150b55d4692Sfgsch to the front of the contents! */
151b55d4692Sfgsch struct ar_cache {
1522159047fSniklas file_ptr ptr;
1532159047fSniklas bfd *arelt;
1542159047fSniklas struct ar_cache *next;
1552159047fSniklas };
1562159047fSniklas
1572159047fSniklas #define ar_padchar(abfd) ((abfd)->xvec->ar_pad_char)
1582159047fSniklas #define ar_maxnamelen(abfd) ((abfd)->xvec->ar_max_namelen)
1592159047fSniklas
1602159047fSniklas #define arch_eltdata(bfd) ((struct areltdata *) ((bfd)->arelt_data))
1612159047fSniklas #define arch_hdr(bfd) ((struct ar_hdr *) arch_eltdata(bfd)->arch_header)
1622159047fSniklas
1632159047fSniklas
164c074d1c9Sdrahn bfd_boolean
_bfd_generic_mkarchive(bfd * abfd)165007c2a45Smiod _bfd_generic_mkarchive (bfd *abfd)
1662159047fSniklas {
167c074d1c9Sdrahn bfd_size_type amt = sizeof (struct artdata);
1682159047fSniklas
169007c2a45Smiod abfd->tdata.aout_ar_data = bfd_zalloc (abfd, amt);
1702159047fSniklas if (bfd_ardata (abfd) == NULL)
171c074d1c9Sdrahn return FALSE;
1722159047fSniklas
1732159047fSniklas bfd_ardata (abfd)->cache = NULL;
1742159047fSniklas bfd_ardata (abfd)->archive_head = NULL;
1752159047fSniklas bfd_ardata (abfd)->symdefs = NULL;
1762159047fSniklas bfd_ardata (abfd)->extended_names = NULL;
1772159047fSniklas bfd_ardata (abfd)->tdata = NULL;
1782159047fSniklas
179c074d1c9Sdrahn return TRUE;
1802159047fSniklas }
1812159047fSniklas
1822159047fSniklas /*
1832159047fSniklas FUNCTION
1842159047fSniklas bfd_get_next_mapent
1852159047fSniklas
1862159047fSniklas SYNOPSIS
187007c2a45Smiod symindex bfd_get_next_mapent
188007c2a45Smiod (bfd *abfd, symindex previous, carsym **sym);
1892159047fSniklas
1902159047fSniklas DESCRIPTION
1912159047fSniklas Step through archive @var{abfd}'s symbol table (if it
1922159047fSniklas has one). Successively update @var{sym} with the next symbol's
1932159047fSniklas information, returning that symbol's (internal) index into the
1942159047fSniklas symbol table.
1952159047fSniklas
1962159047fSniklas Supply <<BFD_NO_MORE_SYMBOLS>> as the @var{previous} entry to get
1972159047fSniklas the first one; returns <<BFD_NO_MORE_SYMBOLS>> when you've already
1982159047fSniklas got the last one.
1992159047fSniklas
2002159047fSniklas A <<carsym>> is a canonical archive symbol. The only
2012159047fSniklas user-visible element is its name, a null-terminated string.
2022159047fSniklas */
2032159047fSniklas
2042159047fSniklas symindex
bfd_get_next_mapent(bfd * abfd,symindex prev,carsym ** entry)205007c2a45Smiod bfd_get_next_mapent (bfd *abfd, symindex prev, carsym **entry)
2062159047fSniklas {
2072159047fSniklas if (!bfd_has_map (abfd))
2082159047fSniklas {
2092159047fSniklas bfd_set_error (bfd_error_invalid_operation);
2102159047fSniklas return BFD_NO_MORE_SYMBOLS;
2112159047fSniklas }
2122159047fSniklas
2132159047fSniklas if (prev == BFD_NO_MORE_SYMBOLS)
2142159047fSniklas prev = 0;
2152159047fSniklas else
2162159047fSniklas ++prev;
2172159047fSniklas if (prev >= bfd_ardata (abfd)->symdef_count)
2182159047fSniklas return BFD_NO_MORE_SYMBOLS;
2192159047fSniklas
2202159047fSniklas *entry = (bfd_ardata (abfd)->symdefs + prev);
2212159047fSniklas return prev;
2222159047fSniklas }
2232159047fSniklas
2242159047fSniklas /* To be called by backends only */
2252159047fSniklas
2262159047fSniklas bfd *
_bfd_create_empty_archive_element_shell(bfd * obfd)227007c2a45Smiod _bfd_create_empty_archive_element_shell (bfd *obfd)
2282159047fSniklas {
229c88b1d6cSniklas return _bfd_new_bfd_contained_in (obfd);
2302159047fSniklas }
2312159047fSniklas
2322159047fSniklas /*
2332159047fSniklas FUNCTION
2342159047fSniklas bfd_set_archive_head
2352159047fSniklas
2362159047fSniklas SYNOPSIS
237c074d1c9Sdrahn bfd_boolean bfd_set_archive_head (bfd *output, bfd *new_head);
2382159047fSniklas
2392159047fSniklas DESCRIPTION
2402159047fSniklas Set the head of the chain of
2412159047fSniklas BFDs contained in the archive @var{output} to @var{new_head}.
2422159047fSniklas */
2432159047fSniklas
244c074d1c9Sdrahn bfd_boolean
bfd_set_archive_head(bfd * output_archive,bfd * new_head)245007c2a45Smiod bfd_set_archive_head (bfd *output_archive, bfd *new_head)
2462159047fSniklas {
2472159047fSniklas output_archive->archive_head = new_head;
248c074d1c9Sdrahn return TRUE;
2492159047fSniklas }
2502159047fSniklas
2512159047fSniklas bfd *
_bfd_look_for_bfd_in_cache(bfd * arch_bfd,file_ptr filepos)252007c2a45Smiod _bfd_look_for_bfd_in_cache (bfd *arch_bfd, file_ptr filepos)
2532159047fSniklas {
2542159047fSniklas struct ar_cache *current;
2552159047fSniklas
2562159047fSniklas for (current = bfd_ardata (arch_bfd)->cache; current != NULL;
2572159047fSniklas current = current->next)
2582159047fSniklas if (current->ptr == filepos)
2592159047fSniklas return current->arelt;
2602159047fSniklas
2612159047fSniklas return NULL;
2622159047fSniklas }
2632159047fSniklas
2642159047fSniklas /* Kind of stupid to call cons for each one, but we don't do too many */
265c074d1c9Sdrahn bfd_boolean
_bfd_add_bfd_to_archive_cache(bfd * arch_bfd,file_ptr filepos,bfd * new_elt)266007c2a45Smiod _bfd_add_bfd_to_archive_cache (bfd *arch_bfd, file_ptr filepos, bfd *new_elt)
2672159047fSniklas {
268c074d1c9Sdrahn bfd_size_type amt = sizeof (struct ar_cache);
2692159047fSniklas
270007c2a45Smiod struct ar_cache *new_cache = bfd_zalloc (arch_bfd, amt);
2712159047fSniklas if (new_cache == NULL)
272c074d1c9Sdrahn return FALSE;
2732159047fSniklas
2742159047fSniklas new_cache->ptr = filepos;
2752159047fSniklas new_cache->arelt = new_elt;
276007c2a45Smiod new_cache->next = NULL;
2772159047fSniklas if (bfd_ardata (arch_bfd)->cache == NULL)
2782159047fSniklas bfd_ardata (arch_bfd)->cache = new_cache;
2792159047fSniklas else
2802159047fSniklas {
2812159047fSniklas struct ar_cache *current = bfd_ardata (arch_bfd)->cache;
2822159047fSniklas
2832159047fSniklas while (current->next != NULL)
2842159047fSniklas current = current->next;
2852159047fSniklas current->next = new_cache;
2862159047fSniklas }
2872159047fSniklas
288c074d1c9Sdrahn return TRUE;
2892159047fSniklas }
2902159047fSniklas
2912159047fSniklas /* The name begins with space. Hence the rest of the name is an index into
2922159047fSniklas the string table. */
2932159047fSniklas
2942159047fSniklas static char *
get_extended_arelt_filename(bfd * arch,const char * name)295007c2a45Smiod get_extended_arelt_filename (bfd *arch, const char *name)
2962159047fSniklas {
2972159047fSniklas unsigned long index = 0;
2982159047fSniklas
2992159047fSniklas /* Should extract string so that I can guarantee not to overflow into
3002159047fSniklas the next region, but I'm too lazy. */
3012159047fSniklas errno = 0;
3022159047fSniklas /* Skip first char, which is '/' in SVR4 or ' ' in some other variants. */
3032159047fSniklas index = strtol (name + 1, NULL, 10);
3042159047fSniklas if (errno != 0)
3052159047fSniklas {
3062159047fSniklas bfd_set_error (bfd_error_malformed_archive);
3072159047fSniklas return NULL;
3082159047fSniklas }
3092159047fSniklas
3102159047fSniklas return bfd_ardata (arch)->extended_names + index;
3112159047fSniklas }
3122159047fSniklas
3132159047fSniklas /* This functions reads an arch header and returns an areltdata pointer, or
3142159047fSniklas NULL on error.
3152159047fSniklas
3162159047fSniklas Presumes the file pointer is already in the right place (ie pointing
3172159047fSniklas to the ar_hdr in the file). Moves the file pointer; on success it
3182159047fSniklas should be pointing to the front of the file contents; on failure it
3192159047fSniklas could have been moved arbitrarily.
3202159047fSniklas */
3212159047fSniklas
322007c2a45Smiod void *
_bfd_generic_read_ar_hdr(bfd * abfd)323007c2a45Smiod _bfd_generic_read_ar_hdr (bfd *abfd)
3242159047fSniklas {
325007c2a45Smiod return _bfd_generic_read_ar_hdr_mag (abfd, NULL);
326c88b1d6cSniklas }
3272159047fSniklas
328c88b1d6cSniklas /* Alpha ECOFF uses an optional different ARFMAG value, so we have a
329c88b1d6cSniklas variant of _bfd_generic_read_ar_hdr which accepts a magic string. */
330c88b1d6cSniklas
331007c2a45Smiod void *
_bfd_generic_read_ar_hdr_mag(bfd * abfd,const char * mag)332007c2a45Smiod _bfd_generic_read_ar_hdr_mag (bfd *abfd, const char *mag)
333c88b1d6cSniklas {
3342159047fSniklas struct ar_hdr hdr;
3352159047fSniklas char *hdrp = (char *) &hdr;
336c074d1c9Sdrahn size_t parsed_size;
3372159047fSniklas struct areltdata *ared;
3382159047fSniklas char *filename = NULL;
339c074d1c9Sdrahn bfd_size_type namelen = 0;
340c074d1c9Sdrahn bfd_size_type allocsize = sizeof (struct areltdata) + sizeof (struct ar_hdr);
3412159047fSniklas char *allocptr = 0;
3422159047fSniklas
343007c2a45Smiod if (bfd_bread (hdrp, sizeof (struct ar_hdr), abfd) != sizeof (struct ar_hdr))
3442159047fSniklas {
3452159047fSniklas if (bfd_get_error () != bfd_error_system_call)
3462159047fSniklas bfd_set_error (bfd_error_no_more_archived_files);
3472159047fSniklas return NULL;
3482159047fSniklas }
349c88b1d6cSniklas if (strncmp (hdr.ar_fmag, ARFMAG, 2) != 0
350c88b1d6cSniklas && (mag == NULL
351c88b1d6cSniklas || strncmp (hdr.ar_fmag, mag, 2) != 0))
3522159047fSniklas {
3532159047fSniklas bfd_set_error (bfd_error_malformed_archive);
3542159047fSniklas return NULL;
3552159047fSniklas }
3562159047fSniklas
3572159047fSniklas errno = 0;
3582159047fSniklas parsed_size = strtol (hdr.ar_size, NULL, 10);
3592159047fSniklas if (errno != 0)
3602159047fSniklas {
3612159047fSniklas bfd_set_error (bfd_error_malformed_archive);
3622159047fSniklas return NULL;
3632159047fSniklas }
3642159047fSniklas
3652159047fSniklas /* Extract the filename from the archive - there are two ways to
366b305b0f1Sespie specify an extended name table, either the first char of the
3672159047fSniklas name is a space, or it's a slash. */
3682159047fSniklas if ((hdr.ar_name[0] == '/'
3692159047fSniklas || (hdr.ar_name[0] == ' '
3702159047fSniklas && memchr (hdr.ar_name, '/', ar_maxnamelen (abfd)) == NULL))
3712159047fSniklas && bfd_ardata (abfd)->extended_names != NULL)
3722159047fSniklas {
3732159047fSniklas filename = get_extended_arelt_filename (abfd, hdr.ar_name);
3742159047fSniklas if (filename == NULL)
3752159047fSniklas {
3762159047fSniklas bfd_set_error (bfd_error_malformed_archive);
3772159047fSniklas return NULL;
3782159047fSniklas }
3792159047fSniklas }
3802159047fSniklas /* BSD4.4-style long filename.
3812159047fSniklas Only implemented for reading, so far! */
382b305b0f1Sespie else if (hdr.ar_name[0] == '#'
383b305b0f1Sespie && hdr.ar_name[1] == '1'
384b305b0f1Sespie && hdr.ar_name[2] == '/'
385c074d1c9Sdrahn && ISDIGIT (hdr.ar_name[3]))
3862159047fSniklas {
3872159047fSniklas /* BSD-4.4 extended name */
3882159047fSniklas namelen = atoi (&hdr.ar_name[3]);
3892159047fSniklas allocsize += namelen + 1;
3902159047fSniklas parsed_size -= namelen;
3912159047fSniklas
3922159047fSniklas allocptr = bfd_zalloc (abfd, allocsize);
3932159047fSniklas if (allocptr == NULL)
3942159047fSniklas return NULL;
3952159047fSniklas filename = (allocptr
3962159047fSniklas + sizeof (struct areltdata)
3972159047fSniklas + sizeof (struct ar_hdr));
398c074d1c9Sdrahn if (bfd_bread (filename, namelen, abfd) != namelen)
3992159047fSniklas {
4002159047fSniklas if (bfd_get_error () != bfd_error_system_call)
4012159047fSniklas bfd_set_error (bfd_error_no_more_archived_files);
4022159047fSniklas return NULL;
4032159047fSniklas }
4042159047fSniklas filename[namelen] = '\0';
4052159047fSniklas }
4062159047fSniklas else
4072159047fSniklas {
4082159047fSniklas /* We judge the end of the name by looking for '/' or ' '.
4092159047fSniklas Note: The SYSV format (terminated by '/') allows embedded
4102159047fSniklas spaces, so only look for ' ' if we don't find '/'. */
4112159047fSniklas
412b305b0f1Sespie char *e;
413007c2a45Smiod e = memchr (hdr.ar_name, '\0', ar_maxnamelen (abfd));
414b305b0f1Sespie if (e == NULL)
4152159047fSniklas {
416007c2a45Smiod e = memchr (hdr.ar_name, '/', ar_maxnamelen (abfd));
417b305b0f1Sespie if (e == NULL)
418007c2a45Smiod e = memchr (hdr.ar_name, ' ', ar_maxnamelen (abfd));
4192159047fSniklas }
420b305b0f1Sespie
421b305b0f1Sespie if (e != NULL)
422b305b0f1Sespie namelen = e - hdr.ar_name;
423b305b0f1Sespie else
424b305b0f1Sespie {
425b305b0f1Sespie /* If we didn't find a termination character, then the name
426b305b0f1Sespie must be the entire field. */
427b305b0f1Sespie namelen = ar_maxnamelen (abfd);
4282159047fSniklas }
4292159047fSniklas
4302159047fSniklas allocsize += namelen + 1;
4312159047fSniklas }
4322159047fSniklas
4332159047fSniklas if (!allocptr)
4342159047fSniklas {
4352159047fSniklas allocptr = bfd_zalloc (abfd, allocsize);
4362159047fSniklas if (allocptr == NULL)
4372159047fSniklas return NULL;
4382159047fSniklas }
4392159047fSniklas
4402159047fSniklas ared = (struct areltdata *) allocptr;
4412159047fSniklas
4422159047fSniklas ared->arch_header = allocptr + sizeof (struct areltdata);
443007c2a45Smiod memcpy (ared->arch_header, &hdr, sizeof (struct ar_hdr));
4442159047fSniklas ared->parsed_size = parsed_size;
4452159047fSniklas
4462159047fSniklas if (filename != NULL)
4472159047fSniklas ared->filename = filename;
4482159047fSniklas else
4492159047fSniklas {
4502159047fSniklas ared->filename = allocptr + (sizeof (struct areltdata) +
4512159047fSniklas sizeof (struct ar_hdr));
4522159047fSniklas if (namelen)
453007c2a45Smiod memcpy (ared->filename, hdr.ar_name, namelen);
4542159047fSniklas ared->filename[namelen] = '\0';
4552159047fSniklas }
4562159047fSniklas
457007c2a45Smiod return ared;
4582159047fSniklas }
4592159047fSniklas
4602159047fSniklas /* This is an internal function; it's mainly used when indexing
4612159047fSniklas through the archive symbol table, but also used to get the next
4622159047fSniklas element, since it handles the bookkeeping so nicely for us. */
4632159047fSniklas
4642159047fSniklas bfd *
_bfd_get_elt_at_filepos(bfd * archive,file_ptr filepos)465007c2a45Smiod _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos)
4662159047fSniklas {
4672159047fSniklas struct areltdata *new_areldata;
4682159047fSniklas bfd *n_nfd;
4692159047fSniklas
4702159047fSniklas n_nfd = _bfd_look_for_bfd_in_cache (archive, filepos);
4712159047fSniklas if (n_nfd)
4722159047fSniklas return n_nfd;
4732159047fSniklas
4742159047fSniklas if (0 > bfd_seek (archive, filepos, SEEK_SET))
4752159047fSniklas return NULL;
4762159047fSniklas
477007c2a45Smiod if ((new_areldata = _bfd_read_ar_hdr (archive)) == NULL)
4782159047fSniklas return NULL;
4792159047fSniklas
4802159047fSniklas n_nfd = _bfd_create_empty_archive_element_shell (archive);
4812159047fSniklas if (n_nfd == NULL)
4822159047fSniklas {
483007c2a45Smiod bfd_release (archive, new_areldata);
4842159047fSniklas return NULL;
4852159047fSniklas }
4862159047fSniklas
4872159047fSniklas n_nfd->origin = bfd_tell (archive);
488007c2a45Smiod n_nfd->arelt_data = new_areldata;
4892159047fSniklas n_nfd->filename = new_areldata->filename;
4902159047fSniklas
4912159047fSniklas if (_bfd_add_bfd_to_archive_cache (archive, filepos, n_nfd))
4922159047fSniklas return n_nfd;
4932159047fSniklas
494b55d4692Sfgsch /* Huh? */
495007c2a45Smiod bfd_release (archive, n_nfd);
496007c2a45Smiod bfd_release (archive, new_areldata);
4972159047fSniklas return NULL;
4982159047fSniklas }
4992159047fSniklas
500c88b1d6cSniklas /* Return the BFD which is referenced by the symbol in ABFD indexed by
501c88b1d6cSniklas INDEX. INDEX should have been returned by bfd_get_next_mapent. */
5022159047fSniklas
5032159047fSniklas bfd *
_bfd_generic_get_elt_at_index(bfd * abfd,symindex index)504007c2a45Smiod _bfd_generic_get_elt_at_index (bfd *abfd, symindex index)
5052159047fSniklas {
5062159047fSniklas carsym *entry;
5072159047fSniklas
5082159047fSniklas entry = bfd_ardata (abfd)->symdefs + index;
5092159047fSniklas return _bfd_get_elt_at_filepos (abfd, entry->file_offset);
5102159047fSniklas }
5112159047fSniklas
5122159047fSniklas /*
5132159047fSniklas FUNCTION
5142159047fSniklas bfd_openr_next_archived_file
5152159047fSniklas
5162159047fSniklas SYNOPSIS
5172159047fSniklas bfd *bfd_openr_next_archived_file (bfd *archive, bfd *previous);
5182159047fSniklas
5192159047fSniklas DESCRIPTION
5202159047fSniklas Provided a BFD, @var{archive}, containing an archive and NULL, open
5212159047fSniklas an input BFD on the first contained element and returns that.
5222159047fSniklas Subsequent calls should pass
5232159047fSniklas the archive and the previous return value to return a created
5242159047fSniklas BFD to the next contained element. NULL is returned when there
5252159047fSniklas are no more.
5262159047fSniklas */
5272159047fSniklas
5282159047fSniklas bfd *
bfd_openr_next_archived_file(bfd * archive,bfd * last_file)529007c2a45Smiod bfd_openr_next_archived_file (bfd *archive, bfd *last_file)
5302159047fSniklas {
5312159047fSniklas if ((bfd_get_format (archive) != bfd_archive) ||
5322159047fSniklas (archive->direction == write_direction))
5332159047fSniklas {
5342159047fSniklas bfd_set_error (bfd_error_invalid_operation);
5352159047fSniklas return NULL;
5362159047fSniklas }
5372159047fSniklas
5382159047fSniklas return BFD_SEND (archive,
539007c2a45Smiod openr_next_archived_file, (archive, last_file));
5402159047fSniklas }
5412159047fSniklas
5422159047fSniklas bfd *
bfd_generic_openr_next_archived_file(bfd * archive,bfd * last_file)543007c2a45Smiod bfd_generic_openr_next_archived_file (bfd *archive, bfd *last_file)
5442159047fSniklas {
5452159047fSniklas file_ptr filestart;
5462159047fSniklas
5472159047fSniklas if (!last_file)
5482159047fSniklas filestart = bfd_ardata (archive)->first_file_filepos;
5492159047fSniklas else
5502159047fSniklas {
5512159047fSniklas unsigned int size = arelt_size (last_file);
5522159047fSniklas /* Pad to an even boundary...
5532159047fSniklas Note that last_file->origin can be odd in the case of
5542159047fSniklas BSD-4.4-style element with a long odd size. */
5552159047fSniklas filestart = last_file->origin + size;
5562159047fSniklas filestart += filestart % 2;
5572159047fSniklas }
5582159047fSniklas
5592159047fSniklas return _bfd_get_elt_at_filepos (archive, filestart);
5602159047fSniklas }
5612159047fSniklas
5622159047fSniklas const bfd_target *
bfd_generic_archive_p(bfd * abfd)563007c2a45Smiod bfd_generic_archive_p (bfd *abfd)
5642159047fSniklas {
5652159047fSniklas struct artdata *tdata_hold;
5662159047fSniklas char armag[SARMAG + 1];
567c074d1c9Sdrahn bfd_size_type amt;
5682159047fSniklas
569007c2a45Smiod if (bfd_bread (armag, SARMAG, abfd) != SARMAG)
5702159047fSniklas {
5712159047fSniklas if (bfd_get_error () != bfd_error_system_call)
5722159047fSniklas bfd_set_error (bfd_error_wrong_format);
5732159047fSniklas return NULL;
5742159047fSniklas }
5752159047fSniklas
5762159047fSniklas #ifdef GNU960
5772159047fSniklas if (strncmp (armag, BFD_GNU960_ARMAG (abfd), SARMAG) != 0)
5782159047fSniklas return 0;
5792159047fSniklas #else
5802159047fSniklas if (strncmp (armag, ARMAG, SARMAG) != 0 &&
5812159047fSniklas strncmp (armag, ARMAGB, SARMAG) != 0)
5822159047fSniklas return 0;
5832159047fSniklas #endif
5842159047fSniklas
585c074d1c9Sdrahn tdata_hold = bfd_ardata (abfd);
5862159047fSniklas
587c074d1c9Sdrahn amt = sizeof (struct artdata);
588007c2a45Smiod bfd_ardata (abfd) = bfd_zalloc (abfd, amt);
5892159047fSniklas if (bfd_ardata (abfd) == NULL)
590c074d1c9Sdrahn {
591c074d1c9Sdrahn bfd_ardata (abfd) = tdata_hold;
5922159047fSniklas return NULL;
593c074d1c9Sdrahn }
5942159047fSniklas
5952159047fSniklas bfd_ardata (abfd)->first_file_filepos = SARMAG;
5962159047fSniklas bfd_ardata (abfd)->cache = NULL;
5972159047fSniklas bfd_ardata (abfd)->archive_head = NULL;
5982159047fSniklas bfd_ardata (abfd)->symdefs = NULL;
5992159047fSniklas bfd_ardata (abfd)->extended_names = NULL;
6002159047fSniklas bfd_ardata (abfd)->tdata = NULL;
6012159047fSniklas
602c074d1c9Sdrahn if (!BFD_SEND (abfd, _bfd_slurp_armap, (abfd))
603c074d1c9Sdrahn || !BFD_SEND (abfd, _bfd_slurp_extended_name_table, (abfd)))
6042159047fSniklas {
605b305b0f1Sespie if (bfd_get_error () != bfd_error_system_call)
606b305b0f1Sespie bfd_set_error (bfd_error_wrong_format);
6072159047fSniklas bfd_release (abfd, bfd_ardata (abfd));
608c074d1c9Sdrahn bfd_ardata (abfd) = tdata_hold;
6092159047fSniklas return NULL;
6102159047fSniklas }
6112159047fSniklas
6122159047fSniklas if (bfd_has_map (abfd))
6132159047fSniklas {
6142159047fSniklas bfd *first;
6152159047fSniklas
6162159047fSniklas /* This archive has a map, so we may presume that the contents
617c88b1d6cSniklas are object files. Make sure that if the first file in the
618c88b1d6cSniklas archive can be recognized as an object file, it is for this
619c88b1d6cSniklas target. If not, assume that this is the wrong format. If
620c88b1d6cSniklas the first file is not an object file, somebody is doing
621c88b1d6cSniklas something weird, and we permit it so that ar -t will work.
6222159047fSniklas
6232159047fSniklas This is done because any normal format will recognize any
6242159047fSniklas normal archive, regardless of the format of the object files.
6252159047fSniklas We do accept an empty archive. */
6262159047fSniklas
627007c2a45Smiod first = bfd_openr_next_archived_file (abfd, NULL);
6282159047fSniklas if (first != NULL)
6292159047fSniklas {
630c074d1c9Sdrahn bfd_boolean fail;
6312159047fSniklas
632c074d1c9Sdrahn first->target_defaulted = FALSE;
633c074d1c9Sdrahn fail = FALSE;
634c88b1d6cSniklas if (bfd_check_format (first, bfd_object)
635c88b1d6cSniklas && first->xvec != abfd->xvec)
6362159047fSniklas {
637c074d1c9Sdrahn #if 0
638c074d1c9Sdrahn /* We ought to close `first' here, but we can't, because
639c074d1c9Sdrahn we have no way to remove it from the archive cache.
640c074d1c9Sdrahn It's close to impossible to figure out when we can
641c074d1c9Sdrahn release bfd_ardata. FIXME. */
642007c2a45Smiod bfd_close (first);
6432159047fSniklas bfd_release (abfd, bfd_ardata (abfd));
644c074d1c9Sdrahn #endif
645c074d1c9Sdrahn bfd_set_error (bfd_error_wrong_object_format);
646c074d1c9Sdrahn bfd_ardata (abfd) = tdata_hold;
6472159047fSniklas return NULL;
6482159047fSniklas }
649c074d1c9Sdrahn /* And we ought to close `first' here too. */
6502159047fSniklas }
6512159047fSniklas }
6522159047fSniklas
6532159047fSniklas return abfd->xvec;
6542159047fSniklas }
6552159047fSniklas
6562159047fSniklas /* Some constants for a 32 bit BSD archive structure. We do not
6572159047fSniklas support 64 bit archives presently; so far as I know, none actually
6582159047fSniklas exist. Supporting them would require changing these constants, and
659c074d1c9Sdrahn changing some H_GET_32 to H_GET_64. */
6602159047fSniklas
6612159047fSniklas /* The size of an external symdef structure. */
6622159047fSniklas #define BSD_SYMDEF_SIZE 8
6632159047fSniklas
6642159047fSniklas /* The offset from the start of a symdef structure to the file offset. */
6652159047fSniklas #define BSD_SYMDEF_OFFSET_SIZE 4
6662159047fSniklas
6672159047fSniklas /* The size of the symdef count. */
6682159047fSniklas #define BSD_SYMDEF_COUNT_SIZE 4
6692159047fSniklas
6702159047fSniklas /* The size of the string count. */
6712159047fSniklas #define BSD_STRING_COUNT_SIZE 4
6722159047fSniklas
673c074d1c9Sdrahn /* Returns FALSE on error, TRUE otherwise */
6742159047fSniklas
675c074d1c9Sdrahn static bfd_boolean
do_slurp_bsd_armap(bfd * abfd)676007c2a45Smiod do_slurp_bsd_armap (bfd *abfd)
6772159047fSniklas {
6782159047fSniklas struct areltdata *mapdata;
6792159047fSniklas unsigned int counter;
6802159047fSniklas bfd_byte *raw_armap, *rbase;
6812159047fSniklas struct artdata *ardata = bfd_ardata (abfd);
6822159047fSniklas char *stringbase;
683c074d1c9Sdrahn bfd_size_type parsed_size, amt;
6842159047fSniklas carsym *set;
6852159047fSniklas
686007c2a45Smiod mapdata = _bfd_read_ar_hdr (abfd);
6872159047fSniklas if (mapdata == NULL)
688c074d1c9Sdrahn return FALSE;
6892159047fSniklas parsed_size = mapdata->parsed_size;
690007c2a45Smiod bfd_release (abfd, mapdata); /* Don't need it any more. */
6912159047fSniklas
692007c2a45Smiod raw_armap = bfd_zalloc (abfd, parsed_size);
693007c2a45Smiod if (raw_armap == NULL)
694c074d1c9Sdrahn return FALSE;
6952159047fSniklas
696007c2a45Smiod if (bfd_bread (raw_armap, parsed_size, abfd) != parsed_size)
6972159047fSniklas {
6982159047fSniklas if (bfd_get_error () != bfd_error_system_call)
6992159047fSniklas bfd_set_error (bfd_error_malformed_archive);
7002159047fSniklas byebye:
701007c2a45Smiod bfd_release (abfd, raw_armap);
702c074d1c9Sdrahn return FALSE;
7032159047fSniklas }
7042159047fSniklas
705c074d1c9Sdrahn ardata->symdef_count = H_GET_32 (abfd, raw_armap) / BSD_SYMDEF_SIZE;
7062159047fSniklas
7072159047fSniklas if (ardata->symdef_count * BSD_SYMDEF_SIZE >
7082159047fSniklas parsed_size - BSD_SYMDEF_COUNT_SIZE)
7092159047fSniklas {
7102159047fSniklas /* Probably we're using the wrong byte ordering. */
7112159047fSniklas bfd_set_error (bfd_error_wrong_format);
7122159047fSniklas goto byebye;
7132159047fSniklas }
7142159047fSniklas
7152159047fSniklas ardata->cache = 0;
7162159047fSniklas rbase = raw_armap + BSD_SYMDEF_COUNT_SIZE;
7172159047fSniklas stringbase = ((char *) rbase
7182159047fSniklas + ardata->symdef_count * BSD_SYMDEF_SIZE
7192159047fSniklas + BSD_STRING_COUNT_SIZE);
720007c2a45Smiod amt = ardata->symdef_count * sizeof (carsym);
721007c2a45Smiod ardata->symdefs = bfd_alloc (abfd, amt);
7222159047fSniklas if (!ardata->symdefs)
723c074d1c9Sdrahn return FALSE;
7242159047fSniklas
7252159047fSniklas for (counter = 0, set = ardata->symdefs;
7262159047fSniklas counter < ardata->symdef_count;
7272159047fSniklas counter++, set++, rbase += BSD_SYMDEF_SIZE)
7282159047fSniklas {
729c074d1c9Sdrahn set->name = H_GET_32 (abfd, rbase) + stringbase;
730c074d1c9Sdrahn set->file_offset = H_GET_32 (abfd, rbase + BSD_SYMDEF_OFFSET_SIZE);
7312159047fSniklas }
7322159047fSniklas
7332159047fSniklas ardata->first_file_filepos = bfd_tell (abfd);
734b55d4692Sfgsch /* Pad to an even boundary if you have to. */
7352159047fSniklas ardata->first_file_filepos += (ardata->first_file_filepos) % 2;
7362159047fSniklas /* FIXME, we should provide some way to free raw_ardata when
7372159047fSniklas we are done using the strings from it. For now, it seems
738b305b0f1Sespie to be allocated on an objalloc anyway... */
739c074d1c9Sdrahn bfd_has_map (abfd) = TRUE;
740c074d1c9Sdrahn return TRUE;
7412159047fSniklas }
7422159047fSniklas
743c074d1c9Sdrahn /* Returns FALSE on error, TRUE otherwise. */
744b55d4692Sfgsch
745c074d1c9Sdrahn static bfd_boolean
do_slurp_coff_armap(bfd * abfd)746007c2a45Smiod do_slurp_coff_armap (bfd *abfd)
7472159047fSniklas {
7482159047fSniklas struct areltdata *mapdata;
7492159047fSniklas int *raw_armap, *rawptr;
7502159047fSniklas struct artdata *ardata = bfd_ardata (abfd);
7512159047fSniklas char *stringbase;
752c074d1c9Sdrahn bfd_size_type stringsize;
7532159047fSniklas unsigned int parsed_size;
7542159047fSniklas carsym *carsyms;
755c074d1c9Sdrahn bfd_size_type nsymz; /* Number of symbols in armap. */
756007c2a45Smiod bfd_vma (*swap) (const void *);
7572159047fSniklas char int_buf[sizeof (long)];
758c074d1c9Sdrahn bfd_size_type carsym_size, ptrsize;
759c074d1c9Sdrahn unsigned int i;
7602159047fSniklas
761007c2a45Smiod mapdata = _bfd_read_ar_hdr (abfd);
7622159047fSniklas if (mapdata == NULL)
763c074d1c9Sdrahn return FALSE;
7642159047fSniklas parsed_size = mapdata->parsed_size;
765007c2a45Smiod bfd_release (abfd, mapdata); /* Don't need it any more. */
7662159047fSniklas
767007c2a45Smiod if (bfd_bread (int_buf, 4, abfd) != 4)
7682159047fSniklas {
7692159047fSniklas if (bfd_get_error () != bfd_error_system_call)
7702159047fSniklas bfd_set_error (bfd_error_malformed_archive);
771c074d1c9Sdrahn return FALSE;
7722159047fSniklas }
7732159047fSniklas /* It seems that all numeric information in a coff archive is always
7742159047fSniklas in big endian format, nomatter the host or target. */
7752159047fSniklas swap = bfd_getb32;
776007c2a45Smiod nsymz = bfd_getb32 (int_buf);
7772159047fSniklas stringsize = parsed_size - (4 * nsymz) - 4;
7782159047fSniklas
7792159047fSniklas #if 1
7802159047fSniklas /* ... except that some archive formats are broken, and it may be our
7812159047fSniklas fault - the i960 little endian coff sometimes has big and sometimes
7822159047fSniklas little, because our tools changed. Here's a horrible hack to clean
7832159047fSniklas up the crap. */
7842159047fSniklas
785e93f7393Sniklas if (stringsize > 0xfffff
786e93f7393Sniklas && bfd_get_arch (abfd) == bfd_arch_i960
787e93f7393Sniklas && bfd_get_flavour (abfd) == bfd_target_coff_flavour)
7882159047fSniklas {
789b55d4692Sfgsch /* This looks dangerous, let's do it the other way around. */
790007c2a45Smiod nsymz = bfd_getl32 (int_buf);
7912159047fSniklas stringsize = parsed_size - (4 * nsymz) - 4;
7922159047fSniklas swap = bfd_getl32;
7932159047fSniklas }
7942159047fSniklas #endif
7952159047fSniklas
7962159047fSniklas /* The coff armap must be read sequentially. So we construct a
7972159047fSniklas bsd-style one in core all at once, for simplicity. */
7982159047fSniklas
7992159047fSniklas carsym_size = (nsymz * sizeof (carsym));
8002159047fSniklas ptrsize = (4 * nsymz);
8012159047fSniklas
802007c2a45Smiod ardata->symdefs = bfd_zalloc (abfd, carsym_size + stringsize + 1);
8032159047fSniklas if (ardata->symdefs == NULL)
804c074d1c9Sdrahn return FALSE;
8052159047fSniklas carsyms = ardata->symdefs;
8062159047fSniklas stringbase = ((char *) ardata->symdefs) + carsym_size;
8072159047fSniklas
8082159047fSniklas /* Allocate and read in the raw offsets. */
809007c2a45Smiod raw_armap = bfd_alloc (abfd, ptrsize);
8102159047fSniklas if (raw_armap == NULL)
8112159047fSniklas goto release_symdefs;
812007c2a45Smiod if (bfd_bread (raw_armap, ptrsize, abfd) != ptrsize
813007c2a45Smiod || (bfd_bread (stringbase, stringsize, abfd) != stringsize))
8142159047fSniklas {
8152159047fSniklas if (bfd_get_error () != bfd_error_system_call)
8162159047fSniklas bfd_set_error (bfd_error_malformed_archive);
8172159047fSniklas goto release_raw_armap;
8182159047fSniklas }
8192159047fSniklas
820b55d4692Sfgsch /* OK, build the carsyms. */
8212159047fSniklas for (i = 0; i < nsymz; i++)
8222159047fSniklas {
8232159047fSniklas rawptr = raw_armap + i;
824007c2a45Smiod carsyms->file_offset = swap ((bfd_byte *) rawptr);
8252159047fSniklas carsyms->name = stringbase;
8262159047fSniklas stringbase += strlen (stringbase) + 1;
8272159047fSniklas carsyms++;
8282159047fSniklas }
8292159047fSniklas *stringbase = 0;
8302159047fSniklas
8312159047fSniklas ardata->symdef_count = nsymz;
8322159047fSniklas ardata->first_file_filepos = bfd_tell (abfd);
833b55d4692Sfgsch /* Pad to an even boundary if you have to. */
8342159047fSniklas ardata->first_file_filepos += (ardata->first_file_filepos) % 2;
8352159047fSniklas
836c074d1c9Sdrahn bfd_has_map (abfd) = TRUE;
837007c2a45Smiod bfd_release (abfd, raw_armap);
8382159047fSniklas
839b55d4692Sfgsch /* Check for a second archive header (as used by PE). */
8402159047fSniklas {
8412159047fSniklas struct areltdata *tmp;
8422159047fSniklas
8432159047fSniklas bfd_seek (abfd, ardata->first_file_filepos, SEEK_SET);
844007c2a45Smiod tmp = _bfd_read_ar_hdr (abfd);
8452159047fSniklas if (tmp != NULL)
8462159047fSniklas {
8472159047fSniklas if (tmp->arch_header[0] == '/'
8482159047fSniklas && tmp->arch_header[1] == ' ')
8492159047fSniklas {
8502159047fSniklas ardata->first_file_filepos +=
851c074d1c9Sdrahn (tmp->parsed_size + sizeof (struct ar_hdr) + 1) & ~(unsigned) 1;
8522159047fSniklas }
8532159047fSniklas bfd_release (abfd, tmp);
8542159047fSniklas }
8552159047fSniklas }
8562159047fSniklas
857c074d1c9Sdrahn return TRUE;
8582159047fSniklas
8592159047fSniklas release_raw_armap:
860007c2a45Smiod bfd_release (abfd, raw_armap);
8612159047fSniklas release_symdefs:
862007c2a45Smiod bfd_release (abfd, (ardata)->symdefs);
863c074d1c9Sdrahn return FALSE;
8642159047fSniklas }
8652159047fSniklas
8662159047fSniklas /* This routine can handle either coff-style or bsd-style armaps.
867c074d1c9Sdrahn Returns FALSE on error, TRUE otherwise */
8682159047fSniklas
869c074d1c9Sdrahn bfd_boolean
bfd_slurp_armap(bfd * abfd)870007c2a45Smiod bfd_slurp_armap (bfd *abfd)
8712159047fSniklas {
8722159047fSniklas char nextname[17];
873007c2a45Smiod int i = bfd_bread (nextname, 16, abfd);
8742159047fSniklas
8752159047fSniklas if (i == 0)
876c074d1c9Sdrahn return TRUE;
8772159047fSniklas if (i != 16)
878c074d1c9Sdrahn return FALSE;
8792159047fSniklas
8802159047fSniklas if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0)
881c074d1c9Sdrahn return FALSE;
8822159047fSniklas
8832159047fSniklas if (!strncmp (nextname, "__.SYMDEF ", 16)
8842159047fSniklas || !strncmp (nextname, "__.SYMDEF/ ", 16)) /* old Linux archives */
8852159047fSniklas return do_slurp_bsd_armap (abfd);
8862159047fSniklas else if (!strncmp (nextname, "/ ", 16))
8872159047fSniklas return do_slurp_coff_armap (abfd);
8880c6d0228Sniklas else if (!strncmp (nextname, "/SYM64/ ", 16))
8890c6d0228Sniklas {
890c074d1c9Sdrahn /* 64bit ELF (Irix 6) archive. */
891c074d1c9Sdrahn #ifdef BFD64
892007c2a45Smiod extern bfd_boolean bfd_elf64_archive_slurp_armap (bfd *);
893c074d1c9Sdrahn return bfd_elf64_archive_slurp_armap (abfd);
894c074d1c9Sdrahn #else
8950c6d0228Sniklas bfd_set_error (bfd_error_wrong_format);
896c074d1c9Sdrahn return FALSE;
897c074d1c9Sdrahn #endif
8980c6d0228Sniklas }
8992159047fSniklas
900c074d1c9Sdrahn bfd_has_map (abfd) = FALSE;
901c074d1c9Sdrahn return TRUE;
9022159047fSniklas }
9032159047fSniklas
904c074d1c9Sdrahn /* Returns FALSE on error, TRUE otherwise */
9052159047fSniklas /* flavor 2 of a bsd armap, similar to bfd_slurp_bsd_armap except the
9062159047fSniklas header is in a slightly different order and the map name is '/'.
9072159047fSniklas This flavour is used by hp300hpux. */
9082159047fSniklas
9092159047fSniklas #define HPUX_SYMDEF_COUNT_SIZE 2
9102159047fSniklas
911c074d1c9Sdrahn bfd_boolean
bfd_slurp_bsd_armap_f2(bfd * abfd)912007c2a45Smiod bfd_slurp_bsd_armap_f2 (bfd *abfd)
9132159047fSniklas {
9142159047fSniklas struct areltdata *mapdata;
9152159047fSniklas char nextname[17];
9162159047fSniklas unsigned int counter;
9172159047fSniklas bfd_byte *raw_armap, *rbase;
9182159047fSniklas struct artdata *ardata = bfd_ardata (abfd);
9192159047fSniklas char *stringbase;
9202159047fSniklas unsigned int stringsize;
921c074d1c9Sdrahn bfd_size_type amt;
9222159047fSniklas carsym *set;
923007c2a45Smiod int i = bfd_bread (nextname, 16, abfd);
9242159047fSniklas
9252159047fSniklas if (i == 0)
926c074d1c9Sdrahn return TRUE;
9272159047fSniklas if (i != 16)
928c074d1c9Sdrahn return FALSE;
9292159047fSniklas
930b55d4692Sfgsch /* The archive has at least 16 bytes in it. */
931c074d1c9Sdrahn if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0)
932c074d1c9Sdrahn return FALSE;
9332159047fSniklas
9342159047fSniklas if (!strncmp (nextname, "__.SYMDEF ", 16)
9352159047fSniklas || !strncmp (nextname, "__.SYMDEF/ ", 16)) /* old Linux archives */
9362159047fSniklas return do_slurp_bsd_armap (abfd);
9372159047fSniklas
9382159047fSniklas if (strncmp (nextname, "/ ", 16))
9392159047fSniklas {
940c074d1c9Sdrahn bfd_has_map (abfd) = FALSE;
941c074d1c9Sdrahn return TRUE;
9422159047fSniklas }
9432159047fSniklas
944007c2a45Smiod mapdata = _bfd_read_ar_hdr (abfd);
9452159047fSniklas if (mapdata == NULL)
946c074d1c9Sdrahn return FALSE;
9472159047fSniklas
948c074d1c9Sdrahn amt = mapdata->parsed_size;
949007c2a45Smiod raw_armap = bfd_zalloc (abfd, amt);
9502159047fSniklas if (raw_armap == NULL)
9512159047fSniklas {
9522159047fSniklas byebye:
953007c2a45Smiod bfd_release (abfd, mapdata);
954c074d1c9Sdrahn return FALSE;
9552159047fSniklas }
9562159047fSniklas
957007c2a45Smiod if (bfd_bread (raw_armap, amt, abfd) != amt)
9582159047fSniklas {
9592159047fSniklas if (bfd_get_error () != bfd_error_system_call)
9602159047fSniklas bfd_set_error (bfd_error_malformed_archive);
9612159047fSniklas byebyebye:
962007c2a45Smiod bfd_release (abfd, raw_armap);
9632159047fSniklas goto byebye;
9642159047fSniklas }
9652159047fSniklas
966007c2a45Smiod ardata->symdef_count = H_GET_16 (abfd, raw_armap);
9672159047fSniklas
9682159047fSniklas if (ardata->symdef_count * BSD_SYMDEF_SIZE
9692159047fSniklas > mapdata->parsed_size - HPUX_SYMDEF_COUNT_SIZE)
9702159047fSniklas {
9712159047fSniklas /* Probably we're using the wrong byte ordering. */
9722159047fSniklas bfd_set_error (bfd_error_wrong_format);
9732159047fSniklas goto byebyebye;
9742159047fSniklas }
9752159047fSniklas
9762159047fSniklas ardata->cache = 0;
9772159047fSniklas
978c074d1c9Sdrahn stringsize = H_GET_32 (abfd, raw_armap + HPUX_SYMDEF_COUNT_SIZE);
979b55d4692Sfgsch /* Skip sym count and string sz. */
9802159047fSniklas stringbase = ((char *) raw_armap
9812159047fSniklas + HPUX_SYMDEF_COUNT_SIZE
9822159047fSniklas + BSD_STRING_COUNT_SIZE);
9832159047fSniklas rbase = (bfd_byte *) stringbase + stringsize;
984007c2a45Smiod amt = ardata->symdef_count * BSD_SYMDEF_SIZE;
985007c2a45Smiod ardata->symdefs = bfd_alloc (abfd, amt);
9862159047fSniklas if (!ardata->symdefs)
987c074d1c9Sdrahn return FALSE;
9882159047fSniklas
9892159047fSniklas for (counter = 0, set = ardata->symdefs;
9902159047fSniklas counter < ardata->symdef_count;
9912159047fSniklas counter++, set++, rbase += BSD_SYMDEF_SIZE)
9922159047fSniklas {
993c074d1c9Sdrahn set->name = H_GET_32 (abfd, rbase) + stringbase;
994c074d1c9Sdrahn set->file_offset = H_GET_32 (abfd, rbase + BSD_SYMDEF_OFFSET_SIZE);
9952159047fSniklas }
9962159047fSniklas
9972159047fSniklas ardata->first_file_filepos = bfd_tell (abfd);
998b55d4692Sfgsch /* Pad to an even boundary if you have to. */
9992159047fSniklas ardata->first_file_filepos += (ardata->first_file_filepos) % 2;
10002159047fSniklas /* FIXME, we should provide some way to free raw_ardata when
10012159047fSniklas we are done using the strings from it. For now, it seems
1002b305b0f1Sespie to be allocated on an objalloc anyway... */
1003c074d1c9Sdrahn bfd_has_map (abfd) = TRUE;
1004c074d1c9Sdrahn return TRUE;
10052159047fSniklas }
10062159047fSniklas
10072159047fSniklas /** Extended name table.
10082159047fSniklas
10092159047fSniklas Normally archives support only 14-character filenames.
10102159047fSniklas
10112159047fSniklas Intel has extended the format: longer names are stored in a special
10122159047fSniklas element (the first in the archive, or second if there is an armap);
10132159047fSniklas the name in the ar_hdr is replaced by <space><index into filename
10142159047fSniklas element>. Index is the P.R. of an int (decimal). Data General have
1015b55d4692Sfgsch extended the format by using the prefix // for the special element. */
10162159047fSniklas
1017c074d1c9Sdrahn /* Returns FALSE on error, TRUE otherwise. */
1018b55d4692Sfgsch
1019c074d1c9Sdrahn bfd_boolean
_bfd_slurp_extended_name_table(bfd * abfd)1020007c2a45Smiod _bfd_slurp_extended_name_table (bfd *abfd)
10212159047fSniklas {
10222159047fSniklas char nextname[17];
10232159047fSniklas struct areltdata *namedata;
1024c074d1c9Sdrahn bfd_size_type amt;
10252159047fSniklas
10262159047fSniklas /* FIXME: Formatting sucks here, and in case of failure of BFD_READ,
1027c074d1c9Sdrahn we probably don't want to return TRUE. */
10282159047fSniklas bfd_seek (abfd, bfd_ardata (abfd)->first_file_filepos, SEEK_SET);
1029007c2a45Smiod if (bfd_bread (nextname, 16, abfd) == 16)
10302159047fSniklas {
10312159047fSniklas if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0)
1032c074d1c9Sdrahn return FALSE;
10332159047fSniklas
10342159047fSniklas if (strncmp (nextname, "ARFILENAMES/ ", 16) != 0 &&
10352159047fSniklas strncmp (nextname, "// ", 16) != 0)
10362159047fSniklas {
10372159047fSniklas bfd_ardata (abfd)->extended_names = NULL;
1038c074d1c9Sdrahn return TRUE;
10392159047fSniklas }
10402159047fSniklas
1041007c2a45Smiod namedata = _bfd_read_ar_hdr (abfd);
10422159047fSniklas if (namedata == NULL)
1043c074d1c9Sdrahn return FALSE;
10442159047fSniklas
1045c074d1c9Sdrahn amt = namedata->parsed_size;
1046c074d1c9Sdrahn bfd_ardata (abfd)->extended_names = bfd_zalloc (abfd, amt);
10472159047fSniklas if (bfd_ardata (abfd)->extended_names == NULL)
10482159047fSniklas {
10492159047fSniklas byebye:
1050007c2a45Smiod bfd_release (abfd, namedata);
1051c074d1c9Sdrahn return FALSE;
10522159047fSniklas }
10532159047fSniklas
1054007c2a45Smiod if (bfd_bread (bfd_ardata (abfd)->extended_names, amt, abfd) != amt)
10552159047fSniklas {
10562159047fSniklas if (bfd_get_error () != bfd_error_system_call)
10572159047fSniklas bfd_set_error (bfd_error_malformed_archive);
1058007c2a45Smiod bfd_release (abfd, (bfd_ardata (abfd)->extended_names));
10592159047fSniklas bfd_ardata (abfd)->extended_names = NULL;
10602159047fSniklas goto byebye;
10612159047fSniklas }
10622159047fSniklas
10632159047fSniklas /* Since the archive is supposed to be printable if it contains
10642159047fSniklas text, the entries in the list are newline-padded, not null
10652159047fSniklas padded. In SVR4-style archives, the names also have a
10662159047fSniklas trailing '/'. DOS/NT created archive often have \ in them
10672159047fSniklas We'll fix all problems here.. */
10682159047fSniklas {
10692159047fSniklas char *temp = bfd_ardata (abfd)->extended_names;
10702159047fSniklas char *limit = temp + namedata->parsed_size;
1071b55d4692Sfgsch for (; temp < limit; ++temp)
1072b55d4692Sfgsch {
10732159047fSniklas if (*temp == '\012')
10742159047fSniklas temp[temp[-1] == '/' ? -1 : 0] = '\0';
10752159047fSniklas if (*temp == '\\')
10762159047fSniklas *temp = '/';
10772159047fSniklas }
10782159047fSniklas }
10792159047fSniklas
1080b55d4692Sfgsch /* Pad to an even boundary if you have to. */
10812159047fSniklas bfd_ardata (abfd)->first_file_filepos = bfd_tell (abfd);
10822159047fSniklas bfd_ardata (abfd)->first_file_filepos +=
10832159047fSniklas (bfd_ardata (abfd)->first_file_filepos) % 2;
10842159047fSniklas
10852159047fSniklas /* FIXME, we can't release namedata here because it was allocated
1086b305b0f1Sespie below extended_names on the objalloc... */
1087b55d4692Sfgsch #if 0
1088b55d4692Sfgsch bfd_release (abfd, namedata);
1089b55d4692Sfgsch #endif
10902159047fSniklas }
1091c074d1c9Sdrahn return TRUE;
10922159047fSniklas }
10932159047fSniklas
10942159047fSniklas #ifdef VMS
10952159047fSniklas
10962159047fSniklas /* Return a copy of the stuff in the filename between any :]> and a
1097b55d4692Sfgsch semicolon. */
1098b55d4692Sfgsch
10992159047fSniklas static const char *
normalize(bfd * abfd,const char * file)1100007c2a45Smiod normalize (bfd *abfd, const char *file)
11012159047fSniklas {
1102c074d1c9Sdrahn const char *first;
1103c074d1c9Sdrahn const char *last;
11042159047fSniklas char *copy;
11052159047fSniklas
11062159047fSniklas first = file + strlen (file) - 1;
11072159047fSniklas last = first + 1;
11082159047fSniklas
11092159047fSniklas while (first != file)
11102159047fSniklas {
11112159047fSniklas if (*first == ';')
11122159047fSniklas last = first;
11132159047fSniklas if (*first == ':' || *first == ']' || *first == '>')
11142159047fSniklas {
11152159047fSniklas first++;
11162159047fSniklas break;
11172159047fSniklas }
11182159047fSniklas first--;
11192159047fSniklas }
11202159047fSniklas
1121007c2a45Smiod copy = bfd_alloc (abfd, last - first + 1);
11222159047fSniklas if (copy == NULL)
11232159047fSniklas return NULL;
11242159047fSniklas
11252159047fSniklas memcpy (copy, first, last - first);
11262159047fSniklas copy[last - first] = 0;
11272159047fSniklas
11282159047fSniklas return copy;
11292159047fSniklas }
11302159047fSniklas
11312159047fSniklas #else
11322159047fSniklas static const char *
normalize(bfd * abfd ATTRIBUTE_UNUSED,const char * file)1133007c2a45Smiod normalize (bfd *abfd ATTRIBUTE_UNUSED, const char *file)
11342159047fSniklas {
11352159047fSniklas const char *filename = strrchr (file, '/');
11362159047fSniklas
1137b305b0f1Sespie #ifdef HAVE_DOS_BASED_FILE_SYSTEM
1138b305b0f1Sespie {
1139b305b0f1Sespie /* We could have foo/bar\\baz, or foo\\bar, or d:bar. */
1140b305b0f1Sespie char *bslash = strrchr (file, '\\');
1141b55d4692Sfgsch if (filename == NULL || (bslash != NULL && bslash > filename))
1142b305b0f1Sespie filename = bslash;
1143b305b0f1Sespie if (filename == NULL && file[0] != '\0' && file[1] == ':')
1144b305b0f1Sespie filename = file + 1;
1145b305b0f1Sespie }
1146b305b0f1Sespie #endif
1147007c2a45Smiod if (filename != NULL)
11482159047fSniklas filename++;
11492159047fSniklas else
11502159047fSniklas filename = file;
11512159047fSniklas return filename;
11522159047fSniklas }
11532159047fSniklas #endif
11542159047fSniklas
11552159047fSniklas /* Build a BFD style extended name table. */
11562159047fSniklas
1157c074d1c9Sdrahn bfd_boolean
_bfd_archive_bsd_construct_extended_name_table(bfd * abfd,char ** tabloc,bfd_size_type * tablen,const char ** name)1158007c2a45Smiod _bfd_archive_bsd_construct_extended_name_table (bfd *abfd,
1159007c2a45Smiod char **tabloc,
1160007c2a45Smiod bfd_size_type *tablen,
1161007c2a45Smiod const char **name)
11622159047fSniklas {
11632159047fSniklas *name = "ARFILENAMES/";
1164c074d1c9Sdrahn return _bfd_construct_extended_name_table (abfd, FALSE, tabloc, tablen);
11652159047fSniklas }
11662159047fSniklas
11672159047fSniklas /* Build an SVR4 style extended name table. */
11682159047fSniklas
1169c074d1c9Sdrahn bfd_boolean
_bfd_archive_coff_construct_extended_name_table(bfd * abfd,char ** tabloc,bfd_size_type * tablen,const char ** name)1170007c2a45Smiod _bfd_archive_coff_construct_extended_name_table (bfd *abfd,
1171007c2a45Smiod char **tabloc,
1172007c2a45Smiod bfd_size_type *tablen,
1173007c2a45Smiod const char **name)
11742159047fSniklas {
11752159047fSniklas *name = "//";
1176c074d1c9Sdrahn return _bfd_construct_extended_name_table (abfd, TRUE, tabloc, tablen);
11772159047fSniklas }
11782159047fSniklas
11792159047fSniklas /* Follows archive_head and produces an extended name table if
11802159047fSniklas necessary. Returns (in tabloc) a pointer to an extended name
11812159047fSniklas table, and in tablen the length of the table. If it makes an entry
11822159047fSniklas it clobbers the filename so that the element may be written without
1183c074d1c9Sdrahn further massage. Returns TRUE if it ran successfully, FALSE if
11842159047fSniklas something went wrong. A successful return may still involve a
11852159047fSniklas zero-length tablen! */
11862159047fSniklas
1187c074d1c9Sdrahn bfd_boolean
_bfd_construct_extended_name_table(bfd * abfd,bfd_boolean trailing_slash,char ** tabloc,bfd_size_type * tablen)1188007c2a45Smiod _bfd_construct_extended_name_table (bfd *abfd,
1189007c2a45Smiod bfd_boolean trailing_slash,
1190007c2a45Smiod char **tabloc,
1191007c2a45Smiod bfd_size_type *tablen)
11922159047fSniklas {
11932159047fSniklas unsigned int maxname = abfd->xvec->ar_max_namelen;
1194c074d1c9Sdrahn bfd_size_type total_namelen = 0;
11952159047fSniklas bfd *current;
11962159047fSniklas char *strptr;
11972159047fSniklas
11982159047fSniklas *tablen = 0;
11992159047fSniklas
1200b55d4692Sfgsch /* Figure out how long the table should be. */
12012159047fSniklas for (current = abfd->archive_head; current != NULL; current = current->next)
12022159047fSniklas {
12032159047fSniklas const char *normal;
12042159047fSniklas unsigned int thislen;
12052159047fSniklas
12062159047fSniklas normal = normalize (current, current->filename);
12072159047fSniklas if (normal == NULL)
1208c074d1c9Sdrahn return FALSE;
12092159047fSniklas
12102159047fSniklas thislen = strlen (normal);
12112159047fSniklas
12122159047fSniklas if (thislen > maxname
12132159047fSniklas && (bfd_get_file_flags (abfd) & BFD_TRADITIONAL_FORMAT) != 0)
12142159047fSniklas thislen = maxname;
12152159047fSniklas
12162159047fSniklas if (thislen > maxname)
12172159047fSniklas {
12182159047fSniklas /* Add one to leave room for \n. */
12192159047fSniklas total_namelen += thislen + 1;
12202159047fSniklas if (trailing_slash)
12212159047fSniklas {
12222159047fSniklas /* Leave room for trailing slash. */
12232159047fSniklas ++total_namelen;
12242159047fSniklas }
12252159047fSniklas }
12262159047fSniklas else
12272159047fSniklas {
12282159047fSniklas struct ar_hdr *hdr = arch_hdr (current);
12292159047fSniklas if (strncmp (normal, hdr->ar_name, thislen) != 0
12302159047fSniklas || (thislen < sizeof hdr->ar_name
12312159047fSniklas && hdr->ar_name[thislen] != ar_padchar (current)))
12322159047fSniklas {
12332159047fSniklas /* Must have been using extended format even though it
12342159047fSniklas didn't need to. Fix it to use normal format. */
12352159047fSniklas memcpy (hdr->ar_name, normal, thislen);
12362159047fSniklas if (thislen < maxname
12372159047fSniklas || (thislen == maxname && thislen < sizeof hdr->ar_name))
12382159047fSniklas hdr->ar_name[thislen] = ar_padchar (current);
12392159047fSniklas }
12402159047fSniklas }
12412159047fSniklas }
12422159047fSniklas
12432159047fSniklas if (total_namelen == 0)
1244c074d1c9Sdrahn return TRUE;
12452159047fSniklas
12462159047fSniklas *tabloc = bfd_zalloc (abfd, total_namelen);
12472159047fSniklas if (*tabloc == NULL)
1248c074d1c9Sdrahn return FALSE;
12492159047fSniklas
12502159047fSniklas *tablen = total_namelen;
12512159047fSniklas strptr = *tabloc;
12522159047fSniklas
12532159047fSniklas for (current = abfd->archive_head; current != NULL; current =
12542159047fSniklas current->next)
12552159047fSniklas {
12562159047fSniklas const char *normal;
12572159047fSniklas unsigned int thislen;
12582159047fSniklas
12592159047fSniklas normal = normalize (current, current->filename);
12602159047fSniklas if (normal == NULL)
1261c074d1c9Sdrahn return FALSE;
12622159047fSniklas
12632159047fSniklas thislen = strlen (normal);
12642159047fSniklas if (thislen > maxname)
12652159047fSniklas {
12662159047fSniklas /* Works for now; may need to be re-engineered if we
12672159047fSniklas encounter an oddball archive format and want to
12682159047fSniklas generalise this hack. */
12692159047fSniklas struct ar_hdr *hdr = arch_hdr (current);
12702159047fSniklas strcpy (strptr, normal);
12712159047fSniklas if (! trailing_slash)
12722159047fSniklas strptr[thislen] = '\012';
12732159047fSniklas else
12742159047fSniklas {
12752159047fSniklas strptr[thislen] = '/';
12762159047fSniklas strptr[thislen + 1] = '\012';
12772159047fSniklas }
12782159047fSniklas hdr->ar_name[0] = ar_padchar (current);
12792159047fSniklas /* We know there will always be enough room (one of the few
12802159047fSniklas cases where you may safely use sprintf). */
12812159047fSniklas sprintf ((hdr->ar_name) + 1, "%-d", (unsigned) (strptr - *tabloc));
12822159047fSniklas /* Kinda Kludgy. We should just use the returned value of
1283b55d4692Sfgsch sprintf but not all implementations get this right. */
12842159047fSniklas {
12852159047fSniklas char *temp = hdr->ar_name + 2;
12862159047fSniklas for (; temp < hdr->ar_name + maxname; temp++)
12872159047fSniklas if (*temp == '\0')
12882159047fSniklas *temp = ' ';
12892159047fSniklas }
12902159047fSniklas strptr += thislen + 1;
12912159047fSniklas if (trailing_slash)
12922159047fSniklas ++strptr;
12932159047fSniklas }
12942159047fSniklas }
12952159047fSniklas
1296c074d1c9Sdrahn return TRUE;
12972159047fSniklas }
12982159047fSniklas
12992159047fSniklas /** A couple of functions for creating ar_hdrs */
13002159047fSniklas
1301b55d4692Sfgsch #ifdef HPUX_LARGE_AR_IDS
1302b55d4692Sfgsch /* Function to encode large UID/GID values according to HP. */
1303b55d4692Sfgsch
1304b55d4692Sfgsch static void
hpux_uid_gid_encode(char str[6],long int id)1305007c2a45Smiod hpux_uid_gid_encode (char str[6], long int id)
1306b55d4692Sfgsch {
1307b55d4692Sfgsch int cnt;
1308b55d4692Sfgsch
1309b55d4692Sfgsch str[5] = '@' + (id & 3);
1310b55d4692Sfgsch id >>= 2;
1311b55d4692Sfgsch
1312b55d4692Sfgsch for (cnt = 4; cnt >= 0; ++cnt, id >>= 6)
1313b55d4692Sfgsch str[cnt] = ' ' + (id & 0x3f);
1314b55d4692Sfgsch }
1315b55d4692Sfgsch #endif /* HPUX_LARGE_AR_IDS */
1316b55d4692Sfgsch
1317b305b0f1Sespie #ifndef HAVE_GETUID
1318b305b0f1Sespie #define getuid() 0
1319b305b0f1Sespie #endif
1320b305b0f1Sespie
1321b305b0f1Sespie #ifndef HAVE_GETGID
1322b305b0f1Sespie #define getgid() 0
1323b305b0f1Sespie #endif
1324b305b0f1Sespie
13252159047fSniklas /* Takes a filename, returns an arelt_data for it, or NULL if it can't
13262159047fSniklas make one. The filename must refer to a filename in the filesystem.
1327b305b0f1Sespie The filename field of the ar_hdr will NOT be initialized. If member
1328b305b0f1Sespie is set, and it's an in-memory bfd, we fake it. */
13292159047fSniklas
13302159047fSniklas static struct areltdata *
bfd_ar_hdr_from_filesystem(bfd * abfd,const char * filename,bfd * member)1331007c2a45Smiod bfd_ar_hdr_from_filesystem (bfd *abfd, const char *filename, bfd *member)
13322159047fSniklas {
13332159047fSniklas struct stat status;
13342159047fSniklas struct areltdata *ared;
13352159047fSniklas struct ar_hdr *hdr;
13362159047fSniklas char *temp, *temp1;
1337c074d1c9Sdrahn bfd_size_type amt;
13382159047fSniklas
1339b305b0f1Sespie if (member && (member->flags & BFD_IN_MEMORY) != 0)
1340b305b0f1Sespie {
1341b55d4692Sfgsch /* Assume we just "made" the member, and fake it. */
1342007c2a45Smiod struct bfd_in_memory *bim = member->iostream;
1343b305b0f1Sespie time (&status.st_mtime);
1344b305b0f1Sespie status.st_uid = getuid ();
1345b305b0f1Sespie status.st_gid = getgid ();
1346b305b0f1Sespie status.st_mode = 0644;
1347b305b0f1Sespie status.st_size = bim->size;
1348b305b0f1Sespie }
1349b305b0f1Sespie else if (stat (filename, &status) != 0)
13502159047fSniklas {
13512159047fSniklas bfd_set_error (bfd_error_system_call);
13522159047fSniklas return NULL;
13532159047fSniklas }
13542159047fSniklas
1355c074d1c9Sdrahn amt = sizeof (struct ar_hdr) + sizeof (struct areltdata);
1356007c2a45Smiod ared = bfd_zalloc (abfd, amt);
13572159047fSniklas if (ared == NULL)
13582159047fSniklas return NULL;
13592159047fSniklas hdr = (struct ar_hdr *) (((char *) ared) + sizeof (struct areltdata));
13602159047fSniklas
13612159047fSniklas /* ar headers are space padded, not null padded! */
1362007c2a45Smiod memset (hdr, ' ', sizeof (struct ar_hdr));
13632159047fSniklas
13642159047fSniklas strncpy (hdr->ar_fmag, ARFMAG, 2);
13652159047fSniklas
1366b55d4692Sfgsch /* Goddamned sprintf doesn't permit MAXIMUM field lengths. */
1367d04417c8Smiod sprintf ((hdr->ar_date), "%-12lld", (long long) status.st_mtime);
1368b55d4692Sfgsch #ifdef HPUX_LARGE_AR_IDS
1369b55d4692Sfgsch /* HP has a very "special" way to handle UID/GID's with numeric values
1370b55d4692Sfgsch > 99999. */
1371b55d4692Sfgsch if (status.st_uid > 99999)
1372b55d4692Sfgsch hpux_uid_gid_encode (hdr->ar_gid, (long) status.st_uid);
1373b55d4692Sfgsch else
1374b55d4692Sfgsch #endif
13752159047fSniklas sprintf ((hdr->ar_uid), "%ld", (long) status.st_uid);
1376b55d4692Sfgsch #ifdef HPUX_LARGE_AR_IDS
1377b55d4692Sfgsch /* HP has a very "special" way to handle UID/GID's with numeric values
1378b55d4692Sfgsch > 99999. */
1379b55d4692Sfgsch if (status.st_gid > 99999)
1380b55d4692Sfgsch hpux_uid_gid_encode (hdr->ar_uid, (long) status.st_gid);
1381b55d4692Sfgsch else
1382b55d4692Sfgsch #endif
13832159047fSniklas sprintf ((hdr->ar_gid), "%ld", (long) status.st_gid);
13842159047fSniklas sprintf ((hdr->ar_mode), "%-8o", (unsigned int) status.st_mode);
13852159047fSniklas sprintf ((hdr->ar_size), "%-10ld", (long) status.st_size);
13862159047fSniklas /* Correct for a lossage in sprintf whereby it null-terminates. I cannot
13872159047fSniklas understand how these C losers could design such a ramshackle bunch of
1388b55d4692Sfgsch IO operations. */
13892159047fSniklas temp = (char *) hdr;
13902159047fSniklas temp1 = temp + sizeof (struct ar_hdr) - 2;
13912159047fSniklas for (; temp < temp1; temp++)
13922159047fSniklas {
13932159047fSniklas if (*temp == '\0')
13942159047fSniklas *temp = ' ';
13952159047fSniklas }
13962159047fSniklas strncpy (hdr->ar_fmag, ARFMAG, 2);
13972159047fSniklas ared->parsed_size = status.st_size;
13982159047fSniklas ared->arch_header = (char *) hdr;
13992159047fSniklas
14002159047fSniklas return ared;
14012159047fSniklas }
14022159047fSniklas
14032159047fSniklas /* This is magic required by the "ar" program. Since it's
14042159047fSniklas undocumented, it's undocumented. You may think that it would take
14052159047fSniklas a strong stomach to write this, and it does, but it takes even a
14062159047fSniklas stronger stomach to try to code around such a thing! */
14072159047fSniklas
1408007c2a45Smiod struct ar_hdr *bfd_special_undocumented_glue (bfd *, const char *);
1409b305b0f1Sespie
14102159047fSniklas struct ar_hdr *
bfd_special_undocumented_glue(bfd * abfd,const char * filename)1411007c2a45Smiod bfd_special_undocumented_glue (bfd *abfd, const char *filename)
14122159047fSniklas {
1413b305b0f1Sespie struct areltdata *ar_elt = bfd_ar_hdr_from_filesystem (abfd, filename, 0);
14142159047fSniklas if (ar_elt == NULL)
14152159047fSniklas return NULL;
14162159047fSniklas return (struct ar_hdr *) ar_elt->arch_header;
14172159047fSniklas }
14182159047fSniklas
1419b55d4692Sfgsch /* Analogous to stat call. */
14202159047fSniklas
14212159047fSniklas int
bfd_generic_stat_arch_elt(bfd * abfd,struct stat * buf)1422007c2a45Smiod bfd_generic_stat_arch_elt (bfd *abfd, struct stat *buf)
14232159047fSniklas {
14242159047fSniklas struct ar_hdr *hdr;
14252159047fSniklas char *aloser;
14262159047fSniklas
14272159047fSniklas if (abfd->arelt_data == NULL)
14282159047fSniklas {
14292159047fSniklas bfd_set_error (bfd_error_invalid_operation);
14302159047fSniklas return -1;
14312159047fSniklas }
14322159047fSniklas
14332159047fSniklas hdr = arch_hdr (abfd);
14342159047fSniklas
14352159047fSniklas #define foo(arelt, stelt, size) \
14362159047fSniklas buf->stelt = strtol (hdr->arelt, &aloser, size); \
1437b55d4692Sfgsch if (aloser == hdr->arelt) \
1438b55d4692Sfgsch return -1;
1439b55d4692Sfgsch
1440d04417c8Smiod #define fooll(arelt, stelt, size) \
1441d04417c8Smiod buf->stelt = strtoll (hdr->arelt, &aloser, size); \
1442d04417c8Smiod if (aloser == hdr->arelt) \
1443d04417c8Smiod return -1;
1444d04417c8Smiod
1445b55d4692Sfgsch /* Some platforms support special notations for large IDs. */
1446b55d4692Sfgsch #ifdef HPUX_LARGE_AR_IDS
1447b55d4692Sfgsch # define foo2(arelt, stelt, size) \
1448b55d4692Sfgsch if (hdr->arelt[5] == ' ') \
1449b55d4692Sfgsch { \
1450b55d4692Sfgsch foo (arelt, stelt, size); \
1451b55d4692Sfgsch } \
1452b55d4692Sfgsch else \
1453b55d4692Sfgsch { \
1454b55d4692Sfgsch int cnt; \
1455b55d4692Sfgsch for (buf->stelt = cnt = 0; cnt < 5; ++cnt) \
1456b55d4692Sfgsch { \
1457b55d4692Sfgsch if (hdr->arelt[cnt] < ' ' || hdr->arelt[cnt] > ' ' + 0x3f) \
1458b55d4692Sfgsch return -1; \
1459b55d4692Sfgsch buf->stelt <<= 6; \
1460b55d4692Sfgsch buf->stelt += hdr->arelt[cnt] - ' '; \
1461b55d4692Sfgsch } \
1462b55d4692Sfgsch if (hdr->arelt[5] < '@' || hdr->arelt[5] > '@' + 3) \
1463b55d4692Sfgsch return -1; \
1464b55d4692Sfgsch buf->stelt <<= 2; \
1465b55d4692Sfgsch buf->stelt += hdr->arelt[5] - '@'; \
1466b55d4692Sfgsch }
1467b55d4692Sfgsch #else
1468b55d4692Sfgsch # define foo2(arelt, stelt, size) foo (arelt, stelt, size)
1469b55d4692Sfgsch #endif
14702159047fSniklas
1471d04417c8Smiod fooll (ar_date, st_mtime, 10);
1472b55d4692Sfgsch foo2 (ar_uid, st_uid, 10);
1473b55d4692Sfgsch foo2 (ar_gid, st_gid, 10);
14742159047fSniklas foo (ar_mode, st_mode, 8);
14752159047fSniklas
14762159047fSniklas buf->st_size = arch_eltdata (abfd)->parsed_size;
14772159047fSniklas
14782159047fSniklas return 0;
14792159047fSniklas }
14802159047fSniklas
14812159047fSniklas void
bfd_dont_truncate_arname(bfd * abfd,const char * pathname,char * arhdr)1482007c2a45Smiod bfd_dont_truncate_arname (bfd *abfd, const char *pathname, char *arhdr)
14832159047fSniklas {
14842159047fSniklas /* FIXME: This interacts unpleasantly with ar's quick-append option.
14852159047fSniklas Fortunately ic960 users will never use that option. Fixing this
14862159047fSniklas is very hard; fortunately I know how to do it and will do so once
14872159047fSniklas intel's release is out the door. */
14882159047fSniklas
14892159047fSniklas struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
14902159047fSniklas size_t length;
14912159047fSniklas const char *filename;
14922159047fSniklas size_t maxlen = ar_maxnamelen (abfd);
14932159047fSniklas
14942159047fSniklas if ((bfd_get_file_flags (abfd) & BFD_TRADITIONAL_FORMAT) != 0)
14952159047fSniklas {
14962159047fSniklas bfd_bsd_truncate_arname (abfd, pathname, arhdr);
14972159047fSniklas return;
14982159047fSniklas }
14992159047fSniklas
15002159047fSniklas filename = normalize (abfd, pathname);
15012159047fSniklas if (filename == NULL)
15022159047fSniklas {
15032159047fSniklas /* FIXME */
15042159047fSniklas abort ();
15052159047fSniklas }
15062159047fSniklas
15072159047fSniklas length = strlen (filename);
15082159047fSniklas
15092159047fSniklas if (length <= maxlen)
15102159047fSniklas memcpy (hdr->ar_name, filename, length);
15112159047fSniklas
15122159047fSniklas /* Add the padding character if there is room for it. */
15132159047fSniklas if (length < maxlen
15142159047fSniklas || (length == maxlen && length < sizeof hdr->ar_name))
15152159047fSniklas (hdr->ar_name)[length] = ar_padchar (abfd);
15162159047fSniklas }
15172159047fSniklas
15182159047fSniklas void
bfd_bsd_truncate_arname(bfd * abfd,const char * pathname,char * arhdr)1519007c2a45Smiod bfd_bsd_truncate_arname (bfd *abfd, const char *pathname, char *arhdr)
15202159047fSniklas {
15212159047fSniklas struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
1522c074d1c9Sdrahn size_t length;
1523c074d1c9Sdrahn const char *filename = strrchr (pathname, '/');
1524c074d1c9Sdrahn size_t maxlen = ar_maxnamelen (abfd);
15252159047fSniklas
1526b305b0f1Sespie #ifdef HAVE_DOS_BASED_FILE_SYSTEM
1527b305b0f1Sespie {
1528b305b0f1Sespie /* We could have foo/bar\\baz, or foo\\bar, or d:bar. */
1529b305b0f1Sespie char *bslash = strrchr (pathname, '\\');
1530b55d4692Sfgsch if (filename == NULL || (bslash != NULL && bslash > filename))
1531b305b0f1Sespie filename = bslash;
1532b305b0f1Sespie if (filename == NULL && pathname[0] != '\0' && pathname[1] == ':')
1533b305b0f1Sespie filename = pathname + 1;
1534b305b0f1Sespie }
1535b305b0f1Sespie #endif
1536b305b0f1Sespie
15372159047fSniklas if (filename == NULL)
15382159047fSniklas filename = pathname;
15392159047fSniklas else
15402159047fSniklas ++filename;
15412159047fSniklas
15422159047fSniklas length = strlen (filename);
15432159047fSniklas
15442159047fSniklas if (length <= maxlen)
15452159047fSniklas memcpy (hdr->ar_name, filename, length);
15462159047fSniklas else
15472159047fSniklas {
15482159047fSniklas /* pathname: meet procrustes */
15492159047fSniklas memcpy (hdr->ar_name, filename, maxlen);
15502159047fSniklas length = maxlen;
15512159047fSniklas }
15522159047fSniklas
15532159047fSniklas if (length < maxlen)
15542159047fSniklas (hdr->ar_name)[length] = ar_padchar (abfd);
15552159047fSniklas }
15562159047fSniklas
15572159047fSniklas /* Store name into ar header. Truncates the name to fit.
15582159047fSniklas 1> strip pathname to be just the basename.
15592159047fSniklas 2> if it's short enuf to fit, stuff it in.
15602159047fSniklas 3> If it doesn't end with .o, truncate it to fit
15612159047fSniklas 4> truncate it before the .o, append .o, stuff THAT in. */
15622159047fSniklas
15632159047fSniklas /* This is what gnu ar does. It's better but incompatible with the
15642159047fSniklas bsd ar. */
15652159047fSniklas
15662159047fSniklas void
bfd_gnu_truncate_arname(bfd * abfd,const char * pathname,char * arhdr)1567007c2a45Smiod bfd_gnu_truncate_arname (bfd *abfd, const char *pathname, char *arhdr)
15682159047fSniklas {
15692159047fSniklas struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
1570c074d1c9Sdrahn size_t length;
1571c074d1c9Sdrahn const char *filename = strrchr (pathname, '/');
1572c074d1c9Sdrahn size_t maxlen = ar_maxnamelen (abfd);
15732159047fSniklas
1574b305b0f1Sespie #ifdef HAVE_DOS_BASED_FILE_SYSTEM
1575b305b0f1Sespie {
1576b305b0f1Sespie /* We could have foo/bar\\baz, or foo\\bar, or d:bar. */
1577b305b0f1Sespie char *bslash = strrchr (pathname, '\\');
1578b55d4692Sfgsch if (filename == NULL || (bslash != NULL && bslash > filename))
1579b305b0f1Sespie filename = bslash;
1580b305b0f1Sespie if (filename == NULL && pathname[0] != '\0' && pathname[1] == ':')
1581b305b0f1Sespie filename = pathname + 1;
1582b305b0f1Sespie }
1583b305b0f1Sespie #endif
1584b305b0f1Sespie
15852159047fSniklas if (filename == NULL)
15862159047fSniklas filename = pathname;
15872159047fSniklas else
15882159047fSniklas ++filename;
15892159047fSniklas
15902159047fSniklas length = strlen (filename);
15912159047fSniklas
15922159047fSniklas if (length <= maxlen)
15932159047fSniklas memcpy (hdr->ar_name, filename, length);
15942159047fSniklas else
15952159047fSniklas { /* pathname: meet procrustes */
15962159047fSniklas memcpy (hdr->ar_name, filename, maxlen);
15972159047fSniklas if ((filename[length - 2] == '.') && (filename[length - 1] == 'o'))
15982159047fSniklas {
15992159047fSniklas hdr->ar_name[maxlen - 2] = '.';
16002159047fSniklas hdr->ar_name[maxlen - 1] = 'o';
16012159047fSniklas }
16022159047fSniklas length = maxlen;
16032159047fSniklas }
16042159047fSniklas
16052159047fSniklas if (length < 16)
16062159047fSniklas (hdr->ar_name)[length] = ar_padchar (abfd);
16072159047fSniklas }
16082159047fSniklas
1609b55d4692Sfgsch /* The BFD is open for write and has its format set to bfd_archive. */
16102159047fSniklas
1611c074d1c9Sdrahn bfd_boolean
_bfd_write_archive_contents(bfd * arch)1612007c2a45Smiod _bfd_write_archive_contents (bfd *arch)
16132159047fSniklas {
16142159047fSniklas bfd *current;
16152159047fSniklas char *etable = NULL;
16162159047fSniklas bfd_size_type elength = 0;
16172159047fSniklas const char *ename = NULL;
1618c074d1c9Sdrahn bfd_boolean makemap = bfd_has_map (arch);
1619c074d1c9Sdrahn /* If no .o's, don't bother to make a map. */
1620c074d1c9Sdrahn bfd_boolean hasobjects = FALSE;
16212159047fSniklas bfd_size_type wrote;
16222159047fSniklas unsigned int i;
16232159047fSniklas int tries;
16242159047fSniklas
16252159047fSniklas /* Verify the viability of all entries; if any of them live in the
16262159047fSniklas filesystem (as opposed to living in an archive open for input)
16272159047fSniklas then construct a fresh ar_hdr for them. */
16282159047fSniklas for (current = arch->archive_head; current; current = current->next)
16292159047fSniklas {
1630b55d4692Sfgsch /* This check is checking the bfds for the objects we're reading
1631b55d4692Sfgsch from (which are usually either an object file or archive on
1632b55d4692Sfgsch disk), not the archive entries we're writing to. We don't
1633b55d4692Sfgsch actually create bfds for the archive members, we just copy
1634b55d4692Sfgsch them byte-wise when we write out the archive. */
16352159047fSniklas if (bfd_write_p (current))
16362159047fSniklas {
16372159047fSniklas bfd_set_error (bfd_error_invalid_operation);
1638c074d1c9Sdrahn return FALSE;
16392159047fSniklas }
16402159047fSniklas if (!current->arelt_data)
16412159047fSniklas {
16422159047fSniklas current->arelt_data =
1643007c2a45Smiod bfd_ar_hdr_from_filesystem (arch, current->filename, current);
16442159047fSniklas if (!current->arelt_data)
1645c074d1c9Sdrahn return FALSE;
16462159047fSniklas
1647b55d4692Sfgsch /* Put in the file name. */
1648007c2a45Smiod BFD_SEND (arch, _bfd_truncate_arname,
1649007c2a45Smiod (arch, current->filename, (char *) arch_hdr (current)));
16502159047fSniklas }
16512159047fSniklas
16522159047fSniklas if (makemap && ! hasobjects)
1653b55d4692Sfgsch { /* Don't bother if we won't make a map! */
16542159047fSniklas if ((bfd_check_format (current, bfd_object))
16552159047fSniklas #if 0 /* FIXME -- these are not set correctly */
16562159047fSniklas && ((bfd_get_file_flags (current) & HAS_SYMS))
16572159047fSniklas #endif
16582159047fSniklas )
1659c074d1c9Sdrahn hasobjects = TRUE;
16602159047fSniklas }
16612159047fSniklas }
16622159047fSniklas
16632159047fSniklas if (!BFD_SEND (arch, _bfd_construct_extended_name_table,
16642159047fSniklas (arch, &etable, &elength, &ename)))
1665c074d1c9Sdrahn return FALSE;
16662159047fSniklas
16672159047fSniklas if (bfd_seek (arch, (file_ptr) 0, SEEK_SET) != 0)
1668c074d1c9Sdrahn return FALSE;
16692159047fSniklas #ifdef GNU960
1670007c2a45Smiod wrote = bfd_bwrite (BFD_GNU960_ARMAG (arch), SARMAG, arch);
16712159047fSniklas #else
1672007c2a45Smiod wrote = bfd_bwrite (ARMAG, SARMAG, arch);
16732159047fSniklas #endif
16742159047fSniklas if (wrote != SARMAG)
1675c074d1c9Sdrahn return FALSE;
16762159047fSniklas
16772159047fSniklas if (makemap && hasobjects)
16782159047fSniklas {
1679c074d1c9Sdrahn if (! _bfd_compute_and_write_armap (arch, (unsigned int) elength))
1680c074d1c9Sdrahn return FALSE;
16812159047fSniklas }
16822159047fSniklas
16832159047fSniklas if (elength != 0)
16842159047fSniklas {
16852159047fSniklas struct ar_hdr hdr;
16862159047fSniklas
1687007c2a45Smiod memset (&hdr, 0, sizeof (struct ar_hdr));
16882159047fSniklas strcpy (hdr.ar_name, ename);
16892159047fSniklas /* Round size up to even number in archive header. */
16902159047fSniklas sprintf (&(hdr.ar_size[0]), "%-10d",
1691c074d1c9Sdrahn (int) ((elength + 1) & ~(bfd_size_type) 1));
16922159047fSniklas strncpy (hdr.ar_fmag, ARFMAG, 2);
16932159047fSniklas for (i = 0; i < sizeof (struct ar_hdr); i++)
16942159047fSniklas if (((char *) (&hdr))[i] == '\0')
16952159047fSniklas (((char *) (&hdr))[i]) = ' ';
1696007c2a45Smiod if ((bfd_bwrite (&hdr, sizeof (struct ar_hdr), arch)
16972159047fSniklas != sizeof (struct ar_hdr))
1698c074d1c9Sdrahn || bfd_bwrite (etable, elength, arch) != elength)
1699c074d1c9Sdrahn return FALSE;
17002159047fSniklas if ((elength % 2) == 1)
17012159047fSniklas {
1702007c2a45Smiod if (bfd_bwrite ("\012", 1, arch) != 1)
1703c074d1c9Sdrahn return FALSE;
17042159047fSniklas }
17052159047fSniklas }
17062159047fSniklas
17072159047fSniklas for (current = arch->archive_head; current; current = current->next)
17082159047fSniklas {
17092159047fSniklas char buffer[DEFAULT_BUFFERSIZE];
17102159047fSniklas unsigned int remaining = arelt_size (current);
17112159047fSniklas struct ar_hdr *hdr = arch_hdr (current);
17122159047fSniklas
1713b55d4692Sfgsch /* Write ar header. */
1714007c2a45Smiod if (bfd_bwrite (hdr, sizeof (*hdr), arch)
1715c074d1c9Sdrahn != sizeof (*hdr))
1716c074d1c9Sdrahn return FALSE;
17172159047fSniklas if (bfd_seek (current, (file_ptr) 0, SEEK_SET) != 0)
1718c074d1c9Sdrahn return FALSE;
17192159047fSniklas while (remaining)
17202159047fSniklas {
17212159047fSniklas unsigned int amt = DEFAULT_BUFFERSIZE;
17222159047fSniklas if (amt > remaining)
17232159047fSniklas amt = remaining;
17242159047fSniklas errno = 0;
1725007c2a45Smiod if (bfd_bread (buffer, amt, current) != amt)
17262159047fSniklas {
17272159047fSniklas if (bfd_get_error () != bfd_error_system_call)
17282159047fSniklas bfd_set_error (bfd_error_malformed_archive);
1729c074d1c9Sdrahn return FALSE;
17302159047fSniklas }
1731007c2a45Smiod if (bfd_bwrite (buffer, amt, arch) != amt)
1732c074d1c9Sdrahn return FALSE;
17332159047fSniklas remaining -= amt;
17342159047fSniklas }
17352159047fSniklas if ((arelt_size (current) % 2) == 1)
17362159047fSniklas {
1737007c2a45Smiod if (bfd_bwrite ("\012", 1, arch) != 1)
1738c074d1c9Sdrahn return FALSE;
17392159047fSniklas }
17402159047fSniklas }
17412159047fSniklas
17422159047fSniklas if (makemap && hasobjects)
17432159047fSniklas {
17442159047fSniklas /* Verify the timestamp in the archive file. If it would not be
17452159047fSniklas accepted by the linker, rewrite it until it would be. If
17462159047fSniklas anything odd happens, break out and just return. (The
17472159047fSniklas Berkeley linker checks the timestamp and refuses to read the
17482159047fSniklas table-of-contents if it is >60 seconds less than the file's
17492159047fSniklas modified-time. That painful hack requires this painful hack. */
17502159047fSniklas tries = 1;
17512159047fSniklas do
17522159047fSniklas {
17532159047fSniklas if (bfd_update_armap_timestamp (arch))
17542159047fSniklas break;
17552159047fSniklas (*_bfd_error_handler)
1756b305b0f1Sespie (_("Warning: writing archive was slow: rewriting timestamp\n"));
17572159047fSniklas }
17582159047fSniklas while (++tries < 6);
17592159047fSniklas }
17602159047fSniklas
1761c074d1c9Sdrahn return TRUE;
17622159047fSniklas }
17632159047fSniklas
1764b55d4692Sfgsch /* Note that the namidx for the first symbol is 0. */
17652159047fSniklas
1766c074d1c9Sdrahn bfd_boolean
_bfd_compute_and_write_armap(bfd * arch,unsigned int elength)1767007c2a45Smiod _bfd_compute_and_write_armap (bfd *arch, unsigned int elength)
17682159047fSniklas {
17692159047fSniklas char *first_name = NULL;
17702159047fSniklas bfd *current;
17712159047fSniklas file_ptr elt_no = 0;
17722159047fSniklas struct orl *map = NULL;
1773c074d1c9Sdrahn unsigned int orl_max = 1024; /* fine initial default */
1774c074d1c9Sdrahn unsigned int orl_count = 0;
17752159047fSniklas int stridx = 0; /* string index */
17762159047fSniklas asymbol **syms = NULL;
17772159047fSniklas long syms_max = 0;
1778c074d1c9Sdrahn bfd_boolean ret;
1779c074d1c9Sdrahn bfd_size_type amt;
17802159047fSniklas
17812159047fSniklas /* Dunno if this is the best place for this info... */
17822159047fSniklas if (elength != 0)
17832159047fSniklas elength += sizeof (struct ar_hdr);
17842159047fSniklas elength += elength % 2;
17852159047fSniklas
1786007c2a45Smiod amt = orl_max * sizeof (struct orl);
1787007c2a45Smiod map = bfd_malloc (amt);
17882159047fSniklas if (map == NULL)
1789c88b1d6cSniklas goto error_return;
17902159047fSniklas
1791b305b0f1Sespie /* We put the symbol names on the arch objalloc, and then discard
17922159047fSniklas them when done. */
1793007c2a45Smiod first_name = bfd_alloc (arch, 1);
17942159047fSniklas if (first_name == NULL)
1795c88b1d6cSniklas goto error_return;
17962159047fSniklas
1797b55d4692Sfgsch /* Drop all the files called __.SYMDEF, we're going to make our own. */
17982159047fSniklas while (arch->archive_head &&
17992159047fSniklas strcmp (arch->archive_head->filename, "__.SYMDEF") == 0)
18002159047fSniklas arch->archive_head = arch->archive_head->next;
18012159047fSniklas
1802b55d4692Sfgsch /* Map over each element. */
18032159047fSniklas for (current = arch->archive_head;
1804007c2a45Smiod current != NULL;
18052159047fSniklas current = current->next, elt_no++)
18062159047fSniklas {
1807c074d1c9Sdrahn if (bfd_check_format (current, bfd_object)
1808c074d1c9Sdrahn && (bfd_get_file_flags (current) & HAS_SYMS) != 0)
18092159047fSniklas {
18102159047fSniklas long storage;
18112159047fSniklas long symcount;
18122159047fSniklas long src_count;
18132159047fSniklas
18142159047fSniklas storage = bfd_get_symtab_upper_bound (current);
18152159047fSniklas if (storage < 0)
18162159047fSniklas goto error_return;
18172159047fSniklas
18182159047fSniklas if (storage != 0)
18192159047fSniklas {
18202159047fSniklas if (storage > syms_max)
18212159047fSniklas {
18222159047fSniklas if (syms_max > 0)
18232159047fSniklas free (syms);
18242159047fSniklas syms_max = storage;
1825007c2a45Smiod syms = bfd_malloc (syms_max);
18262159047fSniklas if (syms == NULL)
1827c88b1d6cSniklas goto error_return;
18282159047fSniklas }
18292159047fSniklas symcount = bfd_canonicalize_symtab (current, syms);
18302159047fSniklas if (symcount < 0)
18312159047fSniklas goto error_return;
18322159047fSniklas
1833b55d4692Sfgsch /* Now map over all the symbols, picking out the ones we
1834b55d4692Sfgsch want. */
18352159047fSniklas for (src_count = 0; src_count < symcount; src_count++)
18362159047fSniklas {
18372159047fSniklas flagword flags = (syms[src_count])->flags;
18382159047fSniklas asection *sec = syms[src_count]->section;
18392159047fSniklas
18402159047fSniklas if ((flags & BSF_GLOBAL ||
18412159047fSniklas flags & BSF_WEAK ||
18422159047fSniklas flags & BSF_INDIRECT ||
18432159047fSniklas bfd_is_com_section (sec))
18442159047fSniklas && ! bfd_is_und_section (sec))
18452159047fSniklas {
1846c074d1c9Sdrahn bfd_size_type namelen;
18472159047fSniklas struct orl *new_map;
18482159047fSniklas
1849b55d4692Sfgsch /* This symbol will go into the archive header. */
18502159047fSniklas if (orl_count == orl_max)
18512159047fSniklas {
18522159047fSniklas orl_max *= 2;
1853007c2a45Smiod amt = orl_max * sizeof (struct orl);
1854007c2a45Smiod new_map = bfd_realloc (map, amt);
1855007c2a45Smiod if (new_map == NULL)
1856c88b1d6cSniklas goto error_return;
18572159047fSniklas
18582159047fSniklas map = new_map;
18592159047fSniklas }
18602159047fSniklas
18612159047fSniklas namelen = strlen (syms[src_count]->name);
1862c074d1c9Sdrahn amt = sizeof (char *);
1863007c2a45Smiod map[orl_count].name = bfd_alloc (arch, amt);
18642159047fSniklas if (map[orl_count].name == NULL)
1865c88b1d6cSniklas goto error_return;
18662159047fSniklas *(map[orl_count].name) = bfd_alloc (arch, namelen + 1);
18672159047fSniklas if (*(map[orl_count].name) == NULL)
1868c88b1d6cSniklas goto error_return;
18692159047fSniklas strcpy (*(map[orl_count].name), syms[src_count]->name);
1870c074d1c9Sdrahn map[orl_count].u.abfd = current;
1871c074d1c9Sdrahn map[orl_count].namidx = stridx;
18722159047fSniklas
18732159047fSniklas stridx += namelen + 1;
18742159047fSniklas ++orl_count;
18752159047fSniklas }
18762159047fSniklas }
18772159047fSniklas }
18782159047fSniklas
18792159047fSniklas /* Now ask the BFD to free up any cached information, so we
18802159047fSniklas don't fill all of memory with symbol tables. */
18812159047fSniklas if (! bfd_free_cached_info (current))
18822159047fSniklas goto error_return;
18832159047fSniklas }
18842159047fSniklas }
18852159047fSniklas
1886b55d4692Sfgsch /* OK, now we have collected all the data, let's write them out. */
18872159047fSniklas ret = BFD_SEND (arch, write_armap,
18882159047fSniklas (arch, elength, map, orl_count, stridx));
18892159047fSniklas
18902159047fSniklas if (syms_max > 0)
18912159047fSniklas free (syms);
18922159047fSniklas if (map != NULL)
18932159047fSniklas free (map);
18942159047fSniklas if (first_name != NULL)
18952159047fSniklas bfd_release (arch, first_name);
18962159047fSniklas
18972159047fSniklas return ret;
18982159047fSniklas
18992159047fSniklas error_return:
19002159047fSniklas if (syms_max > 0)
19012159047fSniklas free (syms);
19022159047fSniklas if (map != NULL)
19032159047fSniklas free (map);
19042159047fSniklas if (first_name != NULL)
19052159047fSniklas bfd_release (arch, first_name);
19062159047fSniklas
1907c074d1c9Sdrahn return FALSE;
19082159047fSniklas }
19092159047fSniklas
1910c074d1c9Sdrahn bfd_boolean
bsd_write_armap(bfd * arch,unsigned int elength,struct orl * map,unsigned int orl_count,int stridx)1911007c2a45Smiod bsd_write_armap (bfd *arch,
1912007c2a45Smiod unsigned int elength,
1913007c2a45Smiod struct orl *map,
1914007c2a45Smiod unsigned int orl_count,
1915007c2a45Smiod int stridx)
19162159047fSniklas {
19172159047fSniklas int padit = stridx & 1;
19182159047fSniklas unsigned int ranlibsize = orl_count * BSD_SYMDEF_SIZE;
19192159047fSniklas unsigned int stringsize = stridx + padit;
19202159047fSniklas /* Include 8 bytes to store ranlibsize and stringsize in output. */
19212159047fSniklas unsigned int mapsize = ranlibsize + stringsize + 8;
19222159047fSniklas file_ptr firstreal;
19232159047fSniklas bfd *current = arch->archive_head;
19242159047fSniklas bfd *last_elt = current; /* last element arch seen */
19252159047fSniklas bfd_byte temp[4];
19262159047fSniklas unsigned int count;
19272159047fSniklas struct ar_hdr hdr;
19282159047fSniklas struct stat statbuf;
19292159047fSniklas unsigned int i;
19302159047fSniklas
19312159047fSniklas firstreal = mapsize + elength + sizeof (struct ar_hdr) + SARMAG;
19322159047fSniklas
19332159047fSniklas stat (arch->filename, &statbuf);
1934007c2a45Smiod memset (&hdr, 0, sizeof (struct ar_hdr));
19352159047fSniklas sprintf (hdr.ar_name, RANLIBMAG);
19362159047fSniklas /* Remember the timestamp, to keep it holy. But fudge it a little. */
19372159047fSniklas bfd_ardata (arch)->armap_timestamp = statbuf.st_mtime + ARMAP_TIME_OFFSET;
19382159047fSniklas bfd_ardata (arch)->armap_datepos = (SARMAG
19392159047fSniklas + offsetof (struct ar_hdr, ar_date[0]));
1940*f3d2a372Sguenther sprintf (hdr.ar_date, "%lld", (long long)bfd_ardata (arch)->armap_timestamp);
19412159047fSniklas sprintf (hdr.ar_uid, "%ld", (long) getuid ());
19422159047fSniklas sprintf (hdr.ar_gid, "%ld", (long) getgid ());
19432159047fSniklas sprintf (hdr.ar_size, "%-10d", (int) mapsize);
19442159047fSniklas strncpy (hdr.ar_fmag, ARFMAG, 2);
19452159047fSniklas for (i = 0; i < sizeof (struct ar_hdr); i++)
19462159047fSniklas if (((char *) (&hdr))[i] == '\0')
19472159047fSniklas (((char *) (&hdr))[i]) = ' ';
1948007c2a45Smiod if (bfd_bwrite (&hdr, sizeof (struct ar_hdr), arch)
19492159047fSniklas != sizeof (struct ar_hdr))
1950c074d1c9Sdrahn return FALSE;
1951c074d1c9Sdrahn H_PUT_32 (arch, ranlibsize, temp);
1952007c2a45Smiod if (bfd_bwrite (temp, sizeof (temp), arch) != sizeof (temp))
1953c074d1c9Sdrahn return FALSE;
19542159047fSniklas
19552159047fSniklas for (count = 0; count < orl_count; count++)
19562159047fSniklas {
19572159047fSniklas bfd_byte buf[BSD_SYMDEF_SIZE];
19582159047fSniklas
1959c074d1c9Sdrahn if (map[count].u.abfd != last_elt)
19602159047fSniklas {
19612159047fSniklas do
19622159047fSniklas {
19632159047fSniklas firstreal += arelt_size (current) + sizeof (struct ar_hdr);
19642159047fSniklas firstreal += firstreal % 2;
19652159047fSniklas current = current->next;
19662159047fSniklas }
1967c074d1c9Sdrahn while (current != map[count].u.abfd);
19682159047fSniklas } /* if new archive element */
19692159047fSniklas
19702159047fSniklas last_elt = current;
1971c074d1c9Sdrahn H_PUT_32 (arch, map[count].namidx, buf);
1972c074d1c9Sdrahn H_PUT_32 (arch, firstreal, buf + BSD_SYMDEF_OFFSET_SIZE);
1973007c2a45Smiod if (bfd_bwrite (buf, BSD_SYMDEF_SIZE, arch)
1974c074d1c9Sdrahn != BSD_SYMDEF_SIZE)
1975c074d1c9Sdrahn return FALSE;
19762159047fSniklas }
19772159047fSniklas
1978b55d4692Sfgsch /* Now write the strings themselves. */
1979c074d1c9Sdrahn H_PUT_32 (arch, stringsize, temp);
1980007c2a45Smiod if (bfd_bwrite (temp, sizeof (temp), arch) != sizeof (temp))
1981c074d1c9Sdrahn return FALSE;
19822159047fSniklas for (count = 0; count < orl_count; count++)
19832159047fSniklas {
19842159047fSniklas size_t len = strlen (*map[count].name) + 1;
19852159047fSniklas
1986007c2a45Smiod if (bfd_bwrite (*map[count].name, len, arch) != len)
1987c074d1c9Sdrahn return FALSE;
19882159047fSniklas }
19892159047fSniklas
19902159047fSniklas /* The spec sez this should be a newline. But in order to be
19912159047fSniklas bug-compatible for sun's ar we use a null. */
19922159047fSniklas if (padit)
19932159047fSniklas {
1994007c2a45Smiod if (bfd_bwrite ("", 1, arch) != 1)
1995c074d1c9Sdrahn return FALSE;
19962159047fSniklas }
19972159047fSniklas
1998c074d1c9Sdrahn return TRUE;
19992159047fSniklas }
20002159047fSniklas
20012159047fSniklas /* At the end of archive file handling, update the timestamp in the
20022159047fSniklas file, so the linker will accept it.
20032159047fSniklas
2004c074d1c9Sdrahn Return TRUE if the timestamp was OK, or an unusual problem happened.
2005c074d1c9Sdrahn Return FALSE if we updated the timestamp. */
20062159047fSniklas
2007c074d1c9Sdrahn bfd_boolean
_bfd_archive_bsd_update_armap_timestamp(bfd * arch)2008007c2a45Smiod _bfd_archive_bsd_update_armap_timestamp (bfd *arch)
20092159047fSniklas {
20102159047fSniklas struct stat archstat;
20112159047fSniklas struct ar_hdr hdr;
20122159047fSniklas unsigned int i;
20132159047fSniklas
20142159047fSniklas /* Flush writes, get last-write timestamp from file, and compare it
20152159047fSniklas to the timestamp IN the file. */
20162159047fSniklas bfd_flush (arch);
20172159047fSniklas if (bfd_stat (arch, &archstat) == -1)
20182159047fSniklas {
2019c074d1c9Sdrahn bfd_perror (_("Reading archive file mod timestamp"));
2020b55d4692Sfgsch
2021b55d4692Sfgsch /* Can't read mod time for some reason. */
2022c074d1c9Sdrahn return TRUE;
20232159047fSniklas }
20242159047fSniklas if (archstat.st_mtime <= bfd_ardata (arch)->armap_timestamp)
2025b55d4692Sfgsch /* OK by the linker's rules. */
2026c074d1c9Sdrahn return TRUE;
20272159047fSniklas
20282159047fSniklas /* Update the timestamp. */
20292159047fSniklas bfd_ardata (arch)->armap_timestamp = archstat.st_mtime + ARMAP_TIME_OFFSET;
20302159047fSniklas
20312159047fSniklas /* Prepare an ASCII version suitable for writing. */
20322159047fSniklas memset (hdr.ar_date, 0, sizeof (hdr.ar_date));
2033*f3d2a372Sguenther sprintf (hdr.ar_date, "%lld", (long long)bfd_ardata (arch)->armap_timestamp);
20342159047fSniklas for (i = 0; i < sizeof (hdr.ar_date); i++)
20352159047fSniklas if (hdr.ar_date[i] == '\0')
20362159047fSniklas (hdr.ar_date)[i] = ' ';
20372159047fSniklas
20382159047fSniklas /* Write it into the file. */
20392159047fSniklas bfd_ardata (arch)->armap_datepos = (SARMAG
20402159047fSniklas + offsetof (struct ar_hdr, ar_date[0]));
20412159047fSniklas if (bfd_seek (arch, bfd_ardata (arch)->armap_datepos, SEEK_SET) != 0
2042007c2a45Smiod || (bfd_bwrite (hdr.ar_date, sizeof (hdr.ar_date), arch)
20432159047fSniklas != sizeof (hdr.ar_date)))
20442159047fSniklas {
2045c074d1c9Sdrahn bfd_perror (_("Writing updated armap timestamp"));
2046b55d4692Sfgsch
2047b55d4692Sfgsch /* Some error while writing. */
2048c074d1c9Sdrahn return TRUE;
20492159047fSniklas }
20502159047fSniklas
2051b55d4692Sfgsch /* We updated the timestamp successfully. */
2052c074d1c9Sdrahn return FALSE;
20532159047fSniklas }
20542159047fSniklas
20552159047fSniklas /* A coff armap looks like :
20562159047fSniklas lARMAG
20572159047fSniklas struct ar_hdr with name = '/'
20582159047fSniklas number of symbols
20592159047fSniklas offset of file for symbol 0
20602159047fSniklas offset of file for symbol 1
20612159047fSniklas
20622159047fSniklas offset of file for symbol n-1
20632159047fSniklas symbol name 0
20642159047fSniklas symbol name 1
20652159047fSniklas
20662159047fSniklas symbol name n-1
20672159047fSniklas */
20682159047fSniklas
2069c074d1c9Sdrahn bfd_boolean
coff_write_armap(bfd * arch,unsigned int elength,struct orl * map,unsigned int symbol_count,int stridx)2070007c2a45Smiod coff_write_armap (bfd *arch,
2071007c2a45Smiod unsigned int elength,
2072007c2a45Smiod struct orl *map,
2073007c2a45Smiod unsigned int symbol_count,
2074007c2a45Smiod int stridx)
20752159047fSniklas {
20762159047fSniklas /* The size of the ranlib is the number of exported symbols in the
2077c074d1c9Sdrahn archive * the number of bytes in an int, + an int for the count. */
20782159047fSniklas unsigned int ranlibsize = (symbol_count * 4) + 4;
20792159047fSniklas unsigned int stringsize = stridx;
20802159047fSniklas unsigned int mapsize = stringsize + ranlibsize;
2081c074d1c9Sdrahn unsigned int archive_member_file_ptr;
20822159047fSniklas bfd *current = arch->archive_head;
20832159047fSniklas unsigned int count;
20842159047fSniklas struct ar_hdr hdr;
20852159047fSniklas unsigned int i;
20862159047fSniklas int padit = mapsize & 1;
20872159047fSniklas
20882159047fSniklas if (padit)
20892159047fSniklas mapsize++;
20902159047fSniklas
2091b55d4692Sfgsch /* Work out where the first object file will go in the archive. */
20922159047fSniklas archive_member_file_ptr = (mapsize
20932159047fSniklas + elength
20942159047fSniklas + sizeof (struct ar_hdr)
20952159047fSniklas + SARMAG);
20962159047fSniklas
2097007c2a45Smiod memset (&hdr, 0, sizeof (struct ar_hdr));
20982159047fSniklas hdr.ar_name[0] = '/';
20992159047fSniklas sprintf (hdr.ar_size, "%-10d", (int) mapsize);
21002159047fSniklas sprintf (hdr.ar_date, "%ld", (long) time (NULL));
2101b55d4692Sfgsch /* This, at least, is what Intel coff sets the values to. */
21022159047fSniklas sprintf ((hdr.ar_uid), "%d", 0);
21032159047fSniklas sprintf ((hdr.ar_gid), "%d", 0);
21042159047fSniklas sprintf ((hdr.ar_mode), "%-7o", (unsigned) 0);
21052159047fSniklas strncpy (hdr.ar_fmag, ARFMAG, 2);
21062159047fSniklas
21072159047fSniklas for (i = 0; i < sizeof (struct ar_hdr); i++)
21082159047fSniklas if (((char *) (&hdr))[i] == '\0')
21092159047fSniklas (((char *) (&hdr))[i]) = ' ';
21102159047fSniklas
2111b55d4692Sfgsch /* Write the ar header for this item and the number of symbols. */
21122159047fSniklas
2113007c2a45Smiod if (bfd_bwrite (&hdr, sizeof (struct ar_hdr), arch)
21142159047fSniklas != sizeof (struct ar_hdr))
2115c074d1c9Sdrahn return FALSE;
21162159047fSniklas
2117c074d1c9Sdrahn if (!bfd_write_bigendian_4byte_int (arch, symbol_count))
2118c074d1c9Sdrahn return FALSE;
21192159047fSniklas
21202159047fSniklas /* Two passes, first write the file offsets for each symbol -
21212159047fSniklas remembering that each offset is on a two byte boundary. */
21222159047fSniklas
21232159047fSniklas /* Write out the file offset for the file associated with each
21242159047fSniklas symbol, and remember to keep the offsets padded out. */
21252159047fSniklas
21262159047fSniklas current = arch->archive_head;
21272159047fSniklas count = 0;
2128007c2a45Smiod while (current != NULL && count < symbol_count)
21292159047fSniklas {
2130b55d4692Sfgsch /* For each symbol which is used defined in this object, write
2131b55d4692Sfgsch out the object file's address in the archive. */
21322159047fSniklas
2133c074d1c9Sdrahn while (count < symbol_count && map[count].u.abfd == current)
21342159047fSniklas {
2135c074d1c9Sdrahn if (!bfd_write_bigendian_4byte_int (arch, archive_member_file_ptr))
2136c074d1c9Sdrahn return FALSE;
21372159047fSniklas count++;
21382159047fSniklas }
2139b55d4692Sfgsch /* Add size of this archive entry. */
2140007c2a45Smiod archive_member_file_ptr += arelt_size (current) + sizeof (struct ar_hdr);
2141b55d4692Sfgsch /* Remember aboout the even alignment. */
21422159047fSniklas archive_member_file_ptr += archive_member_file_ptr % 2;
21432159047fSniklas current = current->next;
21442159047fSniklas }
21452159047fSniklas
2146b55d4692Sfgsch /* Now write the strings themselves. */
21472159047fSniklas for (count = 0; count < symbol_count; count++)
21482159047fSniklas {
21492159047fSniklas size_t len = strlen (*map[count].name) + 1;
21502159047fSniklas
2151007c2a45Smiod if (bfd_bwrite (*map[count].name, len, arch) != len)
2152c074d1c9Sdrahn return FALSE;
21532159047fSniklas }
21542159047fSniklas
21552159047fSniklas /* The spec sez this should be a newline. But in order to be
21562159047fSniklas bug-compatible for arc960 we use a null. */
21572159047fSniklas if (padit)
21582159047fSniklas {
2159007c2a45Smiod if (bfd_bwrite ("", 1, arch) != 1)
2160c074d1c9Sdrahn return FALSE;
21612159047fSniklas }
21622159047fSniklas
2163c074d1c9Sdrahn return TRUE;
21642159047fSniklas }
2165