X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Fcoff-rs6000.c;h=4859f31b2b4c3f57511684fa9e8b71b7d402d327;hb=d8045f234d8865a7a7bfce71e81fcbeaf4098a7e;hp=1257fbb143614d9322cf6ac19cd81769ea1427ea;hpb=dfeffb9fe1d18c568b06be976da294b928753821;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/coff-rs6000.c b/bfd/coff-rs6000.c index 1257fbb143..4859f31b2b 100644 --- a/bfd/coff-rs6000.c +++ b/bfd/coff-rs6000.c @@ -1,33 +1,29 @@ /* BFD back-end for IBM RS/6000 "XCOFF" files. - Copyright 1990-1999, 2000, 2001, 2002, 2003, 2004 - Free Software Foundation, Inc. - FIXME: Can someone provide a transliteration of this name into ASCII? - Using the following chars caused a compiler warning on HIUX (so I replaced - them with octal escapes), and isn't useful without an understanding of what - character set it is. - Written by Metin G. Ozisik, Mimi Ph\373\364ng-Th\345o V\365, - and John Gilmore. + Copyright 1990-1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, + 2008, 2009 Free Software Foundation, Inc. + Written by Metin G. Ozisik, Mimi Phuong-Thao Vo, and John Gilmore. Archive support from Damon A. Permezel. Contributed by IBM Corporation and Cygnus Support. -This file is part of BFD, the Binary File Descriptor library. + This file is part of BFD, the Binary File Descriptor library. -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 -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. + 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ -#include "bfd.h" #include "sysdep.h" +#include "bfd.h" #include "bfdlink.h" #include "libbfd.h" #include "coff/internal.h" @@ -59,7 +55,7 @@ extern bfd_boolean _bfd_xcoff_write_armap extern bfd_boolean _bfd_xcoff_write_archive_contents PARAMS ((bfd *)); extern int _bfd_xcoff_sizeof_headers - PARAMS ((bfd *, bfd_boolean)); + PARAMS ((bfd *, struct bfd_link_info *)); extern void _bfd_xcoff_swap_sym_in PARAMS ((bfd *, PTR, PTR)); extern unsigned int _bfd_xcoff_swap_sym_out @@ -98,6 +94,7 @@ void xcoff_rtype2howto #define coff_bfd_copy_private_bfd_data _bfd_xcoff_copy_private_bfd_data #define coff_bfd_is_local_label_name _bfd_xcoff_is_local_label_name #define coff_bfd_reloc_type_lookup _bfd_xcoff_reloc_type_lookup +#define coff_bfd_reloc_name_lookup _bfd_xcoff_reloc_name_lookup #ifdef AIX_CORE extern const bfd_target * rs6000coff_core_p PARAMS ((bfd *abfd)); @@ -131,6 +128,10 @@ extern int rs6000coff_core_file_failing_signal #define coff_swap_reloc_out xcoff_swap_reloc_out #define NO_COFF_RELOCS +#ifndef bfd_pe_print_pdata +#define bfd_pe_print_pdata NULL +#endif + #include "coffcode.h" /* The main body of code is in coffcode.h. */ @@ -179,8 +180,6 @@ static bfd_boolean do_pad PARAMS ((bfd *, unsigned int)); static bfd_boolean do_copy PARAMS ((bfd *, bfd *)); -static bfd_boolean do_shared_object_padding - PARAMS ((bfd *, bfd *, file_ptr *, int)); /* Relocation functions */ static bfd_boolean xcoff_reloc_type_br @@ -237,6 +236,119 @@ bfd_boolean (*xcoff_complain_overflow[XCOFF_MAX_COMPLAIN_OVERFLOW]) xcoff_complain_overflow_unsigned_func, }; +/* Information about one member of an archive. */ +struct member_layout { + /* The archive member that this structure describes. */ + bfd *member; + + /* The number of bytes of padding that must be inserted before the + start of the member in order to ensure that the section contents + are correctly aligned. */ + unsigned int leading_padding; + + /* The offset of MEMBER from the start of the archive (i.e. the end + of the leading padding). */ + file_ptr offset; + + /* The normalized name of MEMBER. */ + const char *name; + + /* The length of NAME, without padding. */ + bfd_size_type namlen; + + /* The length of NAME, with padding. */ + bfd_size_type padded_namlen; + + /* The size of MEMBER's header, including the name and magic sequence. */ + bfd_size_type header_size; + + /* The size of the MEMBER's contents. */ + bfd_size_type contents_size; + + /* The number of bytes of padding that must be inserted after MEMBER + in order to preserve even alignment. */ + bfd_size_type trailing_padding; +}; + +/* A structure used for iterating over the members of an archive. */ +struct archive_iterator { + /* The archive itself. */ + bfd *archive; + + /* Information about the current archive member. */ + struct member_layout current; + + /* Information about the next archive member. MEMBER is null if there + are no more archive members, in which case OFFSET is the offset of + the first unused byte. */ + struct member_layout next; +}; + +/* Initialize INFO so that it describes member MEMBER of archive ARCHIVE. + OFFSET is the even-padded offset of MEMBER, not including any leading + padding needed for section alignment. */ + +static void +member_layout_init (struct member_layout *info, bfd *archive, + bfd *member, file_ptr offset) +{ + info->member = member; + info->leading_padding = 0; + if (member) + { + info->name = normalize_filename (member); + info->namlen = strlen (info->name); + info->padded_namlen = info->namlen + (info->namlen & 1); + if (xcoff_big_format_p (archive)) + info->header_size = SIZEOF_AR_HDR_BIG; + else + info->header_size = SIZEOF_AR_HDR; + info->header_size += info->padded_namlen + SXCOFFARFMAG; + info->contents_size = arelt_size (member); + info->trailing_padding = info->contents_size & 1; + + if (bfd_check_format (member, bfd_object) + && bfd_get_flavour (member) == bfd_target_xcoff_flavour + && (member->flags & DYNAMIC) != 0) + info->leading_padding + = (-(offset + info->header_size) + & ((1 << bfd_xcoff_text_align_power (member)) - 1)); + } + info->offset = offset + info->leading_padding; +} + +/* Set up ITERATOR to iterate through archive ARCHIVE. */ + +static void +archive_iterator_begin (struct archive_iterator *iterator, + bfd *archive) +{ + iterator->archive = archive; + member_layout_init (&iterator->next, archive, archive->archive_head, + xcoff_big_format_p (archive) + ? SIZEOF_AR_FILE_HDR_BIG + : SIZEOF_AR_FILE_HDR); +} + +/* Make ITERATOR visit the first unvisited archive member. Return true + on success; return false if all members have been visited. */ + +static bfd_boolean +archive_iterator_next (struct archive_iterator *iterator) +{ + if (!iterator->next.member) + return FALSE; + + iterator->current = iterator->next; + member_layout_init (&iterator->next, iterator->archive, + iterator->current.member->archive_next, + iterator->current.offset + + iterator->current.header_size + + iterator->current.contents_size + + iterator->current.trailing_padding); + return TRUE; +} + /* We use our own tdata type. Its first field is the COFF tdata type, so the COFF routines are compatible. */ @@ -421,6 +533,7 @@ _bfd_xcoff_swap_aux_in (abfd, ext1, type, class, indx, numaux, in1) /* RS/6000 "csect" auxents */ case C_EXT: + case C_AIX_WEAKEXT: case C_HIDEXT: if (indx + 1 == numaux) { @@ -530,6 +643,7 @@ _bfd_xcoff_swap_aux_out (abfd, inp, type, class, indx, numaux, extp) /* RS/6000 "csect" auxents */ case C_EXT: + case C_AIX_WEAKEXT: case C_HIDEXT: if (indx + 1 == numaux) { @@ -1051,6 +1165,21 @@ _bfd_xcoff_reloc_type_lookup (abfd, code) } } +static reloc_howto_type * +_bfd_xcoff_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, + const char *r_name) +{ + unsigned int i; + + for (i = 0; + i < sizeof (xcoff_howto_table) / sizeof (xcoff_howto_table[0]); + i++) + if (xcoff_howto_table[i].name != NULL + && strcasecmp (xcoff_howto_table[i].name, r_name) == 0) + return &xcoff_howto_table[i]; + + return NULL; +} /* XCOFF archive support. The original version of this code was by Damon A. Permezel. It was enhanced to permit cross support, and @@ -1294,10 +1423,12 @@ _bfd_xcoff_archive_p (abfd) if (bfd_ardata (abfd) == (struct artdata *) NULL) goto error_ret_restore; - bfd_ardata (abfd)->cache = NULL; - bfd_ardata (abfd)->archive_head = NULL; - bfd_ardata (abfd)->symdefs = NULL; - bfd_ardata (abfd)->extended_names = NULL; + /* Cleared by bfd_zalloc above. + bfd_ardata (abfd)->cache = NULL; + bfd_ardata (abfd)->archive_head = NULL; + bfd_ardata (abfd)->symdefs = NULL; + bfd_ardata (abfd)->extended_names = NULL; + bfd_ardata (abfd)->extended_names_size = 0; */ /* Now handle the two formats. */ if (magic[1] != 'b') @@ -1583,11 +1714,10 @@ xcoff_write_armap_old (abfd, elength, map, orl_count, stridx) unsigned int orl_count; int stridx; { + struct archive_iterator iterator; struct xcoff_ar_hdr hdr; char *p; unsigned char buf[4]; - bfd *sub; - file_ptr fileoff; unsigned int i; memset (&hdr, 0, sizeof hdr); @@ -1615,29 +1745,16 @@ xcoff_write_armap_old (abfd, elength, map, orl_count, stridx) if (bfd_bwrite (buf, (bfd_size_type) 4, abfd) != 4) return FALSE; - sub = abfd->archive_head; - fileoff = SIZEOF_AR_FILE_HDR; i = 0; - while (sub != NULL && i < orl_count) - { - size_t namlen; - - while (map[i].u.abfd == sub) - { - H_PUT_32 (abfd, fileoff, buf); - if (bfd_bwrite (buf, (bfd_size_type) 4, abfd) != 4) - return FALSE; - ++i; - } - namlen = strlen (normalize_filename (sub)); - namlen = (namlen + 1) &~ (size_t) 1; - fileoff += (SIZEOF_AR_HDR - + namlen - + SXCOFFARFMAG - + arelt_size (sub)); - fileoff = (fileoff + 1) &~ 1; - sub = sub->next; - } + archive_iterator_begin (&iterator, abfd); + while (i < orl_count && archive_iterator_next (&iterator)) + while (map[i].u.abfd == iterator.current.member) + { + H_PUT_32 (abfd, iterator.current.offset, buf); + if (bfd_bwrite (buf, (bfd_size_type) 4, abfd) != 4) + return FALSE; + ++i; + } for (i = 0; i < orl_count; i++) { @@ -1738,34 +1855,6 @@ do_copy (out_bfd, in_bfd) return TRUE; } -static bfd_boolean -do_shared_object_padding (out_bfd, in_bfd, offset, ar_header_size) - bfd *out_bfd; - bfd *in_bfd; - file_ptr *offset; - int ar_header_size; -{ - if (bfd_check_format (in_bfd, bfd_object) - && bfd_get_flavour (in_bfd) == bfd_target_xcoff_flavour - && (in_bfd->flags & DYNAMIC) != 0) - { - bfd_size_type pad = 0; - int text_align_power; - - text_align_power = bfd_xcoff_text_align_power (in_bfd); - - pad = 1 << text_align_power; - pad -= (*offset + ar_header_size) & (pad - 1); - - if (! do_pad (out_bfd, pad)) - return FALSE; - - *offset += pad; - } - - return TRUE; -} - static bfd_boolean xcoff_write_armap_big (abfd, elength, map, orl_count, stridx) bfd *abfd; @@ -1774,9 +1863,10 @@ xcoff_write_armap_big (abfd, elength, map, orl_count, stridx) unsigned int orl_count; int stridx; { + struct archive_iterator iterator; struct xcoff_ar_file_hdr_big *fhdr; bfd_vma i, sym_32, sym_64, str_32, str_64; - const bfd_arch_info_type *arch_info = NULL; + const bfd_arch_info_type *arch_info; bfd *current_bfd; size_t string_length; file_ptr nextoff, prevoff; @@ -1785,16 +1875,15 @@ xcoff_write_armap_big (abfd, elength, map, orl_count, stridx) from 32-bit objects and which from 64-bit ones. */ sym_32 = sym_64 = str_32 = str_64 = 0; - current_bfd = abfd->archive_head; - if (current_bfd != NULL) - arch_info = bfd_get_arch_info (current_bfd); - i = 0; - while (current_bfd != NULL && i < orl_count) + i = 0; + for (current_bfd = abfd->archive_head; + current_bfd != NULL && i < orl_count; + current_bfd = current_bfd->archive_next) { + arch_info = bfd_get_arch_info (current_bfd); while (map[i].u.abfd == current_bfd) { string_length = strlen (*map[i].name) + 1; - if (arch_info->bits_per_address == 64) { sym_64++; @@ -1807,9 +1896,6 @@ xcoff_write_armap_big (abfd, elength, map, orl_count, stridx) } i++; } - current_bfd = current_bfd->next; - if (current_bfd != NULL) - arch_info = bfd_get_arch_info (current_bfd); } /* A quick sanity check... */ @@ -1849,9 +1935,8 @@ xcoff_write_armap_big (abfd, elength, map, orl_count, stridx) if (sym_32) { struct xcoff_ar_hdr_big *hdr; - bfd_byte *symbol_table; - bfd_byte *st; - file_ptr fileoff; + char *symbol_table; + char *st; bfd_vma symbol_table_size = SIZEOF_AR_HDR_BIG @@ -1860,8 +1945,7 @@ xcoff_write_armap_big (abfd, elength, map, orl_count, stridx) + 8 * sym_32 + str_32 + (str_32 & 1); - symbol_table = NULL; - symbol_table = (bfd_byte *) bfd_zmalloc (symbol_table_size); + symbol_table = bfd_zmalloc (symbol_table_size); if (symbol_table == NULL) return FALSE; @@ -1889,41 +1973,29 @@ xcoff_write_armap_big (abfd, elength, map, orl_count, stridx) st += 8; /* loop over the 32 bit offsets */ - current_bfd = abfd->archive_head; - if (current_bfd != NULL) - arch_info = bfd_get_arch_info (current_bfd); - fileoff = SIZEOF_AR_FILE_HDR_BIG; i = 0; - while (current_bfd != NULL && i < orl_count) + archive_iterator_begin (&iterator, abfd); + while (i < orl_count && archive_iterator_next (&iterator)) { - while (map[i].u.abfd == current_bfd) + arch_info = bfd_get_arch_info (iterator.current.member); + while (map[i].u.abfd == iterator.current.member) { if (arch_info->bits_per_address == 32) { - bfd_h_put_64 (abfd, fileoff, st); + bfd_h_put_64 (abfd, iterator.current.offset, st); st += 8; } i++; } - string_length = strlen (normalize_filename (current_bfd)); - string_length += string_length & 1; - fileoff += (SIZEOF_AR_HDR_BIG - + string_length - + SXCOFFARFMAG - + arelt_size (current_bfd)); - fileoff += fileoff & 1; - current_bfd = current_bfd->next; - if (current_bfd != NULL) - arch_info = bfd_get_arch_info (current_bfd); } /* loop over the 32 bit symbol names */ - current_bfd = abfd->archive_head; - if (current_bfd != NULL) - arch_info = bfd_get_arch_info (current_bfd); i = 0; - while (current_bfd != NULL && i < orl_count) + for (current_bfd = abfd->archive_head; + current_bfd != NULL && i < orl_count; + current_bfd = current_bfd->archive_next) { + arch_info = bfd_get_arch_info (current_bfd); while (map[i].u.abfd == current_bfd) { if (arch_info->bits_per_address == 32) @@ -1933,15 +2005,11 @@ xcoff_write_armap_big (abfd, elength, map, orl_count, stridx) } i++; } - current_bfd = current_bfd->next; - if (current_bfd != NULL) - arch_info = bfd_get_arch_info (current_bfd); } bfd_bwrite (symbol_table, symbol_table_size, abfd); free (symbol_table); - symbol_table = NULL; prevoff = nextoff; nextoff = nextoff + symbol_table_size; @@ -1952,9 +2020,8 @@ xcoff_write_armap_big (abfd, elength, map, orl_count, stridx) if (sym_64) { struct xcoff_ar_hdr_big *hdr; - bfd_byte *symbol_table; - bfd_byte *st; - file_ptr fileoff; + char *symbol_table; + char *st; bfd_vma symbol_table_size = SIZEOF_AR_HDR_BIG @@ -1963,8 +2030,7 @@ xcoff_write_armap_big (abfd, elength, map, orl_count, stridx) + 8 * sym_64 + str_64 + (str_64 & 1); - symbol_table = NULL; - symbol_table = (bfd_byte *) bfd_zmalloc (symbol_table_size); + symbol_table = bfd_zmalloc (symbol_table_size); if (symbol_table == NULL) return FALSE; @@ -1987,41 +2053,29 @@ xcoff_write_armap_big (abfd, elength, map, orl_count, stridx) st += 8; /* loop over the 64 bit offsets */ - current_bfd = abfd->archive_head; - if (current_bfd != NULL) - arch_info = bfd_get_arch_info (current_bfd); - fileoff = SIZEOF_AR_FILE_HDR_BIG; i = 0; - while (current_bfd != NULL && i < orl_count) + archive_iterator_begin (&iterator, abfd); + while (i < orl_count && archive_iterator_next (&iterator)) { - while (map[i].u.abfd == current_bfd) + arch_info = bfd_get_arch_info (iterator.current.member); + while (map[i].u.abfd == iterator.current.member) { if (arch_info->bits_per_address == 64) { - bfd_h_put_64 (abfd, fileoff, st); + bfd_h_put_64 (abfd, iterator.current.offset, st); st += 8; } i++; } - string_length = strlen (normalize_filename (current_bfd)); - string_length += string_length & 1; - fileoff += (SIZEOF_AR_HDR_BIG - + string_length - + SXCOFFARFMAG - + arelt_size (current_bfd)); - fileoff += fileoff & 1; - current_bfd = current_bfd->next; - if (current_bfd != NULL) - arch_info = bfd_get_arch_info (current_bfd); } /* loop over the 64 bit symbol names */ - current_bfd = abfd->archive_head; - if (current_bfd != NULL) - arch_info = bfd_get_arch_info (current_bfd); i = 0; - while (current_bfd != NULL && i < orl_count) + for (current_bfd = abfd->archive_head; + current_bfd != NULL && i < orl_count; + current_bfd = current_bfd->archive_next) { + arch_info = bfd_get_arch_info (current_bfd); while (map[i].u.abfd == current_bfd) { if (arch_info->bits_per_address == 64) @@ -2031,15 +2085,11 @@ xcoff_write_armap_big (abfd, elength, map, orl_count, stridx) } i++; } - current_bfd = current_bfd->next; - if (current_bfd != NULL) - arch_info = bfd_get_arch_info (current_bfd); } bfd_bwrite (symbol_table, symbol_table_size, abfd); free (symbol_table); - symbol_table = NULL; PRINT20 (fhdr->symoff64, nextoff); } @@ -2070,6 +2120,7 @@ static bfd_boolean xcoff_write_archive_contents_old (abfd) bfd *abfd; { + struct archive_iterator iterator; struct xcoff_ar_file_hdr fhdr; bfd_size_type count; bfd_size_type total_namlen; @@ -2085,126 +2136,102 @@ xcoff_write_archive_contents_old (abfd) char decbuf[XCOFFARMAG_ELEMENT_SIZE + 1]; memset (&fhdr, 0, sizeof fhdr); - strncpy (fhdr.magic, XCOFFARMAG, SXCOFFARMAG); + (void) strncpy (fhdr.magic, XCOFFARMAG, SXCOFFARMAG); sprintf (fhdr.firstmemoff, "%d", SIZEOF_AR_FILE_HDR); sprintf (fhdr.freeoff, "%d", 0); count = 0; total_namlen = 0; - for (sub = abfd->archive_head; sub != NULL; sub = sub->next) + for (sub = abfd->archive_head; sub != NULL; sub = sub->archive_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, (file_ptr) SIZEOF_AR_FILE_HDR, SEEK_SET) != 0) - return FALSE; - - makemap = bfd_has_map (abfd); - hasobjects = FALSE; - prevoff = 0; - nextoff = SIZEOF_AR_FILE_HDR; - for (sub = abfd->archive_head, i = 0; sub != NULL; sub = sub->next, i++) - { - const char *name; - bfd_size_type namlen; - struct xcoff_ar_hdr *ahdrp; - bfd_size_type remaining; - - if (makemap && ! hasobjects) + if (sub->arelt_data == NULL) { - if (bfd_check_format (sub, bfd_object)) - hasobjects = TRUE; + sub->arelt_data = bfd_zalloc (sub, sizeof (struct areltdata)); + if (sub->arelt_data == NULL) + return FALSE; } - - name = normalize_filename (sub); - namlen = strlen (name); - - if (sub->arelt_data != NULL) - ahdrp = arch_xhdr (sub); - else - ahdrp = NULL; - - if (ahdrp == NULL) + if (arch_xhdr (sub) == NULL) { + struct xcoff_ar_hdr *ahdrp; struct stat s; - memset (&ahdr, 0, sizeof ahdr); - ahdrp = &ahdr; if (stat (bfd_get_filename (sub), &s) != 0) { bfd_set_error (bfd_error_system_call); return FALSE; } + ahdrp = bfd_zalloc (sub, sizeof (*ahdrp)); + if (ahdrp == NULL) + return FALSE; + 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) - { - size = sizeof (struct areltdata); - sub->arelt_data = bfd_alloc (sub, size); - if (sub->arelt_data == NULL) - return FALSE; - } - + arch_eltdata (sub)->arch_header = (char *) ahdrp; arch_eltdata (sub)->parsed_size = s.st_size; } + } + offsets = (file_ptr *) bfd_alloc (abfd, count * sizeof (file_ptr)); + if (offsets == NULL) + return FALSE; - 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) &~ (bfd_size_type) 1; - - remaining = arelt_size (sub); - size = (SIZEOF_AR_HDR - + namlen - + SXCOFFARFMAG - + remaining); - - BFD_ASSERT (nextoff == bfd_tell (abfd)); + if (bfd_seek (abfd, (file_ptr) SIZEOF_AR_FILE_HDR, SEEK_SET) != 0) + return FALSE; - offsets[i] = nextoff; + makemap = bfd_has_map (abfd); + hasobjects = FALSE; + prevoff = 0; + for (archive_iterator_begin (&iterator, abfd), i = 0; + archive_iterator_next (&iterator); + i++) + { + bfd_size_type namlen; + struct xcoff_ar_hdr *ahdrp; - prevoff = nextoff; - nextoff += size + (size & 1); + if (makemap && ! hasobjects) + { + if (bfd_check_format (iterator.current.member, bfd_object)) + hasobjects = TRUE; + } - sprintf (ahdrp->nextoff, "%ld", (long) nextoff); + ahdrp = arch_xhdr (iterator.current.member); + sprintf (ahdrp->prevoff, "%ld", (long) prevoff); + sprintf (ahdrp->namlen, "%ld", (long) iterator.current.namlen); + sprintf (ahdrp->nextoff, "%ld", (long) iterator.next.offset); /* We need spaces, not null bytes, in the header. */ for (p = (char *) ahdrp; p < (char *) ahdrp + SIZEOF_AR_HDR; p++) if (*p == '\0') *p = ' '; - if ((bfd_bwrite ((PTR) ahdrp, (bfd_size_type) SIZEOF_AR_HDR, abfd) - != SIZEOF_AR_HDR) - || bfd_bwrite ((PTR) name, namlen, abfd) != namlen - || bfd_bwrite ((PTR) XCOFFARFMAG, (bfd_size_type) SXCOFFARFMAG, - abfd) != SXCOFFARFMAG) - return FALSE; - - if (bfd_seek (sub, (file_ptr) 0, SEEK_SET) != 0) + if (!do_pad (abfd, iterator.current.leading_padding)) return FALSE; - if (! do_copy (abfd, sub)) + BFD_ASSERT (iterator.current.offset == bfd_tell (abfd)); + namlen = iterator.current.padded_namlen; + if (bfd_bwrite (ahdrp, SIZEOF_AR_HDR, abfd) != SIZEOF_AR_HDR + || bfd_bwrite (iterator.current.name, namlen, abfd) != namlen + || bfd_bwrite (XCOFFARFMAG, SXCOFFARFMAG, abfd) != SXCOFFARFMAG + || bfd_seek (iterator.current.member, 0, SEEK_SET) != 0 + || !do_copy (abfd, iterator.current.member) + || !do_pad (abfd, iterator.current.trailing_padding)) return FALSE; - if (! do_pad (abfd, size & 1)) - return FALSE; + offsets[i] = iterator.current.offset; + prevoff = iterator.current.offset; } sprintf (fhdr.lastmemoff, "%ld", (long) prevoff); /* Write out the member table. */ + nextoff = iterator.next.offset; BFD_ASSERT (nextoff == bfd_tell (abfd)); sprintf (fhdr.memoff, "%ld", (long) nextoff); @@ -2255,7 +2282,7 @@ xcoff_write_archive_contents_old (abfd) abfd) != XCOFFARMAG_ELEMENT_SIZE) return FALSE; } - for (sub = abfd->archive_head; sub != NULL; sub = sub->next) + for (sub = abfd->archive_head; sub != NULL; sub = sub->archive_next) { const char *name; bfd_size_type namlen; @@ -2309,10 +2336,11 @@ xcoff_write_archive_contents_big (abfd) file_ptr prevoff, nextoff; bfd *current_bfd; size_t i; - struct xcoff_ar_hdr_big *hdr, ahdr; + struct xcoff_ar_hdr_big *hdr; bfd_size_type size; - bfd_byte *member_table, *mt; + char *member_table, *mt; bfd_vma member_table_size; + struct archive_iterator iterator; memset (&fhdr, 0, SIZEOF_AR_FILE_HDR_BIG); memcpy (fhdr.magic, XCOFFARMAGBIG, SXCOFFARMAG); @@ -2325,7 +2353,7 @@ xcoff_write_archive_contents_big (abfd) hasobjects = FALSE; for (current_bfd = abfd->archive_head, count = 0, total_namlen = 0; current_bfd != NULL; - current_bfd = current_bfd->next, count++) + current_bfd = current_bfd->archive_next, count++) { total_namlen += strlen (normalize_filename (current_bfd)) + 1; @@ -2333,40 +2361,20 @@ xcoff_write_archive_contents_big (abfd) && ! hasobjects && bfd_check_format (current_bfd, bfd_object)) hasobjects = TRUE; - } - - offsets = NULL; - if (count) - { - offsets = (file_ptr *) bfd_malloc (count * sizeof (file_ptr)); - if (offsets == NULL) - return FALSE; - } - - prevoff = 0; - nextoff = SIZEOF_AR_FILE_HDR_BIG; - for (current_bfd = abfd->archive_head, i = 0; - current_bfd != NULL; - current_bfd = current_bfd->next, i++) - { - const char *name; - bfd_size_type namlen; - struct xcoff_ar_hdr_big *ahdrp; - bfd_size_type remaining; - - name = normalize_filename (current_bfd); - namlen = strlen (name); - if (current_bfd->arelt_data != NULL) - ahdrp = arch_xhdr_big (current_bfd); - else - ahdrp = NULL; + if (current_bfd->arelt_data == NULL) + { + size = sizeof (struct areltdata); + current_bfd->arelt_data = bfd_zalloc (current_bfd, size); + if (current_bfd->arelt_data == NULL) + return FALSE; + } - if (ahdrp == NULL) + if (arch_xhdr_big (current_bfd) == NULL) { + struct xcoff_ar_hdr_big *ahdrp; struct stat s; - ahdrp = &ahdr; /* XXX This should actually be a call to stat64 (at least on 32-bit machines). XXX This call will fail if the original object is not found. */ @@ -2376,68 +2384,57 @@ xcoff_write_archive_contents_big (abfd) return FALSE; } + ahdrp = bfd_zalloc (current_bfd, sizeof (*ahdrp)); + if (ahdrp == NULL) + return FALSE; + PRINT20 (ahdrp->size, s.st_size); PRINT12 (ahdrp->date, s.st_mtime); PRINT12 (ahdrp->uid, s.st_uid); PRINT12 (ahdrp->gid, s.st_gid); PRINT12_OCTAL (ahdrp->mode, s.st_mode); - if (current_bfd->arelt_data == NULL) - { - size = sizeof (struct areltdata); - current_bfd->arelt_data = bfd_alloc (current_bfd, size); - if (current_bfd->arelt_data == NULL) - return FALSE; - } - + arch_eltdata (current_bfd)->arch_header = (char *) ahdrp; arch_eltdata (current_bfd)->parsed_size = s.st_size; } + } - PRINT20 (ahdrp->prevoff, prevoff); - PRINT4 (ahdrp->namlen, namlen); - - /* If the length of the name is odd, we write out the null byte - after the name as well. */ - namlen = (namlen + 1) &~ (bfd_size_type) 1; - - remaining = arelt_size (current_bfd); - size = (SIZEOF_AR_HDR_BIG - + namlen - + SXCOFFARFMAG - + remaining); - - BFD_ASSERT (nextoff == bfd_tell (abfd)); - - /* Check for xcoff shared objects. - Their text section needs to be aligned wrt the archive file position. - This requires extra padding before the archive header. */ - if (! do_shared_object_padding (abfd, current_bfd, & nextoff, - SIZEOF_AR_HDR_BIG + namlen - + SXCOFFARFMAG)) + offsets = NULL; + if (count) + { + offsets = (file_ptr *) bfd_malloc (count * sizeof (file_ptr)); + if (offsets == NULL) return FALSE; + } - offsets[i] = nextoff; - - prevoff = nextoff; - nextoff += size + (size & 1); - - PRINT20 (ahdrp->nextoff, nextoff); + prevoff = 0; + for (archive_iterator_begin (&iterator, abfd), i = 0; + archive_iterator_next (&iterator); + i++) + { + bfd_size_type namlen; + struct xcoff_ar_hdr_big *ahdrp; - if ((bfd_bwrite ((PTR) ahdrp, (bfd_size_type) SIZEOF_AR_HDR_BIG, abfd) - != SIZEOF_AR_HDR_BIG) - || bfd_bwrite ((PTR) name, (bfd_size_type) namlen, abfd) != namlen - || (bfd_bwrite ((PTR) XCOFFARFMAG, (bfd_size_type) SXCOFFARFMAG, - abfd) != SXCOFFARFMAG)) - return FALSE; + ahdrp = arch_xhdr_big (iterator.current.member); + PRINT20 (ahdrp->prevoff, prevoff); + PRINT4 (ahdrp->namlen, iterator.current.namlen); + PRINT20 (ahdrp->nextoff, iterator.next.offset); - if (bfd_seek (current_bfd, (file_ptr) 0, SEEK_SET) != 0) + if (!do_pad (abfd, iterator.current.leading_padding)) return FALSE; - if (! do_copy (abfd, current_bfd)) + BFD_ASSERT (iterator.current.offset == bfd_tell (abfd)); + namlen = iterator.current.padded_namlen; + if (bfd_bwrite (ahdrp, SIZEOF_AR_HDR_BIG, abfd) != SIZEOF_AR_HDR_BIG + || bfd_bwrite (iterator.current.name, namlen, abfd) != namlen + || bfd_bwrite (XCOFFARFMAG, SXCOFFARFMAG, abfd) != SXCOFFARFMAG + || bfd_seek (iterator.current.member, 0, SEEK_SET) != 0 + || !do_copy (abfd, iterator.current.member) + || !do_pad (abfd, iterator.current.trailing_padding)) return FALSE; - if (! do_pad (abfd, size & 1)) - return FALSE; + offsets[i] = iterator.current.offset; + prevoff = iterator.current.offset; } if (count) @@ -2467,6 +2464,7 @@ xcoff_write_archive_contents_big (abfd) ?? pad to even bytes. */ + nextoff = iterator.next.offset; BFD_ASSERT (nextoff == bfd_tell (abfd)); member_table_size = (SIZEOF_AR_HDR_BIG @@ -2476,8 +2474,7 @@ xcoff_write_archive_contents_big (abfd) + total_namlen); member_table_size += member_table_size & 1; - member_table = NULL; - member_table = (bfd_byte *) bfd_zmalloc (member_table_size); + member_table = bfd_zmalloc (member_table_size); if (member_table == NULL) return FALSE; @@ -2515,8 +2512,9 @@ xcoff_write_archive_contents_big (abfd) offsets = NULL; } - for (current_bfd = abfd->archive_head; current_bfd != NULL; - current_bfd = current_bfd->next) + for (current_bfd = abfd->archive_head; + current_bfd != NULL; + current_bfd = current_bfd->archive_next) { const char *name; size_t namlen; @@ -2530,7 +2528,6 @@ xcoff_write_archive_contents_big (abfd) return FALSE; free (member_table); - member_table = NULL; PRINT20 (fhdr.memoff, nextoff); @@ -2577,9 +2574,8 @@ _bfd_xcoff_write_archive_contents (abfd) always uses an a.out header. */ int -_bfd_xcoff_sizeof_headers (abfd, reloc) - bfd *abfd; - bfd_boolean reloc ATTRIBUTE_UNUSED; +_bfd_xcoff_sizeof_headers (bfd *abfd, + struct bfd_link_info *info ATTRIBUTE_UNUSED) { int size; @@ -2933,11 +2929,13 @@ xcoff_reloc_type_br (input_bfd, input_section, output_bfd, rel, sym, howto, bfd_byte *contents; { struct xcoff_link_hash_entry *h; + bfd_vma section_offset; if (0 > rel->r_symndx) return FALSE; h = obj_xcoff_sym_hashes (input_bfd)[rel->r_symndx]; + section_offset = rel->r_vaddr - input_section->vma; /* If we see an R_BR or R_RBR reloc which is jumping to global linkage code, and it is followed by an appropriate cror nop @@ -2947,13 +2945,14 @@ xcoff_reloc_type_br (input_bfd, input_section, output_bfd, rel, sym, howto, going to global linkage code, we can replace the load with a cror. */ if (NULL != h - && bfd_link_hash_defined == h->root.type - && rel->r_vaddr - input_section->vma + 8 <= input_section->size) + && (bfd_link_hash_defined == h->root.type + || bfd_link_hash_defweak == h->root.type) + && section_offset + 8 <= input_section->size) { bfd_byte *pnext; unsigned long next; - pnext = contents + (rel->r_vaddr - input_section->vma) + 4; + pnext = contents + section_offset + 4; next = bfd_get_32 (input_bfd, pnext); /* The _ptrgl function is magic. It is used by the AIX @@ -2963,12 +2962,12 @@ xcoff_reloc_type_br (input_bfd, input_section, output_bfd, rel, sym, howto, if (next == 0x4def7b82 /* cror 15,15,15 */ || next == 0x4ffffb82 /* cror 31,31,31 */ || next == 0x60000000) /* ori r0,r0,0 */ - bfd_put_32 (input_bfd, 0x80410014, pnext); /* lwz r1,20(r1) */ + bfd_put_32 (input_bfd, 0x80410014, pnext); /* lwz r2,20(r1) */ } else { - if (next == 0x80410014) /* lwz r1,20(r1) */ + if (next == 0x80410014) /* lwz r2,20(r1) */ bfd_put_32 (input_bfd, 0x60000000, pnext); /* ori r0,r0,0 */ } } @@ -2984,16 +2983,42 @@ xcoff_reloc_type_br (input_bfd, input_section, output_bfd, rel, sym, howto, howto->complain_on_overflow = complain_overflow_dont; } - howto->pc_relative = TRUE; + /* The original PC-relative relocation is biased by -r_vaddr, so adding + the value below will give the absolute target address. */ + *relocation = val + addend + rel->r_vaddr; + howto->src_mask &= ~3; howto->dst_mask = howto->src_mask; - /* A PC relative reloc includes the section address. */ - addend += input_section->vma; - - *relocation = val + addend; - *relocation -= (input_section->output_section->vma - + input_section->output_offset); + if (h != NULL + && (h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak) + && bfd_is_abs_section (h->root.u.def.section) + && section_offset + 4 <= input_section->size) + { + bfd_byte *ptr; + bfd_vma insn; + + /* Turn the relative branch into an absolute one by setting the + AA bit. */ + ptr = contents + section_offset; + insn = bfd_get_32 (input_bfd, ptr); + insn |= 2; + bfd_put_32 (input_bfd, insn, ptr); + + /* Make the howto absolute too. */ + howto->pc_relative = FALSE; + howto->complain_on_overflow = complain_overflow_bitfield; + } + else + { + /* Use a PC-relative howto and subtract the instruction's address + from the target address we calculated above. */ + howto->pc_relative = TRUE; + *relocation -= (input_section->output_section->vma + + input_section->output_offset + + section_offset); + } return TRUE; } @@ -3309,9 +3334,7 @@ xcoff_complain_overflow_unsigned_func (input_bfd, val, relocation, howto) R_RBR: A relative branch which may be modified to become an - absolute branch. FIXME: We don't implement this, - although we should for symbols of storage mapping class - XMC_XO. + absolute branch. R_RL: The PowerPC AIX ABI describes this as a load which may be @@ -3408,6 +3431,17 @@ xcoff_ppc_relocate_section (output_bfd, info, input_bfd, } else { + if (info->unresolved_syms_in_objects != RM_IGNORE + && (h->flags & XCOFF_WAS_UNDEFINED) != 0) + { + if (! ((*info->callbacks->undefined_symbol) + (info, h->root.root.string, + input_bfd, input_section, + rel->r_vaddr - input_section->vma, + (info->unresolved_syms_in_objects + == RM_GENERATE_ERROR)))) + return FALSE; + } if (h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) { @@ -3423,17 +3457,11 @@ xcoff_ppc_relocate_section (output_bfd, info, input_bfd, + sec->output_offset); } - else if ((0 == (h->flags & (XCOFF_DEF_DYNAMIC | XCOFF_IMPORT))) - && ! info->relocatable) + else { - if (! ((*info->callbacks->undefined_symbol) - (info, h->root.root.string, input_bfd, input_section, - rel->r_vaddr - input_section->vma, TRUE))) - return FALSE; - - /* Don't try to process the reloc. It can't help, and - it may generate another error. */ - continue; + BFD_ASSERT (info->relocatable + || (h->flags & XCOFF_DEF_DYNAMIC) != 0 + || (h->flags & XCOFF_IMPORT) != 0); } } } @@ -3530,7 +3558,7 @@ _bfd_xcoff_put_ldsymbol_name (abfd, ldinfo, ldsym, name) if (ldinfo->string_size + len + 3 > ldinfo->string_alc) { bfd_size_type newalc; - bfd_byte *newstrings; + char *newstrings; newalc = ldinfo->string_alc * 2; if (newalc == 0) @@ -3538,8 +3566,7 @@ _bfd_xcoff_put_ldsymbol_name (abfd, ldinfo, ldsym, name) while (ldinfo->string_size + len + 3 > newalc) newalc *= 2; - newstrings = ((bfd_byte *) - bfd_realloc ((PTR) ldinfo->strings, newalc)); + newstrings = bfd_realloc (ldinfo->strings, newalc); if (newstrings == NULL) { ldinfo->failed = TRUE; @@ -3998,7 +4025,7 @@ static const struct xcoff_backend_data_rec bfd_xcoff_backend_data = LINESZ, FILNMLEN, TRUE, /* _bfd_coff_long_filenames */ - FALSE, /* _bfd_coff_long_section_names */ + XCOFF_NO_LONG_SECTION_NAMES, /* _bfd_coff_long_section_names */ 3, /* _bfd_coff_default_section_alignment_power */ FALSE, /* _bfd_coff_force_symnames_in_strings */ 2, /* _bfd_coff_debug_string_prefix_length */ @@ -4025,7 +4052,8 @@ static const struct xcoff_backend_data_rec bfd_xcoff_backend_data = NULL, /* _bfd_coff_adjust_symndx */ _bfd_generic_link_add_one_symbol, coff_link_output_has_begun, - coff_final_link_postscript + coff_final_link_postscript, + NULL /* print_pdata. */ }, 0x01DF, /* magic number */ @@ -4140,6 +4168,7 @@ const bfd_target rs6000coff_vec = /* Copy */ _bfd_xcoff_copy_private_bfd_data, ((bfd_boolean (*) (bfd *, bfd *)) bfd_true), + _bfd_generic_init_private_section_data, ((bfd_boolean (*) (bfd *, asection *, bfd *, asection *)) bfd_true), ((bfd_boolean (*) (bfd *, asymbol *, bfd *, asymbol *)) bfd_true), ((bfd_boolean (*) (bfd *, bfd *)) bfd_true), @@ -4173,6 +4202,8 @@ const bfd_target rs6000coff_vec = coff_bfd_is_target_special_symbol, coff_get_lineno, coff_find_nearest_line, + _bfd_generic_find_line, + coff_find_inliner_info, coff_bfd_make_debug_symbol, _bfd_generic_read_minisymbols, _bfd_generic_minisymbol_to_symbol, @@ -4181,6 +4212,7 @@ const bfd_target rs6000coff_vec = coff_get_reloc_upper_bound, coff_canonicalize_reloc, _bfd_xcoff_reloc_type_lookup, + _bfd_xcoff_reloc_name_lookup, /* Write */ coff_set_arch_mach, @@ -4201,6 +4233,7 @@ const bfd_target rs6000coff_vec = bfd_generic_is_group_section, bfd_generic_discard_group, _bfd_generic_section_already_linked, + _bfd_xcoff_define_common_symbol, /* Dynamic */ _bfd_xcoff_get_dynamic_symtab_upper_bound, @@ -4245,7 +4278,7 @@ static const struct xcoff_backend_data_rec bfd_pmac_xcoff_backend_data = LINESZ, FILNMLEN, TRUE, /* _bfd_coff_long_filenames */ - FALSE, /* _bfd_coff_long_section_names */ + XCOFF_NO_LONG_SECTION_NAMES, /* _bfd_coff_long_section_names */ 3, /* _bfd_coff_default_section_alignment_power */ FALSE, /* _bfd_coff_force_symnames_in_strings */ 2, /* _bfd_coff_debug_string_prefix_length */ @@ -4272,7 +4305,8 @@ static const struct xcoff_backend_data_rec bfd_pmac_xcoff_backend_data = NULL, /* _bfd_coff_adjust_symndx */ _bfd_generic_link_add_one_symbol, coff_link_output_has_begun, - coff_final_link_postscript + coff_final_link_postscript, + NULL /* print_pdata. */ }, 0x01DF, /* magic number */ @@ -4387,6 +4421,7 @@ const bfd_target pmac_xcoff_vec = /* Copy */ _bfd_xcoff_copy_private_bfd_data, ((bfd_boolean (*) (bfd *, bfd *)) bfd_true), + _bfd_generic_init_private_section_data, ((bfd_boolean (*) (bfd *, asection *, bfd *, asection *)) bfd_true), ((bfd_boolean (*) (bfd *, asymbol *, bfd *, asymbol *)) bfd_true), ((bfd_boolean (*) (bfd *, bfd *)) bfd_true), @@ -4420,6 +4455,8 @@ const bfd_target pmac_xcoff_vec = coff_bfd_is_target_special_symbol, coff_get_lineno, coff_find_nearest_line, + _bfd_generic_find_line, + coff_find_inliner_info, coff_bfd_make_debug_symbol, _bfd_generic_read_minisymbols, _bfd_generic_minisymbol_to_symbol, @@ -4428,6 +4465,7 @@ const bfd_target pmac_xcoff_vec = coff_get_reloc_upper_bound, coff_canonicalize_reloc, _bfd_xcoff_reloc_type_lookup, + _bfd_xcoff_reloc_name_lookup, /* Write */ coff_set_arch_mach, @@ -4448,6 +4486,7 @@ const bfd_target pmac_xcoff_vec = bfd_generic_is_group_section, bfd_generic_discard_group, _bfd_generic_section_already_linked, + _bfd_xcoff_define_common_symbol, /* Dynamic */ _bfd_xcoff_get_dynamic_symtab_upper_bound,