+/* 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;
/* $Id$ */
-#include "sysdep.h"
+#include <sysdep.h>
#include "bfd.h"
#include "libbfd.h"
#include "ar.h"
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;
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;
bfd *arch;
char *name;
{
+#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;
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) ||
bfd_slurp_bsd_armap (abfd)
bfd *abfd;
{
+
struct areltdata *mapdata;
char nextname[17];
unsigned int counter = 0;
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;
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);
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;
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;
- bfd_release (abfd, (PTR)raw_armap);
- bfd_release (abfd, (PTR)mapdata);
+
+ /* 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
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:
- bfd_release (abfd, (PTR)namedata);
- 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:
+ bfd_release (abfd, (PTR)namedata);
+ return false;
+ }
- 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;
- }
+ 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;
-
- /* FIXME, we can't release namedata here because it was allocated
- below extended_names on the obstack... */
- /* bfd_release (abfd, namedata); */
-}
+ /* 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;
{
/* FIXME: This interacts unpleasantly with ar's quick-append option.
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;
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, RANLIBMAG);
- sprintf (hdr.ar_size, "%-10d", (int) mapsize);
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 ((char *)&hdr, 1, sizeof (struct ar_hdr), arch);
-
- /* FIXME, this needs to be byte-swapped! */
- temp = orl_count /* + 4 */;
+ 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 */
- /* FIXME, this needs to be byte-swapped! */
- 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 ((char *)&hdr, 1, sizeof (struct ar_hdr), arch);
+ bfd_write ((PTR)&hdr, 1, sizeof (struct ar_hdr), arch);
/* FIXME, this needs to be byte-swapped */
- bfd_write (&orl_count, 1, sizeof (orl_count), arch);
+ 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
last_eltno++;
}
/* FIXME, this needs to be byte-swapped */
- bfd_write (&archive_member_file_ptr,
+ 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);