X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Fcoff-ppc.c;h=ab5c2c837c10e10b317261a6488b916535ff7edb;hb=d0d6922c6855c7473d0d2dda45674443ba503cb5;hp=ae87505d67e68fec2a9749dd98668fa5ed8c0cdf;hpb=d6f41a7d3e56c2b8467f39cd05283649050c09cc;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/coff-ppc.c b/bfd/coff-ppc.c index ae87505d67..ab5c2c837c 100644 --- a/bfd/coff-ppc.c +++ b/bfd/coff-ppc.c @@ -1,38 +1,39 @@ /* BFD back-end for PowerPC Microsoft Portable Executable files. - Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. + Copyright (C) 1990-2019 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 + 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 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 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 3 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. + 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. */ + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, 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 "bfd.h" #include "libbfd.h" -#include "obstack.h" #include "coff/powerpc.h" #include "coff/internal.h" @@ -47,9 +48,159 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "libcoff.h" -/* 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. */ +/* This file is compiled more than once, but we only compile the + final_link routine once. */ +extern bfd_boolean ppc_bfd_coff_final_link (bfd *, struct bfd_link_info *); +extern void dump_toc (void *); + +/* The toc is a set of bfd_vma fields. We use the fact that valid + addresses are even (i.e. the bit representing "1" is off) to allow + us to encode a little extra information in the field + - Unallocated addresses are initialized to 1. + - Allocated addresses are even numbers. + The first time we actually write a reference to the toc in the bfd, + we want to record that fact in a fixup file (if it is asked for), so + we keep track of whether or not an address has been written by marking + the low order bit with a "1" upon writing. */ + +#define SET_UNALLOCATED(x) ((x) = 1) +#define IS_UNALLOCATED(x) ((x) == 1) + +#define IS_WRITTEN(x) ((x) & 1) +#define MARK_AS_WRITTEN(x) ((x) |= 1) +#define MAKE_ADDR_AGAIN(x) ((x) &= ~1) + +/* Turn on this check if you suspect something amiss in the hash tables. */ +#ifdef DEBUG_HASH + +/* Need a 7 char string for an eye catcher. */ +#define EYE "krkjunk" + +#define HASH_CHECK_DCL char eye_catcher[8]; +#define HASH_CHECK_INIT(ret) strcpy(ret->eye_catcher, EYE) +#define HASH_CHECK(addr) \ + if (strcmp (addr->eye_catcher, EYE) != 0) \ + { \ + fprintf (stderr,\ + /* xgettext: c-format */ \ + _("File %s, line %d, Hash check failure, bad eye %8s\n"), \ + __FILE__, __LINE__, addr->eye_catcher); \ + abort (); \ + } + +#else + +#define HASH_CHECK_DCL +#define HASH_CHECK_INIT(ret) +#define HASH_CHECK(addr) + +#endif + +/* 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; + + HASH_CHECK_DCL +}; + +/* PE linker hash table. */ + +struct ppc_coff_link_hash_table +{ + struct coff_link_hash_table root; /* First entry, as required. */ +}; + +/* Routine to create an entry in the link hash table. */ + +static struct bfd_hash_entry * +ppc_coff_link_hash_newfunc (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. */ + SET_UNALLOCATED (ret->toc_offset); + ret->symbol_is_glue = 0; + ret->glue_insn = 0; + + HASH_CHECK_INIT (ret); + } + + return (struct bfd_hash_entry *) ret; +} + +/* Initialize a PE linker hash table. */ + +static bfd_boolean +ppc_coff_link_hash_table_init (struct ppc_coff_link_hash_table *table, + bfd *abfd, + struct bfd_hash_entry *(*newfunc) + (struct bfd_hash_entry *, + struct bfd_hash_table *, + const char *), + unsigned int entsize) +{ + return _bfd_coff_link_hash_table_init (&table->root, abfd, newfunc, entsize); +} + +/* Create a PE linker hash table. */ + +static struct bfd_link_hash_table * +ppc_coff_link_hash_table_create (bfd *abfd) +{ + struct ppc_coff_link_hash_table *ret; + bfd_size_type amt = sizeof (struct ppc_coff_link_hash_table); + + ret = (struct ppc_coff_link_hash_table *) bfd_malloc (amt); + if (ret == NULL) + return NULL; + if (!ppc_coff_link_hash_table_init (ret, abfd, + ppc_coff_link_hash_newfunc, + sizeof (struct ppc_coff_link_hash_entry))) + { + free (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. 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" @@ -61,558 +212,513 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 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... */ +/* These should definitely go in a header file somewhere... */ /* NOP */ -#define IMAGE_REL_PPC_ABSOLUTE 0x0000 +#define IMAGE_REL_PPC_ABSOLUTE 0x0000 /* 64-bit address */ -#define IMAGE_REL_PPC_ADDR64 0x0001 +#define IMAGE_REL_PPC_ADDR64 0x0001 /* 32-bit address */ -#define IMAGE_REL_PPC_ADDR32 0x0002 +#define IMAGE_REL_PPC_ADDR32 0x0002 /* 26-bit address, shifted left 2 (branch absolute) */ -#define IMAGE_REL_PPC_ADDR24 0x0003 +#define IMAGE_REL_PPC_ADDR24 0x0003 /* 16-bit address */ -#define IMAGE_REL_PPC_ADDR16 0x0004 +#define IMAGE_REL_PPC_ADDR16 0x0004 /* 16-bit address, shifted left 2 (load doubleword) */ -#define IMAGE_REL_PPC_ADDR14 0x0005 +#define IMAGE_REL_PPC_ADDR14 0x0005 /* 26-bit PC-relative offset, shifted left 2 (branch relative) */ -#define IMAGE_REL_PPC_REL24 0x0006 +#define IMAGE_REL_PPC_REL24 0x0006 /* 16-bit PC-relative offset, shifted left 2 (br cond relative) */ -#define IMAGE_REL_PPC_REL14 0x0007 +#define IMAGE_REL_PPC_REL14 0x0007 /* 16-bit offset from TOC base */ -#define IMAGE_REL_PPC_TOCREL16 0x0008 +#define IMAGE_REL_PPC_TOCREL16 0x0008 /* 16-bit offset from TOC base, shifted left 2 (load doubleword) */ -#define IMAGE_REL_PPC_TOCREL14 0x0009 +#define IMAGE_REL_PPC_TOCREL14 0x0009 /* 32-bit addr w/o image base */ -#define IMAGE_REL_PPC_ADDR32NB 0x000A +#define IMAGE_REL_PPC_ADDR32NB 0x000A /* va of containing section (as in an image sectionhdr) */ -#define IMAGE_REL_PPC_SECREL 0x000B +#define IMAGE_REL_PPC_SECREL 0x000B /* sectionheader number */ -#define IMAGE_REL_PPC_SECTION 0x000C +#define IMAGE_REL_PPC_SECTION 0x000C /* substitute TOC restore instruction iff symbol is glue code */ -#define IMAGE_REL_PPC_IFGLUE 0x000D +#define IMAGE_REL_PPC_IFGLUE 0x000D /* symbol is glue code; virtual address is TOC restore instruction */ -#define IMAGE_REL_PPC_IMGLUE 0x000E +#define IMAGE_REL_PPC_IMGLUE 0x000E /* va of containing section (limited to 16 bits) */ -#define IMAGE_REL_PPC_SECREL16 0x000F +#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 +/* 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 +/* This is essentially the same as tocrel16, with TOCDEFN assumed. */ +#define IMAGE_REL_PPC_TOCREL16_DEFN 0x0013 -/* Flag bits in IMAGE_RELOCATION.TYPE */ +/* Flag bits in IMAGE_RELOCATION.TYPE. */ -/* subtract reloc value rather than adding it */ -#define IMAGE_REL_PPC_NEG 0x0100 +/* 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 taken. */ +#define IMAGE_REL_PPC_BRTAKEN 0x0200 -/* fix branch prediction bit to predict branch not taken */ -#define IMAGE_REL_PPC_BRNTAKEN 0x0400 +/* 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 +/* 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 +/* 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_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)) - +#define EXTRACT_JUNK(x) \ + ((x) & ~(IMAGE_REL_PPC_TYPEMASK | IMAGE_REL_PPC_FLAGMASK)) -/* static helper functions to make relocation work */ +/* 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)); +static bfd_reloc_status_type ppc_refhi_reloc + (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); +static bfd_reloc_status_type ppc_pair_reloc + (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); +static bfd_reloc_status_type ppc_toc16_reloc + (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); +static bfd_reloc_status_type ppc_section_reloc + (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); +static bfd_reloc_status_type ppc_secrel_reloc + (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); +static bfd_reloc_status_type ppc_imglue_reloc + (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); - /* 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. */ -/* */ -/* */ -/* */ -/*---------------------------------------------------------------------------*/ + 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 */ + 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 */ - + 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 */ + 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 */ + 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 */ - + 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 */ + /* 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 */ + 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 */ - + 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 */ + 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 */ - + 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 */ + 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 */ - + 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 */ + 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 */ - + 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 */ + 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 */ - + 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 */ + 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 */ - + 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 */ + 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 */ - + 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 */ + 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 */ - + 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 */ + 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 */ + 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 */ + 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 */ + 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 */ + 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 */ + 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 */ + 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 */ + 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 */ + 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 */ + 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 */ + 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 */ + 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 */ + 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 */ + 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 */ + 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 */ -}; - + ppc_pair_reloc, /* special_function */ + "PAIR", /* name */ + TRUE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* IMAGE_REL_PPC_TOCREL16_DEFN 0x0013 */ + /* 16-bit offset from TOC base, without causing a definition */ + /* Used: */ + HOWTO ( (IMAGE_REL_PPC_TOCREL16 | IMAGE_REL_PPC_TOCDEFN), /* type */ + 0, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + 0, /* special_function */ + "TOCREL16, TOCDEFN", /* name */ + FALSE, /* partial_inplace */ + 0xffff, /* src_mask */ + 0xffff, /* dst_mask */ + FALSE), /* pcrel_offset */ +}; - -/* Some really cheezy macros that can be turned on to test stderr :-) */ - +/* 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 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); \ +#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 +/* 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); \ +#define n_offset _n._n_n._n_offset */ + +#define DUMP_RELOC2(n,r) \ +{ \ + fprintf (stderr,"%s sym %d, r_vaddr %d %s\n", \ + n, r->r_symndx, r->r_vaddr, \ + (((r->r_type) & IMAGE_REL_PPC_TOCDEFN) == 0) \ + ?" ":" TOCDEFN" ); \ } #else @@ -620,13 +726,14 @@ static reloc_howto_type ppc_coff_howto_table[] = #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; +/* TOC construction and management routines. */ +/* This file is compiled twice, and these variables are defined in one + of the compilations. FIXME: This is confusing and weird. Also, + BFD should not use global variables. */ +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; @@ -638,251 +745,218 @@ enum toc_type toc_64 }; -/* 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; +enum ref_category { - bfd_byte *t; - bfd_byte *old_contents; - asection *s; - int element_size; - int data; + priv, + pub, + tocdata +}; + +struct list_ele +{ + struct list_ele *next; + bfd_vma addr; + enum ref_category cat; int offset; - struct coff_link_hash_entry *h; - struct coff_symbol_struct *target; - int ret_val; const char *name; +}; + +extern struct list_ele *head; +extern struct list_ele *tail; + +static void +record_toc (asection *toc_section, + bfd_signed_vma our_toc_offset, + enum ref_category cat, + const char *name) +{ + /* Add this entry to our toc addr-offset-name list. */ + bfd_size_type amt = sizeof (struct list_ele); + struct list_ele *t = (struct list_ele *) bfd_malloc (amt); + + if (t == NULL) + abort (); + t->next = 0; + t->offset = our_toc_offset; + t->name = name; + t->cat = cat; + t->addr = toc_section->output_offset + our_toc_offset; + + if (head == 0) + { + head = t; + tail = t; + } + else + { + tail->next = t; + tail = t; + } +} + +#ifdef COFF_IMAGE_WITH_PE +/* Record a toc offset against a symbol. */ +static bfd_boolean +ppc_record_toc_entry (bfd *abfd, + struct bfd_link_info *info ATTRIBUTE_UNUSED, + asection *sec ATTRIBUTE_UNUSED, + int sym, + enum toc_type toc_kind ATTRIBUTE_UNUSED) +{ + struct ppc_coff_link_hash_entry *h; int *local_syms; h = 0; - h = obj_coff_sym_hashes (abfd)[sym]; + h = (struct ppc_coff_link_hash_entry *) (obj_coff_sym_hashes (abfd)[sym]); + if (h != 0) + { + HASH_CHECK(h); + } - if (h == 0) - { + if (h == 0) + { local_syms = obj_coff_local_toc_table(abfd); + if (local_syms == 0) { - int i; + unsigned int i; + bfd_size_type amt; + /* allocate a table */ - local_syms = - (int *) bfd_zalloc (abfd, - obj_raw_syment_count(abfd) * sizeof(int)); + amt = (bfd_size_type) obj_raw_syment_count (abfd) * sizeof (int); + local_syms = (int *) bfd_zalloc (abfd, amt); if (local_syms == 0) + return FALSE; + obj_coff_local_toc_table (abfd) = local_syms; + + for (i = 0; i < obj_raw_syment_count (abfd); ++i) { - bfd_set_error (bfd_error_no_memory); - return false; + SET_UNALLOCATED (local_syms[i]); } - 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) + if (IS_UNALLOCATED(local_syms[sym])) { 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 + + /* The size must fit in a 16-bit displacement. */ + if (global_toc_size > 65535) + { + _bfd_error_handler (_("TOC overflow")); + bfd_set_error (bfd_error_file_too_big); + return FALSE; + } } } else { - name = h->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) + /* Check to see if there's a toc slot allocated. If not, do it + here. It will be used in relocate_section. */ + if (IS_UNALLOCATED(h->toc_offset)) { 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 + + /* The size must fit in a 16-bit displacement. */ + if (global_toc_size >= 65535) + { + _bfd_error_handler (_("TOC overflow")); + bfd_set_error (bfd_error_file_too_big); + return FALSE; + } } } - return ret_val; + return TRUE; } - -/* Provided the symbol, returns the value reffed */ -static long get_symbol_value PARAMS ((asymbol *)); +/* Record a toc offset against a symbol. */ +static void +ppc_mark_symbol_as_glue (bfd *abfd, + int sym, + struct internal_reloc *rel) +{ + struct ppc_coff_link_hash_entry *h; -static long -get_symbol_value (symbol) - asymbol *symbol; -{ - long relocation = 0; + h = (struct ppc_coff_link_hash_entry *) (obj_coff_sym_hashes (abfd)[sym]); - if (bfd_is_com_section (symbol->section)) - { - relocation = 0; - } - else - { - relocation = symbol->value + - symbol->section->output_section->vma + - symbol->section->output_offset; - } - - return(relocation); + HASH_CHECK(h); + + h->symbol_is_glue = 1; + h->glue_insn = bfd_get_32 (abfd, (bfd_byte *) &rel->r_vaddr); + + return; } -/* Return true if this relocation should - appear in the output .reloc section. */ +#endif /* COFF_IMAGE_WITH_PE */ + +/* 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; +static bfd_boolean +in_reloc_p (bfd * abfd ATTRIBUTE_UNUSED, + reloc_howto_type *howto) { - return - (! howto->pc_relative) + return + (! howto->pc_relative) + && (howto->type != IMAGE_REL_PPC_ADDR32NB) && (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) */ + && (howto->type != IMAGE_REL_PPC_IMGLUE) + && (howto->type != IMAGE_REL_PPC_IFGLUE) + && (howto->type != IMAGE_REL_PPC_SECREL) + && (howto->type != IMAGE_REL_PPC_SECTION) + && (howto->type != IMAGE_REL_PPC_SECREL16) + && (howto->type != IMAGE_REL_PPC_REFHI) + && (howto->type != IMAGE_REL_PPC_REFLO) + && (howto->type != IMAGE_REL_PPC_PAIR) + && (howto->type != IMAGE_REL_PPC_TOCREL16_DEFN) ; +} -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; +static bfd_boolean +write_base_file_entry (bfd *obfd, struct bfd_link_info *info, bfd_vma addr) { - /* 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); - } + if (coff_data (obfd)->pe) + addr -= pe_data (obfd)->pe_opthdr.ImageBase; + if (fwrite (&addr, sizeof (addr), 1, (FILE *) info->base_file) == 1) + return TRUE; - - sym_value = get_symbol_value(symbol_in); - - return(bfd_reloc_ok); + bfd_set_error (bfd_error_system_call); + return FALSE; } /* 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; +static bfd_boolean +coff_ppc_relocate_section (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 + + /* If we are performing a relocatable 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; + if (bfd_link_relocatable (info)) + return TRUE; rel = relocs; relend = rel + input_section->reloc_count; for (; rel < relend; rel++) { long symndx; - struct coff_link_hash_entry *h; + struct ppc_coff_link_hash_entry *h; struct internal_syment *sym; bfd_vma val; @@ -892,24 +966,6 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section, 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; @@ -924,14 +980,26 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section, } else { - h = obj_coff_sym_hashes (input_bfd)[symndx]; + h = (struct ppc_coff_link_hash_entry *) + (obj_coff_sym_hashes (input_bfd)[symndx]); + if (h != 0) + { + HASH_CHECK(h); + } + sym = syms + symndx; } + if (r_type == IMAGE_REL_PPC_IMGLUE && h == 0) + { + /* An IMGLUE reloc must have a name. Something is very wrong. */ + abort (); + } + sec = NULL; val = 0; - /* FIXME: PAIR unsupported in the following code */ + /* FIXME: PAIR unsupported in the following code. */ if (h == NULL) { if (symndx == -1) @@ -941,364 +1009,393 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section, sec = sections[symndx]; val = (sec->output_section->vma + sec->output_offset - + sym->n_value - - sec->vma); + + sym->n_value); + if (! obj_pe (output_bfd)) + val -= sec->vma; } } else { - if (h->root.type == bfd_link_hash_defined - || h->root.type == bfd_link_hash_defweak) + HASH_CHECK(h); + + if (h->root.root.type == bfd_link_hash_defined + || h->root.root.type == bfd_link_hash_defweak) { - sec = h->root.u.def.section; - val = (h->root.u.def.value + 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.string, input_bfd, input_section, - rel->r_vaddr - input_section->vma))) - return false; - } + (*info->callbacks->undefined_symbol) + (info, h->root.root.root.string, input_bfd, input_section, + rel->r_vaddr - input_section->vma, TRUE); } rstat = bfd_reloc_ok; - - /* Each case must do its own relocation, setting rstat appropriately */ + + /* 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); + /* xgettext: c-format */ + _bfd_error_handler (_("%pB: unsupported relocation type %#x"), + input_bfd, r_type); bfd_set_error (bfd_error_bad_value); - abort(); - return false; + return FALSE; case IMAGE_REL_PPC_TOCREL16: { - bfd_vma our_toc_offset; + bfd_signed_vma our_toc_offset; int fixit; DUMP_RELOC2(howto->name, rel); - if (toc_section == 0) + if (toc_section == 0) { - toc_section = bfd_get_section_by_name (bfd_of_toc_owner, + 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 ) + if ( toc_section == NULL ) { - fprintf(stderr, "No Toc section!\n"); - abort(); + /* There is no toc section. Something is very wrong. */ + abort (); } } - /* - * 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; + /* 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 */ + { + /* It is a file local symbol. */ int *local_toc_table; - const char *name; + char name[SYMNMLEN + 1]; sym = syms + symndx; - name = sym->_n._n_name; + strncpy (name, sym->_n._n_name, SYMNMLEN); + name[SYMNMLEN] = '\0'; local_toc_table = obj_coff_local_toc_table(input_bfd); our_toc_offset = local_toc_table[symndx]; - if ((our_toc_offset & 1) != 0) + if (IS_WRITTEN(our_toc_offset)) { - /* if it has been written out, it is marked with the + /* 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 + again. */ + MAKE_ADDR_AGAIN(our_toc_offset); } else { - /* write out the toc entry */ -#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 + /* Write out the toc entry. */ + record_toc (toc_section, our_toc_offset, priv, + strdup (name)); - bfd_put_32(output_bfd, - val, + bfd_put_32 (output_bfd, val, toc_section->contents + our_toc_offset); - local_toc_table[symndx] |= 1; - fixit = true; + MARK_AS_WRITTEN(local_toc_table[symndx]); + fixit = TRUE; } } else { - const char *name = h->root.root.string; + const char *name = h->root.root.root.string; our_toc_offset = h->toc_offset; - if ((our_toc_offset & 1) != 0) + + if ((r_flags & IMAGE_REL_PPC_TOCDEFN) + == IMAGE_REL_PPC_TOCDEFN ) + { + /* This is unbelievable cheese. Some knowledgable asm + hacker has decided to use r2 as a base for loading + a value. He/She does this by setting the tocdefn bit, + and not supplying a toc definition. The behaviour is + then to use the difference between the value of the + symbol and the actual location of the toc as the toc + index. + + In fact, what is usually happening is, because the + Import Address Table is mapped immediately following + the toc, some trippy library code trying for speed on + dll linkage, takes advantage of that and considers + the IAT to be part of the toc, thus saving a load. */ + + our_toc_offset = val - (toc_section->output_section->vma + + toc_section->output_offset); + + /* The size must still fit in a 16-bit displacement. */ + if ((bfd_vma) our_toc_offset >= 65535) + { + _bfd_error_handler + /* xgettext: c-format */ + (_("%pB: Relocation for %s of %#" PRIx64 " exceeds " + "Toc size limit"), + input_bfd, name, (uint64_t) our_toc_offset); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + + record_toc (toc_section, our_toc_offset, pub, + strdup (name)); + } + else if (IS_WRITTEN (our_toc_offset)) { - /* if it has been written out, it is marked with the + /* 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 + again. */ + MAKE_ADDR_AGAIN(our_toc_offset); } else { -#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 + record_toc(toc_section, our_toc_offset, pub, + strdup (name)); - /* write out the toc entry */ - bfd_put_32(output_bfd, - val, + /* 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; + MARK_AS_WRITTEN(h->toc_offset); + /* The tricky part is that this is the address that + needs a .reloc entry for it. */ + fixit = TRUE; } } - if (fixit && info->base_file) + 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); - } + 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); - /* FIXME: this test is conservative */ - if (our_toc_offset > toc_section->_raw_size) + if (!write_base_file_entry (output_bfd, info, addr)) + return FALSE; + } + + /* FIXME: this test is conservative. */ + if ((r_flags & IMAGE_REL_PPC_TOCDEFN) != IMAGE_REL_PPC_TOCDEFN + && (bfd_vma) our_toc_offset > toc_section->size) { - fprintf(stderr, - "reloc offset is bigger than the toc size!\n"); - abort(); + _bfd_error_handler + /* xgettext: c-format */ + (_("%pB: Relocation exceeds allocated TOC (%#" PRIx64 ")"), + input_bfd, (uint64_t) toc_section->size); + bfd_set_error (bfd_error_bad_value); + return FALSE; } - /* Now we know the relocation for this toc reference */ + /* 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); + 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 function included */ - /* in the link or not. If it is, then we leave the nop instruction */ - /* alone, and the reloc is done. */ - - /* Actually, for dll support on NT, this is likely not necessary at - all. For any library function, a glue code stub must be supplied - to the linker, and the glue will take care of the toc reload */ - DUMP_RELOC2(howto->name, rel); -#if 0 - if (h == 0) - { - /* this better be a static function */ - fprintf(stderr, - "It's a static function.... \n"); - } - else - { - /* this is an externally visible function */ - /* is it present? */ - if (h->root.type == bfd_link_hash_defined - || h->root.type == bfd_link_hash_defweak) - { - fprintf(stderr, - "The function is present. \n"); - ; - } - else - { - fprintf(stderr, - "The function is not present. \n"); - } - } -#endif + { + /* 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. */ + DUMP_RELOC2 (howto->name, rel); + + if (h != 0) + { + if (h->symbol_is_glue == 1) + { + bfd_put_32 (input_bfd, (bfd_vma) 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. */ + /* 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 */ + /* Unimplemented: codeview debugging information. */ /* Is used to indicate that the value should be relative to the beginning of the section that contains the - symbol */ + symbol. */ break; case IMAGE_REL_PPC_ABSOLUTE: - case IMAGE_REL_PPC_IMGLUE: { const char *my_name; + char buf[SYMNMLEN + 1]; + if (h == 0) - my_name = (syms+symndx)->_n._n_name; + { + strncpy (buf, (syms+symndx)->_n._n_name, SYMNMLEN); + buf[SYMNMLEN] = '\0'; + my_name = buf; + } else - my_name = h->root.root.string; + my_name = h->root.root.root.string; + + _bfd_error_handler + /* xgettext: c-format */ + (_("warning: unsupported reloc %s \n" + "sym %ld (%s), r_vaddr %" PRId64 " (%#" PRIx64 ")"), + howto->name, input_bfd, input_section, + rel->r_symndx, my_name, + (int64_t) rel->r_vaddr, (uint64_t) 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; - fprintf(stderr, - "Warning: unsupported reloc %s \n", - howto->name, - bfd_get_filename(input_bfd), - input_section->name); + if (h->symbol_is_glue == 1) + break; + my_name = h->root.root.root.string; - fprintf(stderr,"sym %d (%s), r_vaddr %d (%x)\n", - rel->r_symndx, my_name, rel->r_vaddr, rel->r_vaddr); + _bfd_error_handler + /* xgettext: c-format */ + (_("%pB: Out of order IMGLUE reloc for %s"), input_bfd, my_name); + bfd_set_error (bfd_error_bad_value); + return FALSE; } - 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; + + DUMP_RELOC2 (howto->name, rel); + + if (CONST_STRNEQ (input_section->name, ".idata$2") && first_thunk_address == 0) + { + /* Set magic values. */ + int idata5offset; + struct coff_link_hash_entry *myh; + + 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; } + + if (h == 0) + /* It is a file local symbol. */ + sym = syms + symndx; else { char *target = 0; - name = h->root.root.string; - if (strcmp(".idata$2", name) == 0) + name = h->root.root.root.string; + if (strcmp (".idata$2", name) == 0) target = "__idata2_magic__"; - else if (strcmp(".idata$4", name) == 0) + else if (strcmp (".idata$4", name) == 0) target = "__idata4_magic__"; - else if (strcmp(".idata$5", name) == 0) + 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) + if (target != 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); + struct coff_link_hash_entry *myh; - 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; + target, + FALSE, FALSE, TRUE); + if (myh == 0) + { + /* Missing magic cookies. Something is very wrong. */ + 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, + input_bfd, + val - + pe_data (output_bfd)->pe_opthdr.ImageBase, loc); } break; - case IMAGE_REL_PPC_ADDR16: case IMAGE_REL_PPC_REL24: + DUMP_RELOC2(howto->name, rel); + val -= (input_section->output_section->vma + + input_section->output_offset); + + rstat = _bfd_relocate_contents (howto, + input_bfd, + val, + loc); + break; + case IMAGE_REL_PPC_ADDR16: case IMAGE_REL_PPC_ADDR24: case IMAGE_REL_PPC_ADDR32: DUMP_RELOC2(howto->name, rel); rstat = _bfd_relocate_contents (howto, - input_bfd, - val, + input_bfd, + val, loc); break; } - if ( info->base_file ) + 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)) + 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); + /* 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 (!write_base_file_entry (output_bfd, info, addr)) + return FALSE; } } @@ -1316,7 +1413,7 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section, if (symndx == -1) name = "*ABS*"; else if (h != NULL) - name = h->root.root.string; + name = NULL; else if (sym == NULL) name = "*unknown*"; else if (sym->_n._n_n._n_zeroes == 0 @@ -1328,31 +1425,25 @@ coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section, 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; + (*info->callbacks->reloc_overflow) + (info, (h ? &h->root.root : NULL), name, howto->name, + (bfd_vma) 0, input_bfd, input_section, + rel->r_vaddr - input_section->vma); } } + } - } - - return true; + return TRUE; } #ifdef COFF_IMAGE_WITH_PE -long int global_toc_size = 0; +/* FIXME: BFD should not use global variables. This file is compiled + twice, and these variables are shared. This is confusing and + weird. */ + +long int global_toc_size = 4; bfd* bfd_of_toc_owner = 0; @@ -1360,150 +1451,163 @@ long int import_table_size; long int first_thunk_address; long int thunk_size; +struct list_ele *head; +struct list_ele *tail; -boolean -ppc_allocate_toc_section (info) - struct bfd_link_info *info; -{ - asection *s; - bfd_byte *foo; - static char test_char = '1'; +static char * +h1 = N_("\n\t\t\tTOC MAPPING\n\n"); +static char * +h2 = N_(" TOC disassembly Comments Name\n"); +static char * +h3 = N_(" Offset spelling (if present)\n"); -#ifdef DEBUG_TOC - fprintf(stderr, - "ppc_allocate_toc_section: allocating %s section of size %d\n", - TOC_SECTION_NAME, global_toc_size); -#endif +void +dump_toc (void * vfile) +{ + FILE *file = (FILE *) vfile; + struct list_ele *t; - if ( global_toc_size == 0 ) /* FIXME: does this get me in trouble? */ - return true; + fputs (_(h1), file); + fputs (_(h2), file); + fputs (_(h3), file); - if (bfd_of_toc_owner == 0) + for (t = head; t != 0; t=t->next) { - fprintf(stderr, - "There is no bfd that owns the toc section!\n"); - abort(); - } + const char *cat = ""; - s = bfd_get_section_by_name ( bfd_of_toc_owner , TOC_SECTION_NAME); - if (s == NULL) - { - fprintf(stderr, "No Toc section!\n"); - abort(); - } + if (t->cat == priv) + cat = _("private "); + else if (t->cat == pub) + cat = _("public "); + else if (t->cat == tocdata) + cat = _("data-in-toc "); - foo = bfd_alloc(bfd_of_toc_owner, global_toc_size); - memset(foo, test_char, global_toc_size); + if (t->offset > global_toc_size) + { + if (t->offset <= global_toc_size + thunk_size) + cat = _("IAT reference "); + else + { + fprintf (file, + /* xgettext: c-format */ + _("**** global_toc_size %ld(%lx), thunk_size %ld(%lx)\n"), + global_toc_size, (unsigned long) global_toc_size, + thunk_size, (unsigned long) thunk_size); + cat = _("Out of bounds!"); + } + } - s->_raw_size = s->_cooked_size = global_toc_size; - s->contents = foo; + fprintf (file, + " %04lx (%d)", (unsigned long) t->offset, t->offset - 32768); + fprintf (file, + " %s %s\n", + cat, t->name); + + } - return true; + fprintf (file, "\n"); } -boolean -ppc_process_before_allocation (abfd, info) - bfd *abfd; - struct bfd_link_info *info; +bfd_boolean +ppc_allocate_toc_section (struct bfd_link_info *info ATTRIBUTE_UNUSED) { - asection *sec; - struct internal_reloc *i, *rel; + asection *s; + bfd_byte *foo; + bfd_size_type amt; + static char test_char = '1'; -#if 0 - fprintf(stderr, - "ppc_process_before_allocation: BFD %s\n", - bfd_get_filename(abfd)); -#endif + if ( global_toc_size == 0 ) /* FIXME: does this get me in trouble? */ + return TRUE; + + if (bfd_of_toc_owner == 0) + /* No toc owner? Something is very wrong. */ + abort (); + + s = bfd_get_section_by_name ( bfd_of_toc_owner , TOC_SECTION_NAME); + if (s == NULL) + /* No toc section? Something is very wrong. */ + abort (); + + amt = global_toc_size; + foo = (bfd_byte *) bfd_alloc (bfd_of_toc_owner, amt); + memset(foo, test_char, (size_t) global_toc_size); - /* 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. */ + s->size = global_toc_size; + s->contents = foo; + + return TRUE; +} + +bfd_boolean +ppc_process_before_allocation (bfd *abfd, + struct bfd_link_info *info) +{ + asection *sec; + struct internal_reloc *i, *rel; - _bfd_coff_get_external_symbols(abfd); + /* 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 */ + /* Rummage around all the relocs and map the toc. */ sec = abfd->sections; if (sec == 0) - { - return true; - } + 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; - 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); - /* 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(); + if (i == 0) + abort (); - for (rel=i;relreloc_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); + 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); + bfd_boolean ok = TRUE; -#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"); + DUMP_RELOC2 (ppc_coff_howto_table[r_type].name, rel); + + switch(r_type) + { + case IMAGE_REL_PPC_TOCREL16: + /* If TOCDEFN is on, ignore as someone else has allocated the + toc entry. */ + if ((r_flags & IMAGE_REL_PPC_TOCDEFN) != IMAGE_REL_PPC_TOCDEFN) + ok = ppc_record_toc_entry(abfd, info, sec, + rel->r_symndx, default_toc); + if (!ok) + return FALSE; + break; + case IMAGE_REL_PPC_IMGLUE: + ppc_mark_symbol_as_glue (abfd, rel->r_symndx, rel); + break; + default: + break; + } + } } -#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; - default: - break; - } - } - } + return TRUE; } #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; +ppc_refhi_reloc (bfd *abfd ATTRIBUTE_UNUSED, + arelent *reloc_entry ATTRIBUTE_UNUSED, + asymbol *symbol ATTRIBUTE_UNUSED, + void * data ATTRIBUTE_UNUSED, + asection *input_section ATTRIBUTE_UNUSED, + bfd *output_bfd, + char **error_message ATTRIBUTE_UNUSED) { UN_IMPL("REFHI"); DUMP_RELOC("REFHI",reloc_entry); @@ -1515,45 +1619,13 @@ ppc_refhi_reloc (abfd, } 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; +ppc_pair_reloc (bfd *abfd ATTRIBUTE_UNUSED, + arelent *reloc_entry ATTRIBUTE_UNUSED, + asymbol *symbol ATTRIBUTE_UNUSED, + void * data ATTRIBUTE_UNUSED, + asection *input_section ATTRIBUTE_UNUSED, + bfd *output_bfd, + char **error_message ATTRIBUTE_UNUSED) { UN_IMPL("PAIR"); DUMP_RELOC("PAIR",reloc_entry); @@ -1564,77 +1636,32 @@ ppc_pair_reloc (abfd, 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; +ppc_toc16_reloc (bfd *abfd ATTRIBUTE_UNUSED, + arelent *reloc_entry ATTRIBUTE_UNUSED, + asymbol *symbol ATTRIBUTE_UNUSED, + void * data ATTRIBUTE_UNUSED, + asection *input_section ATTRIBUTE_UNUSED, + bfd *output_bfd, + char **error_message ATTRIBUTE_UNUSED) { - UN_IMPL("TOCREL16"); - DUMP_RELOC("TOCREL16",reloc_entry); + 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_continue; 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; +ppc_secrel_reloc (bfd *abfd ATTRIBUTE_UNUSED, + arelent *reloc_entry ATTRIBUTE_UNUSED, + asymbol *symbol ATTRIBUTE_UNUSED, + void * data ATTRIBUTE_UNUSED, + asection *input_section ATTRIBUTE_UNUSED, + bfd *output_bfd, + char **error_message ATTRIBUTE_UNUSED) { UN_IMPL("SECREL"); DUMP_RELOC("SECREL",reloc_entry); @@ -1646,20 +1673,13 @@ ppc_secrel_reloc (abfd, } 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; +ppc_section_reloc (bfd *abfd ATTRIBUTE_UNUSED, + arelent *reloc_entry ATTRIBUTE_UNUSED, + asymbol *symbol ATTRIBUTE_UNUSED, + void * data ATTRIBUTE_UNUSED, + asection *input_section ATTRIBUTE_UNUSED, + bfd *output_bfd, + char **error_message ATTRIBUTE_UNUSED) { UN_IMPL("SECTION"); DUMP_RELOC("SECTION",reloc_entry); @@ -1671,20 +1691,14 @@ ppc_section_reloc (abfd, } 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; +ppc_imglue_reloc (bfd *abfd ATTRIBUTE_UNUSED, + arelent *reloc_entry ATTRIBUTE_UNUSED, + asymbol *symbol ATTRIBUTE_UNUSED, + void * data ATTRIBUTE_UNUSED, + asection *input_section ATTRIBUTE_UNUSED, + bfd *output_bfd, + char **error_message ATTRIBUTE_UNUSED) + { UN_IMPL("IMGLUE"); DUMP_RELOC("IMGLUE",reloc_entry); @@ -1694,347 +1708,795 @@ ppc_imglue_reloc (abfd, return bfd_reloc_ok; } - - #define MAX_RELOC_INDEX \ - (sizeof(ppc_coff_howto_table) / sizeof(ppc_coff_howto_table[0]) - 1) - + (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)); +/* FIXME: There is a possibility 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 (relent, internal) - arelent *relent; - struct internal_reloc *internal; -{ - +ppc_coff_rtype2howto (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 + 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. + 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. - */ - + than that. */ + reloc_howto_type *howto; 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(); - } + /* The masking process only slices off the bottom byte for r_type. */ + if ( r_type > MAX_RELOC_INDEX ) + 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 + /* Check for absolute crap. */ + if (junk != 0) + abort (); - switch(r_type) + 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); + DUMP_RELOC2 (ppc_coff_howto_table[r_type].name, internal); + howto = ppc_coff_howto_table + r_type; break; case IMAGE_REL_PPC_IMGLUE: - DUMP_RELOC2(ppc_coff_howto_table[r_type].name, internal); - /* IMGLUE relocs have big numbers in them. Don't know what for yet. */ - internal->r_vaddr = 0; /* make it zero for now */ + DUMP_RELOC2 (ppc_coff_howto_table[r_type].name, internal); + howto = ppc_coff_howto_table + r_type; + break; + case IMAGE_REL_PPC_TOCREL16: + DUMP_RELOC2 (ppc_coff_howto_table[r_type].name, internal); + if (r_flags & IMAGE_REL_PPC_TOCDEFN) + howto = ppc_coff_howto_table + IMAGE_REL_PPC_TOCREL16_DEFN; + else + howto = ppc_coff_howto_table + IMAGE_REL_PPC_TOCREL16; break; default: - fprintf(stderr, - "Warning: Unsupported reloc %s [%d] used -- it may not work.\n", - ppc_coff_howto_table[r_type].name, - r_type); + _bfd_error_handler + /* xgettext: c-format */ + (_("warning: unsupported reloc %s [%d] used -- it may not work"), + ppc_coff_howto_table[r_type].name, r_type); + howto = ppc_coff_howto_table + r_type; break; } - - relent->howto = ppc_coff_howto_table + r_type; - + + relent->howto = howto; } 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; +coff_ppc_rtype_to_howto (bfd *abfd ATTRIBUTE_UNUSED, + asection *sec, + struct internal_reloc *rel, + struct coff_link_hash_entry *h ATTRIBUTE_UNUSED, + struct internal_syment *sym ATTRIBUTE_UNUSED, + 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 + 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. + 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. - */ + 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); + 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) + abort (); - /* 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) + /* Check for absolute crap. */ + if (junk != 0) + abort (); + + 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; + howto = ppc_coff_howto_table + r_type; + break; + case IMAGE_REL_PPC_TOCREL16: + DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel); + if (r_flags & IMAGE_REL_PPC_TOCDEFN) + howto = ppc_coff_howto_table + IMAGE_REL_PPC_TOCREL16_DEFN; + else + howto = ppc_coff_howto_table + IMAGE_REL_PPC_TOCREL16; 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); + howto = ppc_coff_howto_table + r_type; break; case IMAGE_REL_PPC_IMGLUE: DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel); - /* IMGLUE relocs have big numbers in them. Don't know what for yet. */ - rel->r_vaddr = 0; /* make it zero for now */ + howto = ppc_coff_howto_table + r_type; break; default: - fprintf(stderr, - "Warning: Unsupported reloc %s [%d] used -- it may not work.\n", - ppc_coff_howto_table[r_type].name, - r_type); + _bfd_error_handler + /* xgettext: c-format */ + (_("warning: unsupported reloc %s [%d] used -- it may not work"), + ppc_coff_howto_table[r_type].name, r_type); + howto = ppc_coff_howto_table + r_type; break; } - - howto = ppc_coff_howto_table + r_type; + return howto; } - -/* a cheesy little macro to make the code a little more readable */ +/* 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; +ppc_coff_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, + 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_32_GOTOFF, IMAGE_REL_PPC_IMGLUE); HOW2MAP(BFD_RELOC_16_GOT_PCREL, IMAGE_REL_PPC_IFGLUE); - HOW2MAP(BFD_RELOC_16, IMAGE_REL_PPC_ADDR16); + 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"); + HOW2MAP(BFD_RELOC_16_GOTOFF, IMAGE_REL_PPC_TOCREL16_DEFN); + HOW2MAP(BFD_RELOC_32, IMAGE_REL_PPC_ADDR32); + HOW2MAP(BFD_RELOC_RVA, IMAGE_REL_PPC_ADDR32NB); + default: return NULL; } - - return NULL; } - #undef HOW2MAP +static reloc_howto_type * +ppc_coff_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, + const char *r_name) +{ + unsigned int i; + + for (i = 0; + i < sizeof (ppc_coff_howto_table) / sizeof (ppc_coff_howto_table[0]); + i++) + if (ppc_coff_howto_table[i].name != NULL + && strcasecmp (ppc_coff_howto_table[i].name, r_name) == 0) + return &ppc_coff_howto_table[i]; + + return NULL; +} -/* Tailor coffcode.h -- macro heaven. */ +/* 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 +#define coff_bfd_reloc_name_lookup ppc_coff_reloc_name_lookup +#define coff_rtype_to_howto coff_ppc_rtype_to_howto +#define coff_relocate_section coff_ppc_relocate_section +#define coff_bfd_final_link ppc_bfd_coff_final_link #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 COFF_PAGE_SIZE 0x1000 +/* FIXME: This controls some code that used to be in peicode.h and is + now in peigen.c. It will not control the code in peigen.c. If + anybody wants to get this working, you will need to fix that. */ #define POWERPC_LE_PE -#include "coffcode.h" +#define COFF_SECTION_ALIGNMENT_ENTRIES \ +{ COFF_SECTION_NAME_EXACT_MATCH (".idata$2"), \ + COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }, \ +{ COFF_SECTION_NAME_EXACT_MATCH (".idata$3"), \ + COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }, \ +{ COFF_SECTION_NAME_EXACT_MATCH (".idata$4"), \ + COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \ +{ COFF_SECTION_NAME_EXACT_MATCH (".idata$5"), \ + COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \ +{ COFF_SECTION_NAME_EXACT_MATCH (".idata$6"), \ + COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 1 }, \ +{ COFF_SECTION_NAME_EXACT_MATCH (".reloc"), \ + COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 1 } +#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; + +static bfd_boolean +ppc_do_last (bfd *abfd) { - SYMENT *ext = (SYMENT *)ext1; - struct internal_syment *in = (struct internal_syment *)in1; + if (abfd == bfd_of_toc_owner) + return TRUE; + else + return FALSE; +} -#if 0 - if (bfd_of_toc_owner != 0) /* we already have a toc, so go home */ - return; -#endif +static bfd * +ppc_get_last (void) +{ + return bfd_of_toc_owner; +} + +/* This piece of machinery exists only to guarantee that the bfd that holds + the toc section is written last. + + This does depend on bfd_make_section attaching a new section to the + end of the section list for the bfd. + + This is otherwise intended to be functionally the same as + cofflink.c:_bfd_coff_final_link(). It is specifically different only + where the POWERPC_LE_PE macro modifies the code. It is left in as a + precise form of comment. krk@cygnus.com */ - if (strcmp(in->_n._n_name, ".toc") == 0) +/* Do the final link step. */ + +bfd_boolean +ppc_bfd_coff_final_link (bfd *abfd, struct bfd_link_info *info) +{ + bfd_size_type symesz; + struct coff_final_link_info flaginfo; + bfd_boolean debug_merge_allocated; + asection *o; + struct bfd_link_order *p; + bfd_size_type max_sym_count; + bfd_size_type max_lineno_count; + bfd_size_type max_reloc_count; + bfd_size_type max_output_reloc_count; + bfd_size_type max_contents_size; + file_ptr rel_filepos; + unsigned int relsz; + file_ptr line_filepos; + unsigned int linesz; + bfd *sub; + bfd_byte *external_relocs = NULL; + char strbuf[STRING_SIZE_SIZE]; + bfd_size_type amt; + + symesz = bfd_coff_symesz (abfd); + + flaginfo.info = info; + flaginfo.output_bfd = abfd; + flaginfo.strtab = NULL; + flaginfo.section_info = NULL; + flaginfo.last_file_index = -1; + flaginfo.last_bf_index = -1; + flaginfo.internal_syms = NULL; + flaginfo.sec_ptrs = NULL; + flaginfo.sym_indices = NULL; + flaginfo.outsyms = NULL; + flaginfo.linenos = NULL; + flaginfo.contents = NULL; + flaginfo.external_relocs = NULL; + flaginfo.internal_relocs = NULL; + debug_merge_allocated = FALSE; + + coff_data (abfd)->link_info = info; + + flaginfo.strtab = _bfd_stringtab_init (); + if (flaginfo.strtab == NULL) + goto error_return; + + if (! coff_debug_merge_hash_table_init (&flaginfo.debug_merge)) + goto error_return; + debug_merge_allocated = TRUE; + + /* Compute the file positions for all the sections. */ + if (! abfd->output_has_begun) + { + if (! bfd_coff_compute_section_file_positions (abfd)) + return FALSE; + } + + /* Count the line numbers and relocation entries required for the + output file. Set the file positions for the relocs. */ + rel_filepos = obj_relocbase (abfd); + relsz = bfd_coff_relsz (abfd); + max_contents_size = 0; + max_lineno_count = 0; + max_reloc_count = 0; + + for (o = abfd->sections; o != NULL; o = o->next) { - flagword flags; - register asection *s; - char *foo; + o->reloc_count = 0; + o->lineno_count = 0; - s = bfd_get_section_by_name ( abfd , TOC_SECTION_NAME); - if (s != NULL) + for (p = o->map_head.link_order; p != NULL; p = p->next) { - return; + if (p->type == bfd_indirect_link_order) + { + asection *sec; + + sec = p->u.indirect.section; + + /* Mark all sections which are to be included in the + link. This will normally be every section. We need + to do this so that we can identify any sections which + the linker has decided to not include. */ + sec->linker_mark = TRUE; + + if (info->strip == strip_none + || info->strip == strip_some) + o->lineno_count += sec->lineno_count; + + if (bfd_link_relocatable (info)) + o->reloc_count += sec->reloc_count; + + if (sec->rawsize > max_contents_size) + max_contents_size = sec->rawsize; + if (sec->size > max_contents_size) + max_contents_size = sec->size; + if (sec->lineno_count > max_lineno_count) + max_lineno_count = sec->lineno_count; + if (sec->reloc_count > max_reloc_count) + max_reloc_count = sec->reloc_count; + } + else if (bfd_link_relocatable (info) + && (p->type == bfd_section_reloc_link_order + || p->type == bfd_symbol_reloc_link_order)) + ++o->reloc_count; + } + if (o->reloc_count == 0) + o->rel_filepos = 0; + else + { + o->flags |= SEC_RELOC; + o->rel_filepos = rel_filepos; + rel_filepos += o->reloc_count * relsz; + } + } + + /* If doing a relocatable link, allocate space for the pointers we + need to keep. */ + if (bfd_link_relocatable (info)) + { + unsigned int i; + + /* We use section_count + 1, rather than section_count, because + the target_index fields are 1 based. */ + amt = abfd->section_count + 1; + amt *= sizeof (struct coff_link_section_info); + flaginfo.section_info = (struct coff_link_section_info *) bfd_malloc (amt); + + if (flaginfo.section_info == NULL) + goto error_return; + + for (i = 0; i <= abfd->section_count; i++) + { + flaginfo.section_info[i].relocs = NULL; + flaginfo.section_info[i].rel_hashes = NULL; + } + } + + /* We now know the size of the relocs, so we can determine the file + positions of the line numbers. */ + line_filepos = rel_filepos; + linesz = bfd_coff_linesz (abfd); + max_output_reloc_count = 0; + + for (o = abfd->sections; o != NULL; o = o->next) + { + if (o->lineno_count == 0) + o->line_filepos = 0; + else + { + o->line_filepos = line_filepos; + line_filepos += o->lineno_count * linesz; } - flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY ; + if (o->reloc_count != 0) + { + /* We don't know the indices of global symbols until we have + written out all the local symbols. For each section in + the output file, we keep an array of pointers to hash + table entries. Each entry in the array corresponds to a + reloc. When we find a reloc against a global symbol, we + set the corresponding entry in this array so that we can + fix up the symbol index after we have written out all the + local symbols. + + Because of this problem, we also keep the relocs in + memory until the end of the link. This wastes memory, + but only when doing a relocatable link, which is not the + common case. */ + BFD_ASSERT (bfd_link_relocatable (info)); + amt = o->reloc_count; + amt *= sizeof (struct internal_reloc); + flaginfo.section_info[o->target_index].relocs = + (struct internal_reloc *) bfd_malloc (amt); + amt = o->reloc_count; + amt *= sizeof (struct coff_link_hash_entry *); + flaginfo.section_info[o->target_index].rel_hashes = + (struct coff_link_hash_entry **) bfd_malloc (amt); + if (flaginfo.section_info[o->target_index].relocs == NULL + || flaginfo.section_info[o->target_index].rel_hashes == NULL) + goto error_return; + + if (o->reloc_count > max_output_reloc_count) + max_output_reloc_count = o->reloc_count; + } + + /* Reset the reloc and lineno counts, so that we can use them to + count the number of entries we have output so far. */ + o->reloc_count = 0; + o->lineno_count = 0; + } + + obj_sym_filepos (abfd) = line_filepos; + + /* Figure out the largest number of symbols in an input BFD. Take + the opportunity to clear the output_has_begun fields of all the + input BFD's. */ + max_sym_count = 0; + for (sub = info->input_bfds; sub != NULL; sub = sub->link.next) + { + bfd_size_type sz; + + sub->output_has_begun = FALSE; + sz = obj_raw_syment_count (sub); + if (sz > max_sym_count) + max_sym_count = sz; + } + + /* Allocate some buffers used while linking. */ + amt = max_sym_count * sizeof (struct internal_syment); + flaginfo.internal_syms = (struct internal_syment *) bfd_malloc (amt); + amt = max_sym_count * sizeof (asection *); + flaginfo.sec_ptrs = (asection **) bfd_malloc (amt); + amt = max_sym_count * sizeof (long); + flaginfo.sym_indices = (long *) bfd_malloc (amt); + amt = (max_sym_count + 1) * symesz; + flaginfo.outsyms = (bfd_byte *) bfd_malloc (amt); + amt = max_lineno_count * bfd_coff_linesz (abfd); + flaginfo.linenos = (bfd_byte *) bfd_malloc (amt); + flaginfo.contents = (bfd_byte *) bfd_malloc (max_contents_size); + flaginfo.external_relocs = (bfd_byte *) bfd_malloc (max_reloc_count * relsz); + if (! bfd_link_relocatable (info)) + { + amt = max_reloc_count * sizeof (struct internal_reloc); + flaginfo.internal_relocs = (struct internal_reloc *) bfd_malloc (amt); + } + if ((flaginfo.internal_syms == NULL && max_sym_count > 0) + || (flaginfo.sec_ptrs == NULL && max_sym_count > 0) + || (flaginfo.sym_indices == NULL && max_sym_count > 0) + || flaginfo.outsyms == NULL + || (flaginfo.linenos == NULL && max_lineno_count > 0) + || (flaginfo.contents == NULL && max_contents_size > 0) + || (flaginfo.external_relocs == NULL && max_reloc_count > 0) + || (! bfd_link_relocatable (info) + && flaginfo.internal_relocs == NULL + && max_reloc_count > 0)) + goto error_return; + + /* We now know the position of everything in the file, except that + we don't know the size of the symbol table and therefore we don't + know where the string table starts. We just build the string + table in memory as we go along. We process all the relocations + for a single input file at once. */ + obj_raw_syment_count (abfd) = 0; + + if (coff_backend_info (abfd)->_bfd_coff_start_final_link) + { + if (! bfd_coff_start_final_link (abfd, info)) + goto error_return; + } + + for (o = abfd->sections; o != NULL; o = o->next) + { + for (p = o->map_head.link_order; p != NULL; p = p->next) + { + if (p->type == bfd_indirect_link_order + && (bfd_get_flavour (p->u.indirect.section->owner) + == bfd_target_coff_flavour)) + { + sub = p->u.indirect.section->owner; +#ifdef POWERPC_LE_PE + if (! sub->output_has_begun && !ppc_do_last(sub)) +#else + if (! sub->output_has_begun) +#endif + { + if (! _bfd_coff_link_input_bfd (&flaginfo, sub)) + goto error_return; + sub->output_has_begun = TRUE; + } + } + else if (p->type == bfd_section_reloc_link_order + || p->type == bfd_symbol_reloc_link_order) + { + if (! _bfd_coff_reloc_link_order (abfd, &flaginfo, o, p)) + goto error_return; + } + else + { + if (! _bfd_default_link_order (abfd, info, o, p)) + goto error_return; + } + } + } -#ifdef TOC_DEBUG - fprintf(stderr, - "ppc_coff_swap_sym_in_hook: about to create the %s section\n", - TOC_SECTION_NAME); +#ifdef POWERPC_LE_PE + { + bfd* last_one = ppc_get_last(); + if (last_one) + { + if (! _bfd_coff_link_input_bfd (&flaginfo, last_one)) + goto error_return; + } + last_one->output_has_begun = TRUE; + } #endif - s = bfd_make_section (abfd, TOC_SECTION_NAME); + /* Free up the buffers used by _bfd_coff_link_input_bfd. */ + coff_debug_merge_hash_table_free (&flaginfo.debug_merge); + debug_merge_allocated = FALSE; + + if (flaginfo.internal_syms != NULL) + { + free (flaginfo.internal_syms); + flaginfo.internal_syms = NULL; + } + if (flaginfo.sec_ptrs != NULL) + { + free (flaginfo.sec_ptrs); + flaginfo.sec_ptrs = NULL; + } + if (flaginfo.sym_indices != NULL) + { + free (flaginfo.sym_indices); + flaginfo.sym_indices = NULL; + } + if (flaginfo.linenos != NULL) + { + free (flaginfo.linenos); + flaginfo.linenos = NULL; + } + if (flaginfo.contents != NULL) + { + free (flaginfo.contents); + flaginfo.contents = NULL; + } + if (flaginfo.external_relocs != NULL) + { + free (flaginfo.external_relocs); + flaginfo.external_relocs = NULL; + } + if (flaginfo.internal_relocs != NULL) + { + free (flaginfo.internal_relocs); + flaginfo.internal_relocs = NULL; + } + + /* The value of the last C_FILE symbol is supposed to be the symbol + index of the first external symbol. Write it out again if + necessary. */ + if (flaginfo.last_file_index != -1 + && (unsigned int) flaginfo.last_file.n_value != obj_raw_syment_count (abfd)) + { + file_ptr pos; + + flaginfo.last_file.n_value = obj_raw_syment_count (abfd); + bfd_coff_swap_sym_out (abfd, &flaginfo.last_file, + flaginfo.outsyms); + pos = obj_sym_filepos (abfd) + flaginfo.last_file_index * symesz; + if (bfd_seek (abfd, pos, SEEK_SET) != 0 + || bfd_bwrite (flaginfo.outsyms, symesz, abfd) != symesz) + return FALSE; + } - if (s == NULL - || !bfd_set_section_flags (abfd, s, flags) - || !bfd_set_section_alignment (abfd, s, 2)) + /* Write out the global symbols. */ + flaginfo.failed = FALSE; + bfd_hash_traverse (&info->hash->table, _bfd_coff_write_global_sym, &flaginfo); + if (flaginfo.failed) + goto error_return; + + /* The outsyms buffer is used by _bfd_coff_write_global_sym. */ + if (flaginfo.outsyms != NULL) + { + free (flaginfo.outsyms); + flaginfo.outsyms = NULL; + } + + if (bfd_link_relocatable (info)) + { + /* Now that we have written out all the global symbols, we know + the symbol indices to use for relocs against them, and we can + finally write out the relocs. */ + amt = max_output_reloc_count * relsz; + external_relocs = (bfd_byte *) bfd_malloc (amt); + if (external_relocs == NULL) + goto error_return; + + for (o = abfd->sections; o != NULL; o = o->next) { - fprintf(stderr, - "toc section allocation failed!\n"); - abort(); + struct internal_reloc *irel; + struct internal_reloc *irelend; + struct coff_link_hash_entry **rel_hash; + bfd_byte *erel; + + if (o->reloc_count == 0) + continue; + + irel = flaginfo.section_info[o->target_index].relocs; + irelend = irel + o->reloc_count; + rel_hash = flaginfo.section_info[o->target_index].rel_hashes; + erel = external_relocs; + for (; irel < irelend; irel++, rel_hash++, erel += relsz) + { + if (*rel_hash != NULL) + { + BFD_ASSERT ((*rel_hash)->indx >= 0); + irel->r_symndx = (*rel_hash)->indx; + } + bfd_coff_swap_reloc_out (abfd, irel, erel); + } + + amt = relsz * o->reloc_count; + if (bfd_seek (abfd, o->rel_filepos, SEEK_SET) != 0 + || bfd_bwrite (external_relocs, amt, abfd) != amt) + goto error_return; } - /* save the bfd for later allocation */ - bfd_of_toc_owner = abfd; + free (external_relocs); + external_relocs = NULL; } - return; -} + /* Free up the section information. */ + if (flaginfo.section_info != NULL) + { + unsigned int i; + + for (i = 0; i < abfd->section_count; i++) + { + if (flaginfo.section_info[i].relocs != NULL) + free (flaginfo.section_info[i].relocs); + if (flaginfo.section_info[i].rel_hashes != NULL) + free (flaginfo.section_info[i].rel_hashes); + } + free (flaginfo.section_info); + flaginfo.section_info = NULL; + } + + /* If we have optimized stabs strings, output them. */ + if (coff_hash_table (info)->stab_info.stabstr != NULL) + { + if (! _bfd_write_stab_strings (abfd, &coff_hash_table (info)->stab_info)) + return FALSE; + } + + /* Write out the string table. */ + if (obj_raw_syment_count (abfd) != 0) + { + file_ptr pos; + + pos = obj_sym_filepos (abfd) + obj_raw_syment_count (abfd) * symesz; + if (bfd_seek (abfd, pos, SEEK_SET) != 0) + return FALSE; + +#if STRING_SIZE_SIZE == 4 + H_PUT_32 (abfd, + _bfd_stringtab_size (flaginfo.strtab) + STRING_SIZE_SIZE, + strbuf); +#else + #error Change H_PUT_32 above #endif + if (bfd_bwrite (strbuf, (bfd_size_type) STRING_SIZE_SIZE, abfd) + != STRING_SIZE_SIZE) + return FALSE; + + if (! _bfd_stringtab_emit (abfd, flaginfo.strtab)) + return FALSE; + } + + _bfd_stringtab_free (flaginfo.strtab); + + /* Setting symcount to 0 will cause write_object_contents to + not try to write out the symbols. */ + abfd->symcount = 0; + + return TRUE; + + error_return: + if (debug_merge_allocated) + coff_debug_merge_hash_table_free (&flaginfo.debug_merge); + if (flaginfo.strtab != NULL) + _bfd_stringtab_free (flaginfo.strtab); + if (flaginfo.section_info != NULL) + { + unsigned int i; + + for (i = 0; i < abfd->section_count; i++) + { + if (flaginfo.section_info[i].relocs != NULL) + free (flaginfo.section_info[i].relocs); + if (flaginfo.section_info[i].rel_hashes != NULL) + free (flaginfo.section_info[i].rel_hashes); + } + free (flaginfo.section_info); + } + if (flaginfo.internal_syms != NULL) + free (flaginfo.internal_syms); + if (flaginfo.sec_ptrs != NULL) + free (flaginfo.sec_ptrs); + if (flaginfo.sym_indices != NULL) + free (flaginfo.sym_indices); + if (flaginfo.outsyms != NULL) + free (flaginfo.outsyms); + if (flaginfo.linenos != NULL) + free (flaginfo.linenos); + if (flaginfo.contents != NULL) + free (flaginfo.contents); + if (flaginfo.external_relocs != NULL) + free (flaginfo.external_relocs); + if (flaginfo.internal_relocs != NULL) + free (flaginfo.internal_relocs); + if (external_relocs != NULL) + free (external_relocs); + return FALSE; +} +#endif +/* Forward declaration for use by alternative_target field. */ +#ifdef TARGET_BIG_SYM +extern const bfd_target TARGET_BIG_SYM; +#endif -/* The transfer vectors that lead the outside world to all of the above. */ +/* The transfer vectors that lead the outside world to all of the above. */ #ifdef TARGET_LITTLE_SYM -const bfd_target -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 */ + BFD_ENDIAN_LITTLE, /* data byte order is little */ + BFD_ENDIAN_LITTLE, /* header byte order is little */ + + (HAS_RELOC | EXEC_P /* FIXME: object flags */ + | HAS_LINENO | HAS_DEBUG + | HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), + +#ifndef COFF_WITH_PE + (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_READONLY + | SEC_RELOC), /* section flags */ +#else + (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_READONLY + | SEC_RELOC | SEC_LINK_ONCE | SEC_LINK_DUPLICATES), +#endif + 0, /* leading char */ '/', /* ar_pad_char */ 15, /* ar_max_namelen??? FIXMEmgo */ + 0, /* match priority. */ bfd_getl64, bfd_getl_signed_64, bfd_putl64, bfd_getl32, bfd_getl_signed_32, bfd_putl32, @@ -2043,14 +2505,26 @@ TARGET_LITTLE_SYM = 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_check_format */ + _bfd_dummy_target, + coff_object_p, + bfd_generic_archive_p, + coff_object_p + }, + { /* bfd_set_format */ + _bfd_bool_bfd_false_error, + coff_mkobject, + _bfd_generic_mkarchive, + _bfd_bool_bfd_false_error + }, + { /* bfd_write_contents */ + _bfd_bool_bfd_false_error, + coff_write_object_contents, + _bfd_write_archive_contents, + _bfd_bool_bfd_false_error + }, + BFD_JUMP_TABLE_GENERIC (coff), BFD_JUMP_TABLE_COPY (coff), BFD_JUMP_TABLE_CORE (_bfd_nocore), @@ -2060,28 +2534,42 @@ TARGET_LITTLE_SYM = BFD_JUMP_TABLE_WRITE (coff), BFD_JUMP_TABLE_LINK (coff), BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), - - COFF_SWAP_TABLE, + + /* Alternative_target. */ +#ifdef TARGET_BIG_SYM + &TARGET_BIG_SYM, +#else + NULL, +#endif + + COFF_SWAP_TABLE }; #endif #ifdef TARGET_BIG_SYM -const bfd_target -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 */ + bfd_target_coff_flavour, + BFD_ENDIAN_BIG, /* data byte order is big */ + BFD_ENDIAN_BIG, /* header byte order is big */ - (HAS_RELOC | EXEC_P | /* FIXME: object flags */ - HAS_LINENO | HAS_DEBUG | - HAS_SYMS | HAS_LOCALS | WP_TEXT), + (HAS_RELOC | EXEC_P /* FIXME: object flags */ + | HAS_LINENO | HAS_DEBUG + | HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), + +#ifndef COFF_WITH_PE + (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_READONLY + | SEC_RELOC), /* section flags */ +#else + (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_READONLY + | SEC_RELOC | SEC_LINK_ONCE | SEC_LINK_DUPLICATES), +#endif - (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ 0, /* leading char */ '/', /* ar_pad_char */ 15, /* ar_max_namelen??? FIXMEmgo */ + 0, /* match priority. */ bfd_getb64, bfd_getb_signed_64, bfd_putb64, bfd_getb32, bfd_getb_signed_32, bfd_putb32, @@ -2091,12 +2579,24 @@ TARGET_BIG_SYM = 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_check_format */ + _bfd_dummy_target, + coff_object_p, + bfd_generic_archive_p, + coff_object_p + }, + { /* bfd_set_format */ + _bfd_bool_bfd_false_error, + coff_mkobject, + _bfd_generic_mkarchive, + _bfd_bool_bfd_false_error + }, + { /* bfd_write_contents */ + _bfd_bool_bfd_false_error, + coff_write_object_contents, + _bfd_write_archive_contents, + _bfd_bool_bfd_false_error + }, BFD_JUMP_TABLE_GENERIC (coff), BFD_JUMP_TABLE_COPY (coff), @@ -2108,16 +2608,14 @@ TARGET_BIG_SYM = BFD_JUMP_TABLE_LINK (coff), BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), - COFF_SWAP_TABLE, -}; - + /* Alternative_target. */ +#ifdef TARGET_LITTLE_SYM + &TARGET_LITTLE_SYM, +#else + NULL, #endif + COFF_SWAP_TABLE +}; - - - - - - - +#endif