160484Sobrien/* BFD back-end for Sparc COFF files. 2130561Sobrien Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1999, 2000, 2001, 3218822Sdim 2002, 2003, 2005, 2007 Free Software Foundation, Inc. 460484Sobrien Written by Cygnus Support. 560484Sobrien 660484SobrienThis file is part of BFD, the Binary File Descriptor library. 760484Sobrien 860484SobrienThis program is free software; you can redistribute it and/or modify 960484Sobrienit under the terms of the GNU General Public License as published by 1060484Sobrienthe Free Software Foundation; either version 2 of the License, or 1160484Sobrien(at your option) any later version. 1260484Sobrien 1360484SobrienThis program is distributed in the hope that it will be useful, 1460484Sobrienbut WITHOUT ANY WARRANTY; without even the implied warranty of 1560484SobrienMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1660484SobrienGNU General Public License for more details. 1760484Sobrien 1860484SobrienYou should have received a copy of the GNU General Public License 1960484Sobrienalong with this program; if not, write to the Free Software 20218822SdimFoundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 2160484Sobrien 22218822Sdim#include "sysdep.h" 2360484Sobrien#include "bfd.h" 2460484Sobrien#include "libbfd.h" 2560484Sobrien#include "coff/sparc.h" 2660484Sobrien#include "coff/internal.h" 2760484Sobrien#include "libcoff.h" 2860484Sobrien 2960484Sobrien#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (3) 3060484Sobrien 3160484Sobrien#define BADMAG(x) ((x).f_magic != SPARCMAGIC && (x).f_magic != LYNXCOFFMAGIC) 3260484Sobrien 3360484Sobrien/* The page size is a guess based on ELF. */ 3460484Sobrien#define COFF_PAGE_SIZE 0x10000 3560484Sobrien 3689857Sobrien 3789857Sobrienstatic reloc_howto_type *coff_sparc_reloc_type_lookup 3889857Sobrien PARAMS ((bfd *, bfd_reloc_code_real_type)); 3989857Sobrienstatic void rtype2howto PARAMS ((arelent *, struct internal_reloc *)); 4089857Sobrien 4160484Sobrienenum reloc_type 4260484Sobrien { 4360484Sobrien R_SPARC_NONE = 0, 4477298Sobrien R_SPARC_8, R_SPARC_16, R_SPARC_32, 4577298Sobrien R_SPARC_DISP8, R_SPARC_DISP16, R_SPARC_DISP32, 4660484Sobrien R_SPARC_WDISP30, R_SPARC_WDISP22, 4760484Sobrien R_SPARC_HI22, R_SPARC_22, 4860484Sobrien R_SPARC_13, R_SPARC_LO10, 4960484Sobrien R_SPARC_GOT10, R_SPARC_GOT13, R_SPARC_GOT22, 5060484Sobrien R_SPARC_PC10, R_SPARC_PC22, 5160484Sobrien R_SPARC_WPLT30, 5260484Sobrien R_SPARC_COPY, 5360484Sobrien R_SPARC_GLOB_DAT, R_SPARC_JMP_SLOT, 5460484Sobrien R_SPARC_RELATIVE, 5560484Sobrien R_SPARC_UA32, 5660484Sobrien R_SPARC_max 5760484Sobrien }; 5860484Sobrien 5960484Sobrien/* This is stolen pretty directly from elf.c. */ 6060484Sobrienstatic bfd_reloc_status_type 6160484Sobrienbfd_coff_generic_reloc PARAMS ((bfd *, arelent *, asymbol *, PTR, 6260484Sobrien asection *, bfd *, char **)); 6360484Sobrien 6460484Sobrienstatic bfd_reloc_status_type 6560484Sobrienbfd_coff_generic_reloc (abfd, reloc_entry, symbol, data, input_section, 6660484Sobrien output_bfd, error_message) 6760484Sobrien bfd *abfd ATTRIBUTE_UNUSED; 6860484Sobrien arelent *reloc_entry; 6960484Sobrien asymbol *symbol; 7060484Sobrien PTR data ATTRIBUTE_UNUSED; 7160484Sobrien asection *input_section; 7260484Sobrien bfd *output_bfd; 7360484Sobrien char **error_message ATTRIBUTE_UNUSED; 7460484Sobrien{ 7560484Sobrien if (output_bfd != (bfd *) NULL 7660484Sobrien && (symbol->flags & BSF_SECTION_SYM) == 0) 7760484Sobrien { 7860484Sobrien reloc_entry->address += input_section->output_offset; 7960484Sobrien return bfd_reloc_ok; 8060484Sobrien } 8160484Sobrien 8260484Sobrien return bfd_reloc_continue; 8360484Sobrien} 8460484Sobrien 8577298Sobrienstatic reloc_howto_type coff_sparc_howto_table[] = 8660484Sobrien{ 87130561Sobrien HOWTO(R_SPARC_NONE, 0,0, 0,FALSE,0,complain_overflow_dont, bfd_coff_generic_reloc,"R_SPARC_NONE", FALSE,0,0x00000000,TRUE), 88130561Sobrien HOWTO(R_SPARC_8, 0,0, 8,FALSE,0,complain_overflow_bitfield,bfd_coff_generic_reloc,"R_SPARC_8", FALSE,0,0x000000ff,TRUE), 89130561Sobrien HOWTO(R_SPARC_16, 0,1,16,FALSE,0,complain_overflow_bitfield,bfd_coff_generic_reloc,"R_SPARC_16", FALSE,0,0x0000ffff,TRUE), 90130561Sobrien HOWTO(R_SPARC_32, 0,2,32,FALSE,0,complain_overflow_bitfield,bfd_coff_generic_reloc,"R_SPARC_32", FALSE,0,0xffffffff,TRUE), 91130561Sobrien HOWTO(R_SPARC_DISP8, 0,0, 8,TRUE, 0,complain_overflow_signed, bfd_coff_generic_reloc,"R_SPARC_DISP8", FALSE,0,0x000000ff,TRUE), 92130561Sobrien HOWTO(R_SPARC_DISP16, 0,1,16,TRUE, 0,complain_overflow_signed, bfd_coff_generic_reloc,"R_SPARC_DISP16", FALSE,0,0x0000ffff,TRUE), 93130561Sobrien HOWTO(R_SPARC_DISP32, 0,2,32,TRUE, 0,complain_overflow_signed, bfd_coff_generic_reloc,"R_SPARC_DISP32", FALSE,0,0x00ffffff,TRUE), 94130561Sobrien HOWTO(R_SPARC_WDISP30, 2,2,30,TRUE, 0,complain_overflow_signed, bfd_coff_generic_reloc,"R_SPARC_WDISP30", FALSE,0,0x3fffffff,TRUE), 95130561Sobrien HOWTO(R_SPARC_WDISP22, 2,2,22,TRUE, 0,complain_overflow_signed, bfd_coff_generic_reloc,"R_SPARC_WDISP22", FALSE,0,0x003fffff,TRUE), 96130561Sobrien HOWTO(R_SPARC_HI22, 10,2,22,FALSE,0,complain_overflow_dont, bfd_coff_generic_reloc,"R_SPARC_HI22", FALSE,0,0x003fffff,TRUE), 97130561Sobrien HOWTO(R_SPARC_22, 0,2,22,FALSE,0,complain_overflow_bitfield,bfd_coff_generic_reloc,"R_SPARC_22", FALSE,0,0x003fffff,TRUE), 98130561Sobrien HOWTO(R_SPARC_13, 0,2,13,FALSE,0,complain_overflow_bitfield,bfd_coff_generic_reloc,"R_SPARC_13", FALSE,0,0x00001fff,TRUE), 99130561Sobrien HOWTO(R_SPARC_LO10, 0,2,10,FALSE,0,complain_overflow_dont, bfd_coff_generic_reloc,"R_SPARC_LO10", FALSE,0,0x000003ff,TRUE), 100130561Sobrien HOWTO(R_SPARC_GOT10, 0,2,10,FALSE,0,complain_overflow_bitfield,bfd_coff_generic_reloc,"R_SPARC_GOT10", FALSE,0,0x000003ff,TRUE), 101130561Sobrien HOWTO(R_SPARC_GOT13, 0,2,13,FALSE,0,complain_overflow_bitfield,bfd_coff_generic_reloc,"R_SPARC_GOT13", FALSE,0,0x00001fff,TRUE), 102130561Sobrien HOWTO(R_SPARC_GOT22, 10,2,22,FALSE,0,complain_overflow_bitfield,bfd_coff_generic_reloc,"R_SPARC_GOT22", FALSE,0,0x003fffff,TRUE), 103130561Sobrien HOWTO(R_SPARC_PC10, 0,2,10,FALSE,0,complain_overflow_bitfield,bfd_coff_generic_reloc,"R_SPARC_PC10", FALSE,0,0x000003ff,TRUE), 104130561Sobrien HOWTO(R_SPARC_PC22, 0,2,22,FALSE,0,complain_overflow_bitfield,bfd_coff_generic_reloc,"R_SPARC_PC22", FALSE,0,0x003fffff,TRUE), 105130561Sobrien HOWTO(R_SPARC_WPLT30, 0,0,00,FALSE,0,complain_overflow_dont, bfd_coff_generic_reloc,"R_SPARC_WPLT30", FALSE,0,0x00000000,TRUE), 106130561Sobrien HOWTO(R_SPARC_COPY, 0,0,00,FALSE,0,complain_overflow_dont, bfd_coff_generic_reloc,"R_SPARC_COPY", FALSE,0,0x00000000,TRUE), 107130561Sobrien HOWTO(R_SPARC_GLOB_DAT,0,0,00,FALSE,0,complain_overflow_dont, bfd_coff_generic_reloc,"R_SPARC_GLOB_DAT",FALSE,0,0x00000000,TRUE), 108130561Sobrien HOWTO(R_SPARC_JMP_SLOT,0,0,00,FALSE,0,complain_overflow_dont, bfd_coff_generic_reloc,"R_SPARC_JMP_SLOT",FALSE,0,0x00000000,TRUE), 109130561Sobrien HOWTO(R_SPARC_RELATIVE,0,0,00,FALSE,0,complain_overflow_dont, bfd_coff_generic_reloc,"R_SPARC_RELATIVE",FALSE,0,0x00000000,TRUE), 110130561Sobrien HOWTO(R_SPARC_UA32, 0,0,00,FALSE,0,complain_overflow_dont, bfd_coff_generic_reloc,"R_SPARC_UA32", FALSE,0,0x00000000,TRUE), 11160484Sobrien}; 11260484Sobrien 11360484Sobrienstruct coff_reloc_map { 11460484Sobrien bfd_reloc_code_real_type bfd_reloc_val; 11560484Sobrien unsigned char coff_reloc_val; 11660484Sobrien}; 11760484Sobrien 11889857Sobrienstatic const struct coff_reloc_map sparc_reloc_map[] = 11960484Sobrien{ 12060484Sobrien { BFD_RELOC_NONE, R_SPARC_NONE, }, 12160484Sobrien { BFD_RELOC_16, R_SPARC_16, }, 12260484Sobrien { BFD_RELOC_8, R_SPARC_8 }, 12360484Sobrien { BFD_RELOC_8_PCREL, R_SPARC_DISP8 }, 12460484Sobrien { BFD_RELOC_CTOR, R_SPARC_32 }, /* @@ Assumes 32 bits. */ 12560484Sobrien { BFD_RELOC_32, R_SPARC_32 }, 12660484Sobrien { BFD_RELOC_32_PCREL, R_SPARC_DISP32 }, 12760484Sobrien { BFD_RELOC_HI22, R_SPARC_HI22 }, 12860484Sobrien { BFD_RELOC_LO10, R_SPARC_LO10, }, 12960484Sobrien { BFD_RELOC_32_PCREL_S2, R_SPARC_WDISP30 }, 13060484Sobrien { BFD_RELOC_SPARC22, R_SPARC_22 }, 13160484Sobrien { BFD_RELOC_SPARC13, R_SPARC_13 }, 13260484Sobrien { BFD_RELOC_SPARC_GOT10, R_SPARC_GOT10 }, 13360484Sobrien { BFD_RELOC_SPARC_GOT13, R_SPARC_GOT13 }, 13460484Sobrien { BFD_RELOC_SPARC_GOT22, R_SPARC_GOT22 }, 13560484Sobrien { BFD_RELOC_SPARC_PC10, R_SPARC_PC10 }, 13660484Sobrien { BFD_RELOC_SPARC_PC22, R_SPARC_PC22 }, 13760484Sobrien { BFD_RELOC_SPARC_WPLT30, R_SPARC_WPLT30 }, 13860484Sobrien { BFD_RELOC_SPARC_COPY, R_SPARC_COPY }, 13960484Sobrien { BFD_RELOC_SPARC_GLOB_DAT, R_SPARC_GLOB_DAT }, 14060484Sobrien { BFD_RELOC_SPARC_JMP_SLOT, R_SPARC_JMP_SLOT }, 14160484Sobrien { BFD_RELOC_SPARC_RELATIVE, R_SPARC_RELATIVE }, 14260484Sobrien { BFD_RELOC_SPARC_WDISP22, R_SPARC_WDISP22 }, 14360484Sobrien /* { BFD_RELOC_SPARC_UA32, R_SPARC_UA32 }, not used?? */ 14460484Sobrien}; 14560484Sobrien 14660484Sobrienstatic reloc_howto_type * 14760484Sobriencoff_sparc_reloc_type_lookup (abfd, code) 14860484Sobrien bfd *abfd ATTRIBUTE_UNUSED; 14960484Sobrien bfd_reloc_code_real_type code; 15060484Sobrien{ 15160484Sobrien unsigned int i; 15260484Sobrien for (i = 0; i < sizeof (sparc_reloc_map) / sizeof (struct coff_reloc_map); i++) 15360484Sobrien { 15460484Sobrien if (sparc_reloc_map[i].bfd_reloc_val == code) 15560484Sobrien return &coff_sparc_howto_table[(int) sparc_reloc_map[i].coff_reloc_val]; 15660484Sobrien } 15760484Sobrien return 0; 15860484Sobrien} 15960484Sobrien#define coff_bfd_reloc_type_lookup coff_sparc_reloc_type_lookup 16060484Sobrien 161218822Sdimstatic reloc_howto_type * 162218822Sdimcoff_sparc_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, 163218822Sdim const char *r_name) 164218822Sdim{ 165218822Sdim unsigned int i; 166218822Sdim 167218822Sdim for (i = 0; 168218822Sdim i < (sizeof (coff_sparc_howto_table) 169218822Sdim / sizeof (coff_sparc_howto_table[0])); 170218822Sdim i++) 171218822Sdim if (coff_sparc_howto_table[i].name != NULL 172218822Sdim && strcasecmp (coff_sparc_howto_table[i].name, r_name) == 0) 173218822Sdim return &coff_sparc_howto_table[i]; 174218822Sdim 175218822Sdim return NULL; 176218822Sdim} 177218822Sdim#define coff_bfd_reloc_name_lookup coff_sparc_reloc_name_lookup 178218822Sdim 17960484Sobrienstatic void 18060484Sobrienrtype2howto (cache_ptr, dst) 18160484Sobrien arelent *cache_ptr; 18260484Sobrien struct internal_reloc *dst; 18360484Sobrien{ 18460484Sobrien BFD_ASSERT (dst->r_type < (unsigned int) R_SPARC_max); 18560484Sobrien cache_ptr->howto = &coff_sparc_howto_table[dst->r_type]; 18660484Sobrien} 18760484Sobrien 18860484Sobrien#define RTYPE2HOWTO(internal, relocentry) rtype2howto(internal,relocentry) 18960484Sobrien 19089857Sobrien#define SWAP_IN_RELOC_OFFSET H_GET_32 19189857Sobrien#define SWAP_OUT_RELOC_OFFSET H_PUT_32 19260484Sobrien#define CALC_ADDEND(abfd, ptr, reloc, cache_ptr) \ 19360484Sobrien cache_ptr->addend = reloc.r_offset; 19460484Sobrien 19560484Sobrien/* Clear the r_spare field in relocs. */ 19660484Sobrien#define SWAP_OUT_RELOC_EXTRA(abfd,src,dst) \ 19760484Sobrien do { \ 19860484Sobrien dst->r_spare[0] = 0; \ 19960484Sobrien dst->r_spare[1] = 0; \ 20060484Sobrien } while (0) 20160484Sobrien 20260484Sobrien#define __A_MAGIC_SET__ 20360484Sobrien 20477298Sobrien/* Enable Sparc-specific hacks in coffcode.h. */ 20560484Sobrien 20660484Sobrien#define COFF_SPARC 20760484Sobrien 20860484Sobrien#include "coffcode.h" 20960484Sobrien 21060484Sobrien#ifndef TARGET_SYM 21160484Sobrien#define TARGET_SYM sparccoff_vec 21260484Sobrien#endif 21360484Sobrien 21460484Sobrien#ifndef TARGET_NAME 21560484Sobrien#define TARGET_NAME "coff-sparc" 21660484Sobrien#endif 21760484Sobrien 218130561SobrienCREATE_BIG_COFF_TARGET_VEC (TARGET_SYM, TARGET_NAME, D_PAGED, 0, '_', NULL, COFF_SWAP_TABLE) 219