static PTR alpha_ecoff_read_ar_hdr PARAMS ((bfd *)); static bfd *alpha_ecoff_get_elt_at_filepos PARAMS ((bfd *, file_ptr)); static bfd *alpha_ecoff_openr_next_archived_file PARAMS ((bfd *, bfd *)); static bfd *alpha_ecoff_get_elt_at_index PARAMS ((bfd *, symindex));
static const bfd_target *alpha_ecoff_object_p PARAMS ((bfd *));static boolean alpha_ecoff_bad_format_hook PARAMS ((bfd *abfd, PTR filehdr));static PTR alpha_ecoff_mkobject_hook PARAMS ((bfd *, PTR filehdr, PTR aouthdr));static void alpha_ecoff_swap_reloc_in PARAMS ((bfd *, PTR,					      struct internal_reloc *));static void alpha_ecoff_swap_reloc_out PARAMS ((bfd *,					       const struct internal_reloc *,					       PTR));static void alpha_adjust_reloc_in PARAMS ((bfd *,					   const struct internal_reloc *,					   arelent *));static void alpha_adjust_reloc_out PARAMS ((bfd *, const arelent *,					    struct internal_reloc *));static bfd_byte *alpha_ecoff_get_relocated_section_contents  PARAMS ((bfd *abfd, struct bfd_link_info *, struct bfd_link_order *,	   bfd_byte *data, boolean relocateable, asymbol **symbols));static bfd_vma alpha_convert_external_reloc  PARAMS ((bfd *, struct bfd_link_info *, bfd *, struct external_reloc *,	   struct ecoff_link_hash_entry *));static boolean alpha_relocate_section PARAMS ((bfd *, struct bfd_link_info *,					       bfd *, asection *,					       bfd_byte *, PTR));static boolean alpha_adjust_headers  PARAMS ((bfd *, struct internal_filehdr *, struct internal_aouthdr *));/* ECOFF has COFF sections, but the debugging information is stored in   a completely different format.  ECOFF targets use some of the   swapping routines from coffswap.h, and some of the generic COFF   routines in coffgen.c, but, unlike the real COFF targets, do not   use coffcode.h itself.   Get the generic COFF swapping routines, except for the reloc,   symbol, and lineno ones.  Give them ecoff names.  Define some   accessor macros for the large sizes used for Alpha ECOFF.  */#define GET_FILEHDR_SYMPTR bfd_h_get_64#define PUT_FILEHDR_SYMPTR bfd_h_put_64#define GET_AOUTHDR_TSIZE bfd_h_get_64#define PUT_AOUTHDR_TSIZE bfd_h_put_64#define GET_AOUTHDR_DSIZE bfd_h_get_64#define PUT_AOUTHDR_DSIZE bfd_h_put_64#define GET_AOUTHDR_BSIZE bfd_h_get_64#define PUT_AOUTHDR_BSIZE bfd_h_put_64#define GET_AOUTHDR_ENTRY bfd_h_get_64#define PUT_AOUTHDR_ENTRY bfd_h_put_64#define GET_AOUTHDR_TEXT_START bfd_h_get_64#define PUT_AOUTHDR_TEXT_START bfd_h_put_64#define GET_AOUTHDR_DATA_START bfd_h_get_64#define PUT_AOUTHDR_DATA_START bfd_h_put_64#define GET_SCNHDR_PADDR bfd_h_get_64#define PUT_SCNHDR_PADDR bfd_h_put_64#define GET_SCNHDR_VADDR bfd_h_get_64#define PUT_SCNHDR_VADDR bfd_h_put_64#define GET_SCNHDR_SIZE bfd_h_get_64#define PUT_SCNHDR_SIZE bfd_h_put_64#define GET_SCNHDR_SCNPTR bfd_h_get_64#define PUT_SCNHDR_SCNPTR bfd_h_put_64#define GET_SCNHDR_RELPTR bfd_h_get_64#define PUT_SCNHDR_RELPTR bfd_h_put_64#define GET_SCNHDR_LNNOPTR bfd_h_get_64#define PUT_SCNHDR_LNNOPTR bfd_h_put_64#define ALPHAECOFF#define NO_COFF_RELOCS#define NO_COFF_SYMBOLS#define NO_COFF_LINENOS#define coff_swap_filehdr_in alpha_ecoff_swap_filehdr_in#define coff_swap_filehdr_out alpha_ecoff_swap_filehdr_out#define coff_swap_aouthdr_in alpha_ecoff_swap_aouthdr_in#define coff_swap_aouthdr_out alpha_ecoff_swap_aouthdr_out#define coff_swap_scnhdr_in alpha_ecoff_swap_scnhdr_in#define coff_swap_scnhdr_out alpha_ecoff_swap_scnhdr_out#include "coffswap.h"/* Get the ECOFF swapping routines.  */#define ECOFF_64#include "ecoffswap.h"/* How to process the various reloc types.  */static bfd_reloc_status_typereloc_nil PARAMS ((bfd *, arelent *, asymbol *, PTR,		   asection *, bfd *, char **));static bfd_reloc_status_typereloc_nil (abfd, reloc, sym, data, sec, output_bfd, error_message)     bfd *abfd;     arelent *reloc;     asymbol *sym;     PTR data;     asection *sec;     bfd *output_bfd;     char **error_message;{  return bfd_reloc_ok;}/* In case we're on a 32-bit machine, construct a 64-bit "-1" value   from smaller values.  Start with zero, widen, *then* decrement.  */#define MINUS_ONE	(((bfd_vma)0) - 1)static reloc_howto_type alpha_howto_table[] ={  /* Reloc type 0 is ignored by itself.  However, it appears after a     GPDISP reloc to identify the location where the low order 16 bits     of the gp register are loaded.  */  HOWTO (ALPHA_R_IGNORE,	/* type */	 0,			/* rightshift */	 0,			/* size (0 = byte, 1 = short, 2 = long) */	 8,			/* bitsize */	 true,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_dont, /* complain_on_overflow */	 reloc_nil,		/* special_function */	 "IGNORE",		/* name */	 true,			/* partial_inplace */	 0,			/* src_mask */	 0,			/* dst_mask */	 true),			/* pcrel_offset */  /* A 32 bit reference to a symbol.  */  HOWTO (ALPHA_R_REFLONG,	/* type */	 0,			/* rightshift */	 2,			/* size (0 = byte, 1 = short, 2 = long) */	 32,			/* bitsize */	 false,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_bitfield, /* complain_on_overflow */	 0,			/* special_function */	 "REFLONG",		/* name */	 true,			/* partial_inplace */	 0xffffffff,		/* src_mask */	 0xffffffff,		/* dst_mask */	 false),		/* pcrel_offset */  /* A 64 bit reference to a symbol.  */  HOWTO (ALPHA_R_REFQUAD,	/* type */	 0,			/* rightshift */	 4,			/* size (0 = byte, 1 = short, 2 = long) */	 64,			/* bitsize */	 false,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_bitfield, /* complain_on_overflow */	 0,			/* special_function */	 "REFQUAD",		/* name */	 true,			/* partial_inplace */	 MINUS_ONE,		/* src_mask */	 MINUS_ONE,		/* dst_mask */	 false),		/* pcrel_offset */  /* A 32 bit GP relative offset.  This is just like REFLONG except     that when the value is used the value of the gp register will be     added in.  */  HOWTO (ALPHA_R_GPREL32,	/* type */	 0,			/* rightshift */	 2,			/* size (0 = byte, 1 = short, 2 = long) */	 32,			/* bitsize */	 false,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_bitfield, /* complain_on_overflow */	 0,			/* special_function */	 "GPREL32",		/* name */	 true,			/* partial_inplace */	 0xffffffff,		/* src_mask */	 0xffffffff,		/* dst_mask */	 false),		/* pcrel_offset */  /* Used for an instruction that refers to memory off the GP     register.  The offset is 16 bits of the 32 bit instruction.  This     reloc always seems to be against the .lita section.  */  HOWTO (ALPHA_R_LITERAL,	/* type */	 0,			/* rightshift */	 2,			/* size (0 = byte, 1 = short, 2 = long) */	 16,			/* bitsize */	 false,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_signed, /* complain_on_overflow */	 0,			/* special_function */	 "LITERAL",		/* name */	 true,			/* partial_inplace */	 0xffff,		/* src_mask */	 0xffff,		/* dst_mask */	 false),		/* pcrel_offset */  /* This reloc only appears immediately following a LITERAL reloc.     It identifies a use of the literal.  It seems that the linker can     use this to eliminate a portion of the .lita section.  The symbol     index is special: 1 means the literal address is in the base     register of a memory format instruction; 2 means the literal     address is in the byte offset register of a byte-manipulation     instruction; 3 means the literal address is in the target     register of a jsr instruction.  This does not actually do any     relocation.  */  HOWTO (ALPHA_R_LITUSE,	/* type */	 0,			/* rightshift */	 2,			/* size (0 = byte, 1 = short, 2 = long) */	 32,			/* bitsize */	 false,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_dont, /* complain_on_overflow */	 reloc_nil,		/* special_function */	 "LITUSE",		/* name */	 false,			/* partial_inplace */	 0,			/* src_mask */	 0,			/* dst_mask */	 false),		/* pcrel_offset */  /* Load the gp register.  This is always used for a ldah instruction     which loads the upper 16 bits of the gp register.  The next reloc     will be an IGNORE reloc which identifies the location of the lda     instruction which loads the lower 16 bits.  The symbol index of     the GPDISP instruction appears to actually be the number of bytes     between the ldah and lda instructions.  This gives two different     ways to determine where the lda instruction is; I don't know why     both are used.  The value to use for the relocation is the     difference between the GP value and the current location; the     load will always be done against a register holding the current     address.  */  HOWTO (ALPHA_R_GPDISP,	/* type */	 16,			/* rightshift */	 2,			/* size (0 = byte, 1 = short, 2 = long) */	 16,			/* bitsize */	 true,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_dont, /* complain_on_overflow */	 reloc_nil,		/* special_function */	 "GPDISP",		/* name */	 true,			/* partial_inplace */	 0xffff,		/* src_mask */	 0xffff,		/* dst_mask */	 true),			/* pcrel_offset */  /* A 21 bit branch.  The native assembler generates these for     branches within the text segment, and also fills in the PC     relative offset in the instruction.  */  HOWTO (ALPHA_R_BRADDR,	/* type */	 2,			/* rightshift */	 2,			/* size (0 = byte, 1 = short, 2 = long) */	 21,			/* bitsize */	 true,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_signed, /* complain_on_overflow */	 0,			/* special_function */	 "BRADDR",		/* name */	 true,			/* partial_inplace */	 0x1fffff,		/* src_mask */	 0x1fffff,		/* dst_mask */	 false),		/* pcrel_offset */  /* A hint for a jump to a register.  */  HOWTO (ALPHA_R_HINT,		/* type */	 2,			/* rightshift */	 2,			/* size (0 = byte, 1 = short, 2 = long) */	 14,			/* bitsize */	 true,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_dont, /* complain_on_overflow */	 0,			/* special_function */	 "HINT",		/* name */	 true,			/* partial_inplace */	 0x3fff,		/* src_mask */	 0x3fff,		/* dst_mask */	 false),		/* pcrel_offset */  /* 16 bit PC relative offset.  */  HOWTO (ALPHA_R_SREL16,	/* type */	 0,			/* rightshift */	 1,			/* size (0 = byte, 1 = short, 2 = long) */	 16,			/* bitsize */	 true,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_signed, /* complain_on_overflow */	 0,			/* special_function */	 "SREL16",		/* name */	 true,			/* partial_inplace */	 0xffff,		/* src_mask */	 0xffff,		/* dst_mask */	 false),		/* pcrel_offset */  /* 32 bit PC relative offset.  */  HOWTO (ALPHA_R_SREL32,	/* type */	 0,			/* rightshift */	 2,			/* size (0 = byte, 1 = short, 2 = long) */	 32,			/* bitsize */	 true,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_signed, /* complain_on_overflow */	 0,			/* special_function */	 "SREL32",		/* name */	 true,			/* partial_inplace */	 0xffffffff,		/* src_mask */	 0xffffffff,		/* dst_mask */	 false),		/* pcrel_offset */  /* A 64 bit PC relative offset.  */  HOWTO (ALPHA_R_SREL64,	/* type */	 0,			/* rightshift */	 4,			/* size (0 = byte, 1 = short, 2 = long) */	 64,			/* bitsize */	 true,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_signed, /* complain_on_overflow */	 0,			/* special_function */	 "SREL64",		/* name */	 true,			/* partial_inplace */	 MINUS_ONE,		/* src_mask */	 MINUS_ONE,		/* dst_mask */	 false),		/* pcrel_offset */  /* Push a value on the reloc evaluation stack.  */  HOWTO (ALPHA_R_OP_PUSH,	/* type */	 0,			/* rightshift */	 0,			/* size (0 = byte, 1 = short, 2 = long) */	 0,			/* bitsize */	 false,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_dont, /* complain_on_overflow */	 0,			/* special_function */	 "OP_PUSH",		/* name */	 false,			/* partial_inplace */	 0,			/* src_mask */	 0,			/* dst_mask */	 false),		/* pcrel_offset */  /* Store the value from the stack at the given address.  Store it in     a bitfield of size r_size starting at bit position r_offset.  */  HOWTO (ALPHA_R_OP_STORE,	/* type */	 0,			/* rightshift */	 4,			/* size (0 = byte, 1 = short, 2 = long) */	 64,			/* bitsize */	 false,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_dont, /* complain_on_overflow */	 0,			/* special_function */	 "OP_STORE",		/* name */	 false,			/* partial_inplace */	 0,			/* src_mask */	 MINUS_ONE,		/* dst_mask */	 false),		/* pcrel_offset */  /* Subtract the reloc address from the value on the top of the     relocation stack.  */  HOWTO (ALPHA_R_OP_PSUB,	/* type */	 0,			/* rightshift */	 0,			/* size (0 = byte, 1 = short, 2 = long) */	 0,			/* bitsize */	 false,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_dont, /* complain_on_overflow */	 0,			/* special_function */	 "OP_PSUB",		/* name */	 false,			/* partial_inplace */	 0,			/* src_mask */	 0,			/* dst_mask */	 false),		/* pcrel_offset */  /* Shift the value on the top of the relocation stack right by the     given value.  */  HOWTO (ALPHA_R_OP_PRSHIFT,	/* type */	 0,			/* rightshift */	 0,			/* size (0 = byte, 1 = short, 2 = long) */	 0,			/* bitsize */	 false,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_dont, /* complain_on_overflow */	 0,			/* special_function */	 "OP_PRSHIFT",		/* name */	 false,			/* partial_inplace */	 0,			/* src_mask */	 0,			/* dst_mask */	 false),		/* pcrel_offset */  /* Adjust the GP value for a new range in the object file.  */  HOWTO (ALPHA_R_GPVALUE,	/* type */	 0,			/* rightshift */	 0,			/* size (0 = byte, 1 = short, 2 = long) */	 0,			/* bitsize */	 false,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_dont, /* complain_on_overflow */	 0,			/* special_function */	 "GPVALUE",		/* name */	 false,			/* partial_inplace */	 0,			/* src_mask */	 0,			/* dst_mask */	 false)			/* pcrel_offset */};/* Recognize an Alpha ECOFF file.  */static const bfd_target *alpha_ecoff_object_p (abfd)     bfd *abfd;{  static const bfd_target *ret;  ret = coff_object_p (abfd);  if (ret != NULL)    {      asection *sec;      /* Alpha ECOFF has a .pdata section.  The lnnoptr field of the	 .pdata section is the number of entries it contains.  Each	 entry takes up 8 bytes.  The number of entries is required	 since the section is aligned to a 16 byte boundary.  When we	 link .pdata sections together, we do not want to include the	 alignment bytes.  We handle this on input by faking the size	 of the .pdata section to remove the unwanted alignment bytes.	 On output we will set the lnnoptr field and force the	 alignment.  */      sec = bfd_get_section_by_name (abfd, _PDATA);      if (sec != (asection *) NULL)	{	  bfd_size_type size;	  size = sec->line_filepos * 8;	  BFD_ASSERT (size == bfd_section_size (abfd, sec)		      || size + 8 == bfd_section_size (abfd, sec));	  if (! bfd_set_section_size (abfd, sec, size))	    return NULL;	}    }  return ret;}