133965Sjdp/* BFD back-end for ALPHA Extended-Coff files. 2218822Sdim Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 3218822Sdim 2003, 2004, 2005, 2007 Free Software Foundation, Inc. 433965Sjdp Modified from coff-mips.c by Steve Chamberlain <sac@cygnus.com> and 533965Sjdp Ian Lance Taylor <ian@cygnus.com>. 633965Sjdp 733965SjdpThis file is part of BFD, the Binary File Descriptor library. 833965Sjdp 933965SjdpThis program is free software; you can redistribute it and/or modify 1033965Sjdpit under the terms of the GNU General Public License as published by 1133965Sjdpthe Free Software Foundation; either version 2 of the License, or 1233965Sjdp(at your option) any later version. 1333965Sjdp 1433965SjdpThis program is distributed in the hope that it will be useful, 1533965Sjdpbut WITHOUT ANY WARRANTY; without even the implied warranty of 1633965SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1733965SjdpGNU General Public License for more details. 1833965Sjdp 1933965SjdpYou should have received a copy of the GNU General Public License 2033965Sjdpalong with this program; if not, write to the Free Software 21218822SdimFoundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 2233965Sjdp 23218822Sdim#include "sysdep.h" 2433965Sjdp#include "bfd.h" 2533965Sjdp#include "bfdlink.h" 2633965Sjdp#include "libbfd.h" 2733965Sjdp#include "coff/internal.h" 2833965Sjdp#include "coff/sym.h" 2933965Sjdp#include "coff/symconst.h" 3033965Sjdp#include "coff/ecoff.h" 3133965Sjdp#include "coff/alpha.h" 3233965Sjdp#include "aout/ar.h" 3333965Sjdp#include "libcoff.h" 3433965Sjdp#include "libecoff.h" 3533965Sjdp 3633965Sjdp/* Prototypes for static functions. */ 3733965Sjdp 38130561Sobrienstatic const bfd_target *alpha_ecoff_object_p 39130561Sobrien PARAMS ((bfd *)); 40130561Sobrienstatic bfd_boolean alpha_ecoff_bad_format_hook 41130561Sobrien PARAMS ((bfd *abfd, PTR filehdr)); 42130561Sobrienstatic PTR alpha_ecoff_mkobject_hook 43130561Sobrien PARAMS ((bfd *, PTR filehdr, PTR aouthdr)); 44130561Sobrienstatic void alpha_ecoff_swap_reloc_in 45130561Sobrien PARAMS ((bfd *, PTR, struct internal_reloc *)); 46130561Sobrienstatic void alpha_ecoff_swap_reloc_out 47130561Sobrien PARAMS ((bfd *, const struct internal_reloc *, PTR)); 48130561Sobrienstatic void alpha_adjust_reloc_in 49130561Sobrien PARAMS ((bfd *, const struct internal_reloc *, arelent *)); 50130561Sobrienstatic void alpha_adjust_reloc_out 51130561Sobrien PARAMS ((bfd *, const arelent *, struct internal_reloc *)); 5233965Sjdpstatic reloc_howto_type *alpha_bfd_reloc_type_lookup 53130561Sobrien PARAMS ((bfd *, bfd_reloc_code_real_type)); 5433965Sjdpstatic bfd_byte *alpha_ecoff_get_relocated_section_contents 5533965Sjdp PARAMS ((bfd *abfd, struct bfd_link_info *, struct bfd_link_order *, 56130561Sobrien bfd_byte *data, bfd_boolean relocatable, asymbol **symbols)); 5733965Sjdpstatic bfd_vma alpha_convert_external_reloc 5833965Sjdp PARAMS ((bfd *, struct bfd_link_info *, bfd *, struct external_reloc *, 5933965Sjdp struct ecoff_link_hash_entry *)); 60130561Sobrienstatic bfd_boolean alpha_relocate_section 61130561Sobrien PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, PTR)); 62130561Sobrienstatic bfd_boolean alpha_adjust_headers 6333965Sjdp PARAMS ((bfd *, struct internal_filehdr *, struct internal_aouthdr *)); 64130561Sobrienstatic PTR alpha_ecoff_read_ar_hdr 65130561Sobrien PARAMS ((bfd *)); 66130561Sobrienstatic bfd *alpha_ecoff_get_elt_at_filepos 67130561Sobrien PARAMS ((bfd *, file_ptr)); 68130561Sobrienstatic bfd *alpha_ecoff_openr_next_archived_file 69130561Sobrien PARAMS ((bfd *, bfd *)); 70130561Sobrienstatic bfd *alpha_ecoff_get_elt_at_index 71130561Sobrien PARAMS ((bfd *, symindex)); 7233965Sjdp 7333965Sjdp/* ECOFF has COFF sections, but the debugging information is stored in 7433965Sjdp a completely different format. ECOFF targets use some of the 7533965Sjdp swapping routines from coffswap.h, and some of the generic COFF 7633965Sjdp routines in coffgen.c, but, unlike the real COFF targets, do not 7733965Sjdp use coffcode.h itself. 7833965Sjdp 7933965Sjdp Get the generic COFF swapping routines, except for the reloc, 8033965Sjdp symbol, and lineno ones. Give them ecoff names. Define some 8133965Sjdp accessor macros for the large sizes used for Alpha ECOFF. */ 8233965Sjdp 8389857Sobrien#define GET_FILEHDR_SYMPTR H_GET_64 8489857Sobrien#define PUT_FILEHDR_SYMPTR H_PUT_64 8589857Sobrien#define GET_AOUTHDR_TSIZE H_GET_64 8689857Sobrien#define PUT_AOUTHDR_TSIZE H_PUT_64 8789857Sobrien#define GET_AOUTHDR_DSIZE H_GET_64 8889857Sobrien#define PUT_AOUTHDR_DSIZE H_PUT_64 8989857Sobrien#define GET_AOUTHDR_BSIZE H_GET_64 9089857Sobrien#define PUT_AOUTHDR_BSIZE H_PUT_64 9189857Sobrien#define GET_AOUTHDR_ENTRY H_GET_64 9289857Sobrien#define PUT_AOUTHDR_ENTRY H_PUT_64 9389857Sobrien#define GET_AOUTHDR_TEXT_START H_GET_64 9489857Sobrien#define PUT_AOUTHDR_TEXT_START H_PUT_64 9589857Sobrien#define GET_AOUTHDR_DATA_START H_GET_64 9689857Sobrien#define PUT_AOUTHDR_DATA_START H_PUT_64 9789857Sobrien#define GET_SCNHDR_PADDR H_GET_64 9889857Sobrien#define PUT_SCNHDR_PADDR H_PUT_64 9989857Sobrien#define GET_SCNHDR_VADDR H_GET_64 10089857Sobrien#define PUT_SCNHDR_VADDR H_PUT_64 10189857Sobrien#define GET_SCNHDR_SIZE H_GET_64 10289857Sobrien#define PUT_SCNHDR_SIZE H_PUT_64 10389857Sobrien#define GET_SCNHDR_SCNPTR H_GET_64 10489857Sobrien#define PUT_SCNHDR_SCNPTR H_PUT_64 10589857Sobrien#define GET_SCNHDR_RELPTR H_GET_64 10689857Sobrien#define PUT_SCNHDR_RELPTR H_PUT_64 10789857Sobrien#define GET_SCNHDR_LNNOPTR H_GET_64 10889857Sobrien#define PUT_SCNHDR_LNNOPTR H_PUT_64 10933965Sjdp 11033965Sjdp#define ALPHAECOFF 11133965Sjdp 11233965Sjdp#define NO_COFF_RELOCS 11333965Sjdp#define NO_COFF_SYMBOLS 11433965Sjdp#define NO_COFF_LINENOS 11533965Sjdp#define coff_swap_filehdr_in alpha_ecoff_swap_filehdr_in 11633965Sjdp#define coff_swap_filehdr_out alpha_ecoff_swap_filehdr_out 11733965Sjdp#define coff_swap_aouthdr_in alpha_ecoff_swap_aouthdr_in 11833965Sjdp#define coff_swap_aouthdr_out alpha_ecoff_swap_aouthdr_out 11933965Sjdp#define coff_swap_scnhdr_in alpha_ecoff_swap_scnhdr_in 12033965Sjdp#define coff_swap_scnhdr_out alpha_ecoff_swap_scnhdr_out 12133965Sjdp#include "coffswap.h" 12233965Sjdp 12333965Sjdp/* Get the ECOFF swapping routines. */ 12433965Sjdp#define ECOFF_64 12533965Sjdp#include "ecoffswap.h" 12633965Sjdp 12733965Sjdp/* How to process the various reloc types. */ 12833965Sjdp 129130561Sobrienstatic bfd_reloc_status_type reloc_nil 130130561Sobrien PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); 13133965Sjdp 13233965Sjdpstatic bfd_reloc_status_type 13333965Sjdpreloc_nil (abfd, reloc, sym, data, sec, output_bfd, error_message) 13478828Sobrien bfd *abfd ATTRIBUTE_UNUSED; 13578828Sobrien arelent *reloc ATTRIBUTE_UNUSED; 13678828Sobrien asymbol *sym ATTRIBUTE_UNUSED; 13778828Sobrien PTR data ATTRIBUTE_UNUSED; 13878828Sobrien asection *sec ATTRIBUTE_UNUSED; 13978828Sobrien bfd *output_bfd ATTRIBUTE_UNUSED; 14078828Sobrien char **error_message ATTRIBUTE_UNUSED; 14133965Sjdp{ 14233965Sjdp return bfd_reloc_ok; 14333965Sjdp} 14433965Sjdp 14533965Sjdp/* In case we're on a 32-bit machine, construct a 64-bit "-1" value 14633965Sjdp from smaller values. Start with zero, widen, *then* decrement. */ 14733965Sjdp#define MINUS_ONE (((bfd_vma)0) - 1) 14833965Sjdp 14933965Sjdpstatic reloc_howto_type alpha_howto_table[] = 15033965Sjdp{ 15133965Sjdp /* Reloc type 0 is ignored by itself. However, it appears after a 15233965Sjdp GPDISP reloc to identify the location where the low order 16 bits 15333965Sjdp of the gp register are loaded. */ 15433965Sjdp HOWTO (ALPHA_R_IGNORE, /* type */ 15533965Sjdp 0, /* rightshift */ 15633965Sjdp 0, /* size (0 = byte, 1 = short, 2 = long) */ 15733965Sjdp 8, /* bitsize */ 158130561Sobrien TRUE, /* pc_relative */ 15933965Sjdp 0, /* bitpos */ 16033965Sjdp complain_overflow_dont, /* complain_on_overflow */ 16133965Sjdp reloc_nil, /* special_function */ 16233965Sjdp "IGNORE", /* name */ 163130561Sobrien TRUE, /* partial_inplace */ 16433965Sjdp 0, /* src_mask */ 16533965Sjdp 0, /* dst_mask */ 166130561Sobrien TRUE), /* pcrel_offset */ 16733965Sjdp 16833965Sjdp /* A 32 bit reference to a symbol. */ 16933965Sjdp HOWTO (ALPHA_R_REFLONG, /* type */ 17033965Sjdp 0, /* rightshift */ 17133965Sjdp 2, /* size (0 = byte, 1 = short, 2 = long) */ 17233965Sjdp 32, /* bitsize */ 173130561Sobrien FALSE, /* pc_relative */ 17433965Sjdp 0, /* bitpos */ 17533965Sjdp complain_overflow_bitfield, /* complain_on_overflow */ 17633965Sjdp 0, /* special_function */ 17733965Sjdp "REFLONG", /* name */ 178130561Sobrien TRUE, /* partial_inplace */ 17933965Sjdp 0xffffffff, /* src_mask */ 18033965Sjdp 0xffffffff, /* dst_mask */ 181130561Sobrien FALSE), /* pcrel_offset */ 18233965Sjdp 18333965Sjdp /* A 64 bit reference to a symbol. */ 18433965Sjdp HOWTO (ALPHA_R_REFQUAD, /* type */ 18533965Sjdp 0, /* rightshift */ 18633965Sjdp 4, /* size (0 = byte, 1 = short, 2 = long) */ 18733965Sjdp 64, /* bitsize */ 188130561Sobrien FALSE, /* pc_relative */ 18933965Sjdp 0, /* bitpos */ 19033965Sjdp complain_overflow_bitfield, /* complain_on_overflow */ 19133965Sjdp 0, /* special_function */ 19233965Sjdp "REFQUAD", /* name */ 193130561Sobrien TRUE, /* partial_inplace */ 19433965Sjdp MINUS_ONE, /* src_mask */ 19533965Sjdp MINUS_ONE, /* dst_mask */ 196130561Sobrien FALSE), /* pcrel_offset */ 19733965Sjdp 19833965Sjdp /* A 32 bit GP relative offset. This is just like REFLONG except 19933965Sjdp that when the value is used the value of the gp register will be 20033965Sjdp added in. */ 20133965Sjdp HOWTO (ALPHA_R_GPREL32, /* type */ 20233965Sjdp 0, /* rightshift */ 20333965Sjdp 2, /* size (0 = byte, 1 = short, 2 = long) */ 20433965Sjdp 32, /* bitsize */ 205130561Sobrien FALSE, /* pc_relative */ 20633965Sjdp 0, /* bitpos */ 20733965Sjdp complain_overflow_bitfield, /* complain_on_overflow */ 20833965Sjdp 0, /* special_function */ 20933965Sjdp "GPREL32", /* name */ 210130561Sobrien TRUE, /* partial_inplace */ 21133965Sjdp 0xffffffff, /* src_mask */ 21233965Sjdp 0xffffffff, /* dst_mask */ 213130561Sobrien FALSE), /* pcrel_offset */ 21433965Sjdp 21533965Sjdp /* Used for an instruction that refers to memory off the GP 21633965Sjdp register. The offset is 16 bits of the 32 bit instruction. This 21733965Sjdp reloc always seems to be against the .lita section. */ 21833965Sjdp HOWTO (ALPHA_R_LITERAL, /* type */ 21933965Sjdp 0, /* rightshift */ 22033965Sjdp 2, /* size (0 = byte, 1 = short, 2 = long) */ 22133965Sjdp 16, /* bitsize */ 222130561Sobrien FALSE, /* pc_relative */ 22333965Sjdp 0, /* bitpos */ 22433965Sjdp complain_overflow_signed, /* complain_on_overflow */ 22533965Sjdp 0, /* special_function */ 22633965Sjdp "LITERAL", /* name */ 227130561Sobrien TRUE, /* partial_inplace */ 22833965Sjdp 0xffff, /* src_mask */ 22933965Sjdp 0xffff, /* dst_mask */ 230130561Sobrien FALSE), /* pcrel_offset */ 23133965Sjdp 23233965Sjdp /* This reloc only appears immediately following a LITERAL reloc. 23333965Sjdp It identifies a use of the literal. It seems that the linker can 23433965Sjdp use this to eliminate a portion of the .lita section. The symbol 23533965Sjdp index is special: 1 means the literal address is in the base 23633965Sjdp register of a memory format instruction; 2 means the literal 23733965Sjdp address is in the byte offset register of a byte-manipulation 23833965Sjdp instruction; 3 means the literal address is in the target 23933965Sjdp register of a jsr instruction. This does not actually do any 24033965Sjdp relocation. */ 24133965Sjdp HOWTO (ALPHA_R_LITUSE, /* type */ 24233965Sjdp 0, /* rightshift */ 24333965Sjdp 2, /* size (0 = byte, 1 = short, 2 = long) */ 24433965Sjdp 32, /* bitsize */ 245130561Sobrien FALSE, /* pc_relative */ 24633965Sjdp 0, /* bitpos */ 24733965Sjdp complain_overflow_dont, /* complain_on_overflow */ 24833965Sjdp reloc_nil, /* special_function */ 24933965Sjdp "LITUSE", /* name */ 250130561Sobrien FALSE, /* partial_inplace */ 25133965Sjdp 0, /* src_mask */ 25233965Sjdp 0, /* dst_mask */ 253130561Sobrien FALSE), /* pcrel_offset */ 25433965Sjdp 25533965Sjdp /* Load the gp register. This is always used for a ldah instruction 25633965Sjdp which loads the upper 16 bits of the gp register. The next reloc 25733965Sjdp will be an IGNORE reloc which identifies the location of the lda 25833965Sjdp instruction which loads the lower 16 bits. The symbol index of 25933965Sjdp the GPDISP instruction appears to actually be the number of bytes 26033965Sjdp between the ldah and lda instructions. This gives two different 26133965Sjdp ways to determine where the lda instruction is; I don't know why 26233965Sjdp both are used. The value to use for the relocation is the 26333965Sjdp difference between the GP value and the current location; the 26433965Sjdp load will always be done against a register holding the current 26533965Sjdp address. */ 26633965Sjdp HOWTO (ALPHA_R_GPDISP, /* type */ 26733965Sjdp 16, /* rightshift */ 26833965Sjdp 2, /* size (0 = byte, 1 = short, 2 = long) */ 26933965Sjdp 16, /* bitsize */ 270130561Sobrien TRUE, /* pc_relative */ 27133965Sjdp 0, /* bitpos */ 27233965Sjdp complain_overflow_dont, /* complain_on_overflow */ 27333965Sjdp reloc_nil, /* special_function */ 27433965Sjdp "GPDISP", /* name */ 275130561Sobrien TRUE, /* partial_inplace */ 27633965Sjdp 0xffff, /* src_mask */ 27733965Sjdp 0xffff, /* dst_mask */ 278130561Sobrien TRUE), /* pcrel_offset */ 27933965Sjdp 28033965Sjdp /* A 21 bit branch. The native assembler generates these for 28133965Sjdp branches within the text segment, and also fills in the PC 28233965Sjdp relative offset in the instruction. */ 28333965Sjdp HOWTO (ALPHA_R_BRADDR, /* type */ 28433965Sjdp 2, /* rightshift */ 28533965Sjdp 2, /* size (0 = byte, 1 = short, 2 = long) */ 28633965Sjdp 21, /* bitsize */ 287130561Sobrien TRUE, /* pc_relative */ 28833965Sjdp 0, /* bitpos */ 28933965Sjdp complain_overflow_signed, /* complain_on_overflow */ 29033965Sjdp 0, /* special_function */ 29133965Sjdp "BRADDR", /* name */ 292130561Sobrien TRUE, /* partial_inplace */ 29333965Sjdp 0x1fffff, /* src_mask */ 29433965Sjdp 0x1fffff, /* dst_mask */ 295130561Sobrien FALSE), /* pcrel_offset */ 29633965Sjdp 29733965Sjdp /* A hint for a jump to a register. */ 29833965Sjdp HOWTO (ALPHA_R_HINT, /* type */ 29933965Sjdp 2, /* rightshift */ 30033965Sjdp 2, /* size (0 = byte, 1 = short, 2 = long) */ 30133965Sjdp 14, /* bitsize */ 302130561Sobrien TRUE, /* pc_relative */ 30333965Sjdp 0, /* bitpos */ 30433965Sjdp complain_overflow_dont, /* complain_on_overflow */ 30533965Sjdp 0, /* special_function */ 30633965Sjdp "HINT", /* name */ 307130561Sobrien TRUE, /* partial_inplace */ 30833965Sjdp 0x3fff, /* src_mask */ 30933965Sjdp 0x3fff, /* dst_mask */ 310130561Sobrien FALSE), /* pcrel_offset */ 31133965Sjdp 31233965Sjdp /* 16 bit PC relative offset. */ 31333965Sjdp HOWTO (ALPHA_R_SREL16, /* type */ 31433965Sjdp 0, /* rightshift */ 31533965Sjdp 1, /* size (0 = byte, 1 = short, 2 = long) */ 31633965Sjdp 16, /* bitsize */ 317130561Sobrien TRUE, /* pc_relative */ 31833965Sjdp 0, /* bitpos */ 31933965Sjdp complain_overflow_signed, /* complain_on_overflow */ 32033965Sjdp 0, /* special_function */ 32133965Sjdp "SREL16", /* name */ 322130561Sobrien TRUE, /* partial_inplace */ 32333965Sjdp 0xffff, /* src_mask */ 32433965Sjdp 0xffff, /* dst_mask */ 325130561Sobrien FALSE), /* pcrel_offset */ 32633965Sjdp 32733965Sjdp /* 32 bit PC relative offset. */ 32833965Sjdp HOWTO (ALPHA_R_SREL32, /* type */ 32933965Sjdp 0, /* rightshift */ 33033965Sjdp 2, /* size (0 = byte, 1 = short, 2 = long) */ 33133965Sjdp 32, /* bitsize */ 332130561Sobrien TRUE, /* pc_relative */ 33333965Sjdp 0, /* bitpos */ 33433965Sjdp complain_overflow_signed, /* complain_on_overflow */ 33533965Sjdp 0, /* special_function */ 33633965Sjdp "SREL32", /* name */ 337130561Sobrien TRUE, /* partial_inplace */ 33833965Sjdp 0xffffffff, /* src_mask */ 33933965Sjdp 0xffffffff, /* dst_mask */ 340130561Sobrien FALSE), /* pcrel_offset */ 34133965Sjdp 34233965Sjdp /* A 64 bit PC relative offset. */ 34333965Sjdp HOWTO (ALPHA_R_SREL64, /* type */ 34433965Sjdp 0, /* rightshift */ 34533965Sjdp 4, /* size (0 = byte, 1 = short, 2 = long) */ 34633965Sjdp 64, /* bitsize */ 347130561Sobrien TRUE, /* pc_relative */ 34833965Sjdp 0, /* bitpos */ 34933965Sjdp complain_overflow_signed, /* complain_on_overflow */ 35033965Sjdp 0, /* special_function */ 35133965Sjdp "SREL64", /* name */ 352130561Sobrien TRUE, /* partial_inplace */ 35333965Sjdp MINUS_ONE, /* src_mask */ 35433965Sjdp MINUS_ONE, /* dst_mask */ 355130561Sobrien FALSE), /* pcrel_offset */ 35633965Sjdp 35733965Sjdp /* Push a value on the reloc evaluation stack. */ 35833965Sjdp HOWTO (ALPHA_R_OP_PUSH, /* type */ 35933965Sjdp 0, /* rightshift */ 36033965Sjdp 0, /* size (0 = byte, 1 = short, 2 = long) */ 36133965Sjdp 0, /* bitsize */ 362130561Sobrien FALSE, /* pc_relative */ 36333965Sjdp 0, /* bitpos */ 36433965Sjdp complain_overflow_dont, /* complain_on_overflow */ 36533965Sjdp 0, /* special_function */ 36633965Sjdp "OP_PUSH", /* name */ 367130561Sobrien FALSE, /* partial_inplace */ 36833965Sjdp 0, /* src_mask */ 36933965Sjdp 0, /* dst_mask */ 370130561Sobrien FALSE), /* pcrel_offset */ 37133965Sjdp 37233965Sjdp /* Store the value from the stack at the given address. Store it in 37333965Sjdp a bitfield of size r_size starting at bit position r_offset. */ 37433965Sjdp HOWTO (ALPHA_R_OP_STORE, /* type */ 37533965Sjdp 0, /* rightshift */ 37633965Sjdp 4, /* size (0 = byte, 1 = short, 2 = long) */ 37733965Sjdp 64, /* bitsize */ 378130561Sobrien FALSE, /* pc_relative */ 37933965Sjdp 0, /* bitpos */ 38033965Sjdp complain_overflow_dont, /* complain_on_overflow */ 38133965Sjdp 0, /* special_function */ 38233965Sjdp "OP_STORE", /* name */ 383130561Sobrien FALSE, /* partial_inplace */ 38433965Sjdp 0, /* src_mask */ 38533965Sjdp MINUS_ONE, /* dst_mask */ 386130561Sobrien FALSE), /* pcrel_offset */ 38733965Sjdp 38833965Sjdp /* Subtract the reloc address from the value on the top of the 38933965Sjdp relocation stack. */ 39033965Sjdp HOWTO (ALPHA_R_OP_PSUB, /* type */ 39133965Sjdp 0, /* rightshift */ 39233965Sjdp 0, /* size (0 = byte, 1 = short, 2 = long) */ 39333965Sjdp 0, /* bitsize */ 394130561Sobrien FALSE, /* pc_relative */ 39533965Sjdp 0, /* bitpos */ 39633965Sjdp complain_overflow_dont, /* complain_on_overflow */ 39733965Sjdp 0, /* special_function */ 39833965Sjdp "OP_PSUB", /* name */ 399130561Sobrien FALSE, /* partial_inplace */ 40033965Sjdp 0, /* src_mask */ 40133965Sjdp 0, /* dst_mask */ 402130561Sobrien FALSE), /* pcrel_offset */ 40333965Sjdp 40433965Sjdp /* Shift the value on the top of the relocation stack right by the 40533965Sjdp given value. */ 40633965Sjdp HOWTO (ALPHA_R_OP_PRSHIFT, /* type */ 40733965Sjdp 0, /* rightshift */ 40833965Sjdp 0, /* size (0 = byte, 1 = short, 2 = long) */ 40933965Sjdp 0, /* bitsize */ 410130561Sobrien FALSE, /* pc_relative */ 41133965Sjdp 0, /* bitpos */ 41233965Sjdp complain_overflow_dont, /* complain_on_overflow */ 41333965Sjdp 0, /* special_function */ 41433965Sjdp "OP_PRSHIFT", /* name */ 415130561Sobrien FALSE, /* partial_inplace */ 41633965Sjdp 0, /* src_mask */ 41733965Sjdp 0, /* dst_mask */ 418130561Sobrien FALSE), /* pcrel_offset */ 41933965Sjdp 42033965Sjdp /* Adjust the GP value for a new range in the object file. */ 42133965Sjdp HOWTO (ALPHA_R_GPVALUE, /* type */ 42233965Sjdp 0, /* rightshift */ 42333965Sjdp 0, /* size (0 = byte, 1 = short, 2 = long) */ 42433965Sjdp 0, /* bitsize */ 425130561Sobrien FALSE, /* pc_relative */ 42633965Sjdp 0, /* bitpos */ 42733965Sjdp complain_overflow_dont, /* complain_on_overflow */ 42833965Sjdp 0, /* special_function */ 42933965Sjdp "GPVALUE", /* name */ 430130561Sobrien FALSE, /* partial_inplace */ 43133965Sjdp 0, /* src_mask */ 43233965Sjdp 0, /* dst_mask */ 433130561Sobrien FALSE) /* pcrel_offset */ 43433965Sjdp}; 43533965Sjdp 43633965Sjdp/* Recognize an Alpha ECOFF file. */ 43733965Sjdp 43833965Sjdpstatic const bfd_target * 43933965Sjdpalpha_ecoff_object_p (abfd) 44033965Sjdp bfd *abfd; 44133965Sjdp{ 44233965Sjdp static const bfd_target *ret; 44333965Sjdp 44433965Sjdp ret = coff_object_p (abfd); 44533965Sjdp 44633965Sjdp if (ret != NULL) 44733965Sjdp { 44833965Sjdp asection *sec; 44933965Sjdp 45033965Sjdp /* Alpha ECOFF has a .pdata section. The lnnoptr field of the 45133965Sjdp .pdata section is the number of entries it contains. Each 45233965Sjdp entry takes up 8 bytes. The number of entries is required 45333965Sjdp since the section is aligned to a 16 byte boundary. When we 45433965Sjdp link .pdata sections together, we do not want to include the 45533965Sjdp alignment bytes. We handle this on input by faking the size 45633965Sjdp of the .pdata section to remove the unwanted alignment bytes. 45733965Sjdp On output we will set the lnnoptr field and force the 45833965Sjdp alignment. */ 45933965Sjdp sec = bfd_get_section_by_name (abfd, _PDATA); 46033965Sjdp if (sec != (asection *) NULL) 46133965Sjdp { 46233965Sjdp bfd_size_type size; 46333965Sjdp 46433965Sjdp size = sec->line_filepos * 8; 465218822Sdim BFD_ASSERT (size == sec->size 466218822Sdim || size + 8 == sec->size); 46733965Sjdp if (! bfd_set_section_size (abfd, sec, size)) 46833965Sjdp return NULL; 46933965Sjdp } 47033965Sjdp } 47133965Sjdp 47233965Sjdp return ret; 47333965Sjdp} 47433965Sjdp 47533965Sjdp/* See whether the magic number matches. */ 47633965Sjdp 477130561Sobrienstatic bfd_boolean 47833965Sjdpalpha_ecoff_bad_format_hook (abfd, filehdr) 47978828Sobrien bfd *abfd ATTRIBUTE_UNUSED; 48033965Sjdp PTR filehdr; 48133965Sjdp{ 48233965Sjdp struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr; 48333965Sjdp 484218822Sdim if (! ALPHA_ECOFF_BADMAG (*internal_f)) 485218822Sdim return TRUE; 48633965Sjdp 487218822Sdim if (ALPHA_ECOFF_COMPRESSEDMAG (*internal_f)) 488218822Sdim (*_bfd_error_handler) 489218822Sdim (_("%B: Cannot handle compressed Alpha binaries.\n" 490218822Sdim " Use compiler flags, or objZ, to generate uncompressed binaries."), 491218822Sdim abfd); 492218822Sdim 493218822Sdim return FALSE; 49433965Sjdp} 49533965Sjdp 49633965Sjdp/* This is a hook called by coff_real_object_p to create any backend 49733965Sjdp specific information. */ 49833965Sjdp 49933965Sjdpstatic PTR 50033965Sjdpalpha_ecoff_mkobject_hook (abfd, filehdr, aouthdr) 50133965Sjdp bfd *abfd; 50233965Sjdp PTR filehdr; 50333965Sjdp PTR aouthdr; 50433965Sjdp{ 50533965Sjdp PTR ecoff; 50633965Sjdp 50733965Sjdp ecoff = _bfd_ecoff_mkobject_hook (abfd, filehdr, aouthdr); 50833965Sjdp 50933965Sjdp if (ecoff != NULL) 51033965Sjdp { 51133965Sjdp struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr; 51233965Sjdp 51333965Sjdp /* Set additional BFD flags according to the object type from the 51433965Sjdp machine specific file header flags. */ 51533965Sjdp switch (internal_f->f_flags & F_ALPHA_OBJECT_TYPE_MASK) 51633965Sjdp { 51733965Sjdp case F_ALPHA_SHARABLE: 51833965Sjdp abfd->flags |= DYNAMIC; 51933965Sjdp break; 52033965Sjdp case F_ALPHA_CALL_SHARED: 52133965Sjdp /* Always executable if using shared libraries as the run time 52233965Sjdp loader might resolve undefined references. */ 52333965Sjdp abfd->flags |= (DYNAMIC | EXEC_P); 52433965Sjdp break; 52533965Sjdp } 52633965Sjdp } 52733965Sjdp return ecoff; 52833965Sjdp} 52933965Sjdp 53033965Sjdp/* Reloc handling. */ 53133965Sjdp 53233965Sjdp/* Swap a reloc in. */ 53333965Sjdp 53433965Sjdpstatic void 53533965Sjdpalpha_ecoff_swap_reloc_in (abfd, ext_ptr, intern) 53633965Sjdp bfd *abfd; 53733965Sjdp PTR ext_ptr; 53833965Sjdp struct internal_reloc *intern; 53933965Sjdp{ 54033965Sjdp const RELOC *ext = (RELOC *) ext_ptr; 54133965Sjdp 54289857Sobrien intern->r_vaddr = H_GET_64 (abfd, ext->r_vaddr); 54389857Sobrien intern->r_symndx = H_GET_32 (abfd, ext->r_symndx); 54433965Sjdp 54533965Sjdp BFD_ASSERT (bfd_header_little_endian (abfd)); 54633965Sjdp 54733965Sjdp intern->r_type = ((ext->r_bits[0] & RELOC_BITS0_TYPE_LITTLE) 54833965Sjdp >> RELOC_BITS0_TYPE_SH_LITTLE); 54933965Sjdp intern->r_extern = (ext->r_bits[1] & RELOC_BITS1_EXTERN_LITTLE) != 0; 55033965Sjdp intern->r_offset = ((ext->r_bits[1] & RELOC_BITS1_OFFSET_LITTLE) 55133965Sjdp >> RELOC_BITS1_OFFSET_SH_LITTLE); 55233965Sjdp /* Ignored the reserved bits. */ 55333965Sjdp intern->r_size = ((ext->r_bits[3] & RELOC_BITS3_SIZE_LITTLE) 55433965Sjdp >> RELOC_BITS3_SIZE_SH_LITTLE); 55533965Sjdp 55633965Sjdp if (intern->r_type == ALPHA_R_LITUSE 55733965Sjdp || intern->r_type == ALPHA_R_GPDISP) 55833965Sjdp { 55933965Sjdp /* Handle the LITUSE and GPDISP relocs specially. Its symndx 56033965Sjdp value is not actually a symbol index, but is instead a 56133965Sjdp special code. We put the code in the r_size field, and 56233965Sjdp clobber the symndx. */ 56333965Sjdp if (intern->r_size != 0) 56433965Sjdp abort (); 56533965Sjdp intern->r_size = intern->r_symndx; 56633965Sjdp intern->r_symndx = RELOC_SECTION_NONE; 56733965Sjdp } 56833965Sjdp else if (intern->r_type == ALPHA_R_IGNORE) 56933965Sjdp { 57033965Sjdp /* The IGNORE reloc generally follows a GPDISP reloc, and is 57133965Sjdp against the .lita section. The section is irrelevant. */ 57233965Sjdp if (! intern->r_extern && 57333965Sjdp intern->r_symndx == RELOC_SECTION_ABS) 57433965Sjdp abort (); 57533965Sjdp if (! intern->r_extern && intern->r_symndx == RELOC_SECTION_LITA) 57633965Sjdp intern->r_symndx = RELOC_SECTION_ABS; 57733965Sjdp } 57833965Sjdp} 57933965Sjdp 58033965Sjdp/* Swap a reloc out. */ 58133965Sjdp 58233965Sjdpstatic void 58333965Sjdpalpha_ecoff_swap_reloc_out (abfd, intern, dst) 58433965Sjdp bfd *abfd; 58533965Sjdp const struct internal_reloc *intern; 58633965Sjdp PTR dst; 58733965Sjdp{ 58833965Sjdp RELOC *ext = (RELOC *) dst; 58933965Sjdp long symndx; 59033965Sjdp unsigned char size; 59133965Sjdp 59233965Sjdp /* Undo the hackery done in swap_reloc_in. */ 59333965Sjdp if (intern->r_type == ALPHA_R_LITUSE 59433965Sjdp || intern->r_type == ALPHA_R_GPDISP) 59533965Sjdp { 59633965Sjdp symndx = intern->r_size; 59733965Sjdp size = 0; 59833965Sjdp } 59933965Sjdp else if (intern->r_type == ALPHA_R_IGNORE 60033965Sjdp && ! intern->r_extern 60133965Sjdp && intern->r_symndx == RELOC_SECTION_ABS) 60233965Sjdp { 60333965Sjdp symndx = RELOC_SECTION_LITA; 60433965Sjdp size = intern->r_size; 60533965Sjdp } 60633965Sjdp else 60733965Sjdp { 60833965Sjdp symndx = intern->r_symndx; 60933965Sjdp size = intern->r_size; 61033965Sjdp } 61133965Sjdp 612218822Sdim /* XXX FIXME: The maximum symndx value used to be 14 but this 613218822Sdim fails with object files produced by DEC's C++ compiler. 614218822Sdim Where does the value 14 (or 15) come from anyway ? */ 61533965Sjdp BFD_ASSERT (intern->r_extern 616218822Sdim || (intern->r_symndx >= 0 && intern->r_symndx <= 15)); 61733965Sjdp 61889857Sobrien H_PUT_64 (abfd, intern->r_vaddr, ext->r_vaddr); 61989857Sobrien H_PUT_32 (abfd, symndx, ext->r_symndx); 62033965Sjdp 62133965Sjdp BFD_ASSERT (bfd_header_little_endian (abfd)); 62233965Sjdp 62333965Sjdp ext->r_bits[0] = ((intern->r_type << RELOC_BITS0_TYPE_SH_LITTLE) 62433965Sjdp & RELOC_BITS0_TYPE_LITTLE); 62533965Sjdp ext->r_bits[1] = ((intern->r_extern ? RELOC_BITS1_EXTERN_LITTLE : 0) 62633965Sjdp | ((intern->r_offset << RELOC_BITS1_OFFSET_SH_LITTLE) 62733965Sjdp & RELOC_BITS1_OFFSET_LITTLE)); 62833965Sjdp ext->r_bits[2] = 0; 62933965Sjdp ext->r_bits[3] = ((size << RELOC_BITS3_SIZE_SH_LITTLE) 63033965Sjdp & RELOC_BITS3_SIZE_LITTLE); 63133965Sjdp} 63233965Sjdp 63333965Sjdp/* Finish canonicalizing a reloc. Part of this is generic to all 63433965Sjdp ECOFF targets, and that part is in ecoff.c. The rest is done in 63533965Sjdp this backend routine. It must fill in the howto field. */ 63633965Sjdp 63733965Sjdpstatic void 63833965Sjdpalpha_adjust_reloc_in (abfd, intern, rptr) 63933965Sjdp bfd *abfd; 64033965Sjdp const struct internal_reloc *intern; 64133965Sjdp arelent *rptr; 64233965Sjdp{ 64333965Sjdp if (intern->r_type > ALPHA_R_GPVALUE) 644218822Sdim { 645218822Sdim (*_bfd_error_handler) 646218822Sdim (_("%B: unknown/unsupported relocation type %d"), 647218822Sdim abfd, intern->r_type); 648218822Sdim bfd_set_error (bfd_error_bad_value); 649218822Sdim rptr->addend = 0; 650218822Sdim rptr->howto = NULL; 651218822Sdim return; 652218822Sdim } 65333965Sjdp 65433965Sjdp switch (intern->r_type) 65533965Sjdp { 65633965Sjdp case ALPHA_R_BRADDR: 65733965Sjdp case ALPHA_R_SREL16: 65833965Sjdp case ALPHA_R_SREL32: 65933965Sjdp case ALPHA_R_SREL64: 66033965Sjdp /* This relocs appear to be fully resolved when they are against 66133965Sjdp internal symbols. Against external symbols, BRADDR at least 66233965Sjdp appears to be resolved against the next instruction. */ 66333965Sjdp if (! intern->r_extern) 66433965Sjdp rptr->addend = 0; 66533965Sjdp else 66633965Sjdp rptr->addend = - (intern->r_vaddr + 4); 66733965Sjdp break; 66833965Sjdp 66933965Sjdp case ALPHA_R_GPREL32: 67033965Sjdp case ALPHA_R_LITERAL: 67133965Sjdp /* Copy the gp value for this object file into the addend, to 67233965Sjdp ensure that we are not confused by the linker. */ 67333965Sjdp if (! intern->r_extern) 67433965Sjdp rptr->addend += ecoff_data (abfd)->gp; 67533965Sjdp break; 67633965Sjdp 67733965Sjdp case ALPHA_R_LITUSE: 67833965Sjdp case ALPHA_R_GPDISP: 67933965Sjdp /* The LITUSE and GPDISP relocs do not use a symbol, or an 68033965Sjdp addend, but they do use a special code. Put this code in the 68133965Sjdp addend field. */ 68233965Sjdp rptr->addend = intern->r_size; 68333965Sjdp break; 68433965Sjdp 68533965Sjdp case ALPHA_R_OP_STORE: 68633965Sjdp /* The STORE reloc needs the size and offset fields. We store 68733965Sjdp them in the addend. */ 688218822Sdim BFD_ASSERT (intern->r_offset <= 256); 68933965Sjdp rptr->addend = (intern->r_offset << 8) + intern->r_size; 69033965Sjdp break; 69133965Sjdp 69233965Sjdp case ALPHA_R_OP_PUSH: 69333965Sjdp case ALPHA_R_OP_PSUB: 69433965Sjdp case ALPHA_R_OP_PRSHIFT: 69533965Sjdp /* The PUSH, PSUB and PRSHIFT relocs do not actually use an 69633965Sjdp address. I believe that the address supplied is really an 69733965Sjdp addend. */ 69833965Sjdp rptr->addend = intern->r_vaddr; 69933965Sjdp break; 70033965Sjdp 70133965Sjdp case ALPHA_R_GPVALUE: 70233965Sjdp /* Set the addend field to the new GP value. */ 70333965Sjdp rptr->addend = intern->r_symndx + ecoff_data (abfd)->gp; 70433965Sjdp break; 70533965Sjdp 70633965Sjdp case ALPHA_R_IGNORE: 70733965Sjdp /* If the type is ALPHA_R_IGNORE, make sure this is a reference 70833965Sjdp to the absolute section so that the reloc is ignored. For 70933965Sjdp some reason the address of this reloc type is not adjusted by 71033965Sjdp the section vma. We record the gp value for this object file 71133965Sjdp here, for convenience when doing the GPDISP relocation. */ 71233965Sjdp rptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; 71333965Sjdp rptr->address = intern->r_vaddr; 71433965Sjdp rptr->addend = ecoff_data (abfd)->gp; 71533965Sjdp break; 71633965Sjdp 71733965Sjdp default: 71833965Sjdp break; 71933965Sjdp } 72033965Sjdp 72133965Sjdp rptr->howto = &alpha_howto_table[intern->r_type]; 72233965Sjdp} 72333965Sjdp 72433965Sjdp/* When writing out a reloc we need to pull some values back out of 72533965Sjdp the addend field into the reloc. This is roughly the reverse of 72633965Sjdp alpha_adjust_reloc_in, except that there are several changes we do 72733965Sjdp not need to undo. */ 72833965Sjdp 72933965Sjdpstatic void 73033965Sjdpalpha_adjust_reloc_out (abfd, rel, intern) 73178828Sobrien bfd *abfd ATTRIBUTE_UNUSED; 73233965Sjdp const arelent *rel; 73333965Sjdp struct internal_reloc *intern; 73433965Sjdp{ 73533965Sjdp switch (intern->r_type) 73633965Sjdp { 73733965Sjdp case ALPHA_R_LITUSE: 73833965Sjdp case ALPHA_R_GPDISP: 73933965Sjdp intern->r_size = rel->addend; 74033965Sjdp break; 74133965Sjdp 74233965Sjdp case ALPHA_R_OP_STORE: 74333965Sjdp intern->r_size = rel->addend & 0xff; 74433965Sjdp intern->r_offset = (rel->addend >> 8) & 0xff; 74533965Sjdp break; 74633965Sjdp 74733965Sjdp case ALPHA_R_OP_PUSH: 74833965Sjdp case ALPHA_R_OP_PSUB: 74933965Sjdp case ALPHA_R_OP_PRSHIFT: 75033965Sjdp intern->r_vaddr = rel->addend; 75133965Sjdp break; 75233965Sjdp 75333965Sjdp case ALPHA_R_IGNORE: 75433965Sjdp intern->r_vaddr = rel->address; 75533965Sjdp break; 75633965Sjdp 75733965Sjdp default: 75833965Sjdp break; 75933965Sjdp } 76033965Sjdp} 76133965Sjdp 76233965Sjdp/* The size of the stack for the relocation evaluator. */ 76333965Sjdp#define RELOC_STACKSIZE (10) 76433965Sjdp 76533965Sjdp/* Alpha ECOFF relocs have a built in expression evaluator as well as 76633965Sjdp other interdependencies. Rather than use a bunch of special 76733965Sjdp functions and global variables, we use a single routine to do all 76833965Sjdp the relocation for a section. I haven't yet worked out how the 76933965Sjdp assembler is going to handle this. */ 77033965Sjdp 77133965Sjdpstatic bfd_byte * 77233965Sjdpalpha_ecoff_get_relocated_section_contents (abfd, link_info, link_order, 773130561Sobrien data, relocatable, symbols) 77433965Sjdp bfd *abfd; 77533965Sjdp struct bfd_link_info *link_info; 77633965Sjdp struct bfd_link_order *link_order; 77733965Sjdp bfd_byte *data; 778130561Sobrien bfd_boolean relocatable; 77933965Sjdp asymbol **symbols; 78033965Sjdp{ 78133965Sjdp bfd *input_bfd = link_order->u.indirect.section->owner; 78233965Sjdp asection *input_section = link_order->u.indirect.section; 78333965Sjdp long reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section); 78433965Sjdp arelent **reloc_vector = NULL; 78533965Sjdp long reloc_count; 786130561Sobrien bfd *output_bfd = relocatable ? abfd : (bfd *) NULL; 78733965Sjdp bfd_vma gp; 788218822Sdim bfd_size_type sz; 789130561Sobrien bfd_boolean gp_undefined; 79033965Sjdp bfd_vma stack[RELOC_STACKSIZE]; 79133965Sjdp int tos = 0; 79233965Sjdp 79333965Sjdp if (reloc_size < 0) 79433965Sjdp goto error_return; 79589857Sobrien reloc_vector = (arelent **) bfd_malloc ((bfd_size_type) reloc_size); 79633965Sjdp if (reloc_vector == NULL && reloc_size != 0) 79733965Sjdp goto error_return; 79833965Sjdp 799218822Sdim sz = input_section->rawsize ? input_section->rawsize : input_section->size; 800218822Sdim if (! bfd_get_section_contents (input_bfd, input_section, data, 0, sz)) 80133965Sjdp goto error_return; 80233965Sjdp 80333965Sjdp reloc_count = bfd_canonicalize_reloc (input_bfd, input_section, 80433965Sjdp reloc_vector, symbols); 80533965Sjdp if (reloc_count < 0) 80633965Sjdp goto error_return; 80733965Sjdp if (reloc_count == 0) 80833965Sjdp goto successful_return; 80933965Sjdp 81033965Sjdp /* Get the GP value for the output BFD. */ 811130561Sobrien gp_undefined = FALSE; 81233965Sjdp gp = _bfd_get_gp_value (abfd); 81333965Sjdp if (gp == 0) 81433965Sjdp { 815130561Sobrien if (relocatable) 81633965Sjdp { 81733965Sjdp asection *sec; 81833965Sjdp bfd_vma lo; 81933965Sjdp 82033965Sjdp /* Make up a value. */ 82133965Sjdp lo = (bfd_vma) -1; 82233965Sjdp for (sec = abfd->sections; sec != NULL; sec = sec->next) 82333965Sjdp { 82433965Sjdp if (sec->vma < lo 82533965Sjdp && (strcmp (sec->name, ".sbss") == 0 82633965Sjdp || strcmp (sec->name, ".sdata") == 0 82733965Sjdp || strcmp (sec->name, ".lit4") == 0 82833965Sjdp || strcmp (sec->name, ".lit8") == 0 82933965Sjdp || strcmp (sec->name, ".lita") == 0)) 83033965Sjdp lo = sec->vma; 83133965Sjdp } 83233965Sjdp gp = lo + 0x8000; 83333965Sjdp _bfd_set_gp_value (abfd, gp); 83433965Sjdp } 83533965Sjdp else 83633965Sjdp { 83733965Sjdp struct bfd_link_hash_entry *h; 83833965Sjdp 839130561Sobrien h = bfd_link_hash_lookup (link_info->hash, "_gp", FALSE, FALSE, 840130561Sobrien TRUE); 84133965Sjdp if (h == (struct bfd_link_hash_entry *) NULL 84233965Sjdp || h->type != bfd_link_hash_defined) 843130561Sobrien gp_undefined = TRUE; 84433965Sjdp else 84533965Sjdp { 84633965Sjdp gp = (h->u.def.value 84733965Sjdp + h->u.def.section->output_section->vma 84833965Sjdp + h->u.def.section->output_offset); 84933965Sjdp _bfd_set_gp_value (abfd, gp); 85033965Sjdp } 85133965Sjdp } 85233965Sjdp } 85333965Sjdp 85433965Sjdp for (; *reloc_vector != (arelent *) NULL; reloc_vector++) 85533965Sjdp { 85633965Sjdp arelent *rel; 85733965Sjdp bfd_reloc_status_type r; 85833965Sjdp char *err; 85933965Sjdp 86033965Sjdp rel = *reloc_vector; 86133965Sjdp r = bfd_reloc_ok; 86233965Sjdp switch (rel->howto->type) 86333965Sjdp { 86433965Sjdp case ALPHA_R_IGNORE: 86533965Sjdp rel->address += input_section->output_offset; 86633965Sjdp break; 86733965Sjdp 86833965Sjdp case ALPHA_R_REFLONG: 86933965Sjdp case ALPHA_R_REFQUAD: 87033965Sjdp case ALPHA_R_BRADDR: 87133965Sjdp case ALPHA_R_HINT: 87233965Sjdp case ALPHA_R_SREL16: 87333965Sjdp case ALPHA_R_SREL32: 87433965Sjdp case ALPHA_R_SREL64: 875130561Sobrien if (relocatable 87633965Sjdp && ((*rel->sym_ptr_ptr)->flags & BSF_SECTION_SYM) == 0) 87733965Sjdp { 87833965Sjdp rel->address += input_section->output_offset; 87933965Sjdp break; 88033965Sjdp } 88133965Sjdp r = bfd_perform_relocation (input_bfd, rel, data, input_section, 88233965Sjdp output_bfd, &err); 88333965Sjdp break; 88433965Sjdp 88533965Sjdp case ALPHA_R_GPREL32: 88633965Sjdp /* This relocation is used in a switch table. It is a 32 88733965Sjdp bit offset from the current GP value. We must adjust it 88833965Sjdp by the different between the original GP value and the 88933965Sjdp current GP value. The original GP value is stored in the 89033965Sjdp addend. We adjust the addend and let 89133965Sjdp bfd_perform_relocation finish the job. */ 89233965Sjdp rel->addend -= gp; 89333965Sjdp r = bfd_perform_relocation (input_bfd, rel, data, input_section, 89433965Sjdp output_bfd, &err); 89533965Sjdp if (r == bfd_reloc_ok && gp_undefined) 89633965Sjdp { 89733965Sjdp r = bfd_reloc_dangerous; 89860484Sobrien err = (char *) _("GP relative relocation used when GP not defined"); 89933965Sjdp } 90033965Sjdp break; 90133965Sjdp 90233965Sjdp case ALPHA_R_LITERAL: 90333965Sjdp /* This is a reference to a literal value, generally 90433965Sjdp (always?) in the .lita section. This is a 16 bit GP 90533965Sjdp relative relocation. Sometimes the subsequent reloc is a 90633965Sjdp LITUSE reloc, which indicates how this reloc is used. 90733965Sjdp This sometimes permits rewriting the two instructions 90833965Sjdp referred to by the LITERAL and the LITUSE into different 90933965Sjdp instructions which do not refer to .lita. This can save 91033965Sjdp a memory reference, and permits removing a value from 91133965Sjdp .lita thus saving GP relative space. 91233965Sjdp 91333965Sjdp We do not these optimizations. To do them we would need 91433965Sjdp to arrange to link the .lita section first, so that by 91533965Sjdp the time we got here we would know the final values to 91633965Sjdp use. This would not be particularly difficult, but it is 91733965Sjdp not currently implemented. */ 91833965Sjdp 91933965Sjdp { 92033965Sjdp unsigned long insn; 92133965Sjdp 92233965Sjdp /* I believe that the LITERAL reloc will only apply to a 92333965Sjdp ldq or ldl instruction, so check my assumption. */ 92433965Sjdp insn = bfd_get_32 (input_bfd, data + rel->address); 92533965Sjdp BFD_ASSERT (((insn >> 26) & 0x3f) == 0x29 92633965Sjdp || ((insn >> 26) & 0x3f) == 0x28); 92733965Sjdp 92833965Sjdp rel->addend -= gp; 92933965Sjdp r = bfd_perform_relocation (input_bfd, rel, data, input_section, 93033965Sjdp output_bfd, &err); 93133965Sjdp if (r == bfd_reloc_ok && gp_undefined) 93233965Sjdp { 93333965Sjdp r = bfd_reloc_dangerous; 93433965Sjdp err = 93560484Sobrien (char *) _("GP relative relocation used when GP not defined"); 93633965Sjdp } 93733965Sjdp } 93833965Sjdp break; 93933965Sjdp 94033965Sjdp case ALPHA_R_LITUSE: 94133965Sjdp /* See ALPHA_R_LITERAL above for the uses of this reloc. It 94233965Sjdp does not cause anything to happen, itself. */ 94333965Sjdp rel->address += input_section->output_offset; 94433965Sjdp break; 94577298Sobrien 94633965Sjdp case ALPHA_R_GPDISP: 94733965Sjdp /* This marks the ldah of an ldah/lda pair which loads the 94833965Sjdp gp register with the difference of the gp value and the 94933965Sjdp current location. The second of the pair is r_size bytes 95033965Sjdp ahead; it used to be marked with an ALPHA_R_IGNORE reloc, 95133965Sjdp but that no longer happens in OSF/1 3.2. */ 95233965Sjdp { 95333965Sjdp unsigned long insn1, insn2; 95433965Sjdp bfd_vma addend; 95533965Sjdp 95633965Sjdp /* Get the two instructions. */ 95733965Sjdp insn1 = bfd_get_32 (input_bfd, data + rel->address); 95833965Sjdp insn2 = bfd_get_32 (input_bfd, data + rel->address + rel->addend); 95933965Sjdp 96033965Sjdp BFD_ASSERT (((insn1 >> 26) & 0x3f) == 0x09); /* ldah */ 96133965Sjdp BFD_ASSERT (((insn2 >> 26) & 0x3f) == 0x08); /* lda */ 96233965Sjdp 96333965Sjdp /* Get the existing addend. We must account for the sign 96433965Sjdp extension done by lda and ldah. */ 96533965Sjdp addend = ((insn1 & 0xffff) << 16) + (insn2 & 0xffff); 96633965Sjdp if (insn1 & 0x8000) 96733965Sjdp { 96833965Sjdp addend -= 0x80000000; 96933965Sjdp addend -= 0x80000000; 97033965Sjdp } 97133965Sjdp if (insn2 & 0x8000) 97233965Sjdp addend -= 0x10000; 97333965Sjdp 97433965Sjdp /* The existing addend includes the different between the 97533965Sjdp gp of the input BFD and the address in the input BFD. 97633965Sjdp Subtract this out. */ 97733965Sjdp addend -= (ecoff_data (input_bfd)->gp 97833965Sjdp - (input_section->vma + rel->address)); 97933965Sjdp 98033965Sjdp /* Now add in the final gp value, and subtract out the 98133965Sjdp final address. */ 98233965Sjdp addend += (gp 98333965Sjdp - (input_section->output_section->vma 98433965Sjdp + input_section->output_offset 98533965Sjdp + rel->address)); 98633965Sjdp 98733965Sjdp /* Change the instructions, accounting for the sign 98833965Sjdp extension, and write them out. */ 98933965Sjdp if (addend & 0x8000) 99033965Sjdp addend += 0x10000; 99133965Sjdp insn1 = (insn1 & 0xffff0000) | ((addend >> 16) & 0xffff); 99233965Sjdp insn2 = (insn2 & 0xffff0000) | (addend & 0xffff); 99333965Sjdp 99433965Sjdp bfd_put_32 (input_bfd, (bfd_vma) insn1, data + rel->address); 99533965Sjdp bfd_put_32 (input_bfd, (bfd_vma) insn2, 99633965Sjdp data + rel->address + rel->addend); 99733965Sjdp 99833965Sjdp rel->address += input_section->output_offset; 99933965Sjdp } 100033965Sjdp break; 100177298Sobrien 100233965Sjdp case ALPHA_R_OP_PUSH: 100333965Sjdp /* Push a value on the reloc evaluation stack. */ 100433965Sjdp { 100533965Sjdp asymbol *symbol; 100633965Sjdp bfd_vma relocation; 100733965Sjdp 1008130561Sobrien if (relocatable) 100933965Sjdp { 101033965Sjdp rel->address += input_section->output_offset; 101133965Sjdp break; 101233965Sjdp } 101333965Sjdp 101433965Sjdp /* Figure out the relocation of this symbol. */ 101533965Sjdp symbol = *rel->sym_ptr_ptr; 101633965Sjdp 101733965Sjdp if (bfd_is_und_section (symbol->section)) 101833965Sjdp r = bfd_reloc_undefined; 101933965Sjdp 102033965Sjdp if (bfd_is_com_section (symbol->section)) 102133965Sjdp relocation = 0; 102233965Sjdp else 102333965Sjdp relocation = symbol->value; 102433965Sjdp relocation += symbol->section->output_section->vma; 102533965Sjdp relocation += symbol->section->output_offset; 102633965Sjdp relocation += rel->addend; 102733965Sjdp 102833965Sjdp if (tos >= RELOC_STACKSIZE) 102933965Sjdp abort (); 103033965Sjdp 103133965Sjdp stack[tos++] = relocation; 103233965Sjdp } 103333965Sjdp break; 103433965Sjdp 103533965Sjdp case ALPHA_R_OP_STORE: 103633965Sjdp /* Store a value from the reloc stack into a bitfield. */ 103733965Sjdp { 103833965Sjdp bfd_vma val; 103933965Sjdp int offset, size; 104033965Sjdp 1041130561Sobrien if (relocatable) 104233965Sjdp { 104333965Sjdp rel->address += input_section->output_offset; 104433965Sjdp break; 104533965Sjdp } 104633965Sjdp 104733965Sjdp if (tos == 0) 104833965Sjdp abort (); 104933965Sjdp 105033965Sjdp /* The offset and size for this reloc are encoded into the 105133965Sjdp addend field by alpha_adjust_reloc_in. */ 105233965Sjdp offset = (rel->addend >> 8) & 0xff; 105333965Sjdp size = rel->addend & 0xff; 105433965Sjdp 105533965Sjdp val = bfd_get_64 (abfd, data + rel->address); 105633965Sjdp val &=~ (((1 << size) - 1) << offset); 105733965Sjdp val |= (stack[--tos] & ((1 << size) - 1)) << offset; 105833965Sjdp bfd_put_64 (abfd, val, data + rel->address); 105933965Sjdp } 106033965Sjdp break; 106133965Sjdp 106233965Sjdp case ALPHA_R_OP_PSUB: 106333965Sjdp /* Subtract a value from the top of the stack. */ 106433965Sjdp { 106533965Sjdp asymbol *symbol; 106633965Sjdp bfd_vma relocation; 106733965Sjdp 1068130561Sobrien if (relocatable) 106933965Sjdp { 107033965Sjdp rel->address += input_section->output_offset; 107133965Sjdp break; 107233965Sjdp } 107333965Sjdp 107433965Sjdp /* Figure out the relocation of this symbol. */ 107533965Sjdp symbol = *rel->sym_ptr_ptr; 107633965Sjdp 107733965Sjdp if (bfd_is_und_section (symbol->section)) 107833965Sjdp r = bfd_reloc_undefined; 107933965Sjdp 108033965Sjdp if (bfd_is_com_section (symbol->section)) 108133965Sjdp relocation = 0; 108233965Sjdp else 108333965Sjdp relocation = symbol->value; 108433965Sjdp relocation += symbol->section->output_section->vma; 108533965Sjdp relocation += symbol->section->output_offset; 108633965Sjdp relocation += rel->addend; 108733965Sjdp 108833965Sjdp if (tos == 0) 108933965Sjdp abort (); 109033965Sjdp 109133965Sjdp stack[tos - 1] -= relocation; 109233965Sjdp } 109333965Sjdp break; 109433965Sjdp 109533965Sjdp case ALPHA_R_OP_PRSHIFT: 109633965Sjdp /* Shift the value on the top of the stack. */ 109733965Sjdp { 109833965Sjdp asymbol *symbol; 109933965Sjdp bfd_vma relocation; 110033965Sjdp 1101130561Sobrien if (relocatable) 110233965Sjdp { 110333965Sjdp rel->address += input_section->output_offset; 110433965Sjdp break; 110533965Sjdp } 110633965Sjdp 110733965Sjdp /* Figure out the relocation of this symbol. */ 110833965Sjdp symbol = *rel->sym_ptr_ptr; 110933965Sjdp 111033965Sjdp if (bfd_is_und_section (symbol->section)) 111133965Sjdp r = bfd_reloc_undefined; 111233965Sjdp 111333965Sjdp if (bfd_is_com_section (symbol->section)) 111433965Sjdp relocation = 0; 111533965Sjdp else 111633965Sjdp relocation = symbol->value; 111733965Sjdp relocation += symbol->section->output_section->vma; 111833965Sjdp relocation += symbol->section->output_offset; 111933965Sjdp relocation += rel->addend; 112033965Sjdp 112133965Sjdp if (tos == 0) 112233965Sjdp abort (); 112333965Sjdp 112433965Sjdp stack[tos - 1] >>= relocation; 112533965Sjdp } 112633965Sjdp break; 112777298Sobrien 112833965Sjdp case ALPHA_R_GPVALUE: 112933965Sjdp /* I really don't know if this does the right thing. */ 113033965Sjdp gp = rel->addend; 1131130561Sobrien gp_undefined = FALSE; 113233965Sjdp break; 113333965Sjdp 113433965Sjdp default: 113533965Sjdp abort (); 113633965Sjdp } 113733965Sjdp 1138130561Sobrien if (relocatable) 113933965Sjdp { 114033965Sjdp asection *os = input_section->output_section; 114133965Sjdp 114233965Sjdp /* A partial link, so keep the relocs. */ 114333965Sjdp os->orelocation[os->reloc_count] = rel; 114433965Sjdp os->reloc_count++; 114533965Sjdp } 114633965Sjdp 114777298Sobrien if (r != bfd_reloc_ok) 114833965Sjdp { 114933965Sjdp switch (r) 115033965Sjdp { 115133965Sjdp case bfd_reloc_undefined: 115233965Sjdp if (! ((*link_info->callbacks->undefined_symbol) 115333965Sjdp (link_info, bfd_asymbol_name (*rel->sym_ptr_ptr), 1154130561Sobrien input_bfd, input_section, rel->address, TRUE))) 115533965Sjdp goto error_return; 115633965Sjdp break; 115777298Sobrien case bfd_reloc_dangerous: 115833965Sjdp if (! ((*link_info->callbacks->reloc_dangerous) 115933965Sjdp (link_info, err, input_bfd, input_section, 116033965Sjdp rel->address))) 116133965Sjdp goto error_return; 116233965Sjdp break; 116333965Sjdp case bfd_reloc_overflow: 116433965Sjdp if (! ((*link_info->callbacks->reloc_overflow) 1165218822Sdim (link_info, NULL, 1166218822Sdim bfd_asymbol_name (*rel->sym_ptr_ptr), 116733965Sjdp rel->howto->name, rel->addend, input_bfd, 116833965Sjdp input_section, rel->address))) 116933965Sjdp goto error_return; 117033965Sjdp break; 117133965Sjdp case bfd_reloc_outofrange: 117233965Sjdp default: 117333965Sjdp abort (); 117433965Sjdp break; 117533965Sjdp } 117633965Sjdp } 117733965Sjdp } 117833965Sjdp 117933965Sjdp if (tos != 0) 118033965Sjdp abort (); 118133965Sjdp 118233965Sjdp successful_return: 118333965Sjdp if (reloc_vector != NULL) 118433965Sjdp free (reloc_vector); 118533965Sjdp return data; 118633965Sjdp 118733965Sjdp error_return: 118833965Sjdp if (reloc_vector != NULL) 118933965Sjdp free (reloc_vector); 119033965Sjdp return NULL; 119133965Sjdp} 119233965Sjdp 119333965Sjdp/* Get the howto structure for a generic reloc type. */ 119433965Sjdp 119533965Sjdpstatic reloc_howto_type * 119633965Sjdpalpha_bfd_reloc_type_lookup (abfd, code) 119778828Sobrien bfd *abfd ATTRIBUTE_UNUSED; 119833965Sjdp bfd_reloc_code_real_type code; 119933965Sjdp{ 120033965Sjdp int alpha_type; 120133965Sjdp 120233965Sjdp switch (code) 120333965Sjdp { 120433965Sjdp case BFD_RELOC_32: 120533965Sjdp alpha_type = ALPHA_R_REFLONG; 120633965Sjdp break; 120733965Sjdp case BFD_RELOC_64: 120833965Sjdp case BFD_RELOC_CTOR: 120933965Sjdp alpha_type = ALPHA_R_REFQUAD; 121033965Sjdp break; 121133965Sjdp case BFD_RELOC_GPREL32: 121233965Sjdp alpha_type = ALPHA_R_GPREL32; 121333965Sjdp break; 121433965Sjdp case BFD_RELOC_ALPHA_LITERAL: 121533965Sjdp alpha_type = ALPHA_R_LITERAL; 121633965Sjdp break; 121733965Sjdp case BFD_RELOC_ALPHA_LITUSE: 121833965Sjdp alpha_type = ALPHA_R_LITUSE; 121933965Sjdp break; 122033965Sjdp case BFD_RELOC_ALPHA_GPDISP_HI16: 122133965Sjdp alpha_type = ALPHA_R_GPDISP; 122233965Sjdp break; 122333965Sjdp case BFD_RELOC_ALPHA_GPDISP_LO16: 122433965Sjdp alpha_type = ALPHA_R_IGNORE; 122533965Sjdp break; 122633965Sjdp case BFD_RELOC_23_PCREL_S2: 122733965Sjdp alpha_type = ALPHA_R_BRADDR; 122833965Sjdp break; 122933965Sjdp case BFD_RELOC_ALPHA_HINT: 123033965Sjdp alpha_type = ALPHA_R_HINT; 123133965Sjdp break; 123233965Sjdp case BFD_RELOC_16_PCREL: 123333965Sjdp alpha_type = ALPHA_R_SREL16; 123433965Sjdp break; 123533965Sjdp case BFD_RELOC_32_PCREL: 123633965Sjdp alpha_type = ALPHA_R_SREL32; 123733965Sjdp break; 123833965Sjdp case BFD_RELOC_64_PCREL: 123933965Sjdp alpha_type = ALPHA_R_SREL64; 124033965Sjdp break; 124133965Sjdp default: 124233965Sjdp return (reloc_howto_type *) NULL; 124333965Sjdp } 124433965Sjdp 124533965Sjdp return &alpha_howto_table[alpha_type]; 124633965Sjdp} 1247218822Sdim 1248218822Sdimstatic reloc_howto_type * 1249218822Sdimalpha_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, 1250218822Sdim const char *r_name) 1251218822Sdim{ 1252218822Sdim unsigned int i; 1253218822Sdim 1254218822Sdim for (i = 0; 1255218822Sdim i < sizeof (alpha_howto_table) / sizeof (alpha_howto_table[0]); 1256218822Sdim i++) 1257218822Sdim if (alpha_howto_table[i].name != NULL 1258218822Sdim && strcasecmp (alpha_howto_table[i].name, r_name) == 0) 1259218822Sdim return &alpha_howto_table[i]; 1260218822Sdim 1261218822Sdim return NULL; 1262218822Sdim} 126333965Sjdp 126433965Sjdp/* A helper routine for alpha_relocate_section which converts an 1265130561Sobrien external reloc when generating relocatable output. Returns the 126633965Sjdp relocation amount. */ 126733965Sjdp 126833965Sjdpstatic bfd_vma 126933965Sjdpalpha_convert_external_reloc (output_bfd, info, input_bfd, ext_rel, h) 127078828Sobrien bfd *output_bfd ATTRIBUTE_UNUSED; 127133965Sjdp struct bfd_link_info *info; 127233965Sjdp bfd *input_bfd; 127333965Sjdp struct external_reloc *ext_rel; 127433965Sjdp struct ecoff_link_hash_entry *h; 127533965Sjdp{ 127633965Sjdp unsigned long r_symndx; 127733965Sjdp bfd_vma relocation; 127833965Sjdp 1279130561Sobrien BFD_ASSERT (info->relocatable); 128033965Sjdp 128133965Sjdp if (h->root.type == bfd_link_hash_defined 128233965Sjdp || h->root.type == bfd_link_hash_defweak) 128333965Sjdp { 128433965Sjdp asection *hsec; 128533965Sjdp const char *name; 128633965Sjdp 128733965Sjdp /* This symbol is defined in the output. Convert the reloc from 128833965Sjdp being against the symbol to being against the section. */ 128933965Sjdp 129033965Sjdp /* Clear the r_extern bit. */ 129133965Sjdp ext_rel->r_bits[1] &=~ RELOC_BITS1_EXTERN_LITTLE; 129233965Sjdp 129333965Sjdp /* Compute a new r_symndx value. */ 129433965Sjdp hsec = h->root.u.def.section; 129533965Sjdp name = bfd_get_section_name (output_bfd, hsec->output_section); 129633965Sjdp 129789857Sobrien r_symndx = (unsigned long) -1; 129833965Sjdp switch (name[1]) 129933965Sjdp { 130033965Sjdp case 'A': 130133965Sjdp if (strcmp (name, "*ABS*") == 0) 130233965Sjdp r_symndx = RELOC_SECTION_ABS; 130333965Sjdp break; 130433965Sjdp case 'b': 130533965Sjdp if (strcmp (name, ".bss") == 0) 130633965Sjdp r_symndx = RELOC_SECTION_BSS; 130733965Sjdp break; 130833965Sjdp case 'd': 130933965Sjdp if (strcmp (name, ".data") == 0) 131033965Sjdp r_symndx = RELOC_SECTION_DATA; 131133965Sjdp break; 131233965Sjdp case 'f': 131333965Sjdp if (strcmp (name, ".fini") == 0) 131433965Sjdp r_symndx = RELOC_SECTION_FINI; 131533965Sjdp break; 131633965Sjdp case 'i': 131733965Sjdp if (strcmp (name, ".init") == 0) 131833965Sjdp r_symndx = RELOC_SECTION_INIT; 131933965Sjdp break; 132033965Sjdp case 'l': 132133965Sjdp if (strcmp (name, ".lita") == 0) 132233965Sjdp r_symndx = RELOC_SECTION_LITA; 132333965Sjdp else if (strcmp (name, ".lit8") == 0) 132433965Sjdp r_symndx = RELOC_SECTION_LIT8; 132533965Sjdp else if (strcmp (name, ".lit4") == 0) 132633965Sjdp r_symndx = RELOC_SECTION_LIT4; 132733965Sjdp break; 132833965Sjdp case 'p': 132933965Sjdp if (strcmp (name, ".pdata") == 0) 133033965Sjdp r_symndx = RELOC_SECTION_PDATA; 133133965Sjdp break; 133233965Sjdp case 'r': 133333965Sjdp if (strcmp (name, ".rdata") == 0) 133433965Sjdp r_symndx = RELOC_SECTION_RDATA; 133533965Sjdp else if (strcmp (name, ".rconst") == 0) 133633965Sjdp r_symndx = RELOC_SECTION_RCONST; 133733965Sjdp break; 133833965Sjdp case 's': 133933965Sjdp if (strcmp (name, ".sdata") == 0) 134033965Sjdp r_symndx = RELOC_SECTION_SDATA; 134133965Sjdp else if (strcmp (name, ".sbss") == 0) 134233965Sjdp r_symndx = RELOC_SECTION_SBSS; 134333965Sjdp break; 134433965Sjdp case 't': 134533965Sjdp if (strcmp (name, ".text") == 0) 134633965Sjdp r_symndx = RELOC_SECTION_TEXT; 134733965Sjdp break; 134833965Sjdp case 'x': 134933965Sjdp if (strcmp (name, ".xdata") == 0) 135033965Sjdp r_symndx = RELOC_SECTION_XDATA; 135133965Sjdp break; 135233965Sjdp } 135377298Sobrien 135489857Sobrien if (r_symndx == (unsigned long) -1) 135533965Sjdp abort (); 135633965Sjdp 135733965Sjdp /* Add the section VMA and the symbol value. */ 135833965Sjdp relocation = (h->root.u.def.value 135933965Sjdp + hsec->output_section->vma 136033965Sjdp + hsec->output_offset); 136133965Sjdp } 136233965Sjdp else 136333965Sjdp { 136433965Sjdp /* Change the symndx value to the right one for 136533965Sjdp the output BFD. */ 136633965Sjdp r_symndx = h->indx; 136789857Sobrien if (r_symndx == (unsigned long) -1) 136833965Sjdp { 136933965Sjdp /* Caller must give an error. */ 137033965Sjdp r_symndx = 0; 137133965Sjdp } 137233965Sjdp relocation = 0; 137333965Sjdp } 137433965Sjdp 137533965Sjdp /* Write out the new r_symndx value. */ 137689857Sobrien H_PUT_32 (input_bfd, r_symndx, ext_rel->r_symndx); 137733965Sjdp 137833965Sjdp return relocation; 137933965Sjdp} 138033965Sjdp 138133965Sjdp/* Relocate a section while linking an Alpha ECOFF file. This is 138233965Sjdp quite similar to get_relocated_section_contents. Perhaps they 138333965Sjdp could be combined somehow. */ 138433965Sjdp 1385130561Sobrienstatic bfd_boolean 138633965Sjdpalpha_relocate_section (output_bfd, info, input_bfd, input_section, 138733965Sjdp contents, external_relocs) 138833965Sjdp bfd *output_bfd; 138933965Sjdp struct bfd_link_info *info; 139033965Sjdp bfd *input_bfd; 139133965Sjdp asection *input_section; 139233965Sjdp bfd_byte *contents; 139333965Sjdp PTR external_relocs; 139433965Sjdp{ 139533965Sjdp asection **symndx_to_section, *lita_sec; 139633965Sjdp struct ecoff_link_hash_entry **sym_hashes; 139733965Sjdp bfd_vma gp; 1398130561Sobrien bfd_boolean gp_undefined; 139933965Sjdp bfd_vma stack[RELOC_STACKSIZE]; 140033965Sjdp int tos = 0; 140133965Sjdp struct external_reloc *ext_rel; 140233965Sjdp struct external_reloc *ext_rel_end; 140389857Sobrien bfd_size_type amt; 140433965Sjdp 140533965Sjdp /* We keep a table mapping the symndx found in an internal reloc to 140633965Sjdp the appropriate section. This is faster than looking up the 140733965Sjdp section by name each time. */ 140833965Sjdp symndx_to_section = ecoff_data (input_bfd)->symndx_to_section; 140933965Sjdp if (symndx_to_section == (asection **) NULL) 141033965Sjdp { 141189857Sobrien amt = NUM_RELOC_SECTIONS * sizeof (asection *); 141289857Sobrien symndx_to_section = (asection **) bfd_alloc (input_bfd, amt); 141333965Sjdp if (!symndx_to_section) 1414130561Sobrien return FALSE; 141533965Sjdp 141633965Sjdp symndx_to_section[RELOC_SECTION_NONE] = NULL; 141733965Sjdp symndx_to_section[RELOC_SECTION_TEXT] = 141833965Sjdp bfd_get_section_by_name (input_bfd, ".text"); 141933965Sjdp symndx_to_section[RELOC_SECTION_RDATA] = 142033965Sjdp bfd_get_section_by_name (input_bfd, ".rdata"); 142133965Sjdp symndx_to_section[RELOC_SECTION_DATA] = 142233965Sjdp bfd_get_section_by_name (input_bfd, ".data"); 142333965Sjdp symndx_to_section[RELOC_SECTION_SDATA] = 142433965Sjdp bfd_get_section_by_name (input_bfd, ".sdata"); 142533965Sjdp symndx_to_section[RELOC_SECTION_SBSS] = 142633965Sjdp bfd_get_section_by_name (input_bfd, ".sbss"); 142733965Sjdp symndx_to_section[RELOC_SECTION_BSS] = 142833965Sjdp bfd_get_section_by_name (input_bfd, ".bss"); 142933965Sjdp symndx_to_section[RELOC_SECTION_INIT] = 143033965Sjdp bfd_get_section_by_name (input_bfd, ".init"); 143133965Sjdp symndx_to_section[RELOC_SECTION_LIT8] = 143233965Sjdp bfd_get_section_by_name (input_bfd, ".lit8"); 143333965Sjdp symndx_to_section[RELOC_SECTION_LIT4] = 143433965Sjdp bfd_get_section_by_name (input_bfd, ".lit4"); 143533965Sjdp symndx_to_section[RELOC_SECTION_XDATA] = 143633965Sjdp bfd_get_section_by_name (input_bfd, ".xdata"); 143733965Sjdp symndx_to_section[RELOC_SECTION_PDATA] = 143833965Sjdp bfd_get_section_by_name (input_bfd, ".pdata"); 143933965Sjdp symndx_to_section[RELOC_SECTION_FINI] = 144033965Sjdp bfd_get_section_by_name (input_bfd, ".fini"); 144133965Sjdp symndx_to_section[RELOC_SECTION_LITA] = 144233965Sjdp bfd_get_section_by_name (input_bfd, ".lita"); 144333965Sjdp symndx_to_section[RELOC_SECTION_ABS] = bfd_abs_section_ptr; 144433965Sjdp symndx_to_section[RELOC_SECTION_RCONST] = 144533965Sjdp bfd_get_section_by_name (input_bfd, ".rconst"); 144633965Sjdp 144733965Sjdp ecoff_data (input_bfd)->symndx_to_section = symndx_to_section; 144833965Sjdp } 144933965Sjdp 145033965Sjdp sym_hashes = ecoff_data (input_bfd)->sym_hashes; 145133965Sjdp 145233965Sjdp /* On the Alpha, the .lita section must be addressable by the global 145333965Sjdp pointer. To support large programs, we need to allow multiple 145433965Sjdp global pointers. This works as long as each input .lita section 145533965Sjdp is <64KB big. This implies that when producing relocatable 145677298Sobrien output, the .lita section is limited to 64KB. . */ 145733965Sjdp 145833965Sjdp lita_sec = symndx_to_section[RELOC_SECTION_LITA]; 145933965Sjdp gp = _bfd_get_gp_value (output_bfd); 1460130561Sobrien if (! info->relocatable && lita_sec != NULL) 146133965Sjdp { 146233965Sjdp struct ecoff_section_tdata *lita_sec_data; 146333965Sjdp 146433965Sjdp /* Make sure we have a section data structure to which we can 146533965Sjdp hang on to the gp value we pick for the section. */ 146633965Sjdp lita_sec_data = ecoff_section_data (input_bfd, lita_sec); 146733965Sjdp if (lita_sec_data == NULL) 146833965Sjdp { 146989857Sobrien amt = sizeof (struct ecoff_section_tdata); 147033965Sjdp lita_sec_data = ((struct ecoff_section_tdata *) 147189857Sobrien bfd_zalloc (input_bfd, amt)); 1472218822Sdim lita_sec->used_by_bfd = lita_sec_data; 147333965Sjdp } 147433965Sjdp 147533965Sjdp if (lita_sec_data->gp != 0) 147633965Sjdp { 147733965Sjdp /* If we already assigned a gp to this section, we better 147833965Sjdp stick with that value. */ 147933965Sjdp gp = lita_sec_data->gp; 148033965Sjdp } 148133965Sjdp else 148233965Sjdp { 148333965Sjdp bfd_vma lita_vma; 148433965Sjdp bfd_size_type lita_size; 148533965Sjdp 148633965Sjdp lita_vma = lita_sec->output_offset + lita_sec->output_section->vma; 1487218822Sdim lita_size = lita_sec->size; 148833965Sjdp 148933965Sjdp if (gp == 0 149033965Sjdp || lita_vma < gp - 0x8000 149133965Sjdp || lita_vma + lita_size >= gp + 0x8000) 149233965Sjdp { 149333965Sjdp /* Either gp hasn't been set at all or the current gp 149433965Sjdp cannot address this .lita section. In both cases we 149533965Sjdp reset the gp to point into the "middle" of the 149633965Sjdp current input .lita section. */ 149733965Sjdp if (gp && !ecoff_data (output_bfd)->issued_multiple_gp_warning) 149833965Sjdp { 149933965Sjdp (*info->callbacks->warning) (info, 150060484Sobrien _("using multiple gp values"), 150133965Sjdp (char *) NULL, output_bfd, 150233965Sjdp (asection *) NULL, (bfd_vma) 0); 1503130561Sobrien ecoff_data (output_bfd)->issued_multiple_gp_warning = TRUE; 150433965Sjdp } 150533965Sjdp if (lita_vma < gp - 0x8000) 150633965Sjdp gp = lita_vma + lita_size - 0x8000; 150733965Sjdp else 150833965Sjdp gp = lita_vma + 0x8000; 150933965Sjdp 151033965Sjdp } 151133965Sjdp 151233965Sjdp lita_sec_data->gp = gp; 151333965Sjdp } 151433965Sjdp 151533965Sjdp _bfd_set_gp_value (output_bfd, gp); 151633965Sjdp } 151733965Sjdp 151833965Sjdp gp_undefined = (gp == 0); 151933965Sjdp 152033965Sjdp BFD_ASSERT (bfd_header_little_endian (output_bfd)); 152133965Sjdp BFD_ASSERT (bfd_header_little_endian (input_bfd)); 152233965Sjdp 152333965Sjdp ext_rel = (struct external_reloc *) external_relocs; 152433965Sjdp ext_rel_end = ext_rel + input_section->reloc_count; 152533965Sjdp for (; ext_rel < ext_rel_end; ext_rel++) 152633965Sjdp { 152733965Sjdp bfd_vma r_vaddr; 152833965Sjdp unsigned long r_symndx; 152933965Sjdp int r_type; 153033965Sjdp int r_extern; 153133965Sjdp int r_offset; 153233965Sjdp int r_size; 1533130561Sobrien bfd_boolean relocatep; 1534130561Sobrien bfd_boolean adjust_addrp; 1535130561Sobrien bfd_boolean gp_usedp; 153633965Sjdp bfd_vma addend; 153733965Sjdp 153889857Sobrien r_vaddr = H_GET_64 (input_bfd, ext_rel->r_vaddr); 153989857Sobrien r_symndx = H_GET_32 (input_bfd, ext_rel->r_symndx); 154033965Sjdp 154133965Sjdp r_type = ((ext_rel->r_bits[0] & RELOC_BITS0_TYPE_LITTLE) 154233965Sjdp >> RELOC_BITS0_TYPE_SH_LITTLE); 154333965Sjdp r_extern = (ext_rel->r_bits[1] & RELOC_BITS1_EXTERN_LITTLE) != 0; 154433965Sjdp r_offset = ((ext_rel->r_bits[1] & RELOC_BITS1_OFFSET_LITTLE) 154533965Sjdp >> RELOC_BITS1_OFFSET_SH_LITTLE); 154633965Sjdp /* Ignored the reserved bits. */ 154733965Sjdp r_size = ((ext_rel->r_bits[3] & RELOC_BITS3_SIZE_LITTLE) 154833965Sjdp >> RELOC_BITS3_SIZE_SH_LITTLE); 154933965Sjdp 1550130561Sobrien relocatep = FALSE; 1551130561Sobrien adjust_addrp = TRUE; 1552130561Sobrien gp_usedp = FALSE; 155333965Sjdp addend = 0; 155433965Sjdp 155533965Sjdp switch (r_type) 155633965Sjdp { 1557218822Sdim case ALPHA_R_GPRELHIGH: 1558218822Sdim (*_bfd_error_handler) 1559218822Sdim (_("%B: unsupported relocation: ALPHA_R_GPRELHIGH"), 1560218822Sdim input_bfd); 1561218822Sdim bfd_set_error (bfd_error_bad_value); 1562218822Sdim continue; 1563218822Sdim 1564218822Sdim case ALPHA_R_GPRELLOW: 1565218822Sdim (*_bfd_error_handler) 1566218822Sdim (_("%B: unsupported relocation: ALPHA_R_GPRELLOW"), 1567218822Sdim input_bfd); 1568218822Sdim bfd_set_error (bfd_error_bad_value); 1569218822Sdim continue; 1570218822Sdim 157133965Sjdp default: 1572218822Sdim (*_bfd_error_handler) 1573218822Sdim (_("%B: unknown relocation type %d"), 1574218822Sdim input_bfd, (int) r_type); 1575218822Sdim bfd_set_error (bfd_error_bad_value); 1576218822Sdim continue; 157733965Sjdp 157833965Sjdp case ALPHA_R_IGNORE: 157933965Sjdp /* This reloc appears after a GPDISP reloc. On earlier 158033965Sjdp versions of OSF/1, It marked the position of the second 158133965Sjdp instruction to be altered by the GPDISP reloc, but it is 158233965Sjdp not otherwise used for anything. For some reason, the 158333965Sjdp address of the relocation does not appear to include the 158433965Sjdp section VMA, unlike the other relocation types. */ 1585130561Sobrien if (info->relocatable) 158689857Sobrien H_PUT_64 (input_bfd, input_section->output_offset + r_vaddr, 158789857Sobrien ext_rel->r_vaddr); 1588130561Sobrien adjust_addrp = FALSE; 158933965Sjdp break; 159033965Sjdp 159133965Sjdp case ALPHA_R_REFLONG: 159233965Sjdp case ALPHA_R_REFQUAD: 159333965Sjdp case ALPHA_R_HINT: 1594130561Sobrien relocatep = TRUE; 159533965Sjdp break; 159633965Sjdp 159733965Sjdp case ALPHA_R_BRADDR: 159833965Sjdp case ALPHA_R_SREL16: 159933965Sjdp case ALPHA_R_SREL32: 160033965Sjdp case ALPHA_R_SREL64: 160133965Sjdp if (r_extern) 160233965Sjdp addend += - (r_vaddr + 4); 1603130561Sobrien relocatep = TRUE; 160433965Sjdp break; 160533965Sjdp 160633965Sjdp case ALPHA_R_GPREL32: 160733965Sjdp /* This relocation is used in a switch table. It is a 32 160833965Sjdp bit offset from the current GP value. We must adjust it 160933965Sjdp by the different between the original GP value and the 161033965Sjdp current GP value. */ 1611130561Sobrien relocatep = TRUE; 161233965Sjdp addend = ecoff_data (input_bfd)->gp - gp; 1613130561Sobrien gp_usedp = TRUE; 161433965Sjdp break; 161533965Sjdp 161633965Sjdp case ALPHA_R_LITERAL: 161733965Sjdp /* This is a reference to a literal value, generally 161833965Sjdp (always?) in the .lita section. This is a 16 bit GP 161933965Sjdp relative relocation. Sometimes the subsequent reloc is a 162033965Sjdp LITUSE reloc, which indicates how this reloc is used. 162133965Sjdp This sometimes permits rewriting the two instructions 162233965Sjdp referred to by the LITERAL and the LITUSE into different 162333965Sjdp instructions which do not refer to .lita. This can save 162433965Sjdp a memory reference, and permits removing a value from 162533965Sjdp .lita thus saving GP relative space. 162633965Sjdp 162733965Sjdp We do not these optimizations. To do them we would need 162833965Sjdp to arrange to link the .lita section first, so that by 162933965Sjdp the time we got here we would know the final values to 163033965Sjdp use. This would not be particularly difficult, but it is 163133965Sjdp not currently implemented. */ 163233965Sjdp 163333965Sjdp /* I believe that the LITERAL reloc will only apply to a ldq 163433965Sjdp or ldl instruction, so check my assumption. */ 163533965Sjdp { 163633965Sjdp unsigned long insn; 163733965Sjdp 163833965Sjdp insn = bfd_get_32 (input_bfd, 163933965Sjdp contents + r_vaddr - input_section->vma); 164033965Sjdp BFD_ASSERT (((insn >> 26) & 0x3f) == 0x29 164133965Sjdp || ((insn >> 26) & 0x3f) == 0x28); 164233965Sjdp } 164333965Sjdp 1644130561Sobrien relocatep = TRUE; 164533965Sjdp addend = ecoff_data (input_bfd)->gp - gp; 1646130561Sobrien gp_usedp = TRUE; 164733965Sjdp break; 164833965Sjdp 164933965Sjdp case ALPHA_R_LITUSE: 165033965Sjdp /* See ALPHA_R_LITERAL above for the uses of this reloc. It 165133965Sjdp does not cause anything to happen, itself. */ 165233965Sjdp break; 165377298Sobrien 165433965Sjdp case ALPHA_R_GPDISP: 165533965Sjdp /* This marks the ldah of an ldah/lda pair which loads the 165633965Sjdp gp register with the difference of the gp value and the 165733965Sjdp current location. The second of the pair is r_symndx 165833965Sjdp bytes ahead. It used to be marked with an ALPHA_R_IGNORE 165933965Sjdp reloc, but OSF/1 3.2 no longer does that. */ 166033965Sjdp { 166133965Sjdp unsigned long insn1, insn2; 166233965Sjdp 166333965Sjdp /* Get the two instructions. */ 166433965Sjdp insn1 = bfd_get_32 (input_bfd, 166533965Sjdp contents + r_vaddr - input_section->vma); 166633965Sjdp insn2 = bfd_get_32 (input_bfd, 166733965Sjdp (contents 166833965Sjdp + r_vaddr 166933965Sjdp - input_section->vma 167033965Sjdp + r_symndx)); 167133965Sjdp 167233965Sjdp BFD_ASSERT (((insn1 >> 26) & 0x3f) == 0x09); /* ldah */ 167333965Sjdp BFD_ASSERT (((insn2 >> 26) & 0x3f) == 0x08); /* lda */ 167433965Sjdp 167533965Sjdp /* Get the existing addend. We must account for the sign 167633965Sjdp extension done by lda and ldah. */ 167733965Sjdp addend = ((insn1 & 0xffff) << 16) + (insn2 & 0xffff); 167833965Sjdp if (insn1 & 0x8000) 167933965Sjdp { 168033965Sjdp /* This is addend -= 0x100000000 without causing an 168133965Sjdp integer overflow on a 32 bit host. */ 168233965Sjdp addend -= 0x80000000; 168333965Sjdp addend -= 0x80000000; 168433965Sjdp } 168533965Sjdp if (insn2 & 0x8000) 168633965Sjdp addend -= 0x10000; 168733965Sjdp 168833965Sjdp /* The existing addend includes the difference between the 168933965Sjdp gp of the input BFD and the address in the input BFD. 169033965Sjdp We want to change this to the difference between the 169133965Sjdp final GP and the final address. */ 169233965Sjdp addend += (gp 169333965Sjdp - ecoff_data (input_bfd)->gp 169433965Sjdp + input_section->vma 169533965Sjdp - (input_section->output_section->vma 169633965Sjdp + input_section->output_offset)); 169733965Sjdp 169833965Sjdp /* Change the instructions, accounting for the sign 169933965Sjdp extension, and write them out. */ 170033965Sjdp if (addend & 0x8000) 170133965Sjdp addend += 0x10000; 170233965Sjdp insn1 = (insn1 & 0xffff0000) | ((addend >> 16) & 0xffff); 170333965Sjdp insn2 = (insn2 & 0xffff0000) | (addend & 0xffff); 170433965Sjdp 170533965Sjdp bfd_put_32 (input_bfd, (bfd_vma) insn1, 170633965Sjdp contents + r_vaddr - input_section->vma); 170733965Sjdp bfd_put_32 (input_bfd, (bfd_vma) insn2, 170833965Sjdp contents + r_vaddr - input_section->vma + r_symndx); 170933965Sjdp 1710130561Sobrien gp_usedp = TRUE; 171133965Sjdp } 171233965Sjdp break; 171377298Sobrien 171433965Sjdp case ALPHA_R_OP_PUSH: 171533965Sjdp case ALPHA_R_OP_PSUB: 171633965Sjdp case ALPHA_R_OP_PRSHIFT: 171733965Sjdp /* Manipulate values on the reloc evaluation stack. The 171833965Sjdp r_vaddr field is not an address in input_section, it is 171933965Sjdp the current value (including any addend) of the object 172033965Sjdp being used. */ 172133965Sjdp if (! r_extern) 172233965Sjdp { 172333965Sjdp asection *s; 172433965Sjdp 172533965Sjdp s = symndx_to_section[r_symndx]; 172633965Sjdp if (s == (asection *) NULL) 172733965Sjdp abort (); 172833965Sjdp addend = s->output_section->vma + s->output_offset - s->vma; 172933965Sjdp } 173033965Sjdp else 173133965Sjdp { 173233965Sjdp struct ecoff_link_hash_entry *h; 173333965Sjdp 173433965Sjdp h = sym_hashes[r_symndx]; 173533965Sjdp if (h == (struct ecoff_link_hash_entry *) NULL) 173633965Sjdp abort (); 173733965Sjdp 1738130561Sobrien if (! info->relocatable) 173933965Sjdp { 174033965Sjdp if (h->root.type == bfd_link_hash_defined 174133965Sjdp || h->root.type == bfd_link_hash_defweak) 174233965Sjdp addend = (h->root.u.def.value 174333965Sjdp + h->root.u.def.section->output_section->vma 174433965Sjdp + h->root.u.def.section->output_offset); 174533965Sjdp else 174633965Sjdp { 174733965Sjdp /* Note that we pass the address as 0, since we 174833965Sjdp do not have a meaningful number for the 174933965Sjdp location within the section that is being 175033965Sjdp relocated. */ 175133965Sjdp if (! ((*info->callbacks->undefined_symbol) 175233965Sjdp (info, h->root.root.string, input_bfd, 1753130561Sobrien input_section, (bfd_vma) 0, TRUE))) 1754130561Sobrien return FALSE; 175533965Sjdp addend = 0; 175633965Sjdp } 175733965Sjdp } 175833965Sjdp else 175933965Sjdp { 176033965Sjdp if (h->root.type != bfd_link_hash_defined 176133965Sjdp && h->root.type != bfd_link_hash_defweak 176233965Sjdp && h->indx == -1) 176333965Sjdp { 176433965Sjdp /* This symbol is not being written out. Pass 176533965Sjdp the address as 0, as with undefined_symbol, 176633965Sjdp above. */ 176733965Sjdp if (! ((*info->callbacks->unattached_reloc) 176833965Sjdp (info, h->root.root.string, input_bfd, 176933965Sjdp input_section, (bfd_vma) 0))) 1770130561Sobrien return FALSE; 177133965Sjdp } 177233965Sjdp 177333965Sjdp addend = alpha_convert_external_reloc (output_bfd, info, 177433965Sjdp input_bfd, 177533965Sjdp ext_rel, h); 177633965Sjdp } 177733965Sjdp } 177833965Sjdp 177933965Sjdp addend += r_vaddr; 178033965Sjdp 1781130561Sobrien if (info->relocatable) 178233965Sjdp { 178333965Sjdp /* Adjust r_vaddr by the addend. */ 178489857Sobrien H_PUT_64 (input_bfd, addend, ext_rel->r_vaddr); 178533965Sjdp } 178633965Sjdp else 178733965Sjdp { 178833965Sjdp switch (r_type) 178933965Sjdp { 179033965Sjdp case ALPHA_R_OP_PUSH: 179133965Sjdp if (tos >= RELOC_STACKSIZE) 179233965Sjdp abort (); 179333965Sjdp stack[tos++] = addend; 179433965Sjdp break; 179533965Sjdp 179633965Sjdp case ALPHA_R_OP_PSUB: 179733965Sjdp if (tos == 0) 179833965Sjdp abort (); 179933965Sjdp stack[tos - 1] -= addend; 180033965Sjdp break; 180133965Sjdp 180233965Sjdp case ALPHA_R_OP_PRSHIFT: 180333965Sjdp if (tos == 0) 180433965Sjdp abort (); 180533965Sjdp stack[tos - 1] >>= addend; 180633965Sjdp break; 180733965Sjdp } 180833965Sjdp } 180933965Sjdp 1810130561Sobrien adjust_addrp = FALSE; 181133965Sjdp break; 181233965Sjdp 181333965Sjdp case ALPHA_R_OP_STORE: 181433965Sjdp /* Store a value from the reloc stack into a bitfield. If 1815130561Sobrien we are generating relocatable output, all we do is 181633965Sjdp adjust the address of the reloc. */ 1817130561Sobrien if (! info->relocatable) 181833965Sjdp { 181933965Sjdp bfd_vma mask; 182033965Sjdp bfd_vma val; 182133965Sjdp 182233965Sjdp if (tos == 0) 182333965Sjdp abort (); 182433965Sjdp 182533965Sjdp /* Get the relocation mask. The separate steps and the 182633965Sjdp casts to bfd_vma are attempts to avoid a bug in the 182733965Sjdp Alpha OSF 1.3 C compiler. See reloc.c for more 182833965Sjdp details. */ 182933965Sjdp mask = 1; 183033965Sjdp mask <<= (bfd_vma) r_size; 183133965Sjdp mask -= 1; 183233965Sjdp 183333965Sjdp /* FIXME: I don't know what kind of overflow checking, 183433965Sjdp if any, should be done here. */ 183533965Sjdp val = bfd_get_64 (input_bfd, 183633965Sjdp contents + r_vaddr - input_section->vma); 183733965Sjdp val &=~ mask << (bfd_vma) r_offset; 183833965Sjdp val |= (stack[--tos] & mask) << (bfd_vma) r_offset; 183933965Sjdp bfd_put_64 (input_bfd, val, 184033965Sjdp contents + r_vaddr - input_section->vma); 184133965Sjdp } 184233965Sjdp break; 184333965Sjdp 184433965Sjdp case ALPHA_R_GPVALUE: 184533965Sjdp /* I really don't know if this does the right thing. */ 184633965Sjdp gp = ecoff_data (input_bfd)->gp + r_symndx; 1847130561Sobrien gp_undefined = FALSE; 184833965Sjdp break; 184933965Sjdp } 185033965Sjdp 185133965Sjdp if (relocatep) 185233965Sjdp { 185333965Sjdp reloc_howto_type *howto; 185433965Sjdp struct ecoff_link_hash_entry *h = NULL; 185533965Sjdp asection *s = NULL; 185633965Sjdp bfd_vma relocation; 185733965Sjdp bfd_reloc_status_type r; 185833965Sjdp 185933965Sjdp /* Perform a relocation. */ 186033965Sjdp 186133965Sjdp howto = &alpha_howto_table[r_type]; 186233965Sjdp 186333965Sjdp if (r_extern) 186433965Sjdp { 186533965Sjdp h = sym_hashes[r_symndx]; 186633965Sjdp /* If h is NULL, that means that there is a reloc 186733965Sjdp against an external symbol which we thought was just 186833965Sjdp a debugging symbol. This should not happen. */ 186933965Sjdp if (h == (struct ecoff_link_hash_entry *) NULL) 187033965Sjdp abort (); 187133965Sjdp } 187233965Sjdp else 187333965Sjdp { 187433965Sjdp if (r_symndx >= NUM_RELOC_SECTIONS) 187533965Sjdp s = NULL; 187633965Sjdp else 187733965Sjdp s = symndx_to_section[r_symndx]; 187833965Sjdp 187933965Sjdp if (s == (asection *) NULL) 188033965Sjdp abort (); 188133965Sjdp } 188233965Sjdp 1883130561Sobrien if (info->relocatable) 188433965Sjdp { 1885130561Sobrien /* We are generating relocatable output, and must 188633965Sjdp convert the existing reloc. */ 188733965Sjdp if (r_extern) 188833965Sjdp { 188933965Sjdp if (h->root.type != bfd_link_hash_defined 189033965Sjdp && h->root.type != bfd_link_hash_defweak 189133965Sjdp && h->indx == -1) 189233965Sjdp { 189333965Sjdp /* This symbol is not being written out. */ 189433965Sjdp if (! ((*info->callbacks->unattached_reloc) 189533965Sjdp (info, h->root.root.string, input_bfd, 189633965Sjdp input_section, r_vaddr - input_section->vma))) 1897130561Sobrien return FALSE; 189833965Sjdp } 189933965Sjdp 190033965Sjdp relocation = alpha_convert_external_reloc (output_bfd, 190133965Sjdp info, 190233965Sjdp input_bfd, 190333965Sjdp ext_rel, 190433965Sjdp h); 190533965Sjdp } 190633965Sjdp else 190733965Sjdp { 190833965Sjdp /* This is a relocation against a section. Adjust 190933965Sjdp the value by the amount the section moved. */ 191033965Sjdp relocation = (s->output_section->vma 191133965Sjdp + s->output_offset 191233965Sjdp - s->vma); 191333965Sjdp } 191433965Sjdp 191533965Sjdp /* If this is PC relative, the existing object file 191633965Sjdp appears to already have the reloc worked out. We 191733965Sjdp must subtract out the old value and add in the new 191833965Sjdp one. */ 191933965Sjdp if (howto->pc_relative) 192033965Sjdp relocation -= (input_section->output_section->vma 192133965Sjdp + input_section->output_offset 192233965Sjdp - input_section->vma); 192333965Sjdp 192433965Sjdp /* Put in any addend. */ 192533965Sjdp relocation += addend; 192633965Sjdp 192733965Sjdp /* Adjust the contents. */ 192833965Sjdp r = _bfd_relocate_contents (howto, input_bfd, relocation, 192933965Sjdp (contents 193033965Sjdp + r_vaddr 193133965Sjdp - input_section->vma)); 193233965Sjdp } 193333965Sjdp else 193433965Sjdp { 193533965Sjdp /* We are producing a final executable. */ 193633965Sjdp if (r_extern) 193733965Sjdp { 193833965Sjdp /* This is a reloc against a symbol. */ 193933965Sjdp if (h->root.type == bfd_link_hash_defined 194033965Sjdp || h->root.type == bfd_link_hash_defweak) 194133965Sjdp { 194233965Sjdp asection *hsec; 194333965Sjdp 194433965Sjdp hsec = h->root.u.def.section; 194533965Sjdp relocation = (h->root.u.def.value 194633965Sjdp + hsec->output_section->vma 194733965Sjdp + hsec->output_offset); 194833965Sjdp } 194933965Sjdp else 195033965Sjdp { 195133965Sjdp if (! ((*info->callbacks->undefined_symbol) 195233965Sjdp (info, h->root.root.string, input_bfd, 195333965Sjdp input_section, 1954130561Sobrien r_vaddr - input_section->vma, TRUE))) 1955130561Sobrien return FALSE; 195633965Sjdp relocation = 0; 195733965Sjdp } 195833965Sjdp } 195933965Sjdp else 196033965Sjdp { 196133965Sjdp /* This is a reloc against a section. */ 196233965Sjdp relocation = (s->output_section->vma 196333965Sjdp + s->output_offset 196433965Sjdp - s->vma); 196533965Sjdp 196633965Sjdp /* Adjust a PC relative relocation by removing the 196733965Sjdp reference to the original source section. */ 196833965Sjdp if (howto->pc_relative) 196933965Sjdp relocation += input_section->vma; 197033965Sjdp } 197133965Sjdp 197233965Sjdp r = _bfd_final_link_relocate (howto, 197333965Sjdp input_bfd, 197433965Sjdp input_section, 197533965Sjdp contents, 197633965Sjdp r_vaddr - input_section->vma, 197733965Sjdp relocation, 197833965Sjdp addend); 197933965Sjdp } 198033965Sjdp 198133965Sjdp if (r != bfd_reloc_ok) 198233965Sjdp { 198333965Sjdp switch (r) 198433965Sjdp { 198533965Sjdp default: 198633965Sjdp case bfd_reloc_outofrange: 198733965Sjdp abort (); 198833965Sjdp case bfd_reloc_overflow: 198933965Sjdp { 199033965Sjdp const char *name; 199133965Sjdp 199233965Sjdp if (r_extern) 199333965Sjdp name = sym_hashes[r_symndx]->root.root.string; 199433965Sjdp else 199533965Sjdp name = bfd_section_name (input_bfd, 199633965Sjdp symndx_to_section[r_symndx]); 199733965Sjdp if (! ((*info->callbacks->reloc_overflow) 1998218822Sdim (info, NULL, name, 1999218822Sdim alpha_howto_table[r_type].name, 200033965Sjdp (bfd_vma) 0, input_bfd, input_section, 200133965Sjdp r_vaddr - input_section->vma))) 2002130561Sobrien return FALSE; 200333965Sjdp } 200433965Sjdp break; 200533965Sjdp } 200633965Sjdp } 200733965Sjdp } 200833965Sjdp 2009130561Sobrien if (info->relocatable && adjust_addrp) 201033965Sjdp { 201133965Sjdp /* Change the address of the relocation. */ 201289857Sobrien H_PUT_64 (input_bfd, 201389857Sobrien (input_section->output_section->vma 201489857Sobrien + input_section->output_offset 201589857Sobrien - input_section->vma 201689857Sobrien + r_vaddr), 201789857Sobrien ext_rel->r_vaddr); 201833965Sjdp } 201933965Sjdp 202033965Sjdp if (gp_usedp && gp_undefined) 202133965Sjdp { 202233965Sjdp if (! ((*info->callbacks->reloc_dangerous) 202389857Sobrien (info, _("GP relative relocation used when GP not defined"), 202433965Sjdp input_bfd, input_section, r_vaddr - input_section->vma))) 2025130561Sobrien return FALSE; 202633965Sjdp /* Only give the error once per link. */ 202733965Sjdp gp = 4; 202833965Sjdp _bfd_set_gp_value (output_bfd, gp); 2029130561Sobrien gp_undefined = FALSE; 203033965Sjdp } 203133965Sjdp } 203233965Sjdp 203333965Sjdp if (tos != 0) 203433965Sjdp abort (); 203533965Sjdp 2036130561Sobrien return TRUE; 203733965Sjdp} 203833965Sjdp 203933965Sjdp/* Do final adjustments to the filehdr and the aouthdr. This routine 204033965Sjdp sets the dynamic bits in the file header. */ 204133965Sjdp 2042130561Sobrienstatic bfd_boolean 204333965Sjdpalpha_adjust_headers (abfd, fhdr, ahdr) 204433965Sjdp bfd *abfd; 204533965Sjdp struct internal_filehdr *fhdr; 204678828Sobrien struct internal_aouthdr *ahdr ATTRIBUTE_UNUSED; 204733965Sjdp{ 204833965Sjdp if ((abfd->flags & (DYNAMIC | EXEC_P)) == (DYNAMIC | EXEC_P)) 204933965Sjdp fhdr->f_flags |= F_ALPHA_CALL_SHARED; 205033965Sjdp else if ((abfd->flags & DYNAMIC) != 0) 205133965Sjdp fhdr->f_flags |= F_ALPHA_SHARABLE; 2052130561Sobrien return TRUE; 205333965Sjdp} 205433965Sjdp 205533965Sjdp/* Archive handling. In OSF/1 (or Digital Unix) v3.2, Digital 205633965Sjdp introduced archive packing, in which the elements in an archive are 205733965Sjdp optionally compressed using a simple dictionary scheme. We know 205833965Sjdp how to read such archives, but we don't write them. */ 205933965Sjdp 206033965Sjdp#define alpha_ecoff_slurp_armap _bfd_ecoff_slurp_armap 206133965Sjdp#define alpha_ecoff_slurp_extended_name_table \ 206233965Sjdp _bfd_ecoff_slurp_extended_name_table 206333965Sjdp#define alpha_ecoff_construct_extended_name_table \ 206433965Sjdp _bfd_ecoff_construct_extended_name_table 206533965Sjdp#define alpha_ecoff_truncate_arname _bfd_ecoff_truncate_arname 206633965Sjdp#define alpha_ecoff_write_armap _bfd_ecoff_write_armap 206733965Sjdp#define alpha_ecoff_generic_stat_arch_elt _bfd_ecoff_generic_stat_arch_elt 206833965Sjdp#define alpha_ecoff_update_armap_timestamp _bfd_ecoff_update_armap_timestamp 206933965Sjdp 207033965Sjdp/* A compressed file uses this instead of ARFMAG. */ 207133965Sjdp 207233965Sjdp#define ARFZMAG "Z\012" 207333965Sjdp 207433965Sjdp/* Read an archive header. This is like the standard routine, but it 207533965Sjdp also accepts ARFZMAG. */ 207633965Sjdp 207733965Sjdpstatic PTR 207833965Sjdpalpha_ecoff_read_ar_hdr (abfd) 207933965Sjdp bfd *abfd; 208033965Sjdp{ 208133965Sjdp struct areltdata *ret; 208233965Sjdp struct ar_hdr *h; 208333965Sjdp 208433965Sjdp ret = (struct areltdata *) _bfd_generic_read_ar_hdr_mag (abfd, ARFZMAG); 208533965Sjdp if (ret == NULL) 208633965Sjdp return NULL; 208733965Sjdp 208833965Sjdp h = (struct ar_hdr *) ret->arch_header; 208933965Sjdp if (strncmp (h->ar_fmag, ARFZMAG, 2) == 0) 209033965Sjdp { 209133965Sjdp bfd_byte ab[8]; 209233965Sjdp 209333965Sjdp /* This is a compressed file. We must set the size correctly. 209433965Sjdp The size is the eight bytes after the dummy file header. */ 209589857Sobrien if (bfd_seek (abfd, (file_ptr) FILHSZ, SEEK_CUR) != 0 209689857Sobrien || bfd_bread (ab, (bfd_size_type) 8, abfd) != 8 209789857Sobrien || bfd_seek (abfd, (file_ptr) (- (FILHSZ + 8)), SEEK_CUR) != 0) 209833965Sjdp return NULL; 209933965Sjdp 210089857Sobrien ret->parsed_size = H_GET_64 (abfd, ab); 210133965Sjdp } 210233965Sjdp 210333965Sjdp return (PTR) ret; 210433965Sjdp} 210533965Sjdp 210633965Sjdp/* Get an archive element at a specified file position. This is where 210733965Sjdp we uncompress the archive element if necessary. */ 210833965Sjdp 210933965Sjdpstatic bfd * 211033965Sjdpalpha_ecoff_get_elt_at_filepos (archive, filepos) 211133965Sjdp bfd *archive; 211233965Sjdp file_ptr filepos; 211333965Sjdp{ 211433965Sjdp bfd *nbfd = NULL; 211533965Sjdp struct areltdata *tdata; 211633965Sjdp struct ar_hdr *hdr; 211733965Sjdp bfd_byte ab[8]; 211833965Sjdp bfd_size_type size; 211933965Sjdp bfd_byte *buf, *p; 212033965Sjdp struct bfd_in_memory *bim; 212133965Sjdp 212233965Sjdp nbfd = _bfd_get_elt_at_filepos (archive, filepos); 212333965Sjdp if (nbfd == NULL) 212433965Sjdp goto error_return; 212533965Sjdp 212633965Sjdp if ((nbfd->flags & BFD_IN_MEMORY) != 0) 212733965Sjdp { 212833965Sjdp /* We have already expanded this BFD. */ 212933965Sjdp return nbfd; 213033965Sjdp } 213133965Sjdp 213233965Sjdp tdata = (struct areltdata *) nbfd->arelt_data; 213333965Sjdp hdr = (struct ar_hdr *) tdata->arch_header; 213433965Sjdp if (strncmp (hdr->ar_fmag, ARFZMAG, 2) != 0) 213533965Sjdp return nbfd; 213633965Sjdp 213733965Sjdp /* We must uncompress this element. We do this by copying it into a 213889857Sobrien memory buffer, and making bfd_bread and bfd_seek use that buffer. 213933965Sjdp This can use a lot of memory, but it's simpler than getting a 214033965Sjdp temporary file, making that work with the file descriptor caching 214133965Sjdp code, and making sure that it is deleted at all appropriate 214233965Sjdp times. It can be changed if it ever becomes important. */ 214333965Sjdp 214433965Sjdp /* The compressed file starts with a dummy ECOFF file header. */ 214589857Sobrien if (bfd_seek (nbfd, (file_ptr) FILHSZ, SEEK_SET) != 0) 214633965Sjdp goto error_return; 214733965Sjdp 214833965Sjdp /* The next eight bytes are the real file size. */ 214989857Sobrien if (bfd_bread (ab, (bfd_size_type) 8, nbfd) != 8) 215033965Sjdp goto error_return; 215189857Sobrien size = H_GET_64 (nbfd, ab); 215233965Sjdp 215333965Sjdp if (size == 0) 215433965Sjdp buf = NULL; 215533965Sjdp else 215633965Sjdp { 215733965Sjdp bfd_size_type left; 215833965Sjdp bfd_byte dict[4096]; 215933965Sjdp unsigned int h; 216033965Sjdp bfd_byte b; 216133965Sjdp 216233965Sjdp buf = (bfd_byte *) bfd_alloc (nbfd, size); 216333965Sjdp if (buf == NULL) 216433965Sjdp goto error_return; 216533965Sjdp p = buf; 216633965Sjdp 216733965Sjdp left = size; 216833965Sjdp 216977298Sobrien /* I don't know what the next eight bytes are for. */ 217089857Sobrien if (bfd_bread (ab, (bfd_size_type) 8, nbfd) != 8) 217133965Sjdp goto error_return; 217233965Sjdp 217333965Sjdp /* This is the uncompression algorithm. It's a simple 217433965Sjdp dictionary based scheme in which each character is predicted 217533965Sjdp by a hash of the previous three characters. A control byte 217633965Sjdp indicates whether the character is predicted or whether it 217733965Sjdp appears in the input stream; each control byte manages the 217833965Sjdp next eight bytes in the output stream. */ 217933965Sjdp memset (dict, 0, sizeof dict); 218033965Sjdp h = 0; 218189857Sobrien while (bfd_bread (&b, (bfd_size_type) 1, nbfd) == 1) 218233965Sjdp { 218333965Sjdp unsigned int i; 218433965Sjdp 218533965Sjdp for (i = 0; i < 8; i++, b >>= 1) 218633965Sjdp { 218733965Sjdp bfd_byte n; 218833965Sjdp 218933965Sjdp if ((b & 1) == 0) 219033965Sjdp n = dict[h]; 219133965Sjdp else 219233965Sjdp { 219389857Sobrien if (! bfd_bread (&n, (bfd_size_type) 1, nbfd)) 219433965Sjdp goto error_return; 219533965Sjdp dict[h] = n; 219633965Sjdp } 219733965Sjdp 219833965Sjdp *p++ = n; 219933965Sjdp 220033965Sjdp --left; 220133965Sjdp if (left == 0) 220233965Sjdp break; 220333965Sjdp 220433965Sjdp h <<= 4; 220533965Sjdp h ^= n; 220633965Sjdp h &= sizeof dict - 1; 220733965Sjdp } 220833965Sjdp 220933965Sjdp if (left == 0) 221033965Sjdp break; 221133965Sjdp } 221233965Sjdp } 221333965Sjdp 221433965Sjdp /* Now the uncompressed file contents are in buf. */ 221533965Sjdp bim = ((struct bfd_in_memory *) 221689857Sobrien bfd_alloc (nbfd, (bfd_size_type) sizeof (struct bfd_in_memory))); 221733965Sjdp if (bim == NULL) 221833965Sjdp goto error_return; 221933965Sjdp bim->size = size; 222033965Sjdp bim->buffer = buf; 222133965Sjdp 2222130561Sobrien nbfd->mtime_set = TRUE; 222333965Sjdp nbfd->mtime = strtol (hdr->ar_date, (char **) NULL, 10); 222433965Sjdp 222533965Sjdp nbfd->flags |= BFD_IN_MEMORY; 222633965Sjdp nbfd->iostream = (PTR) bim; 222733965Sjdp BFD_ASSERT (! nbfd->cacheable); 222833965Sjdp 222933965Sjdp return nbfd; 223033965Sjdp 223133965Sjdp error_return: 223233965Sjdp if (nbfd != NULL) 223333965Sjdp bfd_close (nbfd); 223477298Sobrien return NULL; 223533965Sjdp} 223633965Sjdp 223733965Sjdp/* Open the next archived file. */ 223833965Sjdp 223933965Sjdpstatic bfd * 224033965Sjdpalpha_ecoff_openr_next_archived_file (archive, last_file) 224133965Sjdp bfd *archive; 224233965Sjdp bfd *last_file; 224333965Sjdp{ 224433965Sjdp file_ptr filestart; 224533965Sjdp 224633965Sjdp if (last_file == NULL) 224733965Sjdp filestart = bfd_ardata (archive)->first_file_filepos; 224833965Sjdp else 224933965Sjdp { 225033965Sjdp struct areltdata *t; 225133965Sjdp struct ar_hdr *h; 225233965Sjdp bfd_size_type size; 225333965Sjdp 225433965Sjdp /* We can't use arelt_size here, because that uses parsed_size, 225533965Sjdp which is the uncompressed size. We need the compressed size. */ 225633965Sjdp t = (struct areltdata *) last_file->arelt_data; 225733965Sjdp h = (struct ar_hdr *) t->arch_header; 225833965Sjdp size = strtol (h->ar_size, (char **) NULL, 10); 225933965Sjdp 226033965Sjdp /* Pad to an even boundary... 226133965Sjdp Note that last_file->origin can be odd in the case of 226277298Sobrien BSD-4.4-style element with a long odd size. */ 226333965Sjdp filestart = last_file->origin + size; 226433965Sjdp filestart += filestart % 2; 226533965Sjdp } 226633965Sjdp 226733965Sjdp return alpha_ecoff_get_elt_at_filepos (archive, filestart); 226833965Sjdp} 226933965Sjdp 227033965Sjdp/* Open the archive file given an index into the armap. */ 227133965Sjdp 227233965Sjdpstatic bfd * 227333965Sjdpalpha_ecoff_get_elt_at_index (abfd, index) 227433965Sjdp bfd *abfd; 227533965Sjdp symindex index; 227633965Sjdp{ 227733965Sjdp carsym *entry; 227833965Sjdp 227933965Sjdp entry = bfd_ardata (abfd)->symdefs + index; 228033965Sjdp return alpha_ecoff_get_elt_at_filepos (abfd, entry->file_offset); 228133965Sjdp} 228233965Sjdp 228333965Sjdp/* This is the ECOFF backend structure. The backend field of the 228433965Sjdp target vector points to this. */ 228533965Sjdp 228633965Sjdpstatic const struct ecoff_backend_data alpha_ecoff_backend_data = 228733965Sjdp{ 228833965Sjdp /* COFF backend structure. */ 228933965Sjdp { 229033965Sjdp (void (*) PARAMS ((bfd *,PTR,int,int,int,int,PTR))) bfd_void, /* aux_in */ 229133965Sjdp (void (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* sym_in */ 229233965Sjdp (void (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* lineno_in */ 229333965Sjdp (unsigned (*) PARAMS ((bfd *,PTR,int,int,int,int,PTR)))bfd_void,/*aux_out*/ 229433965Sjdp (unsigned (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* sym_out */ 229533965Sjdp (unsigned (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* lineno_out */ 229633965Sjdp (unsigned (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* reloc_out */ 229733965Sjdp alpha_ecoff_swap_filehdr_out, alpha_ecoff_swap_aouthdr_out, 229833965Sjdp alpha_ecoff_swap_scnhdr_out, 2299130561Sobrien FILHSZ, AOUTSZ, SCNHSZ, 0, 0, 0, 0, FILNMLEN, TRUE, FALSE, 4, FALSE, 2, 230033965Sjdp alpha_ecoff_swap_filehdr_in, alpha_ecoff_swap_aouthdr_in, 230133965Sjdp alpha_ecoff_swap_scnhdr_in, NULL, 230233965Sjdp alpha_ecoff_bad_format_hook, _bfd_ecoff_set_arch_mach_hook, 230333965Sjdp alpha_ecoff_mkobject_hook, _bfd_ecoff_styp_to_sec_flags, 230433965Sjdp _bfd_ecoff_set_alignment_hook, _bfd_ecoff_slurp_symbol_table, 230560484Sobrien NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 230660484Sobrien NULL, NULL, NULL 230733965Sjdp }, 230833965Sjdp /* Supported architecture. */ 230933965Sjdp bfd_arch_alpha, 231033965Sjdp /* Initial portion of armap string. */ 231133965Sjdp "________64", 231233965Sjdp /* The page boundary used to align sections in a demand-paged 231333965Sjdp executable file. E.g., 0x1000. */ 231433965Sjdp 0x2000, 2315130561Sobrien /* TRUE if the .rdata section is part of the text segment, as on the 2316130561Sobrien Alpha. FALSE if .rdata is part of the data segment, as on the 231733965Sjdp MIPS. */ 2318130561Sobrien TRUE, 231933965Sjdp /* Bitsize of constructor entries. */ 232033965Sjdp 64, 232133965Sjdp /* Reloc to use for constructor entries. */ 232233965Sjdp &alpha_howto_table[ALPHA_R_REFQUAD], 232333965Sjdp { 232433965Sjdp /* Symbol table magic number. */ 232533965Sjdp magicSym2, 232633965Sjdp /* Alignment of debugging information. E.g., 4. */ 232733965Sjdp 8, 232833965Sjdp /* Sizes of external symbolic information. */ 232933965Sjdp sizeof (struct hdr_ext), 233033965Sjdp sizeof (struct dnr_ext), 233133965Sjdp sizeof (struct pdr_ext), 233233965Sjdp sizeof (struct sym_ext), 233333965Sjdp sizeof (struct opt_ext), 233433965Sjdp sizeof (struct fdr_ext), 233533965Sjdp sizeof (struct rfd_ext), 233633965Sjdp sizeof (struct ext_ext), 233733965Sjdp /* Functions to swap in external symbolic data. */ 233833965Sjdp ecoff_swap_hdr_in, 233933965Sjdp ecoff_swap_dnr_in, 234033965Sjdp ecoff_swap_pdr_in, 234133965Sjdp ecoff_swap_sym_in, 234233965Sjdp ecoff_swap_opt_in, 234333965Sjdp ecoff_swap_fdr_in, 234433965Sjdp ecoff_swap_rfd_in, 234533965Sjdp ecoff_swap_ext_in, 234633965Sjdp _bfd_ecoff_swap_tir_in, 234733965Sjdp _bfd_ecoff_swap_rndx_in, 234833965Sjdp /* Functions to swap out external symbolic data. */ 234933965Sjdp ecoff_swap_hdr_out, 235033965Sjdp ecoff_swap_dnr_out, 235133965Sjdp ecoff_swap_pdr_out, 235233965Sjdp ecoff_swap_sym_out, 235333965Sjdp ecoff_swap_opt_out, 235433965Sjdp ecoff_swap_fdr_out, 235533965Sjdp ecoff_swap_rfd_out, 235633965Sjdp ecoff_swap_ext_out, 235733965Sjdp _bfd_ecoff_swap_tir_out, 235833965Sjdp _bfd_ecoff_swap_rndx_out, 235933965Sjdp /* Function to read in symbolic data. */ 236033965Sjdp _bfd_ecoff_slurp_symbolic_info 236133965Sjdp }, 236233965Sjdp /* External reloc size. */ 236333965Sjdp RELSZ, 236433965Sjdp /* Reloc swapping functions. */ 236533965Sjdp alpha_ecoff_swap_reloc_in, 236633965Sjdp alpha_ecoff_swap_reloc_out, 236733965Sjdp /* Backend reloc tweaking. */ 236833965Sjdp alpha_adjust_reloc_in, 236933965Sjdp alpha_adjust_reloc_out, 237033965Sjdp /* Relocate section contents while linking. */ 237133965Sjdp alpha_relocate_section, 237233965Sjdp /* Do final adjustments to filehdr and aouthdr. */ 237333965Sjdp alpha_adjust_headers, 237433965Sjdp /* Read an element from an archive at a given file position. */ 237533965Sjdp alpha_ecoff_get_elt_at_filepos 237633965Sjdp}; 237733965Sjdp 237833965Sjdp/* Looking up a reloc type is Alpha specific. */ 237933965Sjdp#define _bfd_ecoff_bfd_reloc_type_lookup alpha_bfd_reloc_type_lookup 2380218822Sdim#define _bfd_ecoff_bfd_reloc_name_lookup \ 2381218822Sdim alpha_bfd_reloc_name_lookup 238233965Sjdp 238333965Sjdp/* So is getting relocated section contents. */ 238433965Sjdp#define _bfd_ecoff_bfd_get_relocated_section_contents \ 238533965Sjdp alpha_ecoff_get_relocated_section_contents 238633965Sjdp 238733965Sjdp/* Handling file windows is generic. */ 238833965Sjdp#define _bfd_ecoff_get_section_contents_in_window \ 238933965Sjdp _bfd_generic_get_section_contents_in_window 239033965Sjdp 239133965Sjdp/* Relaxing sections is generic. */ 239233965Sjdp#define _bfd_ecoff_bfd_relax_section bfd_generic_relax_section 239360484Sobrien#define _bfd_ecoff_bfd_gc_sections bfd_generic_gc_sections 239489857Sobrien#define _bfd_ecoff_bfd_merge_sections bfd_generic_merge_sections 2395218822Sdim#define _bfd_ecoff_bfd_is_group_section bfd_generic_is_group_section 2396104834Sobrien#define _bfd_ecoff_bfd_discard_group bfd_generic_discard_group 2397218822Sdim#define _bfd_ecoff_section_already_linked \ 2398218822Sdim _bfd_generic_section_already_linked 239933965Sjdp 240033965Sjdpconst bfd_target ecoffalpha_little_vec = 240133965Sjdp{ 240233965Sjdp "ecoff-littlealpha", /* name */ 240333965Sjdp bfd_target_ecoff_flavour, 240433965Sjdp BFD_ENDIAN_LITTLE, /* data byte order is little */ 240533965Sjdp BFD_ENDIAN_LITTLE, /* header byte order is little */ 240633965Sjdp 240733965Sjdp (HAS_RELOC | EXEC_P | /* object flags */ 240833965Sjdp HAS_LINENO | HAS_DEBUG | 240933965Sjdp HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED), 241033965Sjdp 241133965Sjdp (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA), 241233965Sjdp 0, /* leading underscore */ 241333965Sjdp ' ', /* ar_pad_char */ 241433965Sjdp 15, /* ar_max_namelen */ 241533965Sjdp bfd_getl64, bfd_getl_signed_64, bfd_putl64, 241633965Sjdp bfd_getl32, bfd_getl_signed_32, bfd_putl32, 241733965Sjdp bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */ 241833965Sjdp bfd_getl64, bfd_getl_signed_64, bfd_putl64, 241933965Sjdp bfd_getl32, bfd_getl_signed_32, bfd_putl32, 242033965Sjdp bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */ 242133965Sjdp 242233965Sjdp {_bfd_dummy_target, alpha_ecoff_object_p, /* bfd_check_format */ 242333965Sjdp _bfd_ecoff_archive_p, _bfd_dummy_target}, 242433965Sjdp {bfd_false, _bfd_ecoff_mkobject, /* bfd_set_format */ 242533965Sjdp _bfd_generic_mkarchive, bfd_false}, 242633965Sjdp {bfd_false, _bfd_ecoff_write_object_contents, /* bfd_write_contents */ 242733965Sjdp _bfd_write_archive_contents, bfd_false}, 242833965Sjdp 242933965Sjdp BFD_JUMP_TABLE_GENERIC (_bfd_ecoff), 243033965Sjdp BFD_JUMP_TABLE_COPY (_bfd_ecoff), 243133965Sjdp BFD_JUMP_TABLE_CORE (_bfd_nocore), 243233965Sjdp BFD_JUMP_TABLE_ARCHIVE (alpha_ecoff), 243333965Sjdp BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff), 243433965Sjdp BFD_JUMP_TABLE_RELOCS (_bfd_ecoff), 243533965Sjdp BFD_JUMP_TABLE_WRITE (_bfd_ecoff), 243633965Sjdp BFD_JUMP_TABLE_LINK (_bfd_ecoff), 243733965Sjdp BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), 243833965Sjdp 243960484Sobrien NULL, 244077298Sobrien 244133965Sjdp (PTR) &alpha_ecoff_backend_data 244233965Sjdp}; 2443