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