* elf32-m68hc11.c (_bfd_m68hc11_elf_print_private_bfd_data): New.
[external/binutils.git] / bfd / elf32-m68hc11.c
1 /* Motorola 68HC11-specific support for 32-bit ELF
2    Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
3    Contributed by Stephane Carrez (stcarrez@nerim.fr)
4    (Heavily copied from the D10V port by Martin Hunt (hunt@cygnus.com))
5
6 This file is part of BFD, the Binary File Descriptor library.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
21
22 #include "bfd.h"
23 #include "sysdep.h"
24 #include "libbfd.h"
25 #include "elf-bfd.h"
26 #include "elf/m68hc11.h"
27
28 static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
29 PARAMS ((bfd * abfd, bfd_reloc_code_real_type code));
30 static void m68hc11_info_to_howto_rel
31 PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
32
33 static bfd_reloc_status_type m68hc11_elf_ignore_reloc
34 PARAMS ((bfd *abfd, arelent *reloc_entry,
35          asymbol *symbol, PTR data, asection *input_section,
36          bfd *output_bfd, char **error_message));
37
38 boolean _bfd_m68hc11_elf_merge_private_bfd_data PARAMS ((bfd*, bfd*));
39 boolean _bfd_m68hc11_elf_set_private_flags PARAMS ((bfd*, flagword));
40 boolean _bfd_m68hc11_elf_print_private_bfd_data PARAMS ((bfd*, PTR));
41
42 /* Use REL instead of RELA to save space */
43 #define USE_REL
44
45 /* The Motorola 68HC11 microcontroler only addresses 64Kb.
46    We must handle 8 and 16-bit relocations.  The 32-bit relocation
47    is defined but not used except by gas when -gstabs is used (which
48    is wrong).
49    The 3-bit and 16-bit PC rel relocation is only used by 68HC12.  */
50 static reloc_howto_type elf_m68hc11_howto_table[] = {
51   /* This reloc does nothing.  */
52   HOWTO (R_M68HC11_NONE,        /* type */
53          0,                     /* rightshift */
54          2,                     /* size (0 = byte, 1 = short, 2 = long) */
55          32,                    /* bitsize */
56          false,                 /* pc_relative */
57          0,                     /* bitpos */
58          complain_overflow_bitfield,    /* complain_on_overflow */
59          bfd_elf_generic_reloc, /* special_function */
60          "R_M68HC11_NONE",      /* name */
61          false,                 /* partial_inplace */
62          0,                     /* src_mask */
63          0,                     /* dst_mask */
64          false),                /* pcrel_offset */
65
66   /* A 8 bit absolute relocation */
67   HOWTO (R_M68HC11_8,           /* type */
68          0,                     /* rightshift */
69          0,                     /* size (0 = byte, 1 = short, 2 = long) */
70          8,                     /* bitsize */
71          false,                 /* pc_relative */
72          0,                     /* bitpos */
73          complain_overflow_bitfield,    /* complain_on_overflow */
74          bfd_elf_generic_reloc, /* special_function */
75          "R_M68HC11_8",         /* name */
76          false,                 /* partial_inplace */
77          0x00ff,                /* src_mask */
78          0x00ff,                /* dst_mask */
79          false),                /* pcrel_offset */
80
81   /* A 8 bit absolute relocation (upper address) */
82   HOWTO (R_M68HC11_HI8,         /* type */
83          8,                     /* rightshift */
84          0,                     /* size (0 = byte, 1 = short, 2 = long) */
85          8,                     /* bitsize */
86          false,                 /* pc_relative */
87          0,                     /* bitpos */
88          complain_overflow_bitfield,    /* complain_on_overflow */
89          bfd_elf_generic_reloc, /* special_function */
90          "R_M68HC11_HI8",       /* name */
91          false,                 /* partial_inplace */
92          0x00ff,                /* src_mask */
93          0x00ff,                /* dst_mask */
94          false),                /* pcrel_offset */
95
96   /* A 8 bit absolute relocation (upper address) */
97   HOWTO (R_M68HC11_LO8,         /* type */
98          0,                     /* rightshift */
99          0,                     /* size (0 = byte, 1 = short, 2 = long) */
100          8,                     /* bitsize */
101          false,                 /* pc_relative */
102          0,                     /* bitpos */
103          complain_overflow_dont,        /* complain_on_overflow */
104          bfd_elf_generic_reloc, /* special_function */
105          "R_M68HC11_LO8",       /* name */
106          false,                 /* partial_inplace */
107          0x00ff,                /* src_mask */
108          0x00ff,                /* dst_mask */
109          false),                /* pcrel_offset */
110
111   /* A 8 bit PC-rel relocation */
112   HOWTO (R_M68HC11_PCREL_8,     /* type */
113          0,                     /* rightshift */
114          0,                     /* size (0 = byte, 1 = short, 2 = long) */
115          8,                     /* bitsize */
116          true,                  /* pc_relative */
117          0,                     /* bitpos */
118          complain_overflow_bitfield,    /* complain_on_overflow */
119          bfd_elf_generic_reloc, /* special_function */
120          "R_M68HC11_PCREL_8",   /* name */
121          false,                 /* partial_inplace */
122          0x00ff,                /* src_mask */
123          0x00ff,                /* dst_mask */
124          false),                /* pcrel_offset */
125
126   /* A 16 bit absolute relocation */
127   HOWTO (R_M68HC11_16,          /* type */
128          0,                     /* rightshift */
129          1,                     /* size (0 = byte, 1 = short, 2 = long) */
130          16,                    /* bitsize */
131          false,                 /* pc_relative */
132          0,                     /* bitpos */
133          complain_overflow_dont /*bitfield */ , /* complain_on_overflow */
134          bfd_elf_generic_reloc, /* special_function */
135          "R_M68HC11_16",        /* name */
136          false,                 /* partial_inplace */
137          0xffff,                /* src_mask */
138          0xffff,                /* dst_mask */
139          false),                /* pcrel_offset */
140
141   /* A 32 bit absolute relocation.  This one is never used for the
142      code relocation.  It's used by gas for -gstabs generation.  */
143   HOWTO (R_M68HC11_32,          /* type */
144          0,                     /* rightshift */
145          2,                     /* size (0 = byte, 1 = short, 2 = long) */
146          32,                    /* bitsize */
147          false,                 /* pc_relative */
148          0,                     /* bitpos */
149          complain_overflow_bitfield,    /* complain_on_overflow */
150          bfd_elf_generic_reloc, /* special_function */
151          "R_M68HC11_32",        /* name */
152          false,                 /* partial_inplace */
153          0xffffffff,            /* src_mask */
154          0xffffffff,            /* dst_mask */
155          false),                /* pcrel_offset */
156
157   /* A 3 bit absolute relocation */
158   HOWTO (R_M68HC11_3B,          /* type */
159          0,                     /* rightshift */
160          0,                     /* size (0 = byte, 1 = short, 2 = long) */
161          3,                     /* bitsize */
162          false,                 /* pc_relative */
163          0,                     /* bitpos */
164          complain_overflow_bitfield,    /* complain_on_overflow */
165          bfd_elf_generic_reloc, /* special_function */
166          "R_M68HC11_4B",        /* name */
167          false,                 /* partial_inplace */
168          0x003,                 /* src_mask */
169          0x003,                 /* dst_mask */
170          false),                /* pcrel_offset */
171
172   /* A 16 bit PC-rel relocation */
173   HOWTO (R_M68HC11_PCREL_16,    /* type */
174          0,                     /* rightshift */
175          1,                     /* size (0 = byte, 1 = short, 2 = long) */
176          16,                    /* bitsize */
177          true,                  /* pc_relative */
178          0,                     /* bitpos */
179          complain_overflow_dont,        /* complain_on_overflow */
180          bfd_elf_generic_reloc, /* special_function */
181          "R_M68HC11_PCREL_16",  /* name */
182          false,                 /* partial_inplace */
183          0xffff,                /* src_mask */
184          0xffff,                /* dst_mask */
185          false),                /* pcrel_offset */
186
187   /* GNU extension to record C++ vtable hierarchy */
188   HOWTO (R_M68HC11_GNU_VTINHERIT,       /* type */
189          0,                     /* rightshift */
190          1,                     /* size (0 = byte, 1 = short, 2 = long) */
191          0,                     /* bitsize */
192          false,                 /* pc_relative */
193          0,                     /* bitpos */
194          complain_overflow_dont,        /* complain_on_overflow */
195          NULL,                  /* special_function */
196          "R_M68HC11_GNU_VTINHERIT",     /* name */
197          false,                 /* partial_inplace */
198          0,                     /* src_mask */
199          0,                     /* dst_mask */
200          false),                /* pcrel_offset */
201
202   /* GNU extension to record C++ vtable member usage */
203   HOWTO (R_M68HC11_GNU_VTENTRY, /* type */
204          0,                     /* rightshift */
205          1,                     /* size (0 = byte, 1 = short, 2 = long) */
206          0,                     /* bitsize */
207          false,                 /* pc_relative */
208          0,                     /* bitpos */
209          complain_overflow_dont,        /* complain_on_overflow */
210          _bfd_elf_rel_vtable_reloc_fn,  /* special_function */
211          "R_M68HC11_GNU_VTENTRY",       /* name */
212          false,                 /* partial_inplace */
213          0,                     /* src_mask */
214          0,                     /* dst_mask */
215          false),                /* pcrel_offset */
216
217   EMPTY_HOWTO (11),
218   EMPTY_HOWTO (12),
219   EMPTY_HOWTO (13),
220   EMPTY_HOWTO (14),
221   EMPTY_HOWTO (15),
222   EMPTY_HOWTO (16),
223   EMPTY_HOWTO (17),
224   EMPTY_HOWTO (18),
225   EMPTY_HOWTO (19),
226   
227   /* Mark beginning of a jump instruction (any form).  */
228   HOWTO (R_M68HC11_RL_JUMP,     /* type */
229          0,                     /* rightshift */
230          1,                     /* size (0 = byte, 1 = short, 2 = long) */
231          0,                     /* bitsize */
232          false,                 /* pc_relative */
233          0,                     /* bitpos */
234          complain_overflow_dont,        /* complain_on_overflow */
235          m68hc11_elf_ignore_reloc,      /* special_function */
236          "R_M68HC11_RL_JUMP",   /* name */
237          true,                  /* partial_inplace */
238          0,                     /* src_mask */
239          0,                     /* dst_mask */
240          true),                 /* pcrel_offset */
241
242   /* Mark beginning of Gcc relaxation group instruction.  */
243   HOWTO (R_M68HC11_RL_GROUP,    /* type */
244          0,                     /* rightshift */
245          1,                     /* 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          m68hc11_elf_ignore_reloc,      /* special_function */
251          "R_M68HC11_RL_GROUP",  /* name */
252          true,                  /* partial_inplace */
253          0,                     /* src_mask */
254          0,                     /* dst_mask */
255          true),                 /* pcrel_offset */
256 };
257
258 /* Map BFD reloc types to M68HC11 ELF reloc types.  */
259
260 struct m68hc11_reloc_map
261 {
262   bfd_reloc_code_real_type bfd_reloc_val;
263   unsigned char elf_reloc_val;
264 };
265
266 static const struct m68hc11_reloc_map m68hc11_reloc_map[] = {
267   {BFD_RELOC_NONE, R_M68HC11_NONE,},
268   {BFD_RELOC_8, R_M68HC11_8},
269   {BFD_RELOC_M68HC11_HI8, R_M68HC11_HI8},
270   {BFD_RELOC_M68HC11_LO8, R_M68HC11_LO8},
271   {BFD_RELOC_8_PCREL, R_M68HC11_PCREL_8},
272   {BFD_RELOC_16_PCREL, R_M68HC11_PCREL_16},
273   {BFD_RELOC_16, R_M68HC11_16},
274   {BFD_RELOC_32, R_M68HC11_32},
275   {BFD_RELOC_M68HC11_3B, R_M68HC11_3B},
276
277   {BFD_RELOC_VTABLE_INHERIT, R_M68HC11_GNU_VTINHERIT},
278   {BFD_RELOC_VTABLE_ENTRY, R_M68HC11_GNU_VTENTRY},
279
280   {BFD_RELOC_M68HC11_RL_JUMP, R_M68HC11_RL_JUMP},
281   {BFD_RELOC_M68HC11_RL_GROUP, R_M68HC11_RL_GROUP},
282 };
283
284 static reloc_howto_type *
285 bfd_elf32_bfd_reloc_type_lookup (abfd, code)
286      bfd *abfd ATTRIBUTE_UNUSED;
287      bfd_reloc_code_real_type code;
288 {
289   unsigned int i;
290
291   for (i = 0;
292        i < sizeof (m68hc11_reloc_map) / sizeof (struct m68hc11_reloc_map);
293        i++)
294     {
295       if (m68hc11_reloc_map[i].bfd_reloc_val == code)
296         return &elf_m68hc11_howto_table[m68hc11_reloc_map[i].elf_reloc_val];
297     }
298
299   return NULL;
300 }
301
302 /* This function is used for relocs which are only used for relaxing,
303    which the linker should otherwise ignore.  */
304
305 static bfd_reloc_status_type
306 m68hc11_elf_ignore_reloc (abfd, reloc_entry, symbol, data, input_section,
307                           output_bfd, error_message)
308      bfd *abfd ATTRIBUTE_UNUSED;
309      arelent *reloc_entry;
310      asymbol *symbol ATTRIBUTE_UNUSED;
311      PTR data ATTRIBUTE_UNUSED;
312      asection *input_section;
313      bfd *output_bfd;
314      char **error_message ATTRIBUTE_UNUSED;
315 {
316   if (output_bfd != NULL)
317     reloc_entry->address += input_section->output_offset;
318   return bfd_reloc_ok;
319 }
320
321 /* Set the howto pointer for an M68HC11 ELF reloc.  */
322
323 static void
324 m68hc11_info_to_howto_rel (abfd, cache_ptr, dst)
325      bfd *abfd ATTRIBUTE_UNUSED;
326      arelent *cache_ptr;
327      Elf32_Internal_Rel *dst;
328 {
329   unsigned int r_type;
330
331   r_type = ELF32_R_TYPE (dst->r_info);
332   BFD_ASSERT (r_type < (unsigned int) R_M68HC11_max);
333   cache_ptr->howto = &elf_m68hc11_howto_table[r_type];
334 }
335
336 \f
337 /* Set and control ELF flags in ELF header.  */
338
339 boolean
340 _bfd_m68hc11_elf_set_private_flags (abfd, flags)
341      bfd *abfd;
342      flagword flags;
343 {
344   BFD_ASSERT (!elf_flags_init (abfd)
345               || elf_elfheader (abfd)->e_flags == flags);
346
347   elf_elfheader (abfd)->e_flags = flags;
348   elf_flags_init (abfd) = true;
349   return true;
350 }
351
352 /* Merge backend specific data from an object file to the output
353    object file when linking.  */
354
355 boolean
356 _bfd_m68hc11_elf_merge_private_bfd_data (ibfd, obfd)
357      bfd *ibfd;
358      bfd *obfd;
359 {
360   flagword old_flags;
361   flagword new_flags;
362   boolean ok = true;
363
364   /* Check if we have the same endianess */
365   if (_bfd_generic_verify_endian_match (ibfd, obfd) == false)
366     return false;
367
368   if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
369       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
370     return true;
371
372   new_flags = elf_elfheader (ibfd)->e_flags;
373   elf_elfheader (obfd)->e_flags |= new_flags & EF_M68HC11_ABI;
374   old_flags = elf_elfheader (obfd)->e_flags;
375
376   if (! elf_flags_init (obfd))
377     {
378       elf_flags_init (obfd) = true;
379       elf_elfheader (obfd)->e_flags = new_flags;
380       elf_elfheader (obfd)->e_ident[EI_CLASS]
381         = elf_elfheader (ibfd)->e_ident[EI_CLASS];
382
383       if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
384           && bfd_get_arch_info (obfd)->the_default)
385         {
386           if (! bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
387                                    bfd_get_mach (ibfd)))
388             return false;
389         }
390
391       return true;
392     }
393
394   /* Check ABI compatibility.  */
395   if ((new_flags & E_M68HC11_I32) != (old_flags & E_M68HC11_I32))
396     {
397       (*_bfd_error_handler)
398         (_("%s: linking files compiled for 16-bit integers (-mshort) "
399            "and others for 32-bit integers"),
400          bfd_archive_filename (ibfd));
401       ok = false;
402     }
403   if ((new_flags & E_M68HC11_F64) != (old_flags & E_M68HC11_F64))
404     {
405       (*_bfd_error_handler)
406         (_("%s: linking files compiled for 32-bit double (-fshort-double) "
407            "and others for 64-bit double"),
408          bfd_archive_filename (ibfd));
409       ok = false;
410     }
411   new_flags &= ~EF_M68HC11_ABI;
412   old_flags &= ~EF_M68HC11_ABI;
413
414   /* Warn about any other mismatches */
415   if (new_flags != old_flags)
416     {
417       (*_bfd_error_handler)
418         (_("%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"),
419          bfd_archive_filename (ibfd), (unsigned long) new_flags,
420          (unsigned long) old_flags);
421       ok = false;
422     }
423
424   if (! ok)
425     {
426       bfd_set_error (bfd_error_bad_value);
427       return false;
428     }
429
430   return true;
431 }
432
433 boolean
434 _bfd_m68hc11_elf_print_private_bfd_data (abfd, ptr)
435      bfd *abfd;
436      PTR ptr;
437 {
438   FILE *file = (FILE *) ptr;
439
440   BFD_ASSERT (abfd != NULL && ptr != NULL);
441
442   /* Print normal ELF private data.  */
443   _bfd_elf_print_private_bfd_data (abfd, ptr);
444
445   /* xgettext:c-format */
446   fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags);
447
448   if (elf_elfheader (abfd)->e_flags & E_M68HC11_I32)
449     fprintf (file, _("[abi=32-bit int,"));
450   else
451     fprintf (file, _("[abi=16-bit int,"));
452
453   if (elf_elfheader (abfd)->e_flags & E_M68HC11_F64)
454     fprintf (file, _(" 64-bit double]"));
455   else
456     fprintf (file, _(" 32-bit double]"));
457
458   if (elf_elfheader (abfd)->e_flags & E_M68HC12_BANKS)
459     fprintf (file, _(" [memory=bank-model]"));
460   else
461     fprintf (file, _(" [memory=flat]"));
462
463   fputc ('\n', file);
464
465   return true;
466 }
467
468 /* Below is the only difference between elf32-m68hc12.c and elf32-m68hc11.c.
469    The Motorola spec says to use a different Elf machine code.  */
470 #define ELF_ARCH                bfd_arch_m68hc11
471 #define ELF_MACHINE_CODE        EM_68HC11
472 #define ELF_MAXPAGESIZE         0x1000
473
474 #define TARGET_BIG_SYM          bfd_elf32_m68hc11_vec
475 #define TARGET_BIG_NAME         "elf32-m68hc11"
476
477 #define elf_info_to_howto       0
478 #define elf_info_to_howto_rel   m68hc11_info_to_howto_rel
479 #define elf_backend_object_p    0
480 #define elf_backend_final_write_processing      0
481
482 #define bfd_elf32_bfd_merge_private_bfd_data \
483                                         _bfd_m68hc11_elf_merge_private_bfd_data
484 #define bfd_elf32_bfd_set_private_flags _bfd_m68hc11_elf_set_private_flags
485 #define bfd_elf32_bfd_print_private_bfd_data \
486                                         _bfd_m68hc11_elf_print_private_bfd_data
487
488 #include "elf32-target.h"