Configure mips64vr4100-elf nee mips64vr41* as a 64 bit mips16 igen simulator.
[deliverable/binutils-gdb.git] / bfd / elf32-fr30.c
CommitLineData
4aeed4f2
NC
1/* FR30-specific support for 32-bit ELF.
2 Copyright (C) 1998 Free Software Foundation, Inc.
3
4This file is part of BFD, the Binary File Descriptor library.
5
6This program is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2 of the License, or
9(at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program; if not, write to the Free Software
18Foundation, 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#include "elf/fr30.h"
25
26/* Forward declarations. */
27static bfd_reloc_status_type fr30_elf_i20_reloc
28 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
82ef568c
NC
29static reloc_howto_type * fr30_reloc_type_lookup
30 PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
31static void fr30_info_to_howto_rela
32 PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));
33static boolean fr30_elf_relocate_section
34 PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
4aeed4f2
NC
35
36static reloc_howto_type fr30_elf_howto_table [] =
37{
38 /* This reloc does nothing. */
39 HOWTO (R_FR30_NONE, /* type */
40 0, /* rightshift */
41 2, /* size (0 = byte, 1 = short, 2 = long) */
42 32, /* bitsize */
43 false, /* pc_relative */
44 0, /* bitpos */
45 complain_overflow_bitfield, /* complain_on_overflow */
46 bfd_elf_generic_reloc, /* special_function */
47 "R_FR30_NONE", /* name */
48 false, /* partial_inplace */
49 0, /* src_mask */
50 0, /* dst_mask */
51 false), /* pcrel_offset */
52
53 /* An 8 bit absolute relocation. */
54 HOWTO (R_FR30_8, /* type */
55 0, /* rightshift */
56 1, /* size (0 = byte, 1 = short, 2 = long) */
57 8, /* bitsize */
58 false, /* pc_relative */
59 4, /* bitpos */
60 complain_overflow_bitfield, /* complain_on_overflow */
61 bfd_elf_generic_reloc, /* special_function */
62 "R_FR30_8", /* name */
63 true, /* partial_inplace */
64 0x0ff0, /* src_mask */
65 0x0ff0, /* dst_mask */
66 false), /* pcrel_offset */
67
68 /* A 20 bit absolute relocation. */
69 HOWTO (R_FR30_20, /* type */
70 0, /* rightshift */
71 2, /* size (0 = byte, 1 = short, 2 = long) */
72 20, /* bitsize */
73 false, /* pc_relative */
74 0, /* bitpos */
75 complain_overflow_bitfield, /* complain_on_overflow */
76 fr30_elf_i20_reloc, /* special_function */
77 "R_FR30_20", /* name */
78 true, /* partial_inplace */
79 0x00f0ffff, /* src_mask */
80 0x00f0ffff, /* dst_mask */
81 false), /* pcrel_offset */
82
83 /* A 32 bit absolute relocation. */
84 HOWTO (R_FR30_32, /* type */
85 0, /* rightshift */
86 2, /* size (0 = byte, 1 = short, 2 = long) */
87 32, /* bitsize */
88 false, /* pc_relative */
89 0, /* bitpos */
90 complain_overflow_bitfield, /* complain_on_overflow */
91 bfd_elf_generic_reloc, /* special_function */
92 "R_FR30_32", /* name */
93 true, /* partial_inplace */
94 0xffffffff, /* src_mask */
95 0xffffffff, /* dst_mask */
96 false), /* pcrel_offset */
97
98 /* A 6 bit absolute relocation. */
99 HOWTO (R_FR30_6_IN_4, /* type */
100 2, /* rightshift */
101 1, /* size (0 = byte, 1 = short, 2 = long) */
102 6, /* bitsize */
103 false, /* pc_relative */
104 4, /* bitpos */
105 complain_overflow_unsigned, /* complain_on_overflow */
106 bfd_elf_generic_reloc, /* special_function */
107 "R_FR30_6_IN_4", /* name */
108 true, /* partial_inplace */
109 0x00f0, /* src_mask */
110 0x00f0, /* dst_mask */
111 false), /* pcrel_offset */
112
113 /* An 8 bit absolute relocation. */
114 HOWTO (R_FR30_8_IN_8, /* type */
115 0, /* rightshift */
116 1, /* size (0 = byte, 1 = short, 2 = long) */
117 8, /* bitsize */
118 false, /* pc_relative */
119 4, /* bitpos */
120 complain_overflow_signed, /* complain_on_overflow */
121 bfd_elf_generic_reloc,/* special_function */
122 "R_FR30_8_IN_8", /* name */
123 true, /* partial_inplace */
124 0x0ff0, /* src_mask */
125 0x0ff0, /* dst_mask */
126 false), /* pcrel_offset */
127
128 /* A 9 bit absolute relocation. */
129 HOWTO (R_FR30_9_IN_8, /* type */
130 1, /* rightshift */
131 1, /* size (0 = byte, 1 = short, 2 = long) */
132 9, /* bitsize */
133 false, /* pc_relative */
134 4, /* bitpos */
135 complain_overflow_signed, /* complain_on_overflow */
136 bfd_elf_generic_reloc,/* special_function */
137 "R_FR30_9_IN_8", /* name */
138 true, /* partial_inplace */
139 0x0ff0, /* src_mask */
140 0x0ff0, /* dst_mask */
141 false), /* pcrel_offset */
142
143 /* A 10 bit absolute relocation. */
144 HOWTO (R_FR30_10_IN_8, /* type */
145 2, /* rightshift */
146 1, /* size (0 = byte, 1 = short, 2 = long) */
147 10, /* bitsize */
148 false, /* pc_relative */
149 4, /* bitpos */
150 complain_overflow_signed, /* complain_on_overflow */
151 bfd_elf_generic_reloc,/* special_function */
152 "R_FR30_10_IN_8", /* name */
153 true, /* partial_inplace */
154 0x0ff0, /* src_mask */
155 0x0ff0, /* dst_mask */
156 false), /* pcrel_offset */
157
158 /* A PC relative 9 bit relocation, right shifted by 1. */
159 HOWTO (R_FR30_9_PCREL, /* type */
160 1, /* rightshift */
161 1, /* size (0 = byte, 1 = short, 2 = long) */
162 9, /* bitsize */
163 true, /* pc_relative */
164 0, /* bitpos */
165 complain_overflow_signed, /* complain_on_overflow */
166 bfd_elf_generic_reloc, /* special_function */
167 "R_FR30_9_PCREL", /* name */
168 false, /* partial_inplace */
169 0x00ff, /* src_mask */
170 0x00ff, /* dst_mask */
171 true), /* pcrel_offset */
172
173 /* A PC relative 12 bit relocation, right shifted by 1. */
174 HOWTO (R_FR30_12_PCREL, /* type */
175 1, /* rightshift */
176 1, /* size (0 = byte, 1 = short, 2 = long) */
177 12, /* bitsize */
178 true, /* pc_relative */
179 0, /* bitpos */
180 complain_overflow_signed, /* complain_on_overflow */
181 bfd_elf_generic_reloc, /* special_function */
182 "R_FR30_12_PCREL", /* name */
183 false, /* partial_inplace */
184 0x07ff, /* src_mask */
185 0x07ff, /* dst_mask */
186 true), /* pcrel_offset */
187};
188\f
189/* Utility to actually perform an R_FR30_20 reloc. */
190
191static bfd_reloc_status_type
192fr30_elf_i20_reloc (abfd, reloc_entry, symbol, data,
193 input_section, output_bfd, error_message)
194 bfd * abfd;
195 arelent * reloc_entry;
196 asymbol * symbol;
197 PTR data;
198 asection * input_section;
199 bfd * output_bfd;
200 char ** error_message;
201{
202 bfd_vma relocation;
203 unsigned long x;
204
205 /* This part is from bfd_elf_generic_reloc. */
206 if (output_bfd != (bfd *) NULL
207 && (symbol->flags & BSF_SECTION_SYM) == 0
208 && (! reloc_entry->howto->partial_inplace
209 || reloc_entry->addend == 0))
210 {
211 reloc_entry->address += input_section->output_offset;
212 return bfd_reloc_ok;
213 }
214
215 if (output_bfd != NULL)
216 /* FIXME: See bfd_perform_relocation. Is this right? */
217 return bfd_reloc_continue;
218
219 relocation =
220 symbol->value
221 + symbol->section->output_section->vma
222 + symbol->section->output_offset
223 + reloc_entry->addend;
224
225 if (relocation > ((1U << 20) - 1))
226 return bfd_reloc_overflow;
227
228 x = bfd_get_32 (abfd, data + reloc_entry->address);
229 x = (x & 0xff0f0000) | (relocation & 0x0000ffff) | ((relocation & 0x000f0000) << 4);
230 bfd_put_32 (abfd, x, data + reloc_entry->address);
231
232 return bfd_reloc_ok;
233}
234
235\f
236/* Map BFD reloc types to FR30 ELF reloc types. */
237
238struct fr30_reloc_map
239{
82ef568c
NC
240 unsigned int bfd_reloc_val;
241 unsigned int fr30_reloc_val;
4aeed4f2
NC
242};
243
244static const struct fr30_reloc_map fr30_reloc_map [] =
245{
246 { BFD_RELOC_NONE, R_FR30_NONE },
247 { BFD_RELOC_8, R_FR30_8 },
248 { BFD_RELOC_FR30_20, R_FR30_20 },
249 { BFD_RELOC_32, R_FR30_32 },
250 { BFD_RELOC_FR30_6_IN_4, R_FR30_6_IN_4 },
251 { BFD_RELOC_FR30_8_IN_8, R_FR30_8_IN_8 },
252 { BFD_RELOC_FR30_9_IN_8, R_FR30_9_IN_8 },
253 { BFD_RELOC_FR30_10_IN_8, R_FR30_10_IN_8 },
254 { BFD_RELOC_FR30_9_PCREL, R_FR30_9_PCREL },
255 { BFD_RELOC_FR30_12_PCREL, R_FR30_12_PCREL },
256};
257
258static reloc_howto_type *
82ef568c 259fr30_reloc_type_lookup (abfd, code)
4aeed4f2
NC
260 bfd * abfd;
261 bfd_reloc_code_real_type code;
262{
263 unsigned int i;
264
265 for (i = sizeof (fr30_reloc_map) / sizeof (fr30_reloc_map[0]);
266 --i;)
82ef568c
NC
267 if (fr30_reloc_map [i].bfd_reloc_val == code)
268 return & fr30_elf_howto_table [fr30_reloc_map[i].fr30_reloc_val];
269
4aeed4f2
NC
270 return NULL;
271}
272
273/* Set the howto pointer for an FR30 ELF reloc. */
274
275static void
82ef568c 276fr30_info_to_howto_rela (abfd, cache_ptr, dst)
4aeed4f2
NC
277 bfd * abfd;
278 arelent * cache_ptr;
279 Elf32_Internal_Rela * dst;
280{
281 unsigned int r_type;
282
283 r_type = ELF32_R_TYPE (dst->r_info);
284 BFD_ASSERT (r_type < (unsigned int) R_FR30_max);
285 cache_ptr->howto = & fr30_elf_howto_table [r_type];
286}
287\f
288/* Relocate an FR30 ELF section.
289 There is some attempt to make this function usable for many architectures,
290 both USE_REL and USE_RELA ['twould be nice if such a critter existed],
291 if only to serve as a learning tool.
292
293 The RELOCATE_SECTION function is called by the new ELF backend linker
294 to handle the relocations for a section.
295
296 The relocs are always passed as Rela structures; if the section
297 actually uses Rel structures, the r_addend field will always be
298 zero.
299
300 This function is responsible for adjusting the section contents as
301 necessary, and (if using Rela relocs and generating a relocateable
302 output file) adjusting the reloc addend as necessary.
303
304 This function does not have to worry about setting the reloc
305 address or the reloc symbol index.
306
307 LOCAL_SYMS is a pointer to the swapped in local symbols.
308
309 LOCAL_SECTIONS is an array giving the section in the input file
310 corresponding to the st_shndx field of each local symbol.
311
312 The global hash table entry for the global symbols can be found
313 via elf_sym_hashes (input_bfd).
314
315 When generating relocateable output, this function must handle
316 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
317 going to be the section symbol corresponding to the output
318 section, which means that the addend must be adjusted
319 accordingly. */
320
321static boolean
322fr30_elf_relocate_section (output_bfd, info, input_bfd, input_section,
323 contents, relocs, local_syms, local_sections)
324 bfd * output_bfd;
325 struct bfd_link_info * info;
326 bfd * input_bfd;
327 asection * input_section;
328 bfd_byte * contents;
329 Elf_Internal_Rela * relocs;
330 Elf_Internal_Sym * local_syms;
331 asection ** local_sections;
332{
333 Elf_Internal_Shdr * symtab_hdr;
334 struct elf_link_hash_entry ** sym_hashes;
335 Elf_Internal_Rela * rel;
336 Elf_Internal_Rela * relend;
337
338 symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
339 sym_hashes = elf_sym_hashes (input_bfd);
340 relend = relocs + input_section->reloc_count;
341
342 for (rel = relocs; rel < relend; rel ++)
343 {
344 reloc_howto_type * howto;
345 unsigned long r_symndx;
346 Elf_Internal_Sym * sym;
347 asection * sec;
348 struct elf_link_hash_entry * h;
349 bfd_vma relocation;
350 bfd_reloc_status_type r;
351 const char * name;
352
353 r_symndx = ELF32_R_SYM (rel->r_info);
354
355 if (info->relocateable)
356 {
357 /* This is a relocateable link. We don't have to change
358 anything, unless the reloc is against a section symbol,
359 in which case we have to adjust according to where the
360 section symbol winds up in the output section. */
361 if (r_symndx < symtab_hdr->sh_info)
362 {
363 sym = local_syms + r_symndx;
364
365 if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
366 {
367 sec = local_sections [r_symndx];
368 rel->r_addend += sec->output_offset + sym->st_value;
369 }
370 }
371
372 continue;
373 }
374
375 /* This is a final link. */
376 howto = fr30_elf_howto_table + ELF32_R_TYPE (rel->r_info);
377 h = NULL;
378 sym = NULL;
379 sec = NULL;
380
381 if (r_symndx < symtab_hdr->sh_info)
382 {
383 sym = local_syms + r_symndx;
384 sec = local_sections [r_symndx];
385 relocation = (sec->output_section->vma
386 + sec->output_offset
387 + sym->st_value);
388
389 name = bfd_elf_string_from_elf_section
390 (input_bfd, symtab_hdr->sh_link, sym->st_name);
391 name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
392#if 0
393 fprintf (stderr, "local: sec: %s, sym: %s (%d), value: %x + %x + %x addend %x\n",
394 sec->name, name, sym->st_name,
395 sec->output_section->vma, sec->output_offset,
396 sym->st_value, rel->r_addend);
397#endif
398 }
399 else
400 {
401 h = sym_hashes [r_symndx - symtab_hdr->sh_info];
402
403 while (h->root.type == bfd_link_hash_indirect
404 || h->root.type == bfd_link_hash_warning)
405 h = (struct elf_link_hash_entry *) h->root.u.i.link;
406
407 name = h->root.root.string;
408
409 if (h->root.type == bfd_link_hash_defined
410 || h->root.type == bfd_link_hash_defweak)
411 {
412 sec = h->root.u.def.section;
413 relocation = (h->root.u.def.value
414 + sec->output_section->vma
415 + sec->output_offset);
416#if 0
417 fprintf (stderr,
418 "defined: sec: %s, name: %s, value: %x + %x + %x gives: %x\n",
419 sec->name, name, h->root.u.def.value,
420 sec->output_section->vma, sec->output_offset, relocation);
421#endif
422 }
423 else if (h->root.type == bfd_link_hash_undefweak)
424 {
425#if 0
426 fprintf (stderr, "undefined: sec: %s, name: %s\n",
427 sec->name, name);
428#endif
429 relocation = 0;
430 }
431 else
432 {
433 if (! ((*info->callbacks->undefined_symbol)
434 (info, h->root.root.string, input_bfd,
435 input_section, rel->r_offset)))
436 return false;
437#if 0
438 fprintf (stderr, "unknown: name: %s\n", name);
439#endif
440 relocation = 0;
441 }
442 }
443
444 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
445 contents, rel->r_offset,
446 relocation, rel->r_addend);
447
448 if (r != bfd_reloc_ok)
449 {
450 const char * msg = (const char *)0;
451
452 switch (r)
453 {
454 case bfd_reloc_overflow:
455 if (! ((*info->callbacks->reloc_overflow)
456 (info, name, howto->name, (bfd_vma) 0,
457 input_bfd, input_section, rel->r_offset)))
458 return false;
459 break;
460
461 case bfd_reloc_undefined:
462 if (! ((*info->callbacks->undefined_symbol)
463 (info, name, input_bfd, input_section,
464 rel->r_offset)))
465 return false;
466 break;
467
468 case bfd_reloc_outofrange:
469 msg = _("internal error: out of range error");
470 goto common_error;
471
472 case bfd_reloc_notsupported:
473 msg = _("internal error: unsupported relocation error");
474 goto common_error;
475
476 case bfd_reloc_dangerous:
477 msg = _("internal error: dangerous relocation");
478 goto common_error;
479
480 case bfd_reloc_other:
481 msg = _("could not locate special linker symbol __gp");
482 goto common_error;
483
484 case bfd_reloc_continue:
485 msg = _("could not locate special linker symbol __ep");
486 goto common_error;
487
488 case (bfd_reloc_dangerous + 1):
489 msg = _("could not locate special linker symbol __ctbp");
490 goto common_error;
491
492 default:
493 msg = _("internal error: unknown error");
494 /* fall through */
495
496 common_error:
497 if (!((*info->callbacks->warning)
498 (info, msg, name, input_bfd, input_section,
499 rel->r_offset)))
500 return false;
501 break;
502 }
503 }
504 }
505
506 return true;
507}
508\f
509#define ELF_ARCH bfd_arch_fr30
510#define ELF_MACHINE_CODE EM_CYGNUS_FR30
511#define ELF_MAXPAGESIZE 0x1000
512
513#define TARGET_BIG_SYM bfd_elf32_fr30_vec
514#define TARGET_BIG_NAME "elf32-fr30"
515
82ef568c
NC
516#define elf_info_to_howto_rel NULL
517#define elf_info_to_howto fr30_info_to_howto_rela
4aeed4f2 518#define elf_backend_relocate_section fr30_elf_relocate_section
82ef568c
NC
519
520#define bfd_elf32_bfd_reloc_type_lookup fr30_reloc_type_lookup
4aeed4f2
NC
521
522#include "elf32-target.h"
This page took 0.043445 seconds and 4 git commands to generate.