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. */
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). */
43 static reloc_howto_type elf_or32_howto_table
[] =
45 /* This reloc does nothing. */
46 HOWTO (R_OR32_NONE
, /* type */
48 2, /* size (0 = byte, 1 = short, 2 = long) */
50 false, /* pc_relative */
52 complain_overflow_bitfield
, /* complain_on_overflow */
53 bfd_elf_generic_reloc
, /* special_function */
54 "R_OR32_NONE", /* name */
55 false, /* partial_inplace */
58 false), /* pcrel_offset */
60 /* A standard 32 bit relocation. */
61 HOWTO (R_OR32_32
, /* type */
63 2, /* size (0 = byte, 1 = short, 2 = long) */
65 false, /* pc_relative */
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 */
78 1, /* size (0 = byte, 1 = short, 2 = long) */
80 false, /* pc_relative */
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 */
93 0, /* size (0 = byte, 1 = short, 2 = long) */
95 false, /* pc_relative */
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 */
108 2, /* size (0 = byte, 1 = short, 2 = long) */
110 false, /* pc_relative */
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 */
123 2, /* size (0 = byte, 1 = short, 2 = long) */
125 true, /* pc_relative */
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 */
138 2, /* size (0 = byte, 1 = short, 2 = long) */
140 true, /* pc_relative */
142 complain_overflow_signed
, /* complain_on_overflow */
143 or32_elf_jumptarg_reloc
,/* special_function */
144 "R_OR32_JUMPTARG", /* name */
145 false, /* partial_inplace */
147 0x03ffffff, /* dst_mask */
148 true), /* pcrel_offset */
150 /* GNU extension to record C++ vtable hierarchy. */
151 HOWTO (R_OR32_GNU_VTINHERIT
, /* type */
153 2, /* size (0 = byte, 1 = short, 2 = long) */
155 false, /* pc_relative */
157 complain_overflow_dont
, /* complain_on_overflow */
158 NULL
, /* special_function */
159 "R_OR32_GNU_VTINHERIT", /* name */
160 false, /* partial_inplace */
163 false), /* pcrel_offset */
165 /* GNU extension to record C++ vtable member usage. */
166 HOWTO (R_OR32_GNU_VTENTRY
, /* type */
168 2, /* size (0 = byte, 1 = short, 2 = long) */
170 false, /* pc_relative */
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 */
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
;
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
];
218 /* Set the howto pointer for an OR32 ELF reloc. */
221 or32_info_to_howto_rel (abfd
, cache_ptr
, dst
)
222 bfd
*abfd ATTRIBUTE_UNUSED
;
224 Elf32_Internal_Rel
*dst
;
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. */
236 or32_elf_object_p (abfd
)
239 (void) bfd_default_set_arch_mach (abfd
, bfd_arch_or32
, 0);
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. */
247 or32_elf_final_write_processing (abfd
, linker
)
249 boolean linker ATTRIBUTE_UNUSED
;
254 switch (mach
= bfd_get_mach (abfd
))
257 case bfd_mach_arc_base:
258 val = E_OR32_MACH_BASE;
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
)
274 arelent
*reloc_entry
;
277 asection
*input_section
;
279 char **error_message ATTRIBUTE_UNUSED
;
281 if (output_bfd
!= (bfd
*) NULL
)
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
);
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
)
304 arelent
*reloc_entry
;
307 asection
*input_section
;
309 char **error_message ATTRIBUTE_UNUSED
;
311 if (output_bfd
!= (bfd
*) NULL
)
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
);
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
;
337 asection
*input_section
;
339 char **error_message ATTRIBUTE_UNUSED
;
341 if (output_bfd
!= (bfd
*) NULL
)
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
);
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. */
371 struct or32_consth
*next
;
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
;
387 asection
*input_section
;
389 char **error_message ATTRIBUTE_UNUSED
;
391 bfd_reloc_status_type ret
;
393 struct or32_consth
*n
;
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
))
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
);
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
;
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
)
436 arelent
*reloc_entry
;
439 asection
*input_section
;
441 char **error_message
;
443 if (or32_consth_list
!= NULL
)
445 struct or32_consth
*l
;
447 l
= or32_consth_list
;
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
)
461 val
= ((insn
& 0xffff) << 16) + vallo
;
464 insn
= (insn
&~ 0xffff) | ((val
>> 16) & 0xffff);
465 bfd_put_32 (abfd
, insn
, l
->addr
);
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
);
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
)
502 arelent
*reloc_entry
;
503 asymbol
*symbol ATTRIBUTE_UNUSED
;
505 asection
*input_section
;
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
);
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"