+/* BFD back-end for archive files (libraries).
+ Copyright (C) 1990-1991 Free Software Foundation, Inc.
+ Written by Cygnus Support. Mostly Gumby Henkel-Wallace's fault.
-/*** archive.c -- an attempt at combining the machine-independent parts of
- archives */
+This file is part of BFD, the Binary File Descriptor library.
-/* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
-
-This file is part of BFD, the Binary File Diddler.
-
-BFD is free software; you can redistribute it and/or modify
+This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 1, or (at your option)
-any later version.
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
-BFD is distributed in the hope that it will be useful,
+This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with BFD; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*doc*
+@setfilename archive-info
+@section Archives
+
+Gumby, you promised to write this bit...
+
+Archives are supported in BFD in @code{archive.c}.
+An archive is represented internally just like another BFD, with a
+pointer to a chain of contained BFDs. Archives can be created by
+opening BFDs, linking them together and attatching them as children to
+another BFD and then closing the parent BFD.
+
+*-*/
/* Assumes:
o - all archive elements start on an even boundary, newline padded;
o - all arch headers are the same size (across architectures).
*/
-/* $Id$
- */
-
+/* $Id$ */
-#include "sysdep.h"
+#include <sysdep.h>
#include "bfd.h"
#include "libbfd.h"
#include "ar.h"
#define arch_hdr(bfd) ((struct ar_hdr *) \
(((struct areltdata *)((bfd)->arelt_data))->arch_header))
-
\f
-
boolean
_bfd_generic_mkarchive (abfd)
bfd *abfd;
{
- abfd->tdata = bfd_zalloc(abfd, sizeof (struct artdata));
+ set_tdata (abfd, bfd_zalloc(abfd, sizeof (struct artdata)));
- if (abfd->tdata == NULL) {
+ if (bfd_ardata (abfd) == NULL) {
bfd_error = no_memory;
return false;
}
return true;
}
+/*proto* bfd_get_next_mapent
+What this does
+*; PROTO(symindex, bfd_get_next_mapent, (bfd *, symindex, carsym **));
+*/
symindex
bfd_get_next_mapent (abfd, prev, entry)
bfd *abfd;
- symindex prev;
+ symindex prev;
carsym **entry;
{
if (!bfd_has_map (abfd)) {
}
if (prev == BFD_NO_MORE_SYMBOLS) prev = 0;
- else if (++prev >= (symindex)(bfd_ardata (abfd)->symdef_count))
+ else if (++prev >= bfd_ardata (abfd)->symdef_count)
return BFD_NO_MORE_SYMBOLS;
*entry = (bfd_ardata (abfd)->symdefs + prev);
return nbfd;
}
+/*proto* bfd_set_archive_head
+Used whilst processing archives. Sets the head of the chain of BFDs
+contained in an archive to @var{new_head}. (see chapter on archives)
+*; PROTO(boolean, bfd_set_archive_head, (bfd *output, bfd *new_head));
+*/
+
boolean
-bfd_set_archive_head (output_archive, new_head)
- bfd *output_archive, *new_head;
+DEFUN(bfd_set_archive_head,(output_archive, new_head),
+ bfd *output_archive AND
+ bfd *new_head)
{
-
+
output_archive->archive_head = new_head;
return true;
}
bfd *arch_bfd, *new_elt;
file_ptr filepos;
{
- struct ar_cache *new_cache = ((struct ar_cache *)bfd_zalloc(arch_bfd,sizeof (struct ar_cache)));
+ struct ar_cache *new_cache = (struct ar_cache *)
+ bfd_zalloc(arch_bfd, sizeof (struct ar_cache));
if (new_cache == NULL) {
bfd_error = no_memory;
bfd *arch;
char *name;
{
- extern int errno;
+#ifndef errno
+ extern int errno;
+#endif
unsigned long index = 0;
/* Should extract string so that I can guarantee not to overflow into
snarf_ar_hdr (abfd)
bfd *abfd;
{
- extern int errno;
+#ifndef errno
+ extern int errno;
+#endif
+
struct ar_hdr hdr;
char *hdrp = (char *) &hdr;
unsigned int parsed_size;
return NULL;
}
- /* extract the filename from the archive */
- if (hdr.ar_name[0] == ' ' && bfd_ardata (abfd)->extended_names != NULL) {
+ /* extract the filename from the archive - there are two ways to
+ specify an extendend name table, either the first char of the
+ name is a space, or it's a slash */
+ if ((hdr.ar_name[0] == '/' || hdr.ar_name[0] == ' ') && bfd_ardata (abfd)->extended_names != NULL) {
filename = get_extended_arelt_filename (abfd, hdr.ar_name);
if (filename == NULL) {
bfd_error = malformed_archive;
ared = (struct areltdata *) allocptr;
ared->arch_header = allocptr + sizeof (struct areltdata);
- memcpy ((char *) ared->arch_header, &hdr, sizeof (struct ar_hdr));
+ memcpy ((char *) ared->arch_header, (char *) &hdr, sizeof (struct ar_hdr));
ared->parsed_size = parsed_size;
if (filename != NULL) ared->filename = filename;
n_nfd = _bfd_create_empty_archive_element_shell (archive);
if (n_nfd == NULL) {
+ bfd_release (archive, (PTR)new_areldata);
return NULL;
}
n_nfd->origin = bfd_tell (archive);
return n_nfd;
/* huh? */
+ bfd_release (archive, (PTR)n_nfd);
+ bfd_release (archive, (PTR)new_areldata);
return NULL;
}
+/*proto* bfd_get_elt_at_index
+
+*; PROTO(bfd *, bfd_get_elt_at_index, (bfd *, int));
+
+*/
bfd *
bfd_get_elt_at_index (abfd, index)
bfd *abfd;
return result;
}
-/* If you've got an archive, call this to read each subfile. */
+/*proto* bfd_openr_next_archived_file
+Initially provided a BFD containing an archive and NULL, opens a BFD
+on the first contained element and returns that. Subsequent calls to
+bfd_openr_next_archived_file should pass the archive and the previous
+return value to return a created BFD to the next contained element.
+NULL is returned when there are no more.
+
+*; PROTO(bfd*, bfd_openr_next_archived_file,
+ (bfd *archive, bfd *previous));
+
+*/
+
bfd *
-bfd_openr_next_archived_file (archive, last_file)
- bfd *archive, *last_file;
+DEFUN(bfd_openr_next_archived_file,(archive, last_file),
+ bfd *archive AND
+ bfd*last_file)
{
if ((bfd_get_format (archive) != bfd_archive) ||
if (!last_file)
filestart = bfd_ardata (archive)->first_file_filepos;
else {
- unsigned int size = arelt_size(last_file);
- filestart = last_file->origin +size + size %2;
-}
-
-
+ unsigned int size = arelt_size(last_file);
+ /* Pad to an even boundary... */
+ filestart = last_file->origin + size + size%2;
+ }
return get_elt_at_filepos (archive, filestart);
}
if (strncmp (armag, ARMAG, SARMAG)) return 0;
#endif
- bfd_set_ardata(abfd, (struct artdata *) bfd_zalloc(abfd,sizeof (struct artdata)));
+ /* We are setting bfd_ardata(abfd) here, but since bfd_ardata
+ involves a cast, we can't do it as the left operand of assignment. */
+ set_tdata (abfd, bfd_zalloc(abfd,sizeof (struct artdata)));
if (bfd_ardata (abfd) == NULL) {
bfd_error = no_memory;
return 0;
}
- /* armap could be left ungc'd! FIXME -- potential storage leak */
if (!BFD_SEND (abfd, _bfd_slurp_extended_name_table, (abfd))) {
bfd_release(abfd, bfd_ardata (abfd));
abfd->tdata = NULL;
bfd_slurp_bsd_armap (abfd)
bfd *abfd;
{
+
struct areltdata *mapdata;
char nextname[17];
unsigned int counter = 0;
struct artdata *ardata = bfd_ardata (abfd);
char *stringbase;
+ /* FIXME, if the read fails, this routine quietly returns "true"!!
+ It should probably do that if the read gives 0 bytes (empty archive),
+ but fail for any other size... */
if (bfd_read ((PTR)nextname, 1, 16, abfd) == 16) {
/* The archive has at least 16 bytes in it */
bfd_seek (abfd, -16L, SEEK_CUR);
+ /* This should be using RANLIBMAG, but at least it can be grepped for
+ in this comment. */
if (strncmp (nextname, "__.SYMDEF ", 16)) {
bfd_has_map (abfd) = false;
return true;
if (raw_armap == NULL) {
bfd_error = no_memory;
byebye:
+ bfd_release (abfd, (PTR)mapdata);
return false;
}
if (bfd_read ((PTR)raw_armap, 1, mapdata->parsed_size, abfd) !=
mapdata->parsed_size) {
bfd_error = malformed_archive;
+ bfd_release (abfd, (PTR)raw_armap);
goto byebye;
}
- ardata->symdef_count = *(raw_armap) / sizeof (struct symdef);
+ ardata->symdef_count = bfd_h_get_32(abfd, (PTR)raw_armap) / sizeof (struct symdef);
ardata->cache = 0;
rbase = raw_armap+1;
ardata->symdefs = (carsym *) rbase;
stringbase = ((char *) (ardata->symdefs + ardata->symdef_count)) + 4;
- for (;counter < (unsigned)( ardata->symdef_count); counter++) {
+ for (;counter < ardata->symdef_count; counter++) {
struct symdef *sym = ((struct symdef *) rbase) + counter;
- sym->s.name = sym->s.string_offset + stringbase;
+ sym->s.name = bfd_h_get_32(abfd, (PTR)(&(sym->s.string_offset))) + stringbase;
+ sym->file_offset = bfd_h_get_32(abfd, (PTR)( &(sym->file_offset)));
}
ardata->first_file_filepos = bfd_tell (abfd);
/* Pad to an even boundary if you have to */
ardata->first_file_filepos += (ardata-> first_file_filepos) %2;
+ /* FIXME, we should provide some way to free raw_ardata when
+ we are done using the strings from it. For now, it seems
+ to be allocated on an obstack anyway... */
bfd_has_map (abfd) = true;
}
return true;
char *stringbase;
unsigned int stringsize;
carsym *carsyms;
+ int result;
- if (bfd_read ((PTR)&nextname, 1, 1, abfd) != 1) {
- bfd_seek (abfd, -1L, SEEK_CUR);
- bfd_has_map(abfd) = false;
- return true;
- }
+ result = bfd_read ((PTR)&nextname, 1, 1, abfd);
bfd_seek (abfd, -1L, SEEK_CUR);
- if (nextname != '/') {
+ if (result != 1 || nextname != '/') {
/* Actually I think this is an error for a COFF archive */
bfd_has_map (abfd) = false;
return true;
if (mapdata == NULL) return false;
raw_armap = (int *) bfd_alloc(abfd,mapdata->parsed_size);
- if (raw_armap == NULL) {
+
+ if (raw_armap == NULL)
+ {
bfd_error = no_memory;
byebye:
-
+ bfd_release (abfd, (PTR)mapdata);
return false;
}
+ /* read in the raw map */
if (bfd_read ((PTR)raw_armap, 1, mapdata->parsed_size, abfd) !=
mapdata->parsed_size) {
bfd_error = malformed_archive;
oops:
-
+ bfd_release (abfd, (PTR)raw_armap);
goto byebye;
}
/* Pad to an even boundary if you have to */
ardata->first_file_filepos += (ardata->first_file_filepos) %2;
+ /* We'd like to release these allocations, but we have allocated stuff
+ since then (using the same obstack, if bfd_release is obstack based).
+ So they will stick around until the BFD is closed. */
+ /* bfd_release (abfd, (PTR)raw_armap);
+ bfd_release (abfd, (PTR)mapdata); */
bfd_has_map (abfd) = true;
return true;
}
-
\f
/** Extended name table.
- Normally archives support only 14-character filenames. Intel has extended
- the format: longer names are stored in a special element (the first in the
- archive, or second if there is an armap); the name in the ar_hdr is replaced
- by <space><index into filename element>. Index is the P.R. of an int (radix:
- 8). */
+ Normally archives support only 14-character filenames.
+
+ Intel has extended the format: longer names are stored in a special
+ element (the first in the archive, or second if there is an armap);
+ the name in the ar_hdr is replaced by <space><index into filename
+ element>. Index is the P.R. of an int (radix: 8). Data General have
+ extended the format by using the prefix // for the special element */
/* Returns false on error, true otherwise */
boolean
char nextname[17];
struct areltdata *namedata;
+ /* FIXME: Formatting sucks here, and in case of failure of BFD_READ,
+ we probably don't want to return true. */
if (bfd_read ((PTR)nextname, 1, 16, abfd) == 16) {
- bfd_seek (abfd, -16L, SEEK_CUR);
+ bfd_seek (abfd, -16L, SEEK_CUR);
- if (strncmp (nextname, "ARFILENAMES/ ", 16)) {
- bfd_ardata (abfd)->extended_names = NULL;
- return true;
- }
+ if (strncmp (nextname, "ARFILENAMES/ ", 16) != 0 &&
+ strncmp (nextname, "// ", 16) != 0)
+ {
+ bfd_ardata (abfd)->extended_names = NULL;
+ return true;
+ }
- namedata = snarf_ar_hdr (abfd);
- if (namedata == NULL) return false;
+ namedata = snarf_ar_hdr (abfd);
+ if (namedata == NULL) return false;
-
- bfd_ardata (abfd)->extended_names = bfd_zalloc(abfd,namedata->parsed_size);
- if (bfd_ardata (abfd)->extended_names == NULL) {
- bfd_error = no_memory;
- byebye:
-
- return false;
- }
-
- if (bfd_read ((PTR)bfd_ardata (abfd)->extended_names, 1,
- namedata->parsed_size, abfd) != namedata->parsed_size) {
- bfd_error = malformed_archive;
+ bfd_ardata (abfd)->extended_names = bfd_zalloc(abfd,namedata->parsed_size);
+ if (bfd_ardata (abfd)->extended_names == NULL) {
+ bfd_error = no_memory;
+ byebye:
+ bfd_release (abfd, (PTR)namedata);
+ return false;
+ }
- bfd_ardata (abfd)->extended_names = NULL;
- goto byebye;
- }
+ if (bfd_read ((PTR)bfd_ardata (abfd)->extended_names, 1,
+ namedata->parsed_size, abfd) != namedata->parsed_size) {
+ bfd_error = malformed_archive;
+ bfd_release (abfd, (PTR)(bfd_ardata (abfd)->extended_names));
+ bfd_ardata (abfd)->extended_names = NULL;
+ goto byebye;
+ }
- /* It appears that the extended names are newline-padded, not null padded.
- */
- {
- char *temp = bfd_ardata (abfd)->extended_names;
- for (; *temp != '\0'; ++temp)
- if (*temp == '\n') *temp = '\0';
- }
+ /* Since the archive is supposed to be printable if it contains
+ text, the entries in the list are newline-padded, not null
+ padded. We'll fix that there.. */
+ {
+ char *temp = bfd_ardata (abfd)->extended_names;
+ for (; *temp != '\0'; ++temp)
+ if (*temp == '\n') *temp = '\0';
+ }
- /* Pad to an even boundary if you have to */
- bfd_ardata (abfd)->first_file_filepos = bfd_tell (abfd);
- bfd_ardata (abfd)->first_file_filepos +=
- (bfd_ardata (abfd)->first_file_filepos) %2;
-
-
-}
+ /* Pad to an even boundary if you have to */
+ bfd_ardata (abfd)->first_file_filepos = bfd_tell (abfd);
+ bfd_ardata (abfd)->first_file_filepos +=
+ (bfd_ardata (abfd)->first_file_filepos) %2;
+
+ /* FIXME, we can't release namedata here because it was allocated
+ below extended_names on the obstack... */
+ /* bfd_release (abfd, namedata); */
+ }
return true;
}
void
bfd_dont_truncate_arname (abfd, pathname, arhdr)
bfd *abfd;
- char *pathname;
+ CONST char *pathname;
char *arhdr;
{
- /* This interacts unpleasantly with ar's quick-append option.
+ /* FIXME: This interacts unpleasantly with ar's quick-append option.
Fortunately ic960 users will never use that option. Fixing this
is very hard; fortunately I know how to do it and will do so once
intel's release is out the door. */
struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
int length;
- char *filename = strrchr (pathname, '/');
+ CONST char *filename = strrchr (pathname, '/');
int maxlen = ar_maxnamelen (abfd);
if (filename == NULL)
void
bfd_bsd_truncate_arname (abfd, pathname, arhdr)
bfd *abfd;
- char *pathname;
+ CONST char *pathname;
char *arhdr;
{
struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
int length;
- char *filename = strrchr (pathname, '/');
+ CONST char *filename = strrchr (pathname, '/');
int maxlen = ar_maxnamelen (abfd);
void
bfd_gnu_truncate_arname (abfd, pathname, arhdr)
bfd *abfd;
- char *pathname;
+ CONST char *pathname;
char *arhdr;
{
struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
int length;
- char *filename = strrchr (pathname, '/');
+ CONST char *filename = strrchr (pathname, '/');
int maxlen = ar_maxnamelen (abfd);
if (filename == NULL)
PROTO (boolean, compute_and_write_armap, (bfd *arch, unsigned int elength));
-/* The bfd is open for write and has its format set to bfd_archive */
+/* The BFD is open for write and has its format set to bfd_archive */
boolean
_bfd_write_archive_contents (arch)
bfd *arch;
boolean hasobjects = false; /* if no .o's, don't bother to make a map */
unsigned int i;
-
/* Verify the viability of all entries; if any of them live in the
filesystem (as opposed to living in an archive open for input)
then construct a fresh ar_hdr for them.
hdr.ar_fmag[0] = '`'; hdr.ar_fmag[1] = '\n';
for (i = 0; i < sizeof (struct ar_hdr); i++)
if (((char *)(&hdr))[i] == '\0') (((char *)(&hdr))[i]) = ' ';
- bfd_write (&hdr, 1, sizeof (struct ar_hdr), arch);
+ bfd_write ((char *)&hdr, 1, sizeof (struct ar_hdr), arch);
bfd_write (etable, 1, elength, arch);
if ((elength % 2) == 1) bfd_write ("\n", 1, 1, arch);
struct ar_hdr *hdr = arch_hdr(current);
/* write ar header */
- if (bfd_write (hdr, 1, sizeof(*hdr), arch) != sizeof(*hdr)) {
+ if (bfd_write ((char *)hdr, 1, sizeof(*hdr), arch) != sizeof(*hdr)) {
syserr:
bfd_error = system_call_error;
return false;
\f
/* Note that the namidx for the first symbol is 0 */
-
-
boolean
compute_and_write_armap (arch, elength)
bfd *arch;
orl_max * sizeof (struct orl));
}
- (map[orl_count]).name = &((syms[src_count])->name);
- (map[orl_count]).pos = elt_no;
+ (map[orl_count]).name = (char **) &((syms[src_count])->name);
+ (map[orl_count]).pos = (file_ptr) current;
(map[orl_count]).namidx = stridx;
stridx += strlen ((syms[src_count])->name) + 1;
return true;
}
-\f
- /* FIXME -- have to byte-swap this */
-
boolean
bsd_write_armap (arch, elength, map, orl_count, stridx)
bfd *arch;
unsigned int mapsize = stringsize + ranlibsize;
file_ptr firstreal;
bfd *current = arch->archive_head;
- int last_eltno = 0; /* last element arch seen */
+ bfd *last_elt = current; /* last element arch seen */
int temp;
int count;
struct ar_hdr hdr;
stat (arch->filename, &statbuf);
memset ((char *)(&hdr), 0, sizeof (struct ar_hdr));
- sprintf (hdr.ar_name, "__.SYMDEF");
- sprintf (hdr.ar_size, "%-10d", (int) mapsize);
+ sprintf (hdr.ar_name, RANLIBMAG);
sprintf (hdr.ar_date, "%ld", statbuf.st_mtime);
+ sprintf (hdr.ar_uid, "%d", getuid());
+ sprintf (hdr.ar_gid, "%d", getgid());
+ sprintf (hdr.ar_size, "%-10d", (int) mapsize);
hdr.ar_fmag[0] = '`'; hdr.ar_fmag[1] = '\n';
for (i = 0; i < sizeof (struct ar_hdr); i++)
if (((char *)(&hdr))[i] == '\0') (((char *)(&hdr))[i]) = ' ';
- bfd_write (&hdr, 1, sizeof (struct ar_hdr), arch);
-
- temp = orl_count /* + 4 */;
+ bfd_write ((char *)&hdr, 1, sizeof (struct ar_hdr), arch);
+ bfd_h_put_32(arch, ranlibsize, (PTR)&temp);
bfd_write (&temp, 1, sizeof (temp), arch);
for (count = 0; count < orl_count; count++) {
struct symdef outs;
struct symdef *outp = &outs;
- if ((map[count]).pos != last_eltno) {
- firstreal += arelt_size (current) + sizeof (struct ar_hdr);
- firstreal += firstreal % 2;
- last_eltno = (map[count]).pos;
- current = current->next;
- }
-
- outs.s.string_offset = ((map[count]).namidx) +4;
- outs.file_offset = firstreal;
+ if (((bfd *)(map[count]).pos) != last_elt) {
+ do {
+ firstreal += arelt_size (current) + sizeof (struct ar_hdr);
+ firstreal += firstreal % 2;
+ current = current->next;
+ } while (current != (bfd *)(map[count]).pos);
+ } /* if new archive element */
+
+ last_elt = current;
+ bfd_h_put_32(arch, ((map[count]).namidx),(PTR) &outs.s.string_offset);
+ bfd_h_put_32(arch, firstreal,(PTR) &outs.file_offset);
bfd_write ((char *)outp, 1, sizeof (outs), arch);
}
/* now write the strings themselves */
- temp = stridx + 4;
- bfd_write (&temp, 1, sizeof (temp), arch);
+ bfd_h_put_32(arch, stridx, (PTR)&temp);
+ bfd_write ((PTR)&temp, 1, sizeof (temp), arch);
for (count = 0; count < orl_count; count++)
bfd_write (*((map[count]).name), 1, strlen (*((map[count]).name))+1, arch);
/* Write the ar header for this item and the number of symbols */
- bfd_write (&hdr, 1, sizeof (struct ar_hdr), arch);
- bfd_write (&orl_count, 1, sizeof (orl_count), arch);
+ bfd_write ((PTR)&hdr, 1, sizeof (struct ar_hdr), arch);
+ /* FIXME, this needs to be byte-swapped */
+ bfd_write ((PTR)&orl_count, 1, sizeof (orl_count), arch);
/* Two passes, first write the file offsets for each symbol -
remembering that each offset is on a two byte boundary
current = current->next;
last_eltno++;
}
- bfd_write (&archive_member_file_ptr,
+ /* FIXME, this needs to be byte-swapped */
+ bfd_write ((PTR)&archive_member_file_ptr,
1,
sizeof (archive_member_file_ptr),
arch);
/* now write the strings themselves */
for (count = 0; count < orl_count; count++) {
- bfd_write (*((map[count]).name),
+ bfd_write ((PTR)*((map[count]).name),
1,
strlen (*((map[count]).name))+1, arch);