s/boolean/bfd_boolean/ s/true/TRUE/ s/false/FALSE/. Simplify
[external/binutils.git] / bfd / elf32-frv.c
1 /* FRV-specific support for 32-bit ELF.
2    Copyright 2002 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 relocateable
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 relocateable 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->relocateable)
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->relocateable
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->relocateable)
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"