]> Git Repo - binutils.git/blob - bfd/elf32-mn10200.c
d86c18def0fe8db1b087566fccb794bd08dabd25
[binutils.git] / bfd / elf32-mn10200.c
1 /* Matsushita 10200 specific support for 32-bit ELF
2    Copyright (C) 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 #include "bfd.h"
21 #include "sysdep.h"
22 #include "libbfd.h"
23 #include "elf-bfd.h"
24
25 static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
26   PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
27 static void mn10200_info_to_howto
28   PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));
29
30
31 /* We have to use RELA instructions since md_apply_fix3 in the assembler
32    does absolutely nothing.  */
33 #define USE_RELA
34
35 enum reloc_type
36 {
37   R_MN10200_NONE = 0,
38   R_MN10200_32,
39   R_MN10200_16,
40   R_MN10200_8,
41   R_MN10200_24,
42   R_MN10200_PCREL8,
43   R_MN10200_PCREL16,
44   R_MN10200_PCREL24,
45   R_MN10200_MAX
46 };
47
48 static reloc_howto_type elf_mn10200_howto_table[] =
49 {
50   /* Dummy relocation.  Does nothing.  */
51   HOWTO (R_MN10200_NONE,
52          0,
53          2,
54          16,
55          false,
56          0,
57          complain_overflow_bitfield,
58          bfd_elf_generic_reloc,
59          "R_MN10200_NONE",
60          false,
61          0,
62          0,
63          false),
64   /* Standard 32 bit reloc.  */
65   HOWTO (R_MN10200_32,
66          0,
67          2,
68          32,
69          false,
70          0,
71          complain_overflow_bitfield,
72          bfd_elf_generic_reloc,
73          "R_MN10200_32",
74          false,
75          0xffffffff,
76          0xffffffff,
77          false),
78   /* Standard 16 bit reloc.  */
79   HOWTO (R_MN10200_16,
80          0,
81          1,
82          16,
83          false,
84          0,
85          complain_overflow_bitfield,
86          bfd_elf_generic_reloc,
87          "R_MN10200_16",
88          false,
89          0xffff,
90          0xffff,
91          false),
92   /* Standard 8 bit reloc.  */
93   HOWTO (R_MN10200_8,
94          0,
95          0,
96          8,
97          false,
98          0,
99          complain_overflow_bitfield,
100          bfd_elf_generic_reloc,
101          "R_MN10200_8",
102          false,
103          0xff,
104          0xff,
105          false),
106   /* Standard 24 bit reloc.  */
107   HOWTO (R_MN10200_24,
108          0,
109          2,
110          24,
111          false,
112          0,
113          complain_overflow_bitfield,
114          bfd_elf_generic_reloc,
115          "R_MN10200_24",
116          false,
117          0xffffff,
118          0xffffff,
119          false),
120   /* Simple 8 pc-relative reloc.  */
121   HOWTO (R_MN10200_PCREL8,
122          0,
123          0,
124          8,
125          true,
126          0,
127          complain_overflow_bitfield,
128          bfd_elf_generic_reloc,
129          "R_MN10200_PCREL8",
130          false,
131          0xff,
132          0xff,
133          true),
134   /* Simple 16 pc-relative reloc.  */
135   HOWTO (R_MN10200_PCREL16,
136          0,
137          1,
138          16,
139          true,
140          0,
141          complain_overflow_bitfield,
142          bfd_elf_generic_reloc,
143          "R_MN10200_PCREL16",
144          false,
145          0xffff,
146          0xffff,
147          true),
148   /* Simple 32bit pc-relative reloc with a 1 byte adjustment
149      to get the pc-relative offset correct.  */
150   HOWTO (R_MN10200_PCREL24,
151          0,
152          2,
153          24,
154          true,
155          0,
156          complain_overflow_bitfield,
157          bfd_elf_generic_reloc,
158          "R_MN10200_PCREL24",
159          false,
160          0xffffff,
161          0xffffff,
162          true),
163 };
164
165 struct mn10200_reloc_map
166 {
167   unsigned char bfd_reloc_val;
168   unsigned char elf_reloc_val;
169 };
170
171 static const struct mn10200_reloc_map mn10200_reloc_map[] =
172 {
173   { BFD_RELOC_NONE, R_MN10200_NONE, },
174   { BFD_RELOC_32, R_MN10200_32, },
175   { BFD_RELOC_16, R_MN10200_16, },
176   { BFD_RELOC_8, R_MN10200_8, },
177   { BFD_RELOC_24, R_MN10200_24, },
178   { BFD_RELOC_8_PCREL, R_MN10200_PCREL8, },
179   { BFD_RELOC_16_PCREL, R_MN10200_PCREL16, },
180   { BFD_RELOC_24_PCREL, R_MN10200_PCREL24, },
181 };
182
183 static reloc_howto_type *
184 bfd_elf32_bfd_reloc_type_lookup (abfd, code)
185      bfd *abfd;
186      bfd_reloc_code_real_type code;
187 {
188   unsigned int i;
189
190   for (i = 0;
191        i < sizeof (mn10200_reloc_map) / sizeof (struct mn10200_reloc_map);
192        i++)
193     {
194       if (mn10200_reloc_map[i].bfd_reloc_val == code)
195         return &elf_mn10200_howto_table[mn10200_reloc_map[i].elf_reloc_val];
196     }
197
198   return NULL;
199 }
200
201 /* Set the howto pointer for an MN10200 ELF reloc.  */
202
203 static void
204 mn10200_info_to_howto (abfd, cache_ptr, dst)
205      bfd *abfd;
206      arelent *cache_ptr;
207      Elf32_Internal_Rela *dst;
208 {
209   unsigned int r_type;
210
211   r_type = ELF32_R_TYPE (dst->r_info);
212   BFD_ASSERT (r_type < (unsigned int) R_MN10200_MAX);
213   cache_ptr->howto = &elf_mn10200_howto_table[r_type];
214 }
215
216 /* Perform a relocation as part of a final link.  */
217 static bfd_reloc_status_type
218 mn10200_elf_final_link_relocate (howto, input_bfd, output_bfd,
219                                  input_section, contents, offset, value,
220                                  addend, info, sym_sec, is_local)
221      reloc_howto_type *howto;
222      bfd *input_bfd;
223      bfd *output_bfd;
224      asection *input_section;
225      bfd_byte *contents;
226      bfd_vma offset;
227      bfd_vma value;
228      bfd_vma addend;
229      struct bfd_link_info *info;
230      asection *sym_sec;
231      int is_local;
232 {
233   unsigned long insn;
234   unsigned long r_type = howto->type;
235   bfd_byte *hit_data = contents + offset;
236
237   switch (r_type)
238     {
239
240     case R_MN10200_NONE:
241       return bfd_reloc_ok;
242
243     case R_MN10200_32:
244       value += bfd_get_32 (input_bfd, hit_data);
245       value += addend;
246       bfd_put_32 (input_bfd, value, hit_data);
247       return bfd_reloc_ok;
248
249     case R_MN10200_16:
250       value += (short)bfd_get_16 (input_bfd, hit_data);
251       value += addend;
252
253       if ((long)value > 0x7fff || (long)value < -0x8000)
254         return bfd_reloc_overflow;
255
256       bfd_put_16 (input_bfd, value, hit_data);
257       return bfd_reloc_ok;
258
259     case R_MN10200_8:
260       value += (char)bfd_get_8 (input_bfd, hit_data);
261       value += addend;
262
263       if ((long)value > 0x7fff || (long)value < -0x8000)
264         return bfd_reloc_overflow;
265
266       bfd_put_8 (input_bfd, value, hit_data);
267       return bfd_reloc_ok;
268
269     case R_MN10200_24:
270       value += (bfd_get_32 (input_bfd, hit_data) & 0xffffff);
271       value += addend;
272
273       if ((long)value > 0x7fffff || (long)value < -0x800000)
274         return bfd_reloc_overflow;
275
276       value &= 0xffffff;
277       value |= (bfd_get_32 (input_bfd, hit_data) & 0xff000000);
278       bfd_put_32 (input_bfd, value, hit_data);
279       return bfd_reloc_ok;
280
281     case R_MN10200_PCREL8:
282       value -= (input_section->output_section->vma
283                 + input_section->output_offset);
284       value -= offset;
285       value += addend;
286
287       if ((long)value > 0xff || (long)value < -0x100)
288         return bfd_reloc_overflow;
289
290       bfd_put_8 (input_bfd, value, hit_data);
291       return bfd_reloc_ok;
292
293     case R_MN10200_PCREL16:
294       value -= (input_section->output_section->vma
295                 + input_section->output_offset);
296       value -= offset;
297       value += addend;
298
299       if ((long)value > 0xffff || (long)value < -0x10000)
300         return bfd_reloc_overflow;
301
302       bfd_put_16 (input_bfd, value, hit_data);
303       return bfd_reloc_ok;
304
305     case R_MN10200_PCREL24:
306       value -= (input_section->output_section->vma
307                 + input_section->output_offset);
308       value -= offset;
309       value += addend;
310
311       if ((long)value > 0xffffff || (long)value < -0x1000000)
312         return bfd_reloc_overflow;
313
314       value &= 0xffffff;
315       value |= (bfd_get_32 (input_bfd, hit_data) & 0xff000000);
316       bfd_put_32 (input_bfd, value, hit_data);
317       return bfd_reloc_ok;
318
319     default:
320       return bfd_reloc_notsupported;
321     }
322 }
323
324 \f
325 /* Relocate an MN10200 ELF section.  */
326 static boolean
327 mn10200_elf_relocate_section (output_bfd, info, input_bfd, input_section,
328                               contents, relocs, local_syms, local_sections)
329      bfd *output_bfd;
330      struct bfd_link_info *info;
331      bfd *input_bfd;
332      asection *input_section;
333      bfd_byte *contents;
334      Elf_Internal_Rela *relocs;
335      Elf_Internal_Sym *local_syms;
336      asection **local_sections;
337 {
338   Elf_Internal_Shdr *symtab_hdr;
339   struct elf_link_hash_entry **sym_hashes;
340   Elf_Internal_Rela *rel, *relend;
341
342   symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
343   sym_hashes = elf_sym_hashes (input_bfd);
344
345   rel = relocs;
346   relend = relocs + input_section->reloc_count;
347   for (; rel < relend; rel++)
348     {
349       int r_type;
350       reloc_howto_type *howto;
351       unsigned long r_symndx;
352       Elf_Internal_Sym *sym;
353       asection *sec;
354       struct elf_link_hash_entry *h;
355       bfd_vma relocation;
356       bfd_reloc_status_type r;
357
358       r_symndx = ELF32_R_SYM (rel->r_info);
359       r_type = ELF32_R_TYPE (rel->r_info);
360       howto = elf_mn10200_howto_table + r_type;
361
362       if (info->relocateable)
363         {
364           /* This is a relocateable link.  We don't have to change
365              anything, unless the reloc is against a section symbol,
366              in which case we have to adjust according to where the
367              section symbol winds up in the output section.  */
368           if (r_symndx < symtab_hdr->sh_info)
369             {
370               sym = local_syms + r_symndx;
371               if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
372                 {
373                   sec = local_sections[r_symndx];
374                   rel->r_addend += sec->output_offset + sym->st_value;
375                 }
376             }
377
378           continue;
379         }
380
381       /* This is a final link.  */
382       h = NULL;
383       sym = NULL;
384       sec = NULL;
385       if (r_symndx < symtab_hdr->sh_info)
386         {
387           sym = local_syms + r_symndx;
388           sec = local_sections[r_symndx];
389           relocation = (sec->output_section->vma
390                         + sec->output_offset
391                         + sym->st_value);
392         }
393       else
394         {
395           h = sym_hashes[r_symndx - symtab_hdr->sh_info];
396           while (h->root.type == bfd_link_hash_indirect
397                  || h->root.type == bfd_link_hash_warning)
398             h = (struct elf_link_hash_entry *) h->root.u.i.link;
399           if (h->root.type == bfd_link_hash_defined
400               || h->root.type == bfd_link_hash_defweak)
401             {
402               sec = h->root.u.def.section;
403               relocation = (h->root.u.def.value
404                             + sec->output_section->vma
405                             + sec->output_offset);
406             }
407           else if (h->root.type == bfd_link_hash_undefweak)
408             relocation = 0;
409           else
410             {
411               if (! ((*info->callbacks->undefined_symbol)
412                      (info, h->root.root.string, input_bfd,
413                       input_section, rel->r_offset)))
414                 return false;
415               relocation = 0;
416             }
417         }
418
419       r = mn10200_elf_final_link_relocate (howto, input_bfd, output_bfd,
420                                            input_section,
421                                            contents, rel->r_offset,
422                                            relocation, rel->r_addend,
423                                            info, sec, h == NULL);
424
425       if (r != bfd_reloc_ok)
426         {
427           const char *name;
428           const char *msg = (const char *)0;
429
430           if (h != NULL)
431             name = h->root.root.string;
432           else
433             {
434               name = (bfd_elf_string_from_elf_section
435                       (input_bfd, symtab_hdr->sh_link, sym->st_name));
436               if (name == NULL || *name == '\0')
437                 name = bfd_section_name (input_bfd, sec);
438             }
439
440           switch (r)
441             {
442             case bfd_reloc_overflow:
443               if (! ((*info->callbacks->reloc_overflow)
444                      (info, name, howto->name, (bfd_vma) 0,
445                       input_bfd, input_section, rel->r_offset)))
446                 return false;
447               break;
448
449             case bfd_reloc_undefined:
450               if (! ((*info->callbacks->undefined_symbol)
451                      (info, name, input_bfd, input_section,
452                       rel->r_offset)))
453                 return false;
454               break;
455
456             case bfd_reloc_outofrange:
457               msg = "internal error: out of range error";
458               goto common_error;
459
460             case bfd_reloc_notsupported:
461               msg = "internal error: unsupported relocation error";
462               goto common_error;
463
464             case bfd_reloc_dangerous:
465               msg = "internal error: dangerous error";
466               goto common_error;
467
468             default:
469               msg = "internal error: unknown error";
470               /* fall through */
471
472             common_error:
473               if (!((*info->callbacks->warning)
474                     (info, msg, name, input_bfd, input_section,
475                      rel->r_offset)))
476                 return false;
477               break;
478             }
479         }
480     }
481
482   return true;
483 }
484
485 #define TARGET_LITTLE_SYM       bfd_elf32_mn10200_vec
486 #define TARGET_LITTLE_NAME      "elf32-mn10200"
487 #define ELF_ARCH                bfd_arch_mn10200
488 #define ELF_MACHINE_CODE        EM_CYGNUS_MN10200
489 #define ELF_MAXPAGESIZE         0x1000
490
491 #define elf_info_to_howto       mn10200_info_to_howto
492 #define elf_info_to_howto_rel   0
493 #define elf_backend_relocate_section mn10200_elf_relocate_section
494
495 #define elf_symbol_leading_char '_'
496
497 #include "elf32-target.h"
This page took 0.04289 seconds and 2 git commands to generate.