* elf32-m68hc11.c (_bfd_m68hc11_elf_print_private_bfd_data): New.
[deliverable/binutils-gdb.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"
This page took 0.044674 seconds and 5 git commands to generate.