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))
6 This file is part of BFD, the Binary File Descriptor library.
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.
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.
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. */
26 #include "elf/m68hc11.h"
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 *));
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));
38 /* GC mark and sweep. */
39 static asection *elf32_m68hc11_gc_mark_hook
40 PARAMS ((bfd *abfd, struct bfd_link_info *info,
41 Elf_Internal_Rela *rel, struct elf_link_hash_entry *h,
42 Elf_Internal_Sym *sym));
43 static boolean elf32_m68hc11_gc_sweep_hook
44 PARAMS ((bfd *abfd, struct bfd_link_info *info,
45 asection *sec, const Elf_Internal_Rela *relocs));
47 boolean _bfd_m68hc11_elf_merge_private_bfd_data PARAMS ((bfd*, bfd*));
48 boolean _bfd_m68hc11_elf_set_private_flags PARAMS ((bfd*, flagword));
49 boolean _bfd_m68hc11_elf_print_private_bfd_data PARAMS ((bfd*, PTR));
51 /* Use REL instead of RELA to save space */
54 /* The Motorola 68HC11 microcontroler only addresses 64Kb.
55 We must handle 8 and 16-bit relocations. The 32-bit relocation
56 is defined but not used except by gas when -gstabs is used (which
58 The 3-bit and 16-bit PC rel relocation is only used by 68HC12. */
59 static reloc_howto_type elf_m68hc11_howto_table[] = {
60 /* This reloc does nothing. */
61 HOWTO (R_M68HC11_NONE, /* type */
63 2, /* size (0 = byte, 1 = short, 2 = long) */
65 false, /* pc_relative */
67 complain_overflow_dont,/* complain_on_overflow */
68 bfd_elf_generic_reloc, /* special_function */
69 "R_M68HC11_NONE", /* name */
70 false, /* partial_inplace */
73 false), /* pcrel_offset */
75 /* A 8 bit absolute relocation */
76 HOWTO (R_M68HC11_8, /* type */
78 0, /* size (0 = byte, 1 = short, 2 = long) */
80 false, /* pc_relative */
82 complain_overflow_bitfield, /* complain_on_overflow */
83 bfd_elf_generic_reloc, /* special_function */
84 "R_M68HC11_8", /* name */
85 false, /* partial_inplace */
86 0x00ff, /* src_mask */
87 0x00ff, /* dst_mask */
88 false), /* pcrel_offset */
90 /* A 8 bit absolute relocation (upper address) */
91 HOWTO (R_M68HC11_HI8, /* type */
93 0, /* size (0 = byte, 1 = short, 2 = long) */
95 false, /* pc_relative */
97 complain_overflow_bitfield, /* complain_on_overflow */
98 bfd_elf_generic_reloc, /* special_function */
99 "R_M68HC11_HI8", /* name */
100 false, /* partial_inplace */
101 0x00ff, /* src_mask */
102 0x00ff, /* dst_mask */
103 false), /* pcrel_offset */
105 /* A 8 bit absolute relocation (upper address) */
106 HOWTO (R_M68HC11_LO8, /* type */
108 0, /* size (0 = byte, 1 = short, 2 = long) */
110 false, /* pc_relative */
112 complain_overflow_dont, /* complain_on_overflow */
113 bfd_elf_generic_reloc, /* special_function */
114 "R_M68HC11_LO8", /* name */
115 false, /* partial_inplace */
116 0x00ff, /* src_mask */
117 0x00ff, /* dst_mask */
118 false), /* pcrel_offset */
120 /* A 8 bit PC-rel relocation */
121 HOWTO (R_M68HC11_PCREL_8, /* type */
123 0, /* size (0 = byte, 1 = short, 2 = long) */
125 true, /* pc_relative */
127 complain_overflow_bitfield, /* complain_on_overflow */
128 bfd_elf_generic_reloc, /* special_function */
129 "R_M68HC11_PCREL_8", /* name */
130 false, /* partial_inplace */
131 0x00ff, /* src_mask */
132 0x00ff, /* dst_mask */
133 false), /* pcrel_offset */
135 /* A 16 bit absolute relocation */
136 HOWTO (R_M68HC11_16, /* type */
138 1, /* size (0 = byte, 1 = short, 2 = long) */
140 false, /* pc_relative */
142 complain_overflow_dont /*bitfield */ , /* complain_on_overflow */
143 bfd_elf_generic_reloc, /* special_function */
144 "R_M68HC11_16", /* name */
145 false, /* partial_inplace */
146 0xffff, /* src_mask */
147 0xffff, /* dst_mask */
148 false), /* pcrel_offset */
150 /* A 32 bit absolute relocation. This one is never used for the
151 code relocation. It's used by gas for -gstabs generation. */
152 HOWTO (R_M68HC11_32, /* type */
154 2, /* size (0 = byte, 1 = short, 2 = long) */
156 false, /* pc_relative */
158 complain_overflow_bitfield, /* complain_on_overflow */
159 bfd_elf_generic_reloc, /* special_function */
160 "R_M68HC11_32", /* name */
161 false, /* partial_inplace */
162 0xffffffff, /* src_mask */
163 0xffffffff, /* dst_mask */
164 false), /* pcrel_offset */
166 /* A 3 bit absolute relocation */
167 HOWTO (R_M68HC11_3B, /* type */
169 0, /* size (0 = byte, 1 = short, 2 = long) */
171 false, /* pc_relative */
173 complain_overflow_bitfield, /* complain_on_overflow */
174 bfd_elf_generic_reloc, /* special_function */
175 "R_M68HC11_4B", /* name */
176 false, /* partial_inplace */
177 0x003, /* src_mask */
178 0x003, /* dst_mask */
179 false), /* pcrel_offset */
181 /* A 16 bit PC-rel relocation */
182 HOWTO (R_M68HC11_PCREL_16, /* type */
184 1, /* size (0 = byte, 1 = short, 2 = long) */
186 true, /* pc_relative */
188 complain_overflow_dont, /* complain_on_overflow */
189 bfd_elf_generic_reloc, /* special_function */
190 "R_M68HC11_PCREL_16", /* name */
191 false, /* partial_inplace */
192 0xffff, /* src_mask */
193 0xffff, /* dst_mask */
194 false), /* pcrel_offset */
196 /* GNU extension to record C++ vtable hierarchy */
197 HOWTO (R_M68HC11_GNU_VTINHERIT, /* type */
199 1, /* size (0 = byte, 1 = short, 2 = long) */
201 false, /* pc_relative */
203 complain_overflow_dont, /* complain_on_overflow */
204 NULL, /* special_function */
205 "R_M68HC11_GNU_VTINHERIT", /* name */
206 false, /* partial_inplace */
209 false), /* pcrel_offset */
211 /* GNU extension to record C++ vtable member usage */
212 HOWTO (R_M68HC11_GNU_VTENTRY, /* type */
214 1, /* size (0 = byte, 1 = short, 2 = long) */
216 false, /* pc_relative */
218 complain_overflow_dont, /* complain_on_overflow */
219 _bfd_elf_rel_vtable_reloc_fn, /* special_function */
220 "R_M68HC11_GNU_VTENTRY", /* name */
221 false, /* partial_inplace */
224 false), /* pcrel_offset */
226 /* A 24 bit relocation */
227 HOWTO (R_M68HC11_24, /* type */
229 1, /* size (0 = byte, 1 = short, 2 = long) */
231 false, /* pc_relative */
233 complain_overflow_bitfield, /* complain_on_overflow */
234 bfd_elf_generic_reloc, /* special_function */
235 "R_M68HC11_24", /* name */
236 false, /* partial_inplace */
237 0xffff, /* src_mask */
238 0xffff, /* dst_mask */
239 false), /* pcrel_offset */
241 /* A 16-bit low relocation */
242 HOWTO (R_M68HC11_LO16, /* type */
244 1, /* size (0 = byte, 1 = short, 2 = long) */
246 false, /* pc_relative */
248 complain_overflow_bitfield, /* complain_on_overflow */
249 bfd_elf_generic_reloc, /* special_function */
250 "R_M68HC11_LO16", /* name */
251 false, /* partial_inplace */
252 0xffff, /* src_mask */
253 0xffff, /* dst_mask */
254 false), /* pcrel_offset */
256 /* A page relocation */
257 HOWTO (R_M68HC11_PAGE, /* type */
259 0, /* size (0 = byte, 1 = short, 2 = long) */
261 false, /* pc_relative */
263 complain_overflow_bitfield, /* complain_on_overflow */
264 bfd_elf_generic_reloc, /* special_function */
265 "R_M68HC11_PAGE", /* name */
266 false, /* partial_inplace */
267 0x00ff, /* src_mask */
268 0x00ff, /* dst_mask */
269 false), /* pcrel_offset */
278 /* Mark beginning of a jump instruction (any form). */
279 HOWTO (R_M68HC11_RL_JUMP, /* type */
281 1, /* size (0 = byte, 1 = short, 2 = long) */
283 false, /* pc_relative */
285 complain_overflow_dont, /* complain_on_overflow */
286 m68hc11_elf_ignore_reloc, /* special_function */
287 "R_M68HC11_RL_JUMP", /* name */
288 true, /* partial_inplace */
291 true), /* pcrel_offset */
293 /* Mark beginning of Gcc relaxation group instruction. */
294 HOWTO (R_M68HC11_RL_GROUP, /* type */
296 1, /* size (0 = byte, 1 = short, 2 = long) */
298 false, /* pc_relative */
300 complain_overflow_dont, /* complain_on_overflow */
301 m68hc11_elf_ignore_reloc, /* special_function */
302 "R_M68HC11_RL_GROUP", /* name */
303 true, /* partial_inplace */
306 true), /* pcrel_offset */
309 /* Map BFD reloc types to M68HC11 ELF reloc types. */
311 struct m68hc11_reloc_map
313 bfd_reloc_code_real_type bfd_reloc_val;
314 unsigned char elf_reloc_val;
317 static const struct m68hc11_reloc_map m68hc11_reloc_map[] = {
318 {BFD_RELOC_NONE, R_M68HC11_NONE,},
319 {BFD_RELOC_8, R_M68HC11_8},
320 {BFD_RELOC_M68HC11_HI8, R_M68HC11_HI8},
321 {BFD_RELOC_M68HC11_LO8, R_M68HC11_LO8},
322 {BFD_RELOC_8_PCREL, R_M68HC11_PCREL_8},
323 {BFD_RELOC_16_PCREL, R_M68HC11_PCREL_16},
324 {BFD_RELOC_16, R_M68HC11_16},
325 {BFD_RELOC_32, R_M68HC11_32},
326 {BFD_RELOC_M68HC11_3B, R_M68HC11_3B},
328 {BFD_RELOC_VTABLE_INHERIT, R_M68HC11_GNU_VTINHERIT},
329 {BFD_RELOC_VTABLE_ENTRY, R_M68HC11_GNU_VTENTRY},
331 {BFD_RELOC_M68HC11_LO16, R_M68HC11_LO16},
332 {BFD_RELOC_M68HC11_PAGE, R_M68HC11_PAGE},
333 {BFD_RELOC_M68HC11_24, R_M68HC11_24},
335 {BFD_RELOC_M68HC11_RL_JUMP, R_M68HC11_RL_JUMP},
336 {BFD_RELOC_M68HC11_RL_GROUP, R_M68HC11_RL_GROUP},
339 static reloc_howto_type *
340 bfd_elf32_bfd_reloc_type_lookup (abfd, code)
341 bfd *abfd ATTRIBUTE_UNUSED;
342 bfd_reloc_code_real_type code;
347 i < sizeof (m68hc11_reloc_map) / sizeof (struct m68hc11_reloc_map);
350 if (m68hc11_reloc_map[i].bfd_reloc_val == code)
351 return &elf_m68hc11_howto_table[m68hc11_reloc_map[i].elf_reloc_val];
357 /* This function is used for relocs which are only used for relaxing,
358 which the linker should otherwise ignore. */
360 static bfd_reloc_status_type
361 m68hc11_elf_ignore_reloc (abfd, reloc_entry, symbol, data, input_section,
362 output_bfd, error_message)
363 bfd *abfd ATTRIBUTE_UNUSED;
364 arelent *reloc_entry;
365 asymbol *symbol ATTRIBUTE_UNUSED;
366 PTR data ATTRIBUTE_UNUSED;
367 asection *input_section;
369 char **error_message ATTRIBUTE_UNUSED;
371 if (output_bfd != NULL)
372 reloc_entry->address += input_section->output_offset;
376 /* Set the howto pointer for an M68HC11 ELF reloc. */
379 m68hc11_info_to_howto_rel (abfd, cache_ptr, dst)
380 bfd *abfd ATTRIBUTE_UNUSED;
382 Elf32_Internal_Rel *dst;
386 r_type = ELF32_R_TYPE (dst->r_info);
387 BFD_ASSERT (r_type < (unsigned int) R_M68HC11_max);
388 cache_ptr->howto = &elf_m68hc11_howto_table[r_type];
392 elf32_m68hc11_gc_mark_hook (abfd, info, rel, h, sym)
394 struct bfd_link_info *info ATTRIBUTE_UNUSED;
395 Elf_Internal_Rela *rel;
396 struct elf_link_hash_entry *h;
397 Elf_Internal_Sym *sym;
401 switch (ELF32_R_TYPE (rel->r_info))
404 switch (h->root.type)
406 case bfd_link_hash_defined:
407 case bfd_link_hash_defweak:
408 return h->root.u.def.section;
410 case bfd_link_hash_common:
411 return h->root.u.c.p->section;
420 if (!(elf_bad_symtab (abfd)
421 && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
422 && !((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
423 && sym->st_shndx != SHN_COMMON))
425 return bfd_section_from_elf_index (abfd, sym->st_shndx);
432 elf32_m68hc11_gc_sweep_hook (abfd, info, sec, relocs)
433 bfd *abfd ATTRIBUTE_UNUSED;
434 struct bfd_link_info *info ATTRIBUTE_UNUSED;
435 asection *sec ATTRIBUTE_UNUSED;
436 const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
438 /* We don't use got and plt entries for 68hc11/68hc12. */
443 /* Set and control ELF flags in ELF header. */
446 _bfd_m68hc11_elf_set_private_flags (abfd, flags)
450 BFD_ASSERT (!elf_flags_init (abfd)
451 || elf_elfheader (abfd)->e_flags == flags);
453 elf_elfheader (abfd)->e_flags = flags;
454 elf_flags_init (abfd) = true;
458 /* Merge backend specific data from an object file to the output
459 object file when linking. */
462 _bfd_m68hc11_elf_merge_private_bfd_data (ibfd, obfd)
470 /* Check if we have the same endianess */
471 if (_bfd_generic_verify_endian_match (ibfd, obfd) == false)
474 if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
475 || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
478 new_flags = elf_elfheader (ibfd)->e_flags;
479 elf_elfheader (obfd)->e_flags |= new_flags & EF_M68HC11_ABI;
480 old_flags = elf_elfheader (obfd)->e_flags;
482 if (! elf_flags_init (obfd))
484 elf_flags_init (obfd) = true;
485 elf_elfheader (obfd)->e_flags = new_flags;
486 elf_elfheader (obfd)->e_ident[EI_CLASS]
487 = elf_elfheader (ibfd)->e_ident[EI_CLASS];
489 if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
490 && bfd_get_arch_info (obfd)->the_default)
492 if (! bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
493 bfd_get_mach (ibfd)))
500 /* Check ABI compatibility. */
501 if ((new_flags & E_M68HC11_I32) != (old_flags & E_M68HC11_I32))
503 (*_bfd_error_handler)
504 (_("%s: linking files compiled for 16-bit integers (-mshort) "
505 "and others for 32-bit integers"),
506 bfd_archive_filename (ibfd));
509 if ((new_flags & E_M68HC11_F64) != (old_flags & E_M68HC11_F64))
511 (*_bfd_error_handler)
512 (_("%s: linking files compiled for 32-bit double (-fshort-double) "
513 "and others for 64-bit double"),
514 bfd_archive_filename (ibfd));
517 new_flags &= ~EF_M68HC11_ABI;
518 old_flags &= ~EF_M68HC11_ABI;
520 /* Warn about any other mismatches */
521 if (new_flags != old_flags)
523 (*_bfd_error_handler)
524 (_("%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"),
525 bfd_archive_filename (ibfd), (unsigned long) new_flags,
526 (unsigned long) old_flags);
532 bfd_set_error (bfd_error_bad_value);
540 _bfd_m68hc11_elf_print_private_bfd_data (abfd, ptr)
544 FILE *file = (FILE *) ptr;
546 BFD_ASSERT (abfd != NULL && ptr != NULL);
548 /* Print normal ELF private data. */
549 _bfd_elf_print_private_bfd_data (abfd, ptr);
551 /* xgettext:c-format */
552 fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags);
554 if (elf_elfheader (abfd)->e_flags & E_M68HC11_I32)
555 fprintf (file, _("[abi=32-bit int,"));
557 fprintf (file, _("[abi=16-bit int,"));
559 if (elf_elfheader (abfd)->e_flags & E_M68HC11_F64)
560 fprintf (file, _(" 64-bit double]"));
562 fprintf (file, _(" 32-bit double]"));
564 if (elf_elfheader (abfd)->e_flags & E_M68HC12_BANKS)
565 fprintf (file, _(" [memory=bank-model]"));
567 fprintf (file, _(" [memory=flat]"));
574 /* Below is the only difference between elf32-m68hc12.c and elf32-m68hc11.c.
575 The Motorola spec says to use a different Elf machine code. */
576 #define ELF_ARCH bfd_arch_m68hc11
577 #define ELF_MACHINE_CODE EM_68HC11
578 #define ELF_MAXPAGESIZE 0x1000
580 #define TARGET_BIG_SYM bfd_elf32_m68hc11_vec
581 #define TARGET_BIG_NAME "elf32-m68hc11"
583 #define elf_info_to_howto 0
584 #define elf_info_to_howto_rel m68hc11_info_to_howto_rel
585 #define elf_backend_gc_mark_hook elf32_m68hc11_gc_mark_hook
586 #define elf_backend_gc_sweep_hook elf32_m68hc11_gc_sweep_hook
587 #define elf_backend_object_p 0
588 #define elf_backend_final_write_processing 0
589 #define elf_backend_can_gc_sections 1
590 #define bfd_elf32_bfd_merge_private_bfd_data \
591 _bfd_m68hc11_elf_merge_private_bfd_data
592 #define bfd_elf32_bfd_set_private_flags _bfd_m68hc11_elf_set_private_flags
593 #define bfd_elf32_bfd_print_private_bfd_data \
594 _bfd_m68hc11_elf_print_private_bfd_data
596 #include "elf32-target.h"