summaryrefslogtreecommitdiff
path: root/gnu/usr.bin/binutils/bfd/coff-ppc.c
diff options
context:
space:
mode:
authorNiklas Hallqvist <niklas@cvs.openbsd.org>1996-01-08 11:10:27 +0000
committerNiklas Hallqvist <niklas@cvs.openbsd.org>1996-01-08 11:10:27 +0000
commit8b46c09925a80623c289e346c12921bc09fd1678 (patch)
tree01507d0da339cc7e5e6f5d16dfa625f94910b091 /gnu/usr.bin/binutils/bfd/coff-ppc.c
parent5d56227f9458a53138642c1b4488b4a30f85f334 (diff)
Initial GNU binutils 2.6 import
Diffstat (limited to 'gnu/usr.bin/binutils/bfd/coff-ppc.c')
-rw-r--r--gnu/usr.bin/binutils/bfd/coff-ppc.c2346
1 files changed, 2346 insertions, 0 deletions
diff --git a/gnu/usr.bin/binutils/bfd/coff-ppc.c b/gnu/usr.bin/binutils/bfd/coff-ppc.c
new file mode 100644
index 00000000000..94ef048546d
--- /dev/null
+++ b/gnu/usr.bin/binutils/bfd/coff-ppc.c
@@ -0,0 +1,2346 @@
+/* BFD back-end for PowerPC Microsoft Portable Executable files.
+ Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+
+ Original version pieced together by Kim Knuttila (krk@cygnus.com)
+
+ There is nothing new under the sun. This file draws a lot on other
+ coff files, in particular, those for the rs/6000, alpha, mips, and
+ intel backends, and the PE work for the arm.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Current State:
+ - objdump works
+ - relocs generated by gas
+ - ld will link files, but they do not run.
+ - dlltool will not produce correct output in some .reloc cases, and will
+ not produce the right glue code for dll function calls.
+*/
+
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "obstack.h"
+
+#include "coff/powerpc.h"
+#include "coff/internal.h"
+
+#include "coff/pe.h"
+
+#ifdef BADMAG
+#undef BADMAG
+#endif
+
+#define BADMAG(x) PPCBADMAG(x)
+
+#include "libcoff.h"
+
+/* In order not to add an int to every hash table item for every coff
+ linker, we define our own hash table, derived from the coff one */
+
+/* PE linker hash table entries. */
+
+struct ppc_coff_link_hash_entry
+{
+ struct coff_link_hash_entry root; /* First entry, as required */
+
+ /* As we wonder around the relocs, we'll keep the assigned toc_offset
+ here */
+ bfd_vma toc_offset; /* Our addition, as required */
+ int symbol_is_glue;
+ unsigned long int glue_insn;
+ char eye_catcher[8];
+};
+
+/* Need a 7 char string for an eye catcher */
+#define EYE "krkjunk"
+
+#define CHECK_EYE(addr) \
+ if (strcmp(addr, EYE) != 0) \
+ { \
+ fprintf(stderr,\
+ "File %s, line %d, Hash check failure, bad eye %8s\n", \
+ __FILE__, __LINE__, addr); \
+ abort(); \
+ }
+
+/* PE linker hash table. */
+
+struct ppc_coff_link_hash_table
+{
+ struct coff_link_hash_table root; /* First entry, as required */
+};
+
+static struct bfd_hash_entry *ppc_coff_link_hash_newfunc
+ PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *,
+ const char *));
+
+/* Routine to create an entry in the link hash table. */
+
+static struct bfd_hash_entry *
+ppc_coff_link_hash_newfunc (entry, table, string)
+ struct bfd_hash_entry *entry;
+ struct bfd_hash_table *table;
+ const char *string;
+{
+ struct ppc_coff_link_hash_entry *ret =
+ (struct ppc_coff_link_hash_entry *) entry;
+
+ /* Allocate the structure if it has not already been allocated by a
+ subclass. */
+ if (ret == (struct ppc_coff_link_hash_entry *) NULL)
+ ret = (struct ppc_coff_link_hash_entry *)
+ bfd_hash_allocate (table,
+ sizeof (struct ppc_coff_link_hash_entry));
+
+ if (ret == (struct ppc_coff_link_hash_entry *) NULL)
+ return NULL;
+
+ /* Call the allocation method of the superclass. */
+ ret = ((struct ppc_coff_link_hash_entry *)
+ _bfd_coff_link_hash_newfunc ((struct bfd_hash_entry *) ret,
+ table, string));
+
+ if (ret)
+ {
+ /* Initialize the local fields. */
+ ret->toc_offset = 1;
+ ret->symbol_is_glue = 0;
+ ret->glue_insn = 0;
+ strcpy(ret->eye_catcher, EYE);
+ }
+
+ return (struct bfd_hash_entry *) ret;
+}
+
+/* Initialize a PE linker hash table. */
+
+static boolean
+ppc_coff_link_hash_table_init (table, abfd, newfunc)
+ struct ppc_coff_link_hash_table *table;
+ bfd *abfd;
+ struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *,
+ struct bfd_hash_table *,
+ const char *));
+{
+ return _bfd_coff_link_hash_table_init (&table->root, abfd, newfunc);
+}
+
+/* Create a PE linker hash table. */
+
+static struct bfd_link_hash_table *
+ppc_coff_link_hash_table_create (abfd)
+ bfd *abfd;
+{
+ struct ppc_coff_link_hash_table *ret;
+
+ ret = ((struct ppc_coff_link_hash_table *)
+ bfd_alloc (abfd, sizeof (struct ppc_coff_link_hash_table)));
+ if (ret == NULL)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return NULL;
+ }
+ if (! ppc_coff_link_hash_table_init (ret, abfd,
+ ppc_coff_link_hash_newfunc))
+ {
+ bfd_release (abfd, ret);
+ return (struct bfd_link_hash_table *) NULL;
+ }
+ return &ret->root.root;
+}
+
+/* Now, tailor coffcode.h to use our hash stuff */
+
+#define coff_bfd_link_hash_table_create ppc_coff_link_hash_table_create
+
+
+/* The nt loader points the toc register to &toc + 32768, in order to */
+/* use the complete range of a 16-bit displacement (I guess). We have */
+/* to adjust for this when we fix up loads displaced off the toc reg. */
+#define TOC_LOAD_ADJUSTMENT (-32768)
+#define TOC_SECTION_NAME ".private.toc"
+
+/* The main body of code is in coffcode.h. */
+
+#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (3)
+
+/* In case we're on a 32-bit machine, construct a 64-bit "-1" value
+ from smaller values. Start with zero, widen, *then* decrement. */
+#define MINUS_ONE (((bfd_vma)0) - 1)
+
+/* these should definitely go in a header file somewhere... */
+
+/* NOP */
+#define IMAGE_REL_PPC_ABSOLUTE 0x0000
+
+/* 64-bit address */
+#define IMAGE_REL_PPC_ADDR64 0x0001
+
+/* 32-bit address */
+#define IMAGE_REL_PPC_ADDR32 0x0002
+
+/* 26-bit address, shifted left 2 (branch absolute) */
+#define IMAGE_REL_PPC_ADDR24 0x0003
+
+/* 16-bit address */
+#define IMAGE_REL_PPC_ADDR16 0x0004
+
+/* 16-bit address, shifted left 2 (load doubleword) */
+#define IMAGE_REL_PPC_ADDR14 0x0005
+
+/* 26-bit PC-relative offset, shifted left 2 (branch relative) */
+#define IMAGE_REL_PPC_REL24 0x0006
+
+/* 16-bit PC-relative offset, shifted left 2 (br cond relative) */
+#define IMAGE_REL_PPC_REL14 0x0007
+
+/* 16-bit offset from TOC base */
+#define IMAGE_REL_PPC_TOCREL16 0x0008
+
+/* 16-bit offset from TOC base, shifted left 2 (load doubleword) */
+#define IMAGE_REL_PPC_TOCREL14 0x0009
+
+/* 32-bit addr w/o image base */
+#define IMAGE_REL_PPC_ADDR32NB 0x000A
+
+/* va of containing section (as in an image sectionhdr) */
+#define IMAGE_REL_PPC_SECREL 0x000B
+
+/* sectionheader number */
+#define IMAGE_REL_PPC_SECTION 0x000C
+
+/* substitute TOC restore instruction iff symbol is glue code */
+#define IMAGE_REL_PPC_IFGLUE 0x000D
+
+/* symbol is glue code; virtual address is TOC restore instruction */
+#define IMAGE_REL_PPC_IMGLUE 0x000E
+
+/* va of containing section (limited to 16 bits) */
+#define IMAGE_REL_PPC_SECREL16 0x000F
+
+/* stuff to handle immediate data when the number of bits in the */
+/* data is greater than the number of bits in the immediate field */
+/* We need to do (usually) 32 bit arithmetic on 16 bit chunks */
+#define IMAGE_REL_PPC_REFHI 0x0010
+#define IMAGE_REL_PPC_REFLO 0x0011
+#define IMAGE_REL_PPC_PAIR 0x0012
+
+
+/* Flag bits in IMAGE_RELOCATION.TYPE */
+
+/* subtract reloc value rather than adding it */
+#define IMAGE_REL_PPC_NEG 0x0100
+
+/* fix branch prediction bit to predict branch taken */
+#define IMAGE_REL_PPC_BRTAKEN 0x0200
+
+/* fix branch prediction bit to predict branch not taken */
+#define IMAGE_REL_PPC_BRNTAKEN 0x0400
+
+/* toc slot defined in file (or, data in toc) */
+#define IMAGE_REL_PPC_TOCDEFN 0x0800
+
+/* masks to isolate above values in IMAGE_RELOCATION.Type */
+#define IMAGE_REL_PPC_TYPEMASK 0x00FF
+#define IMAGE_REL_PPC_FLAGMASK 0x0F00
+
+#define EXTRACT_TYPE(x) ((x) & IMAGE_REL_PPC_TYPEMASK)
+#define EXTRACT_FLAGS(x) ((x) & IMAGE_REL_PPC_FLAGMASK)
+#define EXTRACT_JUNK(x) \
+ ((x) & ~(IMAGE_REL_PPC_TYPEMASK | IMAGE_REL_PPC_FLAGMASK))
+
+
+/* static helper functions to make relocation work */
+/* (Work In Progress) */
+
+static bfd_reloc_status_type ppc_refhi_reloc PARAMS ((bfd *abfd,
+ arelent *reloc,
+ asymbol *symbol,
+ PTR data,
+ asection *section,
+ bfd *output_bfd,
+ char **error));
+static bfd_reloc_status_type ppc_reflo_reloc PARAMS ((bfd *abfd,
+ arelent *reloc,
+ asymbol *symbol,
+ PTR data,
+ asection *section,
+ bfd *output_bfd,
+ char **error));
+static bfd_reloc_status_type ppc_pair_reloc PARAMS ((bfd *abfd,
+ arelent *reloc,
+ asymbol *symbol,
+ PTR data,
+ asection *section,
+ bfd *output_bfd,
+ char **error));
+
+
+static bfd_reloc_status_type ppc_toc16_reloc PARAMS ((bfd *abfd,
+ arelent *reloc,
+ asymbol *symbol,
+ PTR data,
+ asection *section,
+ bfd *output_bfd,
+ char **error));
+
+static bfd_reloc_status_type ppc_addr32nb_reloc PARAMS ((bfd *abfd,
+ arelent *reloc,
+ asymbol *symbol,
+ PTR data,
+ asection *section,
+ bfd *output_bfd,
+ char **error));
+
+static bfd_reloc_status_type ppc_section_reloc PARAMS ((bfd *abfd,
+ arelent *reloc,
+ asymbol *symbol,
+ PTR data,
+ asection *section,
+ bfd *output_bfd,
+ char **error));
+
+static bfd_reloc_status_type ppc_secrel_reloc PARAMS ((bfd *abfd,
+ arelent *reloc,
+ asymbol *symbol,
+ PTR data,
+ asection *section,
+ bfd *output_bfd,
+ char **error));
+
+static bfd_reloc_status_type ppc_imglue_reloc PARAMS ((bfd *abfd,
+ arelent *reloc,
+ asymbol *symbol,
+ PTR data,
+ asection *section,
+ bfd *output_bfd,
+ char **error));
+
+
+
+static boolean in_reloc_p PARAMS((bfd *abfd, reloc_howto_type *howto));
+
+
+/* FIXME: It'll take a while to get through all of these. I only need a few to
+ get us started, so those I'll make sure work. Those marked FIXME are either
+ completely unverified or have a specific unknown marked in the comment */
+
+/*---------------------------------------------------------------------------*/
+/* */
+/* Relocation entries for Windows/NT on PowerPC. */
+/* */
+/* From the document "" we find the following listed as used relocs: */
+/* */
+/* ABSOLUTE : The noop */
+/* ADDR[64|32|16] : fields that hold addresses in data fields or the */
+/* 16 bit displacement field on a load/store. */
+/* ADDR[24|14] : fields that hold addresses in branch and cond */
+/* branches. These represent [26|16] bit addresses. */
+/* The low order 2 bits are preserved. */
+/* REL[24|14] : branches relative to the Instruction Address */
+/* register. These represent [26|16] bit addresses, */
+/* as before. The instruction field will be zero, and */
+/* the address of the SYM will be inserted at link time. */
+/* TOCREL16 : 16 bit displacement field referring to a slot in */
+/* toc. */
+/* TOCREL14 : 16 bit displacement field, similar to REL14 or ADDR14. */
+/* ADDR32NB : 32 bit address relative to the virtual origin. */
+/* (On the alpha, this is always a linker generated thunk)*/
+/* (i.e. 32bit addr relative to the image base) */
+/* SECREL : The value is relative to the start of the section */
+/* containing the symbol. */
+/* SECTION : access to the header containing the item. Supports the */
+/* codeview debugger. */
+/* */
+/* In particular, note that the document does not indicate that the */
+/* relocations listed in the header file are used. */
+/* */
+/* */
+/* */
+/*---------------------------------------------------------------------------*/
+
+static reloc_howto_type ppc_coff_howto_table[] =
+{
+ /* IMAGE_REL_PPC_ABSOLUTE 0x0000 NOP */
+ /* Unused: */
+ HOWTO (IMAGE_REL_PPC_ABSOLUTE, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* dont complain_on_overflow */
+ 0, /* special_function */
+ "ABSOLUTE", /* name */
+ false, /* partial_inplace */
+ 0x00, /* src_mask */
+ 0x00, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* IMAGE_REL_PPC_ADDR64 0x0001 64-bit address */
+ /* Unused: */
+ HOWTO(IMAGE_REL_PPC_ADDR64, /* type */
+ 0, /* rightshift */
+ 3, /* size (0 = byte, 1 = short, 2 = long) */
+ 64, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "ADDR64", /* name */
+ true, /* partial_inplace */
+ MINUS_ONE, /* src_mask */
+ MINUS_ONE, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* IMAGE_REL_PPC_ADDR32 0x0002 32-bit address */
+ /* Used: */
+ HOWTO (IMAGE_REL_PPC_ADDR32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "ADDR32", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* IMAGE_REL_PPC_ADDR24 0x0003 26-bit address, shifted left 2 (branch absolute) */
+ /* the LI field is in bit 6 through bit 29 is 24 bits, + 2 for the shift */
+ /* Of course, That's the IBM approved bit numbering, which is not what */
+ /* anyone else uses.... The li field is in bit 2 thru 25 */
+ /* Used: */
+ HOWTO (IMAGE_REL_PPC_ADDR24, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 26, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "ADDR24", /* name */
+ true, /* partial_inplace */
+ 0x07fffffc, /* src_mask */
+ 0x07fffffc, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* IMAGE_REL_PPC_ADDR16 0x0004 16-bit address */
+ /* Used: */
+ HOWTO (IMAGE_REL_PPC_ADDR16, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "ADDR16", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* IMAGE_REL_PPC_ADDR14 0x0005 */
+ /* 16-bit address, shifted left 2 (load doubleword) */
+ /* FIXME: the mask is likely wrong, and the bit position may be as well */
+ /* Unused: */
+ HOWTO (IMAGE_REL_PPC_ADDR14, /* type */
+ 1, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "ADDR16", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* IMAGE_REL_PPC_REL24 0x0006 */
+ /* 26-bit PC-relative offset, shifted left 2 (branch relative) */
+ /* Used: */
+ HOWTO (IMAGE_REL_PPC_REL24, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 26, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "REL24", /* name */
+ true, /* partial_inplace */
+ 0x3fffffc, /* src_mask */
+ 0x3fffffc, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* IMAGE_REL_PPC_REL14 0x0007 */
+ /* 16-bit PC-relative offset, shifted left 2 (br cond relative) */
+ /* FIXME: the mask is likely wrong, and the bit position may be as well */
+ /* FIXME: how does it know how far to shift? */
+ /* Unused: */
+ HOWTO (IMAGE_REL_PPC_ADDR14, /* type */
+ 1, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "ADDR16", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ /* IMAGE_REL_PPC_TOCREL16 0x0008 */
+ /* 16-bit offset from TOC base */
+ /* Used: */
+ HOWTO (IMAGE_REL_PPC_TOCREL16,/* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc_toc16_reloc, /* special_function */
+ "TOCREL16", /* name */
+ false, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* IMAGE_REL_PPC_TOCREL14 0x0009 */
+ /* 16-bit offset from TOC base, shifted left 2 (load doubleword) */
+ /* Unused: */
+ HOWTO (IMAGE_REL_PPC_TOCREL14,/* type */
+ 1, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "TOCREL14", /* name */
+ false, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* IMAGE_REL_PPC_ADDR32NB 0x000A */
+ /* 32-bit addr w/ image base */
+ /* Unused: */
+ HOWTO (IMAGE_REL_PPC_ADDR32NB,/* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "ADDR32NB", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* IMAGE_REL_PPC_SECREL 0x000B */
+ /* va of containing section (as in an image sectionhdr) */
+ /* Unused: */
+ HOWTO (IMAGE_REL_PPC_SECREL,/* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ ppc_secrel_reloc, /* special_function */
+ "SECREL", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ /* IMAGE_REL_PPC_SECTION 0x000C */
+ /* sectionheader number */
+ /* Unused: */
+ HOWTO (IMAGE_REL_PPC_SECTION,/* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ ppc_section_reloc, /* special_function */
+ "SECTION", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ /* IMAGE_REL_PPC_IFGLUE 0x000D */
+ /* substitute TOC restore instruction iff symbol is glue code */
+ /* Used: */
+ HOWTO (IMAGE_REL_PPC_IFGLUE,/* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "IFGLUE", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* IMAGE_REL_PPC_IMGLUE 0x000E */
+ /* symbol is glue code; virtual address is TOC restore instruction */
+ /* Unused: */
+ HOWTO (IMAGE_REL_PPC_IMGLUE,/* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc_imglue_reloc, /* special_function */
+ "IMGLUE", /* name */
+ false, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* IMAGE_REL_PPC_SECREL16 0x000F */
+ /* va of containing section (limited to 16 bits) */
+ /* Unused: */
+ HOWTO (IMAGE_REL_PPC_SECREL16,/* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "SECREL16", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ /* IMAGE_REL_PPC_REFHI 0x0010 */
+ /* Unused: */
+ HOWTO (IMAGE_REL_PPC_REFHI, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ ppc_refhi_reloc, /* special_function */
+ "REFHI", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* IMAGE_REL_PPC_REFLO 0x0011 */
+ /* Unused: */
+ HOWTO (IMAGE_REL_PPC_REFLO, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ ppc_refhi_reloc, /* special_function */
+ "REFLO", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* IMAGE_REL_PPC_PAIR 0x0012 */
+ /* Unused: */
+ HOWTO (IMAGE_REL_PPC_PAIR, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ ppc_pair_reloc, /* special_function */
+ "PAIR", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false) /* pcrel_offset */
+};
+
+
+
+
+/* Some really cheezy macros that can be turned on to test stderr :-) */
+
+#ifdef DEBUG_RELOC
+#define UN_IMPL(x) \
+{ \
+ static int i; \
+ if (i == 0) \
+ { \
+ i = 1; \
+ fprintf(stderr,"Unimplemented Relocation -- %s\n",x); \
+ } \
+}
+
+#define DUMP_RELOC(n,r) \
+{ \
+ fprintf(stderr,"%s sym %d, addr %d, addend %d\n", \
+ n, (*(r->sym_ptr_ptr))->name, \
+ r->address, r->addend); \
+}
+
+/* Given a reloc name, n, and a pointer to an internal_reloc,
+ dump out interesting information on the contents
+
+#define n_name _n._n_name
+#define n_zeroes _n._n_n._n_zeroes
+#define n_offset _n._n_n._n_offset
+
+*/
+
+#define DUMP_RELOC2(n,r) \
+{ \
+ fprintf(stderr,"%s sym %d, r_vaddr %d\n", \
+ n, r->r_symndx, r->r_vaddr); \
+}
+
+#else
+#define UN_IMPL(x)
+#define DUMP_RELOC(n,r)
+#define DUMP_RELOC2(n,r)
+#endif
+
+
+
+/* toc construction and management routines */
+extern bfd* bfd_of_toc_owner;
+extern long int global_toc_size;
+
+extern long int import_table_size;
+extern long int first_thunk_address;
+extern long int thunk_size;
+
+enum toc_type
+{
+ default_toc,
+ toc_32,
+ toc_64
+};
+
+struct list_ele
+{
+ struct list_ele *next;
+ bfd_vma addr;
+ int offset;
+ const char *name;
+};
+
+extern struct list_ele *head;
+extern struct list_ele *tail;
+
+static void
+record_toc(toc_section, our_toc_offset, name)
+ asection *toc_section;
+ int our_toc_offset;
+ const char *name;
+{
+ /* add this entry to our toc addr-offset-name list */
+ struct list_ele *t;
+ t = malloc(sizeof(struct list_ele));
+ t->next = 0;
+ t->offset = our_toc_offset;
+ t->name = name;
+ t->addr = toc_section->output_offset + our_toc_offset;
+
+ if (head == 0)
+ {
+ head = t;
+ tail = t;
+ }
+ else
+ {
+ tail->next = t;
+ tail = t;
+ }
+}
+
+/* record a toc offset against a symbol */
+static int
+ppc_record_toc_entry(abfd, info, sec, sym, toc_kind)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ asection *sec;
+ int sym;
+ enum toc_type toc_kind;
+{
+ bfd_byte *t;
+ bfd_byte *old_contents;
+ asection *s;
+ int element_size;
+ int data;
+ int offset;
+ struct ppc_coff_link_hash_entry *h;
+ struct coff_symbol_struct *target;
+ int ret_val;
+ const char *name;
+
+ int *local_syms;
+
+ h = 0;
+
+ h = (struct ppc_coff_link_hash_entry *) (obj_coff_sym_hashes (abfd)[sym]);
+ if (h != 0)
+ {
+ CHECK_EYE(h->eye_catcher);
+ }
+
+ if (h == 0)
+ {
+ local_syms = obj_coff_local_toc_table(abfd);
+ if (local_syms == 0)
+ {
+ int i;
+ /* allocate a table */
+ local_syms =
+ (int *) bfd_zalloc (abfd,
+ obj_raw_syment_count(abfd) * sizeof(int));
+ if (local_syms == 0)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return false;
+ }
+ obj_coff_local_toc_table(abfd) = local_syms;
+ for (i = 0; i < obj_raw_syment_count(abfd); ++i)
+ local_syms[i] = 1;
+ }
+
+ if (local_syms[sym] == 1)
+ {
+ local_syms[sym] = global_toc_size;
+ ret_val = global_toc_size;
+ global_toc_size += 4;
+#ifdef TOC_DEBUG
+ fprintf(stderr,
+ "Setting toc_offset for local sym %d to %d\n",
+ sym, ret_val);
+#endif
+ }
+ else
+ {
+ ret_val = local_syms[sym];
+#ifdef TOC_DEBUG
+ fprintf(stderr,
+ "toc_offset already set for local sym %d to %d\n",
+ sym, ret_val);
+#endif
+ }
+ }
+ else
+ {
+ name = h->root.root.root.string;
+
+ /* check to see if there's a toc slot allocated. If not, do it
+ here. It will be used in relocate_section */
+ if (h->toc_offset == 1)
+ {
+ h->toc_offset = global_toc_size;
+ ret_val = global_toc_size;
+ global_toc_size += 4;
+#ifdef TOC_DEBUG
+ fprintf(stderr,
+ "Setting toc_offset for sym %d (%s) [h=%p] to %d\n",
+ sym, name, h, ret_val);
+#endif
+ }
+ else
+ {
+ ret_val = h->toc_offset;
+#ifdef TOC_DEBUG
+ fprintf(stderr,
+ "toc_offset already set for sym %d (%s) [h=%p] to %d\n",
+ sym, name, h, ret_val);
+#endif
+ }
+ }
+
+ return ret_val;
+}
+
+/* record a toc offset against a symbol */
+static void
+ppc_mark_symbol_as_glue(abfd, sym, rel)
+ bfd *abfd;
+ int sym;
+ struct internal_reloc *rel;
+{
+ struct ppc_coff_link_hash_entry *h;
+
+ h = (struct ppc_coff_link_hash_entry *) (obj_coff_sym_hashes (abfd)[sym]);
+
+ CHECK_EYE(h->eye_catcher);
+
+ h->symbol_is_glue = 1;
+ h->glue_insn = bfd_get_32 (abfd, (bfd_byte *) &rel->r_vaddr);
+
+ return;
+}
+
+
+/* Provided the symbol, returns the value reffed */
+static long get_symbol_value PARAMS ((asymbol *));
+
+static long
+get_symbol_value (symbol)
+ asymbol *symbol;
+{
+ long relocation = 0;
+
+ if (bfd_is_com_section (symbol->section))
+ {
+ relocation = 0;
+ }
+ else
+ {
+ relocation = symbol->value +
+ symbol->section->output_section->vma +
+ symbol->section->output_offset;
+ }
+
+ return(relocation);
+}
+
+/* Return true if this relocation should
+ appear in the output .reloc section. */
+
+static boolean in_reloc_p(abfd, howto)
+ bfd * abfd;
+ reloc_howto_type *howto;
+{
+ return
+ (! howto->pc_relative)
+ && (howto->type != IMAGE_REL_PPC_TOCREL16)
+ && (howto->type != IMAGE_REL_PPC_IMGLUE);
+}
+
+/* this function is in charge of performing all the ppc PE relocations */
+/* Don't yet know if we want to do this this particular way ... (krk) */
+/* FIXME: (it is not yet enabled) */
+
+static bfd_reloc_status_type
+pe_ppc_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol_in;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ /* the consth relocation comes in two parts, we have to remember
+ the state between calls, in these variables */
+ static boolean part1_consth_active = false;
+ static unsigned long part1_consth_value;
+
+ unsigned long insn;
+ unsigned long sym_value;
+ unsigned long unsigned_value;
+ unsigned short r_type;
+ long signed_value;
+
+ unsigned long addr = reloc_entry->address ; /*+ input_section->vma*/
+ bfd_byte *hit_data =addr + (bfd_byte *)(data);
+
+ fprintf(stderr, "pe_ppc_reloc (%s)\n", TARGET_LITTLE_NAME);
+
+ r_type = reloc_entry->howto->type;
+
+ if (output_bfd)
+ {
+ /* Partial linking - do nothing */
+ reloc_entry->address += input_section->output_offset;
+ return bfd_reloc_ok;
+ }
+
+ if (symbol_in != NULL
+ && bfd_is_und_section (symbol_in->section))
+ {
+ /* Keep the state machine happy in case we're called again */
+ if (r_type == IMAGE_REL_PPC_REFHI)
+ {
+ part1_consth_active = true;
+ part1_consth_value = 0;
+ }
+ return(bfd_reloc_undefined);
+ }
+
+ if ((part1_consth_active) && (r_type != IMAGE_REL_PPC_PAIR))
+ {
+ part1_consth_active = false;
+ *error_message = (char *) "Missing PAIR";
+ return(bfd_reloc_dangerous);
+ }
+
+
+ sym_value = get_symbol_value(symbol_in);
+
+ return(bfd_reloc_ok);
+}
+
+/* The reloc processing routine for the optimized COFF linker. */
+
+static boolean
+coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
+ contents, relocs, syms, sections)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+ bfd *input_bfd;
+ asection *input_section;
+ bfd_byte *contents;
+ struct internal_reloc *relocs;
+ struct internal_syment *syms;
+ asection **sections;
+{
+ struct internal_reloc *rel;
+ struct internal_reloc *relend;
+ boolean hihalf;
+ bfd_vma hihalf_val;
+ asection *toc_section = 0;
+ bfd_vma relocation;
+ reloc_howto_type *howto = 0;
+
+#ifdef DEBUG_RELOC
+ fprintf(stderr,
+ "pe_ppc_relocate_section (%s) for %s \n",
+ TARGET_LITTLE_NAME,
+ input_section->name);
+
+#endif
+
+ /* If we are performing a relocateable link, we don't need to do a
+ thing. The caller will take care of adjusting the reloc
+ addresses and symbol indices. */
+ if (info->relocateable)
+ return true;
+
+ hihalf = false;
+ hihalf_val = 0;
+
+ rel = relocs;
+ relend = rel + input_section->reloc_count;
+ for (; rel < relend; rel++)
+ {
+ long symndx;
+ struct ppc_coff_link_hash_entry *h;
+ struct internal_syment *sym;
+ bfd_vma val;
+
+ asection *sec;
+ bfd_reloc_status_type rstat;
+ bfd_byte *loc;
+
+ unsigned short r_type = EXTRACT_TYPE (rel->r_type);
+ unsigned short r_flags = EXTRACT_FLAGS(rel->r_type);
+ unsigned short junk = EXTRACT_JUNK (rel->r_type);
+
+#ifdef DEBUG_RELOC
+ /* now examine flags */
+ if (r_flags != 0)
+ {
+ fprintf (stderr, "Reloc with flags found!");
+ if ( r_flags & IMAGE_REL_PPC_NEG )
+ fprintf (stderr, " NEG");
+ if ( r_flags & IMAGE_REL_PPC_BRTAKEN )
+ fprintf (stderr, " BRTAKEN");
+ if ( r_flags & IMAGE_REL_PPC_BRNTAKEN )
+ fprintf (stderr, " BRNTAKEN");
+ if ( r_flags & IMAGE_REL_PPC_TOCDEFN )
+ fprintf (stderr, " TOCDEFN");
+ fprintf(stderr, "\n");
+ }
+#endif
+
+ symndx = rel->r_symndx;
+ loc = contents + rel->r_vaddr - input_section->vma;
+
+ /* FIXME: check bounds on r_type */
+ howto = ppc_coff_howto_table + r_type;
+
+ if (symndx == -1)
+ {
+ h = NULL;
+ sym = NULL;
+ }
+ else
+ {
+ h = (struct ppc_coff_link_hash_entry *)
+ (obj_coff_sym_hashes (input_bfd)[symndx]);
+ if (h != 0)
+ {
+ CHECK_EYE(h->eye_catcher);
+ }
+
+ sym = syms + symndx;
+ }
+
+ sec = NULL;
+ val = 0;
+
+ /* FIXME: PAIR unsupported in the following code */
+ if (h == NULL)
+ {
+ if (symndx == -1)
+ sec = bfd_abs_section_ptr;
+ else
+ {
+ sec = sections[symndx];
+ val = (sec->output_section->vma
+ + sec->output_offset
+ + sym->n_value
+ - sec->vma);
+ }
+ }
+ else
+ {
+ CHECK_EYE(h->eye_catcher);
+
+ if (h->root.root.type == bfd_link_hash_defined
+ || h->root.root.type == bfd_link_hash_defweak)
+ {
+ sec = h->root.root.u.def.section;
+ val = (h->root.root.u.def.value
+ + sec->output_section->vma
+ + sec->output_offset);
+ }
+ else
+ {
+ if (! ((*info->callbacks->undefined_symbol)
+ (info, h->root.root.root.string, input_bfd, input_section,
+ rel->r_vaddr - input_section->vma)))
+ return false;
+ }
+ }
+
+ rstat = bfd_reloc_ok;
+
+ /* Each case must do its own relocation, setting rstat appropriately */
+ switch (r_type)
+ {
+ default:
+ fprintf( stderr,
+ "ERROR: during reloc processing -- unsupported reloc %s\n",
+ howto->name);
+ bfd_set_error (bfd_error_bad_value);
+ abort();
+ return false;
+ case IMAGE_REL_PPC_TOCREL16:
+ {
+ bfd_vma our_toc_offset;
+ int fixit;
+
+ DUMP_RELOC2(howto->name, rel);
+
+ if (toc_section == 0)
+ {
+ toc_section = bfd_get_section_by_name (bfd_of_toc_owner,
+ TOC_SECTION_NAME);
+#ifdef TOC_DEBUG
+
+ fprintf(stderr,
+ "BFD of toc owner %p, section addr of %s %p\n",
+ bfd_of_toc_owner, TOC_SECTION_NAME, toc_section);
+#endif
+
+ if ( toc_section == NULL )
+ {
+ fprintf(stderr, "No Toc section!\n");
+ abort();
+ }
+ }
+
+#if 0
+ if ( r_flags & IMAGE_REL_PPC_TOCDEFN )
+ {
+ /* Somehow, we are to assume that the toc has already been
+ done for this one, and the offset is the value of
+ the symbol? */
+ fprintf(stderr,
+ "Symbol value %d\n", val);
+ }
+#endif
+
+ /*
+ * Amazing bit tricks present. As we may have seen earlier, we
+ * use the 1 bit to tell us whether or not a toc offset has been
+ * allocated. Now that they've all been allocated, we will use
+ * the 1 bit to tell us if we've written this particular toc
+ * entry out.
+ */
+ fixit = false;
+ if (h == 0)
+ { /* it is a file local symbol */
+ int *local_toc_table;
+ const char *name;
+
+ sym = syms + symndx;
+ name = sym->_n._n_name;
+
+ local_toc_table = obj_coff_local_toc_table(input_bfd);
+ our_toc_offset = local_toc_table[symndx];
+
+ if ((our_toc_offset & 1) != 0)
+ {
+ /* if it has been written out, it is marked with the
+ 1 bit. Fix up our offset, but do not write it out
+ again.
+ */
+ our_toc_offset &= ~1;
+#ifdef TOC_DEBUG
+
+ fprintf(stderr,
+ "Not writing out toc_offset of %d for %s\n", our_toc_offset, name);
+#endif
+ }
+ else
+ {
+ /* write out the toc entry */
+ record_toc(toc_section, our_toc_offset, strdup(name));
+#ifdef TOC_DEBUG
+ fprintf(stderr,
+ "Writing out toc_offset toc_section (%p,%p)+%d val %d for %s\n",
+ toc_section,
+ toc_section->contents,
+ our_toc_offset,
+ val,
+ name);
+#endif
+
+ bfd_put_32(output_bfd,
+ val,
+ toc_section->contents + our_toc_offset);
+
+ local_toc_table[symndx] |= 1;
+ fixit = true;
+ }
+ }
+ else
+ {
+ const char *name = h->root.root.root.string;
+ our_toc_offset = h->toc_offset;
+
+ if ((our_toc_offset & 1) != 0)
+ {
+ /* if it has been written out, it is marked with the
+ 1 bit. Fix up our offset, but do not write it out
+ again.
+ */
+ our_toc_offset &= ~1;
+#ifdef TOC_DEBUG
+ fprintf(stderr,
+ "Not writing out toc_offset of %d for %s\n", our_toc_offset, name);
+#endif
+ }
+ else
+ {
+ record_toc(toc_section, our_toc_offset, strdup(name));
+
+#ifdef TOC_DEBUG
+ /* write out the toc entry */
+ fprintf(stderr,
+ "Writing out toc_offset toc_section (%p,%p)+%d val %d for %s\n",
+ toc_section,
+ toc_section->contents,
+ our_toc_offset,
+ val,
+ name);
+#endif
+
+ /* write out the toc entry */
+ bfd_put_32(output_bfd,
+ val,
+ toc_section->contents + our_toc_offset);
+
+ h->toc_offset |= 1;
+ /* The tricky part is that this is the address that */
+ /* needs a .reloc entry for it */
+ fixit = true;
+ }
+ }
+
+ if (fixit && info->base_file)
+ {
+ /* So if this is non pcrelative, and is referenced
+ to a section or a common symbol, then it needs a reloc */
+
+ /* relocation to a symbol in a section which
+ isn't absolute - we output the address here
+ to a file */
+
+ bfd_vma addr = toc_section->output_section->vma
+ + toc_section->output_offset + our_toc_offset;
+
+ fprintf(stderr,
+ " Toc Section reloc candidate\n");
+
+ if (coff_data(output_bfd)->pe)
+ addr -= pe_data(output_bfd)->pe_opthdr.ImageBase;
+ fwrite (&addr, 1,4, (FILE *) info->base_file);
+ }
+
+
+ /* FIXME: this test is conservative */
+ if (our_toc_offset > toc_section->_raw_size)
+ {
+ fprintf(stderr,
+ "reloc offset is bigger than the toc size!\n");
+ abort();
+ }
+
+ /* Now we know the relocation for this toc reference */
+ relocation = our_toc_offset + TOC_LOAD_ADJUSTMENT;
+ rstat = _bfd_relocate_contents (howto,
+ input_bfd,
+ relocation,
+ loc);
+ }
+ break;
+ case IMAGE_REL_PPC_IFGLUE:
+ {
+ /* To solve this, we need to know whether or not the symbol */
+ /* appearing on the call instruction is a glue function or not. */
+ /* A glue function must announce itself via a IMGLUE reloc, and */
+ /* the reloc contains the required toc restore instruction */
+
+ bfd_vma x;
+ const char *my_name;
+ DUMP_RELOC2(howto->name, rel);
+
+ if (h != 0)
+ {
+ my_name = h->root.root.root.string;
+ if (h->symbol_is_glue == 1)
+ {
+ x = bfd_get_32(input_bfd, loc);
+ bfd_put_32(input_bfd, h->glue_insn, loc);
+ }
+ }
+ }
+ break;
+ case IMAGE_REL_PPC_SECREL:
+ /* Unimplemented: codeview debugging information */
+ /* For fast access to the header of the section
+ containing the item. */
+ break;
+ case IMAGE_REL_PPC_SECTION:
+ /* Unimplemented: codeview debugging information */
+ /* Is used to indicate that the value should be relative
+ to the beginning of the section that contains the
+ symbol */
+ break;
+ case IMAGE_REL_PPC_ABSOLUTE:
+ {
+ const char *my_name;
+ if (h == 0)
+ my_name = (syms+symndx)->_n._n_name;
+ else
+ {
+ my_name = h->root.root.root.string;
+ }
+
+ fprintf(stderr,
+ "Warning: unsupported reloc %s <file %s, section %s>\n",
+ howto->name,
+ bfd_get_filename(input_bfd),
+ input_section->name);
+
+ fprintf(stderr,"sym %d (%s), r_vaddr %d (%x)\n",
+ rel->r_symndx, my_name, rel->r_vaddr, rel->r_vaddr);
+ }
+ break;
+ case IMAGE_REL_PPC_IMGLUE:
+ {
+ /* There is nothing to do now. This reloc was noted in the first
+ pass over the relocs, and the glue instruction extracted */
+ const char *my_name;
+ if (h->symbol_is_glue == 1)
+ break;
+ my_name = h->root.root.root.string;
+ fprintf(stderr,
+ "Warning: previously missed IMGLUE reloc %s <file %s, section %s>\n",
+ howto->name,
+ bfd_get_filename(input_bfd),
+ input_section->name);
+ break;
+
+ }
+ break;
+
+ case IMAGE_REL_PPC_ADDR32NB:
+ {
+ struct coff_link_hash_entry *myh = 0;
+ const char *name = 0;
+ DUMP_RELOC2(howto->name, rel);
+ if (h == 0)
+ { /* it is a file local symbol */
+ sym = syms + symndx;
+ name = sym->_n._n_name;
+ }
+ else
+ {
+ char *target = 0;
+
+ name = h->root.root.root.string;
+ if (strcmp(".idata$2", name) == 0)
+ target = "__idata2_magic__";
+ else if (strcmp(".idata$4", name) == 0)
+ target = "__idata4_magic__";
+ else if (strcmp(".idata$5", name) == 0)
+ target = "__idata5_magic__";
+ else
+ abort();
+
+ myh = 0;
+
+ myh = coff_link_hash_lookup (coff_hash_table (info),
+ target,
+ false, false, true);
+ if (myh == 0)
+ {
+ fprintf(stderr, "Missing idata magic cookies, this cannot work anyway...\n");
+ abort();
+ }
+
+ val = myh->root.u.def.value +
+ sec->output_section->vma + sec->output_offset;
+ if (first_thunk_address == 0)
+ {
+ int idata5offset;
+ myh = coff_link_hash_lookup (coff_hash_table (info),
+ "__idata5_magic__",
+ false, false, true);
+ first_thunk_address = myh->root.u.def.value +
+ sec->output_section->vma +
+ sec->output_offset -
+ pe_data(output_bfd)->pe_opthdr.ImageBase;
+
+ idata5offset = myh->root.u.def.value;
+ myh = coff_link_hash_lookup (coff_hash_table (info),
+ "__idata6_magic__",
+ false, false, true);
+
+ thunk_size = myh->root.u.def.value - idata5offset;
+ myh = coff_link_hash_lookup (coff_hash_table (info),
+ "__idata4_magic__",
+ false, false, true);
+ import_table_size = myh->root.u.def.value;
+ }
+ }
+
+ rstat = _bfd_relocate_contents (howto,
+ input_bfd,
+ val -
+ pe_data(output_bfd)->pe_opthdr.ImageBase,
+ loc);
+ }
+ break;
+
+ case IMAGE_REL_PPC_ADDR16:
+ case IMAGE_REL_PPC_REL24:
+ case IMAGE_REL_PPC_ADDR24:
+ case IMAGE_REL_PPC_ADDR32:
+ DUMP_RELOC2(howto->name, rel);
+ rstat = _bfd_relocate_contents (howto,
+ input_bfd,
+ val,
+ loc);
+ break;
+ }
+
+ if ( info->base_file )
+ {
+ /* So if this is non pcrelative, and is referenced
+ to a section or a common symbol, then it needs a reloc */
+ if (sym && pe_data(output_bfd)->in_reloc_p(output_bfd, howto))
+ {
+ /* relocation to a symbol in a section which
+ isn't absolute - we output the address here
+ to a file */
+ bfd_vma addr = rel->r_vaddr
+ - input_section->vma
+ + input_section->output_offset
+ + input_section->output_section->vma;
+
+ if (coff_data(output_bfd)->pe)
+ {
+ addr -= pe_data(output_bfd)->pe_opthdr.ImageBase;
+ fprintf(stderr,
+ " adjusted down to %d", addr);
+ }
+ fprintf(stderr, "\n");
+
+ fwrite (&addr, 1,4, (FILE *) info->base_file);
+ }
+ }
+
+ switch (rstat)
+ {
+ default:
+ abort ();
+ case bfd_reloc_ok:
+ break;
+ case bfd_reloc_overflow:
+ {
+ const char *name;
+ char buf[SYMNMLEN + 1];
+
+ if (symndx == -1)
+ name = "*ABS*";
+ else if (h != NULL)
+ name = h->root.root.root.string;
+ else if (sym == NULL)
+ name = "*unknown*";
+ else if (sym->_n._n_n._n_zeroes == 0
+ && sym->_n._n_n._n_offset != 0)
+ name = obj_coff_strings (input_bfd) + sym->_n._n_n._n_offset;
+ else
+ {
+ strncpy (buf, sym->_n._n_name, SYMNMLEN);
+ buf[SYMNMLEN] = '\0';
+ name = buf;
+ }
+#if 0
+ else
+ {
+ name = _bfd_coff_internal_syment_name (input_bfd, sym, buf);
+ if (name == NULL)
+ return false;
+ }
+#endif
+
+ if (! ((*info->callbacks->reloc_overflow)
+ (info, name, howto->name,
+ (bfd_vma) 0, input_bfd,
+ input_section, rel->r_vaddr - input_section->vma)))
+ return false;
+ }
+ }
+
+ }
+
+ return true;
+}
+
+#ifdef COFF_IMAGE_WITH_PE
+
+long int global_toc_size = 0;
+
+bfd* bfd_of_toc_owner = 0;
+
+long int import_table_size;
+long int first_thunk_address;
+long int thunk_size;
+
+struct list_ele *head;
+struct list_ele *tail;
+
+void
+dump_toc(vfile)
+ void *vfile;
+{
+ FILE *file = vfile;
+ struct list_ele *t;
+
+ fprintf(file,
+ " Offset Offset Name if present\n");
+
+ for(t = head; t != 0; t=t->next)
+ {
+ fprintf(file,
+ " %2x %04lx %s\n",
+ t->offset - 32768, t->offset, t->name);
+ }
+}
+
+boolean
+ppc_allocate_toc_section (info)
+ struct bfd_link_info *info;
+{
+ asection *s;
+ bfd_byte *foo;
+ static char test_char = '1';
+
+#ifdef DEBUG_TOC
+ fprintf(stderr,
+ "ppc_allocate_toc_section: allocating %s section of size %d\n",
+ TOC_SECTION_NAME, global_toc_size);
+#endif
+
+ if ( global_toc_size == 0 ) /* FIXME: does this get me in trouble? */
+ return true;
+
+ if (bfd_of_toc_owner == 0)
+ {
+ fprintf(stderr,
+ "There is no bfd that owns the toc section!\n");
+ abort();
+ }
+
+ s = bfd_get_section_by_name ( bfd_of_toc_owner , TOC_SECTION_NAME);
+ if (s == NULL)
+ {
+ fprintf(stderr, "No Toc section!\n");
+ abort();
+ }
+
+ foo = bfd_alloc(bfd_of_toc_owner, global_toc_size);
+ memset(foo, test_char, global_toc_size);
+
+ s->_raw_size = s->_cooked_size = global_toc_size;
+ s->contents = foo;
+
+ return true;
+}
+
+boolean
+ppc_process_before_allocation (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ asection *sec;
+ struct internal_reloc *i, *rel;
+
+#if 0
+ fprintf(stderr,
+ "ppc_process_before_allocation: BFD %s\n",
+ bfd_get_filename(abfd));
+#endif
+
+ /* here we have a bfd that is to be included on the link. We have a hook
+ to do reloc rummaging, before section sizes are nailed down. */
+
+ _bfd_coff_get_external_symbols(abfd);
+
+ /* rummage around all the relocs and map the toc */
+ sec = abfd->sections;
+
+ if (sec == 0)
+ {
+ return true;
+ }
+
+ for (; sec != 0; sec = sec->next)
+ {
+ int toc_offset;
+#ifdef DEBUG_RELOC
+ fprintf(stderr,
+ " section %s reloc count %d\n",
+ sec->name,
+ sec->reloc_count);
+#endif
+
+ if (sec->reloc_count == 0)
+ continue;
+
+ /* load the relocs */
+ /* FIXME: there may be a storage leak here */
+ i=_bfd_coff_read_internal_relocs(abfd,sec,1,0,0,0);
+
+ if (i == 0)
+ abort();
+
+ for (rel=i;rel<i+sec->reloc_count;++rel)
+ {
+ unsigned short r_type = EXTRACT_TYPE (rel->r_type);
+ unsigned short r_flags = EXTRACT_FLAGS(rel->r_type);
+ unsigned short junk = EXTRACT_JUNK (rel->r_type);
+
+#ifdef DEBUG_RELOC
+ /* now examine flags */
+ if (r_flags != 0)
+ {
+ fprintf (stderr, "Reloc with flags found!");
+ if ( r_flags & IMAGE_REL_PPC_NEG )
+ fprintf (stderr, " NEG");
+ if ( r_flags & IMAGE_REL_PPC_BRTAKEN )
+ fprintf (stderr, " BRTAKEN");
+ if ( r_flags & IMAGE_REL_PPC_BRNTAKEN )
+ fprintf (stderr, " BRNTAKEN");
+ if ( r_flags & IMAGE_REL_PPC_TOCDEFN )
+ fprintf (stderr, " TOCDEFN");
+ fprintf(stderr, "\n");
+ }
+#endif
+
+ DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel);
+
+ switch(r_type)
+ {
+ case IMAGE_REL_PPC_TOCREL16:
+ toc_offset = ppc_record_toc_entry(abfd, info, sec,
+ rel->r_symndx, default_toc);
+ break;
+ case IMAGE_REL_PPC_IMGLUE:
+ ppc_mark_symbol_as_glue(abfd, rel->r_symndx, rel);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
+
+#endif
+
+
+static bfd_reloc_status_type
+ppc_refhi_reloc (abfd,
+ reloc_entry,
+ symbol,
+ data,
+ input_section,
+ output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ UN_IMPL("REFHI");
+ DUMP_RELOC("REFHI",reloc_entry);
+
+ if (output_bfd == (bfd *) NULL)
+ return bfd_reloc_continue;
+
+ return bfd_reloc_undefined;
+}
+
+static bfd_reloc_status_type
+ppc_reflo_reloc (abfd,
+ reloc_entry,
+ symbol,
+ data,
+ input_section,
+ output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ UN_IMPL("REFLO");
+ DUMP_RELOC("REFLO",reloc_entry);
+
+ if (output_bfd == (bfd *) NULL)
+ return bfd_reloc_continue;
+
+ return bfd_reloc_undefined;
+}
+
+static bfd_reloc_status_type
+ppc_pair_reloc (abfd,
+ reloc_entry,
+ symbol,
+ data,
+ input_section,
+ output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ UN_IMPL("PAIR");
+ DUMP_RELOC("PAIR",reloc_entry);
+
+ if (output_bfd == (bfd *) NULL)
+ return bfd_reloc_continue;
+
+ return bfd_reloc_undefined;
+}
+
+
+static bfd_reloc_status_type
+ppc_toc16_reloc (abfd,
+ reloc_entry,
+ symbol,
+ data,
+ input_section,
+ output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ UN_IMPL("TOCREL16");
+ DUMP_RELOC("TOCREL16",reloc_entry);
+
+ if (output_bfd == (bfd *) NULL)
+ {
+ return bfd_reloc_continue;
+ }
+
+ return bfd_reloc_ok;
+}
+
+/* ADDR32NB : 32 bit address relative to the virtual origin. */
+/* (On the alpha, this is always a linker generated thunk)*/
+/* (i.e. 32bit addr relative to the image base) */
+/* */
+/* */
+
+static bfd_reloc_status_type
+ppc_addr32nb_reloc (abfd,
+ reloc_entry,
+ symbol,
+ data,
+ input_section,
+ output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ UN_IMPL("ADDR32NB");
+ DUMP_RELOC("ADDR32NB",reloc_entry);
+
+ return bfd_reloc_ok;
+}
+
+static bfd_reloc_status_type
+ppc_secrel_reloc (abfd,
+ reloc_entry,
+ symbol,
+ data,
+ input_section,
+ output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ UN_IMPL("SECREL");
+ DUMP_RELOC("SECREL",reloc_entry);
+
+ if (output_bfd == (bfd *) NULL)
+ return bfd_reloc_continue;
+
+ return bfd_reloc_ok;
+}
+
+static bfd_reloc_status_type
+ppc_section_reloc (abfd,
+ reloc_entry,
+ symbol,
+ data,
+ input_section,
+ output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ UN_IMPL("SECTION");
+ DUMP_RELOC("SECTION",reloc_entry);
+
+ if (output_bfd == (bfd *) NULL)
+ return bfd_reloc_continue;
+
+ return bfd_reloc_ok;
+}
+
+static bfd_reloc_status_type
+ppc_imglue_reloc (abfd,
+ reloc_entry,
+ symbol,
+ data,
+ input_section,
+ output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ UN_IMPL("IMGLUE");
+ DUMP_RELOC("IMGLUE",reloc_entry);
+
+ if (output_bfd == (bfd *) NULL)
+ return bfd_reloc_continue;
+
+ return bfd_reloc_ok;
+}
+
+
+
+#define MAX_RELOC_INDEX \
+ (sizeof(ppc_coff_howto_table) / sizeof(ppc_coff_howto_table[0]) - 1)
+
+
+/* FIXME: There is a possiblity that when we read in a reloc from a file,
+ that there are some bits encoded in the upper portion of the
+ type field. Not yet implemented.
+*/
+static void ppc_coff_rtype2howto PARAMS ((arelent *relent,
+ struct internal_reloc *internal));
+
+static void
+ppc_coff_rtype2howto (relent, internal)
+ arelent *relent;
+ struct internal_reloc *internal;
+{
+
+ /* We can encode one of three things in the type field, aside from the
+ type:
+ 1. IMAGE_REL_PPC_NEG - indicates the value field is a subtraction
+ value, rather than an addition value
+ 2. IMAGE_REL_PPC_BRTAKEN, IMAGE_REL_PPC_BRNTAKEN - indicates that
+ the branch is expected to be taken or not.
+ 3. IMAGE_REL_PPC_TOCDEFN - toc slot definition in the file
+ For now, we just strip this stuff to find the type, and ignore it other
+ than that.
+ */
+
+ unsigned short r_type = EXTRACT_TYPE (internal->r_type);
+ unsigned short r_flags = EXTRACT_FLAGS(internal->r_type);
+ unsigned short junk = EXTRACT_JUNK (internal->r_type);
+
+ /* the masking process only slices off the bottom byte for r_type. */
+ if ( r_type > MAX_RELOC_INDEX )
+ {
+ fprintf(stderr,
+ "ppc_coff_rtype2howto: reloc index %d out of range [%d, %d]\n",
+ internal->r_type, 0, MAX_RELOC_INDEX);
+ abort();
+ }
+
+ /* check for absolute crap */
+ if ( junk != 0 )
+ {
+ fprintf(stderr,
+ "ppc_coff_rtype2howto: reloc index %d contains junk %d\n",
+ internal->r_type, junk);
+ abort();
+ }
+
+#ifdef DEBUG_RELOC
+ /* now examine flags */
+ if (r_flags != 0)
+ {
+ fprintf (stderr, "Reloc with flags found!");
+ if ( r_flags & IMAGE_REL_PPC_NEG )
+ fprintf (stderr, " NEG");
+ if ( r_flags & IMAGE_REL_PPC_BRTAKEN )
+ fprintf (stderr, " BRTAKEN");
+ if ( r_flags & IMAGE_REL_PPC_BRNTAKEN )
+ fprintf (stderr, " BRNTAKEN");
+ if ( r_flags & IMAGE_REL_PPC_TOCDEFN )
+ fprintf (stderr, " TOCDEFN");
+ fprintf(stderr, "\n");
+ }
+#endif
+
+ switch(r_type)
+ {
+ case IMAGE_REL_PPC_ADDR16:
+ case IMAGE_REL_PPC_REL24:
+ case IMAGE_REL_PPC_ADDR24:
+ case IMAGE_REL_PPC_TOCREL16:
+ case IMAGE_REL_PPC_ADDR32:
+ case IMAGE_REL_PPC_IFGLUE:
+ case IMAGE_REL_PPC_ADDR32NB:
+ case IMAGE_REL_PPC_SECTION:
+ case IMAGE_REL_PPC_SECREL:
+ DUMP_RELOC2(ppc_coff_howto_table[r_type].name, internal);
+ break;
+ case IMAGE_REL_PPC_IMGLUE:
+ DUMP_RELOC2(ppc_coff_howto_table[r_type].name, internal);
+ break;
+ default:
+ fprintf(stderr,
+ "Warning: Unsupported reloc %s [%d] used -- it may not work.\n",
+ ppc_coff_howto_table[r_type].name,
+ r_type);
+ break;
+ }
+
+ relent->howto = ppc_coff_howto_table + r_type;
+
+}
+
+static reloc_howto_type *
+coff_ppc_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
+ bfd *abfd;
+ asection *sec;
+ struct internal_reloc *rel;
+ struct coff_link_hash_entry *h;
+ struct internal_syment *sym;
+ bfd_vma *addendp;
+{
+ reloc_howto_type *howto;
+
+ /* We can encode one of three things in the type field, aside from the
+ type:
+ 1. IMAGE_REL_PPC_NEG - indicates the value field is a subtraction
+ value, rather than an addition value
+ 2. IMAGE_REL_PPC_BRTAKEN, IMAGE_REL_PPC_BRNTAKEN - indicates that
+ the branch is expected to be taken or not.
+ 3. IMAGE_REL_PPC_TOCDEFN - toc slot definition in the file
+ For now, we just strip this stuff to find the type, and ignore it other
+ than that.
+ */
+
+ unsigned short r_type = EXTRACT_TYPE (rel->r_type);
+ unsigned short r_flags = EXTRACT_FLAGS(rel->r_type);
+ unsigned short junk = EXTRACT_JUNK (rel->r_type);
+
+fprintf(stderr,
+ "coff_ppc_rtype_to_howto\n");
+
+ /* the masking process only slices off the bottom byte for r_type. */
+ if ( r_type > MAX_RELOC_INDEX )
+ {
+ fprintf(stderr,
+ "coff_ppc_rtype_to_howto: index %d out of range [%d, %d]\n",
+ r_type, 0, MAX_RELOC_INDEX);
+ abort();
+ }
+
+ /* check for absolute crap */
+ if ( junk != 0 )
+ {
+ fprintf(stderr,
+ "coff_ppc_rtype_to_howto: reloc index %d contains junk %d\n",
+ rel->r_type, junk);
+ abort();
+ }
+
+#ifdef DEBUG_RELOC
+ /* now examine flags */
+ if (r_flags != 0)
+ {
+ fprintf (stderr, "Reloc with flags found!");
+ if ( r_flags & IMAGE_REL_PPC_NEG )
+ fprintf (stderr, " NEG");
+ if ( r_flags & IMAGE_REL_PPC_BRTAKEN )
+ fprintf (stderr, " BRTAKEN");
+ if ( r_flags & IMAGE_REL_PPC_BRNTAKEN )
+ fprintf (stderr, " BRNTAKEN");
+ if ( r_flags & IMAGE_REL_PPC_TOCDEFN )
+ fprintf (stderr, " TOCDEFN");
+ fprintf(stderr, "\n");
+ }
+#endif
+
+ switch(r_type)
+ {
+ case IMAGE_REL_PPC_ADDR32NB:
+ DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel);
+ *addendp -= pe_data(sec->output_section->owner)->pe_opthdr.ImageBase;
+ break;
+ case IMAGE_REL_PPC_ADDR16:
+ case IMAGE_REL_PPC_REL24:
+ case IMAGE_REL_PPC_ADDR24:
+ case IMAGE_REL_PPC_TOCREL16:
+ case IMAGE_REL_PPC_ADDR32:
+ case IMAGE_REL_PPC_IFGLUE:
+ case IMAGE_REL_PPC_SECTION:
+ case IMAGE_REL_PPC_SECREL:
+ DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel);
+ break;
+ case IMAGE_REL_PPC_IMGLUE:
+ DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel);
+ break;
+ default:
+ fprintf(stderr,
+ "Warning: Unsupported reloc %s [%d] used -- it may not work.\n",
+ ppc_coff_howto_table[r_type].name,
+ r_type);
+ break;
+ }
+
+ howto = ppc_coff_howto_table + r_type;
+ return howto;
+}
+
+
+/* a cheesy little macro to make the code a little more readable */
+#define HOW2MAP(bfd_rtype,ppc_rtype) \
+ case bfd_rtype: return &ppc_coff_howto_table[ppc_rtype]
+
+static reloc_howto_type *ppc_coff_reloc_type_lookup
+PARAMS ((bfd *, bfd_reloc_code_real_type));
+
+static reloc_howto_type *
+ppc_coff_reloc_type_lookup (abfd, code)
+ bfd *abfd;
+ bfd_reloc_code_real_type code;
+{
+
+#ifdef DEBUG_RELOC
+ fprintf(stderr, "ppc_coff_reloc_type_lookup for %s\n",
+ bfd_get_reloc_code_name(code));
+#endif
+
+ switch (code)
+ {
+ HOW2MAP(BFD_RELOC_16_GOT_PCREL, IMAGE_REL_PPC_IFGLUE);
+ HOW2MAP(BFD_RELOC_16, IMAGE_REL_PPC_ADDR16);
+ HOW2MAP(BFD_RELOC_PPC_B26, IMAGE_REL_PPC_REL24);
+ HOW2MAP(BFD_RELOC_PPC_BA26, IMAGE_REL_PPC_ADDR24);
+ HOW2MAP(BFD_RELOC_PPC_TOC16, IMAGE_REL_PPC_TOCREL16);
+ HOW2MAP(BFD_RELOC_32, IMAGE_REL_PPC_ADDR32);
+ HOW2MAP(BFD_RELOC_RVA, IMAGE_REL_PPC_ADDR32NB);
+ default:
+ fprintf(stderr,
+ "\treturning NULL\n");
+ return NULL;
+ }
+
+ return NULL;
+}
+
+#undef HOW2MAP
+
+
+/* Tailor coffcode.h -- macro heaven. */
+
+#define RTYPE2HOWTO(cache_ptr, dst) ppc_coff_rtype2howto (cache_ptr, dst)
+
+#ifndef COFF_IMAGE_WITH_PE
+static void
+ppc_coff_swap_sym_in_hook ();
+#endif
+
+/* We use the special COFF backend linker, with our own special touch. */
+
+#define coff_bfd_reloc_type_lookup ppc_coff_reloc_type_lookup
+#define coff_rtype_to_howto coff_ppc_rtype_to_howto
+#define coff_relocate_section coff_ppc_relocate_section
+
+#ifndef COFF_IMAGE_WITH_PE
+#define coff_swap_sym_in_hook ppc_coff_swap_sym_in_hook
+#endif
+
+#define SELECT_RELOC(internal, howto) {internal.r_type=howto->type;}
+
+#define COFF_PAGE_SIZE 0x1000
+
+#define POWERPC_LE_PE
+
+#include "coffcode.h"
+
+
+
+#ifndef COFF_IMAGE_WITH_PE
+static void
+ppc_coff_swap_sym_in_hook (abfd, ext1, in1)
+ bfd *abfd;
+ PTR ext1;
+ PTR in1;
+{
+ SYMENT *ext = (SYMENT *)ext1;
+ struct internal_syment *in = (struct internal_syment *)in1;
+
+#if 0
+ if (bfd_of_toc_owner != 0) /* we already have a toc, so go home */
+ return;
+#endif
+
+ if (strcmp(in->_n._n_name, ".toc") == 0)
+ {
+ flagword flags;
+ register asection *s;
+ char *foo;
+
+ s = bfd_get_section_by_name ( abfd , TOC_SECTION_NAME);
+ if (s != NULL)
+ {
+ return;
+ }
+
+ flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY ;
+
+#ifdef TOC_DEBUG
+ fprintf(stderr,
+ "ppc_coff_swap_sym_in_hook: about to create the %s section\n",
+ TOC_SECTION_NAME);
+#endif
+
+ s = bfd_make_section (abfd, TOC_SECTION_NAME);
+
+ if (s == NULL
+ || !bfd_set_section_flags (abfd, s, flags)
+ || !bfd_set_section_alignment (abfd, s, 2))
+ {
+ fprintf(stderr,
+ "toc section allocation failed!\n");
+ abort();
+ }
+
+ /* save the bfd for later allocation */
+ bfd_of_toc_owner = abfd;
+ }
+
+ return;
+}
+#endif
+
+
+
+/* The transfer vectors that lead the outside world to all of the above. */
+
+#ifdef TARGET_LITTLE_SYM
+const bfd_target
+TARGET_LITTLE_SYM =
+{
+ TARGET_LITTLE_NAME, /* name or coff-arm-little */
+ bfd_target_coff_flavour,
+ false, /* data byte order is little */
+ false, /* header byte order is little */
+
+ (HAS_RELOC | EXEC_P | /* FIXME: object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | WP_TEXT),
+
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+ 0, /* leading char */
+ '/', /* ar_pad_char */
+ 15, /* ar_max_namelen??? FIXMEmgo */
+
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
+
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
+
+ {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
+ bfd_generic_archive_p, /* _bfd_dummy_target */ coff_object_p },
+ {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
+ bfd_false},
+ {bfd_false, coff_write_object_contents, /* bfd_write_contents */
+ _bfd_write_archive_contents, bfd_false},
+
+ BFD_JUMP_TABLE_GENERIC (coff),
+ BFD_JUMP_TABLE_COPY (coff),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
+ BFD_JUMP_TABLE_SYMBOLS (coff),
+ BFD_JUMP_TABLE_RELOCS (coff),
+ BFD_JUMP_TABLE_WRITE (coff),
+ BFD_JUMP_TABLE_LINK (coff),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ COFF_SWAP_TABLE,
+};
+#endif
+
+#ifdef TARGET_BIG_SYM
+const bfd_target
+TARGET_BIG_SYM =
+{
+ TARGET_BIG_NAME,
+ bfd_target_coff_flavour,
+ true, /* data byte order is big */
+ true, /* header byte order is big */
+
+ (HAS_RELOC | EXEC_P | /* FIXME: object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | WP_TEXT),
+
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+ 0, /* leading char */
+ '/', /* ar_pad_char */
+ 15, /* ar_max_namelen??? FIXMEmgo */
+
+ bfd_getb64, bfd_getb_signed_64, bfd_putb64,
+ bfd_getb32, bfd_getb_signed_32, bfd_putb32,
+ bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
+
+ bfd_getb64, bfd_getb_signed_64, bfd_putb64,
+ bfd_getb32, bfd_getb_signed_32, bfd_putb32,
+ bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
+
+ {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
+ bfd_generic_archive_p, /* _bfd_dummy_target */ coff_object_p },
+ {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
+ bfd_false},
+ {bfd_false, coff_write_object_contents, /* bfd_write_contents */
+ _bfd_write_archive_contents, bfd_false},
+
+ BFD_JUMP_TABLE_GENERIC (coff),
+ BFD_JUMP_TABLE_COPY (coff),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
+ BFD_JUMP_TABLE_SYMBOLS (coff),
+ BFD_JUMP_TABLE_RELOCS (coff),
+ BFD_JUMP_TABLE_WRITE (coff),
+ BFD_JUMP_TABLE_LINK (coff),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ COFF_SWAP_TABLE,
+};
+
+#endif