160484Sobrien/* BFD back-end for PowerPC Microsoft Portable Executable files.
278828Sobrien   Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3218822Sdim   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
460484Sobrien   Free Software Foundation, Inc.
560484Sobrien
660484Sobrien   Original version pieced together by Kim Knuttila (krk@cygnus.com)
760484Sobrien
860484Sobrien   There is nothing new under the sun. This file draws a lot on other
977298Sobrien   coff files, in particular, those for the rs/6000, alpha, mips, and
1060484Sobrien   intel backends, and the PE work for the arm.
1160484Sobrien
12130561Sobrien   This file is part of BFD, the Binary File Descriptor library.
1360484Sobrien
14130561Sobrien   This program is free software; you can redistribute it and/or modify
15130561Sobrien   it under the terms of the GNU General Public License as published by
16130561Sobrien   the Free Software Foundation; either version 2 of the License, or
17130561Sobrien   (at your option) any later version.
1860484Sobrien
19130561Sobrien   This program is distributed in the hope that it will be useful,
20130561Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
21130561Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22130561Sobrien   GNU General Public License for more details.
2360484Sobrien
24130561Sobrien   You should have received a copy of the GNU General Public License
25130561Sobrien   along with this program; if not, write to the Free Software
26218822Sdim   Foundation, 51 Franklin Street - Fifth Floor,
27218822Sdim   Boston, MA 02110-1301, USA.  */
2860484Sobrien
2960484Sobrien/* Current State:
3060484Sobrien   - objdump works
3160484Sobrien   - relocs generated by gas
3260484Sobrien   - ld will link files, but they do not run.
3377298Sobrien   - dlltool will not produce correct output in some .reloc cases, and will
34130561Sobrien     not produce the right glue code for dll function calls.  */
3560484Sobrien
36218822Sdim#include "sysdep.h"
3760484Sobrien#include "bfd.h"
3860484Sobrien#include "libbfd.h"
3960484Sobrien
4060484Sobrien#include "coff/powerpc.h"
4160484Sobrien#include "coff/internal.h"
4260484Sobrien
4360484Sobrien#include "coff/pe.h"
4460484Sobrien
4560484Sobrien#ifdef BADMAG
4660484Sobrien#undef BADMAG
4760484Sobrien#endif
4860484Sobrien
4960484Sobrien#define BADMAG(x) PPCBADMAG(x)
5060484Sobrien
5160484Sobrien#include "libcoff.h"
5260484Sobrien
5360484Sobrien/* This file is compiled more than once, but we only compile the
5460484Sobrien   final_link routine once.  */
55130561Sobrienextern bfd_boolean ppc_bfd_coff_final_link
5660484Sobrien  PARAMS ((bfd *, struct bfd_link_info *));
5760484Sobrienextern void dump_toc PARAMS ((PTR));
5860484Sobrien
59130561Sobrien/* The toc is a set of bfd_vma fields. We use the fact that valid
60130561Sobrien   addresses are even (i.e. the bit representing "1" is off) to allow
61130561Sobrien   us to encode a little extra information in the field
62130561Sobrien   - Unallocated addresses are initialized to 1.
63130561Sobrien   - Allocated addresses are even numbers.
64130561Sobrien   The first time we actually write a reference to the toc in the bfd,
65130561Sobrien   we want to record that fact in a fixup file (if it is asked for), so
66130561Sobrien   we keep track of whether or not an address has been written by marking
67130561Sobrien   the low order bit with a "1" upon writing.  */
6860484Sobrien
6960484Sobrien#define SET_UNALLOCATED(x)  ((x) = 1)
7060484Sobrien#define IS_UNALLOCATED(x)   ((x) == 1)
7160484Sobrien
7260484Sobrien#define IS_WRITTEN(x)       ((x) & 1)
7360484Sobrien#define MARK_AS_WRITTEN(x)  ((x) |= 1)
7460484Sobrien#define MAKE_ADDR_AGAIN(x)  ((x) &= ~1)
7560484Sobrien
76130561Sobrien/* Turn on this check if you suspect something amiss in the hash tables.  */
7760484Sobrien#ifdef DEBUG_HASH
7860484Sobrien
79130561Sobrien/* Need a 7 char string for an eye catcher.  */
8060484Sobrien#define EYE "krkjunk"
8160484Sobrien
8260484Sobrien#define HASH_CHECK_DCL char eye_catcher[8];
8360484Sobrien#define HASH_CHECK_INIT(ret)      strcpy(ret->eye_catcher, EYE)
8460484Sobrien#define HASH_CHECK(addr) \
8560484Sobrien if (strcmp(addr->eye_catcher, EYE) != 0) \
8660484Sobrien  { \
8777298Sobrien    fprintf (stderr,\
8860484Sobrien    _("File %s, line %d, Hash check failure, bad eye %8s\n"), \
8960484Sobrien    __FILE__, __LINE__, addr->eye_catcher); \
9077298Sobrien    abort (); \
9160484Sobrien }
9260484Sobrien
9360484Sobrien#else
9460484Sobrien
9560484Sobrien#define HASH_CHECK_DCL
9660484Sobrien#define HASH_CHECK_INIT(ret)
9760484Sobrien#define HASH_CHECK(addr)
9860484Sobrien
9960484Sobrien#endif
10060484Sobrien
10160484Sobrien/* In order not to add an int to every hash table item for every coff
102130561Sobrien   linker, we define our own hash table, derived from the coff one.  */
10360484Sobrien
10477298Sobrien/* PE linker hash table entries.  */
10560484Sobrien
10660484Sobrienstruct ppc_coff_link_hash_entry
10760484Sobrien{
108130561Sobrien  struct coff_link_hash_entry root; /* First entry, as required.  */
10960484Sobrien
11060484Sobrien  /* As we wonder around the relocs, we'll keep the assigned toc_offset
111130561Sobrien     here.  */
112130561Sobrien  bfd_vma toc_offset;               /* Our addition, as required.  */
11360484Sobrien  int symbol_is_glue;
11460484Sobrien  unsigned long int glue_insn;
11560484Sobrien
11660484Sobrien  HASH_CHECK_DCL
11760484Sobrien};
11860484Sobrien
11960484Sobrien/* PE linker hash table.  */
12060484Sobrien
12160484Sobrienstruct ppc_coff_link_hash_table
12260484Sobrien{
123130561Sobrien  struct coff_link_hash_table root; /* First entry, as required.  */
12460484Sobrien};
12560484Sobrien
12660484Sobrienstatic struct bfd_hash_entry *ppc_coff_link_hash_newfunc
12760484Sobrien  PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *,
12860484Sobrien	   const char *));
12960484Sobrienstatic struct bfd_link_hash_table *ppc_coff_link_hash_table_create
13060484Sobrien  PARAMS ((bfd *));
131130561Sobrienstatic bfd_boolean coff_ppc_relocate_section
13260484Sobrien  PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
13360484Sobrien	   struct internal_reloc *, struct internal_syment *, asection **));
13460484Sobrienstatic reloc_howto_type *coff_ppc_rtype_to_howto
13560484Sobrien  PARAMS ((bfd *, asection *, struct internal_reloc *,
13660484Sobrien	   struct coff_link_hash_entry *, struct internal_syment *,
13760484Sobrien	   bfd_vma *));
13860484Sobrien
13960484Sobrien/* Routine to create an entry in the link hash table.  */
14060484Sobrien
14160484Sobrienstatic struct bfd_hash_entry *
14260484Sobrienppc_coff_link_hash_newfunc (entry, table, string)
14360484Sobrien     struct bfd_hash_entry *entry;
14460484Sobrien     struct bfd_hash_table *table;
14560484Sobrien     const char *string;
14660484Sobrien{
14777298Sobrien  struct ppc_coff_link_hash_entry *ret =
14860484Sobrien    (struct ppc_coff_link_hash_entry *) entry;
14960484Sobrien
15060484Sobrien  /* Allocate the structure if it has not already been allocated by a
15160484Sobrien     subclass.  */
15260484Sobrien  if (ret == (struct ppc_coff_link_hash_entry *) NULL)
15360484Sobrien    ret = (struct ppc_coff_link_hash_entry *)
15477298Sobrien      bfd_hash_allocate (table,
15560484Sobrien			 sizeof (struct ppc_coff_link_hash_entry));
15660484Sobrien
15760484Sobrien  if (ret == (struct ppc_coff_link_hash_entry *) NULL)
15860484Sobrien    return NULL;
15960484Sobrien
16060484Sobrien  /* Call the allocation method of the superclass.  */
16160484Sobrien  ret = ((struct ppc_coff_link_hash_entry *)
16277298Sobrien	 _bfd_coff_link_hash_newfunc ((struct bfd_hash_entry *) ret,
16360484Sobrien				      table, string));
16460484Sobrien
16560484Sobrien  if (ret)
16660484Sobrien    {
16760484Sobrien      /* Initialize the local fields.  */
168130561Sobrien      SET_UNALLOCATED (ret->toc_offset);
16960484Sobrien      ret->symbol_is_glue = 0;
17060484Sobrien      ret->glue_insn = 0;
17160484Sobrien
172130561Sobrien      HASH_CHECK_INIT (ret);
17360484Sobrien    }
17460484Sobrien
17560484Sobrien  return (struct bfd_hash_entry *) ret;
17660484Sobrien}
17760484Sobrien
17860484Sobrien/* Initialize a PE linker hash table.  */
17960484Sobrien
180130561Sobrienstatic bfd_boolean
181218822Sdimppc_coff_link_hash_table_init (struct ppc_coff_link_hash_table *table,
182218822Sdim			       bfd *abfd,
183218822Sdim			       struct bfd_hash_entry *(*newfunc) (struct bfd_hash_entry *,
184218822Sdim								  struct bfd_hash_table *,
185218822Sdim								  const char *),
186218822Sdim			       unsigned int entsize)
18760484Sobrien{
188218822Sdim  return _bfd_coff_link_hash_table_init (&table->root, abfd, newfunc, entsize);
18960484Sobrien}
19060484Sobrien
19160484Sobrien/* Create a PE linker hash table.  */
19260484Sobrien
19360484Sobrienstatic struct bfd_link_hash_table *
19460484Sobrienppc_coff_link_hash_table_create (abfd)
19560484Sobrien     bfd *abfd;
19660484Sobrien{
19760484Sobrien  struct ppc_coff_link_hash_table *ret;
19889857Sobrien  bfd_size_type amt = sizeof (struct ppc_coff_link_hash_table);
19960484Sobrien
200104834Sobrien  ret = (struct ppc_coff_link_hash_table *) bfd_malloc (amt);
20160484Sobrien  if (ret == NULL)
20260484Sobrien    return NULL;
203218822Sdim  if (!ppc_coff_link_hash_table_init (ret, abfd,
204218822Sdim				      ppc_coff_link_hash_newfunc,
205218822Sdim				      sizeof (struct ppc_coff_link_hash_entry)))
20660484Sobrien    {
207104834Sobrien      free (ret);
20860484Sobrien      return (struct bfd_link_hash_table *) NULL;
20960484Sobrien    }
21060484Sobrien  return &ret->root.root;
21160484Sobrien}
21260484Sobrien
213130561Sobrien/* Now, tailor coffcode.h to use our hash stuff.  */
21460484Sobrien
21560484Sobrien#define coff_bfd_link_hash_table_create ppc_coff_link_hash_table_create
21660484Sobrien
217130561Sobrien/* The nt loader points the toc register to &toc + 32768, in order to
218130561Sobrien   use the complete range of a 16-bit displacement. We have to adjust
219130561Sobrien   for this when we fix up loads displaced off the toc reg.  */
22060484Sobrien#define TOC_LOAD_ADJUSTMENT (-32768)
22160484Sobrien#define TOC_SECTION_NAME ".private.toc"
22260484Sobrien
22360484Sobrien/* The main body of code is in coffcode.h.  */
22460484Sobrien
22560484Sobrien#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (3)
22660484Sobrien
22760484Sobrien/* In case we're on a 32-bit machine, construct a 64-bit "-1" value
22860484Sobrien   from smaller values.  Start with zero, widen, *then* decrement.  */
22960484Sobrien#define MINUS_ONE	(((bfd_vma)0) - 1)
23060484Sobrien
231130561Sobrien/* These should definitely go in a header file somewhere...  */
23260484Sobrien
23360484Sobrien/* NOP */
23460484Sobrien#define IMAGE_REL_PPC_ABSOLUTE          0x0000
23560484Sobrien
23660484Sobrien/* 64-bit address */
23760484Sobrien#define IMAGE_REL_PPC_ADDR64            0x0001
23860484Sobrien
23960484Sobrien/* 32-bit address */
24060484Sobrien#define IMAGE_REL_PPC_ADDR32            0x0002
24160484Sobrien
24260484Sobrien/* 26-bit address, shifted left 2 (branch absolute) */
24360484Sobrien#define IMAGE_REL_PPC_ADDR24            0x0003
24460484Sobrien
24560484Sobrien/* 16-bit address */
24660484Sobrien#define IMAGE_REL_PPC_ADDR16            0x0004
24760484Sobrien
24860484Sobrien/* 16-bit address, shifted left 2 (load doubleword) */
24960484Sobrien#define IMAGE_REL_PPC_ADDR14            0x0005
25060484Sobrien
25160484Sobrien/* 26-bit PC-relative offset, shifted left 2 (branch relative) */
25260484Sobrien#define IMAGE_REL_PPC_REL24             0x0006
25360484Sobrien
25460484Sobrien/* 16-bit PC-relative offset, shifted left 2 (br cond relative) */
25560484Sobrien#define IMAGE_REL_PPC_REL14             0x0007
25660484Sobrien
25760484Sobrien/* 16-bit offset from TOC base */
25860484Sobrien#define IMAGE_REL_PPC_TOCREL16          0x0008
25960484Sobrien
26060484Sobrien/* 16-bit offset from TOC base, shifted left 2 (load doubleword) */
26160484Sobrien#define IMAGE_REL_PPC_TOCREL14          0x0009
26260484Sobrien
26360484Sobrien/* 32-bit addr w/o image base */
26460484Sobrien#define IMAGE_REL_PPC_ADDR32NB          0x000A
26560484Sobrien
26660484Sobrien/* va of containing section (as in an image sectionhdr) */
26760484Sobrien#define IMAGE_REL_PPC_SECREL            0x000B
26860484Sobrien
26960484Sobrien/* sectionheader number */
27060484Sobrien#define IMAGE_REL_PPC_SECTION           0x000C
27160484Sobrien
27260484Sobrien/* substitute TOC restore instruction iff symbol is glue code */
27360484Sobrien#define IMAGE_REL_PPC_IFGLUE            0x000D
27460484Sobrien
27560484Sobrien/* symbol is glue code; virtual address is TOC restore instruction */
27660484Sobrien#define IMAGE_REL_PPC_IMGLUE            0x000E
27760484Sobrien
27860484Sobrien/* va of containing section (limited to 16 bits) */
27960484Sobrien#define IMAGE_REL_PPC_SECREL16          0x000F
28060484Sobrien
281130561Sobrien/* Stuff to handle immediate data when the number of bits in the
282130561Sobrien   data is greater than the number of bits in the immediate field
283130561Sobrien   We need to do (usually) 32 bit arithmetic on 16 bit chunks.  */
28460484Sobrien#define IMAGE_REL_PPC_REFHI             0x0010
28560484Sobrien#define IMAGE_REL_PPC_REFLO             0x0011
28660484Sobrien#define IMAGE_REL_PPC_PAIR              0x0012
28760484Sobrien
288130561Sobrien/* This is essentially the same as tocrel16, with TOCDEFN assumed.  */
28960484Sobrien#define IMAGE_REL_PPC_TOCREL16_DEFN     0x0013
29060484Sobrien
291130561Sobrien/* Flag bits in IMAGE_RELOCATION.TYPE.  */
29260484Sobrien
293130561Sobrien/* Subtract reloc value rather than adding it.  */
29460484Sobrien#define IMAGE_REL_PPC_NEG               0x0100
29560484Sobrien
296130561Sobrien/* Fix branch prediction bit to predict branch taken.  */
29760484Sobrien#define IMAGE_REL_PPC_BRTAKEN           0x0200
29860484Sobrien
299130561Sobrien/* Fix branch prediction bit to predict branch not taken.  */
30060484Sobrien#define IMAGE_REL_PPC_BRNTAKEN          0x0400
30160484Sobrien
302130561Sobrien/* TOC slot defined in file (or, data in toc).  */
30360484Sobrien#define IMAGE_REL_PPC_TOCDEFN           0x0800
30460484Sobrien
305130561Sobrien/* Masks to isolate above values in IMAGE_RELOCATION.Type.  */
30660484Sobrien#define IMAGE_REL_PPC_TYPEMASK          0x00FF
30760484Sobrien#define IMAGE_REL_PPC_FLAGMASK          0x0F00
30860484Sobrien
30960484Sobrien#define EXTRACT_TYPE(x)                 ((x) & IMAGE_REL_PPC_TYPEMASK)
31060484Sobrien#define EXTRACT_FLAGS(x) ((x) & IMAGE_REL_PPC_FLAGMASK)
31160484Sobrien#define EXTRACT_JUNK(x)  \
31260484Sobrien           ((x) & ~(IMAGE_REL_PPC_TYPEMASK | IMAGE_REL_PPC_FLAGMASK))
31360484Sobrien
314130561Sobrien/* Static helper functions to make relocation work.  */
31560484Sobrien/* (Work In Progress) */
31660484Sobrien
31760484Sobrienstatic bfd_reloc_status_type ppc_refhi_reloc PARAMS ((bfd *abfd,
31860484Sobrien						      arelent *reloc,
31960484Sobrien						      asymbol *symbol,
32060484Sobrien						      PTR data,
32160484Sobrien						      asection *section,
32260484Sobrien						      bfd *output_bfd,
32360484Sobrien						      char **error));
32460484Sobrienstatic bfd_reloc_status_type ppc_pair_reloc PARAMS ((bfd *abfd,
32560484Sobrien						     arelent *reloc,
32660484Sobrien						     asymbol *symbol,
32760484Sobrien						     PTR data,
32860484Sobrien						     asection *section,
32960484Sobrien						     bfd *output_bfd,
33060484Sobrien						     char **error));
33160484Sobrien
33260484Sobrienstatic bfd_reloc_status_type ppc_toc16_reloc PARAMS ((bfd *abfd,
33360484Sobrien						      arelent *reloc,
33460484Sobrien						      asymbol *symbol,
33560484Sobrien						      PTR data,
33660484Sobrien						      asection *section,
33760484Sobrien						      bfd *output_bfd,
33860484Sobrien						      char **error));
33960484Sobrien
34060484Sobrienstatic bfd_reloc_status_type ppc_section_reloc PARAMS ((bfd *abfd,
34160484Sobrien							arelent *reloc,
34260484Sobrien							asymbol *symbol,
34360484Sobrien							PTR data,
34460484Sobrien							asection *section,
34560484Sobrien							bfd *output_bfd,
34660484Sobrien							char **error));
34760484Sobrien
34860484Sobrienstatic bfd_reloc_status_type ppc_secrel_reloc PARAMS ((bfd *abfd,
34960484Sobrien						       arelent *reloc,
35060484Sobrien						       asymbol *symbol,
35160484Sobrien						       PTR data,
35260484Sobrien						       asection *section,
35360484Sobrien						       bfd *output_bfd,
35460484Sobrien						       char **error));
35560484Sobrien
35660484Sobrienstatic bfd_reloc_status_type ppc_imglue_reloc PARAMS ((bfd *abfd,
35760484Sobrien						       arelent *reloc,
35860484Sobrien						       asymbol *symbol,
35960484Sobrien						       PTR data,
36060484Sobrien						       asection *section,
36160484Sobrien						       bfd *output_bfd,
36260484Sobrien						       char **error));
36360484Sobrien
364130561Sobrienstatic bfd_boolean in_reloc_p PARAMS((bfd *abfd, reloc_howto_type *howto));
36560484Sobrien
36660484Sobrien/* FIXME: It'll take a while to get through all of these. I only need a few to
36760484Sobrien   get us started, so those I'll make sure work. Those marked FIXME are either
368130561Sobrien   completely unverified or have a specific unknown marked in the comment.  */
36960484Sobrien
370130561Sobrien/* Relocation entries for Windows/NT on PowerPC.
37160484Sobrien
372130561Sobrien   From the document "" we find the following listed as used relocs:
373130561Sobrien
374130561Sobrien     ABSOLUTE       : The noop
375130561Sobrien     ADDR[64|32|16] : fields that hold addresses in data fields or the
376130561Sobrien                      16 bit displacement field on a load/store.
377130561Sobrien     ADDR[24|14]    : fields that hold addresses in branch and cond
378130561Sobrien                      branches. These represent [26|16] bit addresses.
379130561Sobrien                      The low order 2 bits are preserved.
380130561Sobrien     REL[24|14]     : branches relative to the Instruction Address
381130561Sobrien                      register. These represent [26|16] bit addresses,
382130561Sobrien                      as before. The instruction field will be zero, and
383130561Sobrien                      the address of the SYM will be inserted at link time.
384130561Sobrien     TOCREL16       : 16 bit displacement field referring to a slot in
385130561Sobrien                      toc.
386130561Sobrien     TOCREL14       : 16 bit displacement field, similar to REL14 or ADDR14.
387130561Sobrien     ADDR32NB       : 32 bit address relative to the virtual origin.
388130561Sobrien                      (On the alpha, this is always a linker generated thunk)
389130561Sobrien                      (i.e. 32bit addr relative to the image base)
390130561Sobrien     SECREL         : The value is relative to the start of the section
391130561Sobrien                      containing the symbol.
392130561Sobrien     SECTION        : access to the header containing the item. Supports the
393130561Sobrien                      codeview debugger.
394130561Sobrien
395130561Sobrien   In particular, note that the document does not indicate that the
396130561Sobrien   relocations listed in the header file are used.  */
397130561Sobrien
398130561Sobrien
39960484Sobrienstatic reloc_howto_type ppc_coff_howto_table[] =
40060484Sobrien{
40160484Sobrien  /* IMAGE_REL_PPC_ABSOLUTE 0x0000   NOP */
40260484Sobrien  /* Unused: */
40377298Sobrien  HOWTO (IMAGE_REL_PPC_ABSOLUTE, /* type */
40477298Sobrien	 0,	                 /* rightshift */
40577298Sobrien	 0,	                 /* size (0 = byte, 1 = short, 2 = long) */
40677298Sobrien	 0,	                 /* bitsize */
407130561Sobrien	 FALSE,	                 /* pc_relative */
40877298Sobrien	 0,	                 /* bitpos */
40960484Sobrien	 complain_overflow_dont, /* dont complain_on_overflow */
41077298Sobrien	 0,		         /* special_function */
41160484Sobrien	 "ABSOLUTE",             /* name */
412130561Sobrien	 FALSE,	                 /* partial_inplace */
41377298Sobrien	 0x00,	 	         /* src_mask */
41477298Sobrien	 0x00,        		 /* dst_mask */
415130561Sobrien	 FALSE),                 /* pcrel_offset */
41677298Sobrien
41760484Sobrien  /* IMAGE_REL_PPC_ADDR64 0x0001  64-bit address */
41860484Sobrien  /* Unused: */
41977298Sobrien  HOWTO(IMAGE_REL_PPC_ADDR64,    /* type */
42077298Sobrien	0,	                 /* rightshift */
42177298Sobrien	3,	                 /* size (0 = byte, 1 = short, 2 = long) */
42277298Sobrien	64,	                 /* bitsize */
423130561Sobrien	FALSE,	                 /* pc_relative */
42477298Sobrien	0,	                 /* bitpos */
42560484Sobrien	complain_overflow_bitfield, 	 /* complain_on_overflow */
42677298Sobrien	0,		         /* special_function */
42760484Sobrien	"ADDR64",               /* name */
428130561Sobrien	TRUE,	                 /* partial_inplace */
42960484Sobrien	MINUS_ONE,	 	 /* src_mask */
43060484Sobrien	MINUS_ONE,        	 /* dst_mask */
431130561Sobrien	FALSE),                 /* pcrel_offset */
43260484Sobrien
43360484Sobrien  /* IMAGE_REL_PPC_ADDR32 0x0002  32-bit address */
43460484Sobrien  /* Used: */
43560484Sobrien  HOWTO (IMAGE_REL_PPC_ADDR32,	/* type */
43677298Sobrien	 0,	                /* rightshift */
43777298Sobrien	 2,	                /* size (0 = byte, 1 = short, 2 = long) */
43877298Sobrien	 32,	                /* bitsize */
439130561Sobrien	 FALSE,	                /* pc_relative */
44077298Sobrien	 0,	                /* bitpos */
44160484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
44277298Sobrien	 0,		        /* special_function */
44360484Sobrien	 "ADDR32",              /* name */
444130561Sobrien	 TRUE,	                /* partial_inplace */
44577298Sobrien	 0xffffffff,            /* src_mask */
44677298Sobrien	 0xffffffff,            /* dst_mask */
447130561Sobrien	 FALSE),                /* pcrel_offset */
44877298Sobrien
44960484Sobrien  /* IMAGE_REL_PPC_ADDR24 0x0003  26-bit address, shifted left 2 (branch absolute) */
45060484Sobrien  /* the LI field is in bit 6 through bit 29 is 24 bits, + 2 for the shift */
45160484Sobrien  /* Of course, That's the IBM approved bit numbering, which is not what */
45277298Sobrien  /* anyone else uses.... The li field is in bit 2 thru 25 */
45360484Sobrien  /* Used: */
45460484Sobrien  HOWTO (IMAGE_REL_PPC_ADDR24,  /* type */
45577298Sobrien	 0,	                /* rightshift */
45677298Sobrien	 2,	                /* size (0 = byte, 1 = short, 2 = long) */
45760484Sobrien	 26,	                /* bitsize */
458130561Sobrien	 FALSE,	                /* pc_relative */
45977298Sobrien	 0,	                /* bitpos */
46060484Sobrien	 complain_overflow_bitfield, /* complain_on_overflow */
46177298Sobrien	 0,		        /* special_function */
46260484Sobrien	 "ADDR24",              /* name */
463130561Sobrien	 TRUE,	                /* partial_inplace */
46477298Sobrien	 0x07fffffc,	        /* src_mask */
46577298Sobrien	 0x07fffffc,        	/* dst_mask */
466130561Sobrien	 FALSE),                /* pcrel_offset */
46777298Sobrien
46860484Sobrien  /* IMAGE_REL_PPC_ADDR16 0x0004  16-bit address */
46960484Sobrien  /* Used: */
47077298Sobrien  HOWTO (IMAGE_REL_PPC_ADDR16,  /* type */
47177298Sobrien	 0,	                /* rightshift */
47277298Sobrien	 1,	                /* size (0 = byte, 1 = short, 2 = long) */
47377298Sobrien	 16,	                /* bitsize */
474130561Sobrien	 FALSE,	                /* pc_relative */
47577298Sobrien	 0,	                /* bitpos */
47660484Sobrien	 complain_overflow_signed, /* complain_on_overflow */
47777298Sobrien	 0,		        /* special_function */
47860484Sobrien	 "ADDR16",              /* name */
479130561Sobrien	 TRUE,	                /* partial_inplace */
48077298Sobrien	 0xffff,	        /* src_mask */
48177298Sobrien	 0xffff,        	/* dst_mask */
482130561Sobrien	 FALSE),                /* pcrel_offset */
48377298Sobrien
48460484Sobrien  /* IMAGE_REL_PPC_ADDR14 0x0005 */
48560484Sobrien  /*  16-bit address, shifted left 2 (load doubleword) */
48660484Sobrien  /* FIXME: the mask is likely wrong, and the bit position may be as well */
48760484Sobrien  /* Unused: */
48877298Sobrien  HOWTO (IMAGE_REL_PPC_ADDR14,  /* type */
48977298Sobrien	 1,	                /* rightshift */
49077298Sobrien	 1,	                /* size (0 = byte, 1 = short, 2 = long) */
49177298Sobrien	 16,	                /* bitsize */
492130561Sobrien	 FALSE,	                /* pc_relative */
49377298Sobrien	 0,	                /* bitpos */
49460484Sobrien	 complain_overflow_signed, /* complain_on_overflow */
49577298Sobrien	 0,		        /* special_function */
49660484Sobrien	 "ADDR16",              /* name */
497130561Sobrien	 TRUE,	                /* partial_inplace */
49877298Sobrien	 0xffff,	        /* src_mask */
49977298Sobrien	 0xffff,        	/* dst_mask */
500130561Sobrien	 FALSE),                /* pcrel_offset */
50177298Sobrien
50260484Sobrien  /* IMAGE_REL_PPC_REL24 0x0006 */
50360484Sobrien  /*   26-bit PC-relative offset, shifted left 2 (branch relative) */
50460484Sobrien  /* Used: */
50560484Sobrien  HOWTO (IMAGE_REL_PPC_REL24,   /* type */
50677298Sobrien	 0,	                /* rightshift */
50777298Sobrien	 2,	                /* size (0 = byte, 1 = short, 2 = long) */
50877298Sobrien	 26,	                /* bitsize */
509130561Sobrien	 TRUE,	                /* pc_relative */
51077298Sobrien	 0,	                /* bitpos */
51160484Sobrien	 complain_overflow_signed, /* complain_on_overflow */
51277298Sobrien	 0,		        /* special_function */
51360484Sobrien	 "REL24",               /* name */
514130561Sobrien	 TRUE,	                /* partial_inplace */
51577298Sobrien	 0x3fffffc,	        /* src_mask */
51677298Sobrien	 0x3fffffc,        	/* dst_mask */
517130561Sobrien	 FALSE),                /* pcrel_offset */
51877298Sobrien
51960484Sobrien  /* IMAGE_REL_PPC_REL14 0x0007 */
52060484Sobrien  /*   16-bit PC-relative offset, shifted left 2 (br cond relative) */
52160484Sobrien  /* FIXME: the mask is likely wrong, and the bit position may be as well */
52260484Sobrien  /* FIXME: how does it know how far to shift? */
52360484Sobrien  /* Unused: */
52477298Sobrien  HOWTO (IMAGE_REL_PPC_ADDR14,  /* type */
52577298Sobrien	 1,	                /* rightshift */
52677298Sobrien	 1,	                /* size (0 = byte, 1 = short, 2 = long) */
52777298Sobrien	 16,	                /* bitsize */
528130561Sobrien	 FALSE,	                /* pc_relative */
52977298Sobrien	 0,	                /* bitpos */
53060484Sobrien	 complain_overflow_signed, /* complain_on_overflow */
53177298Sobrien	 0,		        /* special_function */
53260484Sobrien	 "ADDR16",              /* name */
533130561Sobrien	 TRUE,	                /* partial_inplace */
53477298Sobrien	 0xffff,	        /* src_mask */
53577298Sobrien	 0xffff,        	/* dst_mask */
536130561Sobrien	 TRUE),                 /* pcrel_offset */
53777298Sobrien
53860484Sobrien  /* IMAGE_REL_PPC_TOCREL16 0x0008 */
53960484Sobrien  /*   16-bit offset from TOC base */
54060484Sobrien  /* Used: */
54177298Sobrien  HOWTO (IMAGE_REL_PPC_TOCREL16,/* type */
54277298Sobrien	 0,	                /* rightshift */
54377298Sobrien	 1,	                /* size (0 = byte, 1 = short, 2 = long) */
54477298Sobrien	 16,	                /* bitsize */
545130561Sobrien	 FALSE,	                /* pc_relative */
54677298Sobrien	 0,	                /* bitpos */
54760484Sobrien	 complain_overflow_dont, /* complain_on_overflow */
54877298Sobrien	 ppc_toc16_reloc,       /* special_function */
54960484Sobrien	 "TOCREL16",            /* name */
550130561Sobrien	 FALSE,	                /* partial_inplace */
55177298Sobrien	 0xffff,	        /* src_mask */
55277298Sobrien	 0xffff,        	/* dst_mask */
553130561Sobrien	 FALSE),                /* pcrel_offset */
55477298Sobrien
55560484Sobrien  /* IMAGE_REL_PPC_TOCREL14 0x0009 */
55660484Sobrien  /*   16-bit offset from TOC base, shifted left 2 (load doubleword) */
55760484Sobrien  /* Unused: */
55877298Sobrien  HOWTO (IMAGE_REL_PPC_TOCREL14,/* type */
55977298Sobrien	 1,	                /* rightshift */
56077298Sobrien	 1,	                /* size (0 = byte, 1 = short, 2 = long) */
56177298Sobrien	 16,	                /* bitsize */
562130561Sobrien	 FALSE,	                /* pc_relative */
56377298Sobrien	 0,	                /* bitpos */
56460484Sobrien	 complain_overflow_signed, /* complain_on_overflow */
56577298Sobrien	 0,		        /* special_function */
56660484Sobrien	 "TOCREL14",            /* name */
567130561Sobrien	 FALSE,	                /* partial_inplace */
56877298Sobrien	 0xffff,	        /* src_mask */
56977298Sobrien	 0xffff,        	/* dst_mask */
570130561Sobrien	 FALSE),                /* pcrel_offset */
57177298Sobrien
57260484Sobrien  /* IMAGE_REL_PPC_ADDR32NB 0x000A */
57360484Sobrien  /*   32-bit addr w/ image base */
57460484Sobrien  /* Unused: */
57577298Sobrien  HOWTO (IMAGE_REL_PPC_ADDR32NB,/* type */
57677298Sobrien	 0,	                /* rightshift */
57777298Sobrien	 2,	                /* size (0 = byte, 1 = short, 2 = long) */
57877298Sobrien	 32,	                /* bitsize */
579130561Sobrien	 FALSE,	                /* pc_relative */
58077298Sobrien	 0,	                /* bitpos */
58160484Sobrien	 complain_overflow_signed, /* complain_on_overflow */
58277298Sobrien	 0,                     /* special_function */
58360484Sobrien	 "ADDR32NB",            /* name */
584130561Sobrien	 TRUE,	                /* partial_inplace */
58577298Sobrien	 0xffffffff,	        /* src_mask */
58677298Sobrien	 0xffffffff,        	/* dst_mask */
587130561Sobrien	 FALSE),                 /* pcrel_offset */
58877298Sobrien
58960484Sobrien  /* IMAGE_REL_PPC_SECREL 0x000B */
59060484Sobrien  /*   va of containing section (as in an image sectionhdr) */
59160484Sobrien  /* Unused: */
59277298Sobrien  HOWTO (IMAGE_REL_PPC_SECREL,/* type */
59377298Sobrien	 0,	                /* rightshift */
59477298Sobrien	 2,	                /* size (0 = byte, 1 = short, 2 = long) */
59577298Sobrien	 32,	                /* bitsize */
596130561Sobrien	 FALSE,	                /* pc_relative */
59777298Sobrien	 0,	                /* bitpos */
59860484Sobrien	 complain_overflow_signed, /* complain_on_overflow */
59977298Sobrien	 ppc_secrel_reloc,      /* special_function */
60060484Sobrien	 "SECREL",              /* name */
601130561Sobrien	 TRUE,	                /* partial_inplace */
60277298Sobrien	 0xffffffff,	        /* src_mask */
60377298Sobrien	 0xffffffff,        	/* dst_mask */
604130561Sobrien	 TRUE),                 /* pcrel_offset */
60560484Sobrien
60660484Sobrien  /* IMAGE_REL_PPC_SECTION 0x000C */
60760484Sobrien  /*   sectionheader number */
60860484Sobrien  /* Unused: */
60977298Sobrien  HOWTO (IMAGE_REL_PPC_SECTION,/* type */
61077298Sobrien	 0,	                /* rightshift */
61177298Sobrien	 2,	                /* size (0 = byte, 1 = short, 2 = long) */
61277298Sobrien	 32,	                /* bitsize */
613130561Sobrien	 FALSE,	                /* pc_relative */
61477298Sobrien	 0,	                /* bitpos */
61560484Sobrien	 complain_overflow_signed, /* complain_on_overflow */
61677298Sobrien	 ppc_section_reloc,     /* special_function */
61760484Sobrien	 "SECTION",             /* name */
618130561Sobrien	 TRUE,	                /* partial_inplace */
61977298Sobrien	 0xffffffff,	        /* src_mask */
62077298Sobrien	 0xffffffff,        	/* dst_mask */
621130561Sobrien	 TRUE),                 /* pcrel_offset */
62260484Sobrien
62360484Sobrien  /* IMAGE_REL_PPC_IFGLUE 0x000D */
62460484Sobrien  /*   substitute TOC restore instruction iff symbol is glue code */
62560484Sobrien  /* Used: */
62677298Sobrien  HOWTO (IMAGE_REL_PPC_IFGLUE,/* type */
62777298Sobrien	 0,	                /* rightshift */
62877298Sobrien	 2,	                /* size (0 = byte, 1 = short, 2 = long) */
62977298Sobrien	 32,	                /* bitsize */
630130561Sobrien	 FALSE,	                /* pc_relative */
63177298Sobrien	 0,	                /* bitpos */
63260484Sobrien	 complain_overflow_signed, /* complain_on_overflow */
63377298Sobrien	 0,		        /* special_function */
63460484Sobrien	 "IFGLUE",              /* name */
635130561Sobrien	 TRUE,	                /* partial_inplace */
63677298Sobrien	 0xffffffff,	        /* src_mask */
63777298Sobrien	 0xffffffff,        	/* dst_mask */
638130561Sobrien	 FALSE),                /* pcrel_offset */
63960484Sobrien
64060484Sobrien  /* IMAGE_REL_PPC_IMGLUE 0x000E */
64160484Sobrien  /*   symbol is glue code; virtual address is TOC restore instruction */
64260484Sobrien  /* Unused: */
64377298Sobrien  HOWTO (IMAGE_REL_PPC_IMGLUE,/* type */
64477298Sobrien	 0,	                /* rightshift */
64577298Sobrien	 2,	                /* size (0 = byte, 1 = short, 2 = long) */
64677298Sobrien	 32,	                /* bitsize */
647130561Sobrien	 FALSE,	                /* pc_relative */
64877298Sobrien	 0,	                /* bitpos */
64960484Sobrien	 complain_overflow_dont, /* complain_on_overflow */
65077298Sobrien	 ppc_imglue_reloc,      /* special_function */
65160484Sobrien	 "IMGLUE",              /* name */
652130561Sobrien	 FALSE,	                /* partial_inplace */
65377298Sobrien	 0xffffffff,	        /* src_mask */
65477298Sobrien	 0xffffffff,        	/* dst_mask */
655130561Sobrien	 FALSE),                 /* pcrel_offset */
65660484Sobrien
65760484Sobrien  /* IMAGE_REL_PPC_SECREL16 0x000F */
65860484Sobrien  /*   va of containing section (limited to 16 bits) */
65960484Sobrien  /* Unused: */
66077298Sobrien  HOWTO (IMAGE_REL_PPC_SECREL16,/* type */
66177298Sobrien	 0,	                /* rightshift */
66277298Sobrien	 1,	                /* size (0 = byte, 1 = short, 2 = long) */
66377298Sobrien	 16,	                /* bitsize */
664130561Sobrien	 FALSE,	                /* pc_relative */
66577298Sobrien	 0,	                /* bitpos */
66660484Sobrien	 complain_overflow_signed, /* complain_on_overflow */
66777298Sobrien	 0,		        /* special_function */
66860484Sobrien	 "SECREL16",            /* name */
669130561Sobrien	 TRUE,	                /* partial_inplace */
67077298Sobrien	 0xffff,	        /* src_mask */
67177298Sobrien	 0xffff,        	/* dst_mask */
672130561Sobrien	 TRUE),                 /* pcrel_offset */
67360484Sobrien
67460484Sobrien  /* IMAGE_REL_PPC_REFHI             0x0010 */
67560484Sobrien  /* Unused: */
67677298Sobrien  HOWTO (IMAGE_REL_PPC_REFHI,   /* type */
67777298Sobrien	 0,	                /* rightshift */
67877298Sobrien	 1,	                /* size (0 = byte, 1 = short, 2 = long) */
67977298Sobrien	 16,	                /* bitsize */
680130561Sobrien	 FALSE,	                /* pc_relative */
68177298Sobrien	 0,	                /* bitpos */
68260484Sobrien	 complain_overflow_signed, /* complain_on_overflow */
68377298Sobrien	 ppc_refhi_reloc,	/* special_function */
68460484Sobrien	 "REFHI",               /* name */
685130561Sobrien	 TRUE,	                /* partial_inplace */
68677298Sobrien	 0xffffffff,	        /* src_mask */
68777298Sobrien	 0xffffffff,        	/* dst_mask */
688130561Sobrien	 FALSE),                 /* pcrel_offset */
68960484Sobrien
69060484Sobrien  /* IMAGE_REL_PPC_REFLO             0x0011 */
69160484Sobrien  /* Unused: */
69277298Sobrien  HOWTO (IMAGE_REL_PPC_REFLO,   /* type */
69377298Sobrien	 0,	                /* rightshift */
69477298Sobrien	 1,	                /* size (0 = byte, 1 = short, 2 = long) */
69577298Sobrien	 16,	                /* bitsize */
696130561Sobrien	 FALSE,	                /* pc_relative */
69777298Sobrien	 0,	                /* bitpos */
69860484Sobrien	 complain_overflow_signed, /* complain_on_overflow */
69977298Sobrien	 ppc_refhi_reloc,	/* special_function */
70060484Sobrien	 "REFLO",               /* name */
701130561Sobrien	 TRUE,	                /* partial_inplace */
70277298Sobrien	 0xffffffff,	        /* src_mask */
70377298Sobrien	 0xffffffff,        	/* dst_mask */
704130561Sobrien	 FALSE),                /* pcrel_offset */
70560484Sobrien
70660484Sobrien  /* IMAGE_REL_PPC_PAIR              0x0012 */
70760484Sobrien  /* Unused: */
70877298Sobrien  HOWTO (IMAGE_REL_PPC_PAIR,    /* type */
70977298Sobrien	 0,	                /* rightshift */
71077298Sobrien	 1,	                /* size (0 = byte, 1 = short, 2 = long) */
71177298Sobrien	 16,	                /* bitsize */
712130561Sobrien	 FALSE,	                /* pc_relative */
71377298Sobrien	 0,	                /* bitpos */
71460484Sobrien	 complain_overflow_signed, /* complain_on_overflow */
71577298Sobrien	 ppc_pair_reloc,        /* special_function */
71660484Sobrien	 "PAIR",                /* name */
717130561Sobrien	 TRUE,	                /* partial_inplace */
71877298Sobrien	 0xffffffff,	        /* src_mask */
71977298Sobrien	 0xffffffff,        	/* dst_mask */
720130561Sobrien	 FALSE),                /* pcrel_offset */
72160484Sobrien
72260484Sobrien  /* IMAGE_REL_PPC_TOCREL16_DEFN 0x0013 */
72360484Sobrien  /*   16-bit offset from TOC base, without causing a definition */
72460484Sobrien  /* Used: */
72577298Sobrien  HOWTO ( (IMAGE_REL_PPC_TOCREL16 | IMAGE_REL_PPC_TOCDEFN), /* type */
72677298Sobrien	 0,	                /* rightshift */
72777298Sobrien	 1,	                /* size (0 = byte, 1 = short, 2 = long) */
72877298Sobrien	 16,	                /* bitsize */
729130561Sobrien	 FALSE,	                /* pc_relative */
73077298Sobrien	 0,	                /* bitpos */
73160484Sobrien	 complain_overflow_dont, /* complain_on_overflow */
73277298Sobrien	 0,                     /* special_function */
73360484Sobrien	 "TOCREL16, TOCDEFN",   /* name */
734130561Sobrien	 FALSE,	                /* partial_inplace */
73577298Sobrien	 0xffff,	        /* src_mask */
73677298Sobrien	 0xffff,        	/* dst_mask */
737130561Sobrien	 FALSE),                /* pcrel_offset */
73860484Sobrien
73960484Sobrien};
74060484Sobrien
741130561Sobrien/* Some really cheezy macros that can be turned on to test stderr :-)  */
74260484Sobrien
74360484Sobrien#ifdef DEBUG_RELOC
74460484Sobrien#define UN_IMPL(x)                                           \
74560484Sobrien{                                                            \
74660484Sobrien   static int i;                                             \
74760484Sobrien   if (i == 0)                                               \
74860484Sobrien     {                                                       \
74960484Sobrien       i = 1;                                                \
75077298Sobrien       fprintf (stderr,_("Unimplemented Relocation -- %s\n"),x); \
75160484Sobrien     }                                                       \
75260484Sobrien}
75360484Sobrien
75460484Sobrien#define DUMP_RELOC(n,r)                              \
75560484Sobrien{                                                    \
75677298Sobrien   fprintf (stderr,"%s sym %d, addr %d, addend %d\n", \
75760484Sobrien	   n, (*(r->sym_ptr_ptr))->name,             \
75860484Sobrien	   r->address, r->addend);                   \
75960484Sobrien}
76060484Sobrien
76177298Sobrien/* Given a reloc name, n, and a pointer to an internal_reloc,
76277298Sobrien   dump out interesting information on the contents
76360484Sobrien
76460484Sobrien#define n_name		_n._n_name
76560484Sobrien#define n_zeroes	_n._n_n._n_zeroes
766130561Sobrien#define n_offset	_n._n_n._n_offset  */
76760484Sobrien
768130561Sobrien#define DUMP_RELOC2(n,r)                     		\
769130561Sobrien{                                            		\
770130561Sobrien   fprintf (stderr,"%s sym %d, r_vaddr %d %s\n", 	\
771130561Sobrien	   n, r->r_symndx, r->r_vaddr,			\
77260484Sobrien	   (((r->r_type) & IMAGE_REL_PPC_TOCDEFN) == 0) \
773130561Sobrien	   ?" ":" TOCDEFN"  );      			\
77460484Sobrien}
77560484Sobrien
77660484Sobrien#else
77760484Sobrien#define UN_IMPL(x)
77860484Sobrien#define DUMP_RELOC(n,r)
77960484Sobrien#define DUMP_RELOC2(n,r)
78060484Sobrien#endif
78160484Sobrien
782130561Sobrien/* TOC construction and management routines.  */
78360484Sobrien
78460484Sobrien/* This file is compiled twice, and these variables are defined in one
78560484Sobrien   of the compilations.  FIXME: This is confusing and weird.  Also,
78660484Sobrien   BFD should not use global variables.  */
787130561Sobrienextern bfd *    bfd_of_toc_owner;
78860484Sobrienextern long int global_toc_size;
78960484Sobrienextern long int import_table_size;
79060484Sobrienextern long int first_thunk_address;
79160484Sobrienextern long int thunk_size;
79260484Sobrien
79360484Sobrienenum toc_type
79460484Sobrien{
79560484Sobrien  default_toc,
79660484Sobrien  toc_32,
79760484Sobrien  toc_64
79860484Sobrien};
79960484Sobrien
80060484Sobrienenum ref_category
80160484Sobrien{
80260484Sobrien  priv,
80360484Sobrien  pub,
80489857Sobrien  tocdata
80560484Sobrien};
80660484Sobrien
80760484Sobrienstruct list_ele
80860484Sobrien{
80960484Sobrien  struct list_ele *next;
81060484Sobrien  bfd_vma addr;
81160484Sobrien  enum ref_category cat;
81260484Sobrien  int offset;
81360484Sobrien  const char *name;
81460484Sobrien};
81560484Sobrien
81660484Sobrienextern struct list_ele *head;
81760484Sobrienextern struct list_ele *tail;
81860484Sobrien
81960484Sobrienstatic void record_toc
82089857Sobrien  PARAMS ((asection *, bfd_signed_vma, enum ref_category, const char *));
82160484Sobrien
82260484Sobrienstatic void
82360484Sobrienrecord_toc (toc_section, our_toc_offset, cat, name)
82460484Sobrien     asection *toc_section;
82589857Sobrien     bfd_signed_vma our_toc_offset;
82660484Sobrien     enum ref_category cat;
82760484Sobrien     const char *name;
82860484Sobrien{
829130561Sobrien  /* Add this entry to our toc addr-offset-name list.  */
83089857Sobrien  bfd_size_type amt = sizeof (struct list_ele);
83189857Sobrien  struct list_ele *t = (struct list_ele *) bfd_malloc (amt);
83289857Sobrien
83360484Sobrien  if (t == NULL)
83460484Sobrien    abort ();
83560484Sobrien  t->next = 0;
83660484Sobrien  t->offset = our_toc_offset;
83760484Sobrien  t->name = name;
83860484Sobrien  t->cat = cat;
83960484Sobrien  t->addr = toc_section->output_offset + our_toc_offset;
84060484Sobrien
84160484Sobrien  if (head == 0)
84260484Sobrien    {
84360484Sobrien      head = t;
84460484Sobrien      tail = t;
84560484Sobrien    }
84660484Sobrien  else
84760484Sobrien    {
84860484Sobrien      tail->next = t;
84960484Sobrien      tail = t;
85060484Sobrien    }
85160484Sobrien}
85260484Sobrien
85360484Sobrien#ifdef COFF_IMAGE_WITH_PE
85460484Sobrien
855130561Sobrienstatic bfd_boolean ppc_record_toc_entry
85660484Sobrien  PARAMS ((bfd *, struct bfd_link_info *, asection *, int, enum toc_type));
85760484Sobrienstatic void ppc_mark_symbol_as_glue
85860484Sobrien  PARAMS ((bfd *, int, struct internal_reloc *));
85960484Sobrien
860130561Sobrien/* Record a toc offset against a symbol.  */
861130561Sobrienstatic bfd_boolean
86260484Sobrienppc_record_toc_entry(abfd, info, sec, sym, toc_kind)
86360484Sobrien     bfd *abfd;
86460484Sobrien     struct bfd_link_info *info ATTRIBUTE_UNUSED;
86560484Sobrien     asection *sec ATTRIBUTE_UNUSED;
86660484Sobrien     int sym;
86760484Sobrien     enum toc_type toc_kind ATTRIBUTE_UNUSED;
86860484Sobrien{
86960484Sobrien  struct ppc_coff_link_hash_entry *h;
87060484Sobrien  const char *name;
87160484Sobrien
87260484Sobrien  int *local_syms;
87360484Sobrien
87460484Sobrien  h = 0;
87560484Sobrien
87660484Sobrien  h = (struct ppc_coff_link_hash_entry *) (obj_coff_sym_hashes (abfd)[sym]);
87760484Sobrien  if (h != 0)
87860484Sobrien    {
87960484Sobrien      HASH_CHECK(h);
88060484Sobrien    }
88160484Sobrien
88277298Sobrien  if (h == 0)
88377298Sobrien    {
88460484Sobrien      local_syms = obj_coff_local_toc_table(abfd);
885130561Sobrien
88660484Sobrien      if (local_syms == 0)
88760484Sobrien	{
88860484Sobrien	  unsigned int i;
88989857Sobrien	  bfd_size_type amt;
890130561Sobrien
89160484Sobrien	  /* allocate a table */
89289857Sobrien	  amt = (bfd_size_type) obj_raw_syment_count (abfd) * sizeof (int);
89389857Sobrien	  local_syms = (int *) bfd_zalloc (abfd, amt);
89460484Sobrien	  if (local_syms == 0)
895130561Sobrien	    return FALSE;
89689857Sobrien	  obj_coff_local_toc_table (abfd) = local_syms;
897130561Sobrien
89889857Sobrien	  for (i = 0; i < obj_raw_syment_count (abfd); ++i)
89960484Sobrien	    {
90089857Sobrien	      SET_UNALLOCATED (local_syms[i]);
90160484Sobrien	    }
90260484Sobrien	}
90360484Sobrien
90477298Sobrien      if (IS_UNALLOCATED(local_syms[sym]))
90560484Sobrien	{
90660484Sobrien	  local_syms[sym] = global_toc_size;
90760484Sobrien	  global_toc_size += 4;
90860484Sobrien
909130561Sobrien	  /* The size must fit in a 16-bit displacement.  */
91060484Sobrien	  if (global_toc_size > 65535)
91160484Sobrien	    {
91260484Sobrien	      (*_bfd_error_handler) (_("TOC overflow"));
91360484Sobrien	      bfd_set_error (bfd_error_file_too_big);
914130561Sobrien	      return FALSE;
91560484Sobrien	    }
91660484Sobrien	}
91760484Sobrien    }
91860484Sobrien  else
91960484Sobrien    {
92060484Sobrien      name = h->root.root.root.string;
92160484Sobrien
922130561Sobrien      /* Check to see if there's a toc slot allocated. If not, do it
923130561Sobrien	 here. It will be used in relocate_section.  */
92460484Sobrien      if (IS_UNALLOCATED(h->toc_offset))
92560484Sobrien	{
92660484Sobrien	  h->toc_offset = global_toc_size;
92760484Sobrien	  global_toc_size += 4;
92860484Sobrien
929130561Sobrien	  /* The size must fit in a 16-bit displacement.  */
93060484Sobrien	  if (global_toc_size >= 65535)
93160484Sobrien	    {
93260484Sobrien	      (*_bfd_error_handler) (_("TOC overflow"));
93360484Sobrien	      bfd_set_error (bfd_error_file_too_big);
934130561Sobrien	      return FALSE;
93560484Sobrien	    }
93660484Sobrien	}
93760484Sobrien    }
93860484Sobrien
939130561Sobrien  return TRUE;
94060484Sobrien}
94160484Sobrien
942130561Sobrien/* Record a toc offset against a symbol.  */
94360484Sobrienstatic void
94460484Sobrienppc_mark_symbol_as_glue(abfd, sym, rel)
94560484Sobrien     bfd *abfd;
94660484Sobrien     int sym;
94760484Sobrien     struct internal_reloc *rel;
94860484Sobrien{
94960484Sobrien  struct ppc_coff_link_hash_entry *h;
95060484Sobrien
95160484Sobrien  h = (struct ppc_coff_link_hash_entry *) (obj_coff_sym_hashes (abfd)[sym]);
95260484Sobrien
95360484Sobrien  HASH_CHECK(h);
95460484Sobrien
95560484Sobrien  h->symbol_is_glue = 1;
95660484Sobrien  h->glue_insn = bfd_get_32 (abfd, (bfd_byte *) &rel->r_vaddr);
95760484Sobrien
95860484Sobrien  return;
95960484Sobrien}
96060484Sobrien
96160484Sobrien#endif /* COFF_IMAGE_WITH_PE */
96260484Sobrien
963130561Sobrien/* Return TRUE if this relocation should
96477298Sobrien   appear in the output .reloc section.  */
96560484Sobrien
966130561Sobrienstatic bfd_boolean in_reloc_p(abfd, howto)
96760484Sobrien     bfd * abfd ATTRIBUTE_UNUSED;
96860484Sobrien     reloc_howto_type *howto;
96960484Sobrien{
97077298Sobrien  return
97177298Sobrien    (! howto->pc_relative)
97260484Sobrien      && (howto->type != IMAGE_REL_PPC_ADDR32NB)
97360484Sobrien      && (howto->type != IMAGE_REL_PPC_TOCREL16)
97460484Sobrien      && (howto->type != IMAGE_REL_PPC_IMGLUE)
97577298Sobrien      && (howto->type != IMAGE_REL_PPC_IFGLUE)
97660484Sobrien      && (howto->type != IMAGE_REL_PPC_SECREL)
97760484Sobrien      && (howto->type != IMAGE_REL_PPC_SECTION)
97860484Sobrien      && (howto->type != IMAGE_REL_PPC_SECREL16)
97960484Sobrien      && (howto->type != IMAGE_REL_PPC_REFHI)
98060484Sobrien      && (howto->type != IMAGE_REL_PPC_REFLO)
98160484Sobrien      && (howto->type != IMAGE_REL_PPC_PAIR)
98260484Sobrien      && (howto->type != IMAGE_REL_PPC_TOCREL16_DEFN) ;
98377298Sobrien}
98460484Sobrien
98560484Sobrien/* The reloc processing routine for the optimized COFF linker.  */
98660484Sobrien
987130561Sobrienstatic bfd_boolean
98860484Sobriencoff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
98960484Sobrien			   contents, relocs, syms, sections)
99060484Sobrien     bfd *output_bfd;
99160484Sobrien     struct bfd_link_info *info;
99260484Sobrien     bfd *input_bfd;
99360484Sobrien     asection *input_section;
99460484Sobrien     bfd_byte *contents;
99560484Sobrien     struct internal_reloc *relocs;
99660484Sobrien     struct internal_syment *syms;
99760484Sobrien     asection **sections;
99860484Sobrien{
99960484Sobrien  struct internal_reloc *rel;
100060484Sobrien  struct internal_reloc *relend;
1001130561Sobrien  bfd_boolean hihalf;
100260484Sobrien  bfd_vma hihalf_val;
100360484Sobrien  asection *toc_section = 0;
100460484Sobrien  bfd_vma relocation;
100560484Sobrien  reloc_howto_type *howto = 0;
100677298Sobrien
1007130561Sobrien  /* If we are performing a relocatable link, we don't need to do a
100860484Sobrien     thing.  The caller will take care of adjusting the reloc
100960484Sobrien     addresses and symbol indices.  */
1010130561Sobrien  if (info->relocatable)
1011130561Sobrien    return TRUE;
101277298Sobrien
1013130561Sobrien  hihalf = FALSE;
101460484Sobrien  hihalf_val = 0;
101560484Sobrien
101660484Sobrien  rel = relocs;
101760484Sobrien  relend = rel + input_section->reloc_count;
101860484Sobrien  for (; rel < relend; rel++)
101960484Sobrien    {
102060484Sobrien      long symndx;
102160484Sobrien      struct ppc_coff_link_hash_entry *h;
102260484Sobrien      struct internal_syment *sym;
102360484Sobrien      bfd_vma val;
102460484Sobrien
102560484Sobrien      asection *sec;
102660484Sobrien      bfd_reloc_status_type rstat;
102760484Sobrien      bfd_byte *loc;
102860484Sobrien
102960484Sobrien      unsigned short r_type  = EXTRACT_TYPE (rel->r_type);
103060484Sobrien      unsigned short r_flags = EXTRACT_FLAGS(rel->r_type);
103177298Sobrien
103260484Sobrien      symndx = rel->r_symndx;
103360484Sobrien      loc = contents + rel->r_vaddr - input_section->vma;
103460484Sobrien
103560484Sobrien      /* FIXME: check bounds on r_type */
103660484Sobrien      howto = ppc_coff_howto_table + r_type;
103760484Sobrien
103860484Sobrien      if (symndx == -1)
103960484Sobrien	{
104060484Sobrien	  h = NULL;
104160484Sobrien	  sym = NULL;
104260484Sobrien	}
104360484Sobrien      else
104460484Sobrien	{
104577298Sobrien	  h = (struct ppc_coff_link_hash_entry *)
104660484Sobrien	    (obj_coff_sym_hashes (input_bfd)[symndx]);
104777298Sobrien	  if (h != 0)
104860484Sobrien	    {
104960484Sobrien	      HASH_CHECK(h);
105060484Sobrien	    }
105160484Sobrien
105260484Sobrien	  sym = syms + symndx;
105360484Sobrien	}
105460484Sobrien
105560484Sobrien      if (r_type == IMAGE_REL_PPC_IMGLUE && h == 0)
105660484Sobrien	{
105777298Sobrien	  /* An IMGLUE reloc must have a name. Something is very wrong.  */
105877298Sobrien	  abort ();
105960484Sobrien	}
106060484Sobrien
106160484Sobrien      sec = NULL;
106260484Sobrien      val = 0;
106360484Sobrien
1064130561Sobrien      /* FIXME: PAIR unsupported in the following code.  */
106560484Sobrien      if (h == NULL)
106660484Sobrien	{
106760484Sobrien	  if (symndx == -1)
106860484Sobrien	    sec = bfd_abs_section_ptr;
106960484Sobrien	  else
107060484Sobrien	    {
107160484Sobrien	      sec = sections[symndx];
107260484Sobrien	      val = (sec->output_section->vma
107360484Sobrien		     + sec->output_offset
107460484Sobrien		     + sym->n_value);
107560484Sobrien	      if (! obj_pe (output_bfd))
107660484Sobrien		val -= sec->vma;
107760484Sobrien	    }
107860484Sobrien	}
107960484Sobrien      else
108060484Sobrien	{
108160484Sobrien	  HASH_CHECK(h);
108260484Sobrien
108360484Sobrien	  if (h->root.root.type == bfd_link_hash_defined
108460484Sobrien	      || h->root.root.type == bfd_link_hash_defweak)
108560484Sobrien	    {
108660484Sobrien	      sec = h->root.root.u.def.section;
108760484Sobrien	      val = (h->root.root.u.def.value
108860484Sobrien		     + sec->output_section->vma
108960484Sobrien		     + sec->output_offset);
109060484Sobrien	    }
109160484Sobrien	  else
109260484Sobrien	    {
109360484Sobrien	      if (! ((*info->callbacks->undefined_symbol)
109460484Sobrien		     (info, h->root.root.root.string, input_bfd, input_section,
1095130561Sobrien		      rel->r_vaddr - input_section->vma, TRUE)))
1096130561Sobrien		return FALSE;
109760484Sobrien	    }
109860484Sobrien	}
109960484Sobrien
110060484Sobrien      rstat = bfd_reloc_ok;
110177298Sobrien
1102130561Sobrien      /* Each case must do its own relocation, setting rstat appropriately.  */
110360484Sobrien      switch (r_type)
110460484Sobrien	{
110560484Sobrien	default:
110660484Sobrien	  (*_bfd_error_handler)
1107218822Sdim	    (_("%B: unsupported relocation type 0x%02x"), input_bfd, r_type);
110860484Sobrien	  bfd_set_error (bfd_error_bad_value);
1109130561Sobrien	  return FALSE;
111060484Sobrien	case IMAGE_REL_PPC_TOCREL16:
111160484Sobrien	  {
111289857Sobrien	    bfd_signed_vma our_toc_offset;
111360484Sobrien	    int fixit;
111460484Sobrien
111560484Sobrien	    DUMP_RELOC2(howto->name, rel);
111660484Sobrien
111777298Sobrien	    if (toc_section == 0)
111860484Sobrien	      {
111977298Sobrien		toc_section = bfd_get_section_by_name (bfd_of_toc_owner,
112060484Sobrien						       TOC_SECTION_NAME);
112160484Sobrien
112277298Sobrien		if ( toc_section == NULL )
112360484Sobrien		  {
112477298Sobrien		    /* There is no toc section. Something is very wrong.  */
112577298Sobrien		    abort ();
112660484Sobrien		  }
112760484Sobrien	      }
112860484Sobrien
1129130561Sobrien	    /* Amazing bit tricks present. As we may have seen earlier, we
1130130561Sobrien	       use the 1 bit to tell us whether or not a toc offset has been
1131130561Sobrien	       allocated. Now that they've all been allocated, we will use
1132130561Sobrien	       the 1 bit to tell us if we've written this particular toc
1133130561Sobrien	       entry out.  */
1134130561Sobrien	    fixit = FALSE;
113560484Sobrien	    if (h == 0)
1136130561Sobrien	      {
1137130561Sobrien		/* It is a file local symbol.  */
113860484Sobrien		int *local_toc_table;
113960484Sobrien		const char *name;
114060484Sobrien
114160484Sobrien		sym = syms + symndx;
114260484Sobrien		name = sym->_n._n_name;
114360484Sobrien
114460484Sobrien		local_toc_table = obj_coff_local_toc_table(input_bfd);
114560484Sobrien		our_toc_offset = local_toc_table[symndx];
114660484Sobrien
114760484Sobrien		if (IS_WRITTEN(our_toc_offset))
114860484Sobrien		  {
1149130561Sobrien		    /* If it has been written out, it is marked with the
115060484Sobrien		       1 bit. Fix up our offset, but do not write it out
1151130561Sobrien		       again.  */
115260484Sobrien		    MAKE_ADDR_AGAIN(our_toc_offset);
115360484Sobrien		  }
115460484Sobrien		else
115560484Sobrien		  {
1156130561Sobrien		    /* Write out the toc entry.  */
115789857Sobrien		    record_toc (toc_section, our_toc_offset, priv,
115889857Sobrien				strdup (name));
115960484Sobrien
116089857Sobrien		    bfd_put_32 (output_bfd, val,
116160484Sobrien			       toc_section->contents + our_toc_offset);
116260484Sobrien
116360484Sobrien		    MARK_AS_WRITTEN(local_toc_table[symndx]);
1164130561Sobrien		    fixit = TRUE;
116560484Sobrien		  }
116660484Sobrien	      }
116760484Sobrien	    else
116860484Sobrien	      {
116960484Sobrien		const char *name = h->root.root.root.string;
117060484Sobrien		our_toc_offset = h->toc_offset;
117160484Sobrien
117277298Sobrien		if ((r_flags & IMAGE_REL_PPC_TOCDEFN)
117360484Sobrien		    == IMAGE_REL_PPC_TOCDEFN )
117460484Sobrien		  {
117577298Sobrien		    /* This is unbelievable cheese. Some knowledgable asm
117677298Sobrien		       hacker has decided to use r2 as a base for loading
117777298Sobrien		       a value. He/She does this by setting the tocdefn bit,
117877298Sobrien		       and not supplying a toc definition. The behaviour is
117977298Sobrien		       then to use the difference between the value of the
118077298Sobrien		       symbol and the actual location of the toc as the toc
118177298Sobrien		       index.
118260484Sobrien
118360484Sobrien		       In fact, what is usually happening is, because the
118460484Sobrien		       Import Address Table is mapped immediately following
118560484Sobrien		       the toc, some trippy library code trying for speed on
118677298Sobrien		       dll linkage, takes advantage of that and considers
1187130561Sobrien		       the IAT to be part of the toc, thus saving a load.  */
118860484Sobrien
118989857Sobrien		    our_toc_offset = val - (toc_section->output_section->vma
119089857Sobrien					    + toc_section->output_offset);
119160484Sobrien
1192130561Sobrien		    /* The size must still fit in a 16-bit displacement.  */
119389857Sobrien		    if ((bfd_vma) our_toc_offset >= 65535)
119460484Sobrien		      {
119560484Sobrien			(*_bfd_error_handler)
1196218822Sdim			  (_("%B: Relocation for %s of %lx exceeds Toc size limit"),
1197218822Sdim			   input_bfd, name,
119889857Sobrien			   (unsigned long) our_toc_offset);
119960484Sobrien			bfd_set_error (bfd_error_bad_value);
1200130561Sobrien			return FALSE;
120160484Sobrien		      }
120260484Sobrien
120389857Sobrien		    record_toc (toc_section, our_toc_offset, pub,
120489857Sobrien				strdup (name));
120560484Sobrien		  }
1206130561Sobrien		else if (IS_WRITTEN (our_toc_offset))
120760484Sobrien		  {
1208130561Sobrien		    /* If it has been written out, it is marked with the
120960484Sobrien		       1 bit. Fix up our offset, but do not write it out
1210130561Sobrien		       again.  */
121160484Sobrien		    MAKE_ADDR_AGAIN(our_toc_offset);
121260484Sobrien		  }
121360484Sobrien		else
121460484Sobrien		  {
121589857Sobrien		    record_toc(toc_section, our_toc_offset, pub,
121689857Sobrien			       strdup (name));
121760484Sobrien
1218130561Sobrien		    /* Write out the toc entry.  */
121989857Sobrien		    bfd_put_32 (output_bfd, val,
122060484Sobrien			       toc_section->contents + our_toc_offset);
122160484Sobrien
122260484Sobrien		    MARK_AS_WRITTEN(h->toc_offset);
1223130561Sobrien		    /* The tricky part is that this is the address that
1224130561Sobrien		       needs a .reloc entry for it.  */
1225130561Sobrien		    fixit = TRUE;
122660484Sobrien		  }
122760484Sobrien	      }
122860484Sobrien
122977298Sobrien	    if (fixit && info->base_file)
123060484Sobrien	      {
123160484Sobrien		/* So if this is non pcrelative, and is referenced
1232130561Sobrien		   to a section or a common symbol, then it needs a reloc.  */
123360484Sobrien
1234130561Sobrien		/* Relocation to a symbol in a section which
123577298Sobrien		   isn't absolute - we output the address here
1236130561Sobrien		   to a file.  */
123789857Sobrien		bfd_vma addr = (toc_section->output_section->vma
123889857Sobrien				+ toc_section->output_offset + our_toc_offset);
123977298Sobrien
1240130561Sobrien		if (coff_data (output_bfd)->pe)
124160484Sobrien		  addr -= pe_data(output_bfd)->pe_opthdr.ImageBase;
124260484Sobrien
124360484Sobrien		fwrite (&addr, 1,4, (FILE *) info->base_file);
124460484Sobrien	      }
124560484Sobrien
1246130561Sobrien	    /* FIXME: this test is conservative.  */
124789857Sobrien	    if ((r_flags & IMAGE_REL_PPC_TOCDEFN) != IMAGE_REL_PPC_TOCDEFN
1248218822Sdim		&& (bfd_vma) our_toc_offset > toc_section->size)
124960484Sobrien	      {
125060484Sobrien		(*_bfd_error_handler)
1251218822Sdim		  (_("%B: Relocation exceeds allocated TOC (%lx)"),
1252218822Sdim		   input_bfd, (unsigned long) toc_section->size);
125360484Sobrien		bfd_set_error (bfd_error_bad_value);
1254130561Sobrien		return FALSE;
125560484Sobrien	      }
125660484Sobrien
1257130561Sobrien	    /* Now we know the relocation for this toc reference.  */
125860484Sobrien	    relocation =  our_toc_offset + TOC_LOAD_ADJUSTMENT;
125989857Sobrien	    rstat = _bfd_relocate_contents (howto, input_bfd, relocation, loc);
126060484Sobrien	  }
126160484Sobrien	  break;
126260484Sobrien	case IMAGE_REL_PPC_IFGLUE:
126360484Sobrien	  {
1264130561Sobrien	    /* To solve this, we need to know whether or not the symbol
1265130561Sobrien	       appearing on the call instruction is a glue function or not.
1266130561Sobrien	       A glue function must announce itself via a IMGLUE reloc, and
1267130561Sobrien	       the reloc contains the required toc restore instruction.  */
126860484Sobrien	    bfd_vma x;
126960484Sobrien	    const char *my_name;
1270130561Sobrien
1271130561Sobrien	    DUMP_RELOC2 (howto->name, rel);
127260484Sobrien
127360484Sobrien	    if (h != 0)
127460484Sobrien	      {
127560484Sobrien		my_name = h->root.root.root.string;
127677298Sobrien		if (h->symbol_is_glue == 1)
127760484Sobrien		  {
127877298Sobrien		    x = bfd_get_32 (input_bfd, loc);
127989857Sobrien		    bfd_put_32 (input_bfd, (bfd_vma) h->glue_insn, loc);
128060484Sobrien		  }
128160484Sobrien	      }
128260484Sobrien	  }
128360484Sobrien	  break;
128460484Sobrien	case IMAGE_REL_PPC_SECREL:
1285130561Sobrien	  /* Unimplemented: codeview debugging information.  */
128677298Sobrien	  /* For fast access to the header of the section
128777298Sobrien	     containing the item.  */
128860484Sobrien	  break;
128960484Sobrien	case IMAGE_REL_PPC_SECTION:
1290130561Sobrien	  /* Unimplemented: codeview debugging information.  */
129160484Sobrien	  /* Is used to indicate that the value should be relative
129260484Sobrien	     to the beginning of the section that contains the
1293130561Sobrien	     symbol.  */
129460484Sobrien	  break;
129560484Sobrien	case IMAGE_REL_PPC_ABSOLUTE:
129660484Sobrien	  {
129760484Sobrien	    const char *my_name;
1298130561Sobrien
129960484Sobrien	    if (h == 0)
1300130561Sobrien	      my_name = (syms+symndx)->_n._n_name;
130160484Sobrien	    else
1302130561Sobrien	      my_name = h->root.root.root.string;
130360484Sobrien
1304218822Sdim	    (*_bfd_error_handler)
1305218822Sdim	      (_("Warning: unsupported reloc %s <file %B, section %A>\n"
1306218822Sdim		 "sym %ld (%s), r_vaddr %ld (%lx)"),
1307218822Sdim	       input_bfd, input_section, howto->name,
1308218822Sdim	       rel->r_symndx, my_name, (long) rel->r_vaddr,
1309218822Sdim	       (unsigned long) rel->r_vaddr);
131060484Sobrien	  }
131160484Sobrien	  break;
131260484Sobrien	case IMAGE_REL_PPC_IMGLUE:
131360484Sobrien	  {
131460484Sobrien	    /* There is nothing to do now. This reloc was noted in the first
1315130561Sobrien	       pass over the relocs, and the glue instruction extracted.  */
131660484Sobrien	    const char *my_name;
1317130561Sobrien
131877298Sobrien	    if (h->symbol_is_glue == 1)
131960484Sobrien	      break;
132060484Sobrien	    my_name = h->root.root.root.string;
132160484Sobrien
132260484Sobrien	    (*_bfd_error_handler)
1323218822Sdim	      (_("%B: Out of order IMGLUE reloc for %s"), input_bfd, my_name);
132460484Sobrien	    bfd_set_error (bfd_error_bad_value);
1325130561Sobrien	    return FALSE;
132660484Sobrien	  }
132760484Sobrien
132860484Sobrien	case IMAGE_REL_PPC_ADDR32NB:
132960484Sobrien	  {
133060484Sobrien	    const char *name = 0;
133160484Sobrien
1332130561Sobrien	    DUMP_RELOC2 (howto->name, rel);
1333130561Sobrien
1334218822Sdim	    if (CONST_STRNEQ (input_section->name, ".idata$2") && first_thunk_address == 0)
133560484Sobrien	      {
1336130561Sobrien		/* Set magic values.  */
133760484Sobrien		int idata5offset;
133889857Sobrien		struct coff_link_hash_entry *myh;
1339130561Sobrien
134060484Sobrien		myh = coff_link_hash_lookup (coff_hash_table (info),
134160484Sobrien					     "__idata5_magic__",
1342130561Sobrien					     FALSE, FALSE, TRUE);
134377298Sobrien		first_thunk_address = myh->root.u.def.value +
134477298Sobrien		  sec->output_section->vma +
134577298Sobrien		    sec->output_offset -
134660484Sobrien		      pe_data(output_bfd)->pe_opthdr.ImageBase;
134777298Sobrien
134860484Sobrien		idata5offset = myh->root.u.def.value;
134960484Sobrien		myh = coff_link_hash_lookup (coff_hash_table (info),
135060484Sobrien					     "__idata6_magic__",
1351130561Sobrien					     FALSE, FALSE, TRUE);
135277298Sobrien
135360484Sobrien		thunk_size = myh->root.u.def.value - idata5offset;
135460484Sobrien		myh = coff_link_hash_lookup (coff_hash_table (info),
135560484Sobrien					     "__idata4_magic__",
1356130561Sobrien					     FALSE, FALSE, TRUE);
135760484Sobrien		import_table_size = myh->root.u.def.value;
135860484Sobrien	      }
135960484Sobrien
136060484Sobrien	    if (h == 0)
1361130561Sobrien	      {
1362130561Sobrien		/* It is a file local symbol.  */
136360484Sobrien		sym = syms + symndx;
136460484Sobrien		name = sym->_n._n_name;
136560484Sobrien	      }
136660484Sobrien	    else
136760484Sobrien	      {
136860484Sobrien		char *target = 0;
136960484Sobrien
137060484Sobrien		name = h->root.root.root.string;
1371130561Sobrien		if (strcmp (".idata$2", name) == 0)
137260484Sobrien		  target = "__idata2_magic__";
1373130561Sobrien		else if (strcmp (".idata$4", name) == 0)
137460484Sobrien		  target = "__idata4_magic__";
1375130561Sobrien		else if (strcmp (".idata$5", name) == 0)
137660484Sobrien		  target = "__idata5_magic__";
137760484Sobrien
137860484Sobrien		if (target != 0)
137960484Sobrien		  {
138089857Sobrien		    struct coff_link_hash_entry *myh;
138160484Sobrien
138260484Sobrien		    myh = coff_link_hash_lookup (coff_hash_table (info),
138360484Sobrien						 target,
1384130561Sobrien						 FALSE, FALSE, TRUE);
138577298Sobrien		    if (myh == 0)
138660484Sobrien		      {
138777298Sobrien			/* Missing magic cookies. Something is very wrong.  */
138877298Sobrien			abort ();
138960484Sobrien		      }
139077298Sobrien
139177298Sobrien		    val = myh->root.u.def.value +
139260484Sobrien		      sec->output_section->vma + sec->output_offset;
139360484Sobrien		    if (first_thunk_address == 0)
139460484Sobrien		      {
139560484Sobrien			int idata5offset;
139660484Sobrien			myh = coff_link_hash_lookup (coff_hash_table (info),
139760484Sobrien						     "__idata5_magic__",
1398130561Sobrien						     FALSE, FALSE, TRUE);
139977298Sobrien			first_thunk_address = myh->root.u.def.value +
140077298Sobrien			  sec->output_section->vma +
140177298Sobrien			    sec->output_offset -
140260484Sobrien			      pe_data(output_bfd)->pe_opthdr.ImageBase;
140377298Sobrien
140460484Sobrien			idata5offset = myh->root.u.def.value;
140560484Sobrien			myh = coff_link_hash_lookup (coff_hash_table (info),
140660484Sobrien						     "__idata6_magic__",
1407130561Sobrien						     FALSE, FALSE, TRUE);
140877298Sobrien
140960484Sobrien			thunk_size = myh->root.u.def.value - idata5offset;
141060484Sobrien			myh = coff_link_hash_lookup (coff_hash_table (info),
141160484Sobrien						     "__idata4_magic__",
1412130561Sobrien						     FALSE, FALSE, TRUE);
141360484Sobrien			import_table_size = myh->root.u.def.value;
141460484Sobrien		      }
141560484Sobrien		  }
141660484Sobrien	      }
141760484Sobrien
141860484Sobrien	    rstat = _bfd_relocate_contents (howto,
1419130561Sobrien					    input_bfd,
1420130561Sobrien					    val -
1421130561Sobrien					    pe_data (output_bfd)->pe_opthdr.ImageBase,
1422130561Sobrien					    loc);
142360484Sobrien	  }
142460484Sobrien	  break;
142560484Sobrien
142660484Sobrien	case IMAGE_REL_PPC_REL24:
142760484Sobrien	  DUMP_RELOC2(howto->name, rel);
142860484Sobrien	  val -= (input_section->output_section->vma
142960484Sobrien		  + input_section->output_offset);
143060484Sobrien
143160484Sobrien	  rstat = _bfd_relocate_contents (howto,
143277298Sobrien					  input_bfd,
143377298Sobrien					  val,
143460484Sobrien					  loc);
143560484Sobrien	  break;
143660484Sobrien	case IMAGE_REL_PPC_ADDR16:
143760484Sobrien	case IMAGE_REL_PPC_ADDR24:
143860484Sobrien	case IMAGE_REL_PPC_ADDR32:
143960484Sobrien	  DUMP_RELOC2(howto->name, rel);
144060484Sobrien	  rstat = _bfd_relocate_contents (howto,
144177298Sobrien					  input_bfd,
144277298Sobrien					  val,
144360484Sobrien					  loc);
144460484Sobrien	  break;
144560484Sobrien	}
144660484Sobrien
1447130561Sobrien      if (info->base_file)
144860484Sobrien	{
144960484Sobrien	  /* So if this is non pcrelative, and is referenced
1450130561Sobrien	     to a section or a common symbol, then it needs a reloc.  */
1451130561Sobrien	  if (sym && pe_data(output_bfd)->in_reloc_p (output_bfd, howto))
145260484Sobrien	    {
1453130561Sobrien	      /* Relocation to a symbol in a section which
145477298Sobrien		 isn't absolute - we output the address here
1455130561Sobrien		 to a file.  */
145677298Sobrien	      bfd_vma addr = rel->r_vaddr
145777298Sobrien		- input_section->vma
145877298Sobrien		+ input_section->output_offset
145960484Sobrien		  + input_section->output_section->vma;
146060484Sobrien
1461130561Sobrien	      if (coff_data (output_bfd)->pe)
1462130561Sobrien		addr -= pe_data (output_bfd)->pe_opthdr.ImageBase;
1463130561Sobrien
146460484Sobrien	      fwrite (&addr, 1,4, (FILE *) info->base_file);
146560484Sobrien	    }
146660484Sobrien	}
146760484Sobrien
146860484Sobrien      switch (rstat)
146960484Sobrien	{
147060484Sobrien	default:
147160484Sobrien	  abort ();
147260484Sobrien	case bfd_reloc_ok:
147360484Sobrien	  break;
147460484Sobrien	case bfd_reloc_overflow:
147560484Sobrien	  {
147660484Sobrien	    const char *name;
147760484Sobrien	    char buf[SYMNMLEN + 1];
147860484Sobrien
147960484Sobrien	    if (symndx == -1)
148060484Sobrien	      name = "*ABS*";
148160484Sobrien	    else if (h != NULL)
1482218822Sdim	      name = NULL;
148360484Sobrien	    else if (sym == NULL)
148460484Sobrien	      name = "*unknown*";
148560484Sobrien	    else if (sym->_n._n_n._n_zeroes == 0
148660484Sobrien		     && sym->_n._n_n._n_offset != 0)
148760484Sobrien	      name = obj_coff_strings (input_bfd) + sym->_n._n_n._n_offset;
148860484Sobrien	    else
148960484Sobrien	      {
149060484Sobrien		strncpy (buf, sym->_n._n_name, SYMNMLEN);
149160484Sobrien		buf[SYMNMLEN] = '\0';
149260484Sobrien		name = buf;
149360484Sobrien	      }
149460484Sobrien
149560484Sobrien	    if (! ((*info->callbacks->reloc_overflow)
1496218822Sdim		   (info, (h ? &h->root.root : NULL), name, howto->name,
149760484Sobrien		    (bfd_vma) 0, input_bfd,
149860484Sobrien		    input_section, rel->r_vaddr - input_section->vma)))
1499130561Sobrien	      return FALSE;
150060484Sobrien	  }
150160484Sobrien	}
150277298Sobrien    }
150360484Sobrien
1504130561Sobrien  return TRUE;
150560484Sobrien}
150660484Sobrien
150760484Sobrien#ifdef COFF_IMAGE_WITH_PE
150860484Sobrien
150960484Sobrien/* FIXME: BFD should not use global variables.  This file is compiled
151060484Sobrien   twice, and these variables are shared.  This is confusing and
151160484Sobrien   weird.  */
151260484Sobrien
151360484Sobrienlong int global_toc_size = 4;
151460484Sobrien
151560484Sobrienbfd* bfd_of_toc_owner = 0;
151660484Sobrien
151760484Sobrienlong int import_table_size;
151860484Sobrienlong int first_thunk_address;
151960484Sobrienlong int thunk_size;
152060484Sobrien
152160484Sobrienstruct list_ele *head;
152260484Sobrienstruct list_ele *tail;
152360484Sobrien
152460484Sobrienstatic char *
152560484Sobrienh1 = N_("\n\t\t\tTOC MAPPING\n\n");
152660484Sobrienstatic char *
152760484Sobrienh2 = N_(" TOC    disassembly  Comments       Name\n");
152860484Sobrienstatic char *
152960484Sobrienh3 = N_(" Offset  spelling                   (if present)\n");
153060484Sobrien
153160484Sobrienvoid
153260484Sobriendump_toc (vfile)
153360484Sobrien     PTR vfile;
153460484Sobrien{
153560484Sobrien  FILE *file = (FILE *) vfile;
153660484Sobrien  struct list_ele *t;
153760484Sobrien
153877298Sobrien  fprintf (file, _(h1));
153977298Sobrien  fprintf (file, _(h2));
154077298Sobrien  fprintf (file, _(h3));
154160484Sobrien
154277298Sobrien  for (t = head; t != 0; t=t->next)
154360484Sobrien    {
154460484Sobrien      const char *cat = "";
154560484Sobrien
154660484Sobrien      if (t->cat == priv)
154760484Sobrien	cat = _("private       ");
154860484Sobrien      else if (t->cat == pub)
154960484Sobrien	cat = _("public        ");
155089857Sobrien      else if (t->cat == tocdata)
155160484Sobrien	cat = _("data-in-toc   ");
155260484Sobrien
155360484Sobrien      if (t->offset > global_toc_size)
155460484Sobrien	{
155560484Sobrien	  if (t->offset <= global_toc_size + thunk_size)
155660484Sobrien	    cat = _("IAT reference ");
155760484Sobrien	  else
155860484Sobrien	    {
155977298Sobrien	      fprintf (file,
156060484Sobrien		      _("**** global_toc_size %ld(%lx), thunk_size %ld(%lx)\n"),
156189857Sobrien		       global_toc_size, global_toc_size,
156289857Sobrien		       thunk_size, thunk_size);
156360484Sobrien	      cat = _("Out of bounds!");
156460484Sobrien	    }
156560484Sobrien	}
156660484Sobrien
156777298Sobrien      fprintf (file,
156860484Sobrien	      " %04lx    (%d)", (unsigned long) t->offset, t->offset - 32768);
156977298Sobrien      fprintf (file,
157060484Sobrien	      "    %s %s\n",
157160484Sobrien	      cat, t->name);
157260484Sobrien
157360484Sobrien    }
157460484Sobrien
157577298Sobrien  fprintf (file, "\n");
157660484Sobrien}
157760484Sobrien
1578130561Sobrienbfd_boolean
157977298Sobrienppc_allocate_toc_section (info)
158060484Sobrien     struct bfd_link_info *info ATTRIBUTE_UNUSED;
158160484Sobrien{
158260484Sobrien  asection *s;
158360484Sobrien  bfd_byte *foo;
158489857Sobrien  bfd_size_type amt;
158560484Sobrien  static char test_char = '1';
158660484Sobrien
1587130561Sobrien  if ( global_toc_size == 0 ) /* FIXME: does this get me in trouble?  */
1588130561Sobrien    return TRUE;
158960484Sobrien
159060484Sobrien  if (bfd_of_toc_owner == 0)
1591130561Sobrien    /* No toc owner? Something is very wrong.  */
1592130561Sobrien    abort ();
159360484Sobrien
159460484Sobrien  s = bfd_get_section_by_name ( bfd_of_toc_owner , TOC_SECTION_NAME);
159577298Sobrien  if (s == NULL)
1596130561Sobrien    /* No toc section? Something is very wrong.  */
1597130561Sobrien    abort ();
159860484Sobrien
159989857Sobrien  amt = global_toc_size;
160089857Sobrien  foo = (bfd_byte *) bfd_alloc (bfd_of_toc_owner, amt);
160189857Sobrien  memset(foo, test_char, (size_t) global_toc_size);
160260484Sobrien
1603218822Sdim  s->size = global_toc_size;
160460484Sobrien  s->contents = foo;
160560484Sobrien
1606130561Sobrien  return TRUE;
160760484Sobrien}
160860484Sobrien
1609130561Sobrienbfd_boolean
161060484Sobrienppc_process_before_allocation (abfd, info)
161160484Sobrien     bfd *abfd;
161260484Sobrien     struct bfd_link_info *info;
161360484Sobrien{
161460484Sobrien  asection *sec;
161560484Sobrien  struct internal_reloc *i, *rel;
161660484Sobrien
1617130561Sobrien  /* Here we have a bfd that is to be included on the link. We have a hook
161877298Sobrien     to do reloc rummaging, before section sizes are nailed down.  */
1619130561Sobrien  _bfd_coff_get_external_symbols (abfd);
162060484Sobrien
1621130561Sobrien  /* Rummage around all the relocs and map the toc.  */
162260484Sobrien  sec = abfd->sections;
162360484Sobrien
162460484Sobrien  if (sec == 0)
1625130561Sobrien    return TRUE;
162660484Sobrien
162760484Sobrien  for (; sec != 0; sec = sec->next)
1628130561Sobrien    {
1629130561Sobrien      if (sec->reloc_count == 0)
1630130561Sobrien	continue;
163160484Sobrien
1632130561Sobrien      /* load the relocs */
1633130561Sobrien      /* FIXME: there may be a storage leak here */
1634130561Sobrien      i=_bfd_coff_read_internal_relocs(abfd,sec,1,0,0,0);
163577298Sobrien
1636130561Sobrien      if (i == 0)
1637130561Sobrien	abort ();
163860484Sobrien
1639130561Sobrien      for (rel = i; rel < i + sec->reloc_count; ++rel)
1640130561Sobrien	{
1641130561Sobrien	  unsigned short r_type  = EXTRACT_TYPE  (rel->r_type);
1642130561Sobrien	  unsigned short r_flags = EXTRACT_FLAGS (rel->r_type);
1643130561Sobrien	  bfd_boolean ok = TRUE;
164460484Sobrien
1645130561Sobrien	  DUMP_RELOC2 (ppc_coff_howto_table[r_type].name, rel);
164660484Sobrien
1647130561Sobrien	  switch(r_type)
1648130561Sobrien	    {
1649130561Sobrien	    case IMAGE_REL_PPC_TOCREL16:
1650130561Sobrien	      /* If TOCDEFN is on, ignore as someone else has allocated the
1651130561Sobrien		 toc entry.  */
1652130561Sobrien	      if ((r_flags & IMAGE_REL_PPC_TOCDEFN) != IMAGE_REL_PPC_TOCDEFN)
1653130561Sobrien		ok = ppc_record_toc_entry(abfd, info, sec,
1654130561Sobrien					  rel->r_symndx, default_toc);
1655130561Sobrien	      if (!ok)
1656130561Sobrien		return FALSE;
1657130561Sobrien	      break;
1658130561Sobrien	    case IMAGE_REL_PPC_IMGLUE:
1659130561Sobrien	      ppc_mark_symbol_as_glue (abfd, rel->r_symndx, rel);
1660130561Sobrien	      break;
1661130561Sobrien	    default:
1662130561Sobrien	      break;
1663130561Sobrien	    }
1664130561Sobrien	}
1665130561Sobrien    }
166660484Sobrien
1667130561Sobrien  return TRUE;
166860484Sobrien}
166960484Sobrien
167060484Sobrien#endif
167160484Sobrien
167260484Sobrienstatic bfd_reloc_status_type
1673130561Sobrienppc_refhi_reloc (abfd, reloc_entry, symbol, data,
1674130561Sobrien		 input_section, output_bfd, error_message)
167560484Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
167660484Sobrien     arelent *reloc_entry ATTRIBUTE_UNUSED;
167760484Sobrien     asymbol *symbol ATTRIBUTE_UNUSED;
167860484Sobrien     PTR data ATTRIBUTE_UNUSED;
167960484Sobrien     asection *input_section ATTRIBUTE_UNUSED;
168060484Sobrien     bfd *output_bfd;
168160484Sobrien     char **error_message ATTRIBUTE_UNUSED;
168260484Sobrien{
168360484Sobrien  UN_IMPL("REFHI");
168460484Sobrien  DUMP_RELOC("REFHI",reloc_entry);
168560484Sobrien
168660484Sobrien  if (output_bfd == (bfd *) NULL)
168760484Sobrien    return bfd_reloc_continue;
168860484Sobrien
168960484Sobrien  return bfd_reloc_undefined;
169060484Sobrien}
169160484Sobrien
169260484Sobrienstatic bfd_reloc_status_type
1693130561Sobrienppc_pair_reloc (abfd, reloc_entry, symbol, data,
1694130561Sobrien		input_section, output_bfd, error_message)
169560484Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
169660484Sobrien     arelent *reloc_entry ATTRIBUTE_UNUSED;
169760484Sobrien     asymbol *symbol ATTRIBUTE_UNUSED;
169860484Sobrien     PTR data ATTRIBUTE_UNUSED;
169960484Sobrien     asection *input_section ATTRIBUTE_UNUSED;
170060484Sobrien     bfd *output_bfd;
170160484Sobrien     char **error_message ATTRIBUTE_UNUSED;
170260484Sobrien{
170360484Sobrien  UN_IMPL("PAIR");
170460484Sobrien  DUMP_RELOC("PAIR",reloc_entry);
170560484Sobrien
170660484Sobrien  if (output_bfd == (bfd *) NULL)
170760484Sobrien    return bfd_reloc_continue;
170860484Sobrien
170960484Sobrien  return bfd_reloc_undefined;
171060484Sobrien}
171160484Sobrien
171260484Sobrienstatic bfd_reloc_status_type
1713130561Sobrienppc_toc16_reloc (abfd, reloc_entry, symbol, data,
1714130561Sobrien		 input_section, output_bfd, error_message)
171560484Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
171660484Sobrien     arelent *reloc_entry ATTRIBUTE_UNUSED;
171760484Sobrien     asymbol *symbol ATTRIBUTE_UNUSED;
171860484Sobrien     PTR data ATTRIBUTE_UNUSED;
171960484Sobrien     asection *input_section ATTRIBUTE_UNUSED;
172060484Sobrien     bfd *output_bfd;
172160484Sobrien     char **error_message ATTRIBUTE_UNUSED;
172260484Sobrien{
1723130561Sobrien  UN_IMPL ("TOCREL16");
1724130561Sobrien  DUMP_RELOC ("TOCREL16",reloc_entry);
172560484Sobrien
172660484Sobrien  if (output_bfd == (bfd *) NULL)
1727130561Sobrien    return bfd_reloc_continue;
172860484Sobrien
172960484Sobrien  return bfd_reloc_ok;
173060484Sobrien}
173160484Sobrien
173260484Sobrienstatic bfd_reloc_status_type
1733130561Sobrienppc_secrel_reloc (abfd, reloc_entry, symbol, data,
1734130561Sobrien		  input_section, output_bfd, error_message)
173560484Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
173660484Sobrien     arelent *reloc_entry ATTRIBUTE_UNUSED;
173760484Sobrien     asymbol *symbol ATTRIBUTE_UNUSED;
173860484Sobrien     PTR data ATTRIBUTE_UNUSED;
173960484Sobrien     asection *input_section ATTRIBUTE_UNUSED;
174060484Sobrien     bfd *output_bfd;
174160484Sobrien     char **error_message ATTRIBUTE_UNUSED;
174260484Sobrien{
174360484Sobrien  UN_IMPL("SECREL");
174460484Sobrien  DUMP_RELOC("SECREL",reloc_entry);
174560484Sobrien
174660484Sobrien  if (output_bfd == (bfd *) NULL)
174760484Sobrien    return bfd_reloc_continue;
174860484Sobrien
174960484Sobrien  return bfd_reloc_ok;
175060484Sobrien}
175160484Sobrien
175260484Sobrienstatic bfd_reloc_status_type
1753130561Sobrienppc_section_reloc (abfd, reloc_entry, symbol, data,
1754130561Sobrien		   input_section, output_bfd, error_message)
175560484Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
175660484Sobrien     arelent *reloc_entry ATTRIBUTE_UNUSED;
175760484Sobrien     asymbol *symbol ATTRIBUTE_UNUSED;
175860484Sobrien     PTR data ATTRIBUTE_UNUSED;
175960484Sobrien     asection *input_section ATTRIBUTE_UNUSED;
176060484Sobrien     bfd *output_bfd;
176160484Sobrien     char **error_message ATTRIBUTE_UNUSED;
176260484Sobrien{
176360484Sobrien  UN_IMPL("SECTION");
176460484Sobrien  DUMP_RELOC("SECTION",reloc_entry);
176560484Sobrien
176660484Sobrien  if (output_bfd == (bfd *) NULL)
176760484Sobrien    return bfd_reloc_continue;
176860484Sobrien
176960484Sobrien  return bfd_reloc_ok;
177060484Sobrien}
177160484Sobrien
177260484Sobrienstatic bfd_reloc_status_type
1773130561Sobrienppc_imglue_reloc (abfd, reloc_entry, symbol, data,
1774130561Sobrien		  input_section, output_bfd, error_message)
177560484Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
177660484Sobrien     arelent *reloc_entry ATTRIBUTE_UNUSED;
177760484Sobrien     asymbol *symbol ATTRIBUTE_UNUSED;
177860484Sobrien     PTR data ATTRIBUTE_UNUSED;
177960484Sobrien     asection *input_section ATTRIBUTE_UNUSED;
178060484Sobrien     bfd *output_bfd;
178160484Sobrien     char **error_message ATTRIBUTE_UNUSED;
178260484Sobrien{
178360484Sobrien  UN_IMPL("IMGLUE");
178460484Sobrien  DUMP_RELOC("IMGLUE",reloc_entry);
178560484Sobrien
178660484Sobrien  if (output_bfd == (bfd *) NULL)
178760484Sobrien    return bfd_reloc_continue;
178860484Sobrien
178960484Sobrien  return bfd_reloc_ok;
179060484Sobrien}
179160484Sobrien
179260484Sobrien#define MAX_RELOC_INDEX  \
179377298Sobrien      (sizeof (ppc_coff_howto_table) / sizeof (ppc_coff_howto_table[0]) - 1)
179460484Sobrien
1795130561Sobrien/* FIXME: There is a possibility that when we read in a reloc from a file,
179677298Sobrien          that there are some bits encoded in the upper portion of the
1797130561Sobrien	  type field. Not yet implemented.  */
1798130561Sobrienstatic void ppc_coff_rtype2howto PARAMS ((arelent *, struct internal_reloc *));
179960484Sobrien
180060484Sobrienstatic void
180160484Sobrienppc_coff_rtype2howto (relent, internal)
180260484Sobrien     arelent *relent;
180360484Sobrien     struct internal_reloc *internal;
180477298Sobrien{
180560484Sobrien  /* We can encode one of three things in the type field, aside from the
180660484Sobrien     type:
180760484Sobrien     1. IMAGE_REL_PPC_NEG - indicates the value field is a subtraction
180860484Sobrien        value, rather than an addition value
180960484Sobrien     2. IMAGE_REL_PPC_BRTAKEN, IMAGE_REL_PPC_BRNTAKEN - indicates that
181060484Sobrien        the branch is expected to be taken or not.
181160484Sobrien     3. IMAGE_REL_PPC_TOCDEFN - toc slot definition in the file
181260484Sobrien     For now, we just strip this stuff to find the type, and ignore it other
1813130561Sobrien     than that.  */
181460484Sobrien  reloc_howto_type *howto;
181560484Sobrien  unsigned short r_type  = EXTRACT_TYPE (internal->r_type);
181660484Sobrien  unsigned short r_flags = EXTRACT_FLAGS(internal->r_type);
181760484Sobrien  unsigned short junk    = EXTRACT_JUNK (internal->r_type);
181860484Sobrien
1819130561Sobrien  /* The masking process only slices off the bottom byte for r_type.  */
182077298Sobrien  if ( r_type > MAX_RELOC_INDEX )
182177298Sobrien    abort ();
182260484Sobrien
1823130561Sobrien  /* Check for absolute crap.  */
1824130561Sobrien  if (junk != 0)
182577298Sobrien    abort ();
182660484Sobrien
182777298Sobrien  switch(r_type)
182860484Sobrien    {
182960484Sobrien    case IMAGE_REL_PPC_ADDR16:
183060484Sobrien    case IMAGE_REL_PPC_REL24:
183160484Sobrien    case IMAGE_REL_PPC_ADDR24:
183260484Sobrien    case IMAGE_REL_PPC_ADDR32:
183360484Sobrien    case IMAGE_REL_PPC_IFGLUE:
183460484Sobrien    case IMAGE_REL_PPC_ADDR32NB:
183560484Sobrien    case IMAGE_REL_PPC_SECTION:
183660484Sobrien    case IMAGE_REL_PPC_SECREL:
1837130561Sobrien      DUMP_RELOC2 (ppc_coff_howto_table[r_type].name, internal);
183860484Sobrien      howto = ppc_coff_howto_table + r_type;
183960484Sobrien      break;
184060484Sobrien    case IMAGE_REL_PPC_IMGLUE:
1841130561Sobrien      DUMP_RELOC2 (ppc_coff_howto_table[r_type].name, internal);
184260484Sobrien      howto = ppc_coff_howto_table + r_type;
184360484Sobrien      break;
184460484Sobrien    case IMAGE_REL_PPC_TOCREL16:
1845130561Sobrien      DUMP_RELOC2 (ppc_coff_howto_table[r_type].name, internal);
184660484Sobrien      if (r_flags & IMAGE_REL_PPC_TOCDEFN)
184760484Sobrien	howto = ppc_coff_howto_table + IMAGE_REL_PPC_TOCREL16_DEFN;
184860484Sobrien      else
184960484Sobrien	howto = ppc_coff_howto_table + IMAGE_REL_PPC_TOCREL16;
185060484Sobrien      break;
185160484Sobrien    default:
185277298Sobrien      fprintf (stderr,
185360484Sobrien	      _("Warning: Unsupported reloc %s [%d] used -- it may not work.\n"),
185460484Sobrien	      ppc_coff_howto_table[r_type].name,
185560484Sobrien	      r_type);
185677298Sobrien      howto = ppc_coff_howto_table + r_type;
185760484Sobrien      break;
185860484Sobrien    }
185977298Sobrien
186060484Sobrien  relent->howto = howto;
186160484Sobrien}
186260484Sobrien
186360484Sobrienstatic reloc_howto_type *
186460484Sobriencoff_ppc_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
186560484Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
186660484Sobrien     asection *sec;
186760484Sobrien     struct internal_reloc *rel;
186860484Sobrien     struct coff_link_hash_entry *h ATTRIBUTE_UNUSED;
186960484Sobrien     struct internal_syment *sym ATTRIBUTE_UNUSED;
187060484Sobrien     bfd_vma *addendp;
187160484Sobrien{
187260484Sobrien  reloc_howto_type *howto;
187360484Sobrien
187460484Sobrien  /* We can encode one of three things in the type field, aside from the
187560484Sobrien     type:
187660484Sobrien     1. IMAGE_REL_PPC_NEG - indicates the value field is a subtraction
187760484Sobrien        value, rather than an addition value
187860484Sobrien     2. IMAGE_REL_PPC_BRTAKEN, IMAGE_REL_PPC_BRNTAKEN - indicates that
187960484Sobrien        the branch is expected to be taken or not.
188060484Sobrien     3. IMAGE_REL_PPC_TOCDEFN - toc slot definition in the file
188160484Sobrien     For now, we just strip this stuff to find the type, and ignore it other
1882130561Sobrien     than that.  */
188360484Sobrien
1884130561Sobrien  unsigned short r_type  = EXTRACT_TYPE  (rel->r_type);
1885130561Sobrien  unsigned short r_flags = EXTRACT_FLAGS (rel->r_type);
1886130561Sobrien  unsigned short junk    = EXTRACT_JUNK  (rel->r_type);
188760484Sobrien
1888130561Sobrien  /* The masking process only slices off the bottom byte for r_type.  */
1889130561Sobrien  if (r_type > MAX_RELOC_INDEX)
189077298Sobrien    abort ();
189177298Sobrien
1892130561Sobrien  /* Check for absolute crap.  */
1893130561Sobrien  if (junk != 0)
189477298Sobrien    abort ();
189577298Sobrien
189677298Sobrien  switch(r_type)
189760484Sobrien    {
189860484Sobrien    case IMAGE_REL_PPC_ADDR32NB:
189960484Sobrien      DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel);
190060484Sobrien      *addendp -= pe_data(sec->output_section->owner)->pe_opthdr.ImageBase;
190160484Sobrien      howto = ppc_coff_howto_table + r_type;
190260484Sobrien      break;
190360484Sobrien    case IMAGE_REL_PPC_TOCREL16:
190460484Sobrien      DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel);
190560484Sobrien      if (r_flags & IMAGE_REL_PPC_TOCDEFN)
190660484Sobrien	howto = ppc_coff_howto_table + IMAGE_REL_PPC_TOCREL16_DEFN;
190760484Sobrien      else
190860484Sobrien	howto = ppc_coff_howto_table + IMAGE_REL_PPC_TOCREL16;
190960484Sobrien      break;
191060484Sobrien    case IMAGE_REL_PPC_ADDR16:
191160484Sobrien    case IMAGE_REL_PPC_REL24:
191260484Sobrien    case IMAGE_REL_PPC_ADDR24:
191360484Sobrien    case IMAGE_REL_PPC_ADDR32:
191460484Sobrien    case IMAGE_REL_PPC_IFGLUE:
191560484Sobrien    case IMAGE_REL_PPC_SECTION:
191660484Sobrien    case IMAGE_REL_PPC_SECREL:
191760484Sobrien      DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel);
191860484Sobrien      howto = ppc_coff_howto_table + r_type;
191960484Sobrien      break;
192060484Sobrien    case IMAGE_REL_PPC_IMGLUE:
192160484Sobrien      DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel);
192260484Sobrien      howto = ppc_coff_howto_table + r_type;
192360484Sobrien      break;
192460484Sobrien    default:
192577298Sobrien      fprintf (stderr,
192660484Sobrien	      _("Warning: Unsupported reloc %s [%d] used -- it may not work.\n"),
192760484Sobrien	      ppc_coff_howto_table[r_type].name,
192860484Sobrien	      r_type);
192960484Sobrien      howto = ppc_coff_howto_table + r_type;
193060484Sobrien      break;
193160484Sobrien    }
193277298Sobrien
193360484Sobrien  return howto;
193460484Sobrien}
193560484Sobrien
1936130561Sobrien/* A cheesy little macro to make the code a little more readable.  */
193760484Sobrien#define HOW2MAP(bfd_rtype,ppc_rtype)  \
193860484Sobrien case bfd_rtype: return &ppc_coff_howto_table[ppc_rtype]
193960484Sobrien
194060484Sobrienstatic reloc_howto_type *ppc_coff_reloc_type_lookup
194160484SobrienPARAMS ((bfd *, bfd_reloc_code_real_type));
194260484Sobrien
194360484Sobrienstatic reloc_howto_type *
194460484Sobrienppc_coff_reloc_type_lookup (abfd, code)
194560484Sobrien     bfd *abfd ATTRIBUTE_UNUSED;
194660484Sobrien     bfd_reloc_code_real_type code;
194760484Sobrien{
194860484Sobrien  switch (code)
194960484Sobrien    {
195060484Sobrien      HOW2MAP(BFD_RELOC_32_GOTOFF,    IMAGE_REL_PPC_IMGLUE);
195160484Sobrien      HOW2MAP(BFD_RELOC_16_GOT_PCREL, IMAGE_REL_PPC_IFGLUE);
195260484Sobrien      HOW2MAP(BFD_RELOC_16,           IMAGE_REL_PPC_ADDR16);
195360484Sobrien      HOW2MAP(BFD_RELOC_PPC_B26,      IMAGE_REL_PPC_REL24);
195460484Sobrien      HOW2MAP(BFD_RELOC_PPC_BA26,     IMAGE_REL_PPC_ADDR24);
195560484Sobrien      HOW2MAP(BFD_RELOC_PPC_TOC16,    IMAGE_REL_PPC_TOCREL16);
195660484Sobrien      HOW2MAP(BFD_RELOC_16_GOTOFF,    IMAGE_REL_PPC_TOCREL16_DEFN);
195760484Sobrien      HOW2MAP(BFD_RELOC_32,           IMAGE_REL_PPC_ADDR32);
195860484Sobrien      HOW2MAP(BFD_RELOC_RVA,          IMAGE_REL_PPC_ADDR32NB);
195977298Sobrien    default:
196060484Sobrien      return NULL;
196160484Sobrien    }
196260484Sobrien}
1963218822Sdim#undef HOW2MAP
196460484Sobrien
1965218822Sdimstatic reloc_howto_type *
1966218822Sdimppc_coff_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
1967218822Sdim			    const char *r_name)
1968218822Sdim{
1969218822Sdim  unsigned int i;
1970218822Sdim
1971218822Sdim  for (i = 0;
1972218822Sdim       i < sizeof (ppc_coff_howto_table) / sizeof (ppc_coff_howto_table[0]);
1973218822Sdim       i++)
1974218822Sdim    if (ppc_coff_howto_table[i].name != NULL
1975218822Sdim	&& strcasecmp (ppc_coff_howto_table[i].name, r_name) == 0)
1976218822Sdim      return &ppc_coff_howto_table[i];
1977218822Sdim
1978218822Sdim  return NULL;
1979218822Sdim}
198060484Sobrien
198177298Sobrien/* Tailor coffcode.h -- macro heaven.  */
198260484Sobrien
198360484Sobrien#define RTYPE2HOWTO(cache_ptr, dst)  ppc_coff_rtype2howto (cache_ptr, dst)
198460484Sobrien
198560484Sobrien/* We use the special COFF backend linker, with our own special touch.  */
198660484Sobrien
198760484Sobrien#define coff_bfd_reloc_type_lookup   ppc_coff_reloc_type_lookup
1988218822Sdim#define coff_bfd_reloc_name_lookup ppc_coff_reloc_name_lookup
198960484Sobrien#define coff_rtype_to_howto          coff_ppc_rtype_to_howto
199060484Sobrien#define coff_relocate_section        coff_ppc_relocate_section
199177298Sobrien#define coff_bfd_final_link          ppc_bfd_coff_final_link
199260484Sobrien
199360484Sobrien#ifndef COFF_IMAGE_WITH_PE
199460484Sobrien#endif
199560484Sobrien
199660484Sobrien#define SELECT_RELOC(internal, howto) {internal.r_type=howto->type;}
199760484Sobrien
199860484Sobrien#define COFF_PAGE_SIZE                       0x1000
199960484Sobrien
200060484Sobrien/* FIXME: This controls some code that used to be in peicode.h and is
200160484Sobrien   now in peigen.c.  It will not control the code in peigen.c.  If
200260484Sobrien   anybody wants to get this working, you will need to fix that.  */
200360484Sobrien#define POWERPC_LE_PE
200460484Sobrien
200560484Sobrien#define COFF_SECTION_ALIGNMENT_ENTRIES \
200660484Sobrien{ COFF_SECTION_NAME_EXACT_MATCH (".idata$2"), \
200760484Sobrien  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }, \
200860484Sobrien{ COFF_SECTION_NAME_EXACT_MATCH (".idata$3"), \
200960484Sobrien  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }, \
201060484Sobrien{ COFF_SECTION_NAME_EXACT_MATCH (".idata$4"), \
201160484Sobrien  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
201260484Sobrien{ COFF_SECTION_NAME_EXACT_MATCH (".idata$5"), \
201360484Sobrien  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
201460484Sobrien{ COFF_SECTION_NAME_EXACT_MATCH (".idata$6"), \
201560484Sobrien  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 1 }, \
201660484Sobrien{ COFF_SECTION_NAME_EXACT_MATCH (".reloc"), \
201760484Sobrien  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 1 }
201860484Sobrien
201960484Sobrien#include "coffcode.h"
202060484Sobrien
202160484Sobrien#ifndef COFF_IMAGE_WITH_PE
202260484Sobrien
2023130561Sobrienstatic bfd_boolean ppc_do_last PARAMS ((bfd *));
202460484Sobrienstatic bfd *ppc_get_last PARAMS ((void));
202560484Sobrien
2026130561Sobrienstatic bfd_boolean
202760484Sobrienppc_do_last (abfd)
202860484Sobrien     bfd *abfd;
202960484Sobrien{
203060484Sobrien  if (abfd == bfd_of_toc_owner)
2031130561Sobrien    return TRUE;
203260484Sobrien  else
2033130561Sobrien    return FALSE;
203460484Sobrien}
203560484Sobrien
203660484Sobrienstatic bfd *
203760484Sobrienppc_get_last()
203860484Sobrien{
203960484Sobrien  return bfd_of_toc_owner;
204060484Sobrien}
204160484Sobrien
2042130561Sobrien/* This piece of machinery exists only to guarantee that the bfd that holds
204377298Sobrien   the toc section is written last.
204460484Sobrien
204560484Sobrien   This does depend on bfd_make_section attaching a new section to the
204677298Sobrien   end of the section list for the bfd.
204760484Sobrien
204877298Sobrien   This is otherwise intended to be functionally the same as
204977298Sobrien   cofflink.c:_bfd_coff_final_link(). It is specifically different only
205077298Sobrien   where the POWERPC_LE_PE macro modifies the code. It is left in as a
2051130561Sobrien   precise form of comment. krk@cygnus.com  */
205260484Sobrien
205360484Sobrien/* Do the final link step.  */
205460484Sobrien
2055130561Sobrienbfd_boolean
205660484Sobrienppc_bfd_coff_final_link (abfd, info)
205760484Sobrien     bfd *abfd;
205860484Sobrien     struct bfd_link_info *info;
205960484Sobrien{
206060484Sobrien  bfd_size_type symesz;
206160484Sobrien  struct coff_final_link_info finfo;
2062130561Sobrien  bfd_boolean debug_merge_allocated;
206360484Sobrien  asection *o;
206460484Sobrien  struct bfd_link_order *p;
206589857Sobrien  bfd_size_type max_sym_count;
206689857Sobrien  bfd_size_type max_lineno_count;
206789857Sobrien  bfd_size_type max_reloc_count;
206889857Sobrien  bfd_size_type max_output_reloc_count;
206989857Sobrien  bfd_size_type max_contents_size;
207060484Sobrien  file_ptr rel_filepos;
207160484Sobrien  unsigned int relsz;
207260484Sobrien  file_ptr line_filepos;
207360484Sobrien  unsigned int linesz;
207460484Sobrien  bfd *sub;
207560484Sobrien  bfd_byte *external_relocs = NULL;
207660484Sobrien  char strbuf[STRING_SIZE_SIZE];
207789857Sobrien  bfd_size_type amt;
207860484Sobrien
207960484Sobrien  symesz = bfd_coff_symesz (abfd);
208060484Sobrien
208160484Sobrien  finfo.info = info;
208260484Sobrien  finfo.output_bfd = abfd;
208360484Sobrien  finfo.strtab = NULL;
208460484Sobrien  finfo.section_info = NULL;
208560484Sobrien  finfo.last_file_index = -1;
208660484Sobrien  finfo.last_bf_index = -1;
208760484Sobrien  finfo.internal_syms = NULL;
208860484Sobrien  finfo.sec_ptrs = NULL;
208960484Sobrien  finfo.sym_indices = NULL;
209060484Sobrien  finfo.outsyms = NULL;
209160484Sobrien  finfo.linenos = NULL;
209260484Sobrien  finfo.contents = NULL;
209360484Sobrien  finfo.external_relocs = NULL;
209460484Sobrien  finfo.internal_relocs = NULL;
2095130561Sobrien  debug_merge_allocated = FALSE;
209660484Sobrien
209760484Sobrien  coff_data (abfd)->link_info = info;
209860484Sobrien
209960484Sobrien  finfo.strtab = _bfd_stringtab_init ();
210060484Sobrien  if (finfo.strtab == NULL)
210160484Sobrien    goto error_return;
210260484Sobrien
210360484Sobrien  if (! coff_debug_merge_hash_table_init (&finfo.debug_merge))
210460484Sobrien    goto error_return;
2105130561Sobrien  debug_merge_allocated = TRUE;
210660484Sobrien
210760484Sobrien  /* Compute the file positions for all the sections.  */
210860484Sobrien  if (! abfd->output_has_begun)
210960484Sobrien    {
211060484Sobrien      if (! bfd_coff_compute_section_file_positions (abfd))
2111130561Sobrien	return FALSE;
211260484Sobrien    }
211360484Sobrien
211460484Sobrien  /* Count the line numbers and relocation entries required for the
211560484Sobrien     output file.  Set the file positions for the relocs.  */
211660484Sobrien  rel_filepos = obj_relocbase (abfd);
211760484Sobrien  relsz = bfd_coff_relsz (abfd);
211860484Sobrien  max_contents_size = 0;
211960484Sobrien  max_lineno_count = 0;
212060484Sobrien  max_reloc_count = 0;
212160484Sobrien
212260484Sobrien  for (o = abfd->sections; o != NULL; o = o->next)
212360484Sobrien    {
212460484Sobrien      o->reloc_count = 0;
212560484Sobrien      o->lineno_count = 0;
2126130561Sobrien
2127218822Sdim      for (p = o->map_head.link_order; p != NULL; p = p->next)
212860484Sobrien	{
212960484Sobrien	  if (p->type == bfd_indirect_link_order)
213060484Sobrien	    {
213160484Sobrien	      asection *sec;
213260484Sobrien
213360484Sobrien	      sec = p->u.indirect.section;
213460484Sobrien
213560484Sobrien	      /* Mark all sections which are to be included in the
213660484Sobrien		 link.  This will normally be every section.  We need
213760484Sobrien		 to do this so that we can identify any sections which
213860484Sobrien		 the linker has decided to not include.  */
2139130561Sobrien	      sec->linker_mark = TRUE;
214060484Sobrien
214160484Sobrien	      if (info->strip == strip_none
214260484Sobrien		  || info->strip == strip_some)
214360484Sobrien		o->lineno_count += sec->lineno_count;
214460484Sobrien
2145130561Sobrien	      if (info->relocatable)
214660484Sobrien		o->reloc_count += sec->reloc_count;
214760484Sobrien
2148218822Sdim	      if (sec->rawsize > max_contents_size)
2149218822Sdim		max_contents_size = sec->rawsize;
2150218822Sdim	      if (sec->size > max_contents_size)
2151218822Sdim		max_contents_size = sec->size;
215260484Sobrien	      if (sec->lineno_count > max_lineno_count)
215360484Sobrien		max_lineno_count = sec->lineno_count;
215460484Sobrien	      if (sec->reloc_count > max_reloc_count)
215560484Sobrien		max_reloc_count = sec->reloc_count;
215660484Sobrien	    }
2157130561Sobrien	  else if (info->relocatable
215860484Sobrien		   && (p->type == bfd_section_reloc_link_order
215960484Sobrien		       || p->type == bfd_symbol_reloc_link_order))
216060484Sobrien	    ++o->reloc_count;
216160484Sobrien	}
216260484Sobrien      if (o->reloc_count == 0)
216360484Sobrien	o->rel_filepos = 0;
216460484Sobrien      else
216560484Sobrien	{
216660484Sobrien	  o->flags |= SEC_RELOC;
216760484Sobrien	  o->rel_filepos = rel_filepos;
216860484Sobrien	  rel_filepos += o->reloc_count * relsz;
216960484Sobrien	}
217060484Sobrien    }
217160484Sobrien
2172130561Sobrien  /* If doing a relocatable link, allocate space for the pointers we
217360484Sobrien     need to keep.  */
2174130561Sobrien  if (info->relocatable)
217560484Sobrien    {
217660484Sobrien      unsigned int i;
217760484Sobrien
217860484Sobrien      /* We use section_count + 1, rather than section_count, because
217960484Sobrien         the target_index fields are 1 based.  */
218089857Sobrien      amt = abfd->section_count + 1;
218189857Sobrien      amt *= sizeof (struct coff_link_section_info);
218289857Sobrien      finfo.section_info = (struct coff_link_section_info *) bfd_malloc (amt);
2183130561Sobrien
218460484Sobrien      if (finfo.section_info == NULL)
218560484Sobrien	goto error_return;
2186130561Sobrien
218760484Sobrien      for (i = 0; i <= abfd->section_count; i++)
218860484Sobrien	{
218960484Sobrien	  finfo.section_info[i].relocs = NULL;
219060484Sobrien	  finfo.section_info[i].rel_hashes = NULL;
219160484Sobrien	}
219260484Sobrien    }
219360484Sobrien
219460484Sobrien  /* We now know the size of the relocs, so we can determine the file
219560484Sobrien     positions of the line numbers.  */
219660484Sobrien  line_filepos = rel_filepos;
219760484Sobrien  linesz = bfd_coff_linesz (abfd);
219860484Sobrien  max_output_reloc_count = 0;
2199130561Sobrien
220060484Sobrien  for (o = abfd->sections; o != NULL; o = o->next)
220160484Sobrien    {
220260484Sobrien      if (o->lineno_count == 0)
220360484Sobrien	o->line_filepos = 0;
220460484Sobrien      else
220560484Sobrien	{
220660484Sobrien	  o->line_filepos = line_filepos;
220760484Sobrien	  line_filepos += o->lineno_count * linesz;
220860484Sobrien	}
220960484Sobrien
221060484Sobrien      if (o->reloc_count != 0)
221160484Sobrien	{
221260484Sobrien	  /* We don't know the indices of global symbols until we have
221360484Sobrien             written out all the local symbols.  For each section in
221460484Sobrien             the output file, we keep an array of pointers to hash
221560484Sobrien             table entries.  Each entry in the array corresponds to a
221660484Sobrien             reloc.  When we find a reloc against a global symbol, we
221760484Sobrien             set the corresponding entry in this array so that we can
221860484Sobrien             fix up the symbol index after we have written out all the
221960484Sobrien             local symbols.
222060484Sobrien
222160484Sobrien	     Because of this problem, we also keep the relocs in
222260484Sobrien	     memory until the end of the link.  This wastes memory,
2223130561Sobrien	     but only when doing a relocatable link, which is not the
222460484Sobrien	     common case.  */
2225130561Sobrien	  BFD_ASSERT (info->relocatable);
222689857Sobrien	  amt = o->reloc_count;
222789857Sobrien	  amt *= sizeof (struct internal_reloc);
222860484Sobrien	  finfo.section_info[o->target_index].relocs =
222989857Sobrien	    (struct internal_reloc *) bfd_malloc (amt);
223089857Sobrien	  amt = o->reloc_count;
223189857Sobrien	  amt *= sizeof (struct coff_link_hash_entry *);
223260484Sobrien	  finfo.section_info[o->target_index].rel_hashes =
223389857Sobrien	    (struct coff_link_hash_entry **) bfd_malloc (amt);
223460484Sobrien	  if (finfo.section_info[o->target_index].relocs == NULL
223560484Sobrien	      || finfo.section_info[o->target_index].rel_hashes == NULL)
223660484Sobrien	    goto error_return;
223760484Sobrien
223860484Sobrien	  if (o->reloc_count > max_output_reloc_count)
223960484Sobrien	    max_output_reloc_count = o->reloc_count;
224060484Sobrien	}
224160484Sobrien
224260484Sobrien      /* Reset the reloc and lineno counts, so that we can use them to
224360484Sobrien	 count the number of entries we have output so far.  */
224460484Sobrien      o->reloc_count = 0;
224560484Sobrien      o->lineno_count = 0;
224660484Sobrien    }
224760484Sobrien
224860484Sobrien  obj_sym_filepos (abfd) = line_filepos;
224960484Sobrien
225060484Sobrien  /* Figure out the largest number of symbols in an input BFD.  Take
225160484Sobrien     the opportunity to clear the output_has_begun fields of all the
225260484Sobrien     input BFD's.  */
225360484Sobrien  max_sym_count = 0;
225460484Sobrien  for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
225560484Sobrien    {
225689857Sobrien      bfd_size_type sz;
225760484Sobrien
2258130561Sobrien      sub->output_has_begun = FALSE;
225960484Sobrien      sz = obj_raw_syment_count (sub);
226060484Sobrien      if (sz > max_sym_count)
226160484Sobrien	max_sym_count = sz;
226260484Sobrien    }
226360484Sobrien
226460484Sobrien  /* Allocate some buffers used while linking.  */
226589857Sobrien  amt = max_sym_count * sizeof (struct internal_syment);
226689857Sobrien  finfo.internal_syms = (struct internal_syment *) bfd_malloc (amt);
226789857Sobrien  amt = max_sym_count * sizeof (asection *);
226889857Sobrien  finfo.sec_ptrs = (asection **) bfd_malloc (amt);
226989857Sobrien  amt = max_sym_count * sizeof (long);
227089857Sobrien  finfo.sym_indices = (long *) bfd_malloc (amt);
227189857Sobrien  amt = (max_sym_count + 1) * symesz;
227289857Sobrien  finfo.outsyms = (bfd_byte *) bfd_malloc (amt);
227389857Sobrien  amt = max_lineno_count * bfd_coff_linesz (abfd);
227489857Sobrien  finfo.linenos = (bfd_byte *) bfd_malloc (amt);
227560484Sobrien  finfo.contents = (bfd_byte *) bfd_malloc (max_contents_size);
227660484Sobrien  finfo.external_relocs = (bfd_byte *) bfd_malloc (max_reloc_count * relsz);
2277130561Sobrien  if (! info->relocatable)
227889857Sobrien    {
227989857Sobrien      amt = max_reloc_count * sizeof (struct internal_reloc);
228089857Sobrien      finfo.internal_relocs = (struct internal_reloc *) bfd_malloc (amt);
228189857Sobrien    }
228260484Sobrien  if ((finfo.internal_syms == NULL && max_sym_count > 0)
228360484Sobrien      || (finfo.sec_ptrs == NULL && max_sym_count > 0)
228460484Sobrien      || (finfo.sym_indices == NULL && max_sym_count > 0)
228560484Sobrien      || finfo.outsyms == NULL
228660484Sobrien      || (finfo.linenos == NULL && max_lineno_count > 0)
228760484Sobrien      || (finfo.contents == NULL && max_contents_size > 0)
228860484Sobrien      || (finfo.external_relocs == NULL && max_reloc_count > 0)
2289130561Sobrien      || (! info->relocatable
229060484Sobrien	  && finfo.internal_relocs == NULL
229160484Sobrien	  && max_reloc_count > 0))
229260484Sobrien    goto error_return;
229360484Sobrien
229460484Sobrien  /* We now know the position of everything in the file, except that
229560484Sobrien     we don't know the size of the symbol table and therefore we don't
229660484Sobrien     know where the string table starts.  We just build the string
229760484Sobrien     table in memory as we go along.  We process all the relocations
229860484Sobrien     for a single input file at once.  */
229960484Sobrien  obj_raw_syment_count (abfd) = 0;
230060484Sobrien
230160484Sobrien  if (coff_backend_info (abfd)->_bfd_coff_start_final_link)
230260484Sobrien    {
230360484Sobrien      if (! bfd_coff_start_final_link (abfd, info))
230460484Sobrien	goto error_return;
230560484Sobrien    }
230660484Sobrien
230760484Sobrien  for (o = abfd->sections; o != NULL; o = o->next)
230860484Sobrien    {
2309218822Sdim      for (p = o->map_head.link_order; p != NULL; p = p->next)
231060484Sobrien	{
231160484Sobrien	  if (p->type == bfd_indirect_link_order
231260484Sobrien	      && (bfd_get_flavour (p->u.indirect.section->owner)
231360484Sobrien		  == bfd_target_coff_flavour))
231460484Sobrien	    {
231560484Sobrien	      sub = p->u.indirect.section->owner;
231660484Sobrien#ifdef POWERPC_LE_PE
231760484Sobrien	      if (! sub->output_has_begun && !ppc_do_last(sub))
231860484Sobrien#else
231960484Sobrien	      if (! sub->output_has_begun)
232060484Sobrien#endif
232160484Sobrien		{
232260484Sobrien		  if (! _bfd_coff_link_input_bfd (&finfo, sub))
232360484Sobrien		    goto error_return;
2324130561Sobrien		  sub->output_has_begun = TRUE;
232560484Sobrien		}
232660484Sobrien	    }
232760484Sobrien	  else if (p->type == bfd_section_reloc_link_order
232860484Sobrien		   || p->type == bfd_symbol_reloc_link_order)
232960484Sobrien	    {
233060484Sobrien	      if (! _bfd_coff_reloc_link_order (abfd, &finfo, o, p))
233160484Sobrien		goto error_return;
233260484Sobrien	    }
233360484Sobrien	  else
233460484Sobrien	    {
233560484Sobrien	      if (! _bfd_default_link_order (abfd, info, o, p))
233660484Sobrien		goto error_return;
233760484Sobrien	    }
233860484Sobrien	}
233960484Sobrien    }
234060484Sobrien
234160484Sobrien#ifdef POWERPC_LE_PE
234260484Sobrien  {
234360484Sobrien    bfd* last_one = ppc_get_last();
234460484Sobrien    if (last_one)
234560484Sobrien      {
234660484Sobrien	if (! _bfd_coff_link_input_bfd (&finfo, last_one))
234760484Sobrien	  goto error_return;
234860484Sobrien      }
2349130561Sobrien    last_one->output_has_begun = TRUE;
235060484Sobrien  }
235160484Sobrien#endif
235260484Sobrien
235360484Sobrien  /* Free up the buffers used by _bfd_coff_link_input_bfd.  */
235460484Sobrien  coff_debug_merge_hash_table_free (&finfo.debug_merge);
2355130561Sobrien  debug_merge_allocated = FALSE;
235660484Sobrien
235760484Sobrien  if (finfo.internal_syms != NULL)
235860484Sobrien    {
235960484Sobrien      free (finfo.internal_syms);
236060484Sobrien      finfo.internal_syms = NULL;
236160484Sobrien    }
236260484Sobrien  if (finfo.sec_ptrs != NULL)
236360484Sobrien    {
236460484Sobrien      free (finfo.sec_ptrs);
236560484Sobrien      finfo.sec_ptrs = NULL;
236660484Sobrien    }
236760484Sobrien  if (finfo.sym_indices != NULL)
236860484Sobrien    {
236960484Sobrien      free (finfo.sym_indices);
237060484Sobrien      finfo.sym_indices = NULL;
237160484Sobrien    }
237260484Sobrien  if (finfo.linenos != NULL)
237360484Sobrien    {
237460484Sobrien      free (finfo.linenos);
237560484Sobrien      finfo.linenos = NULL;
237660484Sobrien    }
237760484Sobrien  if (finfo.contents != NULL)
237860484Sobrien    {
237960484Sobrien      free (finfo.contents);
238060484Sobrien      finfo.contents = NULL;
238160484Sobrien    }
238260484Sobrien  if (finfo.external_relocs != NULL)
238360484Sobrien    {
238460484Sobrien      free (finfo.external_relocs);
238560484Sobrien      finfo.external_relocs = NULL;
238660484Sobrien    }
238760484Sobrien  if (finfo.internal_relocs != NULL)
238860484Sobrien    {
238960484Sobrien      free (finfo.internal_relocs);
239060484Sobrien      finfo.internal_relocs = NULL;
239160484Sobrien    }
239260484Sobrien
239360484Sobrien  /* The value of the last C_FILE symbol is supposed to be the symbol
239460484Sobrien     index of the first external symbol.  Write it out again if
239560484Sobrien     necessary.  */
239660484Sobrien  if (finfo.last_file_index != -1
239760484Sobrien      && (unsigned int) finfo.last_file.n_value != obj_raw_syment_count (abfd))
239860484Sobrien    {
239989857Sobrien      file_ptr pos;
240089857Sobrien
240160484Sobrien      finfo.last_file.n_value = obj_raw_syment_count (abfd);
240260484Sobrien      bfd_coff_swap_sym_out (abfd, (PTR) &finfo.last_file,
240360484Sobrien			     (PTR) finfo.outsyms);
240489857Sobrien      pos = obj_sym_filepos (abfd) + finfo.last_file_index * symesz;
240589857Sobrien      if (bfd_seek (abfd, pos, SEEK_SET) != 0
240689857Sobrien	  || bfd_bwrite (finfo.outsyms, symesz, abfd) != symesz)
2407130561Sobrien	return FALSE;
240860484Sobrien    }
240960484Sobrien
241060484Sobrien  /* Write out the global symbols.  */
2411130561Sobrien  finfo.failed = FALSE;
241260484Sobrien  coff_link_hash_traverse (coff_hash_table (info), _bfd_coff_write_global_sym,
241360484Sobrien			   (PTR) &finfo);
241460484Sobrien  if (finfo.failed)
241560484Sobrien    goto error_return;
241660484Sobrien
241760484Sobrien  /* The outsyms buffer is used by _bfd_coff_write_global_sym.  */
241860484Sobrien  if (finfo.outsyms != NULL)
241960484Sobrien    {
242060484Sobrien      free (finfo.outsyms);
242160484Sobrien      finfo.outsyms = NULL;
242260484Sobrien    }
242360484Sobrien
2424130561Sobrien  if (info->relocatable)
242560484Sobrien    {
242660484Sobrien      /* Now that we have written out all the global symbols, we know
242760484Sobrien	 the symbol indices to use for relocs against them, and we can
242860484Sobrien	 finally write out the relocs.  */
242989857Sobrien      amt = max_output_reloc_count * relsz;
243089857Sobrien      external_relocs = (bfd_byte *) bfd_malloc (amt);
243160484Sobrien      if (external_relocs == NULL)
243260484Sobrien	goto error_return;
243360484Sobrien
243460484Sobrien      for (o = abfd->sections; o != NULL; o = o->next)
243560484Sobrien	{
243660484Sobrien	  struct internal_reloc *irel;
243760484Sobrien	  struct internal_reloc *irelend;
243860484Sobrien	  struct coff_link_hash_entry **rel_hash;
243960484Sobrien	  bfd_byte *erel;
244060484Sobrien
244160484Sobrien	  if (o->reloc_count == 0)
244260484Sobrien	    continue;
244360484Sobrien
244460484Sobrien	  irel = finfo.section_info[o->target_index].relocs;
244560484Sobrien	  irelend = irel + o->reloc_count;
244660484Sobrien	  rel_hash = finfo.section_info[o->target_index].rel_hashes;
244760484Sobrien	  erel = external_relocs;
244860484Sobrien	  for (; irel < irelend; irel++, rel_hash++, erel += relsz)
244960484Sobrien	    {
245060484Sobrien	      if (*rel_hash != NULL)
245160484Sobrien		{
245260484Sobrien		  BFD_ASSERT ((*rel_hash)->indx >= 0);
245360484Sobrien		  irel->r_symndx = (*rel_hash)->indx;
245460484Sobrien		}
245560484Sobrien	      bfd_coff_swap_reloc_out (abfd, (PTR) irel, (PTR) erel);
245660484Sobrien	    }
245760484Sobrien
245889857Sobrien	  amt = relsz * o->reloc_count;
245960484Sobrien	  if (bfd_seek (abfd, o->rel_filepos, SEEK_SET) != 0
246089857Sobrien	      || bfd_bwrite ((PTR) external_relocs, amt, abfd) != amt)
246160484Sobrien	    goto error_return;
246260484Sobrien	}
246360484Sobrien
246460484Sobrien      free (external_relocs);
246560484Sobrien      external_relocs = NULL;
246660484Sobrien    }
246760484Sobrien
246860484Sobrien  /* Free up the section information.  */
246960484Sobrien  if (finfo.section_info != NULL)
247060484Sobrien    {
247160484Sobrien      unsigned int i;
247260484Sobrien
247360484Sobrien      for (i = 0; i < abfd->section_count; i++)
247460484Sobrien	{
247560484Sobrien	  if (finfo.section_info[i].relocs != NULL)
247660484Sobrien	    free (finfo.section_info[i].relocs);
247760484Sobrien	  if (finfo.section_info[i].rel_hashes != NULL)
247860484Sobrien	    free (finfo.section_info[i].rel_hashes);
247960484Sobrien	}
248060484Sobrien      free (finfo.section_info);
248160484Sobrien      finfo.section_info = NULL;
248260484Sobrien    }
248360484Sobrien
248460484Sobrien  /* If we have optimized stabs strings, output them.  */
2485218822Sdim  if (coff_hash_table (info)->stab_info.stabstr != NULL)
248660484Sobrien    {
248760484Sobrien      if (! _bfd_write_stab_strings (abfd, &coff_hash_table (info)->stab_info))
2488130561Sobrien	return FALSE;
248960484Sobrien    }
249060484Sobrien
249160484Sobrien  /* Write out the string table.  */
249260484Sobrien  if (obj_raw_syment_count (abfd) != 0)
249360484Sobrien    {
249489857Sobrien      file_ptr pos;
249589857Sobrien
249689857Sobrien      pos = obj_sym_filepos (abfd) + obj_raw_syment_count (abfd) * symesz;
249789857Sobrien      if (bfd_seek (abfd, pos, SEEK_SET) != 0)
2498130561Sobrien	return FALSE;
249960484Sobrien
250060484Sobrien#if STRING_SIZE_SIZE == 4
250189857Sobrien      H_PUT_32 (abfd,
250289857Sobrien		_bfd_stringtab_size (finfo.strtab) + STRING_SIZE_SIZE,
250389857Sobrien		strbuf);
250460484Sobrien#else
250589857Sobrien #error Change H_PUT_32 above
250660484Sobrien#endif
250760484Sobrien
250889857Sobrien      if (bfd_bwrite (strbuf, (bfd_size_type) STRING_SIZE_SIZE, abfd)
250989857Sobrien	  != STRING_SIZE_SIZE)
2510130561Sobrien	return FALSE;
251160484Sobrien
251260484Sobrien      if (! _bfd_stringtab_emit (abfd, finfo.strtab))
2513130561Sobrien	return FALSE;
251460484Sobrien    }
251560484Sobrien
251660484Sobrien  _bfd_stringtab_free (finfo.strtab);
251760484Sobrien
251860484Sobrien  /* Setting bfd_get_symcount to 0 will cause write_object_contents to
251960484Sobrien     not try to write out the symbols.  */
252060484Sobrien  bfd_get_symcount (abfd) = 0;
252160484Sobrien
2522130561Sobrien  return TRUE;
252360484Sobrien
252460484Sobrien error_return:
252560484Sobrien  if (debug_merge_allocated)
252660484Sobrien    coff_debug_merge_hash_table_free (&finfo.debug_merge);
252760484Sobrien  if (finfo.strtab != NULL)
252860484Sobrien    _bfd_stringtab_free (finfo.strtab);
252960484Sobrien  if (finfo.section_info != NULL)
253060484Sobrien    {
253160484Sobrien      unsigned int i;
253260484Sobrien
253360484Sobrien      for (i = 0; i < abfd->section_count; i++)
253460484Sobrien	{
253560484Sobrien	  if (finfo.section_info[i].relocs != NULL)
253660484Sobrien	    free (finfo.section_info[i].relocs);
253760484Sobrien	  if (finfo.section_info[i].rel_hashes != NULL)
253860484Sobrien	    free (finfo.section_info[i].rel_hashes);
253960484Sobrien	}
254060484Sobrien      free (finfo.section_info);
254160484Sobrien    }
254260484Sobrien  if (finfo.internal_syms != NULL)
254360484Sobrien    free (finfo.internal_syms);
254460484Sobrien  if (finfo.sec_ptrs != NULL)
254560484Sobrien    free (finfo.sec_ptrs);
254660484Sobrien  if (finfo.sym_indices != NULL)
254760484Sobrien    free (finfo.sym_indices);
254860484Sobrien  if (finfo.outsyms != NULL)
254960484Sobrien    free (finfo.outsyms);
255060484Sobrien  if (finfo.linenos != NULL)
255160484Sobrien    free (finfo.linenos);
255260484Sobrien  if (finfo.contents != NULL)
255360484Sobrien    free (finfo.contents);
255460484Sobrien  if (finfo.external_relocs != NULL)
255560484Sobrien    free (finfo.external_relocs);
255660484Sobrien  if (finfo.internal_relocs != NULL)
255760484Sobrien    free (finfo.internal_relocs);
255860484Sobrien  if (external_relocs != NULL)
255960484Sobrien    free (external_relocs);
2560130561Sobrien  return FALSE;
256160484Sobrien}
256260484Sobrien#endif
256360484Sobrien
256460484Sobrien/* Forward declaration for use by alternative_target field.  */
256560484Sobrien#ifdef TARGET_BIG_SYM
256660484Sobrienextern const bfd_target TARGET_BIG_SYM;
256760484Sobrien#endif
256860484Sobrien
256977298Sobrien/* The transfer vectors that lead the outside world to all of the above.  */
257060484Sobrien
257160484Sobrien#ifdef TARGET_LITTLE_SYM
257260484Sobrienconst bfd_target TARGET_LITTLE_SYM =
257360484Sobrien{
257460484Sobrien  TARGET_LITTLE_NAME,		/* name or coff-arm-little */
257560484Sobrien  bfd_target_coff_flavour,
257660484Sobrien  BFD_ENDIAN_LITTLE,		/* data byte order is little */
257760484Sobrien  BFD_ENDIAN_LITTLE,		/* header byte order is little */
257860484Sobrien
257960484Sobrien  (HAS_RELOC | EXEC_P |		/* FIXME: object flags */
258060484Sobrien   HAS_LINENO | HAS_DEBUG |
258160484Sobrien   HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
258277298Sobrien
258360484Sobrien#ifndef COFF_WITH_PE
258460484Sobrien  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
258560484Sobrien#else
258660484Sobrien  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* section flags */
258760484Sobrien   | SEC_LINK_ONCE | SEC_LINK_DUPLICATES),
258860484Sobrien#endif
258960484Sobrien
259060484Sobrien  0,				/* leading char */
259160484Sobrien  '/',				/* ar_pad_char */
259260484Sobrien  15,				/* ar_max_namelen??? FIXMEmgo */
259360484Sobrien
259460484Sobrien  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
259560484Sobrien  bfd_getl32, bfd_getl_signed_32, bfd_putl32,
259660484Sobrien  bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
259760484Sobrien
259860484Sobrien  bfd_getl64, bfd_getl_signed_64, bfd_putl64,
259960484Sobrien  bfd_getl32, bfd_getl_signed_32, bfd_putl32,
260060484Sobrien  bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
260177298Sobrien
260260484Sobrien  {_bfd_dummy_target, coff_object_p, 	/* bfd_check_format */
260360484Sobrien     bfd_generic_archive_p, /* _bfd_dummy_target */ coff_object_p },
260460484Sobrien  {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
260560484Sobrien     bfd_false},
260660484Sobrien  {bfd_false, coff_write_object_contents,	/* bfd_write_contents */
260760484Sobrien     _bfd_write_archive_contents, bfd_false},
260877298Sobrien
260960484Sobrien  BFD_JUMP_TABLE_GENERIC (coff),
261060484Sobrien  BFD_JUMP_TABLE_COPY (coff),
261160484Sobrien  BFD_JUMP_TABLE_CORE (_bfd_nocore),
261260484Sobrien  BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
261360484Sobrien  BFD_JUMP_TABLE_SYMBOLS (coff),
261460484Sobrien  BFD_JUMP_TABLE_RELOCS (coff),
261560484Sobrien  BFD_JUMP_TABLE_WRITE (coff),
261660484Sobrien  BFD_JUMP_TABLE_LINK (coff),
261760484Sobrien  BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
261860484Sobrien
261960484Sobrien  /* Alternative_target.  */
262060484Sobrien#ifdef TARGET_BIG_SYM
262160484Sobrien  & TARGET_BIG_SYM,
262260484Sobrien#else
262360484Sobrien  NULL,
262460484Sobrien#endif
262577298Sobrien
262660484Sobrien  COFF_SWAP_TABLE
262760484Sobrien};
262860484Sobrien#endif
262960484Sobrien
263060484Sobrien#ifdef TARGET_BIG_SYM
263160484Sobrienconst bfd_target TARGET_BIG_SYM =
263260484Sobrien{
263360484Sobrien  TARGET_BIG_NAME,
263477298Sobrien  bfd_target_coff_flavour,
263560484Sobrien  BFD_ENDIAN_BIG,		/* data byte order is big */
263660484Sobrien  BFD_ENDIAN_BIG,		/* header byte order is big */
263760484Sobrien
263860484Sobrien  (HAS_RELOC | EXEC_P |		/* FIXME: object flags */
263960484Sobrien   HAS_LINENO | HAS_DEBUG |
264060484Sobrien   HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
264160484Sobrien
264260484Sobrien#ifndef COFF_WITH_PE
264360484Sobrien  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
264460484Sobrien#else
264560484Sobrien  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* section flags */
264660484Sobrien   | SEC_LINK_ONCE | SEC_LINK_DUPLICATES),
264760484Sobrien#endif
264860484Sobrien
264960484Sobrien  0,				/* leading char */
265060484Sobrien  '/',				/* ar_pad_char */
265160484Sobrien  15,				/* ar_max_namelen??? FIXMEmgo */
265260484Sobrien
265360484Sobrien  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
265460484Sobrien  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
265560484Sobrien  bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
265660484Sobrien
265760484Sobrien  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
265860484Sobrien  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
265960484Sobrien  bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
266060484Sobrien
266160484Sobrien  {_bfd_dummy_target, coff_object_p, 	/* bfd_check_format */
266260484Sobrien     bfd_generic_archive_p, /* _bfd_dummy_target */ coff_object_p },
266360484Sobrien  {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
266460484Sobrien     bfd_false},
266560484Sobrien  {bfd_false, coff_write_object_contents,	/* bfd_write_contents */
266660484Sobrien     _bfd_write_archive_contents, bfd_false},
266760484Sobrien
266860484Sobrien  BFD_JUMP_TABLE_GENERIC (coff),
266960484Sobrien  BFD_JUMP_TABLE_COPY (coff),
267060484Sobrien  BFD_JUMP_TABLE_CORE (_bfd_nocore),
267160484Sobrien  BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
267260484Sobrien  BFD_JUMP_TABLE_SYMBOLS (coff),
267360484Sobrien  BFD_JUMP_TABLE_RELOCS (coff),
267460484Sobrien  BFD_JUMP_TABLE_WRITE (coff),
267560484Sobrien  BFD_JUMP_TABLE_LINK (coff),
267660484Sobrien  BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
267760484Sobrien
267860484Sobrien  /* Alternative_target.  */
267960484Sobrien#ifdef TARGET_LITTLE_SYM
268060484Sobrien  & TARGET_LITTLE_SYM,
268160484Sobrien#else
268260484Sobrien  NULL,
268360484Sobrien#endif
268477298Sobrien
268560484Sobrien  COFF_SWAP_TABLE
268660484Sobrien};
268760484Sobrien
268860484Sobrien#endif
2689