| 1 | /* SPARC-specific support for 64-bit ELF |
| 2 | Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc. |
| 3 | |
| 4 | This file is part of BFD, the Binary File Descriptor library. |
| 5 | |
| 6 | This program is free software; you can redistribute it and/or modify |
| 7 | it under the terms of the GNU General Public License as published by |
| 8 | the Free Software Foundation; either version 2 of the License, or |
| 9 | (at your option) any later version. |
| 10 | |
| 11 | This program is distributed in the hope that it will be useful, |
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | GNU General Public License for more details. |
| 15 | |
| 16 | You should have received a copy of the GNU General Public License |
| 17 | along with this program; if not, write to the Free Software |
| 18 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
| 19 | |
| 20 | /* We need a published ABI spec for this. Until one comes out, don't |
| 21 | assume this'll remain unchanged forever. */ |
| 22 | |
| 23 | #include "bfd.h" |
| 24 | #include "sysdep.h" |
| 25 | #include "libbfd.h" |
| 26 | #include "elf-bfd.h" |
| 27 | |
| 28 | #define SPARC64_OLD_RELOCS |
| 29 | #include "elf/sparc.h" |
| 30 | |
| 31 | static reloc_howto_type *sparc64_elf_reloc_type_lookup |
| 32 | PARAMS ((bfd *, bfd_reloc_code_real_type)); |
| 33 | static void sparc64_elf_info_to_howto |
| 34 | PARAMS ((bfd *, arelent *, Elf_Internal_Rela *)); |
| 35 | |
| 36 | static boolean sparc64_elf_relocate_section |
| 37 | PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, |
| 38 | Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)); |
| 39 | static boolean sparc64_elf_object_p PARAMS ((bfd *)); |
| 40 | |
| 41 | /* The howto table and associated functions. |
| 42 | ??? Some of the relocation values have changed. Until we're ready |
| 43 | to upgrade, we have our own copy. At some point a non upward compatible |
| 44 | change will be made at which point this table can be deleted and we'll |
| 45 | use the one in elf32-sparc.c. */ |
| 46 | |
| 47 | static bfd_reloc_status_type sparc_elf_wdisp16_reloc |
| 48 | PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); |
| 49 | |
| 50 | static reloc_howto_type sparc64_elf_howto_table[] = |
| 51 | { |
| 52 | HOWTO(R_SPARC_NONE, 0,0, 0,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_NONE", false,0,0x00000000,true), |
| 53 | HOWTO(R_SPARC_8, 0,0, 8,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_8", false,0,0x000000ff,true), |
| 54 | HOWTO(R_SPARC_16, 0,1,16,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_16", false,0,0x0000ffff,true), |
| 55 | HOWTO(R_SPARC_32, 0,2,32,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_32", false,0,0xffffffff,true), |
| 56 | HOWTO(R_SPARC_DISP8, 0,0, 8,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_DISP8", false,0,0x000000ff,true), |
| 57 | HOWTO(R_SPARC_DISP16, 0,1,16,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_DISP16", false,0,0x0000ffff,true), |
| 58 | HOWTO(R_SPARC_DISP32, 0,2,32,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_DISP32", false,0,0x00ffffff,true), |
| 59 | HOWTO(R_SPARC_WDISP30, 2,2,30,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_WDISP30", false,0,0x3fffffff,true), |
| 60 | HOWTO(R_SPARC_WDISP22, 2,2,22,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_WDISP22", false,0,0x003fffff,true), |
| 61 | HOWTO(R_SPARC_HI22, 10,2,22,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_HI22", false,0,0x003fffff,true), |
| 62 | HOWTO(R_SPARC_22, 0,2,22,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_22", false,0,0x003fffff,true), |
| 63 | HOWTO(R_SPARC_13, 0,2,13,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_13", false,0,0x00001fff,true), |
| 64 | HOWTO(R_SPARC_LO10, 0,2,10,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_LO10", false,0,0x000003ff,true), |
| 65 | HOWTO(R_SPARC_GOT10, 0,2,10,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_GOT10", false,0,0x000003ff,true), |
| 66 | HOWTO(R_SPARC_GOT13, 0,2,13,false,0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_GOT13", false,0,0x00001fff,true), |
| 67 | HOWTO(R_SPARC_GOT22, 10,2,22,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_GOT22", false,0,0x003fffff,true), |
| 68 | HOWTO(R_SPARC_PC10, 0,2,10,true, 0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_PC10", false,0,0x000003ff,true), |
| 69 | HOWTO(R_SPARC_PC22, 10,2,22,true, 0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_PC22", false,0,0x003fffff,true), |
| 70 | HOWTO(R_SPARC_WPLT30, 2,2,30,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_WPLT30", false,0,0x3fffffff,true), |
| 71 | HOWTO(R_SPARC_COPY, 0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_COPY", false,0,0x00000000,true), |
| 72 | HOWTO(R_SPARC_GLOB_DAT, 0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_GLOB_DAT",false,0,0x00000000,true), |
| 73 | HOWTO(R_SPARC_JMP_SLOT, 0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_JMP_SLOT",false,0,0x00000000,true), |
| 74 | HOWTO(R_SPARC_RELATIVE, 0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_RELATIVE",false,0,0x00000000,true), |
| 75 | HOWTO(R_SPARC_UA32, 0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_UA32", false,0,0x00000000,true), |
| 76 | #if 0 /* not used yet */ |
| 77 | HOWTO(R_SPARC_PLT32, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_PLT32", false,0,0x00000000,true), |
| 78 | HOWTO(R_SPARC_HIPLT22, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_HIPLT22", false,0,0x00000000,true), |
| 79 | HOWTO(R_SPARC_LOPLT10, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_LOPLT10", false,0,0x00000000,true), |
| 80 | HOWTO(R_SPARC_PCPLT32, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_PCPLT32", false,0,0x00000000,true), |
| 81 | HOWTO(R_SPARC_PCPLT22, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_PCPLT22", false,0,0x00000000,true), |
| 82 | HOWTO(R_SPARC_PCPLT10, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_PCPLT10", false,0,0x00000000,true), |
| 83 | #endif |
| 84 | HOWTO(R_SPARC_10, 0,2,10,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_10", false,0,0x000003ff,true), |
| 85 | HOWTO(R_SPARC_11, 0,2,11,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_11", false,0,0x000007ff,true), |
| 86 | HOWTO(R_SPARC_64, 0,4,00,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_64", false,0,~ (bfd_vma) 0, true), |
| 87 | HOWTO(R_SPARC_OLO10, 0,2,10,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_OLO10", false,0,0x000003ff,true), |
| 88 | HOWTO(R_SPARC_HH22, 42,2,22,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_HH22", false,0,0x003fffff,true), |
| 89 | HOWTO(R_SPARC_HM10, 32,2,10,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_HM10", false,0,0x000003ff,true), |
| 90 | HOWTO(R_SPARC_LM22, 10,2,22,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_LM22", false,0,0x003fffff,true), |
| 91 | HOWTO(R_SPARC_PC_HH22, 42,2,22,true, 0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_HH22", false,0,0x003fffff,true), |
| 92 | HOWTO(R_SPARC_PC_HM10, 32,2,10,true, 0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_HM10", false,0,0x000003ff,true), |
| 93 | HOWTO(R_SPARC_PC_LM22, 10,2,22,true, 0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_LM22", false,0,0x003fffff,true), |
| 94 | HOWTO(R_SPARC_WDISP16, 2,2,16,true, 0,complain_overflow_signed, sparc_elf_wdisp16_reloc,"R_SPARC_WDISP16", false,0,0x00000000,true), |
| 95 | HOWTO(R_SPARC_WDISP19, 2,2,22,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_WDISP19", false,0,0x0007ffff,true), |
| 96 | HOWTO(R_SPARC_UNUSED_42, 0,0, 0,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_UNUSED_42",false,0,0x00000000,true), |
| 97 | HOWTO(R_SPARC_7, 0,2, 7,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_7", false,0,0x0000007f,true), |
| 98 | HOWTO(R_SPARC_5, 0,2, 5,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_5", false,0,0x0000001f,true), |
| 99 | HOWTO(R_SPARC_6, 0,2, 6,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_6", false,0,0x0000003f,true), |
| 100 | }; |
| 101 | |
| 102 | struct elf_reloc_map { |
| 103 | unsigned char bfd_reloc_val; |
| 104 | unsigned char elf_reloc_val; |
| 105 | }; |
| 106 | |
| 107 | static CONST struct elf_reloc_map sparc_reloc_map[] = |
| 108 | { |
| 109 | { BFD_RELOC_NONE, R_SPARC_NONE, }, |
| 110 | { BFD_RELOC_16, R_SPARC_16, }, |
| 111 | { BFD_RELOC_8, R_SPARC_8 }, |
| 112 | { BFD_RELOC_8_PCREL, R_SPARC_DISP8 }, |
| 113 | /* ??? This might cause us to need separate functions in elf{32,64}-sparc.c |
| 114 | (we could still have just one table), but is this reloc ever used? */ |
| 115 | { BFD_RELOC_CTOR, R_SPARC_32 }, /* @@ Assumes 32 bits. */ |
| 116 | { BFD_RELOC_32, R_SPARC_32 }, |
| 117 | { BFD_RELOC_32_PCREL, R_SPARC_DISP32 }, |
| 118 | { BFD_RELOC_HI22, R_SPARC_HI22 }, |
| 119 | { BFD_RELOC_LO10, R_SPARC_LO10, }, |
| 120 | { BFD_RELOC_32_PCREL_S2, R_SPARC_WDISP30 }, |
| 121 | { BFD_RELOC_SPARC22, R_SPARC_22 }, |
| 122 | { BFD_RELOC_SPARC13, R_SPARC_13 }, |
| 123 | { BFD_RELOC_SPARC_GOT10, R_SPARC_GOT10 }, |
| 124 | { BFD_RELOC_SPARC_GOT13, R_SPARC_GOT13 }, |
| 125 | { BFD_RELOC_SPARC_GOT22, R_SPARC_GOT22 }, |
| 126 | { BFD_RELOC_SPARC_PC10, R_SPARC_PC10 }, |
| 127 | { BFD_RELOC_SPARC_PC22, R_SPARC_PC22 }, |
| 128 | { BFD_RELOC_SPARC_WPLT30, R_SPARC_WPLT30 }, |
| 129 | { BFD_RELOC_SPARC_COPY, R_SPARC_COPY }, |
| 130 | { BFD_RELOC_SPARC_GLOB_DAT, R_SPARC_GLOB_DAT }, |
| 131 | { BFD_RELOC_SPARC_JMP_SLOT, R_SPARC_JMP_SLOT }, |
| 132 | { BFD_RELOC_SPARC_RELATIVE, R_SPARC_RELATIVE }, |
| 133 | { BFD_RELOC_SPARC_WDISP22, R_SPARC_WDISP22 }, |
| 134 | /* ??? Doesn't dwarf use this? */ |
| 135 | /*{ BFD_RELOC_SPARC_UA32, R_SPARC_UA32 }, not used?? */ |
| 136 | {BFD_RELOC_SPARC_10, R_SPARC_10}, |
| 137 | {BFD_RELOC_SPARC_11, R_SPARC_11}, |
| 138 | {BFD_RELOC_SPARC_64, R_SPARC_64}, |
| 139 | {BFD_RELOC_SPARC_OLO10, R_SPARC_OLO10}, |
| 140 | {BFD_RELOC_SPARC_HH22, R_SPARC_HH22}, |
| 141 | {BFD_RELOC_SPARC_HM10, R_SPARC_HM10}, |
| 142 | {BFD_RELOC_SPARC_LM22, R_SPARC_LM22}, |
| 143 | {BFD_RELOC_SPARC_PC_HH22, R_SPARC_PC_HH22}, |
| 144 | {BFD_RELOC_SPARC_PC_HM10, R_SPARC_PC_HM10}, |
| 145 | {BFD_RELOC_SPARC_PC_LM22, R_SPARC_PC_LM22}, |
| 146 | {BFD_RELOC_SPARC_WDISP16, R_SPARC_WDISP16}, |
| 147 | {BFD_RELOC_SPARC_WDISP19, R_SPARC_WDISP19}, |
| 148 | {BFD_RELOC_SPARC_7, R_SPARC_7}, |
| 149 | {BFD_RELOC_SPARC_5, R_SPARC_5}, |
| 150 | {BFD_RELOC_SPARC_6, R_SPARC_6}, |
| 151 | }; |
| 152 | |
| 153 | static reloc_howto_type * |
| 154 | sparc64_elf_reloc_type_lookup (abfd, code) |
| 155 | bfd *abfd; |
| 156 | bfd_reloc_code_real_type code; |
| 157 | { |
| 158 | unsigned int i; |
| 159 | for (i = 0; i < sizeof (sparc_reloc_map) / sizeof (struct elf_reloc_map); i++) |
| 160 | { |
| 161 | if (sparc_reloc_map[i].bfd_reloc_val == code) |
| 162 | return &sparc64_elf_howto_table[(int) sparc_reloc_map[i].elf_reloc_val]; |
| 163 | } |
| 164 | return 0; |
| 165 | } |
| 166 | |
| 167 | static void |
| 168 | sparc64_elf_info_to_howto (abfd, cache_ptr, dst) |
| 169 | bfd *abfd; |
| 170 | arelent *cache_ptr; |
| 171 | Elf64_Internal_Rela *dst; |
| 172 | { |
| 173 | BFD_ASSERT (ELF64_R_TYPE (dst->r_info) < (unsigned int) R_SPARC_max); |
| 174 | cache_ptr->howto = &sparc64_elf_howto_table[ELF64_R_TYPE (dst->r_info)]; |
| 175 | } |
| 176 | \f |
| 177 | /* Handle the WDISP16 reloc. */ |
| 178 | |
| 179 | static bfd_reloc_status_type |
| 180 | sparc_elf_wdisp16_reloc (abfd, |
| 181 | reloc_entry, |
| 182 | symbol, |
| 183 | data, |
| 184 | input_section, |
| 185 | output_bfd, |
| 186 | error_message) |
| 187 | bfd *abfd; |
| 188 | arelent *reloc_entry; |
| 189 | asymbol *symbol; |
| 190 | PTR data; |
| 191 | asection *input_section; |
| 192 | bfd *output_bfd; |
| 193 | char **error_message; |
| 194 | { |
| 195 | bfd_vma relocation; |
| 196 | bfd_vma x; |
| 197 | |
| 198 | if (output_bfd != (bfd *) NULL |
| 199 | && (symbol->flags & BSF_SECTION_SYM) == 0 |
| 200 | && (! reloc_entry->howto->partial_inplace |
| 201 | || reloc_entry->addend == 0)) |
| 202 | { |
| 203 | reloc_entry->address += input_section->output_offset; |
| 204 | return bfd_reloc_ok; |
| 205 | } |
| 206 | |
| 207 | if (output_bfd != NULL) |
| 208 | return bfd_reloc_continue; |
| 209 | |
| 210 | if (reloc_entry->address > input_section->_cooked_size) |
| 211 | return bfd_reloc_outofrange; |
| 212 | |
| 213 | relocation = (symbol->value |
| 214 | + symbol->section->output_section->vma |
| 215 | + symbol->section->output_offset); |
| 216 | relocation += reloc_entry->addend; |
| 217 | relocation -= (input_section->output_section->vma |
| 218 | + input_section->output_offset); |
| 219 | relocation -= reloc_entry->address; |
| 220 | |
| 221 | x = bfd_get_32 (abfd, (char *) data + reloc_entry->address); |
| 222 | x |= ((((relocation >> 2) & 0xc000) << 6) |
| 223 | | ((relocation >> 2) & 0x3fff)); |
| 224 | bfd_put_32 (abfd, x, (char *) data + reloc_entry->address); |
| 225 | |
| 226 | if ((bfd_signed_vma) relocation < - 0x40000 |
| 227 | || (bfd_signed_vma) relocation > 0x3ffff) |
| 228 | return bfd_reloc_overflow; |
| 229 | else |
| 230 | return bfd_reloc_ok; |
| 231 | } |
| 232 | \f |
| 233 | /* Relocate a SPARC64 ELF section. */ |
| 234 | |
| 235 | static boolean |
| 236 | sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section, |
| 237 | contents, relocs, local_syms, local_sections) |
| 238 | bfd *output_bfd; |
| 239 | struct bfd_link_info *info; |
| 240 | bfd *input_bfd; |
| 241 | asection *input_section; |
| 242 | bfd_byte *contents; |
| 243 | Elf_Internal_Rela *relocs; |
| 244 | Elf_Internal_Sym *local_syms; |
| 245 | asection **local_sections; |
| 246 | { |
| 247 | Elf_Internal_Shdr *symtab_hdr; |
| 248 | struct elf_link_hash_entry **sym_hashes; |
| 249 | Elf_Internal_Rela *rel; |
| 250 | Elf_Internal_Rela *relend; |
| 251 | |
| 252 | symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; |
| 253 | sym_hashes = elf_sym_hashes (input_bfd); |
| 254 | |
| 255 | rel = relocs; |
| 256 | relend = relocs + input_section->reloc_count; |
| 257 | for (; rel < relend; rel++) |
| 258 | { |
| 259 | int r_type; |
| 260 | reloc_howto_type *howto; |
| 261 | long r_symndx; |
| 262 | struct elf_link_hash_entry *h; |
| 263 | Elf_Internal_Sym *sym; |
| 264 | asection *sec; |
| 265 | bfd_vma relocation; |
| 266 | bfd_reloc_status_type r; |
| 267 | |
| 268 | r_type = ELF64_R_TYPE (rel->r_info); |
| 269 | if (r_type < 0 || r_type >= (int) R_SPARC_max) |
| 270 | { |
| 271 | bfd_set_error (bfd_error_bad_value); |
| 272 | return false; |
| 273 | } |
| 274 | howto = sparc64_elf_howto_table + r_type; |
| 275 | |
| 276 | r_symndx = ELF64_R_SYM (rel->r_info); |
| 277 | |
| 278 | if (info->relocateable) |
| 279 | { |
| 280 | /* This is a relocateable link. We don't have to change |
| 281 | anything, unless the reloc is against a section symbol, |
| 282 | in which case we have to adjust according to where the |
| 283 | section symbol winds up in the output section. */ |
| 284 | if (r_symndx < symtab_hdr->sh_info) |
| 285 | { |
| 286 | sym = local_syms + r_symndx; |
| 287 | if (ELF_ST_TYPE (sym->st_info) == STT_SECTION) |
| 288 | { |
| 289 | sec = local_sections[r_symndx]; |
| 290 | rel->r_addend += sec->output_offset + sym->st_value; |
| 291 | } |
| 292 | } |
| 293 | |
| 294 | continue; |
| 295 | } |
| 296 | |
| 297 | /* This is a final link. */ |
| 298 | h = NULL; |
| 299 | sym = NULL; |
| 300 | sec = NULL; |
| 301 | if (r_symndx < symtab_hdr->sh_info) |
| 302 | { |
| 303 | sym = local_syms + r_symndx; |
| 304 | sec = local_sections[r_symndx]; |
| 305 | relocation = (sec->output_section->vma |
| 306 | + sec->output_offset |
| 307 | + sym->st_value); |
| 308 | } |
| 309 | else |
| 310 | { |
| 311 | h = sym_hashes[r_symndx - symtab_hdr->sh_info]; |
| 312 | while (h->root.type == bfd_link_hash_indirect |
| 313 | || h->root.type == bfd_link_hash_warning) |
| 314 | h = (struct elf_link_hash_entry *) h->root.u.i.link; |
| 315 | if (h->root.type == bfd_link_hash_defined |
| 316 | || h->root.type == bfd_link_hash_defweak) |
| 317 | { |
| 318 | sec = h->root.u.def.section; |
| 319 | relocation = (h->root.u.def.value |
| 320 | + sec->output_section->vma |
| 321 | + sec->output_offset); |
| 322 | } |
| 323 | else if (h->root.type == bfd_link_hash_undefweak) |
| 324 | relocation = 0; |
| 325 | else |
| 326 | { |
| 327 | if (! ((*info->callbacks->undefined_symbol) |
| 328 | (info, h->root.root.string, input_bfd, |
| 329 | input_section, rel->r_offset))) |
| 330 | return false; |
| 331 | relocation = 0; |
| 332 | } |
| 333 | } |
| 334 | |
| 335 | if (r_type != R_SPARC_WDISP16) |
| 336 | r = _bfd_final_link_relocate (howto, input_bfd, input_section, |
| 337 | contents, rel->r_offset, |
| 338 | relocation, rel->r_addend); |
| 339 | else |
| 340 | { |
| 341 | bfd_vma x; |
| 342 | |
| 343 | relocation += rel->r_addend; |
| 344 | relocation -= (input_section->output_section->vma |
| 345 | + input_section->output_offset); |
| 346 | relocation -= rel->r_offset; |
| 347 | |
| 348 | x = bfd_get_32 (input_bfd, contents + rel->r_offset); |
| 349 | x |= ((((relocation >> 2) & 0xc000) << 6) |
| 350 | | ((relocation >> 2) & 0x3fff)); |
| 351 | bfd_put_32 (input_bfd, x, contents + rel->r_offset); |
| 352 | |
| 353 | if ((bfd_signed_vma) relocation < - 0x40000 |
| 354 | || (bfd_signed_vma) relocation > 0x3ffff) |
| 355 | r = bfd_reloc_overflow; |
| 356 | else |
| 357 | r = bfd_reloc_ok; |
| 358 | } |
| 359 | |
| 360 | if (r != bfd_reloc_ok) |
| 361 | { |
| 362 | switch (r) |
| 363 | { |
| 364 | default: |
| 365 | case bfd_reloc_outofrange: |
| 366 | abort (); |
| 367 | case bfd_reloc_overflow: |
| 368 | { |
| 369 | const char *name; |
| 370 | |
| 371 | if (h != NULL) |
| 372 | name = h->root.root.string; |
| 373 | else |
| 374 | { |
| 375 | name = (bfd_elf_string_from_elf_section |
| 376 | (input_bfd, |
| 377 | symtab_hdr->sh_link, |
| 378 | sym->st_name)); |
| 379 | if (name == NULL) |
| 380 | return false; |
| 381 | if (*name == '\0') |
| 382 | name = bfd_section_name (input_bfd, sec); |
| 383 | } |
| 384 | if (! ((*info->callbacks->reloc_overflow) |
| 385 | (info, name, howto->name, (bfd_vma) 0, |
| 386 | input_bfd, input_section, rel->r_offset))) |
| 387 | return false; |
| 388 | } |
| 389 | break; |
| 390 | } |
| 391 | } |
| 392 | } |
| 393 | |
| 394 | return true; |
| 395 | } |
| 396 | |
| 397 | /* Set the right machine number for a SPARC64 ELF file. */ |
| 398 | |
| 399 | static boolean |
| 400 | sparc64_elf_object_p (abfd) |
| 401 | bfd *abfd; |
| 402 | { |
| 403 | return bfd_default_set_arch_mach (abfd, bfd_arch_sparc, bfd_mach_sparc_v9); |
| 404 | } |
| 405 | |
| 406 | #define TARGET_BIG_SYM bfd_elf64_sparc_vec |
| 407 | #define TARGET_BIG_NAME "elf64-sparc" |
| 408 | #define ELF_ARCH bfd_arch_sparc |
| 409 | #define ELF_MACHINE_CODE EM_SPARC64 |
| 410 | #define ELF_MAXPAGESIZE 0x100000 |
| 411 | |
| 412 | #define elf_info_to_howto sparc64_elf_info_to_howto |
| 413 | #define bfd_elf64_bfd_reloc_type_lookup sparc64_elf_reloc_type_lookup |
| 414 | #define elf_backend_relocate_section sparc64_elf_relocate_section |
| 415 | #define elf_backend_object_p sparc64_elf_object_p |
| 416 | |
| 417 | #include "elf64-target.h" |