pe-mips.c revision 179407
1179407Sobrien/* BFD back-end for MIPS PE COFF files. 2179407Sobrien Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 3179407Sobrien 2000, 2001, 2002, 2003 Free Software Foundation, Inc. 4179407Sobrien Modified from coff-i386.c by DJ Delorie, dj@cygnus.com 5179407Sobrien 6179407SobrienThis file is part of BFD, the Binary File Descriptor library. 7179407Sobrien 8179407SobrienThis program is free software; you can redistribute it and/or modify 9179407Sobrienit under the terms of the GNU General Public License as published by 10179407Sobrienthe Free Software Foundation; either version 2 of the License, or 11179407Sobrien(at your option) any later version. 12179407Sobrien 13179407SobrienThis program is distributed in the hope that it will be useful, 14179407Sobrienbut WITHOUT ANY WARRANTY; without even the implied warranty of 15179407SobrienMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16179407SobrienGNU General Public License for more details. 17179407Sobrien 18179407SobrienYou should have received a copy of the GNU General Public License 19179407Sobrienalong with this program; if not, write to the Free Software 20179407SobrienFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 21179407Sobrien 22179407Sobrien#define COFF_WITH_PE 23179407Sobrien#define COFF_LONG_SECTION_NAMES 24179407Sobrien#define PCRELOFFSET TRUE 25179407Sobrien 26179407Sobrien#include "bfd.h" 27179407Sobrien#include "sysdep.h" 28179407Sobrien#include "libbfd.h" 29179407Sobrien 30179407Sobrien#include "coff/mipspe.h" 31179407Sobrien 32179407Sobrien#include "coff/internal.h" 33179407Sobrien 34179407Sobrien#include "coff/pe.h" 35179407Sobrien 36179407Sobrien#include "libcoff.h" 37179407Sobrien 38179407Sobrienstatic bfd_reloc_status_type coff_mips_reloc 39179407Sobrien PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); 40179407Sobrienstatic reloc_howto_type *coff_mips_rtype_to_howto 41179407Sobrien PARAMS ((bfd *, asection *, struct internal_reloc *, 42179407Sobrien struct coff_link_hash_entry *, struct internal_syment *, 43179407Sobrien bfd_vma *)); 44179407Sobrien#if 0 45179407Sobrienstatic void mips_ecoff_swap_reloc_in 46179407Sobrien PARAMS ((bfd *, PTR, struct internal_reloc *)); 47179407Sobrienstatic void mips_ecoff_swap_reloc_out 48179407Sobrien PARAMS ((bfd *, const struct internal_reloc *, PTR)); 49179407Sobrienstatic void mips_adjust_reloc_in 50179407Sobrien PARAMS ((bfd *, const struct internal_reloc *, arelent *)); 51179407Sobrienstatic void mips_adjust_reloc_out 52179407Sobrien PARAMS ((bfd *, const arelent *, struct internal_reloc *)); 53179407Sobrien#endif 54179407Sobrien 55179407Sobrienstatic bfd_boolean in_reloc_p 56179407Sobrien PARAMS ((bfd *, reloc_howto_type *)); 57179407Sobrienstatic reloc_howto_type * coff_mips_reloc_type_lookup 58179407Sobrien PARAMS ((bfd *, bfd_reloc_code_real_type)); 59179407Sobrienstatic void mips_swap_reloc_in 60179407Sobrien PARAMS ((bfd *, PTR, PTR)); 61179407Sobrienstatic unsigned int mips_swap_reloc_out 62179407Sobrien PARAMS ((bfd *, PTR, PTR)); 63179407Sobrienstatic bfd_boolean coff_pe_mips_relocate_section 64179407Sobrien PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, 65179407Sobrien struct internal_reloc *, struct internal_syment *, asection **)); 66179407Sobrien 67179407Sobrien#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2) 68179407Sobrien/* The page size is a guess based on ELF. */ 69179407Sobrien 70179407Sobrien#define COFF_PAGE_SIZE 0x1000 71179407Sobrien 72179407Sobrien/* For some reason when using mips COFF the value stored in the .text 73179407Sobrien section for a reference to a common symbol is the value itself plus 74179407Sobrien any desired offset. Ian Taylor, Cygnus Support. */ 75179407Sobrien 76179407Sobrien/* If we are producing relocatable output, we need to do some 77179407Sobrien adjustments to the object file that are not done by the 78179407Sobrien bfd_perform_relocation function. This function is called by every 79179407Sobrien reloc type to make any required adjustments. */ 80179407Sobrien 81179407Sobrienstatic bfd_reloc_status_type 82179407Sobriencoff_mips_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd, 83179407Sobrien error_message) 84179407Sobrien bfd *abfd; 85179407Sobrien arelent *reloc_entry; 86179407Sobrien asymbol *symbol; 87179407Sobrien PTR data; 88179407Sobrien asection *input_section ATTRIBUTE_UNUSED; 89179407Sobrien bfd *output_bfd; 90179407Sobrien char **error_message ATTRIBUTE_UNUSED; 91179407Sobrien{ 92179407Sobrien symvalue diff; 93179407Sobrien 94179407Sobrien if (output_bfd == (bfd *) NULL) 95179407Sobrien return bfd_reloc_continue; 96179407Sobrien 97179407Sobrien if (bfd_is_com_section (symbol->section)) 98179407Sobrien { 99179407Sobrien#ifndef COFF_WITH_PE 100179407Sobrien /* We are relocating a common symbol. The current value in the 101179407Sobrien object file is ORIG + OFFSET, where ORIG is the value of the 102179407Sobrien common symbol as seen by the object file when it was compiled 103179407Sobrien (this may be zero if the symbol was undefined) and OFFSET is 104179407Sobrien the offset into the common symbol (normally zero, but may be 105179407Sobrien non-zero when referring to a field in a common structure). 106179407Sobrien ORIG is the negative of reloc_entry->addend, which is set by 107179407Sobrien the CALC_ADDEND macro below. We want to replace the value in 108179407Sobrien the object file with NEW + OFFSET, where NEW is the value of 109179407Sobrien the common symbol which we are going to put in the final 110179407Sobrien object file. NEW is symbol->value. */ 111179407Sobrien diff = symbol->value + reloc_entry->addend; 112179407Sobrien#else 113179407Sobrien /* In PE mode, we do not offset the common symbol. */ 114179407Sobrien diff = reloc_entry->addend; 115179407Sobrien#endif 116179407Sobrien } 117179407Sobrien else 118179407Sobrien { 119179407Sobrien /* For some reason bfd_perform_relocation always effectively 120179407Sobrien ignores the addend for a COFF target when producing 121179407Sobrien relocatable output. This seems to be always wrong for 386 122179407Sobrien COFF, so we handle the addend here instead. */ 123179407Sobrien diff = reloc_entry->addend; 124179407Sobrien } 125179407Sobrien 126179407Sobrien#ifdef COFF_WITH_PE 127179407Sobrien#if 0 128179407Sobrien /* dj - handle it like any other reloc? */ 129179407Sobrien /* FIXME: How should this case be handled? */ 130179407Sobrien if (reloc_entry->howto->type == MIPS_R_RVA && diff != 0) 131179407Sobrien abort (); 132179407Sobrien#endif 133179407Sobrien#endif 134179407Sobrien 135179407Sobrien#define DOIT(x) \ 136179407Sobrien x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + (diff >> howto->rightshift)) & howto->dst_mask)) 137179407Sobrien 138179407Sobrien if (diff != 0) 139179407Sobrien { 140179407Sobrien reloc_howto_type *howto = reloc_entry->howto; 141179407Sobrien unsigned char *addr = (unsigned char *) data + reloc_entry->address; 142179407Sobrien 143179407Sobrien switch (howto->size) 144179407Sobrien { 145179407Sobrien case 0: 146179407Sobrien { 147179407Sobrien char x = bfd_get_8 (abfd, addr); 148179407Sobrien DOIT (x); 149179407Sobrien bfd_put_8 (abfd, x, addr); 150179407Sobrien } 151179407Sobrien break; 152179407Sobrien 153179407Sobrien case 1: 154179407Sobrien { 155179407Sobrien short x = bfd_get_16 (abfd, addr); 156179407Sobrien DOIT (x); 157179407Sobrien bfd_put_16 (abfd, (bfd_vma) x, addr); 158179407Sobrien } 159179407Sobrien break; 160179407Sobrien 161179407Sobrien case 2: 162179407Sobrien { 163179407Sobrien long x = bfd_get_32 (abfd, addr); 164179407Sobrien DOIT (x); 165179407Sobrien bfd_put_32 (abfd, (bfd_vma) x, addr); 166179407Sobrien } 167179407Sobrien break; 168179407Sobrien 169179407Sobrien default: 170179407Sobrien abort (); 171179407Sobrien } 172179407Sobrien } 173179407Sobrien 174179407Sobrien /* Now let bfd_perform_relocation finish everything up. */ 175179407Sobrien return bfd_reloc_continue; 176179407Sobrien} 177179407Sobrien 178179407Sobrien#ifdef COFF_WITH_PE 179179407Sobrien/* Return TRUE if this relocation should 180179407Sobrien appear in the output .reloc section. */ 181179407Sobrien 182179407Sobrienstatic bfd_boolean 183179407Sobrienin_reloc_p (abfd, howto) 184179407Sobrien bfd * abfd ATTRIBUTE_UNUSED; 185179407Sobrien reloc_howto_type *howto; 186179407Sobrien{ 187179407Sobrien return ! howto->pc_relative && howto->type != MIPS_R_RVA; 188179407Sobrien} 189179407Sobrien#endif 190179407Sobrien 191179407Sobrien#ifndef PCRELOFFSET 192179407Sobrien#define PCRELOFFSET FALSE 193179407Sobrien#endif 194179407Sobrien 195179407Sobrienstatic reloc_howto_type howto_table[] = 196179407Sobrien{ 197179407Sobrien /* Reloc type 0 is ignored. The reloc reading code ensures that 198179407Sobrien this is a reference to the .abs section, which will cause 199179407Sobrien bfd_perform_relocation to do nothing. */ 200179407Sobrien HOWTO (MIPS_R_ABSOLUTE, /* type */ 201179407Sobrien 0, /* rightshift */ 202179407Sobrien 0, /* size (0 = byte, 1 = short, 2 = long) */ 203179407Sobrien 8, /* bitsize */ 204179407Sobrien FALSE, /* pc_relative */ 205179407Sobrien 0, /* bitpos */ 206179407Sobrien complain_overflow_dont, /* complain_on_overflow */ 207179407Sobrien 0, /* special_function */ 208179407Sobrien "IGNORE", /* name */ 209179407Sobrien FALSE, /* partial_inplace */ 210179407Sobrien 0, /* src_mask */ 211179407Sobrien 0, /* dst_mask */ 212179407Sobrien FALSE), /* pcrel_offset */ 213179407Sobrien 214179407Sobrien /* A 16 bit reference to a symbol, normally from a data section. */ 215179407Sobrien HOWTO (MIPS_R_REFHALF, /* type */ 216179407Sobrien 0, /* rightshift */ 217179407Sobrien 1, /* size (0 = byte, 1 = short, 2 = long) */ 218179407Sobrien 16, /* bitsize */ 219179407Sobrien FALSE, /* pc_relative */ 220179407Sobrien 0, /* bitpos */ 221179407Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 222179407Sobrien coff_mips_reloc, /* special_function */ 223179407Sobrien "REFHALF", /* name */ 224179407Sobrien TRUE, /* partial_inplace */ 225179407Sobrien 0xffff, /* src_mask */ 226179407Sobrien 0xffff, /* dst_mask */ 227179407Sobrien FALSE), /* pcrel_offset */ 228179407Sobrien 229179407Sobrien /* A 32 bit reference to a symbol, normally from a data section. */ 230179407Sobrien HOWTO (MIPS_R_REFWORD, /* type */ 231179407Sobrien 0, /* rightshift */ 232179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 233179407Sobrien 32, /* bitsize */ 234179407Sobrien FALSE, /* pc_relative */ 235179407Sobrien 0, /* bitpos */ 236179407Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 237179407Sobrien coff_mips_reloc, /* special_function */ 238179407Sobrien "REFWORD", /* name */ 239179407Sobrien TRUE, /* partial_inplace */ 240179407Sobrien 0xffffffff, /* src_mask */ 241179407Sobrien 0xffffffff, /* dst_mask */ 242179407Sobrien FALSE), /* pcrel_offset */ 243179407Sobrien 244179407Sobrien /* A 26 bit absolute jump address. */ 245179407Sobrien HOWTO (MIPS_R_JMPADDR, /* type */ 246179407Sobrien 2, /* rightshift */ 247179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 248179407Sobrien 26, /* bitsize */ 249179407Sobrien FALSE, /* pc_relative */ 250179407Sobrien 0, /* bitpos */ 251179407Sobrien complain_overflow_dont, /* complain_on_overflow */ 252179407Sobrien /* This needs complex overflow 253179407Sobrien detection, because the upper four 254179407Sobrien bits must match the PC. */ 255179407Sobrien coff_mips_reloc, /* special_function */ 256179407Sobrien "JMPADDR", /* name */ 257179407Sobrien TRUE, /* partial_inplace */ 258179407Sobrien 0x3ffffff, /* src_mask */ 259179407Sobrien 0x3ffffff, /* dst_mask */ 260179407Sobrien FALSE), /* pcrel_offset */ 261179407Sobrien 262179407Sobrien /* The high 16 bits of a symbol value. Handled by the function 263179407Sobrien mips_refhi_reloc. */ 264179407Sobrien HOWTO (MIPS_R_REFHI, /* type */ 265179407Sobrien 16, /* rightshift */ 266179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 267179407Sobrien 16, /* bitsize */ 268179407Sobrien FALSE, /* pc_relative */ 269179407Sobrien 0, /* bitpos */ 270179407Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 271179407Sobrien coff_mips_reloc, /* special_function */ 272179407Sobrien "REFHI", /* name */ 273179407Sobrien TRUE, /* partial_inplace */ 274179407Sobrien 0xffff, /* src_mask */ 275179407Sobrien 0xffff, /* dst_mask */ 276179407Sobrien FALSE), /* pcrel_offset */ 277179407Sobrien 278179407Sobrien /* The low 16 bits of a symbol value. */ 279179407Sobrien HOWTO (MIPS_R_REFLO, /* type */ 280179407Sobrien 0, /* rightshift */ 281179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 282179407Sobrien 16, /* bitsize */ 283179407Sobrien FALSE, /* pc_relative */ 284179407Sobrien 0, /* bitpos */ 285179407Sobrien complain_overflow_dont, /* complain_on_overflow */ 286179407Sobrien coff_mips_reloc, /* special_function */ 287179407Sobrien "REFLO", /* name */ 288179407Sobrien TRUE, /* partial_inplace */ 289179407Sobrien 0xffff, /* src_mask */ 290179407Sobrien 0xffff, /* dst_mask */ 291179407Sobrien FALSE), /* pcrel_offset */ 292179407Sobrien 293179407Sobrien /* A reference to an offset from the gp register. Handled by the 294179407Sobrien function mips_gprel_reloc. */ 295179407Sobrien HOWTO (MIPS_R_GPREL, /* type */ 296179407Sobrien 0, /* rightshift */ 297179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 298179407Sobrien 16, /* bitsize */ 299179407Sobrien FALSE, /* pc_relative */ 300179407Sobrien 0, /* bitpos */ 301179407Sobrien complain_overflow_signed, /* complain_on_overflow */ 302179407Sobrien coff_mips_reloc, /* special_function */ 303179407Sobrien "GPREL", /* name */ 304179407Sobrien TRUE, /* partial_inplace */ 305179407Sobrien 0xffff, /* src_mask */ 306179407Sobrien 0xffff, /* dst_mask */ 307179407Sobrien FALSE), /* pcrel_offset */ 308179407Sobrien 309179407Sobrien /* A reference to a literal using an offset from the gp register. 310179407Sobrien Handled by the function mips_gprel_reloc. */ 311179407Sobrien HOWTO (MIPS_R_LITERAL, /* type */ 312179407Sobrien 0, /* rightshift */ 313179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 314179407Sobrien 16, /* bitsize */ 315179407Sobrien FALSE, /* pc_relative */ 316179407Sobrien 0, /* bitpos */ 317179407Sobrien complain_overflow_signed, /* complain_on_overflow */ 318179407Sobrien coff_mips_reloc, /* special_function */ 319179407Sobrien "LITERAL", /* name */ 320179407Sobrien TRUE, /* partial_inplace */ 321179407Sobrien 0xffff, /* src_mask */ 322179407Sobrien 0xffff, /* dst_mask */ 323179407Sobrien FALSE), /* pcrel_offset */ 324179407Sobrien 325179407Sobrien EMPTY_HOWTO (8), 326179407Sobrien EMPTY_HOWTO (9), 327179407Sobrien EMPTY_HOWTO (10), 328179407Sobrien EMPTY_HOWTO (11), 329179407Sobrien EMPTY_HOWTO (12), 330179407Sobrien EMPTY_HOWTO (13), 331179407Sobrien EMPTY_HOWTO (14), 332179407Sobrien EMPTY_HOWTO (15), 333179407Sobrien EMPTY_HOWTO (16), 334179407Sobrien EMPTY_HOWTO (17), 335179407Sobrien EMPTY_HOWTO (18), 336179407Sobrien EMPTY_HOWTO (19), 337179407Sobrien EMPTY_HOWTO (20), 338179407Sobrien EMPTY_HOWTO (21), 339179407Sobrien EMPTY_HOWTO (22), 340179407Sobrien EMPTY_HOWTO (23), 341179407Sobrien EMPTY_HOWTO (24), 342179407Sobrien EMPTY_HOWTO (25), 343179407Sobrien EMPTY_HOWTO (26), 344179407Sobrien EMPTY_HOWTO (27), 345179407Sobrien EMPTY_HOWTO (28), 346179407Sobrien EMPTY_HOWTO (29), 347179407Sobrien EMPTY_HOWTO (30), 348179407Sobrien EMPTY_HOWTO (31), 349179407Sobrien EMPTY_HOWTO (32), 350179407Sobrien EMPTY_HOWTO (33), 351179407Sobrien HOWTO (MIPS_R_RVA, /* type */ 352179407Sobrien 0, /* rightshift */ 353179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 354179407Sobrien 32, /* bitsize */ 355179407Sobrien FALSE, /* pc_relative */ 356179407Sobrien 0, /* bitpos */ 357179407Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 358179407Sobrien coff_mips_reloc, /* special_function */ 359179407Sobrien "rva32", /* name */ 360179407Sobrien TRUE, /* partial_inplace */ 361179407Sobrien 0xffffffff, /* src_mask */ 362179407Sobrien 0xffffffff, /* dst_mask */ 363179407Sobrien FALSE), /* pcrel_offset */ 364179407Sobrien EMPTY_HOWTO (35), 365179407Sobrien EMPTY_HOWTO (36), 366179407Sobrien HOWTO (MIPS_R_PAIR, /* type */ 367179407Sobrien 0, /* rightshift */ 368179407Sobrien 2, /* size (0 = byte, 1 = short, 2 = long) */ 369179407Sobrien 32, /* bitsize */ 370179407Sobrien FALSE, /* pc_relative */ 371179407Sobrien 0, /* bitpos */ 372179407Sobrien complain_overflow_bitfield, /* complain_on_overflow */ 373179407Sobrien coff_mips_reloc, /* special_function */ 374179407Sobrien "PAIR", /* name */ 375179407Sobrien TRUE, /* partial_inplace */ 376179407Sobrien 0xffffffff, /* src_mask */ 377179407Sobrien 0xffffffff, /* dst_mask */ 378179407Sobrien FALSE), /* pcrel_offset */ 379179407Sobrien}; 380179407Sobrien 381179407Sobrien/* Turn a howto into a reloc nunmber */ 382179407Sobrien 383179407Sobrien#define SELECT_RELOC(x,howto) { x.r_type = howto->type; } 384179407Sobrien#define BADMAG(x) MIPSBADMAG(x) 385179407Sobrien#define MIPS 1 /* Customize coffcode.h */ 386179407Sobrien 387179407Sobrien#define RTYPE2HOWTO(cache_ptr, dst) \ 388179407Sobrien (cache_ptr)->howto = howto_table + (dst)->r_type; 389179407Sobrien 390179407Sobrien/* Compute the addend of a reloc. If the reloc is to a common symbol, 391179407Sobrien the object file contains the value of the common symbol. By the 392179407Sobrien time this is called, the linker may be using a different symbol 393179407Sobrien from a different object file with a different value. Therefore, we 394179407Sobrien hack wildly to locate the original symbol from this file so that we 395179407Sobrien can make the correct adjustment. This macro sets coffsym to the 396179407Sobrien symbol from the original file, and uses it to set the addend value 397179407Sobrien correctly. If this is not a common symbol, the usual addend 398179407Sobrien calculation is done, except that an additional tweak is needed for 399179407Sobrien PC relative relocs. 400179407Sobrien FIXME: This macro refers to symbols and asect; these are from the 401179407Sobrien calling function, not the macro arguments. */ 402179407Sobrien 403179407Sobrien#define CALC_ADDEND(abfd, ptr, reloc, cache_ptr) \ 404179407Sobrien { \ 405179407Sobrien coff_symbol_type *coffsym = (coff_symbol_type *) NULL; \ 406179407Sobrien if (ptr && bfd_asymbol_bfd (ptr) != abfd) \ 407179407Sobrien coffsym = (obj_symbols (abfd) \ 408179407Sobrien + (cache_ptr->sym_ptr_ptr - symbols)); \ 409179407Sobrien else if (ptr) \ 410179407Sobrien coffsym = coff_symbol_from (abfd, ptr); \ 411179407Sobrien if (coffsym != (coff_symbol_type *) NULL \ 412179407Sobrien && coffsym->native->u.syment.n_scnum == 0) \ 413179407Sobrien cache_ptr->addend = - coffsym->native->u.syment.n_value; \ 414179407Sobrien else if (ptr && bfd_asymbol_bfd (ptr) == abfd \ 415179407Sobrien && ptr->section != (asection *) NULL) \ 416179407Sobrien cache_ptr->addend = - (ptr->section->vma + ptr->value); \ 417179407Sobrien else \ 418179407Sobrien cache_ptr->addend = 0; \ 419179407Sobrien if (ptr && howto_table[reloc.r_type].pc_relative) \ 420179407Sobrien cache_ptr->addend += asect->vma; \ 421179407Sobrien } 422179407Sobrien 423179407Sobrien/* Convert an rtype to howto for the COFF backend linker. */ 424179407Sobrien 425179407Sobrienstatic reloc_howto_type * 426179407Sobriencoff_mips_rtype_to_howto (abfd, sec, rel, h, sym, addendp) 427179407Sobrien bfd *abfd ATTRIBUTE_UNUSED; 428179407Sobrien asection *sec; 429179407Sobrien struct internal_reloc *rel; 430179407Sobrien struct coff_link_hash_entry *h; 431179407Sobrien struct internal_syment *sym; 432179407Sobrien bfd_vma *addendp; 433179407Sobrien{ 434179407Sobrien 435179407Sobrien reloc_howto_type *howto; 436179407Sobrien 437179407Sobrien howto = howto_table + rel->r_type; 438179407Sobrien 439179407Sobrien#ifdef COFF_WITH_PE 440179407Sobrien *addendp = 0; 441179407Sobrien#endif 442179407Sobrien 443179407Sobrien if (howto->pc_relative) 444179407Sobrien *addendp += sec->vma; 445179407Sobrien 446179407Sobrien if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0) 447179407Sobrien { 448179407Sobrien /* This is a common symbol. The section contents include the 449179407Sobrien size (sym->n_value) as an addend. The relocate_section 450179407Sobrien function will be adding in the final value of the symbol. We 451179407Sobrien need to subtract out the current size in order to get the 452179407Sobrien correct result. */ 453179407Sobrien 454179407Sobrien BFD_ASSERT (h != NULL); 455179407Sobrien 456179407Sobrien#ifndef COFF_WITH_PE 457179407Sobrien /* I think we *do* want to bypass this. If we don't, I have 458179407Sobrien seen some data parameters get the wrong relocation address. 459179407Sobrien If I link two versions with and without this section bypassed 460179407Sobrien and then do a binary comparison, the addresses which are 461179407Sobrien different can be looked up in the map. The case in which 462179407Sobrien this section has been bypassed has addresses which correspond 463179407Sobrien to values I can find in the map. */ 464179407Sobrien *addendp -= sym->n_value; 465179407Sobrien#endif 466179407Sobrien } 467179407Sobrien 468179407Sobrien#ifndef COFF_WITH_PE 469179407Sobrien /* If the output symbol is common (in which case this must be a 470179407Sobrien relocatable link), we need to add in the final size of the 471179407Sobrien common symbol. */ 472179407Sobrien if (h != NULL && h->root.type == bfd_link_hash_common) 473179407Sobrien *addendp += h->root.u.c.size; 474179407Sobrien#endif 475179407Sobrien 476179407Sobrien#ifdef COFF_WITH_PE 477179407Sobrien if (howto->pc_relative) 478179407Sobrien { 479179407Sobrien *addendp -= 4; 480179407Sobrien 481179407Sobrien /* If the symbol is defined, then the generic code is going to 482179407Sobrien add back the symbol value in order to cancel out an 483179407Sobrien adjustment it made to the addend. However, we set the addend 484179407Sobrien to 0 at the start of this function. We need to adjust here, 485179407Sobrien to avoid the adjustment the generic code will make. FIXME: 486179407Sobrien This is getting a bit hackish. */ 487179407Sobrien if (sym != NULL && sym->n_scnum != 0) 488179407Sobrien *addendp -= sym->n_value; 489179407Sobrien } 490179407Sobrien 491179407Sobrien if (rel->r_type == MIPS_R_RVA) 492179407Sobrien { 493179407Sobrien *addendp -= pe_data(sec->output_section->owner)->pe_opthdr.ImageBase; 494179407Sobrien } 495179407Sobrien#endif 496179407Sobrien 497179407Sobrien return howto; 498179407Sobrien} 499179407Sobrien 500179407Sobrien#define coff_rtype_to_howto coff_mips_rtype_to_howto 501179407Sobrien 502179407Sobrien#define coff_bfd_reloc_type_lookup coff_mips_reloc_type_lookup 503179407Sobrien 504179407Sobrien/* Get the howto structure for a generic reloc type. */ 505179407Sobrien 506179407Sobrienstatic reloc_howto_type * 507179407Sobriencoff_mips_reloc_type_lookup (abfd, code) 508179407Sobrien bfd *abfd ATTRIBUTE_UNUSED; 509179407Sobrien bfd_reloc_code_real_type code; 510179407Sobrien{ 511179407Sobrien int mips_type; 512179407Sobrien 513179407Sobrien switch (code) 514179407Sobrien { 515179407Sobrien case BFD_RELOC_16: 516179407Sobrien mips_type = MIPS_R_REFHALF; 517179407Sobrien break; 518179407Sobrien case BFD_RELOC_32: 519179407Sobrien case BFD_RELOC_CTOR: 520179407Sobrien mips_type = MIPS_R_REFWORD; 521179407Sobrien break; 522179407Sobrien case BFD_RELOC_MIPS_JMP: 523179407Sobrien mips_type = MIPS_R_JMPADDR; 524179407Sobrien break; 525179407Sobrien case BFD_RELOC_HI16_S: 526179407Sobrien mips_type = MIPS_R_REFHI; 527179407Sobrien break; 528179407Sobrien case BFD_RELOC_LO16: 529179407Sobrien mips_type = MIPS_R_REFLO; 530179407Sobrien break; 531179407Sobrien case BFD_RELOC_GPREL16: 532179407Sobrien mips_type = MIPS_R_GPREL; 533179407Sobrien break; 534179407Sobrien case BFD_RELOC_MIPS_LITERAL: 535179407Sobrien mips_type = MIPS_R_LITERAL; 536179407Sobrien break; 537179407Sobrien/* FIXME? 538179407Sobrien case BFD_RELOC_16_PCREL_S2: 539179407Sobrien mips_type = MIPS_R_PCREL16; 540179407Sobrien break; 541179407Sobrien case BFD_RELOC_PCREL_HI16_S: 542179407Sobrien mips_type = MIPS_R_RELHI; 543179407Sobrien break; 544179407Sobrien case BFD_RELOC_PCREL_LO16: 545179407Sobrien mips_type = MIPS_R_RELLO; 546179407Sobrien break; 547179407Sobrien case BFD_RELOC_GPREL32: 548179407Sobrien mips_type = MIPS_R_SWITCH; 549179407Sobrien break; 550179407Sobrien*/ 551179407Sobrien case BFD_RELOC_RVA: 552179407Sobrien mips_type = MIPS_R_RVA; 553179407Sobrien break; 554179407Sobrien default: 555179407Sobrien return (reloc_howto_type *) NULL; 556179407Sobrien } 557179407Sobrien 558179407Sobrien return &howto_table[mips_type]; 559179407Sobrien} 560179407Sobrien 561179407Sobrienstatic void 562179407Sobrienmips_swap_reloc_in (abfd, src, dst) 563179407Sobrien bfd *abfd; 564179407Sobrien PTR src; 565179407Sobrien PTR dst; 566179407Sobrien{ 567179407Sobrien static struct internal_reloc pair_prev; 568179407Sobrien RELOC *reloc_src = (RELOC *) src; 569179407Sobrien struct internal_reloc *reloc_dst = (struct internal_reloc *) dst; 570179407Sobrien 571179407Sobrien reloc_dst->r_vaddr = H_GET_32 (abfd, reloc_src->r_vaddr); 572179407Sobrien reloc_dst->r_symndx = H_GET_S32 (abfd, reloc_src->r_symndx); 573179407Sobrien reloc_dst->r_type = H_GET_16 (abfd, reloc_src->r_type); 574179407Sobrien reloc_dst->r_size = 0; 575179407Sobrien reloc_dst->r_extern = 0; 576179407Sobrien reloc_dst->r_offset = 0; 577179407Sobrien 578179407Sobrien switch (reloc_dst->r_type) 579179407Sobrien { 580179407Sobrien case MIPS_R_REFHI: 581179407Sobrien pair_prev = *reloc_dst; 582179407Sobrien break; 583179407Sobrien case MIPS_R_PAIR: 584179407Sobrien reloc_dst->r_offset = reloc_dst->r_symndx; 585179407Sobrien if (reloc_dst->r_offset & 0x8000) 586179407Sobrien reloc_dst->r_offset -= 0x10000; 587179407Sobrien /*printf ("dj: pair offset is %08x\n", reloc_dst->r_offset);*/ 588179407Sobrien reloc_dst->r_symndx = pair_prev.r_symndx; 589179407Sobrien break; 590179407Sobrien } 591179407Sobrien} 592179407Sobrien 593179407Sobrienstatic unsigned int 594179407Sobrienmips_swap_reloc_out (abfd, src, dst) 595179407Sobrien bfd *abfd; 596179407Sobrien PTR src; 597179407Sobrien PTR dst; 598179407Sobrien{ 599179407Sobrien static int prev_offset = 1; 600179407Sobrien static bfd_vma prev_addr = 0; 601179407Sobrien struct internal_reloc *reloc_src = (struct internal_reloc *)src; 602179407Sobrien struct external_reloc *reloc_dst = (struct external_reloc *)dst; 603179407Sobrien 604179407Sobrien switch (reloc_src->r_type) 605179407Sobrien { 606179407Sobrien case MIPS_R_REFHI: 607179407Sobrien prev_addr = reloc_src->r_vaddr; 608179407Sobrien prev_offset = reloc_src->r_offset; 609179407Sobrien break; 610179407Sobrien case MIPS_R_REFLO: 611179407Sobrien if (reloc_src->r_vaddr == prev_addr) 612179407Sobrien { 613179407Sobrien /* FIXME: only slightly hackish. If we see a REFLO pointing to 614179407Sobrien the same address as a REFHI, we assume this is the matching 615179407Sobrien PAIR reloc and output it accordingly. The symndx is really 616179407Sobrien the low 16 bits of the addend */ 617179407Sobrien H_PUT_32 (abfd, reloc_src->r_vaddr, reloc_dst->r_vaddr); 618179407Sobrien H_PUT_32 (abfd, reloc_src->r_symndx, reloc_dst->r_symndx); 619179407Sobrien H_PUT_16 (abfd, MIPS_R_PAIR, reloc_dst->r_type); 620179407Sobrien return RELSZ; 621179407Sobrien } 622179407Sobrien break; 623179407Sobrien } 624179407Sobrien 625179407Sobrien H_PUT_32 (abfd, reloc_src->r_vaddr, reloc_dst->r_vaddr); 626179407Sobrien H_PUT_32 (abfd, reloc_src->r_symndx, reloc_dst->r_symndx); 627179407Sobrien 628179407Sobrien H_PUT_16 (abfd, reloc_src->r_type, reloc_dst->r_type); 629179407Sobrien return RELSZ; 630179407Sobrien} 631179407Sobrien 632179407Sobrien#define coff_swap_reloc_in mips_swap_reloc_in 633179407Sobrien#define coff_swap_reloc_out mips_swap_reloc_out 634179407Sobrien#define NO_COFF_RELOCS 635179407Sobrien 636179407Sobrienstatic bfd_boolean 637179407Sobriencoff_pe_mips_relocate_section (output_bfd, info, input_bfd, 638179407Sobrien input_section, contents, relocs, syms, 639179407Sobrien sections) 640179407Sobrien bfd *output_bfd; 641179407Sobrien struct bfd_link_info *info; 642179407Sobrien bfd *input_bfd; 643179407Sobrien asection *input_section; 644179407Sobrien bfd_byte *contents; 645179407Sobrien struct internal_reloc *relocs; 646179407Sobrien struct internal_syment *syms; 647179407Sobrien asection **sections; 648179407Sobrien{ 649179407Sobrien bfd_vma gp; 650179407Sobrien bfd_boolean gp_undefined; 651179407Sobrien size_t adjust; 652179407Sobrien struct internal_reloc *rel; 653179407Sobrien struct internal_reloc *rel_end; 654179407Sobrien unsigned int i; 655179407Sobrien bfd_boolean got_lo; 656179407Sobrien 657179407Sobrien if (info->relocatable) 658179407Sobrien { 659179407Sobrien (*_bfd_error_handler) (_("\ 660179407Sobrien%s: `ld -r' not supported with PE MIPS objects\n"), 661179407Sobrien bfd_archive_filename (input_bfd)); 662179407Sobrien bfd_set_error (bfd_error_bad_value); 663179407Sobrien return FALSE; 664179407Sobrien } 665179407Sobrien 666179407Sobrien BFD_ASSERT (input_bfd->xvec->byteorder 667179407Sobrien == output_bfd->xvec->byteorder); 668179407Sobrien 669179407Sobrien#if 0 670179407Sobrien printf ("dj: relocate %s(%s) %08x\n", 671179407Sobrien input_bfd->filename, input_section->name, 672179407Sobrien input_section->output_section->vma + input_section->output_offset); 673179407Sobrien#endif 674179407Sobrien 675179407Sobrien gp = _bfd_get_gp_value (output_bfd); 676179407Sobrien if (gp == 0) 677179407Sobrien gp_undefined = TRUE; 678179407Sobrien else 679179407Sobrien gp_undefined = FALSE; 680179407Sobrien 681179407Sobrien got_lo = FALSE; 682179407Sobrien 683179407Sobrien adjust = 0; 684179407Sobrien 685179407Sobrien rel = relocs; 686179407Sobrien rel_end = rel + input_section->reloc_count; 687179407Sobrien for (i = 0; rel < rel_end; rel++, i++) 688179407Sobrien { 689179407Sobrien long symndx; 690179407Sobrien struct coff_link_hash_entry *h; 691179407Sobrien struct internal_syment *sym; 692179407Sobrien bfd_vma addend = 0; 693179407Sobrien bfd_vma val, tmp, targ, src, low; 694179407Sobrien reloc_howto_type *howto; 695179407Sobrien unsigned char *mem = contents + rel->r_vaddr; 696179407Sobrien 697179407Sobrien symndx = rel->r_symndx; 698179407Sobrien 699179407Sobrien if (symndx == -1) 700179407Sobrien { 701179407Sobrien h = NULL; 702179407Sobrien sym = NULL; 703179407Sobrien } 704179407Sobrien else 705179407Sobrien { 706179407Sobrien h = obj_coff_sym_hashes (input_bfd)[symndx]; 707179407Sobrien sym = syms + symndx; 708179407Sobrien } 709179407Sobrien 710179407Sobrien /* COFF treats common symbols in one of two ways. Either the 711179407Sobrien size of the symbol is included in the section contents, or it 712179407Sobrien is not. We assume that the size is not included, and force 713179407Sobrien the rtype_to_howto function to adjust the addend as needed. */ 714179407Sobrien 715179407Sobrien if (sym != NULL && sym->n_scnum != 0) 716179407Sobrien addend = - sym->n_value; 717179407Sobrien else 718179407Sobrien addend = 0; 719179407Sobrien 720179407Sobrien howto = bfd_coff_rtype_to_howto (input_bfd, input_section, rel, h, 721179407Sobrien sym, &addend); 722179407Sobrien if (howto == NULL) 723179407Sobrien return FALSE; 724179407Sobrien 725179407Sobrien /* If we are doing a relocatable link, then we can just ignore 726179407Sobrien a PC relative reloc that is pcrel_offset. It will already 727179407Sobrien have the correct value. If this is not a relocatable link, 728179407Sobrien then we should ignore the symbol value. */ 729179407Sobrien if (howto->pc_relative && howto->pcrel_offset) 730179407Sobrien { 731179407Sobrien if (info->relocatable) 732179407Sobrien continue; 733179407Sobrien if (sym != NULL && sym->n_scnum != 0) 734179407Sobrien addend += sym->n_value; 735179407Sobrien } 736179407Sobrien 737179407Sobrien val = 0; 738179407Sobrien 739179407Sobrien if (h == NULL) 740179407Sobrien { 741179407Sobrien asection *sec; 742179407Sobrien 743179407Sobrien if (symndx == -1) 744179407Sobrien { 745179407Sobrien sec = bfd_abs_section_ptr; 746179407Sobrien val = 0; 747179407Sobrien } 748179407Sobrien else 749179407Sobrien { 750179407Sobrien sec = sections[symndx]; 751179407Sobrien val = (sec->output_section->vma 752179407Sobrien + sec->output_offset 753179407Sobrien + sym->n_value); 754179407Sobrien if (! obj_pe (input_bfd)) 755179407Sobrien val -= sec->vma; 756179407Sobrien } 757179407Sobrien } 758179407Sobrien else 759179407Sobrien { 760179407Sobrien if (h->root.type == bfd_link_hash_defined 761179407Sobrien || h->root.type == bfd_link_hash_defweak) 762179407Sobrien { 763179407Sobrien asection *sec; 764179407Sobrien 765179407Sobrien sec = h->root.u.def.section; 766179407Sobrien val = (h->root.u.def.value 767179407Sobrien + sec->output_section->vma 768179407Sobrien + sec->output_offset); 769179407Sobrien } 770179407Sobrien 771179407Sobrien else if (! info->relocatable) 772179407Sobrien { 773179407Sobrien if (! ((*info->callbacks->undefined_symbol) 774179407Sobrien (info, h->root.root.string, input_bfd, input_section, 775179407Sobrien rel->r_vaddr - input_section->vma, TRUE))) 776179407Sobrien return FALSE; 777179407Sobrien } 778179407Sobrien } 779179407Sobrien 780179407Sobrien src = rel->r_vaddr + input_section->output_section->vma 781179407Sobrien + input_section->output_offset; 782179407Sobrien#if 0 783179407Sobrien printf ("dj: reloc %02x %-8s a=%08x/%08x(%08x) v=%08x+%08x %s\n", 784179407Sobrien rel->r_type, howto_table[rel->r_type].name, 785179407Sobrien src, rel->r_vaddr, *(unsigned long *)mem, val, rel->r_offset, 786179407Sobrien h?h->root.root.string:"(none)"); 787179407Sobrien#endif 788179407Sobrien 789179407Sobrien /* OK, at this point the following variables are set up: 790179407Sobrien src = VMA of the memory we're fixing up 791179407Sobrien mem = pointer to memory we're fixing up 792179407Sobrien val = VMA of what we need to refer to 793179407Sobrien */ 794179407Sobrien 795179407Sobrien#define UI(x) (*_bfd_error_handler) (_("%s: unimplemented %s\n"), \ 796179407Sobrien bfd_archive_filename (input_bfd), x); \ 797179407Sobrien bfd_set_error (bfd_error_bad_value); 798179407Sobrien 799179407Sobrien switch (rel->r_type) 800179407Sobrien { 801179407Sobrien case MIPS_R_ABSOLUTE: 802179407Sobrien /* ignore these */ 803179407Sobrien break; 804179407Sobrien 805179407Sobrien case MIPS_R_REFHALF: 806179407Sobrien UI("refhalf"); 807179407Sobrien break; 808179407Sobrien 809179407Sobrien case MIPS_R_REFWORD: 810179407Sobrien tmp = bfd_get_32(input_bfd, mem); 811179407Sobrien /* printf ("refword: src=%08x targ=%08x+%08x\n", src, tmp, val); */ 812179407Sobrien tmp += val; 813179407Sobrien bfd_put_32(input_bfd, tmp, mem); 814179407Sobrien break; 815179407Sobrien 816179407Sobrien case MIPS_R_JMPADDR: 817179407Sobrien tmp = bfd_get_32(input_bfd, mem); 818179407Sobrien targ = val + (tmp&0x03ffffff)*4; 819179407Sobrien if ((src & 0xf0000000) != (targ & 0xf0000000)) 820179407Sobrien { 821179407Sobrien (*_bfd_error_handler) (_("%s: jump too far away\n"), 822179407Sobrien bfd_archive_filename (input_bfd)); 823179407Sobrien bfd_set_error (bfd_error_bad_value); 824179407Sobrien return FALSE; 825179407Sobrien } 826179407Sobrien tmp &= 0xfc000000; 827179407Sobrien tmp |= (targ/4) & 0x3ffffff; 828179407Sobrien bfd_put_32(input_bfd, tmp, mem); 829179407Sobrien break; 830179407Sobrien 831179407Sobrien case MIPS_R_REFHI: 832179407Sobrien tmp = bfd_get_32(input_bfd, mem); 833179407Sobrien switch (rel[1].r_type) 834179407Sobrien { 835179407Sobrien case MIPS_R_PAIR: 836179407Sobrien /* MS PE object */ 837179407Sobrien targ = val + rel[1].r_offset + ((tmp & 0xffff) << 16); 838179407Sobrien break; 839179407Sobrien case MIPS_R_REFLO: 840179407Sobrien /* GNU COFF object */ 841179407Sobrien low = bfd_get_32(input_bfd, contents + rel[1].r_vaddr); 842179407Sobrien low &= 0xffff; 843179407Sobrien if (low & 0x8000) 844179407Sobrien low -= 0x10000; 845179407Sobrien targ = val + low + ((tmp & 0xffff) << 16); 846179407Sobrien break; 847179407Sobrien default: 848179407Sobrien (*_bfd_error_handler) (_("%s: bad pair/reflo after refhi\n"), 849179407Sobrien bfd_archive_filename (input_bfd)); 850179407Sobrien bfd_set_error (bfd_error_bad_value); 851179407Sobrien return FALSE; 852179407Sobrien } 853179407Sobrien tmp &= 0xffff0000; 854179407Sobrien tmp |= (targ >> 16) & 0xffff; 855179407Sobrien bfd_put_32(input_bfd, tmp, mem); 856179407Sobrien break; 857179407Sobrien 858179407Sobrien case MIPS_R_REFLO: 859179407Sobrien tmp = bfd_get_32(input_bfd, mem); 860179407Sobrien targ = val + (tmp & 0xffff); 861179407Sobrien /* printf ("refword: src=%08x targ=%08x\n", src, targ); */ 862179407Sobrien tmp &= 0xffff0000; 863179407Sobrien tmp |= targ & 0xffff; 864179407Sobrien bfd_put_32(input_bfd, tmp, mem); 865179407Sobrien break; 866179407Sobrien 867179407Sobrien case MIPS_R_GPREL: 868179407Sobrien case MIPS_R_LITERAL: 869179407Sobrien UI("gprel"); 870179407Sobrien break; 871179407Sobrien 872179407Sobrien case MIPS_R_SECTION: 873179407Sobrien UI("section"); 874179407Sobrien break; 875179407Sobrien 876179407Sobrien case MIPS_R_SECREL: 877179407Sobrien UI("secrel"); 878179407Sobrien break; 879179407Sobrien 880179407Sobrien case MIPS_R_SECRELLO: 881179407Sobrien UI("secrello"); 882179407Sobrien break; 883179407Sobrien 884179407Sobrien case MIPS_R_SECRELHI: 885179407Sobrien UI("secrelhi"); 886179407Sobrien break; 887179407Sobrien 888179407Sobrien case MIPS_R_RVA: 889179407Sobrien tmp = bfd_get_32 (input_bfd, mem); 890179407Sobrien /* printf ("rva: src=%08x targ=%08x+%08x\n", src, tmp, val); */ 891179407Sobrien tmp += val 892179407Sobrien - pe_data (input_section->output_section->owner)->pe_opthdr.ImageBase; 893179407Sobrien bfd_put_32 (input_bfd, tmp, mem); 894179407Sobrien break; 895179407Sobrien 896179407Sobrien case MIPS_R_PAIR: 897179407Sobrien /* ignore these */ 898179407Sobrien break; 899179407Sobrien } 900179407Sobrien } 901179407Sobrien 902179407Sobrien return TRUE; 903179407Sobrien} 904179407Sobrien 905179407Sobrien#define coff_relocate_section coff_pe_mips_relocate_section 906179407Sobrien 907179407Sobrien#ifdef TARGET_UNDERSCORE 908179407Sobrien 909179407Sobrien/* If mips gcc uses underscores for symbol names, then it does not use 910179407Sobrien a leading dot for local labels, so if TARGET_UNDERSCORE is defined 911179407Sobrien we treat all symbols starting with L as local. */ 912179407Sobrien 913179407Sobrienstatic bfd_boolean coff_mips_is_local_label_name 914179407Sobrien PARAMS ((bfd *, const char *)); 915179407Sobrien 916179407Sobrienstatic bfd_boolean 917179407Sobriencoff_mips_is_local_label_name (abfd, name) 918179407Sobrien bfd *abfd; 919179407Sobrien const char *name; 920179407Sobrien{ 921179407Sobrien if (name[0] == 'L') 922179407Sobrien return TRUE; 923179407Sobrien 924179407Sobrien return _bfd_coff_is_local_label_name (abfd, name); 925179407Sobrien} 926179407Sobrien 927179407Sobrien#define coff_bfd_is_local_label_name coff_mips_is_local_label_name 928179407Sobrien 929179407Sobrien#endif /* TARGET_UNDERSCORE */ 930179407Sobrien 931179407Sobrien#define COFF_NO_HACK_SCNHDR_SIZE 932179407Sobrien 933179407Sobrien#include "coffcode.h" 934179407Sobrien 935179407Sobrienconst bfd_target 936179407Sobrien#ifdef TARGET_SYM 937179407Sobrien TARGET_SYM = 938179407Sobrien#else 939179407Sobrien mipslpe_vec = 940179407Sobrien#endif 941179407Sobrien{ 942179407Sobrien#ifdef TARGET_NAME 943179407Sobrien TARGET_NAME, 944179407Sobrien#else 945179407Sobrien "pe-mips", /* name */ 946179407Sobrien#endif 947179407Sobrien bfd_target_coff_flavour, 948179407Sobrien BFD_ENDIAN_LITTLE, /* data byte order is little */ 949179407Sobrien BFD_ENDIAN_LITTLE, /* header byte order is little */ 950179407Sobrien 951179407Sobrien (HAS_RELOC | EXEC_P | /* object flags */ 952179407Sobrien HAS_LINENO | HAS_DEBUG | 953179407Sobrien HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED), 954179407Sobrien 955179407Sobrien#ifndef COFF_WITH_PE 956179407Sobrien (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* section flags */ 957179407Sobrien | SEC_CODE | SEC_DATA), 958179407Sobrien#else 959179407Sobrien (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* section flags */ 960179407Sobrien | SEC_CODE | SEC_DATA 961179407Sobrien | SEC_LINK_ONCE | SEC_LINK_DUPLICATES), 962179407Sobrien#endif 963179407Sobrien 964179407Sobrien#ifdef TARGET_UNDERSCORE 965179407Sobrien TARGET_UNDERSCORE, /* leading underscore */ 966179407Sobrien#else 967179407Sobrien 0, /* leading underscore */ 968179407Sobrien#endif 969179407Sobrien '/', /* ar_pad_char */ 970179407Sobrien 15, /* ar_max_namelen */ 971179407Sobrien 972179407Sobrien bfd_getl64, bfd_getl_signed_64, bfd_putl64, 973179407Sobrien bfd_getl32, bfd_getl_signed_32, bfd_putl32, 974179407Sobrien bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */ 975179407Sobrien bfd_getl64, bfd_getl_signed_64, bfd_putl64, 976179407Sobrien bfd_getl32, bfd_getl_signed_32, bfd_putl32, 977179407Sobrien bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */ 978179407Sobrien 979179407Sobrien/* Note that we allow an object file to be treated as a core file as well. */ 980179407Sobrien {_bfd_dummy_target, coff_object_p, /* bfd_check_format */ 981179407Sobrien bfd_generic_archive_p, coff_object_p}, 982179407Sobrien {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */ 983179407Sobrien bfd_false}, 984179407Sobrien {bfd_false, coff_write_object_contents, /* bfd_write_contents */ 985179407Sobrien _bfd_write_archive_contents, bfd_false}, 986179407Sobrien 987179407Sobrien BFD_JUMP_TABLE_GENERIC (coff), 988179407Sobrien BFD_JUMP_TABLE_COPY (coff), 989179407Sobrien BFD_JUMP_TABLE_CORE (_bfd_nocore), 990179407Sobrien BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff), 991179407Sobrien BFD_JUMP_TABLE_SYMBOLS (coff), 992179407Sobrien BFD_JUMP_TABLE_RELOCS (coff), 993179407Sobrien BFD_JUMP_TABLE_WRITE (coff), 994179407Sobrien BFD_JUMP_TABLE_LINK (coff), 995179407Sobrien BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic), 996179407Sobrien 997179407Sobrien NULL, 998179407Sobrien 999179407Sobrien COFF_SWAP_TABLE 1000179407Sobrien}; 1001