* elf64-sparc.c (sparc64_elf_object_p): bfd_mach_sparc64 renamed to
[deliverable/binutils-gdb.git] / bfd / elf64-sparc.c
1 /* SPARC-specific support for 64-bit ELF
2 Copyright 1993, 1995 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 static bfd_reloc_status_type sparc64_elf_wdisp16_reloc
29 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
30 static boolean sparc64_elf_relocate_section
31 PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
32 Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
33 static boolean sparc64_elf_object_p PARAMS ((bfd *));
34
35 enum reloc_type
36 {
37 R_SPARC_NONE = 0,
38 R_SPARC_8, R_SPARC_16, R_SPARC_32,
39 R_SPARC_DISP8, R_SPARC_DISP16, R_SPARC_DISP32,
40 R_SPARC_WDISP30, R_SPARC_WDISP22,
41 R_SPARC_HI22, R_SPARC_22,
42 R_SPARC_13, R_SPARC_LO10,
43 R_SPARC_GOT10, R_SPARC_GOT13, R_SPARC_GOT22,
44 R_SPARC_PC10, R_SPARC_PC22,
45 R_SPARC_WPLT30,
46 R_SPARC_COPY,
47 R_SPARC_GLOB_DAT, R_SPARC_JMP_SLOT,
48 R_SPARC_RELATIVE,
49 R_SPARC_UA32,
50
51 /* v9 relocs */
52 R_SPARC_10, R_SPARC_11, R_SPARC_64,
53 R_SPARC_OLO10, R_SPARC_HH22, R_SPARC_HM10, R_SPARC_LM22,
54 R_SPARC_PC_HH22, R_SPARC_PC_HM10, R_SPARC_PC_LM22,
55 R_SPARC_WDISP16, R_SPARC_WDISP19,
56 R_SPARC_GLOB_JMP, R_SPARC_LO7,
57
58 R_SPARC_max
59 };
60
61 #if 0
62 static CONST char *CONST reloc_type_names[] =
63 {
64 "R_SPARC_NONE",
65 "R_SPARC_8", "R_SPARC_16", "R_SPARC_32",
66 "R_SPARC_DISP8", "R_SPARC_DISP16", "R_SPARC_DISP32",
67 "R_SPARC_WDISP30", "R_SPARC_WDISP22",
68 "R_SPARC_HI22", "R_SPARC_22",
69 "R_SPARC_13", "R_SPARC_LO10",
70 "R_SPARC_GOT10", "R_SPARC_GOT13", "R_SPARC_GOT22",
71 "R_SPARC_PC10", "R_SPARC_PC22",
72 "R_SPARC_WPLT30",
73 "R_SPARC_COPY",
74 "R_SPARC_GLOB_DAT", "R_SPARC_JMP_SLOT",
75 "R_SPARC_RELATIVE",
76 "R_SPARC_UA32",
77
78 "R_SPARC_10", "R_SPARC_11", "R_SPARC_64",
79 "R_SPARC_OLO10", "R_SPARC_HH22", "R_SPARC_HM10", "R_SPARC_LM22",
80 "R_SPARC_PC_HH22", "R_SPARC_PC_HM10", "R_SPARC_PC_LM22",
81 "R_SPARC_WDISP16", "R_SPARC_WDISP19",
82 "R_SPARC_GLOB_JMP", "R_SPARC_LO7",
83 };
84 #endif
85
86 extern void abort ();
87 #define DIE ((bfd_reloc_status_type(*)())abort)
88
89 static reloc_howto_type elf_sparc_howto_table[] =
90 {
91 HOWTO (R_SPARC_NONE, 0, 0, 0, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_NONE", false, 0, 0x00000000, true),
92 HOWTO (R_SPARC_8, 0, 0, 8, false, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_SPARC_8", false, 0, 0x000000ff, true),
93 HOWTO (R_SPARC_16, 0, 1, 16, false, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_SPARC_16", false, 0, 0x0000ffff, true),
94 HOWTO (R_SPARC_32, 0, 2, 32, false, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_SPARC_32", false, 0, 0xffffffff, true),
95 HOWTO (R_SPARC_DISP8, 0, 0, 8, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_DISP8", false, 0, 0x000000ff, true),
96 HOWTO (R_SPARC_DISP16, 0, 1, 16, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_DISP16", false, 0, 0x0000ffff, true),
97 HOWTO (R_SPARC_DISP32, 0, 2, 32, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_DISP32", false, 0, 0x00ffffff, true),
98 HOWTO (R_SPARC_WDISP30, 2, 2, 30, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_WDISP30", false, 0, 0x3fffffff, true),
99 HOWTO (R_SPARC_WDISP22, 2, 2, 22, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_WDISP22", false, 0, 0x003fffff, true),
100 HOWTO (R_SPARC_HI22, 10, 2, 22, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_HI22", false, 0, 0x003fffff, true),
101 HOWTO (R_SPARC_22, 0, 2, 22, false, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_SPARC_22", false, 0, 0x003fffff, true),
102 HOWTO (R_SPARC_13, 0, 2, 13, false, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_SPARC_13", false, 0, 0x00001fff, true),
103 HOWTO (R_SPARC_LO10, 0, 2, 10, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_LO10", false, 0, 0x000003ff, true),
104 HOWTO (R_SPARC_GOT10, 0, 2, 10, false, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_SPARC_GOT10", false, 0, 0x000003ff, true),
105 HOWTO (R_SPARC_GOT13, 0, 2, 13, false, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_SPARC_GOT13", false, 0, 0x00001fff, true),
106 HOWTO (R_SPARC_GOT22, 10, 2, 22, false, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_SPARC_GOT22", false, 0, 0x003fffff, true),
107 HOWTO (R_SPARC_PC10, 0, 2, 10, false, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_SPARC_PC10", false, 0, 0x000003ff, true),
108 HOWTO (R_SPARC_PC22, 0, 2, 22, false, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_SPARC_PC22", false, 0, 0x003fffff, true),
109 HOWTO (R_SPARC_WPLT30, 0, 0, 00, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_WPLT30", false, 0, 0x00000000, true),
110 HOWTO (R_SPARC_COPY, 0, 0, 00, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_COPY", false, 0, 0x00000000, true),
111 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),
112 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),
113 HOWTO (R_SPARC_RELATIVE, 0, 0, 00, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_RELATIVE", false, 0, 0x00000000, true),
114 HOWTO (R_SPARC_UA32, 0, 0, 00, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_UA32", false, 0, 0x00000000, true),
115 HOWTO (R_SPARC_10, 0, 2, 10, false, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_SPARC_10", false, 0, 0x000003ff, true),
116 HOWTO (R_SPARC_11, 0, 2, 11, false, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_SPARC_11", false, 0, 0x000007ff, true),
117 HOWTO (R_SPARC_64, 0, 4, 00, false, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_SPARC_64", false, 0, (((bfd_vma) 0xffffffff) << 32) + 0xffffffff, true),
118 HOWTO (R_SPARC_OLO10, 0, 2, 10, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_OLO10", false, 0, 0x000003ff, true),
119 HOWTO (R_SPARC_HH22, 42, 2, 22, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_HH22", false, 0, 0x003fffff, true),
120 HOWTO (R_SPARC_HM10, 32, 2, 10, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_HM10", false, 0, 0x000003ff, true),
121 HOWTO (R_SPARC_LM22, 10, 2, 22, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_LM22", false, 0, 0x003fffff, true),
122 HOWTO (R_SPARC_PC_HH22, 42, 2, 22, true, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_HH22", false, 0, 0x003fffff, true),
123 HOWTO (R_SPARC_PC_HM10, 32, 2, 10, true, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_HM10", false, 0, 0x000003ff, true),
124 HOWTO (R_SPARC_PC_LM22, 10, 2, 22, true, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_LM22", false, 0, 0x003fffff, true),
125 HOWTO (R_SPARC_WDISP16, 2, 2, 16, true, 0, complain_overflow_signed, sparc64_elf_wdisp16_reloc, "R_SPARC_WDISP16", false, 0, 0, true),
126 HOWTO (R_SPARC_WDISP19, 2, 2, 22, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_WDISP19", false, 0, 0x0007ffff, true),
127 HOWTO (R_SPARC_GLOB_JMP, 0, 0, 00, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_GLOB_DAT", false, 0, 0x00000000, true),
128 HOWTO (R_SPARC_LO7, 0, 2, 7, false, 0, complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_LO7", false, 0, 0x0000007f, true),
129 };
130
131 /* Handle the WDISP16 reloc. */
132
133 static bfd_reloc_status_type
134 sparc64_elf_wdisp16_reloc (abfd,
135 reloc_entry,
136 symbol,
137 data,
138 input_section,
139 output_bfd,
140 error_message)
141 bfd *abfd;
142 arelent *reloc_entry;
143 asymbol *symbol;
144 PTR data;
145 asection *input_section;
146 bfd *output_bfd;
147 char **error_message;
148 {
149 bfd_vma relocation;
150 bfd_vma x;
151
152 if (output_bfd != (bfd *) NULL
153 && (symbol->flags & BSF_SECTION_SYM) == 0
154 && (! reloc_entry->howto->partial_inplace
155 || reloc_entry->addend == 0))
156 {
157 reloc_entry->address += input_section->output_offset;
158 return bfd_reloc_ok;
159 }
160
161 if (output_bfd != NULL)
162 return bfd_reloc_continue;
163
164 if (reloc_entry->address > input_section->_cooked_size)
165 return bfd_reloc_outofrange;
166
167 relocation = (symbol->value
168 + symbol->section->output_section->vma
169 + symbol->section->output_offset);
170 relocation += reloc_entry->addend;
171 relocation -= (input_section->output_section->vma
172 + input_section->output_offset);
173 relocation -= reloc_entry->address;
174
175 x = bfd_get_32 (abfd, (char *) data + reloc_entry->address);
176 x |= ((((relocation >> 2) & 0xc000) << 6)
177 | ((relocation >> 2) & 0x3fff));
178 bfd_put_32 (abfd, x, (char *) data + reloc_entry->address);
179
180 if ((bfd_signed_vma) relocation < - 0x40000
181 || (bfd_signed_vma) relocation > 0x3ffff)
182 return bfd_reloc_overflow;
183 else
184 return bfd_reloc_ok;
185 }
186
187 struct elf_reloc_map
188 {
189 unsigned char bfd_reloc_val;
190 unsigned char elf_reloc_val;
191 };
192
193 static CONST struct elf_reloc_map sparc_reloc_map[] =
194 {
195 {BFD_RELOC_NONE, R_SPARC_NONE,},
196 {BFD_RELOC_16, R_SPARC_16,},
197 {BFD_RELOC_8, R_SPARC_8},
198 {BFD_RELOC_8_PCREL, R_SPARC_DISP8},
199 {BFD_RELOC_CTOR, R_SPARC_32}, /* @@ Assumes 32 bits. */
200 {BFD_RELOC_32, R_SPARC_32},
201 {BFD_RELOC_32_PCREL, R_SPARC_DISP32},
202 {BFD_RELOC_HI22, R_SPARC_HI22},
203 {BFD_RELOC_LO10, R_SPARC_LO10,},
204 {BFD_RELOC_32_PCREL_S2, R_SPARC_WDISP30},
205 {BFD_RELOC_SPARC22, R_SPARC_22},
206 {BFD_RELOC_SPARC13, R_SPARC_13},
207 {BFD_RELOC_SPARC_GOT10, R_SPARC_GOT10},
208 {BFD_RELOC_SPARC_GOT13, R_SPARC_GOT13},
209 {BFD_RELOC_SPARC_GOT22, R_SPARC_GOT22},
210 {BFD_RELOC_SPARC_PC10, R_SPARC_PC10},
211 {BFD_RELOC_SPARC_PC22, R_SPARC_PC22},
212 {BFD_RELOC_SPARC_WPLT30, R_SPARC_WPLT30},
213 {BFD_RELOC_SPARC_COPY, R_SPARC_COPY},
214 {BFD_RELOC_SPARC_GLOB_DAT, R_SPARC_GLOB_DAT},
215 {BFD_RELOC_SPARC_JMP_SLOT, R_SPARC_JMP_SLOT},
216 {BFD_RELOC_SPARC_RELATIVE, R_SPARC_RELATIVE},
217 {BFD_RELOC_SPARC_WDISP22, R_SPARC_WDISP22},
218 /* { BFD_RELOC_SPARC_UA32, R_SPARC_UA32 }, not used?? */
219 {BFD_RELOC_SPARC_10, R_SPARC_10},
220 {BFD_RELOC_SPARC_11, R_SPARC_11},
221 {BFD_RELOC_SPARC_64, R_SPARC_64},
222 {BFD_RELOC_SPARC_OLO10, R_SPARC_OLO10},
223 {BFD_RELOC_SPARC_HH22, R_SPARC_HH22},
224 {BFD_RELOC_SPARC_HM10, R_SPARC_HM10},
225 {BFD_RELOC_SPARC_LM22, R_SPARC_LM22},
226 {BFD_RELOC_SPARC_PC_HH22, R_SPARC_PC_HH22},
227 {BFD_RELOC_SPARC_PC_HM10, R_SPARC_PC_HM10},
228 {BFD_RELOC_SPARC_PC_LM22, R_SPARC_PC_LM22},
229 {BFD_RELOC_SPARC_WDISP16, R_SPARC_WDISP16},
230 {BFD_RELOC_SPARC_WDISP19, R_SPARC_WDISP19},
231 {BFD_RELOC_SPARC_GLOB_JMP, R_SPARC_GLOB_JMP},
232 {BFD_RELOC_SPARC_LO7, R_SPARC_LO7},
233 };
234
235 static reloc_howto_type *
236 bfd_elf64_bfd_reloc_type_lookup (abfd, code)
237 bfd *abfd;
238 bfd_reloc_code_real_type code;
239 {
240 int i;
241 for (i = 0; i < sizeof (sparc_reloc_map) / sizeof (struct elf_reloc_map); i++)
242 {
243 if (sparc_reloc_map[i].bfd_reloc_val == code)
244 return &elf_sparc_howto_table[(int) sparc_reloc_map[i].elf_reloc_val];
245 }
246 return 0;
247 }
248
249 static void
250 elf_info_to_howto (abfd, cache_ptr, dst)
251 bfd *abfd;
252 arelent *cache_ptr;
253 Elf64_Internal_Rela *dst;
254 {
255 BFD_ASSERT (ELF64_R_TYPE (dst->r_info) < (unsigned int) R_SPARC_max);
256 cache_ptr->howto = &elf_sparc_howto_table[ELF64_R_TYPE (dst->r_info)];
257 }
258
259 /* Relocate a SPARC64 ELF section. */
260
261 static boolean
262 sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
263 contents, relocs, local_syms, local_sections)
264 bfd *output_bfd;
265 struct bfd_link_info *info;
266 bfd *input_bfd;
267 asection *input_section;
268 bfd_byte *contents;
269 Elf_Internal_Rela *relocs;
270 Elf_Internal_Sym *local_syms;
271 asection **local_sections;
272 {
273 Elf_Internal_Shdr *symtab_hdr;
274 struct elf_link_hash_entry **sym_hashes;
275 Elf_Internal_Rela *rel;
276 Elf_Internal_Rela *relend;
277
278 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
279 sym_hashes = elf_sym_hashes (input_bfd);
280
281 rel = relocs;
282 relend = relocs + input_section->reloc_count;
283 for (; rel < relend; rel++)
284 {
285 int r_type;
286 reloc_howto_type *howto;
287 long r_symndx;
288 struct elf_link_hash_entry *h;
289 Elf_Internal_Sym *sym;
290 asection *sec;
291 bfd_vma relocation;
292 bfd_reloc_status_type r;
293
294 r_type = ELF64_R_TYPE (rel->r_info);
295 if (r_type < 0 || r_type >= (int) R_SPARC_max)
296 {
297 bfd_set_error (bfd_error_bad_value);
298 return false;
299 }
300 howto = elf_sparc_howto_table + r_type;
301
302 r_symndx = ELF64_R_SYM (rel->r_info);
303
304 if (info->relocateable)
305 {
306 /* This is a relocateable link. We don't have to change
307 anything, unless the reloc is against a section symbol,
308 in which case we have to adjust according to where the
309 section symbol winds up in the output section. */
310 if (r_symndx < symtab_hdr->sh_info)
311 {
312 sym = local_syms + r_symndx;
313 if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
314 {
315 sec = local_sections[r_symndx];
316 rel->r_addend += sec->output_offset + sym->st_value;
317 }
318 }
319
320 continue;
321 }
322
323 /* This is a final link. */
324 h = NULL;
325 sym = NULL;
326 sec = NULL;
327 if (r_symndx < symtab_hdr->sh_info)
328 {
329 sym = local_syms + r_symndx;
330 sec = local_sections[r_symndx];
331 relocation = (sec->output_section->vma
332 + sec->output_offset
333 + sym->st_value);
334 }
335 else
336 {
337 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
338 if (h->root.type == bfd_link_hash_defined
339 || h->root.type == bfd_link_hash_defweak)
340 {
341 sec = h->root.u.def.section;
342 relocation = (h->root.u.def.value
343 + sec->output_section->vma
344 + sec->output_offset);
345 }
346 else if (h->root.type == bfd_link_hash_undefweak)
347 relocation = 0;
348 else
349 {
350 if (! ((*info->callbacks->undefined_symbol)
351 (info, h->root.root.string, input_bfd,
352 input_section, rel->r_offset)))
353 return false;
354 relocation = 0;
355 }
356 }
357
358 if (r_type != R_SPARC_WDISP16)
359 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
360 contents, rel->r_offset,
361 relocation, rel->r_addend);
362 else
363 {
364 bfd_vma x;
365
366 relocation += rel->r_addend;
367 relocation -= (input_section->output_section->vma
368 + input_section->output_offset);
369 relocation -= rel->r_offset;
370
371 x = bfd_get_32 (input_bfd, contents + rel->r_offset);
372 x |= ((((relocation >> 2) & 0xc000) << 6)
373 | ((relocation >> 2) & 0x3fff));
374 bfd_put_32 (input_bfd, x, contents + rel->r_offset);
375
376 if ((bfd_signed_vma) relocation < - 0x40000
377 || (bfd_signed_vma) relocation > 0x3ffff)
378 r = bfd_reloc_overflow;
379 else
380 r = bfd_reloc_ok;
381 }
382
383 if (r != bfd_reloc_ok)
384 {
385 switch (r)
386 {
387 default:
388 case bfd_reloc_outofrange:
389 abort ();
390 case bfd_reloc_overflow:
391 {
392 const char *name;
393
394 if (h != NULL)
395 name = h->root.root.string;
396 else
397 {
398 name = (bfd_elf_string_from_elf_section
399 (input_bfd,
400 symtab_hdr->sh_link,
401 sym->st_name));
402 if (name == NULL)
403 return false;
404 if (*name == '\0')
405 name = bfd_section_name (input_bfd, sec);
406 }
407 if (! ((*info->callbacks->reloc_overflow)
408 (info, name, howto->name, (bfd_vma) 0,
409 input_bfd, input_section, rel->r_offset)))
410 return false;
411 }
412 break;
413 }
414 }
415 }
416
417 return true;
418 }
419
420 /* Set the right machine number for a SPARC64 ELF file. */
421
422 static boolean
423 sparc64_elf_object_p (abfd)
424 bfd *abfd;
425 {
426 return bfd_default_set_arch_mach (abfd, bfd_arch_sparc, bfd_mach_sparc_v9);
427 }
428
429 #define TARGET_BIG_SYM bfd_elf64_sparc_vec
430 #define TARGET_BIG_NAME "elf64-sparc"
431 #define ELF_ARCH bfd_arch_sparc
432 #define ELF_MACHINE_CODE EM_SPARC64
433 #define ELF_MAXPAGESIZE 0x100000
434
435 #define elf_backend_relocate_section sparc64_elf_relocate_section
436 #define elf_backend_object_p sparc64_elf_object_p
437
438 #include "elf64-target.h"
This page took 0.042611 seconds and 5 git commands to generate.