1 |
/* FR30-specific support for 32-bit ELF. |
/* FR30-specific support for 32-bit ELF. |
2 |
Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. |
Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 |
3 |
|
Free Software Foundation, Inc. |
4 |
|
|
5 |
This file is part of BFD, the Binary File Descriptor library. |
This file is part of BFD, the Binary File Descriptor library. |
6 |
|
|
32 |
static reloc_howto_type * fr30_reloc_type_lookup |
static reloc_howto_type * fr30_reloc_type_lookup |
33 |
PARAMS ((bfd *abfd, bfd_reloc_code_real_type code)); |
PARAMS ((bfd *abfd, bfd_reloc_code_real_type code)); |
34 |
static void fr30_info_to_howto_rela |
static void fr30_info_to_howto_rela |
35 |
PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *)); |
PARAMS ((bfd *, arelent *, Elf_Internal_Rela *)); |
36 |
static boolean fr30_elf_relocate_section |
static bfd_boolean fr30_elf_relocate_section |
37 |
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, |
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, |
38 |
Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)); |
Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)); |
39 |
static bfd_reloc_status_type fr30_final_link_relocate |
static bfd_reloc_status_type fr30_final_link_relocate |
40 |
PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *, |
PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *, |
41 |
Elf_Internal_Rela *, bfd_vma)); |
Elf_Internal_Rela *, bfd_vma)); |
42 |
static boolean fr30_elf_gc_sweep_hook |
static bfd_boolean fr30_elf_gc_sweep_hook |
43 |
PARAMS ((bfd *, struct bfd_link_info *, asection *, |
PARAMS ((bfd *, struct bfd_link_info *, asection *, |
44 |
const Elf_Internal_Rela *)); |
const Elf_Internal_Rela *)); |
45 |
static asection * fr30_elf_gc_mark_hook |
static asection * fr30_elf_gc_mark_hook |
46 |
PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *, |
PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *, |
47 |
struct elf_link_hash_entry *, Elf_Internal_Sym *)); |
struct elf_link_hash_entry *, Elf_Internal_Sym *)); |
48 |
static boolean fr30_elf_check_relocs |
static bfd_boolean fr30_elf_check_relocs |
49 |
PARAMS ((bfd *, struct bfd_link_info *, asection *, |
PARAMS ((bfd *, struct bfd_link_info *, asection *, |
50 |
const Elf_Internal_Rela *)); |
const Elf_Internal_Rela *)); |
51 |
|
|
56 |
0, /* rightshift */ |
0, /* rightshift */ |
57 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
58 |
32, /* bitsize */ |
32, /* bitsize */ |
59 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
60 |
0, /* bitpos */ |
0, /* bitpos */ |
61 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
62 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
63 |
"R_FR30_NONE", /* name */ |
"R_FR30_NONE", /* name */ |
64 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
65 |
0, /* src_mask */ |
0, /* src_mask */ |
66 |
0, /* dst_mask */ |
0, /* dst_mask */ |
67 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
68 |
|
|
69 |
/* An 8 bit absolute relocation. */ |
/* An 8 bit absolute relocation. */ |
70 |
HOWTO (R_FR30_8, /* type */ |
HOWTO (R_FR30_8, /* type */ |
71 |
0, /* rightshift */ |
0, /* rightshift */ |
72 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
73 |
8, /* bitsize */ |
8, /* bitsize */ |
74 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
75 |
4, /* bitpos */ |
4, /* bitpos */ |
76 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
77 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
78 |
"R_FR30_8", /* name */ |
"R_FR30_8", /* name */ |
79 |
true, /* partial_inplace */ |
TRUE, /* partial_inplace */ |
80 |
0x0000, /* src_mask */ |
0x0000, /* src_mask */ |
81 |
0x0ff0, /* dst_mask */ |
0x0ff0, /* dst_mask */ |
82 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
83 |
|
|
84 |
/* A 20 bit absolute relocation. */ |
/* A 20 bit absolute relocation. */ |
85 |
HOWTO (R_FR30_20, /* type */ |
HOWTO (R_FR30_20, /* type */ |
86 |
0, /* rightshift */ |
0, /* rightshift */ |
87 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
88 |
20, /* bitsize */ |
20, /* bitsize */ |
89 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
90 |
0, /* bitpos */ |
0, /* bitpos */ |
91 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
92 |
fr30_elf_i20_reloc, /* special_function */ |
fr30_elf_i20_reloc, /* special_function */ |
93 |
"R_FR30_20", /* name */ |
"R_FR30_20", /* name */ |
94 |
true, /* partial_inplace */ |
TRUE, /* partial_inplace */ |
95 |
0x00000000, /* src_mask */ |
0x00000000, /* src_mask */ |
96 |
0x00f0ffff, /* dst_mask */ |
0x00f0ffff, /* dst_mask */ |
97 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
98 |
|
|
99 |
/* A 32 bit absolute relocation. */ |
/* A 32 bit absolute relocation. */ |
100 |
HOWTO (R_FR30_32, /* type */ |
HOWTO (R_FR30_32, /* type */ |
101 |
0, /* rightshift */ |
0, /* rightshift */ |
102 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
103 |
32, /* bitsize */ |
32, /* bitsize */ |
104 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
105 |
0, /* bitpos */ |
0, /* bitpos */ |
106 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
107 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
108 |
"R_FR30_32", /* name */ |
"R_FR30_32", /* name */ |
109 |
true, /* partial_inplace */ |
TRUE, /* partial_inplace */ |
110 |
0x00000000, /* src_mask */ |
0x00000000, /* src_mask */ |
111 |
0xffffffff, /* dst_mask */ |
0xffffffff, /* dst_mask */ |
112 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
113 |
|
|
114 |
/* A 32 bit into 48 bits absolute relocation. */ |
/* A 32 bit into 48 bits absolute relocation. */ |
115 |
HOWTO (R_FR30_48, /* type */ |
HOWTO (R_FR30_48, /* type */ |
116 |
0, /* rightshift */ |
0, /* rightshift */ |
117 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
118 |
32, /* bitsize */ |
32, /* bitsize */ |
119 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
120 |
0, /* bitpos */ |
0, /* bitpos */ |
121 |
complain_overflow_bitfield, /* complain_on_overflow */ |
complain_overflow_bitfield, /* complain_on_overflow */ |
122 |
fr30_elf_i32_reloc, /* special_function */ |
fr30_elf_i32_reloc, /* special_function */ |
123 |
"R_FR30_48", /* name */ |
"R_FR30_48", /* name */ |
124 |
true, /* partial_inplace */ |
TRUE, /* partial_inplace */ |
125 |
0x00000000, /* src_mask */ |
0x00000000, /* src_mask */ |
126 |
0xffffffff, /* dst_mask */ |
0xffffffff, /* dst_mask */ |
127 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
128 |
|
|
129 |
/* A 6 bit absolute relocation. */ |
/* A 6 bit absolute relocation. */ |
130 |
HOWTO (R_FR30_6_IN_4, /* type */ |
HOWTO (R_FR30_6_IN_4, /* type */ |
131 |
2, /* rightshift */ |
2, /* rightshift */ |
132 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
133 |
6, /* bitsize */ |
6, /* bitsize */ |
134 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
135 |
4, /* bitpos */ |
4, /* bitpos */ |
136 |
complain_overflow_unsigned, /* complain_on_overflow */ |
complain_overflow_unsigned, /* complain_on_overflow */ |
137 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
138 |
"R_FR30_6_IN_4", /* name */ |
"R_FR30_6_IN_4", /* name */ |
139 |
true, /* partial_inplace */ |
TRUE, /* partial_inplace */ |
140 |
0x0000, /* src_mask */ |
0x0000, /* src_mask */ |
141 |
0x00f0, /* dst_mask */ |
0x00f0, /* dst_mask */ |
142 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
143 |
|
|
144 |
/* An 8 bit absolute relocation. */ |
/* An 8 bit absolute relocation. */ |
145 |
HOWTO (R_FR30_8_IN_8, /* type */ |
HOWTO (R_FR30_8_IN_8, /* type */ |
146 |
0, /* rightshift */ |
0, /* rightshift */ |
147 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
148 |
8, /* bitsize */ |
8, /* bitsize */ |
149 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
150 |
4, /* bitpos */ |
4, /* bitpos */ |
151 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
152 |
bfd_elf_generic_reloc,/* special_function */ |
bfd_elf_generic_reloc,/* special_function */ |
153 |
"R_FR30_8_IN_8", /* name */ |
"R_FR30_8_IN_8", /* name */ |
154 |
true, /* partial_inplace */ |
TRUE, /* partial_inplace */ |
155 |
0x0000, /* src_mask */ |
0x0000, /* src_mask */ |
156 |
0x0ff0, /* dst_mask */ |
0x0ff0, /* dst_mask */ |
157 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
158 |
|
|
159 |
/* A 9 bit absolute relocation. */ |
/* A 9 bit absolute relocation. */ |
160 |
HOWTO (R_FR30_9_IN_8, /* type */ |
HOWTO (R_FR30_9_IN_8, /* type */ |
161 |
1, /* rightshift */ |
1, /* rightshift */ |
162 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
163 |
9, /* bitsize */ |
9, /* bitsize */ |
164 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
165 |
4, /* bitpos */ |
4, /* bitpos */ |
166 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
167 |
bfd_elf_generic_reloc,/* special_function */ |
bfd_elf_generic_reloc,/* special_function */ |
168 |
"R_FR30_9_IN_8", /* name */ |
"R_FR30_9_IN_8", /* name */ |
169 |
true, /* partial_inplace */ |
TRUE, /* partial_inplace */ |
170 |
0x0000, /* src_mask */ |
0x0000, /* src_mask */ |
171 |
0x0ff0, /* dst_mask */ |
0x0ff0, /* dst_mask */ |
172 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
173 |
|
|
174 |
/* A 10 bit absolute relocation. */ |
/* A 10 bit absolute relocation. */ |
175 |
HOWTO (R_FR30_10_IN_8, /* type */ |
HOWTO (R_FR30_10_IN_8, /* type */ |
176 |
2, /* rightshift */ |
2, /* rightshift */ |
177 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
178 |
10, /* bitsize */ |
10, /* bitsize */ |
179 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
180 |
4, /* bitpos */ |
4, /* bitpos */ |
181 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
182 |
bfd_elf_generic_reloc,/* special_function */ |
bfd_elf_generic_reloc,/* special_function */ |
183 |
"R_FR30_10_IN_8", /* name */ |
"R_FR30_10_IN_8", /* name */ |
184 |
true, /* partial_inplace */ |
TRUE, /* partial_inplace */ |
185 |
0x0000, /* src_mask */ |
0x0000, /* src_mask */ |
186 |
0x0ff0, /* dst_mask */ |
0x0ff0, /* dst_mask */ |
187 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
188 |
|
|
189 |
/* A PC relative 9 bit relocation, right shifted by 1. */ |
/* A PC relative 9 bit relocation, right shifted by 1. */ |
190 |
HOWTO (R_FR30_9_PCREL, /* type */ |
HOWTO (R_FR30_9_PCREL, /* type */ |
191 |
1, /* rightshift */ |
1, /* rightshift */ |
192 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
193 |
9, /* bitsize */ |
9, /* bitsize */ |
194 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
195 |
0, /* bitpos */ |
0, /* bitpos */ |
196 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
197 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
198 |
"R_FR30_9_PCREL", /* name */ |
"R_FR30_9_PCREL", /* name */ |
199 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
200 |
0x0000, /* src_mask */ |
0x0000, /* src_mask */ |
201 |
0x00ff, /* dst_mask */ |
0x00ff, /* dst_mask */ |
202 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
203 |
|
|
204 |
/* A PC relative 12 bit relocation, right shifted by 1. */ |
/* A PC relative 12 bit relocation, right shifted by 1. */ |
205 |
HOWTO (R_FR30_12_PCREL, /* type */ |
HOWTO (R_FR30_12_PCREL, /* type */ |
206 |
1, /* rightshift */ |
1, /* rightshift */ |
207 |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
1, /* size (0 = byte, 1 = short, 2 = long) */ |
208 |
12, /* bitsize */ |
12, /* bitsize */ |
209 |
true, /* pc_relative */ |
TRUE, /* pc_relative */ |
210 |
0, /* bitpos */ |
0, /* bitpos */ |
211 |
complain_overflow_signed, /* complain_on_overflow */ |
complain_overflow_signed, /* complain_on_overflow */ |
212 |
bfd_elf_generic_reloc, /* special_function */ |
bfd_elf_generic_reloc, /* special_function */ |
213 |
"R_FR30_12_PCREL", /* name */ |
"R_FR30_12_PCREL", /* name */ |
214 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
215 |
0x0000, /* src_mask */ |
0x0000, /* src_mask */ |
216 |
0x07ff, /* dst_mask */ |
0x07ff, /* dst_mask */ |
217 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
218 |
/* GNU extension to record C++ vtable hierarchy */ |
/* GNU extension to record C++ vtable hierarchy */ |
219 |
HOWTO (R_FR30_GNU_VTINHERIT, /* type */ |
HOWTO (R_FR30_GNU_VTINHERIT, /* type */ |
220 |
0, /* rightshift */ |
0, /* rightshift */ |
221 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
222 |
0, /* bitsize */ |
0, /* bitsize */ |
223 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
224 |
0, /* bitpos */ |
0, /* bitpos */ |
225 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
226 |
NULL, /* special_function */ |
NULL, /* special_function */ |
227 |
"R_FR30_GNU_VTINHERIT", /* name */ |
"R_FR30_GNU_VTINHERIT", /* name */ |
228 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
229 |
0, /* src_mask */ |
0, /* src_mask */ |
230 |
0, /* dst_mask */ |
0, /* dst_mask */ |
231 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
232 |
|
|
233 |
/* GNU extension to record C++ vtable member usage */ |
/* GNU extension to record C++ vtable member usage */ |
234 |
HOWTO (R_FR30_GNU_VTENTRY, /* type */ |
HOWTO (R_FR30_GNU_VTENTRY, /* type */ |
235 |
0, /* rightshift */ |
0, /* rightshift */ |
236 |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
2, /* size (0 = byte, 1 = short, 2 = long) */ |
237 |
0, /* bitsize */ |
0, /* bitsize */ |
238 |
false, /* pc_relative */ |
FALSE, /* pc_relative */ |
239 |
0, /* bitpos */ |
0, /* bitpos */ |
240 |
complain_overflow_dont, /* complain_on_overflow */ |
complain_overflow_dont, /* complain_on_overflow */ |
241 |
_bfd_elf_rel_vtable_reloc_fn, /* special_function */ |
_bfd_elf_rel_vtable_reloc_fn, /* special_function */ |
242 |
"R_FR30_GNU_VTENTRY", /* name */ |
"R_FR30_GNU_VTENTRY", /* name */ |
243 |
false, /* partial_inplace */ |
FALSE, /* partial_inplace */ |
244 |
0, /* src_mask */ |
0, /* src_mask */ |
245 |
0, /* dst_mask */ |
0, /* dst_mask */ |
246 |
false), /* pcrel_offset */ |
FALSE), /* pcrel_offset */ |
247 |
}; |
}; |
248 |
|
|
249 |
/* Utility to actually perform an R_FR30_20 reloc. */ |
/* Utility to actually perform an R_FR30_20 reloc. */ |
251 |
static bfd_reloc_status_type |
static bfd_reloc_status_type |
252 |
fr30_elf_i20_reloc (abfd, reloc_entry, symbol, data, |
fr30_elf_i20_reloc (abfd, reloc_entry, symbol, data, |
253 |
input_section, output_bfd, error_message) |
input_section, output_bfd, error_message) |
254 |
bfd * abfd; |
bfd *abfd; |
255 |
arelent * reloc_entry; |
arelent *reloc_entry; |
256 |
asymbol * symbol; |
asymbol *symbol; |
257 |
PTR data; |
PTR data; |
258 |
asection * input_section; |
asection *input_section; |
259 |
bfd * output_bfd; |
bfd *output_bfd; |
260 |
char ** error_message ATTRIBUTE_UNUSED; |
char **error_message ATTRIBUTE_UNUSED; |
261 |
{ |
{ |
262 |
bfd_vma relocation; |
bfd_vma relocation; |
263 |
unsigned long x; |
unsigned long x; |
264 |
|
|
265 |
/* This part is from bfd_elf_generic_reloc. */ |
/* This part is from bfd_elf_generic_reloc. */ |
297 |
static bfd_reloc_status_type |
static bfd_reloc_status_type |
298 |
fr30_elf_i32_reloc (abfd, reloc_entry, symbol, data, |
fr30_elf_i32_reloc (abfd, reloc_entry, symbol, data, |
299 |
input_section, output_bfd, error_message) |
input_section, output_bfd, error_message) |
300 |
bfd * abfd; |
bfd *abfd; |
301 |
arelent * reloc_entry; |
arelent *reloc_entry; |
302 |
asymbol * symbol; |
asymbol *symbol; |
303 |
PTR data; |
PTR data; |
304 |
asection * input_section; |
asection *input_section; |
305 |
bfd * output_bfd; |
bfd *output_bfd; |
306 |
char ** error_message ATTRIBUTE_UNUSED; |
char **error_message ATTRIBUTE_UNUSED; |
307 |
{ |
{ |
308 |
bfd_vma relocation; |
bfd_vma relocation; |
309 |
|
|
310 |
/* This part is from bfd_elf_generic_reloc. */ |
/* This part is from bfd_elf_generic_reloc. */ |
311 |
if (output_bfd != (bfd *) NULL |
if (output_bfd != (bfd *) NULL |
359 |
|
|
360 |
static reloc_howto_type * |
static reloc_howto_type * |
361 |
fr30_reloc_type_lookup (abfd, code) |
fr30_reloc_type_lookup (abfd, code) |
362 |
bfd * abfd ATTRIBUTE_UNUSED; |
bfd *abfd ATTRIBUTE_UNUSED; |
363 |
bfd_reloc_code_real_type code; |
bfd_reloc_code_real_type code; |
364 |
{ |
{ |
365 |
unsigned int i; |
unsigned int i; |
376 |
|
|
377 |
static void |
static void |
378 |
fr30_info_to_howto_rela (abfd, cache_ptr, dst) |
fr30_info_to_howto_rela (abfd, cache_ptr, dst) |
379 |
bfd * abfd ATTRIBUTE_UNUSED; |
bfd *abfd ATTRIBUTE_UNUSED; |
380 |
arelent * cache_ptr; |
arelent *cache_ptr; |
381 |
Elf32_Internal_Rela * dst; |
Elf_Internal_Rela *dst; |
382 |
{ |
{ |
383 |
unsigned int r_type; |
unsigned int r_type; |
384 |
|
|
391 |
routines, but a few relocs, we have to do them ourselves. */ |
routines, but a few relocs, we have to do them ourselves. */ |
392 |
|
|
393 |
static bfd_reloc_status_type |
static bfd_reloc_status_type |
394 |
fr30_final_link_relocate (howto, input_bfd, input_section, contents, rel, relocation) |
fr30_final_link_relocate (howto, input_bfd, input_section, contents, rel, |
395 |
reloc_howto_type * howto; |
relocation) |
396 |
bfd * input_bfd; |
reloc_howto_type *howto; |
397 |
asection * input_section; |
bfd *input_bfd; |
398 |
bfd_byte * contents; |
asection *input_section; |
399 |
Elf_Internal_Rela * rel; |
bfd_byte *contents; |
400 |
bfd_vma relocation; |
Elf_Internal_Rela *rel; |
401 |
|
bfd_vma relocation; |
402 |
{ |
{ |
403 |
bfd_reloc_status_type r = bfd_reloc_ok; |
bfd_reloc_status_type r = bfd_reloc_ok; |
404 |
bfd_vma x; |
bfd_vma x; |
405 |
bfd_signed_vma srel; |
bfd_signed_vma srel; |
406 |
|
|
407 |
switch (howto->type) |
switch (howto->type) |
408 |
{ |
{ |
470 |
} |
} |
471 |
|
|
472 |
/* Relocate an FR30 ELF section. |
/* Relocate an FR30 ELF section. |
|
There is some attempt to make this function usable for many architectures, |
|
|
both USE_REL and USE_RELA ['twould be nice if such a critter existed], |
|
|
if only to serve as a learning tool. |
|
473 |
|
|
474 |
The RELOCATE_SECTION function is called by the new ELF backend linker |
The RELOCATE_SECTION function is called by the new ELF backend linker |
475 |
to handle the relocations for a section. |
to handle the relocations for a section. |
479 |
zero. |
zero. |
480 |
|
|
481 |
This function is responsible for adjusting the section contents as |
This function is responsible for adjusting the section contents as |
482 |
necessary, and (if using Rela relocs and generating a relocateable |
necessary, and (if using Rela relocs and generating a relocatable |
483 |
output file) adjusting the reloc addend as necessary. |
output file) adjusting the reloc addend as necessary. |
484 |
|
|
485 |
This function does not have to worry about setting the reloc |
This function does not have to worry about setting the reloc |
493 |
The global hash table entry for the global symbols can be found |
The global hash table entry for the global symbols can be found |
494 |
via elf_sym_hashes (input_bfd). |
via elf_sym_hashes (input_bfd). |
495 |
|
|
496 |
When generating relocateable output, this function must handle |
When generating relocatable output, this function must handle |
497 |
STB_LOCAL/STT_SECTION symbols specially. The output symbol is |
STB_LOCAL/STT_SECTION symbols specially. The output symbol is |
498 |
going to be the section symbol corresponding to the output |
going to be the section symbol corresponding to the output |
499 |
section, which means that the addend must be adjusted |
section, which means that the addend must be adjusted |
500 |
accordingly. */ |
accordingly. */ |
501 |
|
|
502 |
static boolean |
static bfd_boolean |
503 |
fr30_elf_relocate_section (output_bfd, info, input_bfd, input_section, |
fr30_elf_relocate_section (output_bfd, info, input_bfd, input_section, |
504 |
contents, relocs, local_syms, local_sections) |
contents, relocs, local_syms, local_sections) |
505 |
bfd * output_bfd; |
bfd *output_bfd; |
506 |
struct bfd_link_info * info; |
struct bfd_link_info *info; |
507 |
bfd * input_bfd; |
bfd *input_bfd; |
508 |
asection * input_section; |
asection *input_section; |
509 |
bfd_byte * contents; |
bfd_byte *contents; |
510 |
Elf_Internal_Rela * relocs; |
Elf_Internal_Rela *relocs; |
511 |
Elf_Internal_Sym * local_syms; |
Elf_Internal_Sym *local_syms; |
512 |
asection ** local_sections; |
asection **local_sections; |
513 |
{ |
{ |
514 |
Elf_Internal_Shdr * symtab_hdr; |
Elf_Internal_Shdr *symtab_hdr; |
515 |
struct elf_link_hash_entry ** sym_hashes; |
struct elf_link_hash_entry **sym_hashes; |
516 |
Elf_Internal_Rela * rel; |
Elf_Internal_Rela *rel; |
517 |
Elf_Internal_Rela * relend; |
Elf_Internal_Rela *relend; |
518 |
|
|
519 |
if (info->relocateable) |
if (info->relocatable) |
520 |
return true; |
return TRUE; |
521 |
|
|
522 |
symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr; |
symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr; |
523 |
sym_hashes = elf_sym_hashes (input_bfd); |
sym_hashes = elf_sym_hashes (input_bfd); |
525 |
|
|
526 |
for (rel = relocs; rel < relend; rel ++) |
for (rel = relocs; rel < relend; rel ++) |
527 |
{ |
{ |
528 |
reloc_howto_type * howto; |
reloc_howto_type *howto; |
529 |
unsigned long r_symndx; |
unsigned long r_symndx; |
530 |
Elf_Internal_Sym * sym; |
Elf_Internal_Sym *sym; |
531 |
asection * sec; |
asection *sec; |
532 |
struct elf_link_hash_entry * h; |
struct elf_link_hash_entry *h; |
533 |
bfd_vma relocation; |
bfd_vma relocation; |
534 |
bfd_reloc_status_type r; |
bfd_reloc_status_type r; |
535 |
const char * name = NULL; |
const char *name; |
536 |
int r_type; |
int r_type; |
537 |
|
|
538 |
r_type = ELF32_R_TYPE (rel->r_info); |
r_type = ELF32_R_TYPE (rel->r_info); |
539 |
|
|
552 |
{ |
{ |
553 |
sym = local_syms + r_symndx; |
sym = local_syms + r_symndx; |
554 |
sec = local_sections [r_symndx]; |
sec = local_sections [r_symndx]; |
555 |
relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel); |
relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel); |
556 |
|
|
557 |
name = bfd_elf_string_from_elf_section |
name = bfd_elf_string_from_elf_section |
558 |
(input_bfd, symtab_hdr->sh_link, sym->st_name); |
(input_bfd, symtab_hdr->sh_link, sym->st_name); |
559 |
name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name; |
name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name; |
|
#if 0 |
|
|
fprintf (stderr, "local: sec: %s, sym: %s (%d), value: %x + %x + %x addend %x\n", |
|
|
sec->name, name, sym->st_name, |
|
|
sec->output_section->vma, sec->output_offset, |
|
|
sym->st_value, rel->r_addend); |
|
|
#endif |
|
560 |
} |
} |
561 |
else |
else |
562 |
{ |
{ |
563 |
h = sym_hashes [r_symndx - symtab_hdr->sh_info]; |
bfd_boolean unresolved_reloc, warned; |
564 |
|
|
565 |
while (h->root.type == bfd_link_hash_indirect |
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, |
566 |
|| h->root.type == bfd_link_hash_warning) |
r_symndx, symtab_hdr, sym_hashes, |
567 |
h = (struct elf_link_hash_entry *) h->root.u.i.link; |
h, sec, relocation, |
568 |
|
unresolved_reloc, warned); |
569 |
|
|
570 |
name = h->root.root.string; |
name = h->root.root.string; |
|
|
|
|
if (h->root.type == bfd_link_hash_defined |
|
|
|| h->root.type == bfd_link_hash_defweak) |
|
|
{ |
|
|
sec = h->root.u.def.section; |
|
|
relocation = (h->root.u.def.value |
|
|
+ sec->output_section->vma |
|
|
+ sec->output_offset); |
|
|
#if 0 |
|
|
fprintf (stderr, |
|
|
"defined: sec: %s, name: %s, value: %x + %x + %x gives: %x\n", |
|
|
sec->name, name, h->root.u.def.value, |
|
|
sec->output_section->vma, sec->output_offset, relocation); |
|
|
#endif |
|
|
} |
|
|
else if (h->root.type == bfd_link_hash_undefweak) |
|
|
{ |
|
|
#if 0 |
|
|
fprintf (stderr, "undefined: sec: %s, name: %s\n", |
|
|
sec->name, name); |
|
|
#endif |
|
|
relocation = 0; |
|
|
} |
|
|
else |
|
|
{ |
|
|
if (! ((*info->callbacks->undefined_symbol) |
|
|
(info, h->root.root.string, input_bfd, |
|
|
input_section, rel->r_offset, true))) |
|
|
return false; |
|
|
#if 0 |
|
|
fprintf (stderr, "unknown: name: %s\n", name); |
|
|
#endif |
|
|
relocation = 0; |
|
|
} |
|
571 |
} |
} |
572 |
|
|
573 |
r = fr30_final_link_relocate (howto, input_bfd, input_section, |
r = fr30_final_link_relocate (howto, input_bfd, input_section, |
581 |
{ |
{ |
582 |
case bfd_reloc_overflow: |
case bfd_reloc_overflow: |
583 |
r = info->callbacks->reloc_overflow |
r = info->callbacks->reloc_overflow |
584 |
(info, name, howto->name, (bfd_vma) 0, |
(info, (h ? &h->root : NULL), name, howto->name, |
585 |
input_bfd, input_section, rel->r_offset); |
(bfd_vma) 0, input_bfd, input_section, rel->r_offset); |
586 |
break; |
break; |
587 |
|
|
588 |
case bfd_reloc_undefined: |
case bfd_reloc_undefined: |
589 |
r = info->callbacks->undefined_symbol |
r = info->callbacks->undefined_symbol |
590 |
(info, name, input_bfd, input_section, rel->r_offset, |
(info, name, input_bfd, input_section, rel->r_offset, |
591 |
true); |
TRUE); |
592 |
break; |
break; |
593 |
|
|
594 |
case bfd_reloc_outofrange: |
case bfd_reloc_outofrange: |
613 |
(info, msg, name, input_bfd, input_section, rel->r_offset); |
(info, msg, name, input_bfd, input_section, rel->r_offset); |
614 |
|
|
615 |
if (! r) |
if (! r) |
616 |
return false; |
return FALSE; |
617 |
} |
} |
618 |
} |
} |
619 |
|
|
620 |
return true; |
return TRUE; |
621 |
} |
} |
622 |
|
|
623 |
/* Return the section that should be marked against GC for a given |
/* Return the section that should be marked against GC for a given |
625 |
|
|
626 |
static asection * |
static asection * |
627 |
fr30_elf_gc_mark_hook (sec, info, rel, h, sym) |
fr30_elf_gc_mark_hook (sec, info, rel, h, sym) |
628 |
asection * sec; |
asection *sec; |
629 |
struct bfd_link_info * info ATTRIBUTE_UNUSED; |
struct bfd_link_info *info ATTRIBUTE_UNUSED; |
630 |
Elf_Internal_Rela * rel; |
Elf_Internal_Rela *rel; |
631 |
struct elf_link_hash_entry * h; |
struct elf_link_hash_entry *h; |
632 |
Elf_Internal_Sym * sym; |
Elf_Internal_Sym * sym; |
633 |
{ |
{ |
634 |
if (h != NULL) |
if (h != NULL) |
635 |
{ |
{ |
662 |
|
|
663 |
/* Update the got entry reference counts for the section being removed. */ |
/* Update the got entry reference counts for the section being removed. */ |
664 |
|
|
665 |
static boolean |
static bfd_boolean |
666 |
fr30_elf_gc_sweep_hook (abfd, info, sec, relocs) |
fr30_elf_gc_sweep_hook (abfd, info, sec, relocs) |
667 |
bfd * abfd ATTRIBUTE_UNUSED; |
bfd *abfd ATTRIBUTE_UNUSED; |
668 |
struct bfd_link_info * info ATTRIBUTE_UNUSED; |
struct bfd_link_info *info ATTRIBUTE_UNUSED; |
669 |
asection * sec ATTRIBUTE_UNUSED; |
asection *sec ATTRIBUTE_UNUSED; |
670 |
const Elf_Internal_Rela * relocs ATTRIBUTE_UNUSED; |
const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED; |
671 |
{ |
{ |
672 |
return true; |
return TRUE; |
673 |
} |
} |
674 |
|
|
675 |
/* Look through the relocs for a section during the first phase. |
/* Look through the relocs for a section during the first phase. |
676 |
Since we don't do .gots or .plts, we just need to consider the |
Since we don't do .gots or .plts, we just need to consider the |
677 |
virtual table relocs for gc. */ |
virtual table relocs for gc. */ |
678 |
|
|
679 |
static boolean |
static bfd_boolean |
680 |
fr30_elf_check_relocs (abfd, info, sec, relocs) |
fr30_elf_check_relocs (abfd, info, sec, relocs) |
681 |
bfd *abfd; |
bfd *abfd; |
682 |
struct bfd_link_info *info; |
struct bfd_link_info *info; |
688 |
const Elf_Internal_Rela *rel; |
const Elf_Internal_Rela *rel; |
689 |
const Elf_Internal_Rela *rel_end; |
const Elf_Internal_Rela *rel_end; |
690 |
|
|
691 |
if (info->relocateable) |
if (info->relocatable) |
692 |
return true; |
return TRUE; |
693 |
|
|
694 |
symtab_hdr = &elf_tdata (abfd)->symtab_hdr; |
symtab_hdr = &elf_tdata (abfd)->symtab_hdr; |
695 |
sym_hashes = elf_sym_hashes (abfd); |
sym_hashes = elf_sym_hashes (abfd); |
714 |
/* This relocation describes the C++ object vtable hierarchy. |
/* This relocation describes the C++ object vtable hierarchy. |
715 |
Reconstruct it for later use during GC. */ |
Reconstruct it for later use during GC. */ |
716 |
case R_FR30_GNU_VTINHERIT: |
case R_FR30_GNU_VTINHERIT: |
717 |
if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) |
if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) |
718 |
return false; |
return FALSE; |
719 |
break; |
break; |
720 |
|
|
721 |
/* This relocation describes which C++ vtable entries are actually |
/* This relocation describes which C++ vtable entries are actually |
722 |
used. Record for later use during GC. */ |
used. Record for later use during GC. */ |
723 |
case R_FR30_GNU_VTENTRY: |
case R_FR30_GNU_VTENTRY: |
724 |
if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend)) |
if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend)) |
725 |
return false; |
return FALSE; |
726 |
break; |
break; |
727 |
} |
} |
728 |
} |
} |
729 |
|
|
730 |
return true; |
return TRUE; |
731 |
} |
} |
732 |
|
|
733 |
#define ELF_ARCH bfd_arch_fr30 |
#define ELF_ARCH bfd_arch_fr30 |