Update email addresses for bugs and patches.
[binutils.git] / bfd / elf32-or32.c
bloba61b09d415258967e2bb0ce8fae66280186527ec
1 /* OR32-specific support for 32-bit ELF
2 Copyright (C) 2002 Free Software Foundation, Inc.
3 Contributed by Ivan Guzvinec <ivang@opencores.org>
5 This file is part of BFD, the Binary File Descriptor library.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21 #include "bfd.h"
22 #include "sysdep.h"
23 #include "libbfd.h"
24 #include "elf-bfd.h"
25 #include "elf/or32.h"
26 #include "libiberty.h"
28 static reloc_howto_type * bfd_elf32_bfd_reloc_type_lookup PARAMS ((bfd *, bfd_reloc_code_real_type));
29 static void or32_info_to_howto_rel PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
30 static boolean or32_elf_object_p PARAMS ((bfd *));
31 static void or32_elf_final_write_processing PARAMS ((bfd *, boolean));
32 static bfd_reloc_status_type or32_elf_32_reloc PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
33 static bfd_reloc_status_type or32_elf_16_reloc PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
34 static bfd_reloc_status_type or32_elf_8_reloc PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
35 static bfd_reloc_status_type or32_elf_const_reloc PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
36 static bfd_reloc_status_type or32_elf_consth_reloc PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
37 static bfd_reloc_status_type or32_elf_jumptarg_reloc PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
39 /* Try to minimize the amount of space occupied by relocation tables
40 on the ROM (not that the ROM won't be swamped by other ELF overhead). */
41 #define USE_REL
43 static reloc_howto_type elf_or32_howto_table[] =
45 /* This reloc does nothing. */
46 HOWTO (R_OR32_NONE, /* type */
47 0, /* rightshift */
48 2, /* size (0 = byte, 1 = short, 2 = long) */
49 32, /* bitsize */
50 false, /* pc_relative */
51 0, /* bitpos */
52 complain_overflow_bitfield, /* complain_on_overflow */
53 bfd_elf_generic_reloc, /* special_function */
54 "R_OR32_NONE", /* name */
55 false, /* partial_inplace */
56 0, /* src_mask */
57 0, /* dst_mask */
58 false), /* pcrel_offset */
60 /* A standard 32 bit relocation. */
61 HOWTO (R_OR32_32, /* type */
62 0, /* rightshift */
63 2, /* size (0 = byte, 1 = short, 2 = long) */
64 32, /* bitsize */
65 false, /* pc_relative */
66 0, /* bitpos */
67 complain_overflow_bitfield, /* complain_on_overflow */
68 or32_elf_32_reloc, /* special_function */
69 "R_OR32_32", /* name */
70 false, /* partial_inplace */
71 0xffffffff, /* src_mask */
72 0xffffffff, /* dst_mask */
73 false), /* pcrel_offset */
75 /* A standard 16 bit relocation. */
76 HOWTO (R_OR32_16, /* type */
77 0, /* rightshift */
78 1, /* size (0 = byte, 1 = short, 2 = long) */
79 16, /* bitsize */
80 false, /* pc_relative */
81 0, /* bitpos */
82 complain_overflow_bitfield, /* complain_on_overflow */
83 or32_elf_16_reloc, /* special_function */
84 "R_OR32_16", /* name */
85 false, /* partial_inplace */
86 0x0000ffff, /* src_mask */
87 0x0000ffff, /* dst_mask */
88 false), /* pcrel_offset */
90 /* A standard 8 bit relocation. */
91 HOWTO (R_OR32_8, /* type */
92 0, /* rightshift */
93 0, /* size (0 = byte, 1 = short, 2 = long) */
94 8, /* bitsize */
95 false, /* pc_relative */
96 0, /* bitpos */
97 complain_overflow_bitfield, /* complain_on_overflow */
98 or32_elf_8_reloc, /* special_function */
99 "R_OR32_8", /* name */
100 false, /* partial_inplace */
101 0x000000ff, /* src_mask */
102 0x000000ff, /* dst_mask */
103 false), /* pcrel_offset */
105 /* A standard low 16 bit relocation. */
106 HOWTO (R_OR32_CONST, /* type */
107 0, /* rightshift */
108 2, /* size (0 = byte, 1 = short, 2 = long) */
109 16, /* bitsize */
110 false, /* pc_relative */
111 0, /* bitpos */
112 complain_overflow_dont, /* complain_on_overflow */
113 or32_elf_const_reloc, /* special_function */
114 "R_OR32_CONST", /* name */
115 false, /* partial_inplace */
116 0x0000ffff, /* src_mask */
117 0x0000ffff, /* dst_mask */
118 false), /* pcrel_offset */
120 /* A standard high 16 bit relocation. */
121 HOWTO (R_OR32_CONSTH, /* type */
122 16, /* rightshift */
123 2, /* size (0 = byte, 1 = short, 2 = long) */
124 16, /* bitsize */
125 true, /* pc_relative */
126 0, /* bitpos */
127 complain_overflow_dont, /* complain_on_overflow */
128 or32_elf_consth_reloc, /* special_function */
129 "R_OR32_CONSTH", /* name */
130 false, /* partial_inplace */
131 0xffff0000, /* src_mask */
132 0x0000ffff, /* dst_mask */
133 false), /* pcrel_offset */
135 /* A standard branch relocation. */
136 HOWTO (R_OR32_JUMPTARG, /* type */
137 2, /* rightshift */
138 2, /* size (0 = byte, 1 = short, 2 = long) */
139 28, /* bitsize */
140 true, /* pc_relative */
141 0, /* bitpos */
142 complain_overflow_signed, /* complain_on_overflow */
143 or32_elf_jumptarg_reloc,/* special_function */
144 "R_OR32_JUMPTARG", /* name */
145 false, /* partial_inplace */
146 0, /* src_mask */
147 0x03ffffff, /* dst_mask */
148 true), /* pcrel_offset */
150 /* GNU extension to record C++ vtable hierarchy. */
151 HOWTO (R_OR32_GNU_VTINHERIT, /* type */
152 0, /* rightshift */
153 2, /* size (0 = byte, 1 = short, 2 = long) */
154 0, /* bitsize */
155 false, /* pc_relative */
156 0, /* bitpos */
157 complain_overflow_dont, /* complain_on_overflow */
158 NULL, /* special_function */
159 "R_OR32_GNU_VTINHERIT", /* name */
160 false, /* partial_inplace */
161 0, /* src_mask */
162 0, /* dst_mask */
163 false), /* pcrel_offset */
165 /* GNU extension to record C++ vtable member usage. */
166 HOWTO (R_OR32_GNU_VTENTRY, /* type */
167 0, /* rightshift */
168 2, /* size (0 = byte, 1 = short, 2 = long) */
169 0, /* bitsize */
170 false, /* pc_relative */
171 0, /* bitpos */
172 complain_overflow_dont, /* complain_on_overflow */
173 _bfd_elf_rel_vtable_reloc_fn, /* special_function */
174 "R_OR32_GNU_VTENTRY", /* name */
175 false, /* partial_inplace */
176 0, /* src_mask */
177 0, /* dst_mask */
178 false), /* pcrel_offset */
181 /* Map BFD reloc types to OR32 ELF reloc types. */
183 struct or32_reloc_map
185 bfd_reloc_code_real_type bfd_reloc_val;
186 unsigned char elf_reloc_val;
189 static const struct or32_reloc_map or32_reloc_map[] =
191 { BFD_RELOC_NONE, R_OR32_NONE },
192 { BFD_RELOC_32, R_OR32_32 },
193 { BFD_RELOC_16, R_OR32_16 },
194 { BFD_RELOC_8, R_OR32_8 },
195 { BFD_RELOC_LO16, R_OR32_CONST },
196 { BFD_RELOC_HI16, R_OR32_CONSTH },
197 { BFD_RELOC_32_GOT_PCREL, R_OR32_JUMPTARG },
198 { BFD_RELOC_VTABLE_INHERIT, R_OR32_GNU_VTINHERIT },
199 { BFD_RELOC_VTABLE_ENTRY, R_OR32_GNU_VTENTRY },
202 static reloc_howto_type *
203 bfd_elf32_bfd_reloc_type_lookup (abfd, code)
204 bfd *abfd ATTRIBUTE_UNUSED;
205 bfd_reloc_code_real_type code;
207 unsigned int i;
209 for (i = ARRAY_SIZE (or32_reloc_map); i--;)
211 if (or32_reloc_map[i].bfd_reloc_val == code)
212 return &elf_or32_howto_table[or32_reloc_map[i].elf_reloc_val];
215 return NULL;
218 /* Set the howto pointer for an OR32 ELF reloc. */
220 static void
221 or32_info_to_howto_rel (abfd, cache_ptr, dst)
222 bfd *abfd ATTRIBUTE_UNUSED;
223 arelent *cache_ptr;
224 Elf32_Internal_Rel *dst;
226 unsigned int r_type;
228 r_type = ELF32_R_TYPE (dst->r_info);
229 BFD_ASSERT (r_type < (unsigned int) R_OR32_max);
230 cache_ptr->howto = &elf_or32_howto_table[r_type];
233 /* Set the right machine number for an OR32 ELF file. */
235 static boolean
236 or32_elf_object_p (abfd)
237 bfd *abfd;
239 (void) bfd_default_set_arch_mach (abfd, bfd_arch_or32, 0);
240 return true;
243 /* The final processing done just before writing out an OR32 ELF object file.
244 This gets the OR32 architecture right based on the machine number. */
246 static void
247 or32_elf_final_write_processing (abfd, linker)
248 bfd *abfd;
249 boolean linker ATTRIBUTE_UNUSED;
251 int mach;
252 unsigned long val;
254 switch (mach = bfd_get_mach (abfd))
257 case bfd_mach_arc_base:
258 val = E_OR32_MACH_BASE;
259 break;
261 default:
262 val = 0;
263 return;
266 elf_elfheader (abfd)->e_flags &=~ EF_OR32_MACH;
267 elf_elfheader (abfd)->e_flags |= val;
270 bfd_reloc_status_type
271 or32_elf_32_reloc (abfd, reloc_entry, symbol, data, input_section,
272 output_bfd, error_message)
273 bfd *abfd;
274 arelent *reloc_entry;
275 asymbol *symbol;
276 PTR data;
277 asection *input_section;
278 bfd *output_bfd;
279 char **error_message ATTRIBUTE_UNUSED;
281 if (output_bfd != (bfd *) NULL)
283 unsigned long insn;
284 bfd_size_type addr = reloc_entry->address;
286 reloc_entry->address += input_section->output_offset;
288 insn = bfd_get_32 (abfd, (bfd_byte *) data + addr);
289 insn += symbol->section->output_section->vma;
290 insn += symbol->section->output_offset;
291 insn += symbol->value;
292 bfd_put_32 (abfd, insn, (bfd_byte *) data + addr);
294 return bfd_reloc_ok;
297 return bfd_reloc_continue;
300 bfd_reloc_status_type
301 or32_elf_16_reloc (abfd, reloc_entry, symbol, data, input_section,
302 output_bfd, error_message)
303 bfd *abfd;
304 arelent *reloc_entry;
305 asymbol *symbol;
306 PTR data;
307 asection *input_section;
308 bfd *output_bfd;
309 char **error_message ATTRIBUTE_UNUSED;
311 if (output_bfd != (bfd *) NULL)
313 unsigned short insn;
314 bfd_size_type addr = reloc_entry->address;
316 reloc_entry->address += input_section->output_offset;
318 insn = bfd_get_16 (abfd, (bfd_byte *) data + addr);
319 insn += symbol->section->output_section->vma;
320 insn += symbol->section->output_offset;
321 insn += symbol->value;
322 bfd_put_16 (abfd, insn, (bfd_byte *) data + addr);
324 return bfd_reloc_ok;
327 return bfd_reloc_continue;
330 bfd_reloc_status_type
331 or32_elf_8_reloc (abfd, reloc_entry, symbol, data, input_section,
332 output_bfd, error_message)
333 bfd *abfd ATTRIBUTE_UNUSED;
334 arelent *reloc_entry;
335 asymbol *symbol;
336 PTR data;
337 asection *input_section;
338 bfd *output_bfd;
339 char **error_message ATTRIBUTE_UNUSED;
341 if (output_bfd != (bfd *) NULL)
343 unsigned char insn;
344 bfd_size_type addr = reloc_entry->address;
346 reloc_entry->address += input_section->output_offset;
348 insn = bfd_get_8 (abfd, (bfd_byte *) data + addr);
349 insn += symbol->section->output_section->vma;
350 insn += symbol->section->output_offset;
351 insn += symbol->value;
352 bfd_put_8 (abfd, insn, (bfd_byte *) data + addr);
354 return bfd_reloc_ok;
357 return bfd_reloc_continue;
360 /* Do a R_OR32_CONSTH relocation. This has to be done in combination
361 with a R_OR32_CONST reloc, because there is a carry from the LO16 to
362 the HI16. Here we just save the information we need; we do the
363 actual relocation when we see the LO16. OR32 ELF requires that the
364 LO16 immediately follow the HI16. As a GNU extension, we permit an
365 arbitrary number of HI16 relocs to be associated with a single LO16
366 reloc. This extension permits gcc to output the HI and LO relocs
367 itself. This code is copied from the elf32-mips.c. */
369 struct or32_consth
371 struct or32_consth *next;
372 bfd_byte *addr;
373 bfd_vma addend;
376 /* FIXME: This should not be a static variable. */
378 static struct or32_consth *or32_consth_list;
380 bfd_reloc_status_type
381 or32_elf_consth_reloc (abfd, reloc_entry, symbol, data, input_section,
382 output_bfd, error_message)
383 bfd *abfd ATTRIBUTE_UNUSED;
384 arelent *reloc_entry;
385 asymbol *symbol;
386 PTR data;
387 asection *input_section;
388 bfd *output_bfd;
389 char **error_message ATTRIBUTE_UNUSED;
391 bfd_reloc_status_type ret;
392 bfd_vma relocation;
393 struct or32_consth *n;
395 ret = bfd_reloc_ok;
397 if (bfd_is_und_section (symbol->section)
398 && output_bfd == (bfd *) NULL)
399 ret = bfd_reloc_undefined;
401 if (bfd_is_com_section (symbol->section))
402 relocation = 0;
403 else
404 relocation = symbol->value;
406 relocation += symbol->section->output_section->vma;
407 relocation += symbol->section->output_offset;
408 relocation += reloc_entry->addend;
410 if (reloc_entry->address > input_section->_cooked_size)
411 return bfd_reloc_outofrange;
413 /* Save the information, and let LO16 do the actual relocation. */
414 n = (struct or32_consth *) bfd_malloc (sizeof *n);
415 if (n == NULL)
416 return bfd_reloc_outofrange;
417 n->addr = (bfd_byte *) data + reloc_entry->address;
418 n->addend = relocation;
419 n->next = or32_consth_list;
420 or32_consth_list = n;
422 if (output_bfd != (bfd *) NULL)
423 reloc_entry->address += input_section->output_offset;
425 return ret;
428 /* Do a R_OR32_CONST relocation. This is a straightforward 16 bit
429 inplace relocation; this function exists in order to do the
430 R_OR32_CONSTH relocation described above. */
432 bfd_reloc_status_type
433 or32_elf_const_reloc (abfd, reloc_entry, symbol, data, input_section,
434 output_bfd, error_message)
435 bfd *abfd;
436 arelent *reloc_entry;
437 asymbol *symbol;
438 PTR data;
439 asection *input_section;
440 bfd *output_bfd;
441 char **error_message;
443 if (or32_consth_list != NULL)
445 struct or32_consth *l;
447 l = or32_consth_list;
448 while (l != NULL)
450 unsigned long insn;
451 unsigned long val;
452 unsigned long vallo;
453 struct or32_consth *next;
455 /* Do the HI16 relocation. Note that we actually don't need
456 to know anything about the LO16 itself, except where to
457 find the low 16 bits of the addend needed by the LO16. */
458 insn = bfd_get_32 (abfd, l->addr);
459 vallo = (bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address)
460 & 0xffff);
461 val = ((insn & 0xffff) << 16) + vallo;
462 val += l->addend;
464 insn = (insn &~ 0xffff) | ((val >> 16) & 0xffff);
465 bfd_put_32 (abfd, insn, l->addr);
467 next = l->next;
468 free (l);
469 l = next;
472 or32_consth_list = NULL;
475 if (output_bfd != (bfd *) NULL)
477 unsigned long insn, tmp;
478 bfd_size_type addr = reloc_entry->address;
480 reloc_entry->address += input_section->output_offset;
482 insn = bfd_get_32 (abfd, (bfd_byte *) data + addr);
483 tmp = insn & 0x0000ffff;
484 tmp += symbol->section->output_section->vma;
485 tmp += symbol->section->output_offset;
486 tmp += symbol->value;
487 insn = (insn & 0xffff0000) | (tmp & 0x0000ffff);
488 bfd_put_32 (abfd, insn, (bfd_byte *) data + addr);
490 return bfd_reloc_ok;
493 /* Now do the LO16 reloc in the usual way. */
494 return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
495 input_section, output_bfd, error_message);
498 bfd_reloc_status_type
499 or32_elf_jumptarg_reloc (abfd, reloc_entry, symbol, data, input_section,
500 output_bfd, error_message)
501 bfd *abfd;
502 arelent *reloc_entry;
503 asymbol *symbol ATTRIBUTE_UNUSED;
504 PTR data;
505 asection *input_section;
506 bfd *output_bfd;
507 char **error_message ATTRIBUTE_UNUSED;
509 if (output_bfd != (bfd *) NULL)
511 unsigned long insn, tmp;
512 bfd_size_type addr = reloc_entry->address;
514 reloc_entry->address += input_section->output_offset;
516 insn = bfd_get_32 (abfd, (bfd_byte *) data + addr);
517 tmp = insn | 0xfc000000;
518 tmp -= (input_section->output_offset >> 2);
519 insn = (insn & 0xfc000000) | (tmp & 0x03ffffff);
520 bfd_put_32 (abfd, insn, (bfd_byte *) data + addr);
522 return bfd_reloc_ok;
525 return bfd_reloc_continue;
528 #define TARGET_LITTLE_SYM bfd_elf32_or32_little_vec
529 #define TARGET_LITTLE_NAME "elf32-littleor32"
530 #define TARGET_BIG_SYM bfd_elf32_or32_big_vec
531 #define TARGET_BIG_NAME "elf32-or32"
532 #define ELF_ARCH bfd_arch_or32
533 #define ELF_MACHINE_CODE EM_OR32
534 #define ELF_MAXPAGESIZE 0x1000
536 #define elf_info_to_howto 0
537 #define elf_info_to_howto_rel or32_info_to_howto_rel
538 #define elf_backend_object_p or32_elf_object_p
539 #define elf_backend_final_write_processing \
540 or32_elf_final_write_processing
542 #include "elf32-target.h"