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