mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-23 18:14:13 +08:00
Add support for thin archives.
* bfd/archive.c (_bfd_find_nested_archive): New function. (get_extended_arelt_filename): Add origin parameter. (_bfd_generic_read_ar_hdr_mag): Deal with extended name combined with a file offset. (append_relative_path): New function. (_bfd_get_elt_at_filepos): Deal with external members and nested archives. (bfd_generic_openr_next_archived_file): Thin archives. (bfd_generic_archive_p): Recognize new magic string. (adjust_relative_path): New function. (_bfd_construct_extended_name_table): Construct extended names for thin archive members. (_bfd_write_archive_contents): Emit new magic string, skip copying files for thin archives. * bfd/bfd-in.h (bfd_is_thin_archive): New macro. * bfd/bfd.c (struct bfd): New fields for thin archives. * bfd/libbfd-in.h (struct areltdata): New field for thin archives. * bfd/opncls.c (bfd_close): Delete BFDs for nested archives. * binutils/ar.c (make_thin_archive): New global flag. (map_over_members): Deal with full pathnames in thin archives. (usage, main): Add 'T' option for building thin archives. (replace_members): Pass thin archive flag to ar_emul_append. * binutils/arsup.c (ar_open): Initialize new flag. * binutils/binemul.c (ar_emul_append): Add new parameter for flattening nested archives. (do_ar_emul_default_append): New function. (ar_emul_default_append): Factored out recursive code. * binutils/binemul.h (ar_emul_default_append): Add new parameter. (struct bin_emulation_xfer_struct): New parameter for ar_append. * binutils/dlltool.c (gen_lib_file): Initialize thin archive flag. * binutils/emul_aix.c (ar_emul_aix_internal): Add new flatten parameter, currently unimplemented. All callers changed. * binutils/objcopy.c (copy_archive): Preserve thin archive flag. * binutils/doc/binutils.texi: Update ar documentation. * binutils/testsuite/binutils-all/ar.exp: Add thin archive tests. * include/aout/ar.h (ARMAGT): New magic string for thin archives.
This commit is contained in:
parent
5c81783097
commit
a8da640382
@ -1,3 +1,25 @@
|
||||
2008-03-27 Cary Coutant <ccoutant@google.com>
|
||||
|
||||
Add support for thin archives.
|
||||
* archive.c (_bfd_find_nested_archive): New function.
|
||||
(get_extended_arelt_filename): Add origin parameter.
|
||||
(_bfd_generic_read_ar_hdr_mag): Deal with extended name
|
||||
combined with a file offset.
|
||||
(append_relative_path): New function.
|
||||
(_bfd_get_elt_at_filepos): Deal with external members and
|
||||
nested archives.
|
||||
(bfd_generic_openr_next_archived_file): Thin archives.
|
||||
(bfd_generic_archive_p): Recognize new magic string.
|
||||
(adjust_relative_path): New function.
|
||||
(_bfd_construct_extended_name_table): Construct extended
|
||||
names for thin archive members.
|
||||
(_bfd_write_archive_contents): Emit new magic string, skip
|
||||
copying files for thin archives.
|
||||
* bfd-in.h (bfd_is_thin_archive): New macro.
|
||||
* bfd.c (struct bfd): New fields for thin archives.
|
||||
* libbfd-in.h (struct areltdata): New field for thin archives.
|
||||
* opncls.c (bfd_close): Delete BFDs for nested archives.
|
||||
|
||||
2008-03-25 Bernd Schmidt <bernd.schmidt@analog.com>
|
||||
|
||||
* elf32-bfin.c (bfin_final_link_relocate): New function, wrapper around
|
||||
|
372
bfd/archive.c
372
bfd/archive.c
@ -1,6 +1,6 @@
|
||||
/* BFD back-end for archive files (libraries).
|
||||
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
||||
2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
|
||||
2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
|
||||
Free Software Foundation, Inc.
|
||||
Written by Cygnus Support. Mostly Gumby Henkel-Wallace's fault.
|
||||
|
||||
@ -137,6 +137,7 @@ SUBSECTION
|
||||
#include "aout/ranlib.h"
|
||||
#include "safe-ctype.h"
|
||||
#include "hashtab.h"
|
||||
#include "filenames.h"
|
||||
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
@ -157,7 +158,7 @@ struct ar_cache {
|
||||
#define ar_maxnamelen(abfd) ((abfd)->xvec->ar_max_namelen)
|
||||
|
||||
#define arch_eltdata(bfd) ((struct areltdata *) ((bfd)->arelt_data))
|
||||
#define arch_hdr(bfd) ((struct ar_hdr *) arch_eltdata(bfd)->arch_header)
|
||||
#define arch_hdr(bfd) ((struct ar_hdr *) arch_eltdata (bfd)->arch_header)
|
||||
|
||||
void
|
||||
_bfd_ar_spacepad (char *p, size_t n, const char *fmt, long val)
|
||||
@ -326,24 +327,61 @@ _bfd_add_bfd_to_archive_cache (bfd *arch_bfd, file_ptr filepos, bfd *new_elt)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static bfd *
|
||||
_bfd_find_nested_archive (bfd *arch_bfd, const char *filename)
|
||||
{
|
||||
bfd *abfd;
|
||||
|
||||
for (abfd = arch_bfd->nested_archives;
|
||||
abfd != NULL;
|
||||
abfd = abfd->archive_next)
|
||||
{
|
||||
if (strcmp (filename, abfd->filename) == 0)
|
||||
return abfd;
|
||||
}
|
||||
abfd = bfd_openr (filename, NULL);
|
||||
if (abfd)
|
||||
{
|
||||
abfd->archive_next = arch_bfd->nested_archives;
|
||||
arch_bfd->nested_archives = abfd;
|
||||
}
|
||||
return abfd;
|
||||
}
|
||||
|
||||
/* The name begins with space. Hence the rest of the name is an index into
|
||||
the string table. */
|
||||
|
||||
static char *
|
||||
get_extended_arelt_filename (bfd *arch, const char *name)
|
||||
get_extended_arelt_filename (bfd *arch, const char *name, file_ptr *originp)
|
||||
{
|
||||
unsigned long index = 0;
|
||||
const char *endp;
|
||||
|
||||
/* Should extract string so that I can guarantee not to overflow into
|
||||
the next region, but I'm too lazy. */
|
||||
errno = 0;
|
||||
/* Skip first char, which is '/' in SVR4 or ' ' in some other variants. */
|
||||
index = strtol (name + 1, NULL, 10);
|
||||
index = strtol (name + 1, (char **) &endp, 10);
|
||||
if (errno != 0 || index >= bfd_ardata (arch)->extended_names_size)
|
||||
{
|
||||
bfd_set_error (bfd_error_malformed_archive);
|
||||
return NULL;
|
||||
}
|
||||
/* In a thin archive, a member of an archive-within-an-archive
|
||||
will have the offset in the inner archive encoded here. */
|
||||
if (bfd_is_thin_archive (arch) && endp != NULL && *endp == ':')
|
||||
{
|
||||
file_ptr origin = strtol (endp + 1, NULL, 10);
|
||||
|
||||
if (errno != 0 || index >= bfd_ardata (arch)->extended_names_size)
|
||||
{
|
||||
bfd_set_error (bfd_error_malformed_archive);
|
||||
return NULL;
|
||||
}
|
||||
*originp = origin;
|
||||
}
|
||||
else
|
||||
*originp = 0;
|
||||
|
||||
return bfd_ardata (arch)->extended_names + index;
|
||||
}
|
||||
@ -376,6 +414,7 @@ _bfd_generic_read_ar_hdr_mag (bfd *abfd, const char *mag)
|
||||
bfd_size_type namelen = 0;
|
||||
bfd_size_type allocsize = sizeof (struct areltdata) + sizeof (struct ar_hdr);
|
||||
char *allocptr = 0;
|
||||
file_ptr origin = 0;
|
||||
|
||||
if (bfd_bread (hdrp, sizeof (struct ar_hdr), abfd) != sizeof (struct ar_hdr))
|
||||
{
|
||||
@ -407,7 +446,7 @@ _bfd_generic_read_ar_hdr_mag (bfd *abfd, const char *mag)
|
||||
&& memchr (hdr.ar_name, '/', ar_maxnamelen (abfd)) == NULL))
|
||||
&& bfd_ardata (abfd)->extended_names != NULL)
|
||||
{
|
||||
filename = get_extended_arelt_filename (abfd, hdr.ar_name);
|
||||
filename = get_extended_arelt_filename (abfd, hdr.ar_name, &origin);
|
||||
if (filename == NULL)
|
||||
return NULL;
|
||||
}
|
||||
@ -476,6 +515,7 @@ _bfd_generic_read_ar_hdr_mag (bfd *abfd, const char *mag)
|
||||
ared->arch_header = allocptr + sizeof (struct areltdata);
|
||||
memcpy (ared->arch_header, &hdr, sizeof (struct ar_hdr));
|
||||
ared->parsed_size = parsed_size;
|
||||
ared->origin = origin;
|
||||
|
||||
if (filename != NULL)
|
||||
ared->filename = filename;
|
||||
@ -491,6 +531,30 @@ _bfd_generic_read_ar_hdr_mag (bfd *abfd, const char *mag)
|
||||
return ared;
|
||||
}
|
||||
|
||||
/* Append the relative pathname for a member of the thin archive
|
||||
to the pathname of the directory containing the archive. */
|
||||
|
||||
static char *
|
||||
append_relative_path (bfd *arch, char *elt_name)
|
||||
{
|
||||
const char *arch_name = arch->filename;
|
||||
const char *base_name = lbasename (arch_name);
|
||||
size_t prefix_len;
|
||||
char *filename;
|
||||
|
||||
if (base_name == arch_name)
|
||||
return elt_name;
|
||||
|
||||
prefix_len = base_name - arch_name;
|
||||
filename = bfd_alloc (arch, prefix_len + strlen (elt_name) + 1);
|
||||
if (filename == NULL)
|
||||
return NULL;
|
||||
|
||||
strncpy (filename, arch_name, prefix_len);
|
||||
strcpy (filename + prefix_len, elt_name);
|
||||
return filename;
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
@ -500,6 +564,7 @@ _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos)
|
||||
{
|
||||
struct areltdata *new_areldata;
|
||||
bfd *n_nfd;
|
||||
char *filename;
|
||||
|
||||
if (archive->my_archive)
|
||||
{
|
||||
@ -517,21 +582,74 @@ _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos)
|
||||
if ((new_areldata = _bfd_read_ar_hdr (archive)) == NULL)
|
||||
return NULL;
|
||||
|
||||
n_nfd = _bfd_create_empty_archive_element_shell (archive);
|
||||
filename = new_areldata->filename;
|
||||
|
||||
if (bfd_is_thin_archive (archive))
|
||||
{
|
||||
/* This is a proxy entry for an external file. */
|
||||
if (! IS_ABSOLUTE_PATH (filename))
|
||||
{
|
||||
filename = append_relative_path (archive, filename);
|
||||
if (filename == NULL)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (new_areldata->origin > 0)
|
||||
{
|
||||
/* This proxy entry refers to an element of a nested archive.
|
||||
Locate the member of that archive and return a bfd for it. */
|
||||
bfd *ext_arch = _bfd_find_nested_archive (archive, filename);
|
||||
|
||||
if (ext_arch == NULL
|
||||
|| ! bfd_check_format (ext_arch, bfd_archive))
|
||||
{
|
||||
bfd_release (archive, new_areldata);
|
||||
return NULL;
|
||||
}
|
||||
n_nfd = _bfd_get_elt_at_filepos (ext_arch, new_areldata->origin);
|
||||
if (n_nfd == NULL)
|
||||
{
|
||||
bfd_release (archive, new_areldata);
|
||||
return NULL;
|
||||
}
|
||||
n_nfd->proxy_origin = bfd_tell (archive);
|
||||
return n_nfd;
|
||||
}
|
||||
/* It's not an element of a nested archive;
|
||||
open the external file as a bfd. */
|
||||
n_nfd = bfd_openr (filename, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
n_nfd = _bfd_create_empty_archive_element_shell (archive);
|
||||
}
|
||||
|
||||
if (n_nfd == NULL)
|
||||
{
|
||||
bfd_release (archive, new_areldata);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
n_nfd->origin = bfd_tell (archive);
|
||||
n_nfd->proxy_origin = bfd_tell (archive);
|
||||
|
||||
if (bfd_is_thin_archive (archive))
|
||||
{
|
||||
n_nfd->origin = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
n_nfd->origin = n_nfd->proxy_origin;
|
||||
n_nfd->filename = filename;
|
||||
}
|
||||
|
||||
n_nfd->arelt_data = new_areldata;
|
||||
n_nfd->filename = new_areldata->filename;
|
||||
|
||||
if (_bfd_add_bfd_to_archive_cache (archive, filepos, n_nfd))
|
||||
return n_nfd;
|
||||
|
||||
/* Huh? */
|
||||
/* FIXME: n_nfd isn't allocated in the archive's memory pool.
|
||||
If we reach this point, I think bfd_release will abort. */
|
||||
bfd_release (archive, n_nfd);
|
||||
bfd_release (archive, new_areldata);
|
||||
return NULL;
|
||||
@ -568,8 +686,8 @@ DESCRIPTION
|
||||
bfd *
|
||||
bfd_openr_next_archived_file (bfd *archive, bfd *last_file)
|
||||
{
|
||||
if ((bfd_get_format (archive) != bfd_archive) ||
|
||||
(archive->direction == write_direction))
|
||||
if ((bfd_get_format (archive) != bfd_archive)
|
||||
|| (archive->direction == write_direction))
|
||||
{
|
||||
bfd_set_error (bfd_error_invalid_operation);
|
||||
return NULL;
|
||||
@ -589,7 +707,9 @@ bfd_generic_openr_next_archived_file (bfd *archive, bfd *last_file)
|
||||
else
|
||||
{
|
||||
unsigned int size = arelt_size (last_file);
|
||||
filestart = last_file->origin + size;
|
||||
filestart = last_file->proxy_origin;
|
||||
if (! bfd_is_thin_archive (archive))
|
||||
filestart += size;
|
||||
if (archive->my_archive)
|
||||
filestart -= archive->origin;
|
||||
/* Pad to an even boundary...
|
||||
@ -615,8 +735,11 @@ bfd_generic_archive_p (bfd *abfd)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (strncmp (armag, ARMAG, SARMAG) != 0 &&
|
||||
strncmp (armag, ARMAGB, SARMAG) != 0)
|
||||
bfd_is_thin_archive (abfd) = (strncmp (armag, ARMAGT, SARMAG) == 0);
|
||||
|
||||
if (strncmp (armag, ARMAG, SARMAG) != 0
|
||||
&& strncmp (armag, ARMAGB, SARMAG) != 0
|
||||
&& ! bfd_is_thin_archive (abfd))
|
||||
return 0;
|
||||
|
||||
tdata_hold = bfd_ardata (abfd);
|
||||
@ -1110,7 +1233,7 @@ _bfd_slurp_extended_name_table (bfd *abfd)
|
||||
char *limit = temp + namedata->parsed_size;
|
||||
for (; temp < limit; ++temp)
|
||||
{
|
||||
if (*temp == '\012')
|
||||
if (*temp == ARFMAG[0])
|
||||
temp[temp > ext_names && temp[-1] == '/' ? -1 : 0] = '\0';
|
||||
if (*temp == '\\')
|
||||
*temp = '/';
|
||||
@ -1190,6 +1313,66 @@ normalize (bfd *abfd ATTRIBUTE_UNUSED, const char *file)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Adjust a relative path name based on the reference path. */
|
||||
|
||||
static const char *
|
||||
adjust_relative_path (const char * path, const char * ref_path)
|
||||
{
|
||||
static char *pathbuf = NULL;
|
||||
static int pathbuf_len = 0;
|
||||
const char *pathp = path;
|
||||
const char *refp = ref_path;
|
||||
int element_count = 0;
|
||||
int len;
|
||||
char *newp;
|
||||
|
||||
/* Remove common leading path elements. */
|
||||
for (;;)
|
||||
{
|
||||
const char *e1 = pathp;
|
||||
const char *e2 = refp;
|
||||
|
||||
while (*e1 && ! IS_DIR_SEPARATOR (*e1))
|
||||
++e1;
|
||||
while (*e2 && ! IS_DIR_SEPARATOR (*e2))
|
||||
++e2;
|
||||
if (*e1 == '\0' || *e2 == '\0' || e1 - pathp != e2 - refp
|
||||
|| strncmp (pathp, refp, e1 - pathp) != 0)
|
||||
break;
|
||||
pathp = e1 + 1;
|
||||
refp = e2 + 1;
|
||||
}
|
||||
|
||||
/* For each leading path element in the reference path,
|
||||
insert "../" into the path. */
|
||||
for (; *refp; ++refp)
|
||||
if (IS_DIR_SEPARATOR (*refp))
|
||||
++element_count;
|
||||
len = 3 * element_count + strlen (path) + 1;
|
||||
|
||||
if (len > pathbuf_len)
|
||||
{
|
||||
if (pathbuf != NULL)
|
||||
free (pathbuf);
|
||||
pathbuf_len = 0;
|
||||
pathbuf = bfd_malloc (len);
|
||||
if (pathbuf == NULL)
|
||||
return path;
|
||||
pathbuf_len = len;
|
||||
}
|
||||
|
||||
newp = pathbuf;
|
||||
while (element_count-- > 0)
|
||||
{
|
||||
/* FIXME: Support Windows style path separators as well. */
|
||||
strcpy (newp, "../");
|
||||
newp += 3;
|
||||
}
|
||||
strcpy (newp, pathp);
|
||||
|
||||
return pathbuf;
|
||||
}
|
||||
|
||||
/* Build a BFD style extended name table. */
|
||||
|
||||
bfd_boolean
|
||||
@ -1232,8 +1415,11 @@ _bfd_construct_extended_name_table (bfd *abfd,
|
||||
bfd_size_type total_namelen = 0;
|
||||
bfd *current;
|
||||
char *strptr;
|
||||
const char *last_filename;
|
||||
long last_stroff;
|
||||
|
||||
*tablen = 0;
|
||||
last_filename = NULL;
|
||||
|
||||
/* Figure out how long the table should be. */
|
||||
for (current = abfd->archive_head;
|
||||
@ -1243,6 +1429,42 @@ _bfd_construct_extended_name_table (bfd *abfd,
|
||||
const char *normal;
|
||||
unsigned int thislen;
|
||||
|
||||
if (bfd_is_thin_archive (abfd))
|
||||
{
|
||||
const char *filename = current->filename;
|
||||
|
||||
/* If the element being added is a member of another archive
|
||||
(i.e., we are flattening), use the containing archive's name. */
|
||||
if (current->my_archive
|
||||
&& ! bfd_is_thin_archive (current->my_archive))
|
||||
filename = current->my_archive->filename;
|
||||
|
||||
/* If the path is the same as the previous path seen,
|
||||
reuse it. This can happen when flattening a thin
|
||||
archive that contains other archives. */
|
||||
if (last_filename && strcmp (last_filename, filename) == 0)
|
||||
continue;
|
||||
|
||||
last_filename = filename;
|
||||
|
||||
/* If the path is relative, adjust it relative to
|
||||
the containing archive. */
|
||||
if (! IS_ABSOLUTE_PATH (filename)
|
||||
&& ! IS_ABSOLUTE_PATH (abfd->filename))
|
||||
normal = adjust_relative_path (filename, abfd->filename);
|
||||
else
|
||||
normal = filename;
|
||||
|
||||
/* In a thin archive, always store the full pathname
|
||||
in the extended name table. */
|
||||
total_namelen += strlen (normal) + 1;
|
||||
if (trailing_slash)
|
||||
/* Leave room for trailing slash. */
|
||||
++total_namelen;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
normal = normalize (current, current->filename);
|
||||
if (normal == NULL)
|
||||
return FALSE;
|
||||
@ -1290,38 +1512,85 @@ _bfd_construct_extended_name_table (bfd *abfd,
|
||||
*tablen = total_namelen;
|
||||
strptr = *tabloc;
|
||||
|
||||
last_filename = NULL;
|
||||
last_stroff = 0;
|
||||
|
||||
for (current = abfd->archive_head;
|
||||
current != NULL;
|
||||
current = current->archive_next)
|
||||
{
|
||||
const char *normal;
|
||||
unsigned int thislen;
|
||||
long stroff;
|
||||
const char *filename = current->filename;
|
||||
|
||||
normal = normalize (current, current->filename);
|
||||
if (normal == NULL)
|
||||
return FALSE;
|
||||
if (bfd_is_thin_archive (abfd))
|
||||
{
|
||||
/* If the element being added is a member of another archive
|
||||
(i.e., we are flattening), use the containing archive's name. */
|
||||
if (current->my_archive
|
||||
&& ! bfd_is_thin_archive (current->my_archive))
|
||||
filename = current->my_archive->filename;
|
||||
/* If the path is the same as the previous path seen,
|
||||
reuse it. This can happen when flattening a thin
|
||||
archive that contains other archives.
|
||||
If the path is relative, adjust it relative to
|
||||
the containing archive. */
|
||||
if (last_filename && strcmp (last_filename, filename) == 0)
|
||||
normal = last_filename;
|
||||
else if (! IS_ABSOLUTE_PATH (filename)
|
||||
&& ! IS_ABSOLUTE_PATH (abfd->filename))
|
||||
normal = adjust_relative_path (filename, abfd->filename);
|
||||
else
|
||||
normal = filename;
|
||||
}
|
||||
else
|
||||
{
|
||||
normal = normalize (current, filename);
|
||||
if (normal == NULL)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
thislen = strlen (normal);
|
||||
if (thislen > maxname)
|
||||
if (thislen > maxname || bfd_is_thin_archive (abfd))
|
||||
{
|
||||
/* Works for now; may need to be re-engineered if we
|
||||
encounter an oddball archive format and want to
|
||||
generalise this hack. */
|
||||
struct ar_hdr *hdr = arch_hdr (current);
|
||||
strcpy (strptr, normal);
|
||||
if (! trailing_slash)
|
||||
strptr[thislen] = '\012';
|
||||
else
|
||||
{
|
||||
strptr[thislen] = '/';
|
||||
strptr[thislen + 1] = '\012';
|
||||
if (normal == last_filename)
|
||||
stroff = last_stroff;
|
||||
else
|
||||
{
|
||||
strcpy (strptr, normal);
|
||||
if (! trailing_slash)
|
||||
strptr[thislen] = ARFMAG[0];
|
||||
else
|
||||
{
|
||||
strptr[thislen] = '/';
|
||||
strptr[thislen + 1] = ARFMAG[0];
|
||||
}
|
||||
stroff = strptr - *tabloc;
|
||||
last_stroff = stroff;
|
||||
}
|
||||
hdr->ar_name[0] = ar_padchar (current);
|
||||
_bfd_ar_spacepad (hdr->ar_name + 1, maxname - 1, "%-ld",
|
||||
strptr - *tabloc);
|
||||
strptr += thislen + 1;
|
||||
if (trailing_slash)
|
||||
++strptr;
|
||||
if (bfd_is_thin_archive (abfd) && current->origin > 0)
|
||||
{
|
||||
int len = snprintf (hdr->ar_name + 1, maxname - 1, "%-ld:",
|
||||
stroff);
|
||||
_bfd_ar_spacepad (hdr->ar_name + 1 + len, maxname - 1 - len,
|
||||
"%-ld",
|
||||
current->origin - sizeof (struct ar_hdr));
|
||||
}
|
||||
else
|
||||
_bfd_ar_spacepad (hdr->ar_name + 1, maxname - 1, "%-ld", stroff);
|
||||
if (normal != last_filename)
|
||||
{
|
||||
strptr += thislen + 1;
|
||||
if (trailing_slash)
|
||||
++strptr;
|
||||
last_filename = filename;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1593,6 +1862,7 @@ bfd_gnu_truncate_arname (bfd *abfd, const char *pathname, char *arhdr)
|
||||
{
|
||||
/* We could have foo/bar\\baz, or foo\\bar, or d:bar. */
|
||||
char *bslash = strrchr (pathname, '\\');
|
||||
|
||||
if (filename == NULL || (bslash != NULL && bslash > filename))
|
||||
filename = bslash;
|
||||
if (filename == NULL && pathname[0] != '\0' && pathname[1] == ':')
|
||||
@ -1610,7 +1880,8 @@ bfd_gnu_truncate_arname (bfd *abfd, const char *pathname, char *arhdr)
|
||||
if (length <= maxlen)
|
||||
memcpy (hdr->ar_name, filename, length);
|
||||
else
|
||||
{ /* pathname: meet procrustes */
|
||||
{
|
||||
/* pathname: meet procrustes. */
|
||||
memcpy (hdr->ar_name, filename, maxlen);
|
||||
if ((filename[length - 2] == '.') && (filename[length - 1] == 'o'))
|
||||
{
|
||||
@ -1638,6 +1909,7 @@ _bfd_write_archive_contents (bfd *arch)
|
||||
bfd_boolean hasobjects = FALSE;
|
||||
bfd_size_type wrote;
|
||||
int tries;
|
||||
char *armag;
|
||||
|
||||
/* Verify the viability of all entries; if any of them live in the
|
||||
filesystem (as opposed to living in an archive open for input)
|
||||
@ -1681,7 +1953,10 @@ _bfd_write_archive_contents (bfd *arch)
|
||||
|
||||
if (bfd_seek (arch, (file_ptr) 0, SEEK_SET) != 0)
|
||||
return FALSE;
|
||||
wrote = bfd_bwrite (ARMAG, SARMAG, arch);
|
||||
armag = ARMAG;
|
||||
if (bfd_is_thin_archive (arch))
|
||||
armag = ARMAGT;
|
||||
wrote = bfd_bwrite (armag, SARMAG, arch);
|
||||
if (wrote != SARMAG)
|
||||
return FALSE;
|
||||
|
||||
@ -1707,7 +1982,7 @@ _bfd_write_archive_contents (bfd *arch)
|
||||
return FALSE;
|
||||
if ((elength % 2) == 1)
|
||||
{
|
||||
if (bfd_bwrite ("\012", 1, arch) != 1)
|
||||
if (bfd_bwrite (ARFMAG, 1, arch) != 1)
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
@ -1724,11 +1999,15 @@ _bfd_write_archive_contents (bfd *arch)
|
||||
if (bfd_bwrite (hdr, sizeof (*hdr), arch)
|
||||
!= sizeof (*hdr))
|
||||
return FALSE;
|
||||
if (bfd_is_thin_archive (arch))
|
||||
continue;
|
||||
if (bfd_seek (current, (file_ptr) 0, SEEK_SET) != 0)
|
||||
goto input_err;
|
||||
|
||||
while (remaining)
|
||||
{
|
||||
unsigned int amt = DEFAULT_BUFFERSIZE;
|
||||
|
||||
if (amt > remaining)
|
||||
amt = remaining;
|
||||
errno = 0;
|
||||
@ -1742,9 +2021,10 @@ _bfd_write_archive_contents (bfd *arch)
|
||||
return FALSE;
|
||||
remaining -= amt;
|
||||
}
|
||||
|
||||
if ((arelt_size (current) % 2) == 1)
|
||||
{
|
||||
if (bfd_bwrite ("\012", 1, arch) != 1)
|
||||
if (bfd_bwrite (ARFMAG, 1, arch) != 1)
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
@ -1809,8 +2089,8 @@ _bfd_compute_and_write_armap (bfd *arch, unsigned int elength)
|
||||
goto error_return;
|
||||
|
||||
/* Drop all the files called __.SYMDEF, we're going to make our own. */
|
||||
while (arch->archive_head &&
|
||||
strcmp (arch->archive_head->filename, "__.SYMDEF") == 0)
|
||||
while (arch->archive_head
|
||||
&& strcmp (arch->archive_head->filename, "__.SYMDEF") == 0)
|
||||
arch->archive_head = arch->archive_head->archive_next;
|
||||
|
||||
/* Map over each element. */
|
||||
@ -1851,10 +2131,10 @@ _bfd_compute_and_write_armap (bfd *arch, unsigned int elength)
|
||||
flagword flags = (syms[src_count])->flags;
|
||||
asection *sec = syms[src_count]->section;
|
||||
|
||||
if ((flags & BSF_GLOBAL ||
|
||||
flags & BSF_WEAK ||
|
||||
flags & BSF_INDIRECT ||
|
||||
bfd_is_com_section (sec))
|
||||
if ((flags & BSF_GLOBAL
|
||||
|| flags & BSF_WEAK
|
||||
|| flags & BSF_INDIRECT
|
||||
|| bfd_is_com_section (sec))
|
||||
&& ! bfd_is_und_section (sec))
|
||||
{
|
||||
bfd_size_type namelen;
|
||||
@ -2139,10 +2419,14 @@ coff_write_armap (bfd *arch,
|
||||
return FALSE;
|
||||
count++;
|
||||
}
|
||||
/* Add size of this archive entry. */
|
||||
archive_member_file_ptr += arelt_size (current) + sizeof (struct ar_hdr);
|
||||
/* Remember aboout the even alignment. */
|
||||
archive_member_file_ptr += archive_member_file_ptr % 2;
|
||||
archive_member_file_ptr += sizeof (struct ar_hdr);
|
||||
if (! bfd_is_thin_archive (arch))
|
||||
{
|
||||
/* Add size of this archive entry. */
|
||||
archive_member_file_ptr += arelt_size (current);
|
||||
/* Remember about the even alignment. */
|
||||
archive_member_file_ptr += archive_member_file_ptr % 2;
|
||||
}
|
||||
current = current->archive_next;
|
||||
}
|
||||
|
||||
|
@ -499,6 +499,7 @@ extern void warn_deprecated (const char *, const char *, int, const char *);
|
||||
#define bfd_applicable_section_flags(abfd) ((abfd)->xvec->section_flags)
|
||||
#define bfd_my_archive(abfd) ((abfd)->my_archive)
|
||||
#define bfd_has_map(abfd) ((abfd)->has_armap)
|
||||
#define bfd_is_thin_archive(abfd) ((abfd)->is_thin_archive)
|
||||
|
||||
#define bfd_valid_reloc_types(abfd) ((abfd)->xvec->valid_reloc_types)
|
||||
#define bfd_usrdata(abfd) ((abfd)->usrdata)
|
||||
|
@ -506,6 +506,7 @@ extern void warn_deprecated (const char *, const char *, int, const char *);
|
||||
#define bfd_applicable_section_flags(abfd) ((abfd)->xvec->section_flags)
|
||||
#define bfd_my_archive(abfd) ((abfd)->my_archive)
|
||||
#define bfd_has_map(abfd) ((abfd)->has_armap)
|
||||
#define bfd_is_thin_archive(abfd) ((abfd)->is_thin_archive)
|
||||
|
||||
#define bfd_valid_reloc_types(abfd) ((abfd)->xvec->valid_reloc_types)
|
||||
#define bfd_usrdata(abfd) ((abfd)->usrdata)
|
||||
@ -4659,6 +4660,13 @@ struct bfd
|
||||
origin, with origin set to 0 for non archive files. */
|
||||
ufile_ptr origin;
|
||||
|
||||
/* The origin in the archive of the proxy entry. This will
|
||||
normally be the same as origin, except for thin archives,
|
||||
when it will contain the current offset of the proxy in the
|
||||
thin archive rather than the offset of the bfd in its actual
|
||||
container. */
|
||||
ufile_ptr proxy_origin;
|
||||
|
||||
/* A hash table for section names. */
|
||||
struct bfd_hash_table section_htab;
|
||||
|
||||
@ -4692,6 +4700,8 @@ struct bfd
|
||||
struct bfd *my_archive; /* The containing archive BFD. */
|
||||
struct bfd *archive_next; /* The next BFD in the archive. */
|
||||
struct bfd *archive_head; /* The first BFD in the archive. */
|
||||
struct bfd *nested_archives; /* List of nested archive in a flattened
|
||||
thin archive. */
|
||||
|
||||
/* A chain of BFD structures involved in a link. */
|
||||
struct bfd *link_next;
|
||||
@ -4774,6 +4784,9 @@ struct bfd
|
||||
|
||||
/* Have archive map. */
|
||||
unsigned int has_armap : 1;
|
||||
|
||||
/* Set if this is a thin archive. */
|
||||
unsigned int is_thin_archive : 1;
|
||||
};
|
||||
|
||||
typedef enum bfd_error
|
||||
|
12
bfd/bfd.c
12
bfd/bfd.c
@ -150,6 +150,13 @@ CODE_FRAGMENT
|
||||
. origin, with origin set to 0 for non archive files. *}
|
||||
. ufile_ptr origin;
|
||||
.
|
||||
. {* The origin in the archive of the proxy entry. This will
|
||||
. normally be the same as origin, except for thin archives,
|
||||
. when it will contain the current offset of the proxy in the
|
||||
. thin archive rather than the offset of the bfd in its actual
|
||||
. container. *}
|
||||
. ufile_ptr proxy_origin;
|
||||
.
|
||||
. {* A hash table for section names. *}
|
||||
. struct bfd_hash_table section_htab;
|
||||
.
|
||||
@ -183,6 +190,8 @@ CODE_FRAGMENT
|
||||
. struct bfd *my_archive; {* The containing archive BFD. *}
|
||||
. struct bfd *archive_next; {* The next BFD in the archive. *}
|
||||
. struct bfd *archive_head; {* The first BFD in the archive. *}
|
||||
. struct bfd *nested_archives; {* List of nested archive in a flattened
|
||||
. thin archive. *}
|
||||
.
|
||||
. {* A chain of BFD structures involved in a link. *}
|
||||
. struct bfd *link_next;
|
||||
@ -265,6 +274,9 @@ CODE_FRAGMENT
|
||||
.
|
||||
. {* Have archive map. *}
|
||||
. unsigned int has_armap : 1;
|
||||
.
|
||||
. {* Set if this is a thin archive. *}
|
||||
. unsigned int is_thin_archive : 1;
|
||||
.};
|
||||
.
|
||||
*/
|
||||
|
@ -91,6 +91,7 @@ struct areltdata {
|
||||
char * arch_header; /* it's actually a string */
|
||||
unsigned int parsed_size; /* octets of filesize not including ar_hdr */
|
||||
char *filename; /* null-terminated */
|
||||
file_ptr origin; /* for element of a thin archive */
|
||||
};
|
||||
|
||||
#define arelt_size(bfd) (((struct areltdata *)((bfd)->arelt_data))->parsed_size)
|
||||
|
@ -96,6 +96,7 @@ struct areltdata {
|
||||
char * arch_header; /* it's actually a string */
|
||||
unsigned int parsed_size; /* octets of filesize not including ar_hdr */
|
||||
char *filename; /* null-terminated */
|
||||
file_ptr origin; /* for element of a thin archive */
|
||||
};
|
||||
|
||||
#define arelt_size(bfd) (((struct areltdata *)((bfd)->arelt_data))->parsed_size)
|
||||
|
@ -647,6 +647,8 @@ bfd_boolean
|
||||
bfd_close (bfd *abfd)
|
||||
{
|
||||
bfd_boolean ret;
|
||||
bfd *nbfd;
|
||||
bfd *next;
|
||||
|
||||
if (bfd_write_p (abfd))
|
||||
{
|
||||
@ -654,6 +656,13 @@ bfd_close (bfd *abfd)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Close nested archives (if this bfd is a thin archive). */
|
||||
for (nbfd = abfd->nested_archives; nbfd; nbfd = next)
|
||||
{
|
||||
next = nbfd->archive_next;
|
||||
bfd_close (nbfd);
|
||||
}
|
||||
|
||||
if (! BFD_SEND (abfd, _close_and_cleanup, (abfd)))
|
||||
return FALSE;
|
||||
|
||||
|
@ -1,3 +1,25 @@
|
||||
2008-03-27 Cary Coutant <ccoutant@google.com>
|
||||
|
||||
Add support for thin archives.
|
||||
* ar.c (make_thin_archive): New global flag.
|
||||
(map_over_members): Deal with full pathnames in thin archives.
|
||||
(usage, main): Add 'T' option for building thin archives.
|
||||
(replace_members): Pass thin archive flag to ar_emul_append.
|
||||
* arsup.c (ar_open): Initialize new flag.
|
||||
* binemul.c (ar_emul_append): Add new parameter for
|
||||
flattening nested archives.
|
||||
(do_ar_emul_default_append): New function.
|
||||
(ar_emul_default_append): Factored out recursive code.
|
||||
* binutils/binemul.h (ar_emul_default_append): Add new parameter.
|
||||
(struct bin_emulation_xfer_struct): New parameter for ar_append.
|
||||
* dlltool.c (gen_lib_file): Initialize thin archive flag.
|
||||
* emul_aix.c (ar_emul_aix_internal): Add new flatten
|
||||
parameter, currently unimplemented.
|
||||
All callers changed.
|
||||
* objcopy.c (copy_archive): Preserve thin archive flag.
|
||||
* doc/binutils.texi: Update ar documentation.
|
||||
* NEWS: Mention the new feature.
|
||||
|
||||
2008-03-20 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* readelf.c (process_mips_specific): Declare addr_size as int.
|
||||
|
@ -1,4 +1,9 @@
|
||||
-*- text -*-
|
||||
* Added support for "thin" archives which contain pathnames pointing to
|
||||
object files rather than the files themselves and which contain a
|
||||
flattened symbol index for all objects, and archives, which have been
|
||||
added to the archive.
|
||||
|
||||
* Added -F switch to objdump to include file offsets in the disassembly.
|
||||
|
||||
* Added -c switch to readelf to allow string dumps of archive symbol index.
|
||||
|
@ -40,9 +40,9 @@
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef __GO32___
|
||||
#define EXT_NAME_LEN 3 /* bufflen of addition to name if it's MS-DOS */
|
||||
#define EXT_NAME_LEN 3 /* Bufflen of addition to name if it's MS-DOS. */
|
||||
#else
|
||||
#define EXT_NAME_LEN 6 /* ditto for *NIX */
|
||||
#define EXT_NAME_LEN 6 /* Ditto for *NIX. */
|
||||
#endif
|
||||
|
||||
/* We need to open files in binary modes on system where that makes a
|
||||
@ -51,12 +51,12 @@
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
/* Kludge declaration from BFD! This is ugly! FIXME! XXX */
|
||||
/* Kludge declaration from BFD! This is ugly! FIXME! XXX */
|
||||
|
||||
struct ar_hdr *
|
||||
bfd_special_undocumented_glue (bfd * abfd, const char *filename);
|
||||
|
||||
/* Static declarations */
|
||||
/* Static declarations. */
|
||||
|
||||
static void mri_emul (void);
|
||||
static const char *normalize (const char *, bfd *);
|
||||
@ -74,7 +74,7 @@ static int ranlib_only (const char *archname);
|
||||
static int ranlib_touch (const char *archname);
|
||||
static void usage (int);
|
||||
|
||||
/** Globals and flags */
|
||||
/** Globals and flags. */
|
||||
|
||||
static int mri_mode;
|
||||
|
||||
@ -134,6 +134,9 @@ static bfd_boolean ar_truncate = FALSE;
|
||||
program. */
|
||||
static bfd_boolean full_pathname = FALSE;
|
||||
|
||||
/* Whether to create a "thin" archive (symbol index only -- no files). */
|
||||
static bfd_boolean make_thin_archive = FALSE;
|
||||
|
||||
int interactive = 0;
|
||||
|
||||
static void
|
||||
@ -176,16 +179,25 @@ map_over_members (bfd *arch, void (*function)(bfd *), char **files, int count)
|
||||
match_count = 0;
|
||||
for (head = arch->archive_next; head; head = head->archive_next)
|
||||
{
|
||||
const char * filename;
|
||||
|
||||
PROGRESS (1);
|
||||
if (head->filename == NULL)
|
||||
filename = head->filename;
|
||||
if (filename == NULL)
|
||||
{
|
||||
/* Some archive formats don't get the filenames filled in
|
||||
until the elements are opened. */
|
||||
struct stat buf;
|
||||
bfd_stat_arch_elt (head, &buf);
|
||||
}
|
||||
if ((head->filename != NULL) &&
|
||||
(!FILENAME_CMP (normalize (*files, arch), head->filename)))
|
||||
else if (bfd_is_thin_archive (arch))
|
||||
{
|
||||
/* Thin archives store full pathnames. Need to normalize. */
|
||||
filename = normalize (filename, arch);
|
||||
}
|
||||
|
||||
if ((filename != NULL) &&
|
||||
(!FILENAME_CMP (normalize (*files, arch), filename)))
|
||||
{
|
||||
++match_count;
|
||||
if (counted_name_mode
|
||||
@ -200,6 +212,7 @@ map_over_members (bfd *arch, void (*function)(bfd *), char **files, int count)
|
||||
function (head);
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
/* xgettext:c-format */
|
||||
fprintf (stderr, _("no entry %s in archive\n"), *files);
|
||||
@ -242,10 +255,11 @@ usage (int help)
|
||||
fprintf (s, _(" [c] - do not warn if the library had to be created\n"));
|
||||
fprintf (s, _(" [s] - create an archive index (cf. ranlib)\n"));
|
||||
fprintf (s, _(" [S] - do not build a symbol table\n"));
|
||||
fprintf (s, _(" [T] - make a thin archive\n"));
|
||||
fprintf (s, _(" [v] - be verbose\n"));
|
||||
fprintf (s, _(" [V] - display the version number\n"));
|
||||
fprintf (s, _(" @<file> - read options from <file>\n"));
|
||||
|
||||
|
||||
ar_emul_usage (s);
|
||||
}
|
||||
else
|
||||
@ -284,6 +298,7 @@ normalize (const char *file, bfd *abfd)
|
||||
{
|
||||
/* We could have foo/bar\\baz, or foo\\bar, or d:bar. */
|
||||
char *bslash = strrchr (file, '\\');
|
||||
|
||||
if (filename == NULL || (bslash != NULL && bslash > filename))
|
||||
filename = bslash;
|
||||
if (filename == NULL && file[0] != '\0' && file[1] == ':')
|
||||
@ -302,7 +317,7 @@ normalize (const char *file, bfd *abfd)
|
||||
char *s;
|
||||
|
||||
/* Space leak. */
|
||||
s = (char *) xmalloc (abfd->xvec->ar_max_namelen + 1);
|
||||
s = xmalloc (abfd->xvec->ar_max_namelen + 1);
|
||||
memcpy (s, filename, abfd->xvec->ar_max_namelen);
|
||||
s[abfd->xvec->ar_max_namelen] = '\0';
|
||||
filename = s;
|
||||
@ -376,6 +391,7 @@ main (int argc, char **argv)
|
||||
{
|
||||
/* We could have foo/bar\\baz, or foo\\bar, or d:bar. */
|
||||
char *bslash = strrchr (program_name, '\\');
|
||||
|
||||
if (temp == NULL || (bslash != NULL && bslash > temp))
|
||||
temp = bslash;
|
||||
if (temp == NULL && program_name[0] != '\0' && program_name[1] == ':')
|
||||
@ -559,6 +575,9 @@ main (int argc, char **argv)
|
||||
case 'P':
|
||||
full_pathname = TRUE;
|
||||
break;
|
||||
case 'T':
|
||||
make_thin_archive = TRUE;
|
||||
break;
|
||||
default:
|
||||
/* xgettext:c-format */
|
||||
non_fatal (_("illegal option -- %c"), c);
|
||||
@ -629,6 +648,9 @@ main (int argc, char **argv)
|
||||
arch = open_inarch (inarch_filename,
|
||||
files == NULL ? (char *) NULL : files[0]);
|
||||
|
||||
if (operation == extract && bfd_is_thin_archive (arch))
|
||||
fatal (_("`x' cannot be used on thin archives."));
|
||||
|
||||
switch (operation)
|
||||
{
|
||||
case print_table:
|
||||
@ -933,7 +955,7 @@ write_archive (bfd *iarch)
|
||||
|
||||
if (new_name == NULL)
|
||||
bfd_fatal ("could not create temporary file whilst writing archive");
|
||||
|
||||
|
||||
output_filename = new_name;
|
||||
|
||||
obfd = bfd_openw (new_name, bfd_get_target (iarch));
|
||||
@ -956,6 +978,9 @@ write_archive (bfd *iarch)
|
||||
obfd->flags |= BFD_TRADITIONAL_FORMAT;
|
||||
}
|
||||
|
||||
if (make_thin_archive || bfd_is_thin_archive (iarch))
|
||||
bfd_is_thin_archive (obfd) = 1;
|
||||
|
||||
if (!bfd_set_archive_head (obfd, contents_head))
|
||||
bfd_fatal (old_name);
|
||||
|
||||
@ -1189,7 +1214,8 @@ replace_members (bfd *arch, char **files_to_move, bfd_boolean quick)
|
||||
/* Add to the end of the archive. */
|
||||
after_bfd = get_pos_bfd (&arch->archive_next, pos_end, NULL);
|
||||
|
||||
if (ar_emul_append (after_bfd, *files_to_move, verbose))
|
||||
if (ar_emul_append (after_bfd, *files_to_move, verbose,
|
||||
make_thin_archive))
|
||||
changed = TRUE;
|
||||
|
||||
next_file:;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* arsup.c - Archive support for MRI compatibility
|
||||
Copyright 1992, 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003,
|
||||
2004, 2007 Free Software Foundation, Inc.
|
||||
2004, 2007, 2008 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Binutils.
|
||||
|
||||
@ -207,6 +207,7 @@ ar_open (char *name, int t)
|
||||
bfd_set_format (obfd, bfd_archive);
|
||||
|
||||
obfd->has_armap = 1;
|
||||
obfd->is_thin_archive = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Binutils emulation layer.
|
||||
Copyright 2002, 2003, 2007 Free Software Foundation, Inc.
|
||||
Copyright 2002, 2003, 2007, 2008 Free Software Foundation, Inc.
|
||||
Written by Tom Rix, Red Hat Inc.
|
||||
|
||||
This file is part of GNU Binutils.
|
||||
@ -39,31 +39,60 @@ ar_emul_default_usage (FILE *fp)
|
||||
}
|
||||
|
||||
bfd_boolean
|
||||
ar_emul_append (bfd **after_bfd, char *file_name, bfd_boolean verbose)
|
||||
ar_emul_append (bfd **after_bfd, char *file_name, bfd_boolean verbose,
|
||||
bfd_boolean flatten)
|
||||
{
|
||||
if (bin_dummy_emulation.ar_append)
|
||||
return bin_dummy_emulation.ar_append (after_bfd, file_name, verbose);
|
||||
return bin_dummy_emulation.ar_append (after_bfd, file_name, verbose,
|
||||
flatten);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bfd_boolean
|
||||
ar_emul_default_append (bfd **after_bfd, char *file_name,
|
||||
bfd_boolean verbose)
|
||||
{
|
||||
bfd *temp;
|
||||
static bfd_boolean
|
||||
do_ar_emul_default_append (bfd **after_bfd, bfd *new_bfd,
|
||||
bfd_boolean verbose, bfd_boolean flatten)
|
||||
{
|
||||
/* When flattening, add the members of an archive instead of the
|
||||
archive itself. */
|
||||
if (flatten && bfd_check_format (new_bfd, bfd_archive))
|
||||
{
|
||||
bfd *elt;
|
||||
bfd_boolean added = FALSE;
|
||||
|
||||
temp = *after_bfd;
|
||||
*after_bfd = bfd_openr (file_name, NULL);
|
||||
for (elt = bfd_openr_next_archived_file (new_bfd, NULL);
|
||||
elt;
|
||||
elt = bfd_openr_next_archived_file (new_bfd, elt))
|
||||
{
|
||||
if (do_ar_emul_default_append (after_bfd, elt, verbose, TRUE))
|
||||
{
|
||||
added = TRUE;
|
||||
after_bfd = &((*after_bfd)->archive_next);
|
||||
}
|
||||
}
|
||||
|
||||
AR_EMUL_ELEMENT_CHECK (*after_bfd, file_name);
|
||||
AR_EMUL_APPEND_PRINT_VERBOSE (verbose, file_name);
|
||||
return added;
|
||||
}
|
||||
|
||||
(*after_bfd)->archive_next = temp;
|
||||
AR_EMUL_APPEND_PRINT_VERBOSE (verbose, new_bfd->filename);
|
||||
|
||||
new_bfd->archive_next = *after_bfd;
|
||||
*after_bfd = new_bfd;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bfd_boolean
|
||||
ar_emul_default_append (bfd **after_bfd, char *file_name,
|
||||
bfd_boolean verbose, bfd_boolean flatten)
|
||||
{
|
||||
bfd *new_bfd;
|
||||
|
||||
new_bfd = bfd_openr (file_name, NULL);
|
||||
AR_EMUL_ELEMENT_CHECK (new_bfd, file_name);
|
||||
return do_ar_emul_default_append (after_bfd, new_bfd, verbose, flatten);
|
||||
}
|
||||
|
||||
bfd_boolean
|
||||
ar_emul_replace (bfd **after_bfd, char *file_name, bfd_boolean verbose)
|
||||
{
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Binutils emulation layer.
|
||||
Copyright 2002, 2003, 2007 Free Software Foundation, Inc.
|
||||
Copyright 2002, 2003, 2007, 2008 Free Software Foundation, Inc.
|
||||
Written by Tom Rix, Red Hat Inc.
|
||||
|
||||
This file is part of GNU Binutils.
|
||||
@ -28,8 +28,9 @@
|
||||
|
||||
extern void ar_emul_usage (FILE *);
|
||||
extern void ar_emul_default_usage (FILE *);
|
||||
extern bfd_boolean ar_emul_append (bfd **, char *, bfd_boolean);
|
||||
extern bfd_boolean ar_emul_default_append (bfd **, char *, bfd_boolean);
|
||||
extern bfd_boolean ar_emul_append (bfd **, char *, bfd_boolean, bfd_boolean);
|
||||
extern bfd_boolean ar_emul_default_append (bfd **, char *, bfd_boolean,
|
||||
bfd_boolean);
|
||||
extern bfd_boolean ar_emul_replace (bfd **, char *, bfd_boolean);
|
||||
extern bfd_boolean ar_emul_default_replace (bfd **, char *, bfd_boolean);
|
||||
extern bfd_boolean ar_emul_parse_arg (char *);
|
||||
@ -54,7 +55,7 @@ typedef struct bin_emulation_xfer_struct
|
||||
{
|
||||
/* Print out the extra options. */
|
||||
void (* ar_usage) (FILE *fp);
|
||||
bfd_boolean (* ar_append) (bfd **, char *, bfd_boolean);
|
||||
bfd_boolean (* ar_append) (bfd **, char *, bfd_boolean, bfd_boolean);
|
||||
bfd_boolean (* ar_replace) (bfd **, char *, bfd_boolean);
|
||||
bfd_boolean (* ar_parse_arg) (char *);
|
||||
}
|
||||
|
@ -2813,6 +2813,7 @@ gen_lib_file (void)
|
||||
|
||||
bfd_set_format (outarch, bfd_archive);
|
||||
outarch->has_armap = 1;
|
||||
outarch->is_thin_archive = 0;
|
||||
|
||||
/* Work out a reasonable size of things to put onto one line. */
|
||||
ar_head = make_head ();
|
||||
|
@ -211,6 +211,18 @@ You may use @samp{nm -s} or @samp{nm --print-armap} to list this index
|
||||
table. If an archive lacks the table, another form of @command{ar} called
|
||||
@command{ranlib} can be used to add just the table.
|
||||
|
||||
@cindex thin archives
|
||||
@sc{gnu} @command{ar} can optionally create a @emph{thin} archive,
|
||||
which contains a symbol index and references to the original copies
|
||||
of the member files of the archives. Such an archive is useful
|
||||
for building libraries for use within a local build, where the
|
||||
relocatable objects are expected to remain available, and copying the
|
||||
contents of each object would only waste time and space. Thin archives
|
||||
are also @emph{flattened}, so that adding one or more archives to a
|
||||
thin archive will add the elements of the nested archive individually.
|
||||
The paths to the elements of the archive are stored relative to the
|
||||
archive itself.
|
||||
|
||||
@cindex compatibility, @command{ar}
|
||||
@cindex @command{ar} compatibility
|
||||
@sc{gnu} @command{ar} is designed to be compatible with two different
|
||||
@ -356,6 +368,8 @@ use the @samp{v} modifier with this operation, to request that
|
||||
If you do not specify a @var{member}, all files in the archive
|
||||
are extracted.
|
||||
|
||||
Files cannot be extracted from a thin archive.
|
||||
|
||||
@end table
|
||||
|
||||
A number of modifiers (@var{mod}) may immediately follow the @var{p}
|
||||
@ -434,6 +448,12 @@ with the linker. In order to build a symbol table, you must omit the
|
||||
@samp{S} modifier on the last execution of @samp{ar}, or you must run
|
||||
@samp{ranlib} on the archive.
|
||||
|
||||
@item T
|
||||
@cindex creating thin archive
|
||||
Make the specified @var{archive} a @emph{thin} archive. If it already
|
||||
exists and is a regular archive, the existing members must be present
|
||||
in the same directory as @var{archive}.
|
||||
|
||||
@item u
|
||||
@cindex updating an archive
|
||||
Normally, @samp{ar r}@dots{} inserts all files
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Binutils emulation layer.
|
||||
Copyright 2002, 2003, 2006, 2007 Free Software Foundation, Inc.
|
||||
Copyright 2002, 2003, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
Written by Tom Rix, Red Hat Inc.
|
||||
|
||||
This file is part of GNU Binutils.
|
||||
@ -35,15 +35,6 @@ static bfd_boolean X32 = TRUE;
|
||||
/* Whether to include 64 bit objects. */
|
||||
static bfd_boolean X64 = FALSE;
|
||||
|
||||
static void ar_emul_aix_usage (FILE *);
|
||||
static bfd_boolean ar_emul_aix_append (bfd **, char *, bfd_boolean);
|
||||
static bfd_boolean ar_emul_aix5_append (bfd **, char *, bfd_boolean);
|
||||
static bfd_boolean ar_emul_aix_replace (bfd **, char *, bfd_boolean);
|
||||
static bfd_boolean ar_emul_aix5_replace (bfd **, char *, bfd_boolean);
|
||||
static bfd_boolean ar_emul_aix_parse_arg (char *);
|
||||
static bfd_boolean ar_emul_aix_internal
|
||||
(bfd **, char *, bfd_boolean, const char *, bfd_boolean);
|
||||
|
||||
static void
|
||||
ar_emul_aix_usage (FILE *fp)
|
||||
{
|
||||
@ -56,8 +47,12 @@ ar_emul_aix_usage (FILE *fp)
|
||||
}
|
||||
|
||||
static bfd_boolean
|
||||
ar_emul_aix_internal (bfd **after_bfd, char *file_name, bfd_boolean verbose,
|
||||
const char * target_name, bfd_boolean is_append)
|
||||
ar_emul_aix_internal (bfd ** after_bfd,
|
||||
char * file_name,
|
||||
bfd_boolean verbose,
|
||||
const char * target_name,
|
||||
bfd_boolean is_append,
|
||||
bfd_boolean flatten ATTRIBUTE_UNUSED)
|
||||
{
|
||||
bfd *temp;
|
||||
bfd *try_bfd;
|
||||
@ -97,31 +92,33 @@ ar_emul_aix_internal (bfd **after_bfd, char *file_name, bfd_boolean verbose,
|
||||
|
||||
|
||||
static bfd_boolean
|
||||
ar_emul_aix_append (bfd **after_bfd, char *file_name, bfd_boolean verbose)
|
||||
ar_emul_aix_append (bfd **after_bfd, char *file_name, bfd_boolean verbose,
|
||||
bfd_boolean flatten)
|
||||
{
|
||||
return ar_emul_aix_internal (after_bfd, file_name, verbose,
|
||||
"aixcoff64-rs6000", TRUE);
|
||||
"aixcoff64-rs6000", TRUE, flatten);
|
||||
}
|
||||
|
||||
static bfd_boolean
|
||||
ar_emul_aix5_append (bfd **after_bfd, char *file_name, bfd_boolean verbose)
|
||||
ar_emul_aix5_append (bfd **after_bfd, char *file_name, bfd_boolean verbose,
|
||||
bfd_boolean flatten)
|
||||
{
|
||||
return ar_emul_aix_internal (after_bfd, file_name, verbose,
|
||||
"aix5coff64-rs6000", TRUE);
|
||||
"aix5coff64-rs6000", TRUE, flatten);
|
||||
}
|
||||
|
||||
static bfd_boolean
|
||||
ar_emul_aix_replace (bfd **after_bfd, char *file_name, bfd_boolean verbose)
|
||||
{
|
||||
return ar_emul_aix_internal (after_bfd, file_name, verbose,
|
||||
"aixcoff64-rs6000", FALSE);
|
||||
"aixcoff64-rs6000", FALSE, FALSE);
|
||||
}
|
||||
|
||||
static bfd_boolean
|
||||
ar_emul_aix5_replace (bfd **after_bfd, char *file_name, bfd_boolean verbose)
|
||||
{
|
||||
return ar_emul_aix_internal (after_bfd, file_name, verbose,
|
||||
"aix5coff64-rs6000", FALSE);
|
||||
"aix5coff64-rs6000", FALSE, FALSE);
|
||||
}
|
||||
|
||||
static bfd_boolean
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* objcopy.c -- copy object file from input to output, optionally massaging it.
|
||||
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
|
||||
2001, 2002, 2003, 2004, 2005, 2006, 2007
|
||||
2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Binutils.
|
||||
@ -1830,6 +1830,7 @@ copy_archive (bfd *ibfd, bfd *obfd, const char *output_target,
|
||||
strerror (errno));
|
||||
|
||||
obfd->has_armap = ibfd->has_armap;
|
||||
obfd->is_thin_archive = ibfd->is_thin_archive;
|
||||
|
||||
list = NULL;
|
||||
|
||||
|
@ -1,3 +1,7 @@
|
||||
2008-03-27 Cary Coutant <ccoutant@google.com>
|
||||
|
||||
* binutils-all/ar.exp: Add thin archive tests.
|
||||
|
||||
2008-02-26 Joseph Myers <joseph@codesourcery.com>
|
||||
|
||||
* config/default.exp (gcc_gas_flag, dlltool_gas_flag): Define to
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Copyright 1995, 1997, 2002, 2004, 2007 Free Software Foundation, Inc.
|
||||
# Copyright 1995, 1997, 2002, 2004, 2007, 2008 Free Software Foundation, Inc.
|
||||
|
||||
# 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
|
||||
@ -215,6 +215,110 @@ proc symbol_table { } {
|
||||
pass $testname
|
||||
}
|
||||
|
||||
# Test building a thin archive.
|
||||
|
||||
proc thin_archive { } {
|
||||
global AR
|
||||
global AS
|
||||
global NM
|
||||
global srcdir
|
||||
global subdir
|
||||
|
||||
set testname "ar thin archive"
|
||||
|
||||
if ![binutils_assemble $srcdir/$subdir/bintest.s tmpdir/bintest.o] {
|
||||
unresolved $testname
|
||||
return
|
||||
}
|
||||
|
||||
if [is_remote host] {
|
||||
set archive artest.a
|
||||
set objfile [remote_download host tmpdir/bintest.o]
|
||||
remote_file host delete $archive
|
||||
} else {
|
||||
set archive tmpdir/artest.a
|
||||
set objfile tmpdir/bintest.o
|
||||
}
|
||||
|
||||
remote_file build delete tmpdir/artest.a
|
||||
|
||||
set got [binutils_run $AR "rcT $archive ${objfile}"]
|
||||
if ![string match "" $got] {
|
||||
fail $testname
|
||||
return
|
||||
}
|
||||
|
||||
set got [binutils_run $NM "--print-armap $archive"]
|
||||
if { ![string match "*text_symbol in *bintest.o*" $got] \
|
||||
|| ![string match "*data_symbol in *bintest.o*" $got] \
|
||||
|| ![string match "*common_symbol in *bintest.o*" $got] \
|
||||
|| [string match "*static_text_symbol in *bintest.o*" $got] \
|
||||
|| [string match "*static_data_symbol in *bintest.o*" $got] \
|
||||
|| [string match "*external_symbol in *bintest.o*" $got] } {
|
||||
fail $testname
|
||||
return
|
||||
}
|
||||
|
||||
pass $testname
|
||||
}
|
||||
|
||||
# Test building a thin archive with a nested archive.
|
||||
|
||||
proc thin_archive_with_nested { } {
|
||||
global AR
|
||||
global AS
|
||||
global NM
|
||||
global srcdir
|
||||
global subdir
|
||||
|
||||
set testname "ar thin archive with nested archive"
|
||||
|
||||
if ![binutils_assemble $srcdir/$subdir/bintest.s tmpdir/bintest.o] {
|
||||
unresolved $testname
|
||||
return
|
||||
}
|
||||
|
||||
if [is_remote host] {
|
||||
set archive artest.a
|
||||
set archive2 artest2.a
|
||||
set objfile [remote_download host tmpdir/bintest.o]
|
||||
remote_file host delete $archive
|
||||
} else {
|
||||
set archive tmpdir/artest.a
|
||||
set archive2 tmpdir/artest2.a
|
||||
set objfile tmpdir/bintest.o
|
||||
}
|
||||
|
||||
remote_file build delete tmpdir/artest.a
|
||||
|
||||
set got [binutils_run $AR "rc $archive ${objfile}"]
|
||||
if ![string match "" $got] {
|
||||
fail $testname
|
||||
return
|
||||
}
|
||||
|
||||
remote_file build delete tmpdir/artest2.a
|
||||
|
||||
set got [binutils_run $AR "rcT $archive2 ${archive}"]
|
||||
if ![string match "" $got] {
|
||||
fail $testname
|
||||
return
|
||||
}
|
||||
|
||||
set got [binutils_run $NM "--print-armap $archive"]
|
||||
if { ![string match "*text_symbol in *bintest.o*" $got] \
|
||||
|| ![string match "*data_symbol in *bintest.o*" $got] \
|
||||
|| ![string match "*common_symbol in *bintest.o*" $got] \
|
||||
|| [string match "*static_text_symbol in *bintest.o*" $got] \
|
||||
|| [string match "*static_data_symbol in *bintest.o*" $got] \
|
||||
|| [string match "*external_symbol in *bintest.o*" $got] } {
|
||||
fail $testname
|
||||
return
|
||||
}
|
||||
|
||||
pass $testname
|
||||
}
|
||||
|
||||
# Test POSIX-compatible argument parsing.
|
||||
|
||||
proc argument_parsing { } {
|
||||
@ -254,4 +358,6 @@ proc argument_parsing { } {
|
||||
|
||||
long_filenames
|
||||
symbol_table
|
||||
thin_archive
|
||||
thin_archive_with_nested
|
||||
argument_parsing
|
||||
|
@ -1,3 +1,7 @@
|
||||
2008-03-27 Cary Coutant <ccoutant@google.com>
|
||||
|
||||
* ar.h (ARMAGT): New magic string for thin archives.
|
||||
|
||||
2005-05-10 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
* Update the address and phone number of the FSF organization in
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* archive file definition for GNU software
|
||||
|
||||
Copyright 2001 Free Software Foundation, Inc.
|
||||
Copyright 2001, 2008 Free Software Foundation, Inc.
|
||||
|
||||
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
|
||||
@ -26,8 +26,9 @@
|
||||
characters, as allowed by ANSI. '\012' has a fixed value, and remains
|
||||
compatible with existing BSDish archives. */
|
||||
|
||||
#define ARMAG "!<arch>\012" /* For COFF and a.out archives */
|
||||
#define ARMAGB "!<bout>\012" /* For b.out archives */
|
||||
#define ARMAG "!<arch>\012" /* For COFF and a.out archives. */
|
||||
#define ARMAGB "!<bout>\012" /* For b.out archives. */
|
||||
#define ARMAGT "!<thin>\012" /* For thin archives. */
|
||||
#define SARMAG 8
|
||||
#define ARFMAG "`\012"
|
||||
|
||||
@ -39,14 +40,15 @@
|
||||
|
||||
#define ARMAP_TIME_OFFSET 60
|
||||
|
||||
struct ar_hdr {
|
||||
char ar_name[16]; /* name of this member */
|
||||
char ar_date[12]; /* file mtime */
|
||||
char ar_uid[6]; /* owner uid; printed as decimal */
|
||||
char ar_gid[6]; /* owner gid; printed as decimal */
|
||||
char ar_mode[8]; /* file mode, printed as octal */
|
||||
char ar_size[10]; /* file size, printed as decimal */
|
||||
char ar_fmag[2]; /* should contain ARFMAG */
|
||||
struct ar_hdr
|
||||
{
|
||||
char ar_name[16]; /* Name of this member. */
|
||||
char ar_date[12]; /* File mtime. */
|
||||
char ar_uid[6]; /* Owner uid; printed as decimal. */
|
||||
char ar_gid[6]; /* Owner gid; printed as decimal. */
|
||||
char ar_mode[8]; /* File mode, printed as octal. */
|
||||
char ar_size[10]; /* File size, printed as decimal. */
|
||||
char ar_fmag[2]; /* Should contain ARFMAG. */
|
||||
};
|
||||
|
||||
#endif /* __GNU_AR_H__ */
|
||||
|
Loading…
Reference in New Issue
Block a user