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_bitfield
, /* 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 */
227 /* Mark beginning of a jump instruction (any form). */
228 HOWTO (R_M68HC11_RL_JUMP
, /* type */
230 1, /* size (0 = byte, 1 = short, 2 = long) */
232 false, /* pc_relative */
234 complain_overflow_dont
, /* complain_on_overflow */
235 m68hc11_elf_ignore_reloc
, /* special_function */
236 "R_M68HC11_RL_JUMP", /* name */
237 true, /* partial_inplace */
240 true), /* pcrel_offset */
242 /* Mark beginning of Gcc relaxation group instruction. */
243 HOWTO (R_M68HC11_RL_GROUP
, /* type */
245 1, /* size (0 = byte, 1 = short, 2 = long) */
247 false, /* pc_relative */
249 complain_overflow_dont
, /* complain_on_overflow */
250 m68hc11_elf_ignore_reloc
, /* special_function */
251 "R_M68HC11_RL_GROUP", /* name */
252 true, /* partial_inplace */
255 true), /* pcrel_offset */
258 /* Map BFD reloc types to M68HC11 ELF reloc types. */
260 struct m68hc11_reloc_map
262 bfd_reloc_code_real_type bfd_reloc_val
;
263 unsigned char elf_reloc_val
;
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
},
277 {BFD_RELOC_VTABLE_INHERIT
, R_M68HC11_GNU_VTINHERIT
},
278 {BFD_RELOC_VTABLE_ENTRY
, R_M68HC11_GNU_VTENTRY
},
280 {BFD_RELOC_M68HC11_RL_JUMP
, R_M68HC11_RL_JUMP
},
281 {BFD_RELOC_M68HC11_RL_GROUP
, R_M68HC11_RL_GROUP
},
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
;
292 i
< sizeof (m68hc11_reloc_map
) / sizeof (struct m68hc11_reloc_map
);
295 if (m68hc11_reloc_map
[i
].bfd_reloc_val
== code
)
296 return &elf_m68hc11_howto_table
[m68hc11_reloc_map
[i
].elf_reloc_val
];
302 /* This function is used for relocs which are only used for relaxing,
303 which the linker should otherwise ignore. */
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
;
314 char **error_message ATTRIBUTE_UNUSED
;
316 if (output_bfd
!= NULL
)
317 reloc_entry
->address
+= input_section
->output_offset
;
321 /* Set the howto pointer for an M68HC11 ELF reloc. */
324 m68hc11_info_to_howto_rel (abfd
, cache_ptr
, dst
)
325 bfd
*abfd ATTRIBUTE_UNUSED
;
327 Elf32_Internal_Rel
*dst
;
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
];
337 /* Set and control ELF flags in ELF header. */
340 _bfd_m68hc11_elf_set_private_flags (abfd
, flags
)
344 BFD_ASSERT (!elf_flags_init (abfd
)
345 || elf_elfheader (abfd
)->e_flags
== flags
);
347 elf_elfheader (abfd
)->e_flags
= flags
;
348 elf_flags_init (abfd
) = true;
352 /* Merge backend specific data from an object file to the output
353 object file when linking. */
356 _bfd_m68hc11_elf_merge_private_bfd_data (ibfd
, obfd
)
364 /* Check if we have the same endianess */
365 if (_bfd_generic_verify_endian_match (ibfd
, obfd
) == false)
368 if (bfd_get_flavour (ibfd
) != bfd_target_elf_flavour
369 || bfd_get_flavour (obfd
) != bfd_target_elf_flavour
)
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
;
376 if (! elf_flags_init (obfd
))
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
];
383 if (bfd_get_arch (obfd
) == bfd_get_arch (ibfd
)
384 && bfd_get_arch_info (obfd
)->the_default
)
386 if (! bfd_set_arch_mach (obfd
, bfd_get_arch (ibfd
),
387 bfd_get_mach (ibfd
)))
394 /* Check ABI compatibility. */
395 if ((new_flags
& E_M68HC11_I32
) != (old_flags
& E_M68HC11_I32
))
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
));
403 if ((new_flags
& E_M68HC11_F64
) != (old_flags
& E_M68HC11_F64
))
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
));
411 new_flags
&= ~EF_M68HC11_ABI
;
412 old_flags
&= ~EF_M68HC11_ABI
;
414 /* Warn about any other mismatches */
415 if (new_flags
!= old_flags
)
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
);
426 bfd_set_error (bfd_error_bad_value
);
434 _bfd_m68hc11_elf_print_private_bfd_data (abfd
, ptr
)
438 FILE *file
= (FILE *) ptr
;
440 BFD_ASSERT (abfd
!= NULL
&& ptr
!= NULL
);
442 /* Print normal ELF private data. */
443 _bfd_elf_print_private_bfd_data (abfd
, ptr
);
445 /* xgettext:c-format */
446 fprintf (file
, _("private flags = %lx:"), elf_elfheader (abfd
)->e_flags
);
448 if (elf_elfheader (abfd
)->e_flags
& E_M68HC11_I32
)
449 fprintf (file
, _("[abi=32-bit int,"));
451 fprintf (file
, _("[abi=16-bit int,"));
453 if (elf_elfheader (abfd
)->e_flags
& E_M68HC11_F64
)
454 fprintf (file
, _(" 64-bit double]"));
456 fprintf (file
, _(" 32-bit double]"));
458 if (elf_elfheader (abfd
)->e_flags
& E_M68HC12_BANKS
)
459 fprintf (file
, _(" [memory=bank-model]"));
461 fprintf (file
, _(" [memory=flat]"));
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
474 #define TARGET_BIG_SYM bfd_elf32_m68hc11_vec
475 #define TARGET_BIG_NAME "elf32-m68hc11"
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
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
488 #include "elf32-target.h"