* coffcode.h (coff_set_arch_mach_hook): Don't use variable-size
arrays. (coff_compute_section_file_positions): Use bfd_free to pair bfd_malloc. (coff_write_object_contents): Likewise. * coff-rs6000.c (xcoff_howto_table_16): New variable. (xcoff_rtype2howto): Handle 16-bit variants of 32-bit relocs.
This commit is contained in:
parent
ff4e7bb239
commit
5ea1af0d5d
3 changed files with 804 additions and 81 deletions
|
@ -1,3 +1,14 @@
|
|||
2000-02-18 Geoff Keating <geoffk@cygnus.com>
|
||||
|
||||
* coffcode.h (coff_set_arch_mach_hook): Don't use variable-size
|
||||
arrays.
|
||||
(coff_compute_section_file_positions): Use bfd_free to pair
|
||||
bfd_malloc.
|
||||
(coff_write_object_contents): Likewise.
|
||||
|
||||
* coff-rs6000.c (xcoff_howto_table_16): New variable.
|
||||
(xcoff_rtype2howto): Handle 16-bit variants of 32-bit relocs.
|
||||
|
||||
2000-02-18 Richard Henderson <rth@cygnus.com>
|
||||
|
||||
* elf-bfd.h (struct elf_link_hash_table): Remove copy_indirect
|
||||
|
|
|
@ -496,6 +496,55 @@ static reloc_howto_type xcoff_howto_table[] =
|
|||
false) /* pcrel_offset */
|
||||
};
|
||||
|
||||
/* These are the first two like the above but for 16-bit relocs. */
|
||||
static reloc_howto_type xcoff_howto_table_16[] =
|
||||
{
|
||||
/* Standard 16 bit relocation. */
|
||||
HOWTO (0, /* type */
|
||||
0, /* rightshift */
|
||||
2, /* size (0 = byte, 1 = short, 2 = long) */
|
||||
16, /* bitsize */
|
||||
false, /* pc_relative */
|
||||
0, /* bitpos */
|
||||
complain_overflow_bitfield, /* complain_on_overflow */
|
||||
0, /* special_function */
|
||||
"R_POS_16", /* name */
|
||||
true, /* partial_inplace */
|
||||
0xffffffff, /* src_mask */
|
||||
0xffffffff, /* dst_mask */
|
||||
false), /* pcrel_offset */
|
||||
|
||||
/* 16 bit relocation, but store negative value. */
|
||||
HOWTO (1, /* type */
|
||||
0, /* rightshift */
|
||||
-2, /* size (0 = byte, 1 = short, 2 = long) */
|
||||
16, /* bitsize */
|
||||
false, /* pc_relative */
|
||||
0, /* bitpos */
|
||||
complain_overflow_bitfield, /* complain_on_overflow */
|
||||
0, /* special_function */
|
||||
"R_NEG_16", /* name */
|
||||
true, /* partial_inplace */
|
||||
0xffffffff, /* src_mask */
|
||||
0xffffffff, /* dst_mask */
|
||||
false), /* pcrel_offset */
|
||||
|
||||
/* 16 bit PC relative relocation. */
|
||||
HOWTO (2, /* type */
|
||||
0, /* rightshift */
|
||||
2, /* size (0 = byte, 1 = short, 2 = long) */
|
||||
32, /* bitsize */
|
||||
true, /* pc_relative */
|
||||
0, /* bitpos */
|
||||
complain_overflow_signed, /* complain_on_overflow */
|
||||
0, /* special_function */
|
||||
"R_REL_16", /* name */
|
||||
true, /* partial_inplace */
|
||||
0xffffffff, /* src_mask */
|
||||
0xffffffff, /* dst_mask */
|
||||
false), /* pcrel_offset */
|
||||
};
|
||||
|
||||
static void
|
||||
xcoff_rtype2howto (relent, internal)
|
||||
arelent *relent;
|
||||
|
@ -503,6 +552,11 @@ xcoff_rtype2howto (relent, internal)
|
|||
{
|
||||
relent->howto = xcoff_howto_table + internal->r_type;
|
||||
|
||||
if (relent->howto->bitsize != ((unsigned int) internal->r_size & 0x1f) + 1
|
||||
&& (internal->r_type
|
||||
< sizeof(xcoff_howto_table_16)/sizeof(xcoff_howto_table_16[0])))
|
||||
relent->howto = xcoff_howto_table_16 + internal->r_type;
|
||||
|
||||
/* The r_size field of an XCOFF reloc encodes the bitsize of the
|
||||
relocation, as well as indicating whether it is signed or not.
|
||||
Doublecheck that the relocation information gathered from the
|
||||
|
@ -591,11 +645,24 @@ xcoff_reloc_type_lookup (abfd, code)
|
|||
binary number which is the number of entries. This is followed by
|
||||
a that many four byte binary numbers; each is the file offset of an
|
||||
entry in the archive. These numbers are followed by a series of
|
||||
null terminated strings, which are symbol names. */
|
||||
null terminated strings, which are symbol names.
|
||||
|
||||
/* XCOFF archives use this as a magic string. */
|
||||
AIX 4.3 introduced a new archive format which can handle larger
|
||||
files and also 32- and 64-bit objects in the same archive. The
|
||||
things said above remain true except that there is now more than
|
||||
one global symbol table. The one is used to index 32-bit objects,
|
||||
the other for 64-bit objects.
|
||||
|
||||
The new archives (recognizable by the new ARMAG string) has larger
|
||||
field lengths so that we cannot really share any code. Also we have
|
||||
to take care that we are not generating the new form of archives
|
||||
on AIX 4.2 or earlier systems. */
|
||||
|
||||
/* XCOFF archives use this as a magic string. Note that both strings
|
||||
have the same length. */
|
||||
|
||||
#define XCOFFARMAG "<aiaff>\012"
|
||||
#define XCOFFARMAGBIG "<bigaf>\012"
|
||||
#define SXCOFFARMAG 8
|
||||
|
||||
/* This terminates an XCOFF archive member name. */
|
||||
|
@ -629,6 +696,38 @@ struct xcoff_ar_file_hdr
|
|||
|
||||
#define SIZEOF_AR_FILE_HDR (5 * 12 + SXCOFFARMAG)
|
||||
|
||||
/* This is the equivalent data structure for the big archive format. */
|
||||
|
||||
struct xcoff_ar_file_hdr_big
|
||||
{
|
||||
/* Magic string. */
|
||||
char magic[SXCOFFARMAG];
|
||||
|
||||
/* Offset of the member table (decimal ASCII string). */
|
||||
char memoff[20];
|
||||
|
||||
/* Offset of the global symbol table for 32-bit objects (decimal ASCII
|
||||
string). */
|
||||
char symoff[20];
|
||||
|
||||
/* Offset of the global symbol table for 64-bit objects (decimal ASCII
|
||||
string). */
|
||||
char symoff64[20];
|
||||
|
||||
/* Offset of the first member in the archive (decimal ASCII string). */
|
||||
char firstmemoff[20];
|
||||
|
||||
/* Offset of the last member in the archive (decimal ASCII string). */
|
||||
char lastmemoff[20];
|
||||
|
||||
/* Offset of the first member on the free list (decimal ASCII
|
||||
string). */
|
||||
char freeoff[20];
|
||||
};
|
||||
|
||||
#define SIZEOF_AR_FILE_HDR_BIG (6 * 20 + SXCOFFARMAG)
|
||||
|
||||
|
||||
/* Each XCOFF archive member starts with this (printable) structure. */
|
||||
|
||||
struct xcoff_ar_hdr
|
||||
|
@ -667,16 +766,65 @@ struct xcoff_ar_hdr
|
|||
|
||||
#define SIZEOF_AR_HDR (7 * 12 + 4)
|
||||
|
||||
/* The equivalent for the big archive format. */
|
||||
|
||||
struct xcoff_ar_hdr_big
|
||||
{
|
||||
/* File size not including the header (decimal ASCII string). */
|
||||
char size[20];
|
||||
|
||||
/* File offset of next archive member (decimal ASCII string). */
|
||||
char nextoff[20];
|
||||
|
||||
/* File offset of previous archive member (decimal ASCII string). */
|
||||
char prevoff[20];
|
||||
|
||||
/* File mtime (decimal ASCII string). */
|
||||
char date[12];
|
||||
|
||||
/* File UID (decimal ASCII string). */
|
||||
char uid[12];
|
||||
|
||||
/* File GID (decimal ASCII string). */
|
||||
char gid[12];
|
||||
|
||||
/* File mode (octal ASCII string). */
|
||||
char mode[12];
|
||||
|
||||
/* Length of file name (decimal ASCII string). */
|
||||
char namlen[4];
|
||||
|
||||
/* This structure is followed by the file name. The length of the
|
||||
name is given in the namlen field. If the length of the name is
|
||||
odd, the name is followed by a null byte. The name and optional
|
||||
null byte are followed by XCOFFARFMAG, which is not included in
|
||||
namlen. The contents of the archive member follow; the number of
|
||||
bytes is given in the size field. */
|
||||
};
|
||||
|
||||
#define SIZEOF_AR_HDR_BIG (3 * 20 + 4 * 12 + 4)
|
||||
|
||||
|
||||
/* We often have to distinguish between the old and big file format.
|
||||
Make it a bit cleaner. We can use `xcoff_ardata' here because the
|
||||
`hdr' member has the same size and position in both formats. */
|
||||
#define xcoff_big_format_p(abfd) \
|
||||
(xcoff_ardata (abfd)->magic[1] == 'b')
|
||||
|
||||
/* We store a copy of the xcoff_ar_file_hdr in the tdata field of the
|
||||
artdata structure. */
|
||||
artdata structure. Similar for the big archive. */
|
||||
#define xcoff_ardata(abfd) \
|
||||
((struct xcoff_ar_file_hdr *) bfd_ardata (abfd)->tdata)
|
||||
#define xcoff_ardata_big(abfd) \
|
||||
((struct xcoff_ar_file_hdr_big *) bfd_ardata (abfd)->tdata)
|
||||
|
||||
/* We store a copy of the xcoff_ar_hdr in the arelt_data field of an
|
||||
archive element. */
|
||||
archive element. Similar for the big archive. */
|
||||
#define arch_eltdata(bfd) ((struct areltdata *) ((bfd)->arelt_data))
|
||||
#define arch_xhdr(bfd) \
|
||||
((struct xcoff_ar_hdr *) arch_eltdata (bfd)->arch_header)
|
||||
#define arch_xhdr_big(bfd) \
|
||||
((struct xcoff_ar_hdr_big *) arch_eltdata (bfd)->arch_header)
|
||||
|
||||
/* XCOFF archives do not have anything which corresponds to an
|
||||
extended name table. */
|
||||
|
@ -702,7 +850,6 @@ xcoff_slurp_armap (abfd)
|
|||
bfd *abfd;
|
||||
{
|
||||
file_ptr off;
|
||||
struct xcoff_ar_hdr hdr;
|
||||
size_t namlen;
|
||||
bfd_size_type sz;
|
||||
bfd_byte *contents, *cend;
|
||||
|
@ -716,6 +863,11 @@ xcoff_slurp_armap (abfd)
|
|||
return true;
|
||||
}
|
||||
|
||||
if (! xcoff_big_format_p (abfd))
|
||||
{
|
||||
/* This is for the old format. */
|
||||
struct xcoff_ar_hdr hdr;
|
||||
|
||||
off = strtol (xcoff_ardata (abfd)->symoff, (char **) NULL, 10);
|
||||
if (off == 0)
|
||||
{
|
||||
|
@ -735,8 +887,40 @@ xcoff_slurp_armap (abfd)
|
|||
if (bfd_seek (abfd, ((namlen + 1) & ~1) + SXCOFFARFMAG, SEEK_CUR) != 0)
|
||||
return false;
|
||||
|
||||
/* Read in the entire symbol table. */
|
||||
sz = strtol (hdr.size, (char **) NULL, 10);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This is for the new format. */
|
||||
struct xcoff_ar_hdr_big hdr;
|
||||
|
||||
off = strtol (xcoff_ardata_big (abfd)->symoff, (char **) NULL, 10);
|
||||
if (off == 0)
|
||||
{
|
||||
bfd_has_map (abfd) = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (bfd_seek (abfd, off, SEEK_SET) != 0)
|
||||
return false;
|
||||
|
||||
/* The symbol table starts with a normal archive header. */
|
||||
if (bfd_read ((PTR) &hdr, SIZEOF_AR_HDR_BIG, 1, abfd)
|
||||
!= SIZEOF_AR_HDR_BIG)
|
||||
return false;
|
||||
|
||||
/* Skip the name (normally empty). */
|
||||
namlen = strtol (hdr.namlen, (char **) NULL, 10);
|
||||
if (bfd_seek (abfd, ((namlen + 1) & ~1) + SXCOFFARFMAG, SEEK_CUR) != 0)
|
||||
return false;
|
||||
|
||||
/* XXX This actually has to be a call to strtoll (at least on 32-bit
|
||||
machines) since the field width is 20 and there numbers with more
|
||||
than 32 bits can be represented. */
|
||||
sz = strtol (hdr.size, (char **) NULL, 10);
|
||||
}
|
||||
|
||||
/* Read in the entire symbol table. */
|
||||
contents = (bfd_byte *) bfd_alloc (abfd, sz);
|
||||
if (contents == NULL)
|
||||
return false;
|
||||
|
@ -789,17 +973,17 @@ static const bfd_target *
|
|||
xcoff_archive_p (abfd)
|
||||
bfd *abfd;
|
||||
{
|
||||
struct xcoff_ar_file_hdr hdr;
|
||||
char magic[SXCOFFARMAG];
|
||||
|
||||
if (bfd_read ((PTR) &hdr, SIZEOF_AR_FILE_HDR, 1, abfd)
|
||||
!= SIZEOF_AR_FILE_HDR)
|
||||
if (bfd_read ((PTR) magic, SXCOFFARMAG, 1, abfd) != SXCOFFARMAG)
|
||||
{
|
||||
if (bfd_get_error () != bfd_error_system_call)
|
||||
bfd_set_error (bfd_error_wrong_format);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (strncmp (hdr.magic, XCOFFARMAG, SXCOFFARMAG) != 0)
|
||||
if (strncmp (magic, XCOFFARMAG, SXCOFFARMAG) != 0
|
||||
&& strncmp (magic, XCOFFARMAGBIG, SXCOFFARMAG) != 0)
|
||||
{
|
||||
bfd_set_error (bfd_error_wrong_format);
|
||||
return NULL;
|
||||
|
@ -814,18 +998,67 @@ xcoff_archive_p (abfd)
|
|||
if (bfd_ardata (abfd) == (struct artdata *) NULL)
|
||||
return NULL;
|
||||
|
||||
bfd_ardata (abfd)->first_file_filepos = strtol (hdr.firstmemoff,
|
||||
(char **) NULL, 10);
|
||||
bfd_ardata (abfd)->cache = NULL;
|
||||
bfd_ardata (abfd)->archive_head = NULL;
|
||||
bfd_ardata (abfd)->symdefs = NULL;
|
||||
bfd_ardata (abfd)->extended_names = NULL;
|
||||
|
||||
/* Now handle the two formats. */
|
||||
if (magic[1] != 'b')
|
||||
{
|
||||
/* This is the old format. */
|
||||
struct xcoff_ar_file_hdr hdr;
|
||||
|
||||
/* Copy over the magic string. */
|
||||
memcpy (hdr.magic, magic, SXCOFFARMAG);
|
||||
|
||||
/* Now read the rest of the file header. */
|
||||
if (bfd_read ((PTR) &hdr.memoff, SIZEOF_AR_FILE_HDR - SXCOFFARMAG, 1,
|
||||
abfd) != SIZEOF_AR_FILE_HDR - SXCOFFARMAG)
|
||||
{
|
||||
if (bfd_get_error () != bfd_error_system_call)
|
||||
bfd_set_error (bfd_error_wrong_format);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bfd_ardata (abfd)->first_file_filepos = strtol (hdr.firstmemoff,
|
||||
(char **) NULL, 10);
|
||||
|
||||
bfd_ardata (abfd)->tdata = bfd_zalloc (abfd, SIZEOF_AR_FILE_HDR);
|
||||
if (bfd_ardata (abfd)->tdata == NULL)
|
||||
return NULL;
|
||||
|
||||
memcpy (bfd_ardata (abfd)->tdata, &hdr, SIZEOF_AR_FILE_HDR);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This is the new format. */
|
||||
struct xcoff_ar_file_hdr_big hdr;
|
||||
|
||||
/* Copy over the magic string. */
|
||||
memcpy (hdr.magic, magic, SXCOFFARMAG);
|
||||
|
||||
/* Now read the rest of the file header. */
|
||||
if (bfd_read ((PTR) &hdr.memoff, SIZEOF_AR_FILE_HDR_BIG - SXCOFFARMAG, 1,
|
||||
abfd) != SIZEOF_AR_FILE_HDR_BIG - SXCOFFARMAG)
|
||||
{
|
||||
if (bfd_get_error () != bfd_error_system_call)
|
||||
bfd_set_error (bfd_error_wrong_format);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* XXX This actually has to be a call to strtoll (at least on 32-bit
|
||||
machines) since the field width is 20 and there numbers with more
|
||||
than 32 bits can be represented. */
|
||||
bfd_ardata (abfd)->first_file_filepos = strtol (hdr.firstmemoff,
|
||||
(char **) NULL, 10);
|
||||
|
||||
bfd_ardata (abfd)->tdata = bfd_zalloc (abfd, SIZEOF_AR_FILE_HDR_BIG);
|
||||
if (bfd_ardata (abfd)->tdata == NULL)
|
||||
return NULL;
|
||||
|
||||
memcpy (bfd_ardata (abfd)->tdata, &hdr, SIZEOF_AR_FILE_HDR_BIG);
|
||||
}
|
||||
|
||||
if (! xcoff_slurp_armap (abfd))
|
||||
{
|
||||
|
@ -843,29 +1076,80 @@ static PTR
|
|||
xcoff_read_ar_hdr (abfd)
|
||||
bfd *abfd;
|
||||
{
|
||||
struct xcoff_ar_hdr hdr;
|
||||
size_t namlen;
|
||||
struct xcoff_ar_hdr *hdrp;
|
||||
struct areltdata *ret;
|
||||
|
||||
if (bfd_read ((PTR) &hdr, SIZEOF_AR_HDR, 1, abfd) != SIZEOF_AR_HDR)
|
||||
return NULL;
|
||||
|
||||
namlen = strtol (hdr.namlen, (char **) NULL, 10);
|
||||
hdrp = (struct xcoff_ar_hdr *) bfd_alloc (abfd, SIZEOF_AR_HDR + namlen + 1);
|
||||
if (hdrp == NULL)
|
||||
return NULL;
|
||||
memcpy (hdrp, &hdr, SIZEOF_AR_HDR);
|
||||
if (bfd_read ((char *) hdrp + SIZEOF_AR_HDR, 1, namlen, abfd) != namlen)
|
||||
return NULL;
|
||||
((char *) hdrp)[SIZEOF_AR_HDR + namlen] = '\0';
|
||||
|
||||
ret = (struct areltdata *) bfd_alloc (abfd, sizeof (struct areltdata));
|
||||
if (ret == NULL)
|
||||
return NULL;
|
||||
|
||||
if (! xcoff_big_format_p (abfd))
|
||||
{
|
||||
struct xcoff_ar_hdr hdr;
|
||||
struct xcoff_ar_hdr *hdrp;
|
||||
|
||||
if (bfd_read ((PTR) &hdr, SIZEOF_AR_HDR, 1, abfd) != SIZEOF_AR_HDR)
|
||||
{
|
||||
free (ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
namlen = strtol (hdr.namlen, (char **) NULL, 10);
|
||||
hdrp = (struct xcoff_ar_hdr *) bfd_alloc (abfd,
|
||||
SIZEOF_AR_HDR + namlen + 1);
|
||||
if (hdrp == NULL)
|
||||
{
|
||||
free (ret);
|
||||
return NULL;
|
||||
}
|
||||
memcpy (hdrp, &hdr, SIZEOF_AR_HDR);
|
||||
if (bfd_read ((char *) hdrp + SIZEOF_AR_HDR, 1, namlen, abfd) != namlen)
|
||||
{
|
||||
free (ret);
|
||||
return NULL;
|
||||
}
|
||||
((char *) hdrp)[SIZEOF_AR_HDR + namlen] = '\0';
|
||||
|
||||
ret->arch_header = (char *) hdrp;
|
||||
ret->parsed_size = strtol (hdr.size, (char **) NULL, 10);
|
||||
ret->filename = (char *) hdrp + SIZEOF_AR_HDR;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct xcoff_ar_hdr_big hdr;
|
||||
struct xcoff_ar_hdr_big *hdrp;
|
||||
|
||||
if (bfd_read ((PTR) &hdr, SIZEOF_AR_HDR_BIG, 1, abfd)
|
||||
!= SIZEOF_AR_HDR_BIG)
|
||||
{
|
||||
free (ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
namlen = strtol (hdr.namlen, (char **) NULL, 10);
|
||||
hdrp = (struct xcoff_ar_hdr_big *) bfd_alloc (abfd,
|
||||
SIZEOF_AR_HDR_BIG
|
||||
+ namlen + 1);
|
||||
if (hdrp == NULL)
|
||||
{
|
||||
free (ret);
|
||||
return NULL;
|
||||
}
|
||||
memcpy (hdrp, &hdr, SIZEOF_AR_HDR_BIG);
|
||||
if (bfd_read ((char *) hdrp + SIZEOF_AR_HDR_BIG, 1, namlen, abfd) != namlen)
|
||||
{
|
||||
free (ret);
|
||||
return NULL;
|
||||
}
|
||||
((char *) hdrp)[SIZEOF_AR_HDR_BIG + namlen] = '\0';
|
||||
|
||||
ret->arch_header = (char *) hdrp;
|
||||
/* XXX This actually has to be a call to strtoll (at least on 32-bit
|
||||
machines) since the field width is 20 and there numbers with more
|
||||
than 32 bits can be represented. */
|
||||
ret->parsed_size = strtol (hdr.size, (char **) NULL, 10);
|
||||
ret->filename = (char *) hdrp + SIZEOF_AR_HDR_BIG;
|
||||
}
|
||||
|
||||
/* Skip over the XCOFFARFMAG at the end of the file name. */
|
||||
if (bfd_seek (abfd, (namlen & 1) + SXCOFFARFMAG, SEEK_CUR) != 0)
|
||||
|
@ -889,10 +1173,13 @@ xcoff_openr_next_archived_file (archive, last_file)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (! xcoff_big_format_p (archive))
|
||||
{
|
||||
if (last_file == NULL)
|
||||
filestart = bfd_ardata (archive)->first_file_filepos;
|
||||
else
|
||||
filestart = strtol (arch_xhdr (last_file)->nextoff, (char **) NULL, 10);
|
||||
filestart = strtol (arch_xhdr (last_file)->nextoff, (char **) NULL,
|
||||
10);
|
||||
|
||||
if (filestart == 0
|
||||
|| filestart == strtol (xcoff_ardata (archive)->memoff,
|
||||
|
@ -903,6 +1190,31 @@ xcoff_openr_next_archived_file (archive, last_file)
|
|||
bfd_set_error (bfd_error_no_more_archived_files);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (last_file == NULL)
|
||||
filestart = bfd_ardata (archive)->first_file_filepos;
|
||||
else
|
||||
/* XXX These actually have to be a calls to strtoll (at least
|
||||
on 32-bit machines) since the fields's width is 20 and
|
||||
there numbers with more than 32 bits can be represented. */
|
||||
filestart = strtol (arch_xhdr_big (last_file)->nextoff, (char **) NULL,
|
||||
10);
|
||||
|
||||
/* XXX These actually have to be calls to strtoll (at least on 32-bit
|
||||
machines) since the fields's width is 20 and there numbers with more
|
||||
than 32 bits can be represented. */
|
||||
if (filestart == 0
|
||||
|| filestart == strtol (xcoff_ardata_big (archive)->memoff,
|
||||
(char **) NULL, 10)
|
||||
|| filestart == strtol (xcoff_ardata_big (archive)->symoff,
|
||||
(char **) NULL, 10))
|
||||
{
|
||||
bfd_set_error (bfd_error_no_more_archived_files);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return _bfd_get_elt_at_filepos (archive, filestart);
|
||||
}
|
||||
|
@ -914,21 +1226,32 @@ xcoff_generic_stat_arch_elt (abfd, s)
|
|||
bfd *abfd;
|
||||
struct stat *s;
|
||||
{
|
||||
struct xcoff_ar_hdr *hdrp;
|
||||
|
||||
if (abfd->arelt_data == NULL)
|
||||
{
|
||||
bfd_set_error (bfd_error_invalid_operation);
|
||||
return -1;
|
||||
}
|
||||
|
||||
hdrp = arch_xhdr (abfd);
|
||||
if (! xcoff_big_format_p (abfd))
|
||||
{
|
||||
struct xcoff_ar_hdr *hdrp = arch_xhdr (abfd);
|
||||
|
||||
s->st_mtime = strtol (hdrp->date, (char **) NULL, 10);
|
||||
s->st_uid = strtol (hdrp->uid, (char **) NULL, 10);
|
||||
s->st_gid = strtol (hdrp->gid, (char **) NULL, 10);
|
||||
s->st_mode = strtol (hdrp->mode, (char **) NULL, 8);
|
||||
s->st_size = arch_eltdata (abfd)->parsed_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct xcoff_ar_hdr_big *hdrp = arch_xhdr_big (abfd);
|
||||
|
||||
s->st_mtime = strtol (hdrp->date, (char **) NULL, 10);
|
||||
s->st_uid = strtol (hdrp->uid, (char **) NULL, 10);
|
||||
s->st_gid = strtol (hdrp->gid, (char **) NULL, 10);
|
||||
s->st_mode = strtol (hdrp->mode, (char **) NULL, 8);
|
||||
s->st_size = arch_eltdata (abfd)->parsed_size;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -955,7 +1278,7 @@ normalize_filename (abfd)
|
|||
|
||||
/*ARGSUSED*/
|
||||
static boolean
|
||||
xcoff_write_armap (abfd, elength, map, orl_count, stridx)
|
||||
xcoff_write_armap_old (abfd, elength, map, orl_count, stridx)
|
||||
bfd *abfd;
|
||||
unsigned int elength ATTRIBUTE_UNUSED;
|
||||
struct orl *map;
|
||||
|
@ -1039,11 +1362,115 @@ xcoff_write_armap (abfd, elength, map, orl_count, stridx)
|
|||
return true;
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static boolean
|
||||
xcoff_write_armap_big (abfd, elength, map, orl_count, stridx)
|
||||
bfd *abfd;
|
||||
unsigned int elength ATTRIBUTE_UNUSED;
|
||||
struct orl *map;
|
||||
unsigned int orl_count;
|
||||
int stridx;
|
||||
{
|
||||
struct xcoff_ar_hdr_big hdr;
|
||||
char *p;
|
||||
unsigned char buf[4];
|
||||
bfd *sub;
|
||||
file_ptr fileoff;
|
||||
unsigned int i;
|
||||
|
||||
memset (&hdr, 0, sizeof hdr);
|
||||
/* XXX This call actually should use %lld (at least on 32-bit
|
||||
machines) since the fields's width is 20 and there numbers with
|
||||
more than 32 bits can be represented. */
|
||||
sprintf (hdr.size, "%ld", (long) (4 + orl_count * 4 + stridx));
|
||||
sprintf (hdr.nextoff, "%d", 0);
|
||||
memcpy (hdr.prevoff, xcoff_ardata (abfd)->memoff, 12);
|
||||
sprintf (hdr.date, "%d", 0);
|
||||
sprintf (hdr.uid, "%d", 0);
|
||||
sprintf (hdr.gid, "%d", 0);
|
||||
sprintf (hdr.mode, "%d", 0);
|
||||
sprintf (hdr.namlen, "%d", 0);
|
||||
|
||||
/* We need spaces, not null bytes, in the header. */
|
||||
for (p = (char *) &hdr; p < (char *) &hdr + SIZEOF_AR_HDR_BIG; p++)
|
||||
if (*p == '\0')
|
||||
*p = ' ';
|
||||
|
||||
if (bfd_write ((PTR) &hdr, SIZEOF_AR_HDR_BIG, 1, abfd) != SIZEOF_AR_HDR_BIG
|
||||
|| bfd_write (XCOFFARFMAG, 1, SXCOFFARFMAG, abfd) != SXCOFFARFMAG)
|
||||
return false;
|
||||
|
||||
bfd_h_put_32 (abfd, orl_count, buf);
|
||||
if (bfd_write (buf, 1, 4, abfd) != 4)
|
||||
return false;
|
||||
|
||||
sub = abfd->archive_head;
|
||||
fileoff = SIZEOF_AR_FILE_HDR_BIG;
|
||||
i = 0;
|
||||
while (sub != NULL && i < orl_count)
|
||||
{
|
||||
size_t namlen;
|
||||
|
||||
while (((bfd *) (map[i]).pos) == sub)
|
||||
{
|
||||
bfd_h_put_32 (abfd, fileoff, buf);
|
||||
if (bfd_write (buf, 1, 4, abfd) != 4)
|
||||
return false;
|
||||
++i;
|
||||
}
|
||||
namlen = strlen (normalize_filename (sub));
|
||||
namlen = (namlen + 1) &~ 1;
|
||||
fileoff += (SIZEOF_AR_HDR_BIG
|
||||
+ namlen
|
||||
+ SXCOFFARFMAG
|
||||
+ arelt_size (sub));
|
||||
fileoff = (fileoff + 1) &~ 1;
|
||||
sub = sub->next;
|
||||
}
|
||||
|
||||
for (i = 0; i < orl_count; i++)
|
||||
{
|
||||
const char *name;
|
||||
size_t namlen;
|
||||
|
||||
name = *map[i].name;
|
||||
namlen = strlen (name);
|
||||
if (bfd_write (name, 1, namlen + 1, abfd) != namlen + 1)
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((stridx & 1) != 0)
|
||||
{
|
||||
char b;
|
||||
|
||||
b = '\0';
|
||||
if (bfd_write (&b, 1, 1, abfd) != 1)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static boolean
|
||||
xcoff_write_armap (abfd, elength, map, orl_count, stridx)
|
||||
bfd *abfd;
|
||||
unsigned int elength ATTRIBUTE_UNUSED;
|
||||
struct orl *map;
|
||||
unsigned int orl_count;
|
||||
int stridx;
|
||||
{
|
||||
if (! xcoff_big_format_p (abfd))
|
||||
return xcoff_write_armap_old (abfd, elength, map, orl_count, stridx);
|
||||
else
|
||||
return xcoff_write_armap_big (abfd, elength, map, orl_count, stridx);
|
||||
}
|
||||
|
||||
/* Write out an XCOFF archive. We always write an entire archive,
|
||||
rather than fussing with the freelist and so forth. */
|
||||
|
||||
static boolean
|
||||
xcoff_write_archive_contents (abfd)
|
||||
xcoff_write_archive_contents_old (abfd)
|
||||
bfd *abfd;
|
||||
{
|
||||
struct xcoff_ar_file_hdr fhdr;
|
||||
|
@ -1286,6 +1713,285 @@ xcoff_write_archive_contents (abfd)
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean
|
||||
xcoff_write_archive_contents_big (abfd)
|
||||
bfd *abfd;
|
||||
{
|
||||
struct xcoff_ar_file_hdr_big fhdr;
|
||||
size_t count;
|
||||
size_t total_namlen;
|
||||
file_ptr *offsets;
|
||||
boolean makemap;
|
||||
boolean hasobjects;
|
||||
file_ptr prevoff, nextoff;
|
||||
bfd *sub;
|
||||
unsigned int i;
|
||||
struct xcoff_ar_hdr_big ahdr;
|
||||
bfd_size_type size;
|
||||
char *p;
|
||||
char decbuf[13];
|
||||
|
||||
memset (&fhdr, 0, sizeof fhdr);
|
||||
strncpy (fhdr.magic, XCOFFARMAGBIG, SXCOFFARMAG);
|
||||
sprintf (fhdr.firstmemoff, "%d", SIZEOF_AR_FILE_HDR_BIG);
|
||||
sprintf (fhdr.freeoff, "%d", 0);
|
||||
|
||||
count = 0;
|
||||
total_namlen = 0;
|
||||
for (sub = abfd->archive_head; sub != NULL; sub = sub->next)
|
||||
{
|
||||
++count;
|
||||
total_namlen += strlen (normalize_filename (sub)) + 1;
|
||||
}
|
||||
offsets = (file_ptr *) bfd_alloc (abfd, count * sizeof (file_ptr));
|
||||
if (offsets == NULL)
|
||||
return false;
|
||||
|
||||
if (bfd_seek (abfd, SIZEOF_AR_FILE_HDR_BIG, SEEK_SET) != 0)
|
||||
return false;
|
||||
|
||||
makemap = bfd_has_map (abfd);
|
||||
hasobjects = false;
|
||||
prevoff = 0;
|
||||
nextoff = SIZEOF_AR_FILE_HDR_BIG;
|
||||
for (sub = abfd->archive_head, i = 0; sub != NULL; sub = sub->next, i++)
|
||||
{
|
||||
const char *name;
|
||||
size_t namlen;
|
||||
struct xcoff_ar_hdr_big *ahdrp;
|
||||
bfd_size_type remaining;
|
||||
|
||||
if (makemap && ! hasobjects)
|
||||
{
|
||||
if (bfd_check_format (sub, bfd_object))
|
||||
hasobjects = true;
|
||||
}
|
||||
|
||||
name = normalize_filename (sub);
|
||||
namlen = strlen (name);
|
||||
|
||||
if (sub->arelt_data != NULL)
|
||||
ahdrp = arch_xhdr_big (sub);
|
||||
else
|
||||
ahdrp = NULL;
|
||||
|
||||
if (ahdrp == NULL)
|
||||
{
|
||||
struct stat s;
|
||||
|
||||
memset (&ahdr, 0, sizeof ahdr);
|
||||
ahdrp = &ahdr;
|
||||
/* XXX This should actually be a call to stat64 (at least on
|
||||
32-bit machines). */
|
||||
if (stat (bfd_get_filename (sub), &s) != 0)
|
||||
{
|
||||
bfd_set_error (bfd_error_system_call);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* XXX This call actually should use %lld (at least on 32-bit
|
||||
machines) since the fields's width is 20 and there numbers with
|
||||
more than 32 bits can be represented. */
|
||||
sprintf (ahdrp->size, "%ld", (long) s.st_size);
|
||||
sprintf (ahdrp->date, "%ld", (long) s.st_mtime);
|
||||
sprintf (ahdrp->uid, "%ld", (long) s.st_uid);
|
||||
sprintf (ahdrp->gid, "%ld", (long) s.st_gid);
|
||||
sprintf (ahdrp->mode, "%o", (unsigned int) s.st_mode);
|
||||
|
||||
if (sub->arelt_data == NULL)
|
||||
{
|
||||
sub->arelt_data = bfd_alloc (sub, sizeof (struct areltdata));
|
||||
if (sub->arelt_data == NULL)
|
||||
return false;
|
||||
}
|
||||
|
||||
arch_eltdata (sub)->parsed_size = s.st_size;
|
||||
}
|
||||
|
||||
/* XXX These calls actually should use %lld (at least on 32-bit
|
||||
machines) since the fields's width is 20 and there numbers with
|
||||
more than 32 bits can be represented. */
|
||||
sprintf (ahdrp->prevoff, "%ld", (long) prevoff);
|
||||
sprintf (ahdrp->namlen, "%ld", (long) namlen);
|
||||
|
||||
/* If the length of the name is odd, we write out the null byte
|
||||
after the name as well. */
|
||||
namlen = (namlen + 1) &~ 1;
|
||||
|
||||
remaining = arelt_size (sub);
|
||||
size = (SIZEOF_AR_HDR_BIG
|
||||
+ namlen
|
||||
+ SXCOFFARFMAG
|
||||
+ remaining);
|
||||
|
||||
BFD_ASSERT (nextoff == bfd_tell (abfd));
|
||||
|
||||
offsets[i] = nextoff;
|
||||
|
||||
prevoff = nextoff;
|
||||
nextoff += size + (size & 1);
|
||||
|
||||
sprintf (ahdrp->nextoff, "%ld", (long) nextoff);
|
||||
|
||||
/* We need spaces, not null bytes, in the header. */
|
||||
for (p = (char *) ahdrp; p < (char *) ahdrp + SIZEOF_AR_HDR_BIG; p++)
|
||||
if (*p == '\0')
|
||||
*p = ' ';
|
||||
|
||||
if (bfd_write ((PTR) ahdrp, 1, SIZEOF_AR_HDR_BIG, abfd)
|
||||
!= SIZEOF_AR_HDR_BIG
|
||||
|| bfd_write ((PTR) name, 1, namlen, abfd) != namlen
|
||||
|| (bfd_write ((PTR) XCOFFARFMAG, 1, SXCOFFARFMAG, abfd)
|
||||
!= SXCOFFARFMAG))
|
||||
return false;
|
||||
|
||||
if (bfd_seek (sub, (file_ptr) 0, SEEK_SET) != 0)
|
||||
return false;
|
||||
while (remaining != 0)
|
||||
{
|
||||
bfd_size_type amt;
|
||||
bfd_byte buffer[DEFAULT_BUFFERSIZE];
|
||||
|
||||
amt = sizeof buffer;
|
||||
if (amt > remaining)
|
||||
amt = remaining;
|
||||
if (bfd_read (buffer, 1, amt, sub) != amt
|
||||
|| bfd_write (buffer, 1, amt, abfd) != amt)
|
||||
return false;
|
||||
remaining -= amt;
|
||||
}
|
||||
|
||||
if ((size & 1) != 0)
|
||||
{
|
||||
bfd_byte b;
|
||||
|
||||
b = '\0';
|
||||
if (bfd_write (&b, 1, 1, abfd) != 1)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX This call actually should use %lld (at least on 32-bit
|
||||
machines) since the fields's width is 20 and there numbers with
|
||||
more than 32 bits can be represented. */
|
||||
sprintf (fhdr.lastmemoff, "%ld", (long) prevoff);
|
||||
|
||||
/* Write out the member table. */
|
||||
|
||||
BFD_ASSERT (nextoff == bfd_tell (abfd));
|
||||
/* XXX This call actually should use %lld (at least on 32-bit
|
||||
machines) since the fields's width is 20 and there numbers with
|
||||
more than 32 bits can be represented. */
|
||||
sprintf (fhdr.memoff, "%ld", (long) nextoff);
|
||||
|
||||
memset (&ahdr, 0, sizeof ahdr);
|
||||
/* XXX The next two calls actually should use %lld (at least on 32-bit
|
||||
machines) since the fields's width is 20 and there numbers with
|
||||
more than 32 bits can be represented. */
|
||||
sprintf (ahdr.size, "%ld", (long) (12 + count * 12 + total_namlen));
|
||||
sprintf (ahdr.prevoff, "%ld", (long) prevoff);
|
||||
sprintf (ahdr.date, "%d", 0);
|
||||
sprintf (ahdr.uid, "%d", 0);
|
||||
sprintf (ahdr.gid, "%d", 0);
|
||||
sprintf (ahdr.mode, "%d", 0);
|
||||
sprintf (ahdr.namlen, "%d", 0);
|
||||
|
||||
size = (SIZEOF_AR_HDR_BIG
|
||||
+ 12
|
||||
+ count * 12
|
||||
+ total_namlen
|
||||
+ SXCOFFARFMAG);
|
||||
|
||||
prevoff = nextoff;
|
||||
nextoff += size + (size & 1);
|
||||
|
||||
if (makemap && hasobjects)
|
||||
/* XXX This call actually should use %lld (at least on 32-bit
|
||||
machines) since the fields's width is 20 and there numbers with
|
||||
more than 32 bits can be represented. */
|
||||
sprintf (ahdr.nextoff, "%ld", (long) nextoff);
|
||||
else
|
||||
sprintf (ahdr.nextoff, "%d", 0);
|
||||
|
||||
/* We need spaces, not null bytes, in the header. */
|
||||
for (p = (char *) &ahdr; p < (char *) &ahdr + SIZEOF_AR_HDR_BIG; p++)
|
||||
if (*p == '\0')
|
||||
*p = ' ';
|
||||
|
||||
if (bfd_write ((PTR) &ahdr, 1, SIZEOF_AR_HDR_BIG, abfd) != SIZEOF_AR_HDR_BIG
|
||||
|| (bfd_write ((PTR) XCOFFARFMAG, 1, SXCOFFARFMAG, abfd)
|
||||
!= SXCOFFARFMAG))
|
||||
return false;
|
||||
|
||||
sprintf (decbuf, "%-12ld", (long) count);
|
||||
if (bfd_write ((PTR) decbuf, 1, 12, abfd) != 12)
|
||||
return false;
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
sprintf (decbuf, "%-12ld", (long) offsets[i]);
|
||||
if (bfd_write ((PTR) decbuf, 1, 12, abfd) != 12)
|
||||
return false;
|
||||
}
|
||||
for (sub = abfd->archive_head; sub != NULL; sub = sub->next)
|
||||
{
|
||||
const char *name;
|
||||
size_t namlen;
|
||||
|
||||
name = normalize_filename (sub);
|
||||
namlen = strlen (name);
|
||||
if (bfd_write ((PTR) name, 1, namlen + 1, abfd) != namlen + 1)
|
||||
return false;
|
||||
}
|
||||
if ((size & 1) != 0)
|
||||
{
|
||||
bfd_byte b;
|
||||
|
||||
b = '\0';
|
||||
if (bfd_write ((PTR) &b, 1, 1, abfd) != 1)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Write out the armap, if appropriate. */
|
||||
|
||||
if (! makemap || ! hasobjects)
|
||||
sprintf (fhdr.symoff, "%d", 0);
|
||||
else
|
||||
{
|
||||
BFD_ASSERT (nextoff == bfd_tell (abfd));
|
||||
/* XXX This call actually should use %lld (at least on 32-bit
|
||||
machines) since the fields's width is 20 and there numbers with
|
||||
more than 32 bits can be represented. */
|
||||
sprintf (fhdr.symoff, "%ld", (long) nextoff);
|
||||
bfd_ardata (abfd)->tdata = (PTR) &fhdr;
|
||||
if (! _bfd_compute_and_write_armap (abfd, 0))
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Write out the archive file header. */
|
||||
|
||||
/* We need spaces, not null bytes, in the header. */
|
||||
for (p = (char *) &fhdr; p < (char *) &fhdr + SIZEOF_AR_FILE_HDR_BIG; p++)
|
||||
if (*p == '\0')
|
||||
*p = ' ';
|
||||
|
||||
if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
|
||||
|| (bfd_write ((PTR) &fhdr, SIZEOF_AR_FILE_HDR_BIG, 1, abfd) !=
|
||||
SIZEOF_AR_FILE_HDR_BIG))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean
|
||||
xcoff_write_archive_contents (abfd)
|
||||
bfd *abfd;
|
||||
{
|
||||
if (! xcoff_big_format_p (abfd))
|
||||
return xcoff_write_archive_contents_old (abfd);
|
||||
else
|
||||
return xcoff_write_archive_contents_big (abfd);
|
||||
}
|
||||
|
||||
/* We can't use the usual coff_sizeof_headers routine, because AIX
|
||||
always uses an a.out header. */
|
||||
|
|
|
@ -1880,17 +1880,23 @@ coff_set_arch_mach_hook (abfd, filehdr)
|
|||
cputype = 0;
|
||||
else
|
||||
{
|
||||
bfd_byte buf[bfd_coff_symesz (abfd)];
|
||||
bfd_byte *buf;
|
||||
struct internal_syment sym;
|
||||
|
||||
buf = (bfd_byte *) bfd_malloc (bfd_coff_symesz (abfd));
|
||||
if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0
|
||||
|| bfd_read (buf, 1, bfd_coff_symesz (abfd), abfd) != bfd_coff_symesz (abfd))
|
||||
|| (bfd_read (buf, 1, bfd_coff_symesz (abfd), abfd)
|
||||
!= bfd_coff_symesz (abfd)))
|
||||
{
|
||||
bfd_free (buf);
|
||||
return false;
|
||||
}
|
||||
coff_swap_sym_in (abfd, (PTR) buf, (PTR) &sym);
|
||||
if (sym.n_sclass == C_FILE)
|
||||
cputype = sym.n_type & 0xff;
|
||||
else
|
||||
cputype = 0;
|
||||
bfd_free (buf);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2762,7 +2768,7 @@ coff_compute_section_file_positions (abfd)
|
|||
current->target_index = target_index++;
|
||||
}
|
||||
|
||||
free (section_list);
|
||||
bfd_free (section_list);
|
||||
}
|
||||
#else /* ! COFF_IMAGE_WITH_PE */
|
||||
{
|
||||
|
@ -3696,7 +3702,7 @@ coff_write_object_contents (abfd)
|
|||
coff_swap_filehdr_out (abfd, (PTR) & internal_f, (PTR) buff);
|
||||
amount = bfd_write ((PTR) buff, 1, bfd_coff_filhsz (abfd), abfd);
|
||||
|
||||
free (buff);
|
||||
bfd_free (buff);
|
||||
|
||||
if (amount != bfd_coff_filhsz (abfd))
|
||||
return false;
|
||||
|
@ -3716,7 +3722,7 @@ coff_write_object_contents (abfd)
|
|||
coff_swap_aouthdr_out (abfd, (PTR) & internal_a, (PTR) buff);
|
||||
amount = bfd_write ((PTR) buff, 1, bfd_coff_aoutsz (abfd), abfd);
|
||||
|
||||
free (buff);
|
||||
bfd_free (buff);
|
||||
|
||||
if (amount != bfd_coff_aoutsz (abfd))
|
||||
return false;
|
||||
|
|
Loading…
Add table
Reference in a new issue