X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Fcoff-alpha.c;h=62a0bb42b59bd9c1c75021193a7ead41594ad9bf;hb=0bf60745767d2465c81ee57ae7705a62d6d8fafe;hp=4ad7077fa621cde622440e06aa658ab71d3dd413;hpb=58142f101dd3256f4741f60a6b25672d79b91371;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/coff-alpha.c b/bfd/coff-alpha.c index 4ad7077fa6..62a0bb42b5 100644 --- a/bfd/coff-alpha.c +++ b/bfd/coff-alpha.c @@ -1,5 +1,6 @@ /* BFD back-end for ALPHA Extended-Coff files. - Copyright 1993, 1994 Free Software Foundation, Inc. + Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, + 2003, 2004, 2005 Free Software Foundation, Inc. Modified from coff-mips.c by Steve Chamberlain and Ian Lance Taylor . @@ -17,7 +18,7 @@ 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. */ +Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ #include "bfd.h" #include "sysdep.h" @@ -28,35 +29,46 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "coff/symconst.h" #include "coff/ecoff.h" #include "coff/alpha.h" +#include "aout/ar.h" #include "libcoff.h" #include "libecoff.h" /* Prototypes for static functions. */ -static const bfd_target *alpha_ecoff_object_p PARAMS ((bfd *)); -static boolean alpha_ecoff_bad_format_hook PARAMS ((bfd *abfd, PTR filehdr)); -static PTR alpha_ecoff_mkobject_hook PARAMS ((bfd *, PTR filehdr, PTR aouthdr)); -static void alpha_ecoff_swap_reloc_in PARAMS ((bfd *, PTR, - struct internal_reloc *)); -static void alpha_ecoff_swap_reloc_out PARAMS ((bfd *, - const struct internal_reloc *, - PTR)); -static void alpha_adjust_reloc_in PARAMS ((bfd *, - const struct internal_reloc *, - arelent *)); -static void alpha_adjust_reloc_out PARAMS ((bfd *, const arelent *, - struct internal_reloc *)); +static const bfd_target *alpha_ecoff_object_p + PARAMS ((bfd *)); +static bfd_boolean alpha_ecoff_bad_format_hook + PARAMS ((bfd *abfd, PTR filehdr)); +static PTR alpha_ecoff_mkobject_hook + PARAMS ((bfd *, PTR filehdr, PTR aouthdr)); +static void alpha_ecoff_swap_reloc_in + PARAMS ((bfd *, PTR, struct internal_reloc *)); +static void alpha_ecoff_swap_reloc_out + PARAMS ((bfd *, const struct internal_reloc *, PTR)); +static void alpha_adjust_reloc_in + PARAMS ((bfd *, const struct internal_reloc *, arelent *)); +static void alpha_adjust_reloc_out + PARAMS ((bfd *, const arelent *, struct internal_reloc *)); +static reloc_howto_type *alpha_bfd_reloc_type_lookup + PARAMS ((bfd *, bfd_reloc_code_real_type)); static bfd_byte *alpha_ecoff_get_relocated_section_contents PARAMS ((bfd *abfd, struct bfd_link_info *, struct bfd_link_order *, - bfd_byte *data, boolean relocateable, asymbol **symbols)); + bfd_byte *data, bfd_boolean relocatable, asymbol **symbols)); static bfd_vma alpha_convert_external_reloc PARAMS ((bfd *, struct bfd_link_info *, bfd *, struct external_reloc *, struct ecoff_link_hash_entry *)); -static boolean alpha_relocate_section PARAMS ((bfd *, struct bfd_link_info *, - bfd *, asection *, - bfd_byte *, PTR)); -static boolean alpha_adjust_headers +static bfd_boolean alpha_relocate_section + PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, PTR)); +static bfd_boolean alpha_adjust_headers PARAMS ((bfd *, struct internal_filehdr *, struct internal_aouthdr *)); +static PTR alpha_ecoff_read_ar_hdr + PARAMS ((bfd *)); +static bfd *alpha_ecoff_get_elt_at_filepos + PARAMS ((bfd *, file_ptr)); +static bfd *alpha_ecoff_openr_next_archived_file + PARAMS ((bfd *, bfd *)); +static bfd *alpha_ecoff_get_elt_at_index + PARAMS ((bfd *, symindex)); /* ECOFF has COFF sections, but the debugging information is stored in a completely different format. ECOFF targets use some of the @@ -68,32 +80,32 @@ static boolean alpha_adjust_headers symbol, and lineno ones. Give them ecoff names. Define some accessor macros for the large sizes used for Alpha ECOFF. */ -#define GET_FILEHDR_SYMPTR bfd_h_get_64 -#define PUT_FILEHDR_SYMPTR bfd_h_put_64 -#define GET_AOUTHDR_TSIZE bfd_h_get_64 -#define PUT_AOUTHDR_TSIZE bfd_h_put_64 -#define GET_AOUTHDR_DSIZE bfd_h_get_64 -#define PUT_AOUTHDR_DSIZE bfd_h_put_64 -#define GET_AOUTHDR_BSIZE bfd_h_get_64 -#define PUT_AOUTHDR_BSIZE bfd_h_put_64 -#define GET_AOUTHDR_ENTRY bfd_h_get_64 -#define PUT_AOUTHDR_ENTRY bfd_h_put_64 -#define GET_AOUTHDR_TEXT_START bfd_h_get_64 -#define PUT_AOUTHDR_TEXT_START bfd_h_put_64 -#define GET_AOUTHDR_DATA_START bfd_h_get_64 -#define PUT_AOUTHDR_DATA_START bfd_h_put_64 -#define GET_SCNHDR_PADDR bfd_h_get_64 -#define PUT_SCNHDR_PADDR bfd_h_put_64 -#define GET_SCNHDR_VADDR bfd_h_get_64 -#define PUT_SCNHDR_VADDR bfd_h_put_64 -#define GET_SCNHDR_SIZE bfd_h_get_64 -#define PUT_SCNHDR_SIZE bfd_h_put_64 -#define GET_SCNHDR_SCNPTR bfd_h_get_64 -#define PUT_SCNHDR_SCNPTR bfd_h_put_64 -#define GET_SCNHDR_RELPTR bfd_h_get_64 -#define PUT_SCNHDR_RELPTR bfd_h_put_64 -#define GET_SCNHDR_LNNOPTR bfd_h_get_64 -#define PUT_SCNHDR_LNNOPTR bfd_h_put_64 +#define GET_FILEHDR_SYMPTR H_GET_64 +#define PUT_FILEHDR_SYMPTR H_PUT_64 +#define GET_AOUTHDR_TSIZE H_GET_64 +#define PUT_AOUTHDR_TSIZE H_PUT_64 +#define GET_AOUTHDR_DSIZE H_GET_64 +#define PUT_AOUTHDR_DSIZE H_PUT_64 +#define GET_AOUTHDR_BSIZE H_GET_64 +#define PUT_AOUTHDR_BSIZE H_PUT_64 +#define GET_AOUTHDR_ENTRY H_GET_64 +#define PUT_AOUTHDR_ENTRY H_PUT_64 +#define GET_AOUTHDR_TEXT_START H_GET_64 +#define PUT_AOUTHDR_TEXT_START H_PUT_64 +#define GET_AOUTHDR_DATA_START H_GET_64 +#define PUT_AOUTHDR_DATA_START H_PUT_64 +#define GET_SCNHDR_PADDR H_GET_64 +#define PUT_SCNHDR_PADDR H_PUT_64 +#define GET_SCNHDR_VADDR H_GET_64 +#define PUT_SCNHDR_VADDR H_PUT_64 +#define GET_SCNHDR_SIZE H_GET_64 +#define PUT_SCNHDR_SIZE H_PUT_64 +#define GET_SCNHDR_SCNPTR H_GET_64 +#define PUT_SCNHDR_SCNPTR H_PUT_64 +#define GET_SCNHDR_RELPTR H_GET_64 +#define PUT_SCNHDR_RELPTR H_PUT_64 +#define GET_SCNHDR_LNNOPTR H_GET_64 +#define PUT_SCNHDR_LNNOPTR H_PUT_64 #define ALPHAECOFF @@ -114,19 +126,18 @@ static boolean alpha_adjust_headers /* How to process the various reloc types. */ -static bfd_reloc_status_type -reloc_nil PARAMS ((bfd *, arelent *, asymbol *, PTR, - asection *, bfd *, char **)); +static bfd_reloc_status_type reloc_nil + PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); static bfd_reloc_status_type reloc_nil (abfd, reloc, sym, data, sec, output_bfd, error_message) - bfd *abfd; - arelent *reloc; - asymbol *sym; - PTR data; - asection *sec; - bfd *output_bfd; - char **error_message; + bfd *abfd ATTRIBUTE_UNUSED; + arelent *reloc ATTRIBUTE_UNUSED; + asymbol *sym ATTRIBUTE_UNUSED; + PTR data ATTRIBUTE_UNUSED; + asection *sec ATTRIBUTE_UNUSED; + bfd *output_bfd ATTRIBUTE_UNUSED; + char **error_message ATTRIBUTE_UNUSED; { return bfd_reloc_ok; } @@ -144,45 +155,45 @@ static reloc_howto_type alpha_howto_table[] = 0, /* rightshift */ 0, /* size (0 = byte, 1 = short, 2 = long) */ 8, /* bitsize */ - true, /* pc_relative */ + TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ reloc_nil, /* special_function */ "IGNORE", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ - true), /* pcrel_offset */ + TRUE), /* pcrel_offset */ /* A 32 bit reference to a symbol. */ HOWTO (ALPHA_R_REFLONG, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 32, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ 0, /* special_function */ "REFLONG", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0xffffffff, /* src_mask */ 0xffffffff, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* A 64 bit reference to a symbol. */ HOWTO (ALPHA_R_REFQUAD, /* type */ 0, /* rightshift */ 4, /* size (0 = byte, 1 = short, 2 = long) */ 64, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ 0, /* special_function */ "REFQUAD", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ MINUS_ONE, /* src_mask */ MINUS_ONE, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* A 32 bit GP relative offset. This is just like REFLONG except that when the value is used the value of the gp register will be @@ -191,15 +202,15 @@ static reloc_howto_type alpha_howto_table[] = 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 32, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ 0, /* special_function */ "GPREL32", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0xffffffff, /* src_mask */ 0xffffffff, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* Used for an instruction that refers to memory off the GP register. The offset is 16 bits of the 32 bit instruction. This @@ -208,15 +219,15 @@ static reloc_howto_type alpha_howto_table[] = 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ 0, /* special_function */ "LITERAL", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* This reloc only appears immediately following a LITERAL reloc. It identifies a use of the literal. It seems that the linker can @@ -231,15 +242,15 @@ static reloc_howto_type alpha_howto_table[] = 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 32, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ reloc_nil, /* special_function */ "LITUSE", /* name */ - false, /* partial_inplace */ + FALSE, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* Load the gp register. This is always used for a ldah instruction which loads the upper 16 bits of the gp register. The next reloc @@ -256,15 +267,15 @@ static reloc_howto_type alpha_howto_table[] = 16, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ - true, /* pc_relative */ + TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ reloc_nil, /* special_function */ "GPDISP", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ - true), /* pcrel_offset */ + TRUE), /* pcrel_offset */ /* A 21 bit branch. The native assembler generates these for branches within the text segment, and also fills in the PC @@ -273,90 +284,90 @@ static reloc_howto_type alpha_howto_table[] = 2, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 21, /* bitsize */ - true, /* pc_relative */ + TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ 0, /* special_function */ "BRADDR", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0x1fffff, /* src_mask */ 0x1fffff, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* A hint for a jump to a register. */ HOWTO (ALPHA_R_HINT, /* type */ 2, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 14, /* bitsize */ - true, /* pc_relative */ + TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ 0, /* special_function */ "HINT", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0x3fff, /* src_mask */ 0x3fff, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* 16 bit PC relative offset. */ HOWTO (ALPHA_R_SREL16, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ - true, /* pc_relative */ + TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ 0, /* special_function */ "SREL16", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* 32 bit PC relative offset. */ HOWTO (ALPHA_R_SREL32, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 32, /* bitsize */ - true, /* pc_relative */ + TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ 0, /* special_function */ "SREL32", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ 0xffffffff, /* src_mask */ 0xffffffff, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* A 64 bit PC relative offset. */ HOWTO (ALPHA_R_SREL64, /* type */ 0, /* rightshift */ 4, /* size (0 = byte, 1 = short, 2 = long) */ 64, /* bitsize */ - true, /* pc_relative */ + TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ 0, /* special_function */ "SREL64", /* name */ - true, /* partial_inplace */ + TRUE, /* partial_inplace */ MINUS_ONE, /* src_mask */ MINUS_ONE, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* Push a value on the reloc evaluation stack. */ HOWTO (ALPHA_R_OP_PUSH, /* type */ 0, /* rightshift */ 0, /* size (0 = byte, 1 = short, 2 = long) */ 0, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ 0, /* special_function */ "OP_PUSH", /* name */ - false, /* partial_inplace */ + FALSE, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* Store the value from the stack at the given address. Store it in a bitfield of size r_size starting at bit position r_offset. */ @@ -364,15 +375,15 @@ static reloc_howto_type alpha_howto_table[] = 0, /* rightshift */ 4, /* size (0 = byte, 1 = short, 2 = long) */ 64, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ 0, /* special_function */ "OP_STORE", /* name */ - false, /* partial_inplace */ + FALSE, /* partial_inplace */ 0, /* src_mask */ MINUS_ONE, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* Subtract the reloc address from the value on the top of the relocation stack. */ @@ -380,15 +391,15 @@ static reloc_howto_type alpha_howto_table[] = 0, /* rightshift */ 0, /* size (0 = byte, 1 = short, 2 = long) */ 0, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ 0, /* special_function */ "OP_PSUB", /* name */ - false, /* partial_inplace */ + FALSE, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* Shift the value on the top of the relocation stack right by the given value. */ @@ -396,30 +407,30 @@ static reloc_howto_type alpha_howto_table[] = 0, /* rightshift */ 0, /* size (0 = byte, 1 = short, 2 = long) */ 0, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ 0, /* special_function */ "OP_PRSHIFT", /* name */ - false, /* partial_inplace */ + FALSE, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ - false), /* pcrel_offset */ + FALSE), /* pcrel_offset */ /* Adjust the GP value for a new range in the object file. */ HOWTO (ALPHA_R_GPVALUE, /* type */ 0, /* rightshift */ 0, /* size (0 = byte, 1 = short, 2 = long) */ 0, /* bitsize */ - false, /* pc_relative */ + FALSE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ 0, /* special_function */ "GPVALUE", /* name */ - false, /* partial_inplace */ + FALSE, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ - false) /* pcrel_offset */ + FALSE) /* pcrel_offset */ }; /* Recognize an Alpha ECOFF file. */ @@ -451,8 +462,8 @@ alpha_ecoff_object_p (abfd) bfd_size_type size; size = sec->line_filepos * 8; - BFD_ASSERT (size == bfd_section_size (abfd, sec) - || size + 8 == bfd_section_size (abfd, sec)); + BFD_ASSERT (size == sec->size + || size + 8 == sec->size); if (! bfd_set_section_size (abfd, sec, size)) return NULL; } @@ -463,17 +474,17 @@ alpha_ecoff_object_p (abfd) /* See whether the magic number matches. */ -static boolean +static bfd_boolean alpha_ecoff_bad_format_hook (abfd, filehdr) - bfd *abfd; + bfd *abfd ATTRIBUTE_UNUSED; PTR filehdr; { struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr; if (ALPHA_ECOFF_BADMAG (*internal_f)) - return false; + return FALSE; - return true; + return TRUE; } /* This is a hook called by coff_real_object_p to create any backend @@ -522,10 +533,10 @@ alpha_ecoff_swap_reloc_in (abfd, ext_ptr, intern) { const RELOC *ext = (RELOC *) ext_ptr; - intern->r_vaddr = bfd_h_get_64 (abfd, (bfd_byte *) ext->r_vaddr); - intern->r_symndx = bfd_h_get_32 (abfd, (bfd_byte *) ext->r_symndx); + intern->r_vaddr = H_GET_64 (abfd, ext->r_vaddr); + intern->r_symndx = H_GET_32 (abfd, ext->r_symndx); - BFD_ASSERT (abfd->xvec->header_byteorder_big_p == false); + BFD_ASSERT (bfd_header_little_endian (abfd)); intern->r_type = ((ext->r_bits[0] & RELOC_BITS0_TYPE_LITTLE) >> RELOC_BITS0_TYPE_SH_LITTLE); @@ -595,10 +606,10 @@ alpha_ecoff_swap_reloc_out (abfd, intern, dst) BFD_ASSERT (intern->r_extern || (intern->r_symndx >= 0 && intern->r_symndx <= 14)); - bfd_h_put_64 (abfd, intern->r_vaddr, (bfd_byte *) ext->r_vaddr); - bfd_h_put_32 (abfd, symndx, (bfd_byte *) ext->r_symndx); + H_PUT_64 (abfd, intern->r_vaddr, ext->r_vaddr); + H_PUT_32 (abfd, symndx, ext->r_symndx); - BFD_ASSERT (abfd->xvec->header_byteorder_big_p == false); + BFD_ASSERT (bfd_header_little_endian (abfd)); ext->r_bits[0] = ((intern->r_type << RELOC_BITS0_TYPE_SH_LITTLE) & RELOC_BITS0_TYPE_LITTLE); @@ -629,9 +640,13 @@ alpha_adjust_reloc_in (abfd, intern, rptr) case ALPHA_R_SREL16: case ALPHA_R_SREL32: case ALPHA_R_SREL64: - /* The PC relative relocs do not seem to use the section VMA as - a negative addend. */ - rptr->addend = 0; + /* This relocs appear to be fully resolved when they are against + internal symbols. Against external symbols, BRADDR at least + appears to be resolved against the next instruction. */ + if (! intern->r_extern) + rptr->addend = 0; + else + rptr->addend = - (intern->r_vaddr + 4); break; case ALPHA_R_GPREL32: @@ -653,7 +668,7 @@ alpha_adjust_reloc_in (abfd, intern, rptr) case ALPHA_R_OP_STORE: /* The STORE reloc needs the size and offset fields. We store them in the addend. */ - BFD_ASSERT (intern->r_offset <= 256 && intern->r_size <= 256); + BFD_ASSERT (intern->r_offset <= 256); rptr->addend = (intern->r_offset << 8) + intern->r_size; break; @@ -696,7 +711,7 @@ alpha_adjust_reloc_in (abfd, intern, rptr) static void alpha_adjust_reloc_out (abfd, rel, intern) - bfd *abfd; + bfd *abfd ATTRIBUTE_UNUSED; const arelent *rel; struct internal_reloc *intern; { @@ -738,12 +753,12 @@ alpha_adjust_reloc_out (abfd, rel, intern) static bfd_byte * alpha_ecoff_get_relocated_section_contents (abfd, link_info, link_order, - data, relocateable, symbols) + data, relocatable, symbols) bfd *abfd; struct bfd_link_info *link_info; struct bfd_link_order *link_order; bfd_byte *data; - boolean relocateable; + bfd_boolean relocatable; asymbol **symbols; { bfd *input_bfd = link_order->u.indirect.section->owner; @@ -751,26 +766,23 @@ alpha_ecoff_get_relocated_section_contents (abfd, link_info, link_order, long reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section); arelent **reloc_vector = NULL; long reloc_count; - bfd *output_bfd = relocateable ? abfd : (bfd *) NULL; + bfd *output_bfd = relocatable ? abfd : (bfd *) NULL; bfd_vma gp; - boolean gp_undefined; + bfd_size_type sz; + bfd_boolean gp_undefined; bfd_vma stack[RELOC_STACKSIZE]; int tos = 0; if (reloc_size < 0) goto error_return; - reloc_vector = (arelent **) bfd_malloc (reloc_size); + reloc_vector = (arelent **) bfd_malloc ((bfd_size_type) reloc_size); if (reloc_vector == NULL && reloc_size != 0) goto error_return; - if (! bfd_get_section_contents (input_bfd, input_section, data, - (file_ptr) 0, input_section->_raw_size)) + sz = input_section->rawsize ? input_section->rawsize : input_section->size; + if (! bfd_get_section_contents (input_bfd, input_section, data, 0, sz)) goto error_return; - /* The section size is not going to change. */ - input_section->_cooked_size = input_section->_raw_size; - input_section->reloc_done = true; - reloc_count = bfd_canonicalize_reloc (input_bfd, input_section, reloc_vector, symbols); if (reloc_count < 0) @@ -779,10 +791,11 @@ alpha_ecoff_get_relocated_section_contents (abfd, link_info, link_order, goto successful_return; /* Get the GP value for the output BFD. */ - gp_undefined = false; - if (ecoff_data (abfd)->gp == 0) + gp_undefined = FALSE; + gp = _bfd_get_gp_value (abfd); + if (gp == 0) { - if (relocateable != false) + if (relocatable) { asection *sec; bfd_vma lo; @@ -799,24 +812,27 @@ alpha_ecoff_get_relocated_section_contents (abfd, link_info, link_order, || strcmp (sec->name, ".lita") == 0)) lo = sec->vma; } - ecoff_data (abfd)->gp = lo + 0x8000; + gp = lo + 0x8000; + _bfd_set_gp_value (abfd, gp); } else { struct bfd_link_hash_entry *h; - h = bfd_link_hash_lookup (link_info->hash, "_gp", false, false, - true); + h = bfd_link_hash_lookup (link_info->hash, "_gp", FALSE, FALSE, + TRUE); if (h == (struct bfd_link_hash_entry *) NULL || h->type != bfd_link_hash_defined) - gp_undefined = true; + gp_undefined = TRUE; else - ecoff_data (abfd)->gp = (h->u.def.value - + h->u.def.section->output_section->vma - + h->u.def.section->output_offset); + { + gp = (h->u.def.value + + h->u.def.section->output_section->vma + + h->u.def.section->output_offset); + _bfd_set_gp_value (abfd, gp); + } } } - gp = ecoff_data (abfd)->gp; for (; *reloc_vector != (arelent *) NULL; reloc_vector++) { @@ -839,7 +855,7 @@ alpha_ecoff_get_relocated_section_contents (abfd, link_info, link_order, case ALPHA_R_SREL16: case ALPHA_R_SREL32: case ALPHA_R_SREL64: - if (relocateable + if (relocatable && ((*rel->sym_ptr_ptr)->flags & BSF_SECTION_SYM) == 0) { rel->address += input_section->output_offset; @@ -862,7 +878,7 @@ alpha_ecoff_get_relocated_section_contents (abfd, link_info, link_order, if (r == bfd_reloc_ok && gp_undefined) { r = bfd_reloc_dangerous; - err = (char *) "GP relative relocation used when GP not defined"; + err = (char *) _("GP relative relocation used when GP not defined"); } break; @@ -899,7 +915,7 @@ alpha_ecoff_get_relocated_section_contents (abfd, link_info, link_order, { r = bfd_reloc_dangerous; err = - (char *) "GP relative relocation used when GP not defined"; + (char *) _("GP relative relocation used when GP not defined"); } } break; @@ -909,21 +925,17 @@ alpha_ecoff_get_relocated_section_contents (abfd, link_info, link_order, does not cause anything to happen, itself. */ rel->address += input_section->output_offset; break; - + case ALPHA_R_GPDISP: /* This marks the ldah of an ldah/lda pair which loads the gp register with the difference of the gp value and the current location. The second of the pair is r_size bytes - ahead, and is marked with an ALPHA_R_IGNORE reloc. */ + ahead; it used to be marked with an ALPHA_R_IGNORE reloc, + but that no longer happens in OSF/1 3.2. */ { unsigned long insn1, insn2; bfd_vma addend; - BFD_ASSERT (reloc_vector[1] != NULL - && reloc_vector[1]->howto->type == ALPHA_R_IGNORE - && (rel->address + rel->addend - == reloc_vector[1]->address)); - /* Get the two instructions. */ insn1 = bfd_get_32 (input_bfd, data + rel->address); insn2 = bfd_get_32 (input_bfd, data + rel->address + rel->addend); @@ -945,7 +957,7 @@ alpha_ecoff_get_relocated_section_contents (abfd, link_info, link_order, /* The existing addend includes the different between the gp of the input BFD and the address in the input BFD. Subtract this out. */ - addend -= (reloc_vector[1]->addend + addend -= (ecoff_data (input_bfd)->gp - (input_section->vma + rel->address)); /* Now add in the final gp value, and subtract out the @@ -969,14 +981,14 @@ alpha_ecoff_get_relocated_section_contents (abfd, link_info, link_order, rel->address += input_section->output_offset; } break; - + case ALPHA_R_OP_PUSH: /* Push a value on the reloc evaluation stack. */ { asymbol *symbol; bfd_vma relocation; - if (relocateable) + if (relocatable) { rel->address += input_section->output_offset; break; @@ -1009,7 +1021,7 @@ alpha_ecoff_get_relocated_section_contents (abfd, link_info, link_order, bfd_vma val; int offset, size; - if (relocateable) + if (relocatable) { rel->address += input_section->output_offset; break; @@ -1036,7 +1048,7 @@ alpha_ecoff_get_relocated_section_contents (abfd, link_info, link_order, asymbol *symbol; bfd_vma relocation; - if (relocateable) + if (relocatable) { rel->address += input_section->output_offset; break; @@ -1069,7 +1081,7 @@ alpha_ecoff_get_relocated_section_contents (abfd, link_info, link_order, asymbol *symbol; bfd_vma relocation; - if (relocateable) + if (relocatable) { rel->address += input_section->output_offset; break; @@ -1095,18 +1107,18 @@ alpha_ecoff_get_relocated_section_contents (abfd, link_info, link_order, stack[tos - 1] >>= relocation; } break; - + case ALPHA_R_GPVALUE: /* I really don't know if this does the right thing. */ gp = rel->addend; - gp_undefined = false; + gp_undefined = FALSE; break; default: abort (); } - if (relocateable) + if (relocatable) { asection *os = input_section->output_section; @@ -1115,17 +1127,17 @@ alpha_ecoff_get_relocated_section_contents (abfd, link_info, link_order, os->reloc_count++; } - if (r != bfd_reloc_ok) + if (r != bfd_reloc_ok) { switch (r) { case bfd_reloc_undefined: if (! ((*link_info->callbacks->undefined_symbol) (link_info, bfd_asymbol_name (*rel->sym_ptr_ptr), - input_bfd, input_section, rel->address))) + input_bfd, input_section, rel->address, TRUE))) goto error_return; break; - case bfd_reloc_dangerous: + case bfd_reloc_dangerous: if (! ((*link_info->callbacks->reloc_dangerous) (link_info, err, input_bfd, input_section, rel->address))) @@ -1133,7 +1145,8 @@ alpha_ecoff_get_relocated_section_contents (abfd, link_info, link_order, break; case bfd_reloc_overflow: if (! ((*link_info->callbacks->reloc_overflow) - (link_info, bfd_asymbol_name (*rel->sym_ptr_ptr), + (link_info, NULL, + bfd_asymbol_name (*rel->sym_ptr_ptr), rel->howto->name, rel->addend, input_bfd, input_section, rel->address))) goto error_return; @@ -1164,7 +1177,7 @@ alpha_ecoff_get_relocated_section_contents (abfd, link_info, link_order, static reloc_howto_type * alpha_bfd_reloc_type_lookup (abfd, code) - bfd *abfd; + bfd *abfd ATTRIBUTE_UNUSED; bfd_reloc_code_real_type code; { int alpha_type; @@ -1208,23 +1221,6 @@ alpha_bfd_reloc_type_lookup (abfd, code) case BFD_RELOC_64_PCREL: alpha_type = ALPHA_R_SREL64; break; -#if 0 - case ???: - alpha_type = ALPHA_R_OP_PUSH; - break; - case ???: - alpha_type = ALPHA_R_OP_STORE; - break; - case ???: - alpha_type = ALPHA_R_OP_PSUB; - break; - case ???: - alpha_type = ALPHA_R_OP_PRSHIFT; - break; - case ???: - alpha_type = ALPHA_R_GPVALUE; - break; -#endif default: return (reloc_howto_type *) NULL; } @@ -1233,12 +1229,12 @@ alpha_bfd_reloc_type_lookup (abfd, code) } /* A helper routine for alpha_relocate_section which converts an - external reloc when generating relocateable output. Returns the + external reloc when generating relocatable output. Returns the relocation amount. */ static bfd_vma alpha_convert_external_reloc (output_bfd, info, input_bfd, ext_rel, h) - bfd *output_bfd; + bfd *output_bfd ATTRIBUTE_UNUSED; struct bfd_link_info *info; bfd *input_bfd; struct external_reloc *ext_rel; @@ -1247,7 +1243,7 @@ alpha_convert_external_reloc (output_bfd, info, input_bfd, ext_rel, h) unsigned long r_symndx; bfd_vma relocation; - BFD_ASSERT (info->relocateable); + BFD_ASSERT (info->relocatable); if (h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) @@ -1265,7 +1261,7 @@ alpha_convert_external_reloc (output_bfd, info, input_bfd, ext_rel, h) hsec = h->root.u.def.section; name = bfd_get_section_name (output_bfd, hsec->output_section); - r_symndx = -1; + r_symndx = (unsigned long) -1; switch (name[1]) { case 'A': @@ -1321,8 +1317,8 @@ alpha_convert_external_reloc (output_bfd, info, input_bfd, ext_rel, h) r_symndx = RELOC_SECTION_XDATA; break; } - - if (r_symndx == -1) + + if (r_symndx == (unsigned long) -1) abort (); /* Add the section VMA and the symbol value. */ @@ -1335,7 +1331,7 @@ alpha_convert_external_reloc (output_bfd, info, input_bfd, ext_rel, h) /* Change the symndx value to the right one for the output BFD. */ r_symndx = h->indx; - if (r_symndx == -1) + if (r_symndx == (unsigned long) -1) { /* Caller must give an error. */ r_symndx = 0; @@ -1344,8 +1340,7 @@ alpha_convert_external_reloc (output_bfd, info, input_bfd, ext_rel, h) } /* Write out the new r_symndx value. */ - bfd_h_put_32 (input_bfd, (bfd_vma) r_symndx, - (bfd_byte *) ext_rel->r_symndx); + H_PUT_32 (input_bfd, r_symndx, ext_rel->r_symndx); return relocation; } @@ -1354,7 +1349,7 @@ alpha_convert_external_reloc (output_bfd, info, input_bfd, ext_rel, h) quite similar to get_relocated_section_contents. Perhaps they could be combined somehow. */ -static boolean +static bfd_boolean alpha_relocate_section (output_bfd, info, input_bfd, input_section, contents, external_relocs) bfd *output_bfd; @@ -1364,14 +1359,15 @@ alpha_relocate_section (output_bfd, info, input_bfd, input_section, bfd_byte *contents; PTR external_relocs; { - asection **symndx_to_section; + asection **symndx_to_section, *lita_sec; struct ecoff_link_hash_entry **sym_hashes; bfd_vma gp; - boolean gp_undefined; + bfd_boolean gp_undefined; bfd_vma stack[RELOC_STACKSIZE]; int tos = 0; struct external_reloc *ext_rel; struct external_reloc *ext_rel_end; + bfd_size_type amt; /* We keep a table mapping the symndx found in an internal reloc to the appropriate section. This is faster than looking up the @@ -1379,12 +1375,10 @@ alpha_relocate_section (output_bfd, info, input_bfd, input_section, symndx_to_section = ecoff_data (input_bfd)->symndx_to_section; if (symndx_to_section == (asection **) NULL) { - symndx_to_section = ((asection **) - bfd_alloc (input_bfd, - (NUM_RELOC_SECTIONS - * sizeof (asection *)))); + amt = NUM_RELOC_SECTIONS * sizeof (asection *); + symndx_to_section = (asection **) bfd_alloc (input_bfd, amt); if (!symndx_to_section) - return false; + return FALSE; symndx_to_section[RELOC_SECTION_NONE] = NULL; symndx_to_section[RELOC_SECTION_TEXT] = @@ -1422,14 +1416,76 @@ alpha_relocate_section (output_bfd, info, input_bfd, input_section, sym_hashes = ecoff_data (input_bfd)->sym_hashes; - gp = ecoff_data (output_bfd)->gp; - if (gp == 0) - gp_undefined = true; - else - gp_undefined = false; + /* On the Alpha, the .lita section must be addressable by the global + pointer. To support large programs, we need to allow multiple + global pointers. This works as long as each input .lita section + is <64KB big. This implies that when producing relocatable + output, the .lita section is limited to 64KB. . */ + + lita_sec = symndx_to_section[RELOC_SECTION_LITA]; + gp = _bfd_get_gp_value (output_bfd); + if (! info->relocatable && lita_sec != NULL) + { + struct ecoff_section_tdata *lita_sec_data; + + /* Make sure we have a section data structure to which we can + hang on to the gp value we pick for the section. */ + lita_sec_data = ecoff_section_data (input_bfd, lita_sec); + if (lita_sec_data == NULL) + { + amt = sizeof (struct ecoff_section_tdata); + lita_sec_data = ((struct ecoff_section_tdata *) + bfd_zalloc (input_bfd, amt)); + lita_sec->used_by_bfd = lita_sec_data; + } + + if (lita_sec_data->gp != 0) + { + /* If we already assigned a gp to this section, we better + stick with that value. */ + gp = lita_sec_data->gp; + } + else + { + bfd_vma lita_vma; + bfd_size_type lita_size; - BFD_ASSERT (output_bfd->xvec->header_byteorder_big_p == false); - BFD_ASSERT (input_bfd->xvec->header_byteorder_big_p == false); + lita_vma = lita_sec->output_offset + lita_sec->output_section->vma; + lita_size = lita_sec->size; + + if (gp == 0 + || lita_vma < gp - 0x8000 + || lita_vma + lita_size >= gp + 0x8000) + { + /* Either gp hasn't been set at all or the current gp + cannot address this .lita section. In both cases we + reset the gp to point into the "middle" of the + current input .lita section. */ + if (gp && !ecoff_data (output_bfd)->issued_multiple_gp_warning) + { + (*info->callbacks->warning) (info, + _("using multiple gp values"), + (char *) NULL, output_bfd, + (asection *) NULL, (bfd_vma) 0); + ecoff_data (output_bfd)->issued_multiple_gp_warning = TRUE; + } + if (lita_vma < gp - 0x8000) + gp = lita_vma + lita_size - 0x8000; + else + gp = lita_vma + 0x8000; + + } + + lita_sec_data->gp = gp; + } + + _bfd_set_gp_value (output_bfd, gp); + } + + gp_undefined = (gp == 0); + + BFD_ASSERT (bfd_header_little_endian (output_bfd)); + BFD_ASSERT (bfd_header_little_endian (input_bfd)); ext_rel = (struct external_reloc *) external_relocs; ext_rel_end = ext_rel + input_section->reloc_count; @@ -1441,13 +1497,13 @@ alpha_relocate_section (output_bfd, info, input_bfd, input_section, int r_extern; int r_offset; int r_size; - boolean relocatep; - boolean adjust_addrp; - boolean gp_usedp; + bfd_boolean relocatep; + bfd_boolean adjust_addrp; + bfd_boolean gp_usedp; bfd_vma addend; - r_vaddr = bfd_h_get_64 (input_bfd, (bfd_byte *) ext_rel->r_vaddr); - r_symndx = bfd_h_get_32 (input_bfd, (bfd_byte *) ext_rel->r_symndx); + r_vaddr = H_GET_64 (input_bfd, ext_rel->r_vaddr); + r_symndx = H_GET_32 (input_bfd, ext_rel->r_symndx); r_type = ((ext_rel->r_bits[0] & RELOC_BITS0_TYPE_LITTLE) >> RELOC_BITS0_TYPE_SH_LITTLE); @@ -1458,9 +1514,9 @@ alpha_relocate_section (output_bfd, info, input_bfd, input_section, r_size = ((ext_rel->r_bits[3] & RELOC_BITS3_SIZE_LITTLE) >> RELOC_BITS3_SIZE_SH_LITTLE); - relocatep = false; - adjust_addrp = true; - gp_usedp = false; + relocatep = FALSE; + adjust_addrp = TRUE; + gp_usedp = FALSE; addend = 0; switch (r_type) @@ -1469,27 +1525,31 @@ alpha_relocate_section (output_bfd, info, input_bfd, input_section, abort (); case ALPHA_R_IGNORE: - /* This reloc appears after a GPDISP reloc. It marks the - position of the second instruction to be altered by the - GPDISP reloc, but is not otherwise used for anything. - For some reason, the address of the relocation does not - appear to include the section VMA, unlike the other - relocation types. */ - if (info->relocateable) - bfd_h_put_64 (input_bfd, - input_section->output_offset + r_vaddr, - (bfd_byte *) ext_rel->r_vaddr); - adjust_addrp = false; + /* This reloc appears after a GPDISP reloc. On earlier + versions of OSF/1, It marked the position of the second + instruction to be altered by the GPDISP reloc, but it is + not otherwise used for anything. For some reason, the + address of the relocation does not appear to include the + section VMA, unlike the other relocation types. */ + if (info->relocatable) + H_PUT_64 (input_bfd, input_section->output_offset + r_vaddr, + ext_rel->r_vaddr); + adjust_addrp = FALSE; break; case ALPHA_R_REFLONG: case ALPHA_R_REFQUAD: - case ALPHA_R_BRADDR: case ALPHA_R_HINT: + relocatep = TRUE; + break; + + case ALPHA_R_BRADDR: case ALPHA_R_SREL16: case ALPHA_R_SREL32: case ALPHA_R_SREL64: - relocatep = true; + if (r_extern) + addend += - (r_vaddr + 4); + relocatep = TRUE; break; case ALPHA_R_GPREL32: @@ -1497,9 +1557,9 @@ alpha_relocate_section (output_bfd, info, input_bfd, input_section, bit offset from the current GP value. We must adjust it by the different between the original GP value and the current GP value. */ - relocatep = true; + relocatep = TRUE; addend = ecoff_data (input_bfd)->gp - gp; - gp_usedp = true; + gp_usedp = TRUE; break; case ALPHA_R_LITERAL: @@ -1530,33 +1590,25 @@ alpha_relocate_section (output_bfd, info, input_bfd, input_section, || ((insn >> 26) & 0x3f) == 0x28); } - relocatep = true; + relocatep = TRUE; addend = ecoff_data (input_bfd)->gp - gp; - gp_usedp = true; + gp_usedp = TRUE; break; case ALPHA_R_LITUSE: /* See ALPHA_R_LITERAL above for the uses of this reloc. It does not cause anything to happen, itself. */ break; - + case ALPHA_R_GPDISP: /* This marks the ldah of an ldah/lda pair which loads the gp register with the difference of the gp value and the current location. The second of the pair is r_symndx - bytes ahead, and is also marked with an ALPHA_R_IGNORE - reloc. */ + bytes ahead. It used to be marked with an ALPHA_R_IGNORE + reloc, but OSF/1 3.2 no longer does that. */ { unsigned long insn1, insn2; - BFD_ASSERT (ext_rel + 1 < ext_rel_end - && (((ext_rel + 1)->r_bits[0] - & RELOC_BITS0_TYPE_LITTLE) - >> RELOC_BITS0_TYPE_SH_LITTLE) == ALPHA_R_IGNORE - && (bfd_h_get_64 (input_bfd, - (bfd_byte *) (ext_rel + 1)->r_vaddr) - == r_vaddr - input_section->vma + r_symndx)); - /* Get the two instructions. */ insn1 = bfd_get_32 (input_bfd, contents + r_vaddr - input_section->vma); @@ -1604,10 +1656,10 @@ alpha_relocate_section (output_bfd, info, input_bfd, input_section, bfd_put_32 (input_bfd, (bfd_vma) insn2, contents + r_vaddr - input_section->vma + r_symndx); - gp_usedp = true; + gp_usedp = TRUE; } break; - + case ALPHA_R_OP_PUSH: case ALPHA_R_OP_PSUB: case ALPHA_R_OP_PRSHIFT: @@ -1632,7 +1684,7 @@ alpha_relocate_section (output_bfd, info, input_bfd, input_section, if (h == (struct ecoff_link_hash_entry *) NULL) abort (); - if (! info->relocateable) + if (! info->relocatable) { if (h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) @@ -1647,8 +1699,8 @@ alpha_relocate_section (output_bfd, info, input_bfd, input_section, relocated. */ if (! ((*info->callbacks->undefined_symbol) (info, h->root.root.string, input_bfd, - input_section, (bfd_vma) 0))) - return false; + input_section, (bfd_vma) 0, TRUE))) + return FALSE; addend = 0; } } @@ -1664,7 +1716,7 @@ alpha_relocate_section (output_bfd, info, input_bfd, input_section, if (! ((*info->callbacks->unattached_reloc) (info, h->root.root.string, input_bfd, input_section, (bfd_vma) 0))) - return false; + return FALSE; } addend = alpha_convert_external_reloc (output_bfd, info, @@ -1675,11 +1727,10 @@ alpha_relocate_section (output_bfd, info, input_bfd, input_section, addend += r_vaddr; - if (info->relocateable) + if (info->relocatable) { /* Adjust r_vaddr by the addend. */ - bfd_h_put_64 (input_bfd, addend, - (bfd_byte *) ext_rel->r_vaddr); + H_PUT_64 (input_bfd, addend, ext_rel->r_vaddr); } else { @@ -1705,14 +1756,14 @@ alpha_relocate_section (output_bfd, info, input_bfd, input_section, } } - adjust_addrp = false; + adjust_addrp = FALSE; break; case ALPHA_R_OP_STORE: /* Store a value from the reloc stack into a bitfield. If - we are generating relocateable output, all we do is + we are generating relocatable output, all we do is adjust the address of the reloc. */ - if (! info->relocateable) + if (! info->relocatable) { bfd_vma mask; bfd_vma val; @@ -1742,7 +1793,7 @@ alpha_relocate_section (output_bfd, info, input_bfd, input_section, case ALPHA_R_GPVALUE: /* I really don't know if this does the right thing. */ gp = ecoff_data (input_bfd)->gp + r_symndx; - gp_undefined = false; + gp_undefined = FALSE; break; } @@ -1778,9 +1829,9 @@ alpha_relocate_section (output_bfd, info, input_bfd, input_section, abort (); } - if (info->relocateable) + if (info->relocatable) { - /* We are generating relocateable output, and must + /* We are generating relocatable output, and must convert the existing reloc. */ if (r_extern) { @@ -1792,7 +1843,7 @@ alpha_relocate_section (output_bfd, info, input_bfd, input_section, if (! ((*info->callbacks->unattached_reloc) (info, h->root.root.string, input_bfd, input_section, r_vaddr - input_section->vma))) - return false; + return FALSE; } relocation = alpha_convert_external_reloc (output_bfd, @@ -1849,8 +1900,8 @@ alpha_relocate_section (output_bfd, info, input_bfd, input_section, if (! ((*info->callbacks->undefined_symbol) (info, h->root.root.string, input_bfd, input_section, - r_vaddr - input_section->vma))) - return false; + r_vaddr - input_section->vma, TRUE))) + return FALSE; relocation = 0; } } @@ -1893,60 +1944,289 @@ alpha_relocate_section (output_bfd, info, input_bfd, input_section, name = bfd_section_name (input_bfd, symndx_to_section[r_symndx]); if (! ((*info->callbacks->reloc_overflow) - (info, name, alpha_howto_table[r_type].name, + (info, NULL, name, + alpha_howto_table[r_type].name, (bfd_vma) 0, input_bfd, input_section, r_vaddr - input_section->vma))) - return false; + return FALSE; } break; } } } - if (info->relocateable && adjust_addrp) + if (info->relocatable && adjust_addrp) { /* Change the address of the relocation. */ - bfd_h_put_64 (input_bfd, - (input_section->output_section->vma - + input_section->output_offset - - input_section->vma - + r_vaddr), - (bfd_byte *) ext_rel->r_vaddr); + H_PUT_64 (input_bfd, + (input_section->output_section->vma + + input_section->output_offset + - input_section->vma + + r_vaddr), + ext_rel->r_vaddr); } if (gp_usedp && gp_undefined) { if (! ((*info->callbacks->reloc_dangerous) - (info, "GP relative relocation when GP not defined", + (info, _("GP relative relocation used when GP not defined"), input_bfd, input_section, r_vaddr - input_section->vma))) - return false; + return FALSE; /* Only give the error once per link. */ - ecoff_data (output_bfd)->gp = gp = 4; - gp_undefined = false; + gp = 4; + _bfd_set_gp_value (output_bfd, gp); + gp_undefined = FALSE; } } if (tos != 0) abort (); - return true; + return TRUE; } /* Do final adjustments to the filehdr and the aouthdr. This routine sets the dynamic bits in the file header. */ -/*ARGSUSED*/ -static boolean +static bfd_boolean alpha_adjust_headers (abfd, fhdr, ahdr) bfd *abfd; struct internal_filehdr *fhdr; - struct internal_aouthdr *ahdr; + struct internal_aouthdr *ahdr ATTRIBUTE_UNUSED; { if ((abfd->flags & (DYNAMIC | EXEC_P)) == (DYNAMIC | EXEC_P)) fhdr->f_flags |= F_ALPHA_CALL_SHARED; else if ((abfd->flags & DYNAMIC) != 0) fhdr->f_flags |= F_ALPHA_SHARABLE; - return true; + return TRUE; +} + +/* Archive handling. In OSF/1 (or Digital Unix) v3.2, Digital + introduced archive packing, in which the elements in an archive are + optionally compressed using a simple dictionary scheme. We know + how to read such archives, but we don't write them. */ + +#define alpha_ecoff_slurp_armap _bfd_ecoff_slurp_armap +#define alpha_ecoff_slurp_extended_name_table \ + _bfd_ecoff_slurp_extended_name_table +#define alpha_ecoff_construct_extended_name_table \ + _bfd_ecoff_construct_extended_name_table +#define alpha_ecoff_truncate_arname _bfd_ecoff_truncate_arname +#define alpha_ecoff_write_armap _bfd_ecoff_write_armap +#define alpha_ecoff_generic_stat_arch_elt _bfd_ecoff_generic_stat_arch_elt +#define alpha_ecoff_update_armap_timestamp _bfd_ecoff_update_armap_timestamp + +/* A compressed file uses this instead of ARFMAG. */ + +#define ARFZMAG "Z\012" + +/* Read an archive header. This is like the standard routine, but it + also accepts ARFZMAG. */ + +static PTR +alpha_ecoff_read_ar_hdr (abfd) + bfd *abfd; +{ + struct areltdata *ret; + struct ar_hdr *h; + + ret = (struct areltdata *) _bfd_generic_read_ar_hdr_mag (abfd, ARFZMAG); + if (ret == NULL) + return NULL; + + h = (struct ar_hdr *) ret->arch_header; + if (strncmp (h->ar_fmag, ARFZMAG, 2) == 0) + { + bfd_byte ab[8]; + + /* This is a compressed file. We must set the size correctly. + The size is the eight bytes after the dummy file header. */ + if (bfd_seek (abfd, (file_ptr) FILHSZ, SEEK_CUR) != 0 + || bfd_bread (ab, (bfd_size_type) 8, abfd) != 8 + || bfd_seek (abfd, (file_ptr) (- (FILHSZ + 8)), SEEK_CUR) != 0) + return NULL; + + ret->parsed_size = H_GET_64 (abfd, ab); + } + + return (PTR) ret; +} + +/* Get an archive element at a specified file position. This is where + we uncompress the archive element if necessary. */ + +static bfd * +alpha_ecoff_get_elt_at_filepos (archive, filepos) + bfd *archive; + file_ptr filepos; +{ + bfd *nbfd = NULL; + struct areltdata *tdata; + struct ar_hdr *hdr; + bfd_byte ab[8]; + bfd_size_type size; + bfd_byte *buf, *p; + struct bfd_in_memory *bim; + + nbfd = _bfd_get_elt_at_filepos (archive, filepos); + if (nbfd == NULL) + goto error_return; + + if ((nbfd->flags & BFD_IN_MEMORY) != 0) + { + /* We have already expanded this BFD. */ + return nbfd; + } + + tdata = (struct areltdata *) nbfd->arelt_data; + hdr = (struct ar_hdr *) tdata->arch_header; + if (strncmp (hdr->ar_fmag, ARFZMAG, 2) != 0) + return nbfd; + + /* We must uncompress this element. We do this by copying it into a + memory buffer, and making bfd_bread and bfd_seek use that buffer. + This can use a lot of memory, but it's simpler than getting a + temporary file, making that work with the file descriptor caching + code, and making sure that it is deleted at all appropriate + times. It can be changed if it ever becomes important. */ + + /* The compressed file starts with a dummy ECOFF file header. */ + if (bfd_seek (nbfd, (file_ptr) FILHSZ, SEEK_SET) != 0) + goto error_return; + + /* The next eight bytes are the real file size. */ + if (bfd_bread (ab, (bfd_size_type) 8, nbfd) != 8) + goto error_return; + size = H_GET_64 (nbfd, ab); + + if (size == 0) + buf = NULL; + else + { + bfd_size_type left; + bfd_byte dict[4096]; + unsigned int h; + bfd_byte b; + + buf = (bfd_byte *) bfd_alloc (nbfd, size); + if (buf == NULL) + goto error_return; + p = buf; + + left = size; + + /* I don't know what the next eight bytes are for. */ + if (bfd_bread (ab, (bfd_size_type) 8, nbfd) != 8) + goto error_return; + + /* This is the uncompression algorithm. It's a simple + dictionary based scheme in which each character is predicted + by a hash of the previous three characters. A control byte + indicates whether the character is predicted or whether it + appears in the input stream; each control byte manages the + next eight bytes in the output stream. */ + memset (dict, 0, sizeof dict); + h = 0; + while (bfd_bread (&b, (bfd_size_type) 1, nbfd) == 1) + { + unsigned int i; + + for (i = 0; i < 8; i++, b >>= 1) + { + bfd_byte n; + + if ((b & 1) == 0) + n = dict[h]; + else + { + if (! bfd_bread (&n, (bfd_size_type) 1, nbfd)) + goto error_return; + dict[h] = n; + } + + *p++ = n; + + --left; + if (left == 0) + break; + + h <<= 4; + h ^= n; + h &= sizeof dict - 1; + } + + if (left == 0) + break; + } + } + + /* Now the uncompressed file contents are in buf. */ + bim = ((struct bfd_in_memory *) + bfd_alloc (nbfd, (bfd_size_type) sizeof (struct bfd_in_memory))); + if (bim == NULL) + goto error_return; + bim->size = size; + bim->buffer = buf; + + nbfd->mtime_set = TRUE; + nbfd->mtime = strtol (hdr->ar_date, (char **) NULL, 10); + + nbfd->flags |= BFD_IN_MEMORY; + nbfd->iostream = (PTR) bim; + BFD_ASSERT (! nbfd->cacheable); + + return nbfd; + + error_return: + if (nbfd != NULL) + bfd_close (nbfd); + return NULL; +} + +/* Open the next archived file. */ + +static bfd * +alpha_ecoff_openr_next_archived_file (archive, last_file) + bfd *archive; + bfd *last_file; +{ + file_ptr filestart; + + if (last_file == NULL) + filestart = bfd_ardata (archive)->first_file_filepos; + else + { + struct areltdata *t; + struct ar_hdr *h; + bfd_size_type size; + + /* We can't use arelt_size here, because that uses parsed_size, + which is the uncompressed size. We need the compressed size. */ + t = (struct areltdata *) last_file->arelt_data; + h = (struct ar_hdr *) t->arch_header; + size = strtol (h->ar_size, (char **) NULL, 10); + + /* Pad to an even boundary... + Note that last_file->origin can be odd in the case of + BSD-4.4-style element with a long odd size. */ + filestart = last_file->origin + size; + filestart += filestart % 2; + } + + return alpha_ecoff_get_elt_at_filepos (archive, filestart); +} + +/* Open the archive file given an index into the armap. */ + +static bfd * +alpha_ecoff_get_elt_at_index (abfd, index) + bfd *abfd; + symindex index; +{ + carsym *entry; + + entry = bfd_ardata (abfd)->symdefs + index; + return alpha_ecoff_get_elt_at_filepos (abfd, entry->file_offset); } /* This is the ECOFF backend structure. The backend field of the @@ -1965,13 +2245,14 @@ static const struct ecoff_backend_data alpha_ecoff_backend_data = (unsigned (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* reloc_out */ alpha_ecoff_swap_filehdr_out, alpha_ecoff_swap_aouthdr_out, alpha_ecoff_swap_scnhdr_out, - FILHSZ, AOUTSZ, SCNHSZ, 0, 0, 0, 0, true, + FILHSZ, AOUTSZ, SCNHSZ, 0, 0, 0, 0, FILNMLEN, TRUE, FALSE, 4, FALSE, 2, alpha_ecoff_swap_filehdr_in, alpha_ecoff_swap_aouthdr_in, alpha_ecoff_swap_scnhdr_in, NULL, alpha_ecoff_bad_format_hook, _bfd_ecoff_set_arch_mach_hook, alpha_ecoff_mkobject_hook, _bfd_ecoff_styp_to_sec_flags, _bfd_ecoff_set_alignment_hook, _bfd_ecoff_slurp_symbol_table, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL }, /* Supported architecture. */ bfd_arch_alpha, @@ -1980,10 +2261,10 @@ static const struct ecoff_backend_data alpha_ecoff_backend_data = /* The page boundary used to align sections in a demand-paged executable file. E.g., 0x1000. */ 0x2000, - /* True if the .rdata section is part of the text segment, as on the - Alpha. False if .rdata is part of the data segment, as on the + /* TRUE if the .rdata section is part of the text segment, as on the + Alpha. FALSE if .rdata is part of the data segment, as on the MIPS. */ - true, + TRUE, /* Bitsize of constructor entries. */ 64, /* Reloc to use for constructor entries. */ @@ -2038,7 +2319,9 @@ static const struct ecoff_backend_data alpha_ecoff_backend_data = /* Relocate section contents while linking. */ alpha_relocate_section, /* Do final adjustments to filehdr and aouthdr. */ - alpha_adjust_headers + alpha_adjust_headers, + /* Read an element from an archive at a given file position. */ + alpha_ecoff_get_elt_at_filepos }; /* Looking up a reloc type is Alpha specific. */ @@ -2054,13 +2337,19 @@ static const struct ecoff_backend_data alpha_ecoff_backend_data = /* Relaxing sections is generic. */ #define _bfd_ecoff_bfd_relax_section bfd_generic_relax_section +#define _bfd_ecoff_bfd_gc_sections bfd_generic_gc_sections +#define _bfd_ecoff_bfd_merge_sections bfd_generic_merge_sections +#define _bfd_ecoff_bfd_is_group_section bfd_generic_is_group_section +#define _bfd_ecoff_bfd_discard_group bfd_generic_discard_group +#define _bfd_ecoff_section_already_linked \ + _bfd_generic_section_already_linked const bfd_target ecoffalpha_little_vec = { "ecoff-littlealpha", /* name */ bfd_target_ecoff_flavour, - false, /* data byte order is little */ - false, /* header byte order is little */ + BFD_ENDIAN_LITTLE, /* data byte order is little */ + BFD_ENDIAN_LITTLE, /* header byte order is little */ (HAS_RELOC | EXEC_P | /* object flags */ HAS_LINENO | HAS_DEBUG | @@ -2087,12 +2376,14 @@ const bfd_target ecoffalpha_little_vec = BFD_JUMP_TABLE_GENERIC (_bfd_ecoff), BFD_JUMP_TABLE_COPY (_bfd_ecoff), BFD_JUMP_TABLE_CORE (_bfd_nocore), - BFD_JUMP_TABLE_ARCHIVE (_bfd_ecoff), + BFD_JUMP_TABLE_ARCHIVE (alpha_ecoff), BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff), BFD_JUMP_TABLE_RELOCS (_bfd_ecoff), BFD_JUMP_TABLE_WRITE (_bfd_ecoff), BFD_JUMP_TABLE_LINK (_bfd_ecoff), BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), + NULL, + (PTR) &alpha_ecoff_backend_data };