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