]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - bfd/elf32-frv.c
Correct spelling of "relocatable".
[thirdparty/binutils-gdb.git] / bfd / elf32-frv.c
1 /* FRV-specific support for 32-bit ELF.
2 Copyright 2002, 2003 Free Software Foundation, Inc.
3
4 This file is part of BFD, the Binary File Descriptor library.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 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. */
27 static bfd_reloc_status_type elf32_frv_relocate_lo16
28 PARAMS ((bfd *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
29 static bfd_reloc_status_type elf32_frv_relocate_hi16
30 PARAMS ((bfd *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
31 static bfd_reloc_status_type elf32_frv_relocate_label24
32 PARAMS ((bfd *, asection *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
33 static bfd_reloc_status_type elf32_frv_relocate_gprel12
34 PARAMS ((struct bfd_link_info *, bfd *, asection *, Elf_Internal_Rela *,
35 bfd_byte *, bfd_vma));
36 static bfd_reloc_status_type elf32_frv_relocate_gprelu12
37 PARAMS ((struct bfd_link_info *, bfd *, asection *, Elf_Internal_Rela *,
38 bfd_byte *, bfd_vma));
39 static bfd_reloc_status_type elf32_frv_relocate_gprello
40 PARAMS ((struct bfd_link_info *, bfd *, asection *, Elf_Internal_Rela *,
41 bfd_byte *, bfd_vma));
42 static bfd_reloc_status_type elf32_frv_relocate_gprelhi
43 PARAMS ((struct bfd_link_info *, bfd *, asection *, Elf_Internal_Rela *,
44 bfd_byte *, bfd_vma));
45 static reloc_howto_type *frv_reloc_type_lookup
46 PARAMS ((bfd *, bfd_reloc_code_real_type));
47 static void frv_info_to_howto_rela
48 PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
49 static 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 **));
52 static 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 *));
55 static bfd_reloc_status_type frv_final_link_relocate
56 PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *,
57 Elf_Internal_Rela *, bfd_vma));
58 static bfd_boolean elf32_frv_gc_sweep_hook
59 PARAMS ((bfd *, struct bfd_link_info *, asection *, const
60 Elf_Internal_Rela *));
61 static asection * elf32_frv_gc_mark_hook
62 PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
63 struct elf_link_hash_entry *, Elf_Internal_Sym *));
64 static bfd_boolean elf32_frv_check_relocs
65 PARAMS ((bfd *, struct bfd_link_info *, asection *,
66 const Elf_Internal_Rela *));
67 static int elf32_frv_machine
68 PARAMS ((bfd *));
69 static bfd_boolean elf32_frv_object_p
70 PARAMS ((bfd *));
71 static bfd_boolean frv_elf_set_private_flags
72 PARAMS ((bfd *, flagword));
73 static bfd_boolean frv_elf_copy_private_bfd_data
74 PARAMS ((bfd *, bfd *));
75 static bfd_boolean frv_elf_merge_private_bfd_data
76 PARAMS ((bfd *, bfd *));
77 static bfd_boolean frv_elf_print_private_bfd_data
78 PARAMS ((bfd *, PTR));
79
80 static 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 */
87 FALSE, /* pc_relative */
88 0, /* bitpos */
89 complain_overflow_bitfield, /* complain_on_overflow */
90 bfd_elf_generic_reloc, /* special_function */
91 "R_FRV_NONE", /* name */
92 FALSE, /* partial_inplace */
93 0, /* src_mask */
94 0, /* dst_mask */
95 FALSE), /* pcrel_offset */
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 */
102 FALSE, /* pc_relative */
103 0, /* bitpos */
104 complain_overflow_bitfield, /* complain_on_overflow */
105 bfd_elf_generic_reloc, /* special_function */
106 "R_FRV_32", /* name */
107 FALSE, /* partial_inplace */
108 0xffffffff, /* src_mask */
109 0xffffffff, /* dst_mask */
110 FALSE), /* pcrel_offset */
111
112 /* A 16 bit pc-relative relocation. */
113 HOWTO (R_FRV_LABEL16, /* type */
114 0, /* rightshift */
115 2, /* size (0 = byte, 1 = short, 2 = long) */
116 16, /* bitsize */
117 TRUE, /* pc_relative */
118 0, /* bitpos */
119 complain_overflow_bitfield, /* complain_on_overflow */
120 bfd_elf_generic_reloc, /* special_function */
121 "R_FRV_LABEL16", /* name */
122 FALSE, /* partial_inplace */
123 0xffff, /* src_mask */
124 0xffff, /* dst_mask */
125 TRUE), /* pcrel_offset */
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 */
132 TRUE, /* pc_relative */
133 0, /* bitpos */
134 complain_overflow_bitfield, /* complain_on_overflow */
135 bfd_elf_generic_reloc, /* special_function */
136 "R_FRV_LABEL24", /* name */
137 FALSE, /* partial_inplace */
138 0x7e03ffff, /* src_mask */
139 0x7e03ffff, /* dst_mask */
140 TRUE), /* pcrel_offset */
141
142 HOWTO (R_FRV_LO16, /* type */
143 0, /* rightshift */
144 2, /* size (0 = byte, 1 = short, 2 = long) */
145 16, /* bitsize */
146 FALSE, /* pc_relative */
147 0, /* bitpos */
148 complain_overflow_dont, /* complain_on_overflow */
149 bfd_elf_generic_reloc, /* special_function */
150 "R_FRV_LO16", /* name */
151 FALSE, /* partial_inplace */
152 0xffff, /* src_mask */
153 0xffff, /* dst_mask */
154 FALSE), /* pcrel_offset */
155
156 HOWTO (R_FRV_HI16, /* type */
157 0, /* rightshift */
158 2, /* size (0 = byte, 1 = short, 2 = long) */
159 16, /* bitsize */
160 FALSE, /* pc_relative */
161 0, /* bitpos */
162 complain_overflow_dont, /* complain_on_overflow */
163 bfd_elf_generic_reloc, /* special_function */
164 "R_FRV_HI16", /* name */
165 FALSE, /* partial_inplace */
166 0xffff, /* src_mask */
167 0xffff, /* dst_mask */
168 FALSE), /* pcrel_offset */
169
170 HOWTO (R_FRV_GPREL12, /* type */
171 0, /* rightshift */
172 2, /* size (0 = byte, 1 = short, 2 = long) */
173 12, /* bitsize */
174 FALSE, /* pc_relative */
175 0, /* bitpos */
176 complain_overflow_dont, /* complain_on_overflow */
177 bfd_elf_generic_reloc, /* special_function */
178 "R_FRV_GPREL12", /* name */
179 FALSE, /* partial_inplace */
180 0xfff, /* src_mask */
181 0xfff, /* dst_mask */
182 FALSE), /* pcrel_offset */
183
184 HOWTO (R_FRV_GPRELU12, /* type */
185 0, /* rightshift */
186 2, /* size (0 = byte, 1 = short, 2 = long) */
187 12, /* bitsize */
188 FALSE, /* pc_relative */
189 0, /* bitpos */
190 complain_overflow_dont, /* complain_on_overflow */
191 bfd_elf_generic_reloc, /* special_function */
192 "R_FRV_GPRELU12", /* name */
193 FALSE, /* partial_inplace */
194 0xfff, /* src_mask */
195 0x3f03f, /* dst_mask */
196 FALSE), /* pcrel_offset */
197
198 HOWTO (R_FRV_GPREL32, /* type */
199 0, /* rightshift */
200 2, /* size (0 = byte, 1 = short, 2 = long) */
201 32, /* bitsize */
202 FALSE, /* pc_relative */
203 0, /* bitpos */
204 complain_overflow_dont, /* complain_on_overflow */
205 bfd_elf_generic_reloc, /* special_function */
206 "R_FRV_GPREL32", /* name */
207 FALSE, /* partial_inplace */
208 0xffffffff, /* src_mask */
209 0xffffffff, /* dst_mask */
210 FALSE), /* pcrel_offset */
211
212 HOWTO (R_FRV_GPRELHI, /* type */
213 0, /* rightshift */
214 2, /* size (0 = byte, 1 = short, 2 = long) */
215 16, /* bitsize */
216 FALSE, /* pc_relative */
217 0, /* bitpos */
218 complain_overflow_dont, /* complain_on_overflow */
219 bfd_elf_generic_reloc, /* special_function */
220 "R_FRV_GPRELHI", /* name */
221 FALSE, /* partial_inplace */
222 0xffff, /* src_mask */
223 0xffff, /* dst_mask */
224 FALSE), /* pcrel_offset */
225
226 HOWTO (R_FRV_GPRELLO, /* type */
227 0, /* rightshift */
228 2, /* size (0 = byte, 1 = short, 2 = long) */
229 16, /* bitsize */
230 FALSE, /* pc_relative */
231 0, /* bitpos */
232 complain_overflow_dont, /* complain_on_overflow */
233 bfd_elf_generic_reloc, /* special_function */
234 "R_FRV_GPRELLO", /* name */
235 FALSE, /* partial_inplace */
236 0xffff, /* src_mask */
237 0xffff, /* dst_mask */
238 FALSE), /* pcrel_offset */
239 };
240
241 /* GNU extension to record C++ vtable hierarchy. */
242 static 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 */
247 FALSE, /* pc_relative */
248 0, /* bitpos */
249 complain_overflow_dont, /* complain_on_overflow */
250 NULL, /* special_function */
251 "R_FRV_GNU_VTINHERIT", /* name */
252 FALSE, /* partial_inplace */
253 0, /* src_mask */
254 0, /* dst_mask */
255 FALSE); /* pcrel_offset */
256
257 /* GNU extension to record C++ vtable member usage. */
258 static 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 */
263 FALSE, /* pc_relative */
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 */
268 FALSE, /* partial_inplace */
269 0, /* src_mask */
270 0, /* dst_mask */
271 FALSE); /* pcrel_offset */
272 \f
273 /* Map BFD reloc types to FRV ELF reloc types. */
274 #if 0
275 struct frv_reloc_map
276 {
277 unsigned int bfd_reloc_val;
278 unsigned int frv_reloc_val;
279 };
280
281 static 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
301 static bfd_reloc_status_type
302 elf32_frv_relocate_gprel12 (info, input_bfd, input_section, relocation,
303 contents, value)
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
315 h = bfd_link_hash_lookup (info->hash, "_gp", FALSE, FALSE, TRUE);
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
340 static bfd_reloc_status_type
341 elf32_frv_relocate_gprelu12 (info, input_bfd, input_section, relocation,
342 contents, value)
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
355 h = bfd_link_hash_lookup (info->hash, "_gp", FALSE, FALSE, TRUE);
356
357 gp = (h->u.def.value
358 + h->u.def.section->output_section->vma
359 + h->u.def.section->output_offset);
360
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
382 static bfd_reloc_status_type
383 elf32_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 }
405 static bfd_reloc_status_type
406 elf32_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
430 static bfd_reloc_status_type
431 elf32_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
444 0 000000 0001111 000000000000000000
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
473 static bfd_reloc_status_type
474 elf32_frv_relocate_gprelhi (info, input_bfd, input_section, relocation,
475 contents, value)
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
487 h = bfd_link_hash_lookup (info->hash, "_gp", FALSE, FALSE, TRUE);
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
508 static bfd_reloc_status_type
509 elf32_frv_relocate_gprello (info, input_bfd, input_section, relocation,
510 contents, value)
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
522 h = bfd_link_hash_lookup (info->hash, "_gp", FALSE, FALSE, TRUE);
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
544 static reloc_howto_type *
545 frv_reloc_type_lookup (abfd, code)
546 bfd *abfd ATTRIBUTE_UNUSED;
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];
556
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
600 static void
601 frv_info_to_howto_rela (abfd, cache_ptr, dst)
602 bfd *abfd ATTRIBUTE_UNUSED;
603 arelent *cache_ptr;
604 Elf_Internal_Rela *dst;
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
628 static bfd_reloc_status_type
629 frv_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;
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.
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
654 necessary, and (if using Rela relocs and generating a relocatable
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
668 When generating relocatable output, this function must handle
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
674 static bfd_boolean
675 elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
676 contents, relocs, local_syms, local_sections)
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;
685 {
686 Elf_Internal_Shdr *symtab_hdr;
687 struct elf_link_hash_entry **sym_hashes;
688 Elf_Internal_Rela *rel;
689 Elf_Internal_Rela *relend;
690
691 if (info->relocatable)
692 return TRUE;
693
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 {
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
710 r_type = ELF32_R_TYPE (rel->r_info);
711
712 if ( r_type == R_FRV_GNU_VTINHERIT
713 || r_type == R_FRV_GNU_VTENTRY)
714 continue;
715
716 /* This is a final link. */
717 r_symndx = ELF32_R_SYM (rel->r_info);
718 howto = elf32_frv_howto_table + ELF32_R_TYPE (rel->r_info);
719 h = NULL;
720 sym = NULL;
721 sec = NULL;
722
723 if (r_symndx < symtab_hdr->sh_info)
724 {
725 sym = local_syms + r_symndx;
726 sec = local_sections [r_symndx];
727 relocation = (sec->output_section->vma
728 + sec->output_offset
729 + sym->st_value);
730
731 name = bfd_elf_string_from_elf_section
732 (input_bfd, symtab_hdr->sh_link, sym->st_name);
733 name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
734 }
735 else
736 {
737 h = sym_hashes [r_symndx - symtab_hdr->sh_info];
738
739 while (h->root.type == bfd_link_hash_indirect
740 || h->root.type == bfd_link_hash_warning)
741 h = (struct elf_link_hash_entry *) h->root.u.i.link;
742
743 name = h->root.root.string;
744
745 if (h->root.type == bfd_link_hash_defined
746 || h->root.type == bfd_link_hash_defweak)
747 {
748 sec = h->root.u.def.section;
749 relocation = (h->root.u.def.value
750 + sec->output_section->vma
751 + sec->output_offset);
752 }
753 else if (h->root.type == bfd_link_hash_undefweak)
754 {
755 relocation = 0;
756 }
757 else
758 {
759 if (! ((*info->callbacks->undefined_symbol)
760 (info, h->root.root.string, input_bfd,
761 input_section, rel->r_offset, TRUE)))
762 return FALSE;
763 relocation = 0;
764 }
765 }
766
767 if (r_type == R_FRV_HI16)
768 r = elf32_frv_relocate_hi16 (input_bfd, rel, contents, relocation);
769
770 else if (r_type == R_FRV_LO16)
771 r = elf32_frv_relocate_lo16 (input_bfd, rel, contents, relocation);
772
773 else if (r_type == R_FRV_LABEL24)
774 r = elf32_frv_relocate_label24 (input_bfd, input_section, rel,
775 contents, relocation);
776
777 else if (r_type == R_FRV_GPREL12)
778 r = elf32_frv_relocate_gprel12 (info, input_bfd, input_section, rel,
779 contents, relocation);
780
781 else if (r_type == R_FRV_GPRELU12)
782 r = elf32_frv_relocate_gprelu12 (info, input_bfd, input_section, rel,
783 contents, relocation);
784
785 else if (r_type == R_FRV_GPRELLO)
786 r = elf32_frv_relocate_gprello (info, input_bfd, input_section, rel,
787 contents, relocation);
788
789 else if (r_type == R_FRV_GPRELHI)
790 r = elf32_frv_relocate_gprelhi (info, input_bfd, input_section, rel,
791 contents, relocation);
792
793 else
794 r = frv_final_link_relocate (howto, input_bfd, input_section, contents,
795 rel, relocation);
796
797 if (r != bfd_reloc_ok)
798 {
799 const char * msg = (const char *) NULL;
800
801 switch (r)
802 {
803 case bfd_reloc_overflow:
804 r = info->callbacks->reloc_overflow
805 (info, name, howto->name, (bfd_vma) 0,
806 input_bfd, input_section, rel->r_offset);
807 break;
808
809 case bfd_reloc_undefined:
810 r = info->callbacks->undefined_symbol
811 (info, name, input_bfd, input_section, rel->r_offset, TRUE);
812 break;
813
814 case bfd_reloc_outofrange:
815 msg = _("internal error: out of range error");
816 break;
817
818 case bfd_reloc_notsupported:
819 msg = _("internal error: unsupported relocation error");
820 break;
821
822 case bfd_reloc_dangerous:
823 msg = _("internal error: dangerous relocation");
824 break;
825
826 default:
827 msg = _("internal error: unknown error");
828 break;
829 }
830
831 if (msg)
832 r = info->callbacks->warning
833 (info, msg, name, input_bfd, input_section, rel->r_offset);
834
835 if (! r)
836 return FALSE;
837 }
838 }
839
840 return TRUE;
841 }
842 \f
843 /* Return the section that should be marked against GC for a given
844 relocation. */
845
846 static asection *
847 elf32_frv_gc_mark_hook (sec, info, rel, h, sym)
848 asection *sec;
849 struct bfd_link_info *info ATTRIBUTE_UNUSED;
850 Elf_Internal_Rela *rel;
851 struct elf_link_hash_entry *h;
852 Elf_Internal_Sym *sym;
853 {
854 if (h != NULL)
855 {
856 switch (ELF32_R_TYPE (rel->r_info))
857 {
858 case R_FRV_GNU_VTINHERIT:
859 case R_FRV_GNU_VTENTRY:
860 break;
861
862 default:
863 switch (h->root.type)
864 {
865 default:
866 break;
867
868 case bfd_link_hash_defined:
869 case bfd_link_hash_defweak:
870 return h->root.u.def.section;
871
872 case bfd_link_hash_common:
873 return h->root.u.c.p->section;
874 }
875 }
876 }
877 else
878 return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
879
880 return NULL;
881 }
882
883 /* Update the got entry reference counts for the section being removed. */
884
885 static bfd_boolean
886 elf32_frv_gc_sweep_hook (abfd, info, sec, relocs)
887 bfd *abfd ATTRIBUTE_UNUSED;
888 struct bfd_link_info *info ATTRIBUTE_UNUSED;
889 asection *sec ATTRIBUTE_UNUSED;
890 const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
891 {
892 return TRUE;
893 }
894
895 \f
896 /* Hook called by the linker routine which adds symbols from an object
897 file. We use it to put .comm items in .scomm, and not .comm. */
898
899 static bfd_boolean
900 elf32_frv_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
901 bfd *abfd;
902 struct bfd_link_info *info;
903 const Elf_Internal_Sym *sym;
904 const char **namep ATTRIBUTE_UNUSED;
905 flagword *flagsp ATTRIBUTE_UNUSED;
906 asection **secp;
907 bfd_vma *valp;
908 {
909 if (sym->st_shndx == SHN_COMMON
910 && !info->relocatable
911 && (int)sym->st_size <= (int)bfd_get_gp_size (abfd))
912 {
913 /* Common symbols less than or equal to -G nn bytes are
914 automatically put into .sbss. */
915
916 asection *scomm = bfd_get_section_by_name (abfd, ".scommon");
917
918 if (scomm == NULL)
919 {
920 scomm = bfd_make_section (abfd, ".scommon");
921 if (scomm == NULL
922 || !bfd_set_section_flags (abfd, scomm, (SEC_ALLOC
923 | SEC_IS_COMMON
924 | SEC_LINKER_CREATED)))
925 return FALSE;
926 }
927
928 *secp = scomm;
929 *valp = sym->st_size;
930 }
931
932 return TRUE;
933 }
934 /* Look through the relocs for a section during the first phase.
935 Since we don't do .gots or .plts, we just need to consider the
936 virtual table relocs for gc. */
937
938 static bfd_boolean
939 elf32_frv_check_relocs (abfd, info, sec, relocs)
940 bfd *abfd;
941 struct bfd_link_info *info;
942 asection *sec;
943 const Elf_Internal_Rela *relocs;
944 {
945 Elf_Internal_Shdr *symtab_hdr;
946 struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
947 const Elf_Internal_Rela *rel;
948 const Elf_Internal_Rela *rel_end;
949
950 if (info->relocatable)
951 return TRUE;
952
953 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
954 sym_hashes = elf_sym_hashes (abfd);
955 sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof(Elf32_External_Sym);
956 if (!elf_bad_symtab (abfd))
957 sym_hashes_end -= symtab_hdr->sh_info;
958
959 rel_end = relocs + sec->reloc_count;
960 for (rel = relocs; rel < rel_end; rel++)
961 {
962 struct elf_link_hash_entry *h;
963 unsigned long r_symndx;
964
965 r_symndx = ELF32_R_SYM (rel->r_info);
966 if (r_symndx < symtab_hdr->sh_info)
967 h = NULL;
968 else
969 h = sym_hashes[r_symndx - symtab_hdr->sh_info];
970
971 switch (ELF32_R_TYPE (rel->r_info))
972 {
973 /* This relocation describes the C++ object vtable hierarchy.
974 Reconstruct it for later use during GC. */
975 case R_FRV_GNU_VTINHERIT:
976 if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
977 return FALSE;
978 break;
979
980 /* This relocation describes which C++ vtable entries are actually
981 used. Record for later use during GC. */
982 case R_FRV_GNU_VTENTRY:
983 if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
984 return FALSE;
985 break;
986 }
987 }
988
989 return TRUE;
990 }
991
992 \f
993 /* Return the machine subcode from the ELF e_flags header. */
994
995 static int
996 elf32_frv_machine (abfd)
997 bfd *abfd;
998 {
999 switch (elf_elfheader (abfd)->e_flags & EF_FRV_CPU_MASK)
1000 {
1001 default: break;
1002 case EF_FRV_CPU_FR500: return bfd_mach_fr500;
1003 case EF_FRV_CPU_FR400: return bfd_mach_fr400;
1004 case EF_FRV_CPU_FR300: return bfd_mach_fr300;
1005 case EF_FRV_CPU_SIMPLE: return bfd_mach_frvsimple;
1006 case EF_FRV_CPU_TOMCAT: return bfd_mach_frvtomcat;
1007 }
1008
1009 return bfd_mach_frv;
1010 }
1011
1012 /* Set the right machine number for a FRV ELF file. */
1013
1014 static bfd_boolean
1015 elf32_frv_object_p (abfd)
1016 bfd *abfd;
1017 {
1018 bfd_default_set_arch_mach (abfd, bfd_arch_frv, elf32_frv_machine (abfd));
1019 return TRUE;
1020 }
1021 \f
1022 /* Function to set the ELF flag bits. */
1023
1024 static bfd_boolean
1025 frv_elf_set_private_flags (abfd, flags)
1026 bfd *abfd;
1027 flagword flags;
1028 {
1029 elf_elfheader (abfd)->e_flags = flags;
1030 elf_flags_init (abfd) = TRUE;
1031 return TRUE;
1032 }
1033
1034 /* Copy backend specific data from one object module to another. */
1035
1036 static bfd_boolean
1037 frv_elf_copy_private_bfd_data (ibfd, obfd)
1038 bfd *ibfd;
1039 bfd *obfd;
1040 {
1041 if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
1042 || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
1043 return TRUE;
1044
1045 BFD_ASSERT (!elf_flags_init (obfd)
1046 || elf_elfheader (obfd)->e_flags == elf_elfheader (ibfd)->e_flags);
1047
1048 elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
1049 elf_flags_init (obfd) = TRUE;
1050 return TRUE;
1051 }
1052
1053 /* Merge backend specific data from an object file to the output
1054 object file when linking. */
1055
1056 static bfd_boolean
1057 frv_elf_merge_private_bfd_data (ibfd, obfd)
1058 bfd *ibfd;
1059 bfd *obfd;
1060 {
1061 flagword old_flags, old_partial;
1062 flagword new_flags, new_partial;
1063 bfd_boolean error = FALSE;
1064 char new_opt[80];
1065 char old_opt[80];
1066
1067 new_opt[0] = old_opt[0] = '\0';
1068 new_flags = elf_elfheader (ibfd)->e_flags;
1069 old_flags = elf_elfheader (obfd)->e_flags;
1070
1071 #ifdef DEBUG
1072 (*_bfd_error_handler) ("old_flags = 0x%.8lx, new_flags = 0x%.8lx, init = %s, filename = %s",
1073 old_flags, new_flags, elf_flags_init (obfd) ? "yes" : "no",
1074 bfd_get_filename (ibfd));
1075 #endif
1076
1077 if (!elf_flags_init (obfd)) /* First call, no flags set. */
1078 {
1079 elf_flags_init (obfd) = TRUE;
1080 old_flags = new_flags;
1081 }
1082
1083 else if (new_flags == old_flags) /* Compatible flags are ok. */
1084 ;
1085
1086 else /* Possibly incompatible flags. */
1087 {
1088 /* Warn if different # of gprs are used. Note, 0 means nothing is
1089 said about the size of gprs. */
1090 new_partial = (new_flags & EF_FRV_GPR_MASK);
1091 old_partial = (old_flags & EF_FRV_GPR_MASK);
1092 if (new_partial == old_partial)
1093 ;
1094
1095 else if (new_partial == 0)
1096 ;
1097
1098 else if (old_partial == 0)
1099 old_flags |= new_partial;
1100
1101 else
1102 {
1103 switch (new_partial)
1104 {
1105 default: strcat (new_opt, " -mgpr-??"); break;
1106 case EF_FRV_GPR_32: strcat (new_opt, " -mgpr-32"); break;
1107 case EF_FRV_GPR_64: strcat (new_opt, " -mgpr-64"); break;
1108 }
1109
1110 switch (old_partial)
1111 {
1112 default: strcat (old_opt, " -mgpr-??"); break;
1113 case EF_FRV_GPR_32: strcat (old_opt, " -mgpr-32"); break;
1114 case EF_FRV_GPR_64: strcat (old_opt, " -mgpr-64"); break;
1115 }
1116 }
1117
1118 /* Warn if different # of fprs are used. Note, 0 means nothing is
1119 said about the size of fprs. */
1120 new_partial = (new_flags & EF_FRV_FPR_MASK);
1121 old_partial = (old_flags & EF_FRV_FPR_MASK);
1122 if (new_partial == old_partial)
1123 ;
1124
1125 else if (new_partial == 0)
1126 ;
1127
1128 else if (old_partial == 0)
1129 old_flags |= new_partial;
1130
1131 else
1132 {
1133 switch (new_partial)
1134 {
1135 default: strcat (new_opt, " -mfpr-?"); break;
1136 case EF_FRV_FPR_32: strcat (new_opt, " -mfpr-32"); break;
1137 case EF_FRV_FPR_64: strcat (new_opt, " -mfpr-64"); break;
1138 case EF_FRV_FPR_NONE: strcat (new_opt, " -msoft-float"); break;
1139 }
1140
1141 switch (old_partial)
1142 {
1143 default: strcat (old_opt, " -mfpr-?"); break;
1144 case EF_FRV_FPR_32: strcat (old_opt, " -mfpr-32"); break;
1145 case EF_FRV_FPR_64: strcat (old_opt, " -mfpr-64"); break;
1146 case EF_FRV_FPR_NONE: strcat (old_opt, " -msoft-float"); break;
1147 }
1148 }
1149
1150 /* Warn if different dword support was used. Note, 0 means nothing is
1151 said about the dword support. */
1152 new_partial = (new_flags & EF_FRV_DWORD_MASK);
1153 old_partial = (old_flags & EF_FRV_DWORD_MASK);
1154 if (new_partial == old_partial)
1155 ;
1156
1157 else if (new_partial == 0)
1158 ;
1159
1160 else if (old_partial == 0)
1161 old_flags |= new_partial;
1162
1163 else
1164 {
1165 switch (new_partial)
1166 {
1167 default: strcat (new_opt, " -mdword-?"); break;
1168 case EF_FRV_DWORD_YES: strcat (new_opt, " -mdword"); break;
1169 case EF_FRV_DWORD_NO: strcat (new_opt, " -mno-dword"); break;
1170 }
1171
1172 switch (old_partial)
1173 {
1174 default: strcat (old_opt, " -mdword-?"); break;
1175 case EF_FRV_DWORD_YES: strcat (old_opt, " -mdword"); break;
1176 case EF_FRV_DWORD_NO: strcat (old_opt, " -mno-dword"); break;
1177 }
1178 }
1179
1180 /* Or in flags that accumulate (ie, if one module uses it, mark that the
1181 feature is used. */
1182 old_flags |= new_flags & (EF_FRV_DOUBLE
1183 | EF_FRV_MEDIA
1184 | EF_FRV_MULADD
1185 | EF_FRV_NON_PIC_RELOCS);
1186
1187 /* If any module was compiled without -G0, clear the G0 bit. */
1188 old_flags = ((old_flags & ~ EF_FRV_G0)
1189 | (old_flags & new_flags & EF_FRV_G0));
1190
1191 /* If any module was compiled without -mnopack, clear the mnopack bit. */
1192 old_flags = ((old_flags & ~ EF_FRV_NOPACK)
1193 | (old_flags & new_flags & EF_FRV_NOPACK));
1194
1195 /* We don't have to do anything if the pic flags are the same, or the new
1196 module(s) were compiled with -mlibrary-pic. */
1197 new_partial = (new_flags & EF_FRV_PIC_FLAGS);
1198 old_partial = (old_flags & EF_FRV_PIC_FLAGS);
1199 if ((new_partial == old_partial) || ((new_partial & EF_FRV_LIBPIC) != 0))
1200 ;
1201
1202 /* If the old module(s) were compiled with -mlibrary-pic, copy in the pic
1203 flags if any from the new module. */
1204 else if ((old_partial & EF_FRV_LIBPIC) != 0)
1205 old_flags = (old_flags & ~ EF_FRV_PIC_FLAGS) | new_partial;
1206
1207 /* If we have mixtures of -fpic and -fPIC, or in both bits. */
1208 else if (new_partial != 0 && old_partial != 0)
1209 old_flags |= new_partial;
1210
1211 /* One module was compiled for pic and the other was not, see if we have
1212 had any relocations that are not pic-safe. */
1213 else
1214 {
1215 if ((old_flags & EF_FRV_NON_PIC_RELOCS) == 0)
1216 old_flags |= new_partial;
1217 else
1218 {
1219 old_flags &= ~ EF_FRV_PIC_FLAGS;
1220 #ifndef FRV_NO_PIC_ERROR
1221 error = TRUE;
1222 (*_bfd_error_handler)
1223 (_("%s: compiled with %s and linked with modules that use non-pic relocations"),
1224 bfd_get_filename (ibfd),
1225 (new_flags & EF_FRV_BIGPIC) ? "-fPIC" : "-fpic");
1226 #endif
1227 }
1228 }
1229
1230 /* Warn if different cpu is used (allow a specific cpu to override
1231 the generic cpu). */
1232 new_partial = (new_flags & EF_FRV_CPU_MASK);
1233 old_partial = (old_flags & EF_FRV_CPU_MASK);
1234 if (new_partial == old_partial)
1235 ;
1236
1237 else if (new_partial == EF_FRV_CPU_GENERIC)
1238 ;
1239
1240 else if (old_partial == EF_FRV_CPU_GENERIC)
1241 old_flags = (old_flags & ~EF_FRV_CPU_MASK) | new_partial;
1242
1243 else
1244 {
1245 switch (new_partial)
1246 {
1247 default: strcat (new_opt, " -mcpu=?"); break;
1248 case EF_FRV_CPU_GENERIC: strcat (new_opt, " -mcpu=frv"); break;
1249 case EF_FRV_CPU_SIMPLE: strcat (new_opt, " -mcpu=simple"); break;
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;
1261 case EF_FRV_CPU_FR500: strcat (old_opt, " -mcpu=fr500"); break;
1262 case EF_FRV_CPU_FR400: strcat (old_opt, " -mcpu=fr400"); break;
1263 case EF_FRV_CPU_FR300: strcat (old_opt, " -mcpu=fr300"); break;
1264 case EF_FRV_CPU_TOMCAT: strcat (old_opt, " -mcpu=tomcat"); break;
1265 }
1266 }
1267
1268 /* Print out any mismatches from above. */
1269 if (new_opt[0])
1270 {
1271 error = TRUE;
1272 (*_bfd_error_handler)
1273 (_("%s: compiled with %s and linked with modules compiled with %s"),
1274 bfd_get_filename (ibfd), new_opt, old_opt);
1275 }
1276
1277 /* Warn about any other mismatches */
1278 new_partial = (new_flags & ~ EF_FRV_ALL_FLAGS);
1279 old_partial = (old_flags & ~ EF_FRV_ALL_FLAGS);
1280 if (new_partial != old_partial)
1281 {
1282 old_flags |= new_partial;
1283 error = TRUE;
1284 (*_bfd_error_handler)
1285 (_("%s: uses different unknown e_flags (0x%lx) fields than previous modules (0x%lx)"),
1286 bfd_get_filename (ibfd), (long)new_partial, (long)old_partial);
1287 }
1288 }
1289
1290 /* If the cpu is -mcpu=simple, then set the -mnopack bit. */
1291 if ((old_flags & EF_FRV_CPU_MASK) == EF_FRV_CPU_SIMPLE)
1292 old_flags |= EF_FRV_NOPACK;
1293
1294 /* Update the old flags now with changes made above. */
1295 old_partial = elf_elfheader (obfd)->e_flags & EF_FRV_CPU_MASK;
1296 elf_elfheader (obfd)->e_flags = old_flags;
1297 if (old_partial != (old_flags & EF_FRV_CPU_MASK))
1298 bfd_default_set_arch_mach (obfd, bfd_arch_frv, elf32_frv_machine (obfd));
1299
1300 if (error)
1301 bfd_set_error (bfd_error_bad_value);
1302
1303 return !error;
1304 }
1305
1306 \f
1307 bfd_boolean
1308 frv_elf_print_private_bfd_data (abfd, ptr)
1309 bfd *abfd;
1310 PTR ptr;
1311 {
1312 FILE *file = (FILE *) ptr;
1313 flagword flags;
1314
1315 BFD_ASSERT (abfd != NULL && ptr != NULL);
1316
1317 /* Print normal ELF private data. */
1318 _bfd_elf_print_private_bfd_data (abfd, ptr);
1319
1320 flags = elf_elfheader (abfd)->e_flags;
1321 fprintf (file, _("private flags = 0x%lx:"), (long)flags);
1322
1323 switch (flags & EF_FRV_CPU_MASK)
1324 {
1325 default: break;
1326 case EF_FRV_CPU_SIMPLE: fprintf (file, " -mcpu=simple"); break;
1327 case EF_FRV_CPU_FR500: fprintf (file, " -mcpu=fr500"); break;
1328 case EF_FRV_CPU_FR400: fprintf (file, " -mcpu=fr400"); break;
1329 case EF_FRV_CPU_FR300: fprintf (file, " -mcpu=fr300"); break;
1330 case EF_FRV_CPU_TOMCAT: fprintf (file, " -mcpu=tomcat"); break;
1331 }
1332
1333 switch (flags & EF_FRV_GPR_MASK)
1334 {
1335 default: break;
1336 case EF_FRV_GPR_32: fprintf (file, " -mgpr-32"); break;
1337 case EF_FRV_GPR_64: fprintf (file, " -mgpr-64"); break;
1338 }
1339
1340 switch (flags & EF_FRV_FPR_MASK)
1341 {
1342 default: break;
1343 case EF_FRV_FPR_32: fprintf (file, " -mfpr-32"); break;
1344 case EF_FRV_FPR_64: fprintf (file, " -mfpr-64"); break;
1345 case EF_FRV_FPR_NONE: fprintf (file, " -msoft-float"); break;
1346 }
1347
1348 switch (flags & EF_FRV_DWORD_MASK)
1349 {
1350 default: break;
1351 case EF_FRV_DWORD_YES: fprintf (file, " -mdword"); break;
1352 case EF_FRV_DWORD_NO: fprintf (file, " -mno-dword"); break;
1353 }
1354
1355 if (flags & EF_FRV_DOUBLE)
1356 fprintf (file, " -mdouble");
1357
1358 if (flags & EF_FRV_MEDIA)
1359 fprintf (file, " -mmedia");
1360
1361 if (flags & EF_FRV_MULADD)
1362 fprintf (file, " -mmuladd");
1363
1364 if (flags & EF_FRV_PIC)
1365 fprintf (file, " -fpic");
1366
1367 if (flags & EF_FRV_BIGPIC)
1368 fprintf (file, " -fPIC");
1369
1370 if (flags & EF_FRV_NON_PIC_RELOCS)
1371 fprintf (file, " non-pic relocations");
1372
1373 if (flags & EF_FRV_G0)
1374 fprintf (file, " -G0");
1375
1376 fputc ('\n', file);
1377 return TRUE;
1378 }
1379
1380 \f
1381 #define ELF_ARCH bfd_arch_frv
1382 #define ELF_MACHINE_CODE EM_CYGNUS_FRV
1383 #define ELF_MAXPAGESIZE 0x1000
1384
1385 #define TARGET_BIG_SYM bfd_elf32_frv_vec
1386 #define TARGET_BIG_NAME "elf32-frv"
1387
1388 #define elf_info_to_howto_rel NULL
1389 #define elf_info_to_howto frv_info_to_howto_rela
1390 #define elf_backend_relocate_section elf32_frv_relocate_section
1391 #define elf_backend_gc_mark_hook elf32_frv_gc_mark_hook
1392 #define elf_backend_gc_sweep_hook elf32_frv_gc_sweep_hook
1393 #define elf_backend_check_relocs elf32_frv_check_relocs
1394 #define elf_backend_object_p elf32_frv_object_p
1395 #define elf_backend_add_symbol_hook elf32_frv_add_symbol_hook
1396
1397 #define elf_backend_can_gc_sections 1
1398 #define elf_backend_rela_normal 1
1399
1400 #define bfd_elf32_bfd_reloc_type_lookup frv_reloc_type_lookup
1401 #define bfd_elf32_bfd_set_private_flags frv_elf_set_private_flags
1402 #define bfd_elf32_bfd_copy_private_bfd_data frv_elf_copy_private_bfd_data
1403 #define bfd_elf32_bfd_merge_private_bfd_data frv_elf_merge_private_bfd_data
1404 #define bfd_elf32_bfd_print_private_bfd_data frv_elf_print_private_bfd_data
1405
1406 #include "elf32-target.h"