xref: /openbsd-src/gnu/usr.bin/binutils/bfd/coff-sparc.c (revision 007c2a4539b8b8aaa95c5e73e77620090abe113b)
12159047fSniklas /* BFD back-end for Sparc COFF files.
2*007c2a45Smiod    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1999, 2000, 2001,
3*007c2a45Smiod    2002, 2003 Free Software Foundation, Inc.
42159047fSniklas    Written by Cygnus Support.
52159047fSniklas 
62159047fSniklas This file is part of BFD, the Binary File Descriptor library.
72159047fSniklas 
82159047fSniklas This program is free software; you can redistribute it and/or modify
92159047fSniklas it under the terms of the GNU General Public License as published by
102159047fSniklas the Free Software Foundation; either version 2 of the License, or
112159047fSniklas (at your option) any later version.
122159047fSniklas 
132159047fSniklas This program is distributed in the hope that it will be useful,
142159047fSniklas but WITHOUT ANY WARRANTY; without even the implied warranty of
152159047fSniklas MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
162159047fSniklas GNU General Public License for more details.
172159047fSniklas 
182159047fSniklas You should have received a copy of the GNU General Public License
192159047fSniklas along with this program; if not, write to the Free Software
202159047fSniklas Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
212159047fSniklas 
222159047fSniklas #include "bfd.h"
232159047fSniklas #include "sysdep.h"
242159047fSniklas #include "libbfd.h"
252159047fSniklas #include "coff/sparc.h"
262159047fSniklas #include "coff/internal.h"
272159047fSniklas #include "libcoff.h"
282159047fSniklas 
292159047fSniklas #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (3)
302159047fSniklas 
312159047fSniklas #define BADMAG(x) ((x).f_magic != SPARCMAGIC && (x).f_magic != LYNXCOFFMAGIC)
322159047fSniklas 
332159047fSniklas /* The page size is a guess based on ELF.  */
342159047fSniklas #define COFF_PAGE_SIZE 0x10000
352159047fSniklas 
36c074d1c9Sdrahn 
37c074d1c9Sdrahn static reloc_howto_type *coff_sparc_reloc_type_lookup
38c074d1c9Sdrahn   PARAMS ((bfd *, bfd_reloc_code_real_type));
39c074d1c9Sdrahn static void rtype2howto PARAMS ((arelent *, struct internal_reloc *));
40c074d1c9Sdrahn 
412159047fSniklas enum reloc_type
422159047fSniklas   {
432159047fSniklas     R_SPARC_NONE = 0,
442159047fSniklas     R_SPARC_8,		R_SPARC_16,		R_SPARC_32,
452159047fSniklas     R_SPARC_DISP8,	R_SPARC_DISP16,		R_SPARC_DISP32,
462159047fSniklas     R_SPARC_WDISP30,	R_SPARC_WDISP22,
472159047fSniklas     R_SPARC_HI22,	R_SPARC_22,
482159047fSniklas     R_SPARC_13,		R_SPARC_LO10,
492159047fSniklas     R_SPARC_GOT10,	R_SPARC_GOT13,		R_SPARC_GOT22,
502159047fSniklas     R_SPARC_PC10,	R_SPARC_PC22,
512159047fSniklas     R_SPARC_WPLT30,
522159047fSniklas     R_SPARC_COPY,
532159047fSniklas     R_SPARC_GLOB_DAT,	R_SPARC_JMP_SLOT,
542159047fSniklas     R_SPARC_RELATIVE,
552159047fSniklas     R_SPARC_UA32,
562159047fSniklas     R_SPARC_max
572159047fSniklas   };
582159047fSniklas 
592159047fSniklas #if 0
60c074d1c9Sdrahn static const char *const reloc_type_names[] =
612159047fSniklas {
622159047fSniklas   "R_SPARC_NONE",
632159047fSniklas   "R_SPARC_8",		"R_SPARC_16",		"R_SPARC_32",
642159047fSniklas   "R_SPARC_DISP8",	"R_SPARC_DISP16",	"R_SPARC_DISP32",
652159047fSniklas   "R_SPARC_WDISP30",	"R_SPARC_WDISP22",
662159047fSniklas   "R_SPARC_HI22",	"R_SPARC_22",
672159047fSniklas   "R_SPARC_13",		"R_SPARC_LO10",
682159047fSniklas   "R_SPARC_GOT10",	"R_SPARC_GOT13",	"R_SPARC_GOT22",
692159047fSniklas   "R_SPARC_PC10",	"R_SPARC_PC22",
702159047fSniklas   "R_SPARC_WPLT30",
712159047fSniklas   "R_SPARC_COPY",
722159047fSniklas   "R_SPARC_GLOB_DAT",	"R_SPARC_JMP_SLOT",
732159047fSniklas   "R_SPARC_RELATIVE",
742159047fSniklas   "R_SPARC_UA32",
752159047fSniklas };
762159047fSniklas #endif
772159047fSniklas 
782159047fSniklas /* This is stolen pretty directly from elf.c.  */
792159047fSniklas static bfd_reloc_status_type
802159047fSniklas bfd_coff_generic_reloc PARAMS ((bfd *, arelent *, asymbol *, PTR,
812159047fSniklas 				asection *, bfd *, char **));
822159047fSniklas 
832159047fSniklas static bfd_reloc_status_type
bfd_coff_generic_reloc(abfd,reloc_entry,symbol,data,input_section,output_bfd,error_message)842159047fSniklas bfd_coff_generic_reloc (abfd, reloc_entry, symbol, data, input_section,
852159047fSniklas 			output_bfd, error_message)
86b305b0f1Sespie      bfd *abfd ATTRIBUTE_UNUSED;
872159047fSniklas      arelent *reloc_entry;
882159047fSniklas      asymbol *symbol;
89b305b0f1Sespie      PTR data ATTRIBUTE_UNUSED;
902159047fSniklas      asection *input_section;
912159047fSniklas      bfd *output_bfd;
92b305b0f1Sespie      char **error_message ATTRIBUTE_UNUSED;
932159047fSniklas {
942159047fSniklas   if (output_bfd != (bfd *) NULL
95c88b1d6cSniklas       && (symbol->flags & BSF_SECTION_SYM) == 0)
962159047fSniklas     {
972159047fSniklas       reloc_entry->address += input_section->output_offset;
982159047fSniklas       return bfd_reloc_ok;
992159047fSniklas     }
1002159047fSniklas 
1012159047fSniklas   return bfd_reloc_continue;
1022159047fSniklas }
1032159047fSniklas 
1042159047fSniklas static reloc_howto_type coff_sparc_howto_table[] =
1052159047fSniklas {
106c074d1c9Sdrahn   HOWTO(R_SPARC_NONE,    0,0, 0,FALSE,0,complain_overflow_dont,    bfd_coff_generic_reloc,"R_SPARC_NONE",    FALSE,0,0x00000000,TRUE),
107c074d1c9Sdrahn   HOWTO(R_SPARC_8,       0,0, 8,FALSE,0,complain_overflow_bitfield,bfd_coff_generic_reloc,"R_SPARC_8",       FALSE,0,0x000000ff,TRUE),
108c074d1c9Sdrahn   HOWTO(R_SPARC_16,      0,1,16,FALSE,0,complain_overflow_bitfield,bfd_coff_generic_reloc,"R_SPARC_16",      FALSE,0,0x0000ffff,TRUE),
109c074d1c9Sdrahn   HOWTO(R_SPARC_32,      0,2,32,FALSE,0,complain_overflow_bitfield,bfd_coff_generic_reloc,"R_SPARC_32",      FALSE,0,0xffffffff,TRUE),
110c074d1c9Sdrahn   HOWTO(R_SPARC_DISP8,   0,0, 8,TRUE, 0,complain_overflow_signed,  bfd_coff_generic_reloc,"R_SPARC_DISP8",   FALSE,0,0x000000ff,TRUE),
111c074d1c9Sdrahn   HOWTO(R_SPARC_DISP16,  0,1,16,TRUE, 0,complain_overflow_signed,  bfd_coff_generic_reloc,"R_SPARC_DISP16",  FALSE,0,0x0000ffff,TRUE),
112c074d1c9Sdrahn   HOWTO(R_SPARC_DISP32,  0,2,32,TRUE, 0,complain_overflow_signed,  bfd_coff_generic_reloc,"R_SPARC_DISP32",  FALSE,0,0x00ffffff,TRUE),
113c074d1c9Sdrahn   HOWTO(R_SPARC_WDISP30, 2,2,30,TRUE, 0,complain_overflow_signed,  bfd_coff_generic_reloc,"R_SPARC_WDISP30", FALSE,0,0x3fffffff,TRUE),
114c074d1c9Sdrahn   HOWTO(R_SPARC_WDISP22, 2,2,22,TRUE, 0,complain_overflow_signed,  bfd_coff_generic_reloc,"R_SPARC_WDISP22", FALSE,0,0x003fffff,TRUE),
115c074d1c9Sdrahn   HOWTO(R_SPARC_HI22,   10,2,22,FALSE,0,complain_overflow_dont,    bfd_coff_generic_reloc,"R_SPARC_HI22",    FALSE,0,0x003fffff,TRUE),
116c074d1c9Sdrahn   HOWTO(R_SPARC_22,      0,2,22,FALSE,0,complain_overflow_bitfield,bfd_coff_generic_reloc,"R_SPARC_22",      FALSE,0,0x003fffff,TRUE),
117c074d1c9Sdrahn   HOWTO(R_SPARC_13,      0,2,13,FALSE,0,complain_overflow_bitfield,bfd_coff_generic_reloc,"R_SPARC_13",      FALSE,0,0x00001fff,TRUE),
118c074d1c9Sdrahn   HOWTO(R_SPARC_LO10,    0,2,10,FALSE,0,complain_overflow_dont,    bfd_coff_generic_reloc,"R_SPARC_LO10",    FALSE,0,0x000003ff,TRUE),
119c074d1c9Sdrahn   HOWTO(R_SPARC_GOT10,   0,2,10,FALSE,0,complain_overflow_bitfield,bfd_coff_generic_reloc,"R_SPARC_GOT10",   FALSE,0,0x000003ff,TRUE),
120c074d1c9Sdrahn   HOWTO(R_SPARC_GOT13,   0,2,13,FALSE,0,complain_overflow_bitfield,bfd_coff_generic_reloc,"R_SPARC_GOT13",   FALSE,0,0x00001fff,TRUE),
121c074d1c9Sdrahn   HOWTO(R_SPARC_GOT22,  10,2,22,FALSE,0,complain_overflow_bitfield,bfd_coff_generic_reloc,"R_SPARC_GOT22",   FALSE,0,0x003fffff,TRUE),
122c074d1c9Sdrahn   HOWTO(R_SPARC_PC10,    0,2,10,FALSE,0,complain_overflow_bitfield,bfd_coff_generic_reloc,"R_SPARC_PC10",    FALSE,0,0x000003ff,TRUE),
123c074d1c9Sdrahn   HOWTO(R_SPARC_PC22,    0,2,22,FALSE,0,complain_overflow_bitfield,bfd_coff_generic_reloc,"R_SPARC_PC22",    FALSE,0,0x003fffff,TRUE),
124c074d1c9Sdrahn   HOWTO(R_SPARC_WPLT30,  0,0,00,FALSE,0,complain_overflow_dont,    bfd_coff_generic_reloc,"R_SPARC_WPLT30",  FALSE,0,0x00000000,TRUE),
125c074d1c9Sdrahn   HOWTO(R_SPARC_COPY,    0,0,00,FALSE,0,complain_overflow_dont,    bfd_coff_generic_reloc,"R_SPARC_COPY",    FALSE,0,0x00000000,TRUE),
126c074d1c9Sdrahn   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),
127c074d1c9Sdrahn   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),
128c074d1c9Sdrahn   HOWTO(R_SPARC_RELATIVE,0,0,00,FALSE,0,complain_overflow_dont,    bfd_coff_generic_reloc,"R_SPARC_RELATIVE",FALSE,0,0x00000000,TRUE),
129c074d1c9Sdrahn   HOWTO(R_SPARC_UA32,    0,0,00,FALSE,0,complain_overflow_dont,    bfd_coff_generic_reloc,"R_SPARC_UA32",    FALSE,0,0x00000000,TRUE),
1302159047fSniklas };
1312159047fSniklas 
1322159047fSniklas struct coff_reloc_map {
133b305b0f1Sespie   bfd_reloc_code_real_type bfd_reloc_val;
1342159047fSniklas   unsigned char coff_reloc_val;
1352159047fSniklas };
1362159047fSniklas 
137c074d1c9Sdrahn static const struct coff_reloc_map sparc_reloc_map[] =
1382159047fSniklas {
1392159047fSniklas   { BFD_RELOC_NONE, R_SPARC_NONE, },
1402159047fSniklas   { BFD_RELOC_16, R_SPARC_16, },
1412159047fSniklas   { BFD_RELOC_8, R_SPARC_8 },
1422159047fSniklas   { BFD_RELOC_8_PCREL, R_SPARC_DISP8 },
1432159047fSniklas   { BFD_RELOC_CTOR, R_SPARC_32 }, /* @@ Assumes 32 bits.  */
1442159047fSniklas   { BFD_RELOC_32, R_SPARC_32 },
1452159047fSniklas   { BFD_RELOC_32_PCREL, R_SPARC_DISP32 },
1462159047fSniklas   { BFD_RELOC_HI22, R_SPARC_HI22 },
1472159047fSniklas   { BFD_RELOC_LO10, R_SPARC_LO10, },
1482159047fSniklas   { BFD_RELOC_32_PCREL_S2, R_SPARC_WDISP30 },
1492159047fSniklas   { BFD_RELOC_SPARC22, R_SPARC_22 },
1502159047fSniklas   { BFD_RELOC_SPARC13, R_SPARC_13 },
1512159047fSniklas   { BFD_RELOC_SPARC_GOT10, R_SPARC_GOT10 },
1522159047fSniklas   { BFD_RELOC_SPARC_GOT13, R_SPARC_GOT13 },
1532159047fSniklas   { BFD_RELOC_SPARC_GOT22, R_SPARC_GOT22 },
1542159047fSniklas   { BFD_RELOC_SPARC_PC10, R_SPARC_PC10 },
1552159047fSniklas   { BFD_RELOC_SPARC_PC22, R_SPARC_PC22 },
1562159047fSniklas   { BFD_RELOC_SPARC_WPLT30, R_SPARC_WPLT30 },
1572159047fSniklas   { BFD_RELOC_SPARC_COPY, R_SPARC_COPY },
1582159047fSniklas   { BFD_RELOC_SPARC_GLOB_DAT, R_SPARC_GLOB_DAT },
1592159047fSniklas   { BFD_RELOC_SPARC_JMP_SLOT, R_SPARC_JMP_SLOT },
1602159047fSniklas   { BFD_RELOC_SPARC_RELATIVE, R_SPARC_RELATIVE },
1612159047fSniklas   { BFD_RELOC_SPARC_WDISP22, R_SPARC_WDISP22 },
1622159047fSniklas   /*  { BFD_RELOC_SPARC_UA32, R_SPARC_UA32 }, not used?? */
1632159047fSniklas };
1642159047fSniklas 
1652159047fSniklas static reloc_howto_type *
coff_sparc_reloc_type_lookup(abfd,code)1662159047fSniklas coff_sparc_reloc_type_lookup (abfd, code)
167b305b0f1Sespie      bfd *abfd ATTRIBUTE_UNUSED;
1682159047fSniklas      bfd_reloc_code_real_type code;
1692159047fSniklas {
1702159047fSniklas   unsigned int i;
1712159047fSniklas   for (i = 0; i < sizeof (sparc_reloc_map) / sizeof (struct coff_reloc_map); i++)
1722159047fSniklas     {
1732159047fSniklas       if (sparc_reloc_map[i].bfd_reloc_val == code)
1742159047fSniklas 	return &coff_sparc_howto_table[(int) sparc_reloc_map[i].coff_reloc_val];
1752159047fSniklas     }
1762159047fSniklas   return 0;
1772159047fSniklas }
1782159047fSniklas #define coff_bfd_reloc_type_lookup	coff_sparc_reloc_type_lookup
1792159047fSniklas 
1802159047fSniklas static void
rtype2howto(cache_ptr,dst)1812159047fSniklas rtype2howto (cache_ptr, dst)
1822159047fSniklas      arelent *cache_ptr;
1832159047fSniklas      struct internal_reloc *dst;
1842159047fSniklas {
1852159047fSniklas   BFD_ASSERT (dst->r_type < (unsigned int) R_SPARC_max);
1862159047fSniklas   cache_ptr->howto = &coff_sparc_howto_table[dst->r_type];
1872159047fSniklas }
1882159047fSniklas 
1892159047fSniklas #define RTYPE2HOWTO(internal, relocentry) rtype2howto(internal,relocentry)
1902159047fSniklas 
191c074d1c9Sdrahn #define SWAP_IN_RELOC_OFFSET	H_GET_32
192c074d1c9Sdrahn #define SWAP_OUT_RELOC_OFFSET	H_PUT_32
1932159047fSniklas #define CALC_ADDEND(abfd, ptr, reloc, cache_ptr) \
194c88b1d6cSniklas   cache_ptr->addend = reloc.r_offset;
1952159047fSniklas 
1962159047fSniklas /* Clear the r_spare field in relocs.  */
1972159047fSniklas #define SWAP_OUT_RELOC_EXTRA(abfd,src,dst) \
1982159047fSniklas   do { \
1992159047fSniklas        dst->r_spare[0] = 0; \
2002159047fSniklas        dst->r_spare[1] = 0; \
2012159047fSniklas      } while (0)
2022159047fSniklas 
2032159047fSniklas #define __A_MAGIC_SET__
2042159047fSniklas 
2052159047fSniklas /* Enable Sparc-specific hacks in coffcode.h.  */
2062159047fSniklas 
2072159047fSniklas #define COFF_SPARC
2082159047fSniklas 
2092159047fSniklas #include "coffcode.h"
2102159047fSniklas 
211b305b0f1Sespie #ifndef TARGET_SYM
212b305b0f1Sespie #define TARGET_SYM sparccoff_vec
2132159047fSniklas #endif
214b305b0f1Sespie 
215b305b0f1Sespie #ifndef TARGET_NAME
216b305b0f1Sespie #define TARGET_NAME "coff-sparc"
2172159047fSniklas #endif
2182159047fSniklas 
219*007c2a45Smiod CREATE_BIG_COFF_TARGET_VEC (TARGET_SYM, TARGET_NAME, D_PAGED, 0, '_', NULL, COFF_SWAP_TABLE)
220