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