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 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
));
42 /* Use REL instead of RELA to save space */
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
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 */
54 2, /* size (0 = byte, 1 = short, 2 = long) */
56 false, /* pc_relative */
58 complain_overflow_dont
,/* complain_on_overflow */
59 bfd_elf_generic_reloc
, /* special_function */
60 "R_M68HC11_NONE", /* name */
61 false, /* partial_inplace */
64 false), /* pcrel_offset */
66 /* A 8 bit absolute relocation */
67 HOWTO (R_M68HC11_8
, /* type */
69 0, /* size (0 = byte, 1 = short, 2 = long) */
71 false, /* pc_relative */
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 */
81 /* A 8 bit absolute relocation (upper address) */
82 HOWTO (R_M68HC11_HI8
, /* type */
84 0, /* size (0 = byte, 1 = short, 2 = long) */
86 false, /* pc_relative */
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 */
96 /* A 8 bit absolute relocation (upper address) */
97 HOWTO (R_M68HC11_LO8
, /* type */
99 0, /* size (0 = byte, 1 = short, 2 = long) */
101 false, /* pc_relative */
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 */
111 /* A 8 bit PC-rel relocation */
112 HOWTO (R_M68HC11_PCREL_8
, /* type */
114 0, /* size (0 = byte, 1 = short, 2 = long) */
116 true, /* pc_relative */
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 */
126 /* A 16 bit absolute relocation */
127 HOWTO (R_M68HC11_16
, /* type */
129 1, /* size (0 = byte, 1 = short, 2 = long) */
131 false, /* pc_relative */
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 */
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 */
145 2, /* size (0 = byte, 1 = short, 2 = long) */
147 false, /* pc_relative */
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 */
157 /* A 3 bit absolute relocation */
158 HOWTO (R_M68HC11_3B
, /* type */
160 0, /* size (0 = byte, 1 = short, 2 = long) */
162 false, /* pc_relative */
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 */
172 /* A 16 bit PC-rel relocation */
173 HOWTO (R_M68HC11_PCREL_16
, /* type */
175 1, /* size (0 = byte, 1 = short, 2 = long) */
177 true, /* pc_relative */
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 */
187 /* GNU extension to record C++ vtable hierarchy */
188 HOWTO (R_M68HC11_GNU_VTINHERIT
, /* type */
190 1, /* size (0 = byte, 1 = short, 2 = long) */
192 false, /* pc_relative */
194 complain_overflow_dont
, /* complain_on_overflow */
195 NULL
, /* special_function */
196 "R_M68HC11_GNU_VTINHERIT", /* name */
197 false, /* partial_inplace */
200 false), /* pcrel_offset */
202 /* GNU extension to record C++ vtable member usage */
203 HOWTO (R_M68HC11_GNU_VTENTRY
, /* type */
205 1, /* size (0 = byte, 1 = short, 2 = long) */
207 false, /* pc_relative */
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 */
215 false), /* pcrel_offset */
217 /* A 24 bit relocation */
218 HOWTO (R_M68HC11_24
, /* type */
220 1, /* size (0 = byte, 1 = short, 2 = long) */
222 false, /* pc_relative */
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 */
232 /* A 16-bit low relocation */
233 HOWTO (R_M68HC11_LO16
, /* type */
235 1, /* size (0 = byte, 1 = short, 2 = long) */
237 false, /* pc_relative */
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 */
247 /* A page relocation */
248 HOWTO (R_M68HC11_PAGE
, /* type */
250 0, /* size (0 = byte, 1 = short, 2 = long) */
252 false, /* pc_relative */
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 */
269 /* Mark beginning of a jump instruction (any form). */
270 HOWTO (R_M68HC11_RL_JUMP
, /* type */
272 1, /* size (0 = byte, 1 = short, 2 = long) */
274 false, /* pc_relative */
276 complain_overflow_dont
, /* complain_on_overflow */
277 m68hc11_elf_ignore_reloc
, /* special_function */
278 "R_M68HC11_RL_JUMP", /* name */
279 true, /* partial_inplace */
282 true), /* pcrel_offset */
284 /* Mark beginning of Gcc relaxation group instruction. */
285 HOWTO (R_M68HC11_RL_GROUP
, /* type */
287 1, /* size (0 = byte, 1 = short, 2 = long) */
289 false, /* pc_relative */
291 complain_overflow_dont
, /* complain_on_overflow */
292 m68hc11_elf_ignore_reloc
, /* special_function */
293 "R_M68HC11_RL_GROUP", /* name */
294 true, /* partial_inplace */
297 true), /* pcrel_offset */
300 /* Map BFD reloc types to M68HC11 ELF reloc types. */
302 struct m68hc11_reloc_map
304 bfd_reloc_code_real_type bfd_reloc_val
;
305 unsigned char elf_reloc_val
;
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
},
319 {BFD_RELOC_VTABLE_INHERIT
, R_M68HC11_GNU_VTINHERIT
},
320 {BFD_RELOC_VTABLE_ENTRY
, R_M68HC11_GNU_VTENTRY
},
322 {BFD_RELOC_M68HC11_LO16
, R_M68HC11_LO16
},
323 {BFD_RELOC_M68HC11_PAGE
, R_M68HC11_PAGE
},
324 {BFD_RELOC_M68HC11_24
, R_M68HC11_24
},
326 {BFD_RELOC_M68HC11_RL_JUMP
, R_M68HC11_RL_JUMP
},
327 {BFD_RELOC_M68HC11_RL_GROUP
, R_M68HC11_RL_GROUP
},
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
;
338 i
< sizeof (m68hc11_reloc_map
) / sizeof (struct m68hc11_reloc_map
);
341 if (m68hc11_reloc_map
[i
].bfd_reloc_val
== code
)
342 return &elf_m68hc11_howto_table
[m68hc11_reloc_map
[i
].elf_reloc_val
];
348 /* This function is used for relocs which are only used for relaxing,
349 which the linker should otherwise ignore. */
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
;
360 char **error_message ATTRIBUTE_UNUSED
;
362 if (output_bfd
!= NULL
)
363 reloc_entry
->address
+= input_section
->output_offset
;
367 /* Set the howto pointer for an M68HC11 ELF reloc. */
370 m68hc11_info_to_howto_rel (abfd
, cache_ptr
, dst
)
371 bfd
*abfd ATTRIBUTE_UNUSED
;
373 Elf32_Internal_Rel
*dst
;
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
];
383 /* Set and control ELF flags in ELF header. */
386 _bfd_m68hc11_elf_set_private_flags (abfd
, flags
)
390 BFD_ASSERT (!elf_flags_init (abfd
)
391 || elf_elfheader (abfd
)->e_flags
== flags
);
393 elf_elfheader (abfd
)->e_flags
= flags
;
394 elf_flags_init (abfd
) = true;
398 /* Merge backend specific data from an object file to the output
399 object file when linking. */
402 _bfd_m68hc11_elf_merge_private_bfd_data (ibfd
, obfd
)
410 /* Check if we have the same endianess */
411 if (_bfd_generic_verify_endian_match (ibfd
, obfd
) == false)
414 if (bfd_get_flavour (ibfd
) != bfd_target_elf_flavour
415 || bfd_get_flavour (obfd
) != bfd_target_elf_flavour
)
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
;
422 if (! elf_flags_init (obfd
))
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
];
429 if (bfd_get_arch (obfd
) == bfd_get_arch (ibfd
)
430 && bfd_get_arch_info (obfd
)->the_default
)
432 if (! bfd_set_arch_mach (obfd
, bfd_get_arch (ibfd
),
433 bfd_get_mach (ibfd
)))
440 /* Check ABI compatibility. */
441 if ((new_flags
& E_M68HC11_I32
) != (old_flags
& E_M68HC11_I32
))
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
));
449 if ((new_flags
& E_M68HC11_F64
) != (old_flags
& E_M68HC11_F64
))
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
));
457 new_flags
&= ~EF_M68HC11_ABI
;
458 old_flags
&= ~EF_M68HC11_ABI
;
460 /* Warn about any other mismatches */
461 if (new_flags
!= old_flags
)
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
);
472 bfd_set_error (bfd_error_bad_value
);
480 _bfd_m68hc11_elf_print_private_bfd_data (abfd
, ptr
)
484 FILE *file
= (FILE *) ptr
;
486 BFD_ASSERT (abfd
!= NULL
&& ptr
!= NULL
);
488 /* Print normal ELF private data. */
489 _bfd_elf_print_private_bfd_data (abfd
, ptr
);
491 /* xgettext:c-format */
492 fprintf (file
, _("private flags = %lx:"), elf_elfheader (abfd
)->e_flags
);
494 if (elf_elfheader (abfd
)->e_flags
& E_M68HC11_I32
)
495 fprintf (file
, _("[abi=32-bit int,"));
497 fprintf (file
, _("[abi=16-bit int,"));
499 if (elf_elfheader (abfd
)->e_flags
& E_M68HC11_F64
)
500 fprintf (file
, _(" 64-bit double]"));
502 fprintf (file
, _(" 32-bit double]"));
504 if (elf_elfheader (abfd
)->e_flags
& E_M68HC12_BANKS
)
505 fprintf (file
, _(" [memory=bank-model]"));
507 fprintf (file
, _(" [memory=flat]"));
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
520 #define TARGET_BIG_SYM bfd_elf32_m68hc11_vec
521 #define TARGET_BIG_NAME "elf32-m68hc11"
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
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
534 #include "elf32-target.h"