]> Git Repo - binutils.git/blob - bfd/elf64-sparc.c
* interp.c (sim_open): New arg `kind'.
[binutils.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.047218 seconds and 4 git commands to generate.