diff options
Diffstat (limited to 'bfd/archive.c')
-rw-r--r-- | bfd/archive.c | 92 |
1 files changed, 81 insertions, 11 deletions
diff --git a/bfd/archive.c b/bfd/archive.c index 53e295eb26c..6fc5f1d80f9 100644 --- a/bfd/archive.c +++ b/bfd/archive.c @@ -1144,10 +1144,9 @@ bfd_slurp_armap (bfd *abfd) return do_slurp_coff_armap (abfd); else if (CONST_STRNEQ (nextname, "/SYM64/ ")) { - /* 64bit ELF (Irix 6) archive. */ + /* 64bit (Irix 6) archive. */ #ifdef BFD64 - extern bfd_boolean bfd_elf64_archive_slurp_armap (bfd *); - return bfd_elf64_archive_slurp_armap (abfd); + return _bfd_archive_64_bit_slurp_armap (abfd); #else bfd_set_error (bfd_error_wrong_format); return FALSE; @@ -2466,15 +2465,49 @@ bsd_write_armap (bfd *arch, unsigned int stringsize = stridx + padit; /* Include 8 bytes to store ranlibsize and stringsize in output. */ unsigned int mapsize = ranlibsize + stringsize + 8; - file_ptr firstreal; - bfd *current = arch->archive_head; - bfd *last_elt = current; /* Last element arch seen. */ + file_ptr firstreal, first; + bfd *current; + bfd *last_elt; bfd_byte temp[4]; unsigned int count; struct ar_hdr hdr; long uid, gid; - firstreal = mapsize + elength + sizeof (struct ar_hdr) + SARMAG; + first = mapsize + elength + sizeof (struct ar_hdr) + SARMAG; + +#ifdef BFD64 + firstreal = first; + current = arch->archive_head; + last_elt = current; /* Last element arch seen. */ + for (count = 0; count < orl_count; count++) + { + unsigned int offset; + + if (map[count].u.abfd != last_elt) + { + do + { + struct areltdata *ared = arch_eltdata (current); + + firstreal += (ared->parsed_size + ared->extra_size + + sizeof (struct ar_hdr)); + firstreal += firstreal % 2; + current = current->archive_next; + } + while (current != map[count].u.abfd); + } + + /* The archive file format only has 4 bytes to store the offset + of the member. Generate 64-bit archive if an archive is past + its 4Gb limit. */ + offset = (unsigned int) firstreal; + if (firstreal != (file_ptr) offset) + return _bfd_archive_64_bit_write_armap (arch, elength, map, + orl_count, stridx); + + last_elt = current; + } +#endif /* If deterministic, we use 0 as the timestamp in the map. Some linkers may require that the archive filesystem modification @@ -2513,6 +2546,9 @@ bsd_write_armap (bfd *arch, if (bfd_bwrite (temp, sizeof (temp), arch) != sizeof (temp)) return FALSE; + firstreal = first; + current = arch->archive_head; + last_elt = current; /* Last element arch seen. */ for (count = 0; count < orl_count; count++) { unsigned int offset; @@ -2654,6 +2690,7 @@ coff_write_armap (bfd *arch, unsigned int stringsize = stridx; unsigned int mapsize = stringsize + ranlibsize; file_ptr archive_member_file_ptr; + file_ptr first_archive_member_file_ptr; bfd *current = arch->archive_head; unsigned int count; struct ar_hdr hdr; @@ -2663,10 +2700,42 @@ coff_write_armap (bfd *arch, mapsize++; /* Work out where the first object file will go in the archive. */ - archive_member_file_ptr = (mapsize - + elength - + sizeof (struct ar_hdr) - + SARMAG); + first_archive_member_file_ptr = (mapsize + + elength + + sizeof (struct ar_hdr) + + SARMAG); + +#ifdef BFD64 + current = arch->archive_head; + count = 0; + archive_member_file_ptr = first_archive_member_file_ptr; + while (current != NULL && count < symbol_count) + { + /* For each symbol which is used defined in this object, write + out the object file's address in the archive. */ + + while (count < symbol_count && map[count].u.abfd == current) + { + unsigned int offset = (unsigned int) archive_member_file_ptr; + + /* Generate 64-bit archive if an archive is past its 4Gb + limit. */ + if (archive_member_file_ptr != (file_ptr) offset) + return _bfd_archive_64_bit_write_armap (arch, elength, map, + symbol_count, stridx); + count++; + } + 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; + } +#endif memset (&hdr, ' ', sizeof (struct ar_hdr)); hdr.ar_name[0] = '/'; @@ -2697,6 +2766,7 @@ coff_write_armap (bfd *arch, current = arch->archive_head; count = 0; + archive_member_file_ptr = first_archive_member_file_ptr; while (current != NULL && count < symbol_count) { /* For each symbol which is used defined in this object, write |