mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2024-11-25 05:00:01 +00:00
Archive doc.
This commit is contained in:
parent
5d13867674
commit
4ee249dab1
279
bfd/archive.c
279
bfd/archive.c
@ -24,16 +24,53 @@ SECTION
|
||||
Archives
|
||||
|
||||
DESCRIPTION
|
||||
Gumby, you promised to write this bit...
|
||||
|
||||
Archives are supported in BFD in <<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 attaching
|
||||
them as children to another BFD and then closing the parent
|
||||
BFD.
|
||||
An archive (or library) is just another BFD. It has a symbol
|
||||
table, although there's not much a user program will do with it.
|
||||
|
||||
The big difference between an archive BFD and an ordinary BFD
|
||||
is that the archive doesn't have sections. Instead it has a
|
||||
chain of BFDs considered its contents. These BFDs can be
|
||||
manipulated just like any other. The BFDs contained in an
|
||||
archive opened for reading will all be opened for reading; you
|
||||
may put either input or output BFDs into an archive opened for
|
||||
output; it will be handled correctly when the archive is closed.
|
||||
|
||||
Use <<bfd_openr_next_archived_file>> to step through all
|
||||
the contents of an archive opened for input. It's not
|
||||
required that you read the entire archive if you don't want
|
||||
to! Read it until you find what you want.
|
||||
|
||||
Archive contents of output BFDs are chained through the
|
||||
<<next>> pointer in a BFD. The first one is findable through
|
||||
the <<archive_head>> slot of the archive. Set it with
|
||||
<<set_archive_head>> (q.v.). A given BFD may be in only one
|
||||
open output archive at a time.
|
||||
|
||||
As expected, the BFD archive code is more general than the
|
||||
archive code of any given environment. BFD archives may
|
||||
contain files of different formats (eg a.out and coff) and
|
||||
even different architectures. You may even place archives
|
||||
recursively into archives!
|
||||
|
||||
This can cause unexpected confusion, since some archive
|
||||
formats are more expressive than others. For instance intel
|
||||
COFF archives can preserve long filenames; Sun a.out archives
|
||||
cannot. If you move a file from the first to the second
|
||||
format and back again, the filename may be truncated.
|
||||
Likewise, different a.out environments have different
|
||||
conventions as to how they truncate filenames, whether they
|
||||
preserve directory names in filenames, etc. When
|
||||
interoperating with native tools, be sure your files are
|
||||
homogeneous.
|
||||
|
||||
Beware: most of these formats do not react well to the
|
||||
presence of spaces in filenames. We do the best we can, but
|
||||
can't always handle this due to restrctions in the format of
|
||||
archives. Many unix utilities are braindead in regards to
|
||||
spaces and such in filenames anyway, so this shouldn't be much
|
||||
of a restriction.
|
||||
*/
|
||||
|
||||
/* Assumes:
|
||||
@ -42,6 +79,20 @@ DESCRIPTION
|
||||
o - all arch headers are the same size (across architectures).
|
||||
*/
|
||||
|
||||
/* Some formats provide a way to cram a long filename into the short
|
||||
(16 chars) space provided by a bsd archive. The trick is: make a
|
||||
special "file" in the front of the archive, sort of like the SYMDEF
|
||||
entry. If the filename is too long to fit, put it in the extended
|
||||
name table, and use its index as the filename. To prevent
|
||||
confusion prepend the index with a space. This means you can't
|
||||
have filenames that start with a space, but then again, many unix
|
||||
utilities can't handle that anyway.
|
||||
|
||||
This scheme unfortunately requires that you stand on your head in
|
||||
order to write an archive since you need to put a magic file at the
|
||||
front, and need to touch every entry to do so. C'est la vie.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include "bfd.h"
|
||||
@ -57,7 +108,7 @@ DESCRIPTION
|
||||
/* We keep a cache of archive filepointers to archive elements to
|
||||
speed up searching the archive by filepos. We only add an entry to
|
||||
the cache when we actually read one. We also don't sort the cache;
|
||||
it's short enough to search linearly.
|
||||
it's generally short enough to search linearly.
|
||||
Note that the pointers here point to the front of the ar_hdr, not
|
||||
to the front of the contents!
|
||||
*/
|
||||
@ -91,17 +142,28 @@ _bfd_generic_mkarchive (abfd)
|
||||
FUNCTION
|
||||
bfd_get_next_mapent
|
||||
|
||||
DESCRIPTION
|
||||
What this does
|
||||
|
||||
SYNOPSIS
|
||||
symindex bfd_get_next_mapent(bfd *, symindex, carsym **);
|
||||
symindex bfd_get_next_mapent(bfd *, symindex previous, carsym ** sym);
|
||||
|
||||
DESCRIPTION
|
||||
This function steps through an archive's symbol table (if it
|
||||
has one). Successively updates <<sym>> with the next symbol's
|
||||
information, returning that symbol's (internal) index into the
|
||||
symbol table.
|
||||
|
||||
Supply BFD_NO_MORE_SYMBOLS as the <<previous>> entry to get
|
||||
the first one; returns BFD_NO_MORE_SYMBOLS when you're already
|
||||
got the last one.
|
||||
|
||||
A <<carsym>> is a canonical archive symbol. The only
|
||||
user-visible element is its name, a null-terminated string.
|
||||
*/
|
||||
|
||||
symindex
|
||||
bfd_get_next_mapent (abfd, prev, entry)
|
||||
bfd *abfd;
|
||||
symindex prev;
|
||||
carsym **entry;
|
||||
DEFUN(bfd_get_next_mapent,(abfd, prev, entry)
|
||||
bfd *abfd AND
|
||||
symindex prev AND
|
||||
carsym **entry)
|
||||
{
|
||||
if (!bfd_has_map (abfd)) {
|
||||
bfd_error = invalid_operation;
|
||||
@ -116,7 +178,6 @@ bfd_get_next_mapent (abfd, prev, entry)
|
||||
return prev;
|
||||
}
|
||||
|
||||
|
||||
/* To be called by backends only */
|
||||
bfd *
|
||||
_bfd_create_empty_archive_element_shell (obfd)
|
||||
@ -136,14 +197,12 @@ _bfd_create_empty_archive_element_shell (obfd)
|
||||
FUNCTION
|
||||
bfd_set_archive_head
|
||||
|
||||
DESCRIPTION
|
||||
Used whilst processing archives. Sets the head of the chain of
|
||||
BFDs contained in an archive to @var{new_head}. (see chapter
|
||||
on archives)
|
||||
|
||||
SYNOPSIS
|
||||
boolean bfd_set_archive_head(bfd *output, bfd *new_head);
|
||||
|
||||
DESCRIPTION
|
||||
Used whilst processing archives. Sets the head of the chain of
|
||||
BFDs contained in an archive to @var{new_head}.
|
||||
*/
|
||||
|
||||
boolean
|
||||
@ -203,7 +262,6 @@ add_bfd_to_cache (arch_bfd, filepos, new_elt)
|
||||
|
||||
/* The name begins with space. Hence the rest of the name is an index into
|
||||
the string table. */
|
||||
|
||||
char *
|
||||
get_extended_arelt_filename (arch, name)
|
||||
bfd *arch;
|
||||
@ -320,6 +378,11 @@ snarf_ar_hdr (abfd)
|
||||
return ared;
|
||||
}
|
||||
|
||||
/* This is an internal function; it's mainly used when indexing
|
||||
through the archive symbol table, but also used to get the next
|
||||
element, since it handles the bookkeeping so nicely for us.
|
||||
*/
|
||||
|
||||
bfd *
|
||||
get_elt_at_filepos (archive, filepos)
|
||||
bfd *archive;
|
||||
@ -360,17 +423,18 @@ get_elt_at_filepos (archive, filepos)
|
||||
FUNCTION
|
||||
bfd_get_elt_at_index
|
||||
|
||||
DESCRIPTION
|
||||
Return the sub bfd contained within the archive at archive index n.
|
||||
|
||||
SYNOPSIS
|
||||
bfd *bfd_get_elt_at_index(bfd *, int);
|
||||
bfd *bfd_get_elt_at_index(bfd * archive, int index);
|
||||
|
||||
DESCRIPTION
|
||||
Return the bfd which is referenced by the symbol indexed by <<index>>.
|
||||
<<index>> should have been returned by <<bfd_get_next_mapent>> (q.v.).
|
||||
|
||||
*/
|
||||
bfd *
|
||||
bfd_get_elt_at_index (abfd, index)
|
||||
bfd *abfd;
|
||||
int index;
|
||||
DEFUN(bfd_get_elt_at_index,(abfd, index)
|
||||
bfd *abfd AND
|
||||
int index)
|
||||
{
|
||||
bfd *result =
|
||||
get_elt_at_filepos
|
||||
@ -382,17 +446,17 @@ bfd_get_elt_at_index (abfd, index)
|
||||
FUNCTION
|
||||
bfd_openr_next_archived_file
|
||||
|
||||
SYNOPSIS
|
||||
bfd* bfd_openr_next_archived_file(bfd *archive, bfd *previous);
|
||||
|
||||
DESCRIPTION
|
||||
Initially provided a BFD containing an archive and NULL, opens
|
||||
a BFD on the first contained element and returns that.
|
||||
an inpout 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.
|
||||
|
||||
SYNOPSIS
|
||||
bfd* bfd_openr_next_archived_file(bfd *archive, bfd *previous);
|
||||
|
||||
*/
|
||||
|
||||
bfd *
|
||||
@ -401,17 +465,17 @@ DEFUN(bfd_openr_next_archived_file,(archive, last_file),
|
||||
bfd*last_file)
|
||||
{
|
||||
|
||||
if ((bfd_get_format (archive) != bfd_archive) ||
|
||||
(archive->direction == write_direction)) {
|
||||
bfd_error = invalid_operation;
|
||||
return NULL;
|
||||
}
|
||||
if ((bfd_get_format (archive) != bfd_archive) ||
|
||||
(archive->direction == write_direction)) {
|
||||
bfd_error = invalid_operation;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
return BFD_SEND (archive,
|
||||
openr_next_archived_file,
|
||||
(archive,
|
||||
last_file));
|
||||
return BFD_SEND (archive,
|
||||
openr_next_archived_file,
|
||||
(archive,
|
||||
last_file));
|
||||
|
||||
}
|
||||
|
||||
@ -431,7 +495,7 @@ bfd *bfd_generic_openr_next_archived_file(archive, last_file)
|
||||
|
||||
return get_elt_at_filepos (archive, filestart);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bfd_target *
|
||||
bfd_generic_archive_p (abfd)
|
||||
@ -482,66 +546,66 @@ bfd_slurp_bsd_armap (abfd)
|
||||
bfd *abfd;
|
||||
{
|
||||
|
||||
struct areltdata *mapdata;
|
||||
char nextname[17];
|
||||
unsigned int counter = 0;
|
||||
int *raw_armap, *rbase;
|
||||
struct artdata *ardata = bfd_ardata (abfd);
|
||||
char *stringbase;
|
||||
struct areltdata *mapdata;
|
||||
char nextname[17];
|
||||
unsigned int counter = 0;
|
||||
int *raw_armap, *rbase;
|
||||
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);
|
||||
/* 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;
|
||||
}
|
||||
/* 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;
|
||||
}
|
||||
|
||||
mapdata = snarf_ar_hdr (abfd);
|
||||
if (mapdata == NULL) return false;
|
||||
mapdata = snarf_ar_hdr (abfd);
|
||||
if (mapdata == NULL) return false;
|
||||
|
||||
raw_armap = (int *) bfd_zalloc(abfd,mapdata->parsed_size);
|
||||
if (raw_armap == NULL) {
|
||||
bfd_error = no_memory;
|
||||
byebye:
|
||||
bfd_release (abfd, (PTR)mapdata);
|
||||
return false;
|
||||
}
|
||||
raw_armap = (int *) bfd_zalloc(abfd,mapdata->parsed_size);
|
||||
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;
|
||||
}
|
||||
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 = 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;
|
||||
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 < ardata->symdef_count; counter++) {
|
||||
struct symdef *sym = ((struct symdef *) rbase) + counter;
|
||||
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)));
|
||||
}
|
||||
for (;counter < ardata->symdef_count; counter++) {
|
||||
struct symdef *sym = ((struct symdef *) rbase) + counter;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
/* Returns false on error, true otherwise */
|
||||
@ -846,6 +910,12 @@ DEFUN(bfd_ar_hdr_from_filesystem, (abfd,filename),
|
||||
return ared;
|
||||
}
|
||||
|
||||
/* This is magic required by the "ar" program. Since it's
|
||||
undocumented, it's undocumented. You may think that it would
|
||||
take a strong stomach to write this, and it does, but it takes
|
||||
even a stronger stomach to try to code around such a thing!
|
||||
*/
|
||||
|
||||
struct ar_hdr *
|
||||
DEFUN(bfd_special_undocumented_glue, (abfd, filename),
|
||||
bfd *abfd AND
|
||||
@ -1193,9 +1263,11 @@ bsd_write_armap (arch, elength, map, orl_count, stridx)
|
||||
unsigned int orl_count;
|
||||
int stridx;
|
||||
{
|
||||
int padit = stridx & 1;
|
||||
unsigned int ranlibsize = orl_count * sizeof (struct ranlib);
|
||||
unsigned int stringsize = stridx + 4;
|
||||
unsigned int mapsize = stringsize + ranlibsize + 4;
|
||||
unsigned int stringsize = stridx + padit;
|
||||
/* Include 8 bytes to store ranlibsize and stringsize in output. */
|
||||
unsigned int mapsize = ranlibsize + stringsize + 8;
|
||||
file_ptr firstreal;
|
||||
bfd *current = arch->archive_head;
|
||||
bfd *last_elt = current; /* last element arch seen */
|
||||
@ -1204,9 +1276,6 @@ bsd_write_armap (arch, elength, map, orl_count, stridx)
|
||||
struct ar_hdr hdr;
|
||||
struct stat statbuf;
|
||||
unsigned int i;
|
||||
int padit = mapsize & 1;
|
||||
|
||||
if (padit) mapsize ++;
|
||||
|
||||
firstreal = mapsize + elength + sizeof (struct ar_hdr) + SARMAG;
|
||||
|
||||
@ -1243,7 +1312,7 @@ bsd_write_armap (arch, elength, map, orl_count, stridx)
|
||||
}
|
||||
|
||||
/* now write the strings themselves */
|
||||
bfd_h_put_32(arch, stridx, (PTR)&temp);
|
||||
bfd_h_put_32(arch, stringsize, (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);
|
||||
@ -1263,15 +1332,15 @@ bsd_write_armap (arch, elength, map, orl_count, stridx)
|
||||
number of symbols
|
||||
offset of file for symbol 0
|
||||
offset of file for symbol 1
|
||||
..
|
||||
|
||||
offset of file for symbol n-1
|
||||
symbol name 0
|
||||
symbol name 1
|
||||
..
|
||||
|
||||
symbol name n-1
|
||||
|
||||
*/
|
||||
|
||||
|
||||
boolean
|
||||
coff_write_armap (arch, elength, map, symbol_count, stridx)
|
||||
bfd *arch;
|
||||
|
Loading…
Reference in New Issue
Block a user