]> Git Repo - binutils.git/blob - bfd/elf32-frv.c
2003-09-14 Andrew Cagney <[email protected]>
[binutils.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 = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
728
729           name = bfd_elf_string_from_elf_section
730             (input_bfd, symtab_hdr->sh_link, sym->st_name);
731           name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
732         }
733       else
734         {
735           h = sym_hashes [r_symndx - symtab_hdr->sh_info];
736
737           while (h->root.type == bfd_link_hash_indirect
738                  || h->root.type == bfd_link_hash_warning)
739             h = (struct elf_link_hash_entry *) h->root.u.i.link;
740
741           name = h->root.root.string;
742
743           if (h->root.type == bfd_link_hash_defined
744               || h->root.type == bfd_link_hash_defweak)
745             {
746               sec = h->root.u.def.section;
747               relocation = (h->root.u.def.value
748                             + sec->output_section->vma
749                             + sec->output_offset);
750             }
751           else if (h->root.type == bfd_link_hash_undefweak)
752             {
753               relocation = 0;
754             }
755           else
756             {
757               if (! ((*info->callbacks->undefined_symbol)
758                      (info, h->root.root.string, input_bfd,
759                       input_section, rel->r_offset, TRUE)))
760                 return FALSE;
761               relocation = 0;
762             }
763         }
764
765      if (r_type == R_FRV_HI16)
766        r = elf32_frv_relocate_hi16 (input_bfd, rel, contents, relocation);
767
768      else if (r_type == R_FRV_LO16)
769        r = elf32_frv_relocate_lo16 (input_bfd, rel, contents, relocation);
770
771      else if (r_type == R_FRV_LABEL24)
772        r = elf32_frv_relocate_label24 (input_bfd, input_section, rel,
773                                        contents, relocation);
774
775      else if (r_type == R_FRV_GPREL12)
776        r = elf32_frv_relocate_gprel12 (info, input_bfd, input_section, rel,
777                                        contents, relocation);
778
779      else if (r_type == R_FRV_GPRELU12)
780        r = elf32_frv_relocate_gprelu12 (info, input_bfd, input_section, rel,
781                                         contents, relocation);
782
783      else if (r_type == R_FRV_GPRELLO)
784        r = elf32_frv_relocate_gprello (info, input_bfd, input_section, rel,
785                                        contents, relocation);
786
787      else if (r_type == R_FRV_GPRELHI)
788        r = elf32_frv_relocate_gprelhi (info, input_bfd, input_section, rel,
789                                        contents, relocation);
790
791      else
792        r = frv_final_link_relocate (howto, input_bfd, input_section, contents,
793                                     rel, relocation);
794
795       if (r != bfd_reloc_ok)
796         {
797           const char * msg = (const char *) NULL;
798
799           switch (r)
800             {
801             case bfd_reloc_overflow:
802               r = info->callbacks->reloc_overflow
803                 (info, name, howto->name, (bfd_vma) 0,
804                  input_bfd, input_section, rel->r_offset);
805               break;
806
807             case bfd_reloc_undefined:
808               r = info->callbacks->undefined_symbol
809                 (info, name, input_bfd, input_section, rel->r_offset, TRUE);
810               break;
811
812             case bfd_reloc_outofrange:
813               msg = _("internal error: out of range error");
814               break;
815
816             case bfd_reloc_notsupported:
817               msg = _("internal error: unsupported relocation error");
818               break;
819
820             case bfd_reloc_dangerous:
821               msg = _("internal error: dangerous relocation");
822               break;
823
824             default:
825               msg = _("internal error: unknown error");
826               break;
827             }
828
829           if (msg)
830             r = info->callbacks->warning
831               (info, msg, name, input_bfd, input_section, rel->r_offset);
832
833           if (! r)
834             return FALSE;
835         }
836     }
837
838   return TRUE;
839 }
840 \f
841 /* Return the section that should be marked against GC for a given
842    relocation.  */
843
844 static asection *
845 elf32_frv_gc_mark_hook (sec, info, rel, h, sym)
846      asection *sec;
847      struct bfd_link_info *info ATTRIBUTE_UNUSED;
848      Elf_Internal_Rela *rel;
849      struct elf_link_hash_entry *h;
850      Elf_Internal_Sym *sym;
851 {
852   if (h != NULL)
853     {
854       switch (ELF32_R_TYPE (rel->r_info))
855         {
856         case R_FRV_GNU_VTINHERIT:
857         case R_FRV_GNU_VTENTRY:
858           break;
859
860         default:
861           switch (h->root.type)
862             {
863             default:
864               break;
865
866             case bfd_link_hash_defined:
867             case bfd_link_hash_defweak:
868               return h->root.u.def.section;
869
870             case bfd_link_hash_common:
871               return h->root.u.c.p->section;
872             }
873         }
874     }
875   else
876     return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
877
878   return NULL;
879 }
880
881 /* Update the got entry reference counts for the section being removed.  */
882
883 static bfd_boolean
884 elf32_frv_gc_sweep_hook (abfd, info, sec, relocs)
885      bfd *abfd ATTRIBUTE_UNUSED;
886      struct bfd_link_info *info ATTRIBUTE_UNUSED;
887      asection *sec ATTRIBUTE_UNUSED;
888      const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
889 {
890   return TRUE;
891 }
892
893 \f
894 /* Hook called by the linker routine which adds symbols from an object
895    file.  We use it to put .comm items in .scomm, and not .comm.  */
896
897 static bfd_boolean
898 elf32_frv_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
899      bfd *abfd;
900      struct bfd_link_info *info;
901      const Elf_Internal_Sym *sym;
902      const char **namep ATTRIBUTE_UNUSED;
903      flagword *flagsp ATTRIBUTE_UNUSED;
904      asection **secp;
905      bfd_vma *valp;
906 {
907   if (sym->st_shndx == SHN_COMMON
908       && !info->relocatable
909       && (int)sym->st_size <= (int)bfd_get_gp_size (abfd))
910     {
911       /* Common symbols less than or equal to -G nn bytes are
912          automatically put into .sbss.  */
913
914       asection *scomm = bfd_get_section_by_name (abfd, ".scommon");
915
916       if (scomm == NULL)
917         {
918           scomm = bfd_make_section (abfd, ".scommon");
919           if (scomm == NULL
920               || !bfd_set_section_flags (abfd, scomm, (SEC_ALLOC
921                                                        | SEC_IS_COMMON
922                                                        | SEC_LINKER_CREATED)))
923             return FALSE;
924         }
925
926       *secp = scomm;
927       *valp = sym->st_size;
928     }
929
930   return TRUE;
931 }
932 /* Look through the relocs for a section during the first phase.
933    Since we don't do .gots or .plts, we just need to consider the
934    virtual table relocs for gc.  */
935
936 static bfd_boolean
937 elf32_frv_check_relocs (abfd, info, sec, relocs)
938      bfd *abfd;
939      struct bfd_link_info *info;
940      asection *sec;
941      const Elf_Internal_Rela *relocs;
942 {
943   Elf_Internal_Shdr *symtab_hdr;
944   struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
945   const Elf_Internal_Rela *rel;
946   const Elf_Internal_Rela *rel_end;
947
948   if (info->relocatable)
949     return TRUE;
950
951   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
952   sym_hashes = elf_sym_hashes (abfd);
953   sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof(Elf32_External_Sym);
954   if (!elf_bad_symtab (abfd))
955     sym_hashes_end -= symtab_hdr->sh_info;
956
957   rel_end = relocs + sec->reloc_count;
958   for (rel = relocs; rel < rel_end; rel++)
959     {
960       struct elf_link_hash_entry *h;
961       unsigned long r_symndx;
962
963       r_symndx = ELF32_R_SYM (rel->r_info);
964       if (r_symndx < symtab_hdr->sh_info)
965         h = NULL;
966       else
967         h = sym_hashes[r_symndx - symtab_hdr->sh_info];
968
969       switch (ELF32_R_TYPE (rel->r_info))
970         {
971         /* This relocation describes the C++ object vtable hierarchy.
972            Reconstruct it for later use during GC.  */
973         case R_FRV_GNU_VTINHERIT:
974           if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
975             return FALSE;
976           break;
977
978         /* This relocation describes which C++ vtable entries are actually
979            used.  Record for later use during GC.  */
980         case R_FRV_GNU_VTENTRY:
981           if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend))
982             return FALSE;
983           break;
984         }
985     }
986
987   return TRUE;
988 }
989
990 \f
991 /* Return the machine subcode from the ELF e_flags header.  */
992
993 static int
994 elf32_frv_machine (abfd)
995      bfd *abfd;
996 {
997   switch (elf_elfheader (abfd)->e_flags & EF_FRV_CPU_MASK)
998     {
999     default:                break;
1000     case EF_FRV_CPU_FR500:  return bfd_mach_fr500;
1001     case EF_FRV_CPU_FR400:  return bfd_mach_fr400;
1002     case EF_FRV_CPU_FR300:  return bfd_mach_fr300;
1003     case EF_FRV_CPU_SIMPLE: return bfd_mach_frvsimple;
1004     case EF_FRV_CPU_TOMCAT: return bfd_mach_frvtomcat;
1005     }
1006
1007   return bfd_mach_frv;
1008 }
1009
1010 /* Set the right machine number for a FRV ELF file.  */
1011
1012 static bfd_boolean
1013 elf32_frv_object_p (abfd)
1014      bfd *abfd;
1015 {
1016   bfd_default_set_arch_mach (abfd, bfd_arch_frv, elf32_frv_machine (abfd));
1017   return TRUE;
1018 }
1019 \f
1020 /* Function to set the ELF flag bits.  */
1021
1022 static bfd_boolean
1023 frv_elf_set_private_flags (abfd, flags)
1024      bfd *abfd;
1025      flagword flags;
1026 {
1027   elf_elfheader (abfd)->e_flags = flags;
1028   elf_flags_init (abfd) = TRUE;
1029   return TRUE;
1030 }
1031
1032 /* Copy backend specific data from one object module to another.  */
1033
1034 static bfd_boolean
1035 frv_elf_copy_private_bfd_data (ibfd, obfd)
1036      bfd *ibfd;
1037      bfd *obfd;
1038 {
1039   if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
1040       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
1041     return TRUE;
1042
1043   BFD_ASSERT (!elf_flags_init (obfd)
1044               || elf_elfheader (obfd)->e_flags == elf_elfheader (ibfd)->e_flags);
1045
1046   elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
1047   elf_flags_init (obfd) = TRUE;
1048   return TRUE;
1049 }
1050
1051 /* Merge backend specific data from an object file to the output
1052    object file when linking.  */
1053
1054 static bfd_boolean
1055 frv_elf_merge_private_bfd_data (ibfd, obfd)
1056      bfd *ibfd;
1057      bfd *obfd;
1058 {
1059   flagword old_flags, old_partial;
1060   flagword new_flags, new_partial;
1061   bfd_boolean error = FALSE;
1062   char new_opt[80];
1063   char old_opt[80];
1064
1065   new_opt[0] = old_opt[0] = '\0';
1066   new_flags = elf_elfheader (ibfd)->e_flags;
1067   old_flags = elf_elfheader (obfd)->e_flags;
1068
1069 #ifdef DEBUG
1070   (*_bfd_error_handler) ("old_flags = 0x%.8lx, new_flags = 0x%.8lx, init = %s, filename = %s",
1071                          old_flags, new_flags, elf_flags_init (obfd) ? "yes" : "no",
1072                          bfd_get_filename (ibfd));
1073 #endif
1074
1075   if (!elf_flags_init (obfd))                   /* First call, no flags set.  */
1076     {
1077       elf_flags_init (obfd) = TRUE;
1078       old_flags = new_flags;
1079     }
1080
1081   else if (new_flags == old_flags)              /* Compatible flags are ok.  */
1082     ;
1083
1084   else                                          /* Possibly incompatible flags.  */
1085     {
1086       /* Warn if different # of gprs are used.  Note, 0 means nothing is
1087          said about the size of gprs.  */
1088       new_partial = (new_flags & EF_FRV_GPR_MASK);
1089       old_partial = (old_flags & EF_FRV_GPR_MASK);
1090       if (new_partial == old_partial)
1091         ;
1092
1093       else if (new_partial == 0)
1094         ;
1095
1096       else if (old_partial == 0)
1097         old_flags |= new_partial;
1098
1099       else
1100         {
1101           switch (new_partial)
1102             {
1103             default:            strcat (new_opt, " -mgpr-??"); break;
1104             case EF_FRV_GPR_32: strcat (new_opt, " -mgpr-32"); break;
1105             case EF_FRV_GPR_64: strcat (new_opt, " -mgpr-64"); break;
1106             }
1107
1108           switch (old_partial)
1109             {
1110             default:            strcat (old_opt, " -mgpr-??"); break;
1111             case EF_FRV_GPR_32: strcat (old_opt, " -mgpr-32"); break;
1112             case EF_FRV_GPR_64: strcat (old_opt, " -mgpr-64"); break;
1113             }
1114         }
1115
1116       /* Warn if different # of fprs are used.  Note, 0 means nothing is
1117          said about the size of fprs.  */
1118       new_partial = (new_flags & EF_FRV_FPR_MASK);
1119       old_partial = (old_flags & EF_FRV_FPR_MASK);
1120       if (new_partial == old_partial)
1121         ;
1122
1123       else if (new_partial == 0)
1124         ;
1125
1126       else if (old_partial == 0)
1127         old_flags |= new_partial;
1128
1129       else
1130         {
1131           switch (new_partial)
1132             {
1133             default:              strcat (new_opt, " -mfpr-?");      break;
1134             case EF_FRV_FPR_32:   strcat (new_opt, " -mfpr-32");     break;
1135             case EF_FRV_FPR_64:   strcat (new_opt, " -mfpr-64");     break;
1136             case EF_FRV_FPR_NONE: strcat (new_opt, " -msoft-float"); break;
1137             }
1138
1139           switch (old_partial)
1140             {
1141             default:              strcat (old_opt, " -mfpr-?");      break;
1142             case EF_FRV_FPR_32:   strcat (old_opt, " -mfpr-32");     break;
1143             case EF_FRV_FPR_64:   strcat (old_opt, " -mfpr-64");     break;
1144             case EF_FRV_FPR_NONE: strcat (old_opt, " -msoft-float"); break;
1145             }
1146         }
1147
1148       /* Warn if different dword support was used.  Note, 0 means nothing is
1149          said about the dword support.  */
1150       new_partial = (new_flags & EF_FRV_DWORD_MASK);
1151       old_partial = (old_flags & EF_FRV_DWORD_MASK);
1152       if (new_partial == old_partial)
1153         ;
1154
1155       else if (new_partial == 0)
1156         ;
1157
1158       else if (old_partial == 0)
1159         old_flags |= new_partial;
1160
1161       else
1162         {
1163           switch (new_partial)
1164             {
1165             default:               strcat (new_opt, " -mdword-?");  break;
1166             case EF_FRV_DWORD_YES: strcat (new_opt, " -mdword");    break;
1167             case EF_FRV_DWORD_NO:  strcat (new_opt, " -mno-dword"); break;
1168             }
1169
1170           switch (old_partial)
1171             {
1172             default:               strcat (old_opt, " -mdword-?");  break;
1173             case EF_FRV_DWORD_YES: strcat (old_opt, " -mdword");    break;
1174             case EF_FRV_DWORD_NO:  strcat (old_opt, " -mno-dword"); break;
1175             }
1176         }
1177
1178       /* Or in flags that accumulate (ie, if one module uses it, mark that the
1179          feature is used.  */
1180       old_flags |= new_flags & (EF_FRV_DOUBLE
1181                                 | EF_FRV_MEDIA
1182                                 | EF_FRV_MULADD
1183                                 | EF_FRV_NON_PIC_RELOCS);
1184
1185       /* If any module was compiled without -G0, clear the G0 bit.  */
1186       old_flags = ((old_flags & ~ EF_FRV_G0)
1187                    | (old_flags & new_flags & EF_FRV_G0));
1188
1189       /* If any module was compiled without -mnopack, clear the mnopack bit.  */
1190       old_flags = ((old_flags & ~ EF_FRV_NOPACK)
1191                    | (old_flags & new_flags & EF_FRV_NOPACK));
1192
1193       /* We don't have to do anything if the pic flags are the same, or the new
1194          module(s) were compiled with -mlibrary-pic.  */
1195       new_partial = (new_flags & EF_FRV_PIC_FLAGS);
1196       old_partial = (old_flags & EF_FRV_PIC_FLAGS);
1197       if ((new_partial == old_partial) || ((new_partial & EF_FRV_LIBPIC) != 0))
1198         ;
1199
1200       /* If the old module(s) were compiled with -mlibrary-pic, copy in the pic
1201          flags if any from the new module.  */
1202       else if ((old_partial & EF_FRV_LIBPIC) != 0)
1203         old_flags = (old_flags & ~ EF_FRV_PIC_FLAGS) | new_partial;
1204
1205       /* If we have mixtures of -fpic and -fPIC, or in both bits.  */
1206       else if (new_partial != 0 && old_partial != 0)
1207         old_flags |= new_partial;
1208
1209       /* One module was compiled for pic and the other was not, see if we have
1210          had any relocations that are not pic-safe.  */
1211       else
1212         {
1213           if ((old_flags & EF_FRV_NON_PIC_RELOCS) == 0)
1214             old_flags |= new_partial;
1215           else
1216             {
1217               old_flags &= ~ EF_FRV_PIC_FLAGS;
1218 #ifndef FRV_NO_PIC_ERROR
1219               error = TRUE;
1220               (*_bfd_error_handler)
1221                 (_("%s: compiled with %s and linked with modules that use non-pic relocations"),
1222                  bfd_get_filename (ibfd),
1223                  (new_flags & EF_FRV_BIGPIC) ? "-fPIC" : "-fpic");
1224 #endif
1225             }
1226         }
1227
1228       /* Warn if different cpu is used (allow a specific cpu to override
1229          the generic cpu).  */
1230       new_partial = (new_flags & EF_FRV_CPU_MASK);
1231       old_partial = (old_flags & EF_FRV_CPU_MASK);
1232       if (new_partial == old_partial)
1233         ;
1234
1235       else if (new_partial == EF_FRV_CPU_GENERIC)
1236         ;
1237
1238       else if (old_partial == EF_FRV_CPU_GENERIC)
1239         old_flags = (old_flags & ~EF_FRV_CPU_MASK) | new_partial;
1240
1241       else
1242         {
1243           switch (new_partial)
1244             {
1245             default:                 strcat (new_opt, " -mcpu=?");      break;
1246             case EF_FRV_CPU_GENERIC: strcat (new_opt, " -mcpu=frv");    break;
1247             case EF_FRV_CPU_SIMPLE:  strcat (new_opt, " -mcpu=simple"); break;
1248             case EF_FRV_CPU_FR500:   strcat (new_opt, " -mcpu=fr500");  break;
1249             case EF_FRV_CPU_FR400:   strcat (new_opt, " -mcpu=fr400");  break;
1250             case EF_FRV_CPU_FR300:   strcat (new_opt, " -mcpu=fr300");  break;
1251             case EF_FRV_CPU_TOMCAT:  strcat (new_opt, " -mcpu=tomcat"); break;
1252             }
1253
1254           switch (old_partial)
1255             {
1256             default:                 strcat (old_opt, " -mcpu=?");      break;
1257             case EF_FRV_CPU_GENERIC: strcat (old_opt, " -mcpu=frv");    break;
1258             case EF_FRV_CPU_SIMPLE:  strcat (old_opt, " -mcpu=simple"); break;
1259             case EF_FRV_CPU_FR500:   strcat (old_opt, " -mcpu=fr500");  break;
1260             case EF_FRV_CPU_FR400:   strcat (old_opt, " -mcpu=fr400");  break;
1261             case EF_FRV_CPU_FR300:   strcat (old_opt, " -mcpu=fr300");  break;
1262             case EF_FRV_CPU_TOMCAT:  strcat (old_opt, " -mcpu=tomcat"); break;
1263             }
1264         }
1265
1266       /* Print out any mismatches from above.  */
1267       if (new_opt[0])
1268         {
1269           error = TRUE;
1270           (*_bfd_error_handler)
1271             (_("%s: compiled with %s and linked with modules compiled with %s"),
1272              bfd_get_filename (ibfd), new_opt, old_opt);
1273         }
1274
1275       /* Warn about any other mismatches */
1276       new_partial = (new_flags & ~ EF_FRV_ALL_FLAGS);
1277       old_partial = (old_flags & ~ EF_FRV_ALL_FLAGS);
1278       if (new_partial != old_partial)
1279         {
1280           old_flags |= new_partial;
1281           error = TRUE;
1282           (*_bfd_error_handler)
1283             (_("%s: uses different unknown e_flags (0x%lx) fields than previous modules (0x%lx)"),
1284              bfd_get_filename (ibfd), (long)new_partial, (long)old_partial);
1285         }
1286     }
1287
1288   /* If the cpu is -mcpu=simple, then set the -mnopack bit.  */
1289   if ((old_flags & EF_FRV_CPU_MASK) == EF_FRV_CPU_SIMPLE)
1290     old_flags |= EF_FRV_NOPACK;
1291
1292   /* Update the old flags now with changes made above.  */
1293   old_partial = elf_elfheader (obfd)->e_flags & EF_FRV_CPU_MASK;
1294   elf_elfheader (obfd)->e_flags = old_flags;
1295   if (old_partial != (old_flags & EF_FRV_CPU_MASK))
1296     bfd_default_set_arch_mach (obfd, bfd_arch_frv, elf32_frv_machine (obfd));
1297
1298   if (error)
1299     bfd_set_error (bfd_error_bad_value);
1300
1301   return !error;
1302 }
1303
1304 \f
1305 bfd_boolean
1306 frv_elf_print_private_bfd_data (abfd, ptr)
1307      bfd *abfd;
1308      PTR ptr;
1309 {
1310   FILE *file = (FILE *) ptr;
1311   flagword flags;
1312
1313   BFD_ASSERT (abfd != NULL && ptr != NULL);
1314
1315   /* Print normal ELF private data.  */
1316   _bfd_elf_print_private_bfd_data (abfd, ptr);
1317
1318   flags = elf_elfheader (abfd)->e_flags;
1319   fprintf (file, _("private flags = 0x%lx:"), (long)flags);
1320
1321   switch (flags & EF_FRV_CPU_MASK)
1322     {
1323     default:                                                    break;
1324     case EF_FRV_CPU_SIMPLE: fprintf (file, " -mcpu=simple");    break;
1325     case EF_FRV_CPU_FR500:  fprintf (file, " -mcpu=fr500");     break;
1326     case EF_FRV_CPU_FR400:  fprintf (file, " -mcpu=fr400");     break;
1327     case EF_FRV_CPU_FR300:  fprintf (file, " -mcpu=fr300");     break;
1328     case EF_FRV_CPU_TOMCAT: fprintf (file, " -mcpu=tomcat");    break;
1329     }
1330
1331   switch (flags & EF_FRV_GPR_MASK)
1332     {
1333     default:                                                    break;
1334     case EF_FRV_GPR_32: fprintf (file, " -mgpr-32");            break;
1335     case EF_FRV_GPR_64: fprintf (file, " -mgpr-64");            break;
1336     }
1337
1338   switch (flags & EF_FRV_FPR_MASK)
1339     {
1340     default:                                                    break;
1341     case EF_FRV_FPR_32:   fprintf (file, " -mfpr-32");          break;
1342     case EF_FRV_FPR_64:   fprintf (file, " -mfpr-64");          break;
1343     case EF_FRV_FPR_NONE: fprintf (file, " -msoft-float");      break;
1344     }
1345
1346   switch (flags & EF_FRV_DWORD_MASK)
1347     {
1348     default:                                                    break;
1349     case EF_FRV_DWORD_YES: fprintf (file, " -mdword");          break;
1350     case EF_FRV_DWORD_NO:  fprintf (file, " -mno-dword");       break;
1351     }
1352
1353   if (flags & EF_FRV_DOUBLE)
1354     fprintf (file, " -mdouble");
1355
1356   if (flags & EF_FRV_MEDIA)
1357     fprintf (file, " -mmedia");
1358
1359   if (flags & EF_FRV_MULADD)
1360     fprintf (file, " -mmuladd");
1361
1362   if (flags & EF_FRV_PIC)
1363     fprintf (file, " -fpic");
1364
1365   if (flags & EF_FRV_BIGPIC)
1366     fprintf (file, " -fPIC");
1367
1368   if (flags & EF_FRV_NON_PIC_RELOCS)
1369     fprintf (file, " non-pic relocations");
1370
1371   if (flags & EF_FRV_G0)
1372     fprintf (file, " -G0");
1373
1374   fputc ('\n', file);
1375   return TRUE;
1376 }
1377
1378 \f
1379 #define ELF_ARCH                bfd_arch_frv
1380 #define ELF_MACHINE_CODE        EM_CYGNUS_FRV
1381 #define ELF_MAXPAGESIZE         0x1000
1382
1383 #define TARGET_BIG_SYM          bfd_elf32_frv_vec
1384 #define TARGET_BIG_NAME         "elf32-frv"
1385
1386 #define elf_info_to_howto_rel                   NULL
1387 #define elf_info_to_howto                       frv_info_to_howto_rela
1388 #define elf_backend_relocate_section            elf32_frv_relocate_section
1389 #define elf_backend_gc_mark_hook                elf32_frv_gc_mark_hook
1390 #define elf_backend_gc_sweep_hook               elf32_frv_gc_sweep_hook
1391 #define elf_backend_check_relocs                elf32_frv_check_relocs
1392 #define elf_backend_object_p                    elf32_frv_object_p
1393 #define elf_backend_add_symbol_hook             elf32_frv_add_symbol_hook
1394
1395 #define elf_backend_can_gc_sections             1
1396 #define elf_backend_rela_normal                 1
1397
1398 #define bfd_elf32_bfd_reloc_type_lookup         frv_reloc_type_lookup
1399 #define bfd_elf32_bfd_set_private_flags         frv_elf_set_private_flags
1400 #define bfd_elf32_bfd_copy_private_bfd_data     frv_elf_copy_private_bfd_data
1401 #define bfd_elf32_bfd_merge_private_bfd_data    frv_elf_merge_private_bfd_data
1402 #define bfd_elf32_bfd_print_private_bfd_data    frv_elf_print_private_bfd_data
1403
1404 #include "elf32-target.h"
This page took 0.103021 seconds and 4 git commands to generate.