2003-12-19 Alexandre Oliva <aoliva@redhat.com>
[deliverable/binutils-gdb.git] / bfd / elf32-frv.c
CommitLineData
4e5ba5b7 1/* FRV-specific support for 32-bit ELF.
1049f94e 2 Copyright 2002, 2003 Free Software Foundation, Inc.
4e5ba5b7
DB
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/frv.h"
25
26/* Forward declarations. */
27static bfd_reloc_status_type elf32_frv_relocate_lo16
28 PARAMS ((bfd *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
29static bfd_reloc_status_type elf32_frv_relocate_hi16
30 PARAMS ((bfd *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
31static bfd_reloc_status_type elf32_frv_relocate_label24
32 PARAMS ((bfd *, asection *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
33static bfd_reloc_status_type elf32_frv_relocate_gprel12
b34976b6
AM
34 PARAMS ((struct bfd_link_info *, bfd *, asection *, Elf_Internal_Rela *,
35 bfd_byte *, bfd_vma));
4e5ba5b7 36static bfd_reloc_status_type elf32_frv_relocate_gprelu12
b34976b6
AM
37 PARAMS ((struct bfd_link_info *, bfd *, asection *, Elf_Internal_Rela *,
38 bfd_byte *, bfd_vma));
4e5ba5b7 39static bfd_reloc_status_type elf32_frv_relocate_gprello
b34976b6
AM
40 PARAMS ((struct bfd_link_info *, bfd *, asection *, Elf_Internal_Rela *,
41 bfd_byte *, bfd_vma));
4e5ba5b7 42static bfd_reloc_status_type elf32_frv_relocate_gprelhi
b34976b6
AM
43 PARAMS ((struct bfd_link_info *, bfd *, asection *, Elf_Internal_Rela *,
44 bfd_byte *, bfd_vma));
4e5ba5b7
DB
45static reloc_howto_type *frv_reloc_type_lookup
46 PARAMS ((bfd *, bfd_reloc_code_real_type));
b34976b6 47static void frv_info_to_howto_rela
947216bf 48 PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
b34976b6
AM
49static bfd_boolean elf32_frv_relocate_section
50 PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
51 Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
52static bfd_boolean elf32_frv_add_symbol_hook
53 PARAMS (( bfd *, struct bfd_link_info *, const Elf_Internal_Sym *,
54 const char **, flagword *, asection **, bfd_vma *));
4e5ba5b7 55static bfd_reloc_status_type frv_final_link_relocate
b34976b6
AM
56 PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *,
57 Elf_Internal_Rela *, bfd_vma));
58static bfd_boolean elf32_frv_gc_sweep_hook
59 PARAMS ((bfd *, struct bfd_link_info *, asection *, const
60 Elf_Internal_Rela *));
4e5ba5b7 61static asection * elf32_frv_gc_mark_hook
b34976b6
AM
62 PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
63 struct elf_link_hash_entry *, Elf_Internal_Sym *));
64static bfd_boolean elf32_frv_check_relocs
65 PARAMS ((bfd *, struct bfd_link_info *, asection *,
66 const Elf_Internal_Rela *));
67static int elf32_frv_machine
68 PARAMS ((bfd *));
69static bfd_boolean elf32_frv_object_p
70 PARAMS ((bfd *));
71static bfd_boolean frv_elf_set_private_flags
72 PARAMS ((bfd *, flagword));
73static bfd_boolean frv_elf_copy_private_bfd_data
74 PARAMS ((bfd *, bfd *));
75static bfd_boolean frv_elf_merge_private_bfd_data
76 PARAMS ((bfd *, bfd *));
77static bfd_boolean frv_elf_print_private_bfd_data
78 PARAMS ((bfd *, PTR));
4e5ba5b7
DB
79
80static reloc_howto_type elf32_frv_howto_table [] =
81{
82 /* This reloc does nothing. */
83 HOWTO (R_FRV_NONE, /* type */
84 0, /* rightshift */
85 2, /* size (0 = byte, 1 = short, 2 = long) */
86 32, /* bitsize */
b34976b6 87 FALSE, /* pc_relative */
4e5ba5b7
DB
88 0, /* bitpos */
89 complain_overflow_bitfield, /* complain_on_overflow */
90 bfd_elf_generic_reloc, /* special_function */
91 "R_FRV_NONE", /* name */
b34976b6 92 FALSE, /* partial_inplace */
4e5ba5b7
DB
93 0, /* src_mask */
94 0, /* dst_mask */
b34976b6 95 FALSE), /* pcrel_offset */
4e5ba5b7
DB
96
97 /* A 32 bit absolute relocation. */
98 HOWTO (R_FRV_32, /* type */
99 0, /* rightshift */
100 2, /* size (0 = byte, 1 = short, 2 = long) */
101 32, /* bitsize */
b34976b6 102 FALSE, /* pc_relative */
4e5ba5b7
DB
103 0, /* bitpos */
104 complain_overflow_bitfield, /* complain_on_overflow */
105 bfd_elf_generic_reloc, /* special_function */
106 "R_FRV_32", /* name */
b34976b6 107 FALSE, /* partial_inplace */
4e5ba5b7
DB
108 0xffffffff, /* src_mask */
109 0xffffffff, /* dst_mask */
b34976b6 110 FALSE), /* pcrel_offset */
4e5ba5b7
DB
111
112 /* A 16 bit pc-relative relocation. */
113 HOWTO (R_FRV_LABEL16, /* type */
b15b52ef 114 2, /* rightshift */
4e5ba5b7
DB
115 2, /* size (0 = byte, 1 = short, 2 = long) */
116 16, /* bitsize */
b34976b6 117 TRUE, /* pc_relative */
4e5ba5b7
DB
118 0, /* bitpos */
119 complain_overflow_bitfield, /* complain_on_overflow */
120 bfd_elf_generic_reloc, /* special_function */
121 "R_FRV_LABEL16", /* name */
b34976b6 122 FALSE, /* partial_inplace */
4e5ba5b7
DB
123 0xffff, /* src_mask */
124 0xffff, /* dst_mask */
b34976b6 125 TRUE), /* pcrel_offset */
4e5ba5b7
DB
126
127 /* A 24-bit pc-relative relocation. */
128 HOWTO (R_FRV_LABEL24, /* type */
129 2, /* rightshift */
130 2, /* size (0 = byte, 1 = short, 2 = long) */
131 26, /* bitsize */
b34976b6 132 TRUE, /* pc_relative */
4e5ba5b7
DB
133 0, /* bitpos */
134 complain_overflow_bitfield, /* complain_on_overflow */
135 bfd_elf_generic_reloc, /* special_function */
136 "R_FRV_LABEL24", /* name */
b34976b6 137 FALSE, /* partial_inplace */
4e5ba5b7
DB
138 0x7e03ffff, /* src_mask */
139 0x7e03ffff, /* dst_mask */
b34976b6 140 TRUE), /* pcrel_offset */
4e5ba5b7
DB
141
142 HOWTO (R_FRV_LO16, /* type */
143 0, /* rightshift */
144 2, /* size (0 = byte, 1 = short, 2 = long) */
145 16, /* bitsize */
b34976b6 146 FALSE, /* pc_relative */
4e5ba5b7
DB
147 0, /* bitpos */
148 complain_overflow_dont, /* complain_on_overflow */
149 bfd_elf_generic_reloc, /* special_function */
150 "R_FRV_LO16", /* name */
b34976b6 151 FALSE, /* partial_inplace */
4e5ba5b7
DB
152 0xffff, /* src_mask */
153 0xffff, /* dst_mask */
b34976b6 154 FALSE), /* pcrel_offset */
4e5ba5b7
DB
155
156 HOWTO (R_FRV_HI16, /* type */
157 0, /* rightshift */
158 2, /* size (0 = byte, 1 = short, 2 = long) */
159 16, /* bitsize */
b34976b6 160 FALSE, /* pc_relative */
4e5ba5b7
DB
161 0, /* bitpos */
162 complain_overflow_dont, /* complain_on_overflow */
163 bfd_elf_generic_reloc, /* special_function */
164 "R_FRV_HI16", /* name */
b34976b6 165 FALSE, /* partial_inplace */
4e5ba5b7
DB
166 0xffff, /* src_mask */
167 0xffff, /* dst_mask */
b34976b6 168 FALSE), /* pcrel_offset */
4e5ba5b7
DB
169
170 HOWTO (R_FRV_GPREL12, /* type */
171 0, /* rightshift */
172 2, /* size (0 = byte, 1 = short, 2 = long) */
173 12, /* bitsize */
b34976b6 174 FALSE, /* pc_relative */
4e5ba5b7
DB
175 0, /* bitpos */
176 complain_overflow_dont, /* complain_on_overflow */
177 bfd_elf_generic_reloc, /* special_function */
178 "R_FRV_GPREL12", /* name */
b34976b6 179 FALSE, /* partial_inplace */
4e5ba5b7
DB
180 0xfff, /* src_mask */
181 0xfff, /* dst_mask */
b34976b6 182 FALSE), /* pcrel_offset */
4e5ba5b7
DB
183
184 HOWTO (R_FRV_GPRELU12, /* type */
185 0, /* rightshift */
186 2, /* size (0 = byte, 1 = short, 2 = long) */
187 12, /* bitsize */
b34976b6 188 FALSE, /* pc_relative */
4e5ba5b7
DB
189 0, /* bitpos */
190 complain_overflow_dont, /* complain_on_overflow */
191 bfd_elf_generic_reloc, /* special_function */
192 "R_FRV_GPRELU12", /* name */
b34976b6 193 FALSE, /* partial_inplace */
4e5ba5b7
DB
194 0xfff, /* src_mask */
195 0x3f03f, /* dst_mask */
b34976b6 196 FALSE), /* pcrel_offset */
4e5ba5b7
DB
197
198 HOWTO (R_FRV_GPREL32, /* type */
199 0, /* rightshift */
200 2, /* size (0 = byte, 1 = short, 2 = long) */
201 32, /* bitsize */
b34976b6 202 FALSE, /* pc_relative */
4e5ba5b7
DB
203 0, /* bitpos */
204 complain_overflow_dont, /* complain_on_overflow */
205 bfd_elf_generic_reloc, /* special_function */
206 "R_FRV_GPREL32", /* name */
b34976b6 207 FALSE, /* partial_inplace */
4e5ba5b7
DB
208 0xffffffff, /* src_mask */
209 0xffffffff, /* dst_mask */
b34976b6 210 FALSE), /* pcrel_offset */
4e5ba5b7
DB
211
212 HOWTO (R_FRV_GPRELHI, /* type */
213 0, /* rightshift */
214 2, /* size (0 = byte, 1 = short, 2 = long) */
215 16, /* bitsize */
b34976b6 216 FALSE, /* pc_relative */
4e5ba5b7
DB
217 0, /* bitpos */
218 complain_overflow_dont, /* complain_on_overflow */
219 bfd_elf_generic_reloc, /* special_function */
220 "R_FRV_GPRELHI", /* name */
b34976b6 221 FALSE, /* partial_inplace */
4e5ba5b7
DB
222 0xffff, /* src_mask */
223 0xffff, /* dst_mask */
b34976b6 224 FALSE), /* pcrel_offset */
4e5ba5b7
DB
225
226 HOWTO (R_FRV_GPRELLO, /* type */
227 0, /* rightshift */
228 2, /* size (0 = byte, 1 = short, 2 = long) */
229 16, /* bitsize */
b34976b6 230 FALSE, /* pc_relative */
4e5ba5b7
DB
231 0, /* bitpos */
232 complain_overflow_dont, /* complain_on_overflow */
233 bfd_elf_generic_reloc, /* special_function */
234 "R_FRV_GPRELLO", /* name */
b34976b6 235 FALSE, /* partial_inplace */
4e5ba5b7
DB
236 0xffff, /* src_mask */
237 0xffff, /* dst_mask */
b34976b6 238 FALSE), /* pcrel_offset */
4e5ba5b7
DB
239};
240
241/* GNU extension to record C++ vtable hierarchy. */
242static reloc_howto_type elf32_frv_vtinherit_howto =
243 HOWTO (R_FRV_GNU_VTINHERIT, /* type */
244 0, /* rightshift */
245 2, /* size (0 = byte, 1 = short, 2 = long) */
246 0, /* bitsize */
b34976b6 247 FALSE, /* pc_relative */
4e5ba5b7
DB
248 0, /* bitpos */
249 complain_overflow_dont, /* complain_on_overflow */
250 NULL, /* special_function */
251 "R_FRV_GNU_VTINHERIT", /* name */
b34976b6 252 FALSE, /* partial_inplace */
4e5ba5b7
DB
253 0, /* src_mask */
254 0, /* dst_mask */
b34976b6 255 FALSE); /* pcrel_offset */
4e5ba5b7
DB
256
257 /* GNU extension to record C++ vtable member usage. */
258static reloc_howto_type elf32_frv_vtentry_howto =
259 HOWTO (R_FRV_GNU_VTENTRY, /* type */
260 0, /* rightshift */
261 2, /* size (0 = byte, 1 = short, 2 = long) */
262 0, /* bitsize */
b34976b6 263 FALSE, /* pc_relative */
4e5ba5b7
DB
264 0, /* bitpos */
265 complain_overflow_dont, /* complain_on_overflow */
266 _bfd_elf_rel_vtable_reloc_fn, /* special_function */
267 "R_FRV_GNU_VTENTRY", /* name */
b34976b6 268 FALSE, /* partial_inplace */
4e5ba5b7
DB
269 0, /* src_mask */
270 0, /* dst_mask */
b34976b6 271 FALSE); /* pcrel_offset */
4e5ba5b7
DB
272\f
273/* Map BFD reloc types to FRV ELF reloc types. */
274#if 0
275struct frv_reloc_map
276{
277 unsigned int bfd_reloc_val;
278 unsigned int frv_reloc_val;
279};
280
281static const struct frv_reloc_map frv_reloc_map [] =
282{
283 { BFD_RELOC_NONE, R_FRV_NONE },
284 { BFD_RELOC_32, R_FRV_32 },
285 { BFD_RELOC_FRV_LABEL16, R_FRV_LABEL16 },
286 { BFD_RELOC_FRV_LABEL24, R_FRV_LABEL24 },
287 { BFD_RELOC_FRV_LO16, R_FRV_LO16 },
288 { BFD_RELOC_FRV_HI16, R_FRV_HI16 },
289 { BFD_RELOC_FRV_GPREL12, R_FRV_GPREL12 },
290 { BFD_RELOC_FRV_GPRELU12, R_FRV_GPRELU12 },
291 { BFD_RELOC_FRV_GPREL32, R_FRV_GPREL32 },
292 { BFD_RELOC_FRV_GPRELHI, R_FRV_GPRELHI },
293 { BFD_RELOC_FRV_GPRELLO, R_FRV_GPRELLO },
294 { BFD_RELOC_VTABLE_INHERIT, R_FRV_GNU_VTINHERIT },
295 { BFD_RELOC_VTABLE_ENTRY, R_FRV_GNU_VTENTRY },
296};
297#endif
298
299/* Handle an FRV small data reloc. */
300
301static bfd_reloc_status_type
b34976b6
AM
302elf32_frv_relocate_gprel12 (info, input_bfd, input_section, relocation,
303 contents, value)
4e5ba5b7
DB
304 struct bfd_link_info *info;
305 bfd *input_bfd;
306 asection *input_section;
307 Elf_Internal_Rela *relocation;
308 bfd_byte *contents;
309 bfd_vma value;
310{
311 bfd_vma insn;
312 bfd_vma gp;
313 struct bfd_link_hash_entry *h;
314
b34976b6 315 h = bfd_link_hash_lookup (info->hash, "_gp", FALSE, FALSE, TRUE);
4e5ba5b7
DB
316
317 gp = (h->u.def.value
318 + h->u.def.section->output_section->vma
319 + h->u.def.section->output_offset);
320
321 value -= input_section->output_section->vma;
322 value -= (gp - input_section->output_section->vma);
323
324 insn = bfd_get_32 (input_bfd, contents + relocation->r_offset);
325
326 value += relocation->r_addend;
327
328 if ((long) value > 0x7ff || (long) value < -0x800)
329 return bfd_reloc_overflow;
330
331 bfd_put_32 (input_bfd,
332 (insn & 0xfffff000) | (value & 0xfff),
333 contents + relocation->r_offset);
334
335 return bfd_reloc_ok;
336}
337
338/* Handle an FRV small data reloc. for the u12 field. */
339
340static bfd_reloc_status_type
b34976b6
AM
341elf32_frv_relocate_gprelu12 (info, input_bfd, input_section, relocation,
342 contents, value)
4e5ba5b7
DB
343 struct bfd_link_info *info;
344 bfd *input_bfd;
345 asection *input_section;
346 Elf_Internal_Rela *relocation;
347 bfd_byte *contents;
348 bfd_vma value;
349{
350 bfd_vma insn;
351 bfd_vma gp;
352 struct bfd_link_hash_entry *h;
353 bfd_vma mask;
354
b34976b6 355 h = bfd_link_hash_lookup (info->hash, "_gp", FALSE, FALSE, TRUE);
4e5ba5b7
DB
356
357 gp = (h->u.def.value
358 + h->u.def.section->output_section->vma
359 + h->u.def.section->output_offset);
b34976b6 360
4e5ba5b7
DB
361 value -= input_section->output_section->vma;
362 value -= (gp - input_section->output_section->vma);
363
364 insn = bfd_get_32 (input_bfd, contents + relocation->r_offset);
365
366 value += relocation->r_addend;
367
368 if ((long) value > 0x7ff || (long) value < -0x800)
369 return bfd_reloc_overflow;
370
371 /* The high 6 bits go into bits 17-12. The low 6 bits go into bits 5-0. */
372 mask = 0x3f03f;
373 insn = (insn & ~mask) | ((value & 0xfc0) << 12) | (value & 0x3f);
374
375 bfd_put_32 (input_bfd, insn, contents + relocation->r_offset);
376
377 return bfd_reloc_ok;
378}
379
380/* Handle an FRV ELF HI16 reloc. */
381
382static bfd_reloc_status_type
383elf32_frv_relocate_hi16 (input_bfd, relhi, contents, value)
384 bfd *input_bfd;
385 Elf_Internal_Rela *relhi;
386 bfd_byte *contents;
387 bfd_vma value;
388{
389 bfd_vma insn;
390
391 insn = bfd_get_32 (input_bfd, contents + relhi->r_offset);
392
393 value += relhi->r_addend;
394 value = ((value >> 16) & 0xffff);
395
396 insn = (insn & 0xffff0000) | value;
397
398 if ((long) value > 0xffff || (long) value < -0x10000)
399 return bfd_reloc_overflow;
400
401 bfd_put_32 (input_bfd, insn, contents + relhi->r_offset);
402 return bfd_reloc_ok;
403
404}
405static bfd_reloc_status_type
406elf32_frv_relocate_lo16 (input_bfd, rello, contents, value)
407 bfd *input_bfd;
408 Elf_Internal_Rela *rello;
409 bfd_byte *contents;
410 bfd_vma value;
411{
412 bfd_vma insn;
413
414 insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
415
416 value += rello->r_addend;
417 value = value & 0xffff;
418
419 insn = (insn & 0xffff0000) | value;
420
421 if ((long) value > 0xffff || (long) value < -0x10000)
422 return bfd_reloc_overflow;
423
424 bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
425 return bfd_reloc_ok;
426}
427
428/* Perform the relocation for the CALL label24 instruction. */
429
430static bfd_reloc_status_type
431elf32_frv_relocate_label24 (input_bfd, input_section, rello, contents, value)
432 bfd *input_bfd;
433 asection *input_section;
434 Elf_Internal_Rela *rello;
435 bfd_byte *contents;
436 bfd_vma value;
437{
438 bfd_vma insn;
439 bfd_vma label6;
440 bfd_vma label18;
441
442 /* The format for the call instruction is:
443
b34976b6 444 0 000000 0001111 000000000000000000
4e5ba5b7
DB
445 label6 opcode label18
446
447 The branch calculation is: pc + (4*label24)
448 where label24 is the concatenation of label6 and label18. */
449
450 /* Grab the instruction. */
451 insn = bfd_get_32 (input_bfd, contents + rello->r_offset);
452
453 value -= input_section->output_section->vma + input_section->output_offset;
454 value -= rello->r_offset;
455 value += rello->r_addend;
456
457 value = value >> 2;
458
459 label6 = value & 0xfc0000;
460 label6 = label6 << 7;
461
462 label18 = value & 0x3ffff;
463
464 insn = insn & 0x803c0000;
465 insn = insn | label6;
466 insn = insn | label18;
467
468 bfd_put_32 (input_bfd, insn, contents + rello->r_offset);
469
470 return bfd_reloc_ok;
471}
472
473static bfd_reloc_status_type
b34976b6
AM
474elf32_frv_relocate_gprelhi (info, input_bfd, input_section, relocation,
475 contents, value)
4e5ba5b7
DB
476 struct bfd_link_info *info;
477 bfd *input_bfd;
478 asection *input_section;
479 Elf_Internal_Rela *relocation;
480 bfd_byte *contents;
481 bfd_vma value;
482{
483 bfd_vma insn;
484 bfd_vma gp;
485 struct bfd_link_hash_entry *h;
486
b34976b6 487 h = bfd_link_hash_lookup (info->hash, "_gp", FALSE, FALSE, TRUE);
4e5ba5b7
DB
488
489 gp = (h->u.def.value
490 + h->u.def.section->output_section->vma
491 + h->u.def.section->output_offset);
492
493 value -= input_section->output_section->vma;
494 value -= (gp - input_section->output_section->vma);
495 value += relocation->r_addend;
496 value = ((value >> 16) & 0xffff);
497
498 if ((long) value > 0xffff || (long) value < -0x10000)
499 return bfd_reloc_overflow;
500
501 insn = bfd_get_32 (input_bfd, contents + relocation->r_offset);
502 insn = (insn & 0xffff0000) | value;
503
504 bfd_put_32 (input_bfd, insn, contents + relocation->r_offset);
505 return bfd_reloc_ok;
506}
507
508static bfd_reloc_status_type
b34976b6
AM
509elf32_frv_relocate_gprello (info, input_bfd, input_section, relocation,
510 contents, value)
4e5ba5b7
DB
511 struct bfd_link_info *info;
512 bfd *input_bfd;
513 asection *input_section;
514 Elf_Internal_Rela *relocation;
515 bfd_byte *contents;
516 bfd_vma value;
517{
518 bfd_vma insn;
519 bfd_vma gp;
520 struct bfd_link_hash_entry *h;
521
b34976b6 522 h = bfd_link_hash_lookup (info->hash, "_gp", FALSE, FALSE, TRUE);
4e5ba5b7
DB
523
524 gp = (h->u.def.value
525 + h->u.def.section->output_section->vma
526 + h->u.def.section->output_offset);
527
528 value -= input_section->output_section->vma;
529 value -= (gp - input_section->output_section->vma);
530 value += relocation->r_addend;
531 value = value & 0xffff;
532
533 if ((long) value > 0xffff || (long) value < -0x10000)
534 return bfd_reloc_overflow;
535
536 insn = bfd_get_32 (input_bfd, contents + relocation->r_offset);
537 insn = (insn & 0xffff0000) | value;
538
539 bfd_put_32 (input_bfd, insn, contents + relocation->r_offset);
540
541 return bfd_reloc_ok;
542}
543
544static reloc_howto_type *
545frv_reloc_type_lookup (abfd, code)
b34976b6 546 bfd *abfd ATTRIBUTE_UNUSED;
4e5ba5b7
DB
547 bfd_reloc_code_real_type code;
548{
549 switch (code)
550 {
551 default:
552 break;
553
554 case BFD_RELOC_NONE:
555 return &elf32_frv_howto_table[ (int) R_FRV_NONE];
b34976b6 556
4e5ba5b7
DB
557 case BFD_RELOC_32:
558 case BFD_RELOC_CTOR:
559 return &elf32_frv_howto_table[ (int) R_FRV_32];
560
561 case BFD_RELOC_FRV_LABEL16:
562 return &elf32_frv_howto_table[ (int) R_FRV_LABEL16];
563
564 case BFD_RELOC_FRV_LABEL24:
565 return &elf32_frv_howto_table[ (int) R_FRV_LABEL24];
566
567 case BFD_RELOC_FRV_LO16:
568 return &elf32_frv_howto_table[ (int) R_FRV_LO16];
569
570 case BFD_RELOC_FRV_HI16:
571 return &elf32_frv_howto_table[ (int) R_FRV_HI16];
572
573 case BFD_RELOC_FRV_GPREL12:
574 return &elf32_frv_howto_table[ (int) R_FRV_GPREL12];
575
576 case BFD_RELOC_FRV_GPRELU12:
577 return &elf32_frv_howto_table[ (int) R_FRV_GPRELU12];
578
579 case BFD_RELOC_FRV_GPREL32:
580 return &elf32_frv_howto_table[ (int) R_FRV_GPREL32];
581
582 case BFD_RELOC_FRV_GPRELHI:
583 return &elf32_frv_howto_table[ (int) R_FRV_GPRELHI];
584
585 case BFD_RELOC_FRV_GPRELLO:
586 return &elf32_frv_howto_table[ (int) R_FRV_GPRELLO];
587
588 case BFD_RELOC_VTABLE_INHERIT:
589 return &elf32_frv_vtinherit_howto;
590
591 case BFD_RELOC_VTABLE_ENTRY:
592 return &elf32_frv_vtentry_howto;
593 }
594
595 return NULL;
596}
597
598/* Set the howto pointer for an FRV ELF reloc. */
599
600static void
601frv_info_to_howto_rela (abfd, cache_ptr, dst)
b34976b6
AM
602 bfd *abfd ATTRIBUTE_UNUSED;
603 arelent *cache_ptr;
604 Elf_Internal_Rela *dst;
4e5ba5b7
DB
605{
606 unsigned int r_type;
607
608 r_type = ELF32_R_TYPE (dst->r_info);
609 switch (r_type)
610 {
611 case R_FRV_GNU_VTINHERIT:
612 cache_ptr->howto = &elf32_frv_vtinherit_howto;
613 break;
614
615 case R_FRV_GNU_VTENTRY:
616 cache_ptr->howto = &elf32_frv_vtentry_howto;
617 break;
618
619 default:
620 cache_ptr->howto = & elf32_frv_howto_table [r_type];
621 break;
622 }
623}
624\f
625/* Perform a single relocation. By default we use the standard BFD
626 routines, but a few relocs, we have to do them ourselves. */
627
628static bfd_reloc_status_type
b34976b6
AM
629frv_final_link_relocate (howto, input_bfd, input_section, contents, rel,
630 relocation)
631 reloc_howto_type *howto;
632 bfd *input_bfd;
633 asection *input_section;
634 bfd_byte *contents;
635 Elf_Internal_Rela *rel;
636 bfd_vma relocation;
4e5ba5b7
DB
637{
638 return _bfd_final_link_relocate (howto, input_bfd, input_section,
639 contents, rel->r_offset, relocation,
640 rel->r_addend);
641}
642
643\f
644/* Relocate an FRV ELF section.
4e5ba5b7
DB
645
646 The RELOCATE_SECTION function is called by the new ELF backend linker
647 to handle the relocations for a section.
648
649 The relocs are always passed as Rela structures; if the section
650 actually uses Rel structures, the r_addend field will always be
651 zero.
652
653 This function is responsible for adjusting the section contents as
1049f94e 654 necessary, and (if using Rela relocs and generating a relocatable
4e5ba5b7
DB
655 output file) adjusting the reloc addend as necessary.
656
657 This function does not have to worry about setting the reloc
658 address or the reloc symbol index.
659
660 LOCAL_SYMS is a pointer to the swapped in local symbols.
661
662 LOCAL_SECTIONS is an array giving the section in the input file
663 corresponding to the st_shndx field of each local symbol.
664
665 The global hash table entry for the global symbols can be found
666 via elf_sym_hashes (input_bfd).
667
1049f94e 668 When generating relocatable output, this function must handle
4e5ba5b7
DB
669 STB_LOCAL/STT_SECTION symbols specially. The output symbol is
670 going to be the section symbol corresponding to the output
671 section, which means that the addend must be adjusted
672 accordingly. */
673
b34976b6 674static bfd_boolean
4e5ba5b7 675elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
de2d743e 676 contents, relocs, local_syms, local_sections)
b34976b6
AM
677 bfd *output_bfd ATTRIBUTE_UNUSED;
678 struct bfd_link_info *info;
679 bfd *input_bfd;
680 asection *input_section;
681 bfd_byte *contents;
682 Elf_Internal_Rela *relocs;
683 Elf_Internal_Sym *local_syms;
684 asection **local_sections;
4e5ba5b7 685{
b34976b6
AM
686 Elf_Internal_Shdr *symtab_hdr;
687 struct elf_link_hash_entry **sym_hashes;
688 Elf_Internal_Rela *rel;
689 Elf_Internal_Rela *relend;
4e5ba5b7 690
1049f94e 691 if (info->relocatable)
b34976b6 692 return TRUE;
de2d743e 693
4e5ba5b7
DB
694 symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
695 sym_hashes = elf_sym_hashes (input_bfd);
696 relend = relocs + input_section->reloc_count;
697
698 for (rel = relocs; rel < relend; rel ++)
699 {
b34976b6
AM
700 reloc_howto_type *howto;
701 unsigned long r_symndx;
702 Elf_Internal_Sym *sym;
703 asection *sec;
704 struct elf_link_hash_entry *h;
705 bfd_vma relocation;
706 bfd_reloc_status_type r;
707 const char * name = NULL;
708 int r_type;
709
4e5ba5b7 710 r_type = ELF32_R_TYPE (rel->r_info);
b34976b6 711
4e5ba5b7
DB
712 if ( r_type == R_FRV_GNU_VTINHERIT
713 || r_type == R_FRV_GNU_VTENTRY)
714 continue;
b34976b6 715
4e5ba5b7 716 /* This is a final link. */
de2d743e 717 r_symndx = ELF32_R_SYM (rel->r_info);
4e5ba5b7
DB
718 howto = elf32_frv_howto_table + ELF32_R_TYPE (rel->r_info);
719 h = NULL;
720 sym = NULL;
721 sec = NULL;
b34976b6 722
4e5ba5b7
DB
723 if (r_symndx < symtab_hdr->sh_info)
724 {
725 sym = local_syms + r_symndx;
726 sec = local_sections [r_symndx];
8517fae7 727 relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
b34976b6 728
4e5ba5b7
DB
729 name = bfd_elf_string_from_elf_section
730 (input_bfd, symtab_hdr->sh_link, sym->st_name);
731 name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
732 }
733 else
734 {
735 h = sym_hashes [r_symndx - symtab_hdr->sh_info];
b34976b6 736
4e5ba5b7
DB
737 while (h->root.type == bfd_link_hash_indirect
738 || h->root.type == bfd_link_hash_warning)
739 h = (struct elf_link_hash_entry *) h->root.u.i.link;
740
741 name = h->root.root.string;
b34976b6 742
4e5ba5b7
DB
743 if (h->root.type == bfd_link_hash_defined
744 || h->root.type == bfd_link_hash_defweak)
745 {
746 sec = h->root.u.def.section;
747 relocation = (h->root.u.def.value
748 + sec->output_section->vma
749 + sec->output_offset);
750 }
751 else if (h->root.type == bfd_link_hash_undefweak)
752 {
753 relocation = 0;
754 }
755 else
756 {
757 if (! ((*info->callbacks->undefined_symbol)
758 (info, h->root.root.string, input_bfd,
b34976b6
AM
759 input_section, rel->r_offset, TRUE)))
760 return FALSE;
4e5ba5b7
DB
761 relocation = 0;
762 }
763 }
b34976b6 764
4e5ba5b7
DB
765 if (r_type == R_FRV_HI16)
766 r = elf32_frv_relocate_hi16 (input_bfd, rel, contents, relocation);
767
768 else if (r_type == R_FRV_LO16)
769 r = elf32_frv_relocate_lo16 (input_bfd, rel, contents, relocation);
770
771 else if (r_type == R_FRV_LABEL24)
b34976b6
AM
772 r = elf32_frv_relocate_label24 (input_bfd, input_section, rel,
773 contents, relocation);
4e5ba5b7
DB
774
775 else if (r_type == R_FRV_GPREL12)
b34976b6
AM
776 r = elf32_frv_relocate_gprel12 (info, input_bfd, input_section, rel,
777 contents, relocation);
4e5ba5b7
DB
778
779 else if (r_type == R_FRV_GPRELU12)
b34976b6
AM
780 r = elf32_frv_relocate_gprelu12 (info, input_bfd, input_section, rel,
781 contents, relocation);
4e5ba5b7
DB
782
783 else if (r_type == R_FRV_GPRELLO)
b34976b6
AM
784 r = elf32_frv_relocate_gprello (info, input_bfd, input_section, rel,
785 contents, relocation);
4e5ba5b7
DB
786
787 else if (r_type == R_FRV_GPRELHI)
b34976b6
AM
788 r = elf32_frv_relocate_gprelhi (info, input_bfd, input_section, rel,
789 contents, relocation);
4e5ba5b7
DB
790
791 else
b34976b6
AM
792 r = frv_final_link_relocate (howto, input_bfd, input_section, contents,
793 rel, relocation);
4e5ba5b7
DB
794
795 if (r != bfd_reloc_ok)
796 {
797 const char * msg = (const char *) NULL;
798
799 switch (r)
800 {
801 case bfd_reloc_overflow:
802 r = info->callbacks->reloc_overflow
803 (info, name, howto->name, (bfd_vma) 0,
804 input_bfd, input_section, rel->r_offset);
805 break;
b34976b6 806
4e5ba5b7
DB
807 case bfd_reloc_undefined:
808 r = info->callbacks->undefined_symbol
b34976b6 809 (info, name, input_bfd, input_section, rel->r_offset, TRUE);
4e5ba5b7 810 break;
b34976b6 811
4e5ba5b7
DB
812 case bfd_reloc_outofrange:
813 msg = _("internal error: out of range error");
814 break;
815
816 case bfd_reloc_notsupported:
817 msg = _("internal error: unsupported relocation error");
818 break;
819
820 case bfd_reloc_dangerous:
821 msg = _("internal error: dangerous relocation");
822 break;
823
824 default:
825 msg = _("internal error: unknown error");
826 break;
827 }
828
829 if (msg)
830 r = info->callbacks->warning
831 (info, msg, name, input_bfd, input_section, rel->r_offset);
832
833 if (! r)
b34976b6 834 return FALSE;
4e5ba5b7
DB
835 }
836 }
837
b34976b6 838 return TRUE;
4e5ba5b7
DB
839}
840\f
841/* Return the section that should be marked against GC for a given
842 relocation. */
843
844static asection *
1e2f5b6e 845elf32_frv_gc_mark_hook (sec, info, rel, h, sym)
b34976b6
AM
846 asection *sec;
847 struct bfd_link_info *info ATTRIBUTE_UNUSED;
848 Elf_Internal_Rela *rel;
849 struct elf_link_hash_entry *h;
850 Elf_Internal_Sym *sym;
4e5ba5b7
DB
851{
852 if (h != NULL)
853 {
854 switch (ELF32_R_TYPE (rel->r_info))
855 {
856 case R_FRV_GNU_VTINHERIT:
857 case R_FRV_GNU_VTENTRY:
858 break;
859
860 default:
861 switch (h->root.type)
862 {
863 default:
864 break;
865
866 case bfd_link_hash_defined:
867 case bfd_link_hash_defweak:
868 return h->root.u.def.section;
869
870 case bfd_link_hash_common:
871 return h->root.u.c.p->section;
872 }
873 }
874 }
875 else
1e2f5b6e 876 return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
4e5ba5b7
DB
877
878 return NULL;
879}
880
881/* Update the got entry reference counts for the section being removed. */
882
b34976b6 883static bfd_boolean
4e5ba5b7 884elf32_frv_gc_sweep_hook (abfd, info, sec, relocs)
b34976b6
AM
885 bfd *abfd ATTRIBUTE_UNUSED;
886 struct bfd_link_info *info ATTRIBUTE_UNUSED;
887 asection *sec ATTRIBUTE_UNUSED;
888 const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
4e5ba5b7 889{
b34976b6 890 return TRUE;
4e5ba5b7
DB
891}
892
893\f
894/* Hook called by the linker routine which adds symbols from an object
895 file. We use it to put .comm items in .scomm, and not .comm. */
896
b34976b6 897static bfd_boolean
4e5ba5b7
DB
898elf32_frv_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
899 bfd *abfd;
900 struct bfd_link_info *info;
901 const Elf_Internal_Sym *sym;
902 const char **namep ATTRIBUTE_UNUSED;
903 flagword *flagsp ATTRIBUTE_UNUSED;
904 asection **secp;
905 bfd_vma *valp;
906{
907 if (sym->st_shndx == SHN_COMMON
1049f94e 908 && !info->relocatable
4e5ba5b7
DB
909 && (int)sym->st_size <= (int)bfd_get_gp_size (abfd))
910 {
911 /* Common symbols less than or equal to -G nn bytes are
912 automatically put into .sbss. */
913
914 asection *scomm = bfd_get_section_by_name (abfd, ".scommon");
915
916 if (scomm == NULL)
917 {
918 scomm = bfd_make_section (abfd, ".scommon");
919 if (scomm == NULL
920 || !bfd_set_section_flags (abfd, scomm, (SEC_ALLOC
921 | SEC_IS_COMMON
922 | SEC_LINKER_CREATED)))
b34976b6 923 return FALSE;
4e5ba5b7
DB
924 }
925
926 *secp = scomm;
927 *valp = sym->st_size;
928 }
929
b34976b6 930 return TRUE;
4e5ba5b7
DB
931}
932/* Look through the relocs for a section during the first phase.
933 Since we don't do .gots or .plts, we just need to consider the
934 virtual table relocs for gc. */
b34976b6
AM
935
936static bfd_boolean
4e5ba5b7
DB
937elf32_frv_check_relocs (abfd, info, sec, relocs)
938 bfd *abfd;
939 struct bfd_link_info *info;
940 asection *sec;
941 const Elf_Internal_Rela *relocs;
942{
943 Elf_Internal_Shdr *symtab_hdr;
944 struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
945 const Elf_Internal_Rela *rel;
946 const Elf_Internal_Rela *rel_end;
b34976b6 947
1049f94e 948 if (info->relocatable)
b34976b6
AM
949 return TRUE;
950
4e5ba5b7
DB
951 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
952 sym_hashes = elf_sym_hashes (abfd);
953 sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof(Elf32_External_Sym);
954 if (!elf_bad_symtab (abfd))
955 sym_hashes_end -= symtab_hdr->sh_info;
b34976b6 956
4e5ba5b7
DB
957 rel_end = relocs + sec->reloc_count;
958 for (rel = relocs; rel < rel_end; rel++)
959 {
960 struct elf_link_hash_entry *h;
961 unsigned long r_symndx;
b34976b6 962
4e5ba5b7
DB
963 r_symndx = ELF32_R_SYM (rel->r_info);
964 if (r_symndx < symtab_hdr->sh_info)
965 h = NULL;
966 else
967 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
b34976b6 968
4e5ba5b7
DB
969 switch (ELF32_R_TYPE (rel->r_info))
970 {
971 /* This relocation describes the C++ object vtable hierarchy.
972 Reconstruct it for later use during GC. */
973 case R_FRV_GNU_VTINHERIT:
974 if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
b34976b6 975 return FALSE;
4e5ba5b7 976 break;
b34976b6 977
4e5ba5b7
DB
978 /* This relocation describes which C++ vtable entries are actually
979 used. Record for later use during GC. */
980 case R_FRV_GNU_VTENTRY:
981 if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
b34976b6 982 return FALSE;
4e5ba5b7
DB
983 break;
984 }
985 }
b34976b6
AM
986
987 return TRUE;
4e5ba5b7
DB
988}
989
990\f
991/* Return the machine subcode from the ELF e_flags header. */
992
993static int
994elf32_frv_machine (abfd)
995 bfd *abfd;
996{
997 switch (elf_elfheader (abfd)->e_flags & EF_FRV_CPU_MASK)
998 {
999 default: break;
9c8ee639 1000 case EF_FRV_CPU_FR550: return bfd_mach_fr550;
4e5ba5b7
DB
1001 case EF_FRV_CPU_FR500: return bfd_mach_fr500;
1002 case EF_FRV_CPU_FR400: return bfd_mach_fr400;
1003 case EF_FRV_CPU_FR300: return bfd_mach_fr300;
1004 case EF_FRV_CPU_SIMPLE: return bfd_mach_frvsimple;
1005 case EF_FRV_CPU_TOMCAT: return bfd_mach_frvtomcat;
1006 }
1007
1008 return bfd_mach_frv;
1009}
1010
1011/* Set the right machine number for a FRV ELF file. */
1012
b34976b6 1013static bfd_boolean
4e5ba5b7
DB
1014elf32_frv_object_p (abfd)
1015 bfd *abfd;
1016{
1017 bfd_default_set_arch_mach (abfd, bfd_arch_frv, elf32_frv_machine (abfd));
b34976b6 1018 return TRUE;
4e5ba5b7
DB
1019}
1020\f
1021/* Function to set the ELF flag bits. */
1022
b34976b6 1023static bfd_boolean
4e5ba5b7
DB
1024frv_elf_set_private_flags (abfd, flags)
1025 bfd *abfd;
1026 flagword flags;
1027{
1028 elf_elfheader (abfd)->e_flags = flags;
b34976b6
AM
1029 elf_flags_init (abfd) = TRUE;
1030 return TRUE;
4e5ba5b7
DB
1031}
1032
1033/* Copy backend specific data from one object module to another. */
1034
b34976b6 1035static bfd_boolean
4e5ba5b7
DB
1036frv_elf_copy_private_bfd_data (ibfd, obfd)
1037 bfd *ibfd;
1038 bfd *obfd;
1039{
1040 if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
1041 || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
b34976b6 1042 return TRUE;
4e5ba5b7
DB
1043
1044 BFD_ASSERT (!elf_flags_init (obfd)
1045 || elf_elfheader (obfd)->e_flags == elf_elfheader (ibfd)->e_flags);
1046
1047 elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
b34976b6
AM
1048 elf_flags_init (obfd) = TRUE;
1049 return TRUE;
4e5ba5b7
DB
1050}
1051
1052/* Merge backend specific data from an object file to the output
1053 object file when linking. */
1054
b34976b6 1055static bfd_boolean
4e5ba5b7
DB
1056frv_elf_merge_private_bfd_data (ibfd, obfd)
1057 bfd *ibfd;
1058 bfd *obfd;
1059{
1060 flagword old_flags, old_partial;
1061 flagword new_flags, new_partial;
b34976b6 1062 bfd_boolean error = FALSE;
4e5ba5b7
DB
1063 char new_opt[80];
1064 char old_opt[80];
1065
1066 new_opt[0] = old_opt[0] = '\0';
1067 new_flags = elf_elfheader (ibfd)->e_flags;
1068 old_flags = elf_elfheader (obfd)->e_flags;
1069
1070#ifdef DEBUG
1071 (*_bfd_error_handler) ("old_flags = 0x%.8lx, new_flags = 0x%.8lx, init = %s, filename = %s",
1072 old_flags, new_flags, elf_flags_init (obfd) ? "yes" : "no",
1073 bfd_get_filename (ibfd));
1074#endif
1075
1076 if (!elf_flags_init (obfd)) /* First call, no flags set. */
1077 {
b34976b6 1078 elf_flags_init (obfd) = TRUE;
4e5ba5b7
DB
1079 old_flags = new_flags;
1080 }
1081
1082 else if (new_flags == old_flags) /* Compatible flags are ok. */
1083 ;
1084
1085 else /* Possibly incompatible flags. */
1086 {
1087 /* Warn if different # of gprs are used. Note, 0 means nothing is
1088 said about the size of gprs. */
1089 new_partial = (new_flags & EF_FRV_GPR_MASK);
1090 old_partial = (old_flags & EF_FRV_GPR_MASK);
1091 if (new_partial == old_partial)
1092 ;
1093
1094 else if (new_partial == 0)
1095 ;
1096
1097 else if (old_partial == 0)
1098 old_flags |= new_partial;
1099
1100 else
1101 {
1102 switch (new_partial)
1103 {
1104 default: strcat (new_opt, " -mgpr-??"); break;
1105 case EF_FRV_GPR_32: strcat (new_opt, " -mgpr-32"); break;
1106 case EF_FRV_GPR_64: strcat (new_opt, " -mgpr-64"); break;
1107 }
1108
1109 switch (old_partial)
1110 {
1111 default: strcat (old_opt, " -mgpr-??"); break;
1112 case EF_FRV_GPR_32: strcat (old_opt, " -mgpr-32"); break;
1113 case EF_FRV_GPR_64: strcat (old_opt, " -mgpr-64"); break;
1114 }
1115 }
1116
1117 /* Warn if different # of fprs are used. Note, 0 means nothing is
1118 said about the size of fprs. */
1119 new_partial = (new_flags & EF_FRV_FPR_MASK);
1120 old_partial = (old_flags & EF_FRV_FPR_MASK);
1121 if (new_partial == old_partial)
1122 ;
1123
1124 else if (new_partial == 0)
1125 ;
1126
1127 else if (old_partial == 0)
1128 old_flags |= new_partial;
1129
1130 else
1131 {
1132 switch (new_partial)
1133 {
1134 default: strcat (new_opt, " -mfpr-?"); break;
1135 case EF_FRV_FPR_32: strcat (new_opt, " -mfpr-32"); break;
1136 case EF_FRV_FPR_64: strcat (new_opt, " -mfpr-64"); break;
1137 case EF_FRV_FPR_NONE: strcat (new_opt, " -msoft-float"); break;
1138 }
1139
1140 switch (old_partial)
1141 {
1142 default: strcat (old_opt, " -mfpr-?"); break;
1143 case EF_FRV_FPR_32: strcat (old_opt, " -mfpr-32"); break;
1144 case EF_FRV_FPR_64: strcat (old_opt, " -mfpr-64"); break;
1145 case EF_FRV_FPR_NONE: strcat (old_opt, " -msoft-float"); break;
1146 }
1147 }
1148
1149 /* Warn if different dword support was used. Note, 0 means nothing is
1150 said about the dword support. */
1151 new_partial = (new_flags & EF_FRV_DWORD_MASK);
1152 old_partial = (old_flags & EF_FRV_DWORD_MASK);
1153 if (new_partial == old_partial)
1154 ;
1155
1156 else if (new_partial == 0)
1157 ;
1158
1159 else if (old_partial == 0)
1160 old_flags |= new_partial;
1161
1162 else
1163 {
1164 switch (new_partial)
1165 {
1166 default: strcat (new_opt, " -mdword-?"); break;
1167 case EF_FRV_DWORD_YES: strcat (new_opt, " -mdword"); break;
1168 case EF_FRV_DWORD_NO: strcat (new_opt, " -mno-dword"); break;
1169 }
1170
1171 switch (old_partial)
1172 {
1173 default: strcat (old_opt, " -mdword-?"); break;
1174 case EF_FRV_DWORD_YES: strcat (old_opt, " -mdword"); break;
1175 case EF_FRV_DWORD_NO: strcat (old_opt, " -mno-dword"); break;
1176 }
1177 }
1178
1179 /* Or in flags that accumulate (ie, if one module uses it, mark that the
1180 feature is used. */
1181 old_flags |= new_flags & (EF_FRV_DOUBLE
1182 | EF_FRV_MEDIA
1183 | EF_FRV_MULADD
1184 | EF_FRV_NON_PIC_RELOCS);
1185
1186 /* If any module was compiled without -G0, clear the G0 bit. */
1187 old_flags = ((old_flags & ~ EF_FRV_G0)
1188 | (old_flags & new_flags & EF_FRV_G0));
1189
1190 /* If any module was compiled without -mnopack, clear the mnopack bit. */
1191 old_flags = ((old_flags & ~ EF_FRV_NOPACK)
1192 | (old_flags & new_flags & EF_FRV_NOPACK));
1193
1194 /* We don't have to do anything if the pic flags are the same, or the new
1195 module(s) were compiled with -mlibrary-pic. */
1196 new_partial = (new_flags & EF_FRV_PIC_FLAGS);
1197 old_partial = (old_flags & EF_FRV_PIC_FLAGS);
1198 if ((new_partial == old_partial) || ((new_partial & EF_FRV_LIBPIC) != 0))
1199 ;
1200
1201 /* If the old module(s) were compiled with -mlibrary-pic, copy in the pic
1202 flags if any from the new module. */
1203 else if ((old_partial & EF_FRV_LIBPIC) != 0)
1204 old_flags = (old_flags & ~ EF_FRV_PIC_FLAGS) | new_partial;
1205
1206 /* If we have mixtures of -fpic and -fPIC, or in both bits. */
1207 else if (new_partial != 0 && old_partial != 0)
1208 old_flags |= new_partial;
1209
1210 /* One module was compiled for pic and the other was not, see if we have
1211 had any relocations that are not pic-safe. */
1212 else
1213 {
1214 if ((old_flags & EF_FRV_NON_PIC_RELOCS) == 0)
1215 old_flags |= new_partial;
1216 else
1217 {
1218 old_flags &= ~ EF_FRV_PIC_FLAGS;
1219#ifndef FRV_NO_PIC_ERROR
b34976b6 1220 error = TRUE;
4e5ba5b7
DB
1221 (*_bfd_error_handler)
1222 (_("%s: compiled with %s and linked with modules that use non-pic relocations"),
1223 bfd_get_filename (ibfd),
1224 (new_flags & EF_FRV_BIGPIC) ? "-fPIC" : "-fpic");
1225#endif
1226 }
1227 }
1228
1229 /* Warn if different cpu is used (allow a specific cpu to override
1230 the generic cpu). */
1231 new_partial = (new_flags & EF_FRV_CPU_MASK);
1232 old_partial = (old_flags & EF_FRV_CPU_MASK);
1233 if (new_partial == old_partial)
1234 ;
1235
1236 else if (new_partial == EF_FRV_CPU_GENERIC)
1237 ;
1238
1239 else if (old_partial == EF_FRV_CPU_GENERIC)
1240 old_flags = (old_flags & ~EF_FRV_CPU_MASK) | new_partial;
1241
1242 else
1243 {
1244 switch (new_partial)
1245 {
1246 default: strcat (new_opt, " -mcpu=?"); break;
1247 case EF_FRV_CPU_GENERIC: strcat (new_opt, " -mcpu=frv"); break;
1248 case EF_FRV_CPU_SIMPLE: strcat (new_opt, " -mcpu=simple"); break;
9c8ee639 1249 case EF_FRV_CPU_FR550: strcat (new_opt, " -mcpu=fr550"); break;
4e5ba5b7
DB
1250 case EF_FRV_CPU_FR500: strcat (new_opt, " -mcpu=fr500"); break;
1251 case EF_FRV_CPU_FR400: strcat (new_opt, " -mcpu=fr400"); break;
1252 case EF_FRV_CPU_FR300: strcat (new_opt, " -mcpu=fr300"); break;
1253 case EF_FRV_CPU_TOMCAT: strcat (new_opt, " -mcpu=tomcat"); break;
1254 }
1255
1256 switch (old_partial)
1257 {
1258 default: strcat (old_opt, " -mcpu=?"); break;
1259 case EF_FRV_CPU_GENERIC: strcat (old_opt, " -mcpu=frv"); break;
1260 case EF_FRV_CPU_SIMPLE: strcat (old_opt, " -mcpu=simple"); break;
9c8ee639 1261 case EF_FRV_CPU_FR550: strcat (old_opt, " -mcpu=fr550"); break;
4e5ba5b7
DB
1262 case EF_FRV_CPU_FR500: strcat (old_opt, " -mcpu=fr500"); break;
1263 case EF_FRV_CPU_FR400: strcat (old_opt, " -mcpu=fr400"); break;
1264 case EF_FRV_CPU_FR300: strcat (old_opt, " -mcpu=fr300"); break;
1265 case EF_FRV_CPU_TOMCAT: strcat (old_opt, " -mcpu=tomcat"); break;
1266 }
1267 }
b34976b6 1268
4e5ba5b7
DB
1269 /* Print out any mismatches from above. */
1270 if (new_opt[0])
1271 {
b34976b6 1272 error = TRUE;
4e5ba5b7
DB
1273 (*_bfd_error_handler)
1274 (_("%s: compiled with %s and linked with modules compiled with %s"),
1275 bfd_get_filename (ibfd), new_opt, old_opt);
1276 }
1277
1278 /* Warn about any other mismatches */
1279 new_partial = (new_flags & ~ EF_FRV_ALL_FLAGS);
1280 old_partial = (old_flags & ~ EF_FRV_ALL_FLAGS);
1281 if (new_partial != old_partial)
1282 {
1283 old_flags |= new_partial;
b34976b6 1284 error = TRUE;
4e5ba5b7
DB
1285 (*_bfd_error_handler)
1286 (_("%s: uses different unknown e_flags (0x%lx) fields than previous modules (0x%lx)"),
1287 bfd_get_filename (ibfd), (long)new_partial, (long)old_partial);
1288 }
1289 }
1290
1291 /* If the cpu is -mcpu=simple, then set the -mnopack bit. */
1292 if ((old_flags & EF_FRV_CPU_MASK) == EF_FRV_CPU_SIMPLE)
1293 old_flags |= EF_FRV_NOPACK;
1294
1295 /* Update the old flags now with changes made above. */
1296 old_partial = elf_elfheader (obfd)->e_flags & EF_FRV_CPU_MASK;
1297 elf_elfheader (obfd)->e_flags = old_flags;
1298 if (old_partial != (old_flags & EF_FRV_CPU_MASK))
1299 bfd_default_set_arch_mach (obfd, bfd_arch_frv, elf32_frv_machine (obfd));
1300
1301 if (error)
1302 bfd_set_error (bfd_error_bad_value);
1303
1304 return !error;
1305}
1306
1307\f
b34976b6 1308bfd_boolean
4e5ba5b7
DB
1309frv_elf_print_private_bfd_data (abfd, ptr)
1310 bfd *abfd;
1311 PTR ptr;
1312{
1313 FILE *file = (FILE *) ptr;
1314 flagword flags;
1315
1316 BFD_ASSERT (abfd != NULL && ptr != NULL);
1317
1318 /* Print normal ELF private data. */
1319 _bfd_elf_print_private_bfd_data (abfd, ptr);
1320
1321 flags = elf_elfheader (abfd)->e_flags;
1322 fprintf (file, _("private flags = 0x%lx:"), (long)flags);
1323
1324 switch (flags & EF_FRV_CPU_MASK)
1325 {
1326 default: break;
1327 case EF_FRV_CPU_SIMPLE: fprintf (file, " -mcpu=simple"); break;
9c8ee639 1328 case EF_FRV_CPU_FR550: fprintf (file, " -mcpu=fr550"); break;
4e5ba5b7
DB
1329 case EF_FRV_CPU_FR500: fprintf (file, " -mcpu=fr500"); break;
1330 case EF_FRV_CPU_FR400: fprintf (file, " -mcpu=fr400"); break;
1331 case EF_FRV_CPU_FR300: fprintf (file, " -mcpu=fr300"); break;
1332 case EF_FRV_CPU_TOMCAT: fprintf (file, " -mcpu=tomcat"); break;
1333 }
1334
1335 switch (flags & EF_FRV_GPR_MASK)
1336 {
1337 default: break;
1338 case EF_FRV_GPR_32: fprintf (file, " -mgpr-32"); break;
1339 case EF_FRV_GPR_64: fprintf (file, " -mgpr-64"); break;
1340 }
1341
1342 switch (flags & EF_FRV_FPR_MASK)
1343 {
1344 default: break;
1345 case EF_FRV_FPR_32: fprintf (file, " -mfpr-32"); break;
1346 case EF_FRV_FPR_64: fprintf (file, " -mfpr-64"); break;
1347 case EF_FRV_FPR_NONE: fprintf (file, " -msoft-float"); break;
1348 }
1349
1350 switch (flags & EF_FRV_DWORD_MASK)
1351 {
1352 default: break;
1353 case EF_FRV_DWORD_YES: fprintf (file, " -mdword"); break;
1354 case EF_FRV_DWORD_NO: fprintf (file, " -mno-dword"); break;
1355 }
1356
1357 if (flags & EF_FRV_DOUBLE)
1358 fprintf (file, " -mdouble");
1359
1360 if (flags & EF_FRV_MEDIA)
1361 fprintf (file, " -mmedia");
1362
1363 if (flags & EF_FRV_MULADD)
1364 fprintf (file, " -mmuladd");
1365
1366 if (flags & EF_FRV_PIC)
1367 fprintf (file, " -fpic");
1368
1369 if (flags & EF_FRV_BIGPIC)
1370 fprintf (file, " -fPIC");
1371
1372 if (flags & EF_FRV_NON_PIC_RELOCS)
1373 fprintf (file, " non-pic relocations");
1374
1375 if (flags & EF_FRV_G0)
1376 fprintf (file, " -G0");
1377
1378 fputc ('\n', file);
b34976b6 1379 return TRUE;
4e5ba5b7
DB
1380}
1381
1382\f
1383#define ELF_ARCH bfd_arch_frv
1384#define ELF_MACHINE_CODE EM_CYGNUS_FRV
1385#define ELF_MAXPAGESIZE 0x1000
1386
1387#define TARGET_BIG_SYM bfd_elf32_frv_vec
1388#define TARGET_BIG_NAME "elf32-frv"
1389
1390#define elf_info_to_howto_rel NULL
1391#define elf_info_to_howto frv_info_to_howto_rela
1392#define elf_backend_relocate_section elf32_frv_relocate_section
1393#define elf_backend_gc_mark_hook elf32_frv_gc_mark_hook
1394#define elf_backend_gc_sweep_hook elf32_frv_gc_sweep_hook
1395#define elf_backend_check_relocs elf32_frv_check_relocs
1396#define elf_backend_object_p elf32_frv_object_p
1397#define elf_backend_add_symbol_hook elf32_frv_add_symbol_hook
1398
1399#define elf_backend_can_gc_sections 1
de2d743e 1400#define elf_backend_rela_normal 1
4e5ba5b7
DB
1401
1402#define bfd_elf32_bfd_reloc_type_lookup frv_reloc_type_lookup
1403#define bfd_elf32_bfd_set_private_flags frv_elf_set_private_flags
1404#define bfd_elf32_bfd_copy_private_bfd_data frv_elf_copy_private_bfd_data
1405#define bfd_elf32_bfd_merge_private_bfd_data frv_elf_merge_private_bfd_data
1406#define bfd_elf32_bfd_print_private_bfd_data frv_elf_print_private_bfd_data
1407
1408#include "elf32-target.h"
This page took 0.163063 seconds and 4 git commands to generate.