diff options
Diffstat (limited to 'bfd/coff-ppc.c')
-rw-r--r-- | bfd/coff-ppc.c | 2582 |
1 files changed, 0 insertions, 2582 deletions
diff --git a/bfd/coff-ppc.c b/bfd/coff-ppc.c deleted file mode 100644 index a3ad1ef..0000000 --- a/bfd/coff-ppc.c +++ /dev/null @@ -1,2582 +0,0 @@ -/* BFD back-end for PowerPC Microsoft Portable Executable files. - Copyright (C) 1990-2020 Free Software Foundation, Inc. - - Original version pieced together by Kim Knuttila (krk@cygnus.com) - - There is nothing new under the sun. This file draws a lot on other - coff files, in particular, those for the rs/6000, alpha, mips, and - intel backends, and the PE work for the arm. - - This file is part of BFD, the Binary File Descriptor library. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 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. - - 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 "sysdep.h" -#include "bfd.h" -#include "libbfd.h" - -#include "coff/powerpc.h" -#include "coff/internal.h" - -#include "coff/pe.h" - -#ifdef BADMAG -#undef BADMAG -#endif - -#define BADMAG(x) PPCBADMAG(x) - -#include "libcoff.h" - -/* 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; - size_t 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" - -/* The main body of code is in coffcode.h. */ - -#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (3) - -/* In case we're on a 32-bit machine, construct a 64-bit "-1" value - from smaller values. Start with zero, widen, *then* decrement. */ -#define MINUS_ONE (((bfd_vma)0) - 1) - -/* These should definitely go in a header file somewhere... */ - -/* NOP */ -#define IMAGE_REL_PPC_ABSOLUTE 0x0000 - -/* 64-bit address */ -#define IMAGE_REL_PPC_ADDR64 0x0001 - -/* 32-bit address */ -#define IMAGE_REL_PPC_ADDR32 0x0002 - -/* 26-bit address, shifted left 2 (branch absolute) */ -#define IMAGE_REL_PPC_ADDR24 0x0003 - -/* 16-bit address */ -#define IMAGE_REL_PPC_ADDR16 0x0004 - -/* 16-bit address, shifted left 2 (load doubleword) */ -#define IMAGE_REL_PPC_ADDR14 0x0005 - -/* 26-bit PC-relative offset, shifted left 2 (branch relative) */ -#define IMAGE_REL_PPC_REL24 0x0006 - -/* 16-bit PC-relative offset, shifted left 2 (br cond relative) */ -#define IMAGE_REL_PPC_REL14 0x0007 - -/* 16-bit offset from TOC base */ -#define IMAGE_REL_PPC_TOCREL16 0x0008 - -/* 16-bit offset from TOC base, shifted left 2 (load doubleword) */ -#define IMAGE_REL_PPC_TOCREL14 0x0009 - -/* 32-bit addr w/o image base */ -#define IMAGE_REL_PPC_ADDR32NB 0x000A - -/* va of containing section (as in an image sectionhdr) */ -#define IMAGE_REL_PPC_SECREL 0x000B - -/* sectionheader number */ -#define IMAGE_REL_PPC_SECTION 0x000C - -/* substitute TOC restore instruction iff symbol is glue code */ -#define IMAGE_REL_PPC_IFGLUE 0x000D - -/* symbol is glue code; virtual address is TOC restore instruction */ -#define IMAGE_REL_PPC_IMGLUE 0x000E - -/* va of containing section (limited to 16 bits) */ -#define IMAGE_REL_PPC_SECREL16 0x000F - -/* Stuff to handle immediate data when the number of bits in the - data is greater than the number of bits in the immediate field - We need to do (usually) 32 bit arithmetic on 16 bit chunks. */ -#define IMAGE_REL_PPC_REFHI 0x0010 -#define IMAGE_REL_PPC_REFLO 0x0011 -#define IMAGE_REL_PPC_PAIR 0x0012 - -/* This is essentially the same as tocrel16, with TOCDEFN assumed. */ -#define IMAGE_REL_PPC_TOCREL16_DEFN 0x0013 - -/* Flag bits in IMAGE_RELOCATION.TYPE. */ - -/* Subtract reloc value rather than adding it. */ -#define IMAGE_REL_PPC_NEG 0x0100 - -/* Fix branch prediction bit to predict branch taken. */ -#define IMAGE_REL_PPC_BRTAKEN 0x0200 - -/* Fix branch prediction bit to predict branch not taken. */ -#define IMAGE_REL_PPC_BRNTAKEN 0x0400 - -/* TOC slot defined in file (or, data in toc). */ -#define IMAGE_REL_PPC_TOCDEFN 0x0800 - -/* Masks to isolate above values in IMAGE_RELOCATION.Type. */ -#define IMAGE_REL_PPC_TYPEMASK 0x00FF -#define IMAGE_REL_PPC_FLAGMASK 0x0F00 - -#define EXTRACT_TYPE(x) ((x) & IMAGE_REL_PPC_TYPEMASK) -#define EXTRACT_FLAGS(x) ((x) & IMAGE_REL_PPC_FLAGMASK) -#define EXTRACT_JUNK(x) \ - ((x) & ~(IMAGE_REL_PPC_TYPEMASK | IMAGE_REL_PPC_FLAGMASK)) - -/* Static helper functions to make relocation work. */ -/* (Work In Progress) */ - -static bfd_reloc_status_type ppc_refhi_reloc - (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. */ - - -static reloc_howto_type ppc_coff_howto_table[] = -{ - /* IMAGE_REL_PPC_ABSOLUTE 0x0000 NOP */ - /* Unused: */ - HOWTO (IMAGE_REL_PPC_ABSOLUTE, /* type */ - 0, /* rightshift */ - 0, /* size (0 = byte, 1 = short, 2 = long) */ - 0, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* dont complain_on_overflow */ - 0, /* special_function */ - "ABSOLUTE", /* name */ - FALSE, /* partial_inplace */ - 0x00, /* src_mask */ - 0x00, /* dst_mask */ - FALSE), /* pcrel_offset */ - - /* IMAGE_REL_PPC_ADDR64 0x0001 64-bit address */ - /* Unused: */ - HOWTO(IMAGE_REL_PPC_ADDR64, /* type */ - 0, /* rightshift */ - 3, /* size (0 = byte, 1 = short, 2 = long) */ - 64, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_bitfield, /* complain_on_overflow */ - 0, /* special_function */ - "ADDR64", /* name */ - TRUE, /* partial_inplace */ - MINUS_ONE, /* src_mask */ - MINUS_ONE, /* dst_mask */ - FALSE), /* pcrel_offset */ - - /* IMAGE_REL_PPC_ADDR32 0x0002 32-bit address */ - /* Used: */ - HOWTO (IMAGE_REL_PPC_ADDR32, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_bitfield, /* complain_on_overflow */ - 0, /* special_function */ - "ADDR32", /* name */ - TRUE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - - /* IMAGE_REL_PPC_ADDR24 0x0003 26-bit address, shifted left 2 (branch absolute) */ - /* the LI field is in bit 6 through bit 29 is 24 bits, + 2 for the shift */ - /* Of course, That's the IBM approved bit numbering, which is not what */ - /* anyone else uses.... The li field is in bit 2 thru 25 */ - /* Used: */ - HOWTO (IMAGE_REL_PPC_ADDR24, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 26, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_bitfield, /* complain_on_overflow */ - 0, /* special_function */ - "ADDR24", /* name */ - TRUE, /* partial_inplace */ - 0x07fffffc, /* src_mask */ - 0x07fffffc, /* dst_mask */ - FALSE), /* pcrel_offset */ - - /* IMAGE_REL_PPC_ADDR16 0x0004 16-bit address */ - /* Used: */ - HOWTO (IMAGE_REL_PPC_ADDR16, /* type */ - 0, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ - 16, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - 0, /* special_function */ - "ADDR16", /* name */ - TRUE, /* partial_inplace */ - 0xffff, /* src_mask */ - 0xffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - - /* IMAGE_REL_PPC_ADDR14 0x0005 */ - /* 16-bit address, shifted left 2 (load doubleword) */ - /* FIXME: the mask is likely wrong, and the bit position may be as well */ - /* Unused: */ - HOWTO (IMAGE_REL_PPC_ADDR14, /* type */ - 1, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ - 16, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - 0, /* special_function */ - "ADDR16", /* name */ - TRUE, /* partial_inplace */ - 0xffff, /* src_mask */ - 0xffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - - /* IMAGE_REL_PPC_REL24 0x0006 */ - /* 26-bit PC-relative offset, shifted left 2 (branch relative) */ - /* Used: */ - HOWTO (IMAGE_REL_PPC_REL24, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 26, /* bitsize */ - TRUE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - 0, /* special_function */ - "REL24", /* name */ - TRUE, /* partial_inplace */ - 0x3fffffc, /* src_mask */ - 0x3fffffc, /* dst_mask */ - FALSE), /* pcrel_offset */ - - /* IMAGE_REL_PPC_REL14 0x0007 */ - /* 16-bit PC-relative offset, shifted left 2 (br cond relative) */ - /* FIXME: the mask is likely wrong, and the bit position may be as well */ - /* FIXME: how does it know how far to shift? */ - /* Unused: */ - HOWTO (IMAGE_REL_PPC_ADDR14, /* type */ - 1, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ - 16, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - 0, /* special_function */ - "ADDR16", /* name */ - TRUE, /* partial_inplace */ - 0xffff, /* src_mask */ - 0xffff, /* dst_mask */ - TRUE), /* pcrel_offset */ - - /* IMAGE_REL_PPC_TOCREL16 0x0008 */ - /* 16-bit offset from TOC base */ - /* Used: */ - HOWTO (IMAGE_REL_PPC_TOCREL16,/* type */ - 0, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ - 16, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - ppc_toc16_reloc, /* special_function */ - "TOCREL16", /* name */ - FALSE, /* partial_inplace */ - 0xffff, /* src_mask */ - 0xffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - - /* IMAGE_REL_PPC_TOCREL14 0x0009 */ - /* 16-bit offset from TOC base, shifted left 2 (load doubleword) */ - /* Unused: */ - HOWTO (IMAGE_REL_PPC_TOCREL14,/* type */ - 1, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ - 16, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - 0, /* special_function */ - "TOCREL14", /* name */ - FALSE, /* partial_inplace */ - 0xffff, /* src_mask */ - 0xffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - - /* IMAGE_REL_PPC_ADDR32NB 0x000A */ - /* 32-bit addr w/ image base */ - /* Unused: */ - HOWTO (IMAGE_REL_PPC_ADDR32NB,/* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - 0, /* special_function */ - "ADDR32NB", /* name */ - TRUE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - - /* IMAGE_REL_PPC_SECREL 0x000B */ - /* va of containing section (as in an image sectionhdr) */ - /* Unused: */ - HOWTO (IMAGE_REL_PPC_SECREL,/* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - ppc_secrel_reloc, /* special_function */ - "SECREL", /* name */ - TRUE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - TRUE), /* pcrel_offset */ - - /* IMAGE_REL_PPC_SECTION 0x000C */ - /* sectionheader number */ - /* Unused: */ - HOWTO (IMAGE_REL_PPC_SECTION,/* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - ppc_section_reloc, /* special_function */ - "SECTION", /* name */ - TRUE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - TRUE), /* pcrel_offset */ - - /* IMAGE_REL_PPC_IFGLUE 0x000D */ - /* substitute TOC restore instruction iff symbol is glue code */ - /* Used: */ - HOWTO (IMAGE_REL_PPC_IFGLUE,/* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - 0, /* special_function */ - "IFGLUE", /* name */ - TRUE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - - /* IMAGE_REL_PPC_IMGLUE 0x000E */ - /* symbol is glue code; virtual address is TOC restore instruction */ - /* Unused: */ - HOWTO (IMAGE_REL_PPC_IMGLUE,/* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont, /* complain_on_overflow */ - ppc_imglue_reloc, /* special_function */ - "IMGLUE", /* name */ - FALSE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - - /* IMAGE_REL_PPC_SECREL16 0x000F */ - /* va of containing section (limited to 16 bits) */ - /* Unused: */ - HOWTO (IMAGE_REL_PPC_SECREL16,/* type */ - 0, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ - 16, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - 0, /* special_function */ - "SECREL16", /* name */ - TRUE, /* partial_inplace */ - 0xffff, /* src_mask */ - 0xffff, /* dst_mask */ - TRUE), /* pcrel_offset */ - - /* IMAGE_REL_PPC_REFHI 0x0010 */ - /* Unused: */ - HOWTO (IMAGE_REL_PPC_REFHI, /* type */ - 0, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ - 16, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - ppc_refhi_reloc, /* special_function */ - "REFHI", /* name */ - TRUE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - - /* IMAGE_REL_PPC_REFLO 0x0011 */ - /* Unused: */ - HOWTO (IMAGE_REL_PPC_REFLO, /* type */ - 0, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ - 16, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - ppc_refhi_reloc, /* special_function */ - "REFLO", /* name */ - TRUE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - - /* IMAGE_REL_PPC_PAIR 0x0012 */ - /* Unused: */ - HOWTO (IMAGE_REL_PPC_PAIR, /* type */ - 0, /* rightshift */ - 1, /* size (0 = byte, 1 = short, 2 = long) */ - 16, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_signed, /* complain_on_overflow */ - ppc_pair_reloc, /* special_function */ - "PAIR", /* name */ - TRUE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ - - /* 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 :-) */ - -#ifdef DEBUG_RELOC -#define UN_IMPL(x) \ -{ \ - static int i; \ - if (i == 0) \ - { \ - i = 1; \ - fprintf (stderr,_("Unimplemented Relocation -- %s\n"),x); \ - } \ -} - -#define DUMP_RELOC(n,r) \ -{ \ - fprintf (stderr,"%s sym %d, addr %d, addend %d\n", \ - n, (*(r->sym_ptr_ptr))->name, \ - r->address, r->addend); \ -} - -/* Given a reloc name, n, and a pointer to an internal_reloc, - dump out interesting information on the contents - -#define n_name _n._n_name -#define n_zeroes _n._n_n._n_zeroes -#define n_offset _n._n_n._n_offset */ - -#define DUMP_RELOC2(n,r) \ -{ \ - fprintf (stderr,"%s sym %d, r_vaddr %d %s\n", \ - n, r->r_symndx, r->r_vaddr, \ - (((r->r_type) & IMAGE_REL_PPC_TOCDEFN) == 0) \ - ?" ":" TOCDEFN" ); \ -} - -#else -#define UN_IMPL(x) -#define DUMP_RELOC(n,r) -#define DUMP_RELOC2(n,r) -#endif - -/* 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; - -enum toc_type -{ - default_toc, - toc_32, - toc_64 -}; - -enum ref_category -{ - priv, - pub, - tocdata -}; - -struct list_ele -{ - struct list_ele *next; - bfd_vma addr; - enum ref_category cat; - int offset; - 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. */ - size_t 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 = (struct ppc_coff_link_hash_entry *) (obj_coff_sym_hashes (abfd)[sym]); - if (h != 0) - { - HASH_CHECK(h); - } - - if (h == 0) - { - local_syms = obj_coff_local_toc_table(abfd); - - if (local_syms == 0) - { - unsigned int i; - bfd_size_type amt; - - /* allocate a table */ - 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) - { - SET_UNALLOCATED (local_syms[i]); - } - } - - if (IS_UNALLOCATED(local_syms[sym])) - { - local_syms[sym] = global_toc_size; - global_toc_size += 4; - - /* 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 - { - /* 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; - global_toc_size += 4; - - /* 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 TRUE; -} - -/* 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; - - h = (struct ppc_coff_link_hash_entry *) (obj_coff_sym_hashes (abfd)[sym]); - - HASH_CHECK(h); - - h->symbol_is_glue = 1; - h->glue_insn = bfd_get_32 (abfd, (bfd_byte *) &rel->r_vaddr); - - return; -} - -#endif /* COFF_IMAGE_WITH_PE */ - -/* Return TRUE if this relocation should - appear in the output .reloc section. */ - -static bfd_boolean -in_reloc_p (bfd * abfd ATTRIBUTE_UNUSED, - reloc_howto_type *howto) -{ - return - (! howto->pc_relative) - && (howto->type != IMAGE_REL_PPC_ADDR32NB) - && (howto->type != IMAGE_REL_PPC_TOCREL16) - && (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_boolean -write_base_file_entry (bfd *obfd, struct bfd_link_info *info, bfd_vma addr) -{ - 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; - - bfd_set_error (bfd_error_system_call); - return FALSE; -} - -/* The reloc processing routine for the optimized COFF linker. */ - -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; - asection *toc_section = 0; - bfd_vma relocation; - reloc_howto_type *howto = 0; - - /* 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 (bfd_link_relocatable (info)) - return TRUE; - - rel = relocs; - relend = rel + input_section->reloc_count; - for (; rel < relend; rel++) - { - long symndx; - struct ppc_coff_link_hash_entry *h; - struct internal_syment *sym; - bfd_vma val; - - asection *sec; - bfd_reloc_status_type rstat; - bfd_byte *loc; - - unsigned short r_type = EXTRACT_TYPE (rel->r_type); - unsigned short r_flags = EXTRACT_FLAGS(rel->r_type); - - symndx = rel->r_symndx; - loc = contents + rel->r_vaddr - input_section->vma; - - /* FIXME: check bounds on r_type */ - howto = ppc_coff_howto_table + r_type; - - if (symndx == -1) - { - h = NULL; - sym = NULL; - } - else - { - h = (struct ppc_coff_link_hash_entry *) - (obj_coff_sym_hashes (input_bfd)[symndx]); - if (h != 0) - { - 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. */ - if (h == NULL) - { - if (symndx == -1) - sec = bfd_abs_section_ptr; - else - { - sec = sections[symndx]; - val = (sec->output_section->vma - + sec->output_offset - + sym->n_value); - if (! obj_pe (output_bfd)) - val -= sec->vma; - } - } - else - { - HASH_CHECK(h); - - if (h->root.root.type == bfd_link_hash_defined - || h->root.root.type == bfd_link_hash_defweak) - { - sec = h->root.root.u.def.section; - val = (h->root.root.u.def.value - + sec->output_section->vma - + sec->output_offset); - } - else - (*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. */ - switch (r_type) - { - default: - /* xgettext: c-format */ - _bfd_error_handler (_("%pB: unsupported relocation type %#x"), - input_bfd, r_type); - bfd_set_error (bfd_error_bad_value); - return FALSE; - case IMAGE_REL_PPC_TOCREL16: - { - bfd_signed_vma our_toc_offset; - int fixit; - - DUMP_RELOC2(howto->name, rel); - - if (toc_section == 0) - { - toc_section = bfd_get_section_by_name (bfd_of_toc_owner, - TOC_SECTION_NAME); - - if ( toc_section == NULL ) - { - /* 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; - if (h == 0) - { - /* It is a file local symbol. */ - int *local_toc_table; - char name[SYMNMLEN + 1]; - - sym = syms + symndx; - 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 (IS_WRITTEN(our_toc_offset)) - { - /* If it has been written out, it is marked with the - 1 bit. Fix up our offset, but do not write it out - again. */ - MAKE_ADDR_AGAIN(our_toc_offset); - } - else - { - /* Write out the toc entry. */ - record_toc (toc_section, our_toc_offset, priv, - strdup (name)); - - bfd_put_32 (output_bfd, val, - toc_section->contents + our_toc_offset); - - MARK_AS_WRITTEN(local_toc_table[symndx]); - fixit = TRUE; - } - } - else - { - const char *name = h->root.root.root.string; - our_toc_offset = h->toc_offset; - - 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 - 1 bit. Fix up our offset, but do not write it out - again. */ - MAKE_ADDR_AGAIN(our_toc_offset); - } - else - { - record_toc(toc_section, our_toc_offset, pub, - strdup (name)); - - /* Write out the toc entry. */ - bfd_put_32 (output_bfd, val, - toc_section->contents + our_toc_offset); - - 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) - { - /* 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); - - 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) - { - _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. */ - relocation = our_toc_offset + TOC_LOAD_ADJUSTMENT; - rstat = _bfd_relocate_contents (howto, input_bfd, relocation, loc); - } - break; - case IMAGE_REL_PPC_IFGLUE: - { - /* To solve this, we need to know whether or not the symbol - appearing on the call instruction is a glue function or not. - A glue function must announce itself via a IMGLUE reloc, and - the reloc contains the required toc restore instruction. */ - 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. */ - break; - case IMAGE_REL_PPC_SECTION: - /* Unimplemented: codeview debugging information. */ - /* Is used to indicate that the value should be relative - to the beginning of the section that contains the - symbol. */ - break; - case IMAGE_REL_PPC_ABSOLUTE: - { - const char *my_name; - char buf[SYMNMLEN + 1]; - - if (h == 0) - { - strncpy (buf, (syms+symndx)->_n._n_name, SYMNMLEN); - buf[SYMNMLEN] = '\0'; - my_name = buf; - } - else - my_name = h->root.root.root.string; - - _bfd_error_handler - /* xgettext: c-format */ - (_("warning: unsupported reloc %s <file %pB, section %pA>\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; - - if (h->symbol_is_glue == 1) - break; - my_name = h->root.root.root.string; - - _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; - } - - case IMAGE_REL_PPC_ADDR32NB: - { - const char *name = 0; - - 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.root.string; - if (strcmp (".idata$2", name) == 0) - target = "__idata2_magic__"; - else if (strcmp (".idata$4", name) == 0) - target = "__idata4_magic__"; - else if (strcmp (".idata$5", name) == 0) - target = "__idata5_magic__"; - - if (target != 0) - { - struct coff_link_hash_entry *myh; - - myh = coff_link_hash_lookup (coff_hash_table (info), - 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, - loc); - } - break; - - 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, - loc); - break; - } - - if (info->base_file) - { - /* So if this is non pcrelative, and is referenced - to a section or a common symbol, then it needs a reloc. */ - if (sym && pe_data(output_bfd)->in_reloc_p (output_bfd, howto)) - { - /* Relocation to a symbol in a section which - isn't absolute - we output the address here - to a file. */ - bfd_vma addr = (rel->r_vaddr - - input_section->vma - + input_section->output_offset - + input_section->output_section->vma); - - if (!write_base_file_entry (output_bfd, info, addr)) - return FALSE; - } - } - - switch (rstat) - { - default: - abort (); - case bfd_reloc_ok: - break; - case bfd_reloc_overflow: - { - const char *name; - char buf[SYMNMLEN + 1]; - - if (symndx == -1) - name = "*ABS*"; - else if (h != NULL) - name = NULL; - else if (sym == NULL) - name = "*unknown*"; - else if (sym->_n._n_n._n_zeroes == 0 - && sym->_n._n_n._n_offset != 0) - name = obj_coff_strings (input_bfd) + sym->_n._n_n._n_offset; - else - { - strncpy (buf, sym->_n._n_name, SYMNMLEN); - buf[SYMNMLEN] = '\0'; - name = buf; - } - - (*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; -} - -#ifdef COFF_IMAGE_WITH_PE - -/* 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; - -long int import_table_size; -long int first_thunk_address; -long int thunk_size; - -struct list_ele *head; -struct list_ele *tail; - -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"); - -void -dump_toc (void * vfile) -{ - FILE *file = (FILE *) vfile; - struct list_ele *t; - - fputs (_(h1), file); - fputs (_(h2), file); - fputs (_(h3), file); - - for (t = head; t != 0; t=t->next) - { - const char *cat = ""; - - if (t->cat == priv) - cat = _("private "); - else if (t->cat == pub) - cat = _("public "); - else if (t->cat == tocdata) - cat = _("data-in-toc "); - - 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!"); - } - } - - fprintf (file, - " %04lx (%d)", (unsigned long) t->offset, t->offset - 32768); - fprintf (file, - " %s %s\n", - cat, t->name); - - } - - fprintf (file, "\n"); -} - -bfd_boolean -ppc_allocate_toc_section (struct bfd_link_info *info ATTRIBUTE_UNUSED) -{ - asection *s; - bfd_byte *foo; - static char test_char = '1'; - - 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 (); - - foo = (bfd_byte *) bfd_alloc (bfd_of_toc_owner, global_toc_size); - memset(foo, test_char, (size_t) global_toc_size); - - 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; - - /* Here we have a bfd that is to be included on the link. We have a hook - to do reloc rummaging, before section sizes are nailed down. */ - _bfd_coff_get_external_symbols (abfd); - - /* Rummage around all the relocs and map the toc. */ - sec = abfd->sections; - - if (sec == 0) - return TRUE; - - for (; sec != 0; sec = sec->next) - { - if (sec->reloc_count == 0) - continue; - - /* load the relocs */ - /* FIXME: there may be a storage leak here */ - i=_bfd_coff_read_internal_relocs(abfd,sec,1,0,0,0); - - if (i == 0) - abort (); - - for (rel = i; rel < i + sec->reloc_count; ++rel) - { - unsigned short r_type = EXTRACT_TYPE (rel->r_type); - unsigned short r_flags = EXTRACT_FLAGS (rel->r_type); - bfd_boolean ok = TRUE; - - 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; - } - } - } - - return TRUE; -} - -#endif - -static bfd_reloc_status_type -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); - - if (output_bfd == (bfd *) NULL) - return bfd_reloc_continue; - - return bfd_reloc_undefined; -} - -static bfd_reloc_status_type -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); - - if (output_bfd == (bfd *) NULL) - return bfd_reloc_continue; - - return bfd_reloc_undefined; -} - -static bfd_reloc_status_type -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); - - if (output_bfd == (bfd *) NULL) - return bfd_reloc_continue; - - return bfd_reloc_ok; -} - -static bfd_reloc_status_type -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); - - if (output_bfd == (bfd *) NULL) - return bfd_reloc_continue; - - return bfd_reloc_ok; -} - -static bfd_reloc_status_type -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); - - if (output_bfd == (bfd *) NULL) - return bfd_reloc_continue; - - return bfd_reloc_ok; -} - -static bfd_reloc_status_type -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); - - if (output_bfd == (bfd *) NULL) - return bfd_reloc_continue; - - return bfd_reloc_ok; -} - -#define MAX_RELOC_INDEX \ - (sizeof (ppc_coff_howto_table) / sizeof (ppc_coff_howto_table[0]) - 1) - -/* FIXME: There is a 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 (arelent *relent, struct internal_reloc *internal) -{ - /* We can encode one of three things in the type field, aside from the - type: - 1. IMAGE_REL_PPC_NEG - indicates the value field is a subtraction - value, rather than an addition value - 2. IMAGE_REL_PPC_BRTAKEN, IMAGE_REL_PPC_BRNTAKEN - indicates that - the branch is expected to be taken or not. - 3. IMAGE_REL_PPC_TOCDEFN - toc slot definition in the file - For now, we just strip this stuff to find the type, and ignore it other - than that. */ - 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 ) - abort (); - - /* Check for absolute crap. */ - if (junk != 0) - abort (); - - switch(r_type) - { - case IMAGE_REL_PPC_ADDR16: - case IMAGE_REL_PPC_REL24: - case IMAGE_REL_PPC_ADDR24: - 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); - howto = ppc_coff_howto_table + r_type; - break; - case IMAGE_REL_PPC_IMGLUE: - 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: - _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 = howto; -} - -static reloc_howto_type * -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 - 2. IMAGE_REL_PPC_BRTAKEN, IMAGE_REL_PPC_BRNTAKEN - indicates that - the branch is expected to be taken or not. - 3. IMAGE_REL_PPC_TOCDEFN - toc slot definition in the file - For now, we just strip this stuff to find the type, and ignore it other - than that. */ - - unsigned short r_type = EXTRACT_TYPE (rel->r_type); - unsigned short r_flags = EXTRACT_FLAGS (rel->r_type); - unsigned short junk = EXTRACT_JUNK (rel->r_type); - - /* The masking process only slices off the bottom byte for r_type. */ - if (r_type > MAX_RELOC_INDEX) - abort (); - - /* 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_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); - howto = ppc_coff_howto_table + r_type; - break; - default: - _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; - } - - return howto; -} - -/* A cheesy little macro to make the code a little more readable. */ -#define HOW2MAP(bfd_rtype,ppc_rtype) \ - case bfd_rtype: return &ppc_coff_howto_table[ppc_rtype] - -static reloc_howto_type * -ppc_coff_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, - bfd_reloc_code_real_type code) -{ - 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_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_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; - } -} -#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. */ - -#define RTYPE2HOWTO(cache_ptr, dst) ppc_coff_rtype2howto (cache_ptr, dst) - -/* 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_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 -#endif - -#define SELECT_RELOC(internal, howto) {internal.r_type=howto->type;} - -#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 - -#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 bfd_boolean -ppc_do_last (bfd *abfd) -{ - if (abfd == bfd_of_toc_owner) - return TRUE; - else - return FALSE; -} - -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 */ - -/* 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) - { - o->reloc_count = 0; - o->lineno_count = 0; - - for (p = o->map_head.link_order; p != NULL; p = p->next) - { - 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; - } - - 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 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 - - /* Free up the buffers used by _bfd_coff_link_input_bfd. */ - coff_debug_merge_hash_table_free (&flaginfo.debug_merge); - debug_merge_allocated = FALSE; - - free (flaginfo.internal_syms); - flaginfo.internal_syms = NULL; - free (flaginfo.sec_ptrs); - flaginfo.sec_ptrs = NULL; - free (flaginfo.sym_indices); - flaginfo.sym_indices = NULL; - free (flaginfo.linenos); - flaginfo.linenos = NULL; - free (flaginfo.contents); - flaginfo.contents = NULL; - free (flaginfo.external_relocs); - flaginfo.external_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; - } - - /* 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. */ - 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) - { - 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; - } - - free (external_relocs); - external_relocs = NULL; - } - - /* Free up the section information. */ - if (flaginfo.section_info != NULL) - { - unsigned int i; - - for (i = 0; i < abfd->section_count; i++) - { - free (flaginfo.section_info[i].relocs); - 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++) - { - free (flaginfo.section_info[i].relocs); - free (flaginfo.section_info[i].rel_hashes); - } - free (flaginfo.section_info); - } - free (flaginfo.internal_syms); - free (flaginfo.sec_ptrs); - free (flaginfo.sym_indices); - free (flaginfo.outsyms); - free (flaginfo.linenos); - free (flaginfo.contents); - free (flaginfo.external_relocs); - free (flaginfo.internal_relocs); - 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. */ - -#ifdef TARGET_LITTLE_SYM -const bfd_target TARGET_LITTLE_SYM = -{ - TARGET_LITTLE_NAME, /* name or coff-arm-little */ - bfd_target_coff_flavour, - 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, - bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */ - - bfd_getl64, bfd_getl_signed_64, bfd_putl64, - bfd_getl32, bfd_getl_signed_32, bfd_putl32, - bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */ - - { /* bfd_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), - BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff), - BFD_JUMP_TABLE_SYMBOLS (coff), - BFD_JUMP_TABLE_RELOCS (coff), - BFD_JUMP_TABLE_WRITE (coff), - BFD_JUMP_TABLE_LINK (coff), - BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), - - /* 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 = -{ - TARGET_BIG_NAME, - 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 | 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_getb64, bfd_getb_signed_64, bfd_putb64, - bfd_getb32, bfd_getb_signed_32, bfd_putb32, - bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */ - - bfd_getb64, bfd_getb_signed_64, bfd_putb64, - bfd_getb32, bfd_getb_signed_32, bfd_putb32, - bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */ - - { /* bfd_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), - BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff), - BFD_JUMP_TABLE_SYMBOLS (coff), - BFD_JUMP_TABLE_RELOCS (coff), - BFD_JUMP_TABLE_WRITE (coff), - BFD_JUMP_TABLE_LINK (coff), - BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), - - /* Alternative_target. */ -#ifdef TARGET_LITTLE_SYM - &TARGET_LITTLE_SYM, -#else - NULL, -#endif - - COFF_SWAP_TABLE -}; - -#endif |