Fix integration pb for:
[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_dont,/* 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   /* A 24 bit relocation */
218   HOWTO (R_M68HC11_24,          /* type */
219          0,                     /* rightshift */
220          1,                     /* size (0 = byte, 1 = short, 2 = long) */
221          24,                    /* bitsize */
222          false,                 /* pc_relative */
223          0,                     /* bitpos */
224          complain_overflow_bitfield,    /* complain_on_overflow */
225          bfd_elf_generic_reloc, /* special_function */
226          "R_M68HC11_24",        /* name */
227          false,                 /* partial_inplace */
228          0xffff,                /* src_mask */
229          0xffff,                /* dst_mask */
230          false),                /* pcrel_offset */
231   
232   /* A 16-bit low relocation */
233   HOWTO (R_M68HC11_LO16,        /* type */
234          0,                     /* rightshift */
235          1,                     /* size (0 = byte, 1 = short, 2 = long) */
236          16,                    /* bitsize */
237          false,                 /* pc_relative */
238          0,                     /* bitpos */
239          complain_overflow_bitfield,    /* complain_on_overflow */
240          bfd_elf_generic_reloc, /* special_function */
241          "R_M68HC11_LO16",      /* name */
242          false,                 /* partial_inplace */
243          0xffff,                /* src_mask */
244          0xffff,                /* dst_mask */
245          false),                /* pcrel_offset */
246
247   /* A page relocation */
248   HOWTO (R_M68HC11_PAGE,        /* type */
249          0,                     /* rightshift */
250          0,                     /* size (0 = byte, 1 = short, 2 = long) */
251          8,                     /* bitsize */
252          false,                 /* pc_relative */
253          0,                     /* bitpos */
254          complain_overflow_bitfield,    /* complain_on_overflow */
255          bfd_elf_generic_reloc, /* special_function */
256          "R_M68HC11_PAGE",      /* name */
257          false,                 /* partial_inplace */
258          0x00ff,                /* src_mask */
259          0x00ff,                /* dst_mask */
260          false),                /* pcrel_offset */
261
262   EMPTY_HOWTO (14),
263   EMPTY_HOWTO (15),
264   EMPTY_HOWTO (16),
265   EMPTY_HOWTO (17),
266   EMPTY_HOWTO (18),
267   EMPTY_HOWTO (19),
268   
269   /* Mark beginning of a jump instruction (any form).  */
270   HOWTO (R_M68HC11_RL_JUMP,     /* type */
271          0,                     /* rightshift */
272          1,                     /* size (0 = byte, 1 = short, 2 = long) */
273          0,                     /* bitsize */
274          false,                 /* pc_relative */
275          0,                     /* bitpos */
276          complain_overflow_dont,        /* complain_on_overflow */
277          m68hc11_elf_ignore_reloc,      /* special_function */
278          "R_M68HC11_RL_JUMP",   /* name */
279          true,                  /* partial_inplace */
280          0,                     /* src_mask */
281          0,                     /* dst_mask */
282          true),                 /* pcrel_offset */
283
284   /* Mark beginning of Gcc relaxation group instruction.  */
285   HOWTO (R_M68HC11_RL_GROUP,    /* type */
286          0,                     /* rightshift */
287          1,                     /* size (0 = byte, 1 = short, 2 = long) */
288          0,                     /* bitsize */
289          false,                 /* pc_relative */
290          0,                     /* bitpos */
291          complain_overflow_dont,        /* complain_on_overflow */
292          m68hc11_elf_ignore_reloc,      /* special_function */
293          "R_M68HC11_RL_GROUP",  /* name */
294          true,                  /* partial_inplace */
295          0,                     /* src_mask */
296          0,                     /* dst_mask */
297          true),                 /* pcrel_offset */
298 };
299
300 /* Map BFD reloc types to M68HC11 ELF reloc types.  */
301
302 struct m68hc11_reloc_map
303 {
304   bfd_reloc_code_real_type bfd_reloc_val;
305   unsigned char elf_reloc_val;
306 };
307
308 static const struct m68hc11_reloc_map m68hc11_reloc_map[] = {
309   {BFD_RELOC_NONE, R_M68HC11_NONE,},
310   {BFD_RELOC_8, R_M68HC11_8},
311   {BFD_RELOC_M68HC11_HI8, R_M68HC11_HI8},
312   {BFD_RELOC_M68HC11_LO8, R_M68HC11_LO8},
313   {BFD_RELOC_8_PCREL, R_M68HC11_PCREL_8},
314   {BFD_RELOC_16_PCREL, R_M68HC11_PCREL_16},
315   {BFD_RELOC_16, R_M68HC11_16},
316   {BFD_RELOC_32, R_M68HC11_32},
317   {BFD_RELOC_M68HC11_3B, R_M68HC11_3B},
318
319   {BFD_RELOC_VTABLE_INHERIT, R_M68HC11_GNU_VTINHERIT},
320   {BFD_RELOC_VTABLE_ENTRY, R_M68HC11_GNU_VTENTRY},
321
322   {BFD_RELOC_M68HC11_LO16, R_M68HC11_LO16},
323   {BFD_RELOC_M68HC11_PAGE, R_M68HC11_PAGE},
324   {BFD_RELOC_M68HC11_24, R_M68HC11_24},
325
326   {BFD_RELOC_M68HC11_RL_JUMP, R_M68HC11_RL_JUMP},
327   {BFD_RELOC_M68HC11_RL_GROUP, R_M68HC11_RL_GROUP},
328 };
329
330 static reloc_howto_type *
331 bfd_elf32_bfd_reloc_type_lookup (abfd, code)
332      bfd *abfd ATTRIBUTE_UNUSED;
333      bfd_reloc_code_real_type code;
334 {
335   unsigned int i;
336
337   for (i = 0;
338        i < sizeof (m68hc11_reloc_map) / sizeof (struct m68hc11_reloc_map);
339        i++)
340     {
341       if (m68hc11_reloc_map[i].bfd_reloc_val == code)
342         return &elf_m68hc11_howto_table[m68hc11_reloc_map[i].elf_reloc_val];
343     }
344
345   return NULL;
346 }
347
348 /* This function is used for relocs which are only used for relaxing,
349    which the linker should otherwise ignore.  */
350
351 static bfd_reloc_status_type
352 m68hc11_elf_ignore_reloc (abfd, reloc_entry, symbol, data, input_section,
353                           output_bfd, error_message)
354      bfd *abfd ATTRIBUTE_UNUSED;
355      arelent *reloc_entry;
356      asymbol *symbol ATTRIBUTE_UNUSED;
357      PTR data ATTRIBUTE_UNUSED;
358      asection *input_section;
359      bfd *output_bfd;
360      char **error_message ATTRIBUTE_UNUSED;
361 {
362   if (output_bfd != NULL)
363     reloc_entry->address += input_section->output_offset;
364   return bfd_reloc_ok;
365 }
366
367 /* Set the howto pointer for an M68HC11 ELF reloc.  */
368
369 static void
370 m68hc11_info_to_howto_rel (abfd, cache_ptr, dst)
371      bfd *abfd ATTRIBUTE_UNUSED;
372      arelent *cache_ptr;
373      Elf32_Internal_Rel *dst;
374 {
375   unsigned int r_type;
376
377   r_type = ELF32_R_TYPE (dst->r_info);
378   BFD_ASSERT (r_type < (unsigned int) R_M68HC11_max);
379   cache_ptr->howto = &elf_m68hc11_howto_table[r_type];
380 }
381
382 \f
383 /* Set and control ELF flags in ELF header.  */
384
385 boolean
386 _bfd_m68hc11_elf_set_private_flags (abfd, flags)
387      bfd *abfd;
388      flagword flags;
389 {
390   BFD_ASSERT (!elf_flags_init (abfd)
391               || elf_elfheader (abfd)->e_flags == flags);
392
393   elf_elfheader (abfd)->e_flags = flags;
394   elf_flags_init (abfd) = true;
395   return true;
396 }
397
398 /* Merge backend specific data from an object file to the output
399    object file when linking.  */
400
401 boolean
402 _bfd_m68hc11_elf_merge_private_bfd_data (ibfd, obfd)
403      bfd *ibfd;
404      bfd *obfd;
405 {
406   flagword old_flags;
407   flagword new_flags;
408   boolean ok = true;
409
410   /* Check if we have the same endianess */
411   if (_bfd_generic_verify_endian_match (ibfd, obfd) == false)
412     return false;
413
414   if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
415       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
416     return true;
417
418   new_flags = elf_elfheader (ibfd)->e_flags;
419   elf_elfheader (obfd)->e_flags |= new_flags & EF_M68HC11_ABI;
420   old_flags = elf_elfheader (obfd)->e_flags;
421
422   if (! elf_flags_init (obfd))
423     {
424       elf_flags_init (obfd) = true;
425       elf_elfheader (obfd)->e_flags = new_flags;
426       elf_elfheader (obfd)->e_ident[EI_CLASS]
427         = elf_elfheader (ibfd)->e_ident[EI_CLASS];
428
429       if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
430           && bfd_get_arch_info (obfd)->the_default)
431         {
432           if (! bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
433                                    bfd_get_mach (ibfd)))
434             return false;
435         }
436
437       return true;
438     }
439
440   /* Check ABI compatibility.  */
441   if ((new_flags & E_M68HC11_I32) != (old_flags & E_M68HC11_I32))
442     {
443       (*_bfd_error_handler)
444         (_("%s: linking files compiled for 16-bit integers (-mshort) "
445            "and others for 32-bit integers"),
446          bfd_archive_filename (ibfd));
447       ok = false;
448     }
449   if ((new_flags & E_M68HC11_F64) != (old_flags & E_M68HC11_F64))
450     {
451       (*_bfd_error_handler)
452         (_("%s: linking files compiled for 32-bit double (-fshort-double) "
453            "and others for 64-bit double"),
454          bfd_archive_filename (ibfd));
455       ok = false;
456     }
457   new_flags &= ~EF_M68HC11_ABI;
458   old_flags &= ~EF_M68HC11_ABI;
459
460   /* Warn about any other mismatches */
461   if (new_flags != old_flags)
462     {
463       (*_bfd_error_handler)
464         (_("%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"),
465          bfd_archive_filename (ibfd), (unsigned long) new_flags,
466          (unsigned long) old_flags);
467       ok = false;
468     }
469
470   if (! ok)
471     {
472       bfd_set_error (bfd_error_bad_value);
473       return false;
474     }
475
476   return true;
477 }
478
479 boolean
480 _bfd_m68hc11_elf_print_private_bfd_data (abfd, ptr)
481      bfd *abfd;
482      PTR ptr;
483 {
484   FILE *file = (FILE *) ptr;
485
486   BFD_ASSERT (abfd != NULL && ptr != NULL);
487
488   /* Print normal ELF private data.  */
489   _bfd_elf_print_private_bfd_data (abfd, ptr);
490
491   /* xgettext:c-format */
492   fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags);
493
494   if (elf_elfheader (abfd)->e_flags & E_M68HC11_I32)
495     fprintf (file, _("[abi=32-bit int,"));
496   else
497     fprintf (file, _("[abi=16-bit int,"));
498
499   if (elf_elfheader (abfd)->e_flags & E_M68HC11_F64)
500     fprintf (file, _(" 64-bit double]"));
501   else
502     fprintf (file, _(" 32-bit double]"));
503
504   if (elf_elfheader (abfd)->e_flags & E_M68HC12_BANKS)
505     fprintf (file, _(" [memory=bank-model]"));
506   else
507     fprintf (file, _(" [memory=flat]"));
508
509   fputc ('\n', file);
510
511   return true;
512 }
513
514 /* Below is the only difference between elf32-m68hc12.c and elf32-m68hc11.c.
515    The Motorola spec says to use a different Elf machine code.  */
516 #define ELF_ARCH                bfd_arch_m68hc11
517 #define ELF_MACHINE_CODE        EM_68HC11
518 #define ELF_MAXPAGESIZE         0x1000
519
520 #define TARGET_BIG_SYM          bfd_elf32_m68hc11_vec
521 #define TARGET_BIG_NAME         "elf32-m68hc11"
522
523 #define elf_info_to_howto       0
524 #define elf_info_to_howto_rel   m68hc11_info_to_howto_rel
525 #define elf_backend_object_p    0
526 #define elf_backend_final_write_processing      0
527
528 #define bfd_elf32_bfd_merge_private_bfd_data \
529                                         _bfd_m68hc11_elf_merge_private_bfd_data
530 #define bfd_elf32_bfd_set_private_flags _bfd_m68hc11_elf_set_private_flags
531 #define bfd_elf32_bfd_print_private_bfd_data \
532                                         _bfd_m68hc11_elf_print_private_bfd_data
533
534 #include "elf32-target.h"