aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog7
-rw-r--r--bfd/coff-rs6000.c115
2 files changed, 106 insertions, 16 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index b268793..c93a5a3 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,10 @@
+2000-07-25 Geoffrey Keating <geoffk@cygnus.com>
+
+ * coff-rs6000.c (xcoff_write_one_armap_big): New procedure.
+ (xcoff_write_armap_big): Write both 32-bit and 64-bit armaps.
+ (xcoff_write_archive_contents_big): Don't update the offset
+ of the symbol table, xcoff_write_armap will do it.
+
2000-07-23 Ulf Carlsson <ulfc@engr.sgi.com>
* elf32-mips.c (_bfd_mips_elf_check_relocs): Use abfd instead
diff --git a/bfd/coff-rs6000.c b/bfd/coff-rs6000.c
index 4689400..d3332d2d 100644
--- a/bfd/coff-rs6000.c
+++ b/bfd/coff-rs6000.c
@@ -1607,29 +1607,39 @@ xcoff_write_armap_old (abfd, elength, map, orl_count, stridx)
return true;
}
-/*ARGSUSED*/
+/* Write a single armap in the big format. */
static boolean
-xcoff_write_armap_big (abfd, elength, map, orl_count, stridx)
+xcoff_write_one_armap_big (abfd, map, orl_count, orl_ccount, stridx, bits64,
+ prevoff, nextoff)
bfd *abfd;
- unsigned int elength ATTRIBUTE_UNUSED;
struct orl *map;
unsigned int orl_count;
- int stridx;
+ unsigned int orl_ccount;
+ unsigned int stridx;
+ int bits64;
+ const char *prevoff;
+ char *nextoff;
{
struct xcoff_ar_hdr_big hdr;
char *p;
unsigned char buf[4];
bfd *sub;
file_ptr fileoff;
+ const bfd_arch_info_type *arch_info;
+ bfd *object_bfd;
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.size, "%ld", (long) (4 + orl_ccount * 4 + stridx));
+ if (bits64)
+ sprintf (hdr.nextoff, "%d", 0);
+ else
+ sprintf (hdr.nextoff, "%d", (strtol (prevoff, (char **) NULL, 10)
+ + 4 + orl_ccount * 4 + stridx));
+ memcpy (hdr.prevoff, prevoff, sizeof (hdr.prevoff));
sprintf (hdr.date, "%d", 0);
sprintf (hdr.uid, "%d", 0);
sprintf (hdr.gid, "%d", 0);
@@ -1641,11 +1651,13 @@ xcoff_write_armap_big (abfd, elength, map, orl_count, stridx)
if (*p == '\0')
*p = ' ';
+ memcpy (nextoff, hdr.nextoff, sizeof (hdr.nextoff));
+
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);
+ bfd_h_put_32 (abfd, orl_ccount, buf);
if (bfd_write (buf, 1, 4, abfd) != 4)
return false;
@@ -1656,13 +1668,18 @@ xcoff_write_armap_big (abfd, elength, map, orl_count, stridx)
{
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;
- }
+ if ((bfd_arch_bits_per_address ((bfd *) map[i].pos) == 64) == bits64)
+ while (((bfd *) (map[i]).pos) == sub)
+ {
+ bfd_h_put_32 (abfd, fileoff, buf);
+ if (bfd_write (buf, 1, 4, abfd) != 4)
+ return false;
+ i++;
+ }
+ else
+ while (((bfd *) (map[i]).pos) == sub)
+ i++;
+
namlen = strlen (normalize_filename (sub));
namlen = (namlen + 1) &~ 1;
fileoff += (SIZEOF_AR_HDR_BIG
@@ -1673,10 +1690,17 @@ xcoff_write_armap_big (abfd, elength, map, orl_count, stridx)
sub = sub->next;
}
+ object_bfd = NULL;
for (i = 0; i < orl_count; i++)
{
const char *name;
size_t namlen;
+ bfd *ob = (bfd *)map[i].pos;
+
+ if (ob != object_bfd)
+ arch_info = bfd_get_arch_info (ob);
+ if ((arch_info->bits_per_address == 64) != bits64)
+ continue;
name = *map[i].name;
namlen = strlen (name);
@@ -1697,6 +1721,66 @@ xcoff_write_armap_big (abfd, elength, map, orl_count, stridx)
}
/*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;
+{
+ unsigned int i;
+ unsigned int orl_count_32, orl_count_64;
+ unsigned int stridx_32, stridx_64;
+ const bfd_arch_info_type *arch_info;
+ bfd *object_bfd;
+
+ /* First, we look through the symbols and work out which are
+ from 32-bit objects and which from 64-bit ones. */
+ orl_count_32 = 0;
+ orl_count_64 = 0;
+ stridx_32 = 0;
+ stridx_64 = 0;
+ object_bfd = NULL;
+ for (i = 0; i < orl_count; i++)
+ {
+ bfd *ob = (bfd *)map[i].pos;
+ unsigned int len;
+ if (ob != object_bfd)
+ arch_info = bfd_get_arch_info (ob);
+ len = strlen (*map[i].name) + 1;
+ if (arch_info->bits_per_address == 64)
+ {
+ orl_count_64++;
+ stridx_64 += len;
+ }
+ else
+ {
+ orl_count_32++;
+ stridx_32 += len;
+ }
+ object_bfd = ob;
+ }
+ /* A quick sanity check... */
+ BFD_ASSERT (orl_count_64 + orl_count_32 == orl_count);
+ BFD_ASSERT (stridx_64 + stridx_32 == stridx);
+
+ /* Now write out each map. */
+ if (! xcoff_write_one_armap_big (abfd, map, orl_count, orl_count_32,
+ stridx_32, false,
+ xcoff_ardata_big (abfd)->memoff,
+ xcoff_ardata_big (abfd)->symoff))
+ return false;
+ if (! xcoff_write_one_armap_big (abfd, map, orl_count, orl_count_64,
+ stridx_64, true,
+ xcoff_ardata_big (abfd)->symoff,
+ xcoff_ardata_big (abfd)->symoff64))
+ return false;
+
+ return true;
+}
+
+/*ARGSUSED*/
boolean
_bfd_xcoff_write_armap (abfd, elength, map, orl_count, stridx)
bfd *abfd;
@@ -2207,7 +2291,6 @@ xcoff_write_archive_contents_big (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;