1 /* Motorola 68HC11-specific support for 32-bit ELF
2 Copyright (C) 1999-2018 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
21 MA 02110-1301, USA. */
28 #include "elf32-m68hc1x.h"
29 #include "elf/m68hc11.h"
30 #include "opcode/m68hc11.h"
32 /* Relocation functions. */
33 static reloc_howto_type
*bfd_elf32_bfd_reloc_type_lookup
34 (bfd
*, bfd_reloc_code_real_type
);
35 static bfd_boolean m68hc11_info_to_howto_rel
36 (bfd
*, arelent
*, Elf_Internal_Rela
*);
38 /* Trampoline generation. */
39 static bfd_boolean m68hc11_elf_size_one_stub
40 (struct bfd_hash_entry
*gen_entry
, void *in_arg
);
41 static bfd_boolean m68hc11_elf_build_one_stub
42 (struct bfd_hash_entry
*gen_entry
, void *in_arg
);
43 static struct bfd_link_hash_table
* m68hc11_elf_bfd_link_hash_table_create
46 /* Linker relaxation. */
47 static bfd_boolean m68hc11_elf_relax_section
48 (bfd
*, asection
*, struct bfd_link_info
*, bfd_boolean
*);
49 static void m68hc11_elf_relax_delete_bytes
50 (bfd
*, asection
*, bfd_vma
, int);
51 static void m68hc11_relax_group
52 (bfd
*, asection
*, bfd_byte
*, unsigned, unsigned long, unsigned long);
53 static int compare_reloc (const void *, const void *);
55 /* Use REL instead of RELA to save space */
58 /* The Motorola 68HC11 microcontroller only addresses 64Kb but we also
59 support a memory bank switching mechanism similar to 68HC12.
60 We must handle 8 and 16-bit relocations. The 32-bit relocation
61 are used for debugging sections (DWARF2) to represent a virtual
63 The 3-bit and 16-bit PC rel relocation is only used by 68HC12. */
64 static reloc_howto_type elf_m68hc11_howto_table
[] = {
65 /* This reloc does nothing. */
66 HOWTO (R_M68HC11_NONE
, /* type */
68 3, /* size (0 = byte, 1 = short, 2 = long) */
70 FALSE
, /* pc_relative */
72 complain_overflow_dont
,/* complain_on_overflow */
73 bfd_elf_generic_reloc
, /* special_function */
74 "R_M68HC11_NONE", /* name */
75 FALSE
, /* partial_inplace */
78 FALSE
), /* pcrel_offset */
80 /* A 8 bit absolute relocation */
81 HOWTO (R_M68HC11_8
, /* type */
83 0, /* size (0 = byte, 1 = short, 2 = long) */
85 FALSE
, /* pc_relative */
87 complain_overflow_bitfield
, /* complain_on_overflow */
88 bfd_elf_generic_reloc
, /* special_function */
89 "R_M68HC11_8", /* name */
90 FALSE
, /* partial_inplace */
91 0x00ff, /* src_mask */
92 0x00ff, /* dst_mask */
93 FALSE
), /* pcrel_offset */
95 /* A 8 bit absolute relocation (upper address) */
96 HOWTO (R_M68HC11_HI8
, /* type */
98 0, /* size (0 = byte, 1 = short, 2 = long) */
100 FALSE
, /* pc_relative */
102 complain_overflow_bitfield
, /* complain_on_overflow */
103 bfd_elf_generic_reloc
, /* special_function */
104 "R_M68HC11_HI8", /* name */
105 FALSE
, /* partial_inplace */
106 0x00ff, /* src_mask */
107 0x00ff, /* dst_mask */
108 FALSE
), /* pcrel_offset */
110 /* A 8 bit absolute relocation (upper address) */
111 HOWTO (R_M68HC11_LO8
, /* type */
113 0, /* size (0 = byte, 1 = short, 2 = long) */
115 FALSE
, /* pc_relative */
117 complain_overflow_dont
, /* complain_on_overflow */
118 bfd_elf_generic_reloc
, /* special_function */
119 "R_M68HC11_LO8", /* name */
120 FALSE
, /* partial_inplace */
121 0x00ff, /* src_mask */
122 0x00ff, /* dst_mask */
123 FALSE
), /* pcrel_offset */
125 /* A 8 bit PC-rel relocation */
126 HOWTO (R_M68HC11_PCREL_8
, /* type */
128 0, /* size (0 = byte, 1 = short, 2 = long) */
130 TRUE
, /* pc_relative */
132 complain_overflow_bitfield
, /* complain_on_overflow */
133 bfd_elf_generic_reloc
, /* special_function */
134 "R_M68HC11_PCREL_8", /* name */
135 FALSE
, /* partial_inplace */
136 0x00ff, /* src_mask */
137 0x00ff, /* dst_mask */
138 TRUE
), /* pcrel_offset */
140 /* A 16 bit absolute relocation */
141 HOWTO (R_M68HC11_16
, /* type */
143 1, /* size (0 = byte, 1 = short, 2 = long) */
145 FALSE
, /* pc_relative */
147 complain_overflow_dont
/*bitfield */ , /* complain_on_overflow */
148 bfd_elf_generic_reloc
, /* special_function */
149 "R_M68HC11_16", /* name */
150 FALSE
, /* partial_inplace */
151 0xffff, /* src_mask */
152 0xffff, /* dst_mask */
153 FALSE
), /* pcrel_offset */
155 /* A 32 bit absolute relocation. This one is never used for the
156 code relocation. It's used by gas for -gstabs generation. */
157 HOWTO (R_M68HC11_32
, /* type */
159 2, /* size (0 = byte, 1 = short, 2 = long) */
161 FALSE
, /* pc_relative */
163 complain_overflow_bitfield
, /* complain_on_overflow */
164 bfd_elf_generic_reloc
, /* special_function */
165 "R_M68HC11_32", /* name */
166 FALSE
, /* partial_inplace */
167 0xffffffff, /* src_mask */
168 0xffffffff, /* dst_mask */
169 FALSE
), /* pcrel_offset */
171 /* A 3 bit absolute relocation */
172 HOWTO (R_M68HC11_3B
, /* type */
174 0, /* size (0 = byte, 1 = short, 2 = long) */
176 FALSE
, /* pc_relative */
178 complain_overflow_bitfield
, /* complain_on_overflow */
179 bfd_elf_generic_reloc
, /* special_function */
180 "R_M68HC11_4B", /* name */
181 FALSE
, /* partial_inplace */
182 0x003, /* src_mask */
183 0x003, /* dst_mask */
184 FALSE
), /* pcrel_offset */
186 /* A 16 bit PC-rel relocation */
187 HOWTO (R_M68HC11_PCREL_16
, /* type */
189 1, /* size (0 = byte, 1 = short, 2 = long) */
191 TRUE
, /* pc_relative */
193 complain_overflow_dont
, /* complain_on_overflow */
194 bfd_elf_generic_reloc
, /* special_function */
195 "R_M68HC11_PCREL_16", /* name */
196 FALSE
, /* partial_inplace */
197 0xffff, /* src_mask */
198 0xffff, /* dst_mask */
199 TRUE
), /* pcrel_offset */
201 /* GNU extension to record C++ vtable hierarchy */
202 HOWTO (R_M68HC11_GNU_VTINHERIT
, /* type */
204 1, /* size (0 = byte, 1 = short, 2 = long) */
206 FALSE
, /* pc_relative */
208 complain_overflow_dont
, /* complain_on_overflow */
209 NULL
, /* special_function */
210 "R_M68HC11_GNU_VTINHERIT", /* name */
211 FALSE
, /* partial_inplace */
214 FALSE
), /* pcrel_offset */
216 /* GNU extension to record C++ vtable member usage */
217 HOWTO (R_M68HC11_GNU_VTENTRY
, /* type */
219 1, /* size (0 = byte, 1 = short, 2 = long) */
221 FALSE
, /* pc_relative */
223 complain_overflow_dont
, /* complain_on_overflow */
224 _bfd_elf_rel_vtable_reloc_fn
, /* special_function */
225 "R_M68HC11_GNU_VTENTRY", /* name */
226 FALSE
, /* partial_inplace */
229 FALSE
), /* pcrel_offset */
231 /* A 24 bit relocation */
232 HOWTO (R_M68HC11_24
, /* type */
234 1, /* size (0 = byte, 1 = short, 2 = long) */
236 FALSE
, /* pc_relative */
238 complain_overflow_bitfield
, /* complain_on_overflow */
239 bfd_elf_generic_reloc
, /* special_function */
240 "R_M68HC11_24", /* name */
241 FALSE
, /* partial_inplace */
242 0xffffff, /* src_mask */
243 0xffffff, /* dst_mask */
244 FALSE
), /* pcrel_offset */
246 /* A 16-bit low relocation */
247 HOWTO (R_M68HC11_LO16
, /* type */
249 1, /* size (0 = byte, 1 = short, 2 = long) */
251 FALSE
, /* pc_relative */
253 complain_overflow_bitfield
, /* complain_on_overflow */
254 bfd_elf_generic_reloc
, /* special_function */
255 "R_M68HC11_LO16", /* name */
256 FALSE
, /* partial_inplace */
257 0xffff, /* src_mask */
258 0xffff, /* dst_mask */
259 FALSE
), /* pcrel_offset */
261 /* A page relocation */
262 HOWTO (R_M68HC11_PAGE
, /* type */
264 0, /* size (0 = byte, 1 = short, 2 = long) */
266 FALSE
, /* pc_relative */
268 complain_overflow_bitfield
, /* complain_on_overflow */
269 bfd_elf_generic_reloc
, /* special_function */
270 "R_M68HC11_PAGE", /* name */
271 FALSE
, /* partial_inplace */
272 0x00ff, /* src_mask */
273 0x00ff, /* dst_mask */
274 FALSE
), /* pcrel_offset */
283 /* Mark beginning of a jump instruction (any form). */
284 HOWTO (R_M68HC11_RL_JUMP
, /* type */
286 1, /* size (0 = byte, 1 = short, 2 = long) */
288 FALSE
, /* pc_relative */
290 complain_overflow_dont
, /* complain_on_overflow */
291 m68hc11_elf_ignore_reloc
, /* special_function */
292 "R_M68HC11_RL_JUMP", /* name */
293 TRUE
, /* partial_inplace */
296 TRUE
), /* pcrel_offset */
298 /* Mark beginning of Gcc relaxation group instruction. */
299 HOWTO (R_M68HC11_RL_GROUP
, /* type */
301 1, /* size (0 = byte, 1 = short, 2 = long) */
303 FALSE
, /* pc_relative */
305 complain_overflow_dont
, /* complain_on_overflow */
306 m68hc11_elf_ignore_reloc
, /* special_function */
307 "R_M68HC11_RL_GROUP", /* name */
308 TRUE
, /* partial_inplace */
311 TRUE
), /* pcrel_offset */
314 /* Map BFD reloc types to M68HC11 ELF reloc types. */
316 struct m68hc11_reloc_map
318 bfd_reloc_code_real_type bfd_reloc_val
;
319 unsigned char elf_reloc_val
;
322 static const struct m68hc11_reloc_map m68hc11_reloc_map
[] = {
323 {BFD_RELOC_NONE
, R_M68HC11_NONE
,},
324 {BFD_RELOC_8
, R_M68HC11_8
},
325 {BFD_RELOC_M68HC11_HI8
, R_M68HC11_HI8
},
326 {BFD_RELOC_M68HC11_LO8
, R_M68HC11_LO8
},
327 {BFD_RELOC_8_PCREL
, R_M68HC11_PCREL_8
},
328 {BFD_RELOC_16_PCREL
, R_M68HC11_PCREL_16
},
329 {BFD_RELOC_16
, R_M68HC11_16
},
330 {BFD_RELOC_32
, R_M68HC11_32
},
331 {BFD_RELOC_M68HC11_3B
, R_M68HC11_3B
},
333 {BFD_RELOC_VTABLE_INHERIT
, R_M68HC11_GNU_VTINHERIT
},
334 {BFD_RELOC_VTABLE_ENTRY
, R_M68HC11_GNU_VTENTRY
},
336 {BFD_RELOC_M68HC11_LO16
, R_M68HC11_LO16
},
337 {BFD_RELOC_M68HC11_PAGE
, R_M68HC11_PAGE
},
338 {BFD_RELOC_M68HC11_24
, R_M68HC11_24
},
340 {BFD_RELOC_M68HC11_RL_JUMP
, R_M68HC11_RL_JUMP
},
341 {BFD_RELOC_M68HC11_RL_GROUP
, R_M68HC11_RL_GROUP
},
344 static reloc_howto_type
*
345 bfd_elf32_bfd_reloc_type_lookup (bfd
*abfd ATTRIBUTE_UNUSED
,
346 bfd_reloc_code_real_type code
)
351 i
< sizeof (m68hc11_reloc_map
) / sizeof (struct m68hc11_reloc_map
);
354 if (m68hc11_reloc_map
[i
].bfd_reloc_val
== code
)
355 return &elf_m68hc11_howto_table
[m68hc11_reloc_map
[i
].elf_reloc_val
];
361 static reloc_howto_type
*
362 bfd_elf32_bfd_reloc_name_lookup (bfd
*abfd ATTRIBUTE_UNUSED
,
368 i
< (sizeof (elf_m68hc11_howto_table
)
369 / sizeof (elf_m68hc11_howto_table
[0]));
371 if (elf_m68hc11_howto_table
[i
].name
!= NULL
372 && strcasecmp (elf_m68hc11_howto_table
[i
].name
, r_name
) == 0)
373 return &elf_m68hc11_howto_table
[i
];
378 /* Set the howto pointer for an M68HC11 ELF reloc. */
381 m68hc11_info_to_howto_rel (bfd
*abfd
,
382 arelent
*cache_ptr
, Elf_Internal_Rela
*dst
)
386 r_type
= ELF32_R_TYPE (dst
->r_info
);
387 if (r_type
>= (unsigned int) R_M68HC11_max
)
389 /* xgettext:c-format */
390 _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
392 bfd_set_error (bfd_error_bad_value
);
395 cache_ptr
->howto
= &elf_m68hc11_howto_table
[r_type
];
400 /* Far trampoline generation. */
402 /* Build a 68HC11 trampoline stub. */
404 m68hc11_elf_build_one_stub (struct bfd_hash_entry
*gen_entry
, void *in_arg
)
406 struct elf32_m68hc11_stub_hash_entry
*stub_entry
;
407 struct bfd_link_info
*info
;
408 struct m68hc11_elf_link_hash_table
*htab
;
412 bfd_vma sym_value
, phys_page
, phys_addr
;
414 /* Massage our args to the form they really have. */
415 stub_entry
= (struct elf32_m68hc11_stub_hash_entry
*) gen_entry
;
416 info
= (struct bfd_link_info
*) in_arg
;
418 htab
= m68hc11_elf_hash_table (info
);
422 stub_sec
= stub_entry
->stub_sec
;
424 /* Make a note of the offset within the stubs for this entry. */
425 stub_entry
->stub_offset
= stub_sec
->size
;
426 stub_sec
->size
+= 10;
427 loc
= stub_sec
->contents
+ stub_entry
->stub_offset
;
429 stub_bfd
= stub_sec
->owner
;
431 /* Create the trampoline call stub:
439 sym_value
= (stub_entry
->target_value
440 + stub_entry
->target_section
->output_offset
441 + stub_entry
->target_section
->output_section
->vma
);
442 phys_addr
= m68hc11_phys_addr (&htab
->pinfo
, sym_value
);
443 phys_page
= m68hc11_phys_page (&htab
->pinfo
, sym_value
);
445 /* pshb; ldab #%page(sym) */
446 bfd_put_8 (stub_bfd
, 0x37, loc
);
447 bfd_put_8 (stub_bfd
, 0xC6, loc
+ 1);
448 bfd_put_8 (stub_bfd
, phys_page
, loc
+ 2);
451 /* ldy #%addr(sym) */
452 bfd_put_8 (stub_bfd
, 0x18, loc
);
453 bfd_put_8 (stub_bfd
, 0xCE, loc
+ 1);
454 bfd_put_16 (stub_bfd
, phys_addr
, loc
+ 2);
457 /* jmp __trampoline */
458 bfd_put_8 (stub_bfd
, 0x7E, loc
);
459 bfd_put_16 (stub_bfd
, htab
->pinfo
.trampoline_addr
, loc
+ 1);
464 /* As above, but don't actually build the stub. Just bump offset so
465 we know stub section sizes. */
468 m68hc11_elf_size_one_stub (struct bfd_hash_entry
*gen_entry
,
469 void *in_arg ATTRIBUTE_UNUSED
)
471 struct elf32_m68hc11_stub_hash_entry
*stub_entry
;
473 /* Massage our args to the form they really have. */
474 stub_entry
= (struct elf32_m68hc11_stub_hash_entry
*) gen_entry
;
476 stub_entry
->stub_sec
->size
+= 10;
480 /* Create a 68HC11 ELF linker hash table. */
482 static struct bfd_link_hash_table
*
483 m68hc11_elf_bfd_link_hash_table_create (bfd
*abfd
)
485 struct m68hc11_elf_link_hash_table
*ret
;
487 ret
= m68hc11_elf_hash_table_create (abfd
);
488 if (ret
== (struct m68hc11_elf_link_hash_table
*) NULL
)
491 ret
->size_one_stub
= m68hc11_elf_size_one_stub
;
492 ret
->build_one_stub
= m68hc11_elf_build_one_stub
;
494 return &ret
->root
.root
;
498 /* 68HC11 Linker Relaxation. */
500 struct m68hc11_direct_relax
504 unsigned char direct_code
;
505 } m68hc11_direct_relax_table
[] = {
506 { "adca", 0xB9, 0x99 },
507 { "adcb", 0xF9, 0xD9 },
508 { "adda", 0xBB, 0x9B },
509 { "addb", 0xFB, 0xDB },
510 { "addd", 0xF3, 0xD3 },
511 { "anda", 0xB4, 0x94 },
512 { "andb", 0xF4, 0xD4 },
513 { "cmpa", 0xB1, 0x91 },
514 { "cmpb", 0xF1, 0xD1 },
515 { "cpd", 0xB3, 0x93 },
516 { "cpxy", 0xBC, 0x9C },
517 /* { "cpy", 0xBC, 0x9C }, */
518 { "eora", 0xB8, 0x98 },
519 { "eorb", 0xF8, 0xD8 },
520 { "jsr", 0xBD, 0x9D },
521 { "ldaa", 0xB6, 0x96 },
522 { "ldab", 0xF6, 0xD6 },
523 { "ldd", 0xFC, 0xDC },
524 { "lds", 0xBE, 0x9E },
525 { "ldxy", 0xFE, 0xDE },
526 /* { "ldy", 0xFE, 0xDE },*/
527 { "oraa", 0xBA, 0x9A },
528 { "orab", 0xFA, 0xDA },
529 { "sbca", 0xB2, 0x92 },
530 { "sbcb", 0xF2, 0xD2 },
531 { "staa", 0xB7, 0x97 },
532 { "stab", 0xF7, 0xD7 },
533 { "std", 0xFD, 0xDD },
534 { "sts", 0xBF, 0x9F },
535 { "stxy", 0xFF, 0xDF },
536 /* { "sty", 0xFF, 0xDF },*/
537 { "suba", 0xB0, 0x90 },
538 { "subb", 0xF0, 0xD0 },
539 { "subd", 0xB3, 0x93 },
543 static struct m68hc11_direct_relax
*
544 find_relaxable_insn (unsigned char code
)
548 for (i
= 0; m68hc11_direct_relax_table
[i
].name
; i
++)
549 if (m68hc11_direct_relax_table
[i
].code
== code
)
550 return &m68hc11_direct_relax_table
[i
];
556 compare_reloc (const void *e1
, const void *e2
)
558 const Elf_Internal_Rela
*i1
= (const Elf_Internal_Rela
*) e1
;
559 const Elf_Internal_Rela
*i2
= (const Elf_Internal_Rela
*) e2
;
561 if (i1
->r_offset
== i2
->r_offset
)
564 return i1
->r_offset
< i2
->r_offset
? -1 : 1;
567 #define M6811_OP_LDX_IMMEDIATE (0xCE)
570 m68hc11_relax_group (bfd
*abfd
, asection
*sec
, bfd_byte
*contents
,
571 unsigned value
, unsigned long offset
,
572 unsigned long end_group
)
575 unsigned long start_offset
;
576 unsigned long ldx_offset
= offset
;
577 unsigned long ldx_size
;
581 /* First instruction of the relax group must be a
582 LDX #value or LDY #value. If this is not the case,
583 ignore the relax group. */
584 code
= bfd_get_8 (abfd
, contents
+ offset
);
589 code
= bfd_get_8 (abfd
, contents
+ offset
);
591 ldx_size
= offset
- ldx_offset
+ 3;
593 if (code
!= M6811_OP_LDX_IMMEDIATE
|| offset
>= end_group
)
597 /* We can remove the LDX/LDY only when all bset/brclr instructions
598 of the relax group have been converted to use direct addressing
601 while (offset
< end_group
)
608 start_offset
= offset
;
609 code
= bfd_get_8 (abfd
, contents
+ offset
);
614 code
= bfd_get_8 (abfd
, contents
+ offset
);
617 /* Check the instruction and translate to use direct addressing mode. */
644 /* This instruction is not recognized and we are not
645 at end of the relax group. Ignore and don't remove
646 the first LDX (we don't know what it is used for...). */
650 new_value
= (unsigned) bfd_get_8 (abfd
, contents
+ offset
+ 1);
652 if ((new_value
& 0xff00) == 0 && bset_use_y
== relax_ldy
)
654 bfd_put_8 (abfd
, code
, contents
+ offset
);
655 bfd_put_8 (abfd
, new_value
, contents
+ offset
+ 1);
656 if (start_offset
!= offset
)
658 m68hc11_elf_relax_delete_bytes (abfd
, sec
, start_offset
,
659 offset
- start_offset
);
667 offset
= start_offset
+ isize
;
671 /* Remove the move instruction (3 or 4 bytes win). */
672 m68hc11_elf_relax_delete_bytes (abfd
, sec
, ldx_offset
, ldx_size
);
676 /* This function handles relaxing for the 68HC11.
679 and somewhat more difficult to support. */
682 m68hc11_elf_relax_section (bfd
*abfd
, asection
*sec
,
683 struct bfd_link_info
*link_info
, bfd_boolean
*again
)
685 Elf_Internal_Shdr
*symtab_hdr
;
686 Elf_Internal_Rela
*internal_relocs
;
687 Elf_Internal_Rela
*free_relocs
= NULL
;
688 Elf_Internal_Rela
*irel
, *irelend
;
689 bfd_byte
*contents
= NULL
;
690 bfd_byte
*free_contents
= NULL
;
691 Elf32_External_Sym
*free_extsyms
= NULL
;
692 Elf_Internal_Rela
*prev_insn_branch
= NULL
;
693 Elf_Internal_Rela
*prev_insn_group
= NULL
;
694 unsigned insn_group_value
= 0;
695 Elf_Internal_Sym
*isymbuf
= NULL
;
697 /* Assume nothing changes. */
700 /* We don't have to do anything for a relocatable link, if
701 this section does not have relocs, or if this is not a
703 if (bfd_link_relocatable (link_info
)
704 || (sec
->flags
& SEC_RELOC
) == 0
705 || sec
->reloc_count
== 0
706 || (sec
->flags
& SEC_CODE
) == 0)
709 symtab_hdr
= &elf_tdata (abfd
)->symtab_hdr
;
711 /* Get a copy of the native relocations. */
712 internal_relocs
= (_bfd_elf_link_read_relocs
713 (abfd
, sec
, NULL
, (Elf_Internal_Rela
*) NULL
,
714 link_info
->keep_memory
));
715 if (internal_relocs
== NULL
)
717 if (! link_info
->keep_memory
)
718 free_relocs
= internal_relocs
;
720 /* Checking for branch relaxation relies on the relocations to
721 be sorted on 'r_offset'. This is not guaranteed so we must sort. */
722 qsort (internal_relocs
, sec
->reloc_count
, sizeof (Elf_Internal_Rela
),
725 /* Walk through them looking for relaxing opportunities. */
726 irelend
= internal_relocs
+ sec
->reloc_count
;
727 for (irel
= internal_relocs
; irel
< irelend
; irel
++)
731 Elf_Internal_Sym
*isym
;
735 /* If this isn't something that can be relaxed, then ignore
737 if (ELF32_R_TYPE (irel
->r_info
) != (int) R_M68HC11_16
738 && ELF32_R_TYPE (irel
->r_info
) != (int) R_M68HC11_RL_JUMP
739 && ELF32_R_TYPE (irel
->r_info
) != (int) R_M68HC11_RL_GROUP
)
741 prev_insn_branch
= 0;
746 /* Get the section contents if we haven't done so already. */
747 if (contents
== NULL
)
749 /* Get cached copy if it exists. */
750 if (elf_section_data (sec
)->this_hdr
.contents
!= NULL
)
751 contents
= elf_section_data (sec
)->this_hdr
.contents
;
754 /* Go get them off disk. */
755 if (!bfd_malloc_and_get_section (abfd
, sec
, &contents
))
760 /* Try to eliminate an unconditional 8 bit pc-relative branch
761 which immediately follows a conditional 8 bit pc-relative
762 branch around the unconditional branch.
769 This happens when the bCC can't reach lab2 at assembly time,
770 but due to other relaxations it can reach at link time. */
771 if (ELF32_R_TYPE (irel
->r_info
) == (int) R_M68HC11_RL_JUMP
)
773 Elf_Internal_Rela
*nrel
;
775 unsigned char roffset
;
777 prev_insn_branch
= 0;
780 /* Do nothing if this reloc is the last byte in the section. */
781 if (irel
->r_offset
+ 2 >= sec
->size
)
784 /* See if the next instruction is an unconditional pc-relative
785 branch, more often than not this test will fail, so we
786 test it first to speed things up. */
787 code
= bfd_get_8 (abfd
, contents
+ irel
->r_offset
+ 2);
791 /* Also make sure the next relocation applies to the next
792 instruction and that it's a pc-relative 8 bit branch. */
795 || irel
->r_offset
+ 3 != nrel
->r_offset
796 || ELF32_R_TYPE (nrel
->r_info
) != (int) R_M68HC11_16
)
799 /* Make sure our destination immediately follows the
800 unconditional branch. */
801 roffset
= bfd_get_8 (abfd
, contents
+ irel
->r_offset
+ 1);
805 prev_insn_branch
= irel
;
810 /* Read this BFD's symbols if we haven't done so already. */
811 if (isymbuf
== NULL
&& symtab_hdr
->sh_info
!= 0)
813 isymbuf
= (Elf_Internal_Sym
*) symtab_hdr
->contents
;
815 isymbuf
= bfd_elf_get_elf_syms (abfd
, symtab_hdr
,
816 symtab_hdr
->sh_info
, 0,
822 /* Get the value of the symbol referred to by the reloc. */
823 if (ELF32_R_SYM (irel
->r_info
) < symtab_hdr
->sh_info
)
825 /* A local symbol. */
826 isym
= isymbuf
+ ELF32_R_SYM (irel
->r_info
);
827 is_far
= isym
->st_other
& STO_M68HC12_FAR
;
828 sym_sec
= bfd_section_from_elf_index (abfd
, isym
->st_shndx
);
829 symval
= (isym
->st_value
830 + sym_sec
->output_section
->vma
831 + sym_sec
->output_offset
);
836 struct elf_link_hash_entry
*h
;
838 /* An external symbol. */
839 indx
= ELF32_R_SYM (irel
->r_info
) - symtab_hdr
->sh_info
;
840 h
= elf_sym_hashes (abfd
)[indx
];
841 BFD_ASSERT (h
!= NULL
);
842 if (h
->root
.type
!= bfd_link_hash_defined
843 && h
->root
.type
!= bfd_link_hash_defweak
)
845 /* This appears to be a reference to an undefined
846 symbol. Just ignore it--it will be caught by the
847 regular reloc processing. */
848 prev_insn_branch
= 0;
853 is_far
= h
->other
& STO_M68HC12_FAR
;
855 sym_sec
= h
->root
.u
.def
.section
;
856 symval
= (h
->root
.u
.def
.value
857 + sym_sec
->output_section
->vma
858 + sym_sec
->output_offset
);
861 if (ELF32_R_TYPE (irel
->r_info
) == (int) R_M68HC11_RL_GROUP
)
863 prev_insn_branch
= 0;
866 /* Do nothing if this reloc is the last byte in the section. */
867 if (irel
->r_offset
== sec
->size
)
870 prev_insn_group
= irel
;
871 insn_group_value
= isym
->st_value
;
875 /* When we relax some bytes, the size of our section changes.
876 This affects the layout of next input sections that go in our
877 output section. When the symbol is part of another section that
878 will go in the same output section as the current one, it's
879 final address may now be incorrect (too far). We must let the
880 linker re-compute all section offsets before processing this
884 .sect .text section size = 6 section size = 4
887 .sect .text.foo_bar output_offset = 6 output_offset = 4
891 If we process the reloc now, the jmp bar is replaced by a
892 relative branch to the initial bar address (output_offset 6). */
893 if (*again
&& sym_sec
!= sec
894 && sym_sec
->output_section
== sec
->output_section
)
897 prev_insn_branch
= 0;
902 /* Try to turn a far branch to a near branch. */
903 if (ELF32_R_TYPE (irel
->r_info
) == (int) R_M68HC11_16
909 offset
= value
- (prev_insn_branch
->r_offset
910 + sec
->output_section
->vma
911 + sec
->output_offset
+ 2);
913 /* If the offset is still out of -128..+127 range,
914 leave that far branch unchanged. */
915 if ((offset
& 0xff80) != 0 && (offset
& 0xff80) != 0xff80)
917 prev_insn_branch
= 0;
921 /* Shrink the branch. */
922 code
= bfd_get_8 (abfd
, contents
+ prev_insn_branch
->r_offset
);
926 bfd_put_8 (abfd
, code
, contents
+ prev_insn_branch
->r_offset
);
927 bfd_put_8 (abfd
, 0xff,
928 contents
+ prev_insn_branch
->r_offset
+ 1);
929 irel
->r_offset
= prev_insn_branch
->r_offset
+ 1;
930 irel
->r_info
= ELF32_R_INFO (ELF32_R_SYM (irel
->r_info
),
932 m68hc11_elf_relax_delete_bytes (abfd
, sec
,
933 irel
->r_offset
+ 1, 1);
938 bfd_put_8 (abfd
, code
, contents
+ prev_insn_branch
->r_offset
);
939 bfd_put_8 (abfd
, 0xff,
940 contents
+ prev_insn_branch
->r_offset
+ 1);
941 irel
->r_offset
= prev_insn_branch
->r_offset
+ 1;
942 irel
->r_info
= ELF32_R_INFO (ELF32_R_SYM (irel
->r_info
),
944 m68hc11_elf_relax_delete_bytes (abfd
, sec
,
945 irel
->r_offset
+ 1, 3);
947 prev_insn_branch
= 0;
951 /* Try to turn a 16 bit address into a 8 bit page0 address. */
952 else if (ELF32_R_TYPE (irel
->r_info
) == (int) R_M68HC11_16
953 && (value
& 0xff00) == 0)
956 unsigned short offset
;
957 struct m68hc11_direct_relax
*rinfo
;
959 prev_insn_branch
= 0;
960 offset
= bfd_get_16 (abfd
, contents
+ irel
->r_offset
);
962 if ((offset
& 0xff00) != 0)
970 unsigned long old_sec_size
= sec
->size
;
972 /* Note that we've changed the relocation contents, etc. */
973 elf_section_data (sec
)->relocs
= internal_relocs
;
976 elf_section_data (sec
)->this_hdr
.contents
= contents
;
977 free_contents
= NULL
;
979 symtab_hdr
->contents
= (bfd_byte
*) isymbuf
;
982 m68hc11_relax_group (abfd
, sec
, contents
, offset
,
983 prev_insn_group
->r_offset
,
985 irel
= prev_insn_group
;
987 irel
->r_info
= ELF32_R_INFO (ELF32_R_SYM (irel
->r_info
),
989 if (sec
->size
!= old_sec_size
)
994 /* Get the opcode. */
995 code
= bfd_get_8 (abfd
, contents
+ irel
->r_offset
- 1);
996 rinfo
= find_relaxable_insn (code
);
1003 /* Note that we've changed the relocation contents, etc. */
1004 elf_section_data (sec
)->relocs
= internal_relocs
;
1007 elf_section_data (sec
)->this_hdr
.contents
= contents
;
1008 free_contents
= NULL
;
1010 symtab_hdr
->contents
= (bfd_byte
*) isymbuf
;
1011 free_extsyms
= NULL
;
1013 /* Fix the opcode. */
1014 /* printf ("A relaxable case : 0x%02x (%s)\n",
1015 code, rinfo->name); */
1016 bfd_put_8 (abfd
, rinfo
->direct_code
,
1017 contents
+ irel
->r_offset
- 1);
1019 /* Delete one byte of data (upper byte of address). */
1020 m68hc11_elf_relax_delete_bytes (abfd
, sec
, irel
->r_offset
, 1);
1022 /* Fix the relocation's type. */
1023 irel
->r_info
= ELF32_R_INFO (ELF32_R_SYM (irel
->r_info
),
1026 /* That will change things, so, we should relax again. */
1029 else if (ELF32_R_TYPE (irel
->r_info
) == R_M68HC11_16
&& !is_far
)
1034 prev_insn_branch
= 0;
1035 code
= bfd_get_8 (abfd
, contents
+ irel
->r_offset
- 1);
1036 if (code
== 0x7e || code
== 0xbd)
1038 offset
= value
- (irel
->r_offset
1039 + sec
->output_section
->vma
1040 + sec
->output_offset
+ 1);
1041 offset
+= bfd_get_16 (abfd
, contents
+ irel
->r_offset
);
1043 /* If the offset is still out of -128..+127 range,
1044 leave that far branch unchanged. */
1045 if ((offset
& 0xff80) == 0 || (offset
& 0xff80) == 0xff80)
1048 /* Note that we've changed the relocation contents, etc. */
1049 elf_section_data (sec
)->relocs
= internal_relocs
;
1052 elf_section_data (sec
)->this_hdr
.contents
= contents
;
1053 free_contents
= NULL
;
1055 symtab_hdr
->contents
= (bfd_byte
*) isymbuf
;
1056 free_extsyms
= NULL
;
1058 /* Shrink the branch. */
1059 code
= (code
== 0x7e) ? 0x20 : 0x8d;
1060 bfd_put_8 (abfd
, code
,
1061 contents
+ irel
->r_offset
- 1);
1062 bfd_put_8 (abfd
, 0xff,
1063 contents
+ irel
->r_offset
);
1064 irel
->r_info
= ELF32_R_INFO (ELF32_R_SYM (irel
->r_info
),
1066 m68hc11_elf_relax_delete_bytes (abfd
, sec
,
1067 irel
->r_offset
+ 1, 1);
1068 /* That will change things, so, we should relax again. */
1073 prev_insn_branch
= 0;
1074 prev_insn_group
= 0;
1077 if (free_relocs
!= NULL
)
1083 if (free_contents
!= NULL
)
1085 if (! link_info
->keep_memory
)
1086 free (free_contents
);
1089 /* Cache the section contents for elf_link_input_bfd. */
1090 elf_section_data (sec
)->this_hdr
.contents
= contents
;
1092 free_contents
= NULL
;
1095 if (free_extsyms
!= NULL
)
1097 if (! link_info
->keep_memory
)
1098 free (free_extsyms
);
1101 /* Cache the symbols for elf_link_input_bfd. */
1102 symtab_hdr
->contents
= (unsigned char *) isymbuf
;
1104 free_extsyms
= NULL
;
1110 if (free_relocs
!= NULL
)
1112 if (free_contents
!= NULL
)
1113 free (free_contents
);
1114 if (free_extsyms
!= NULL
)
1115 free (free_extsyms
);
1119 /* Delete some bytes from a section while relaxing. */
1122 m68hc11_elf_relax_delete_bytes (bfd
*abfd
, asection
*sec
,
1123 bfd_vma addr
, int count
)
1125 Elf_Internal_Shdr
*symtab_hdr
;
1126 unsigned int sec_shndx
;
1128 Elf_Internal_Rela
*irel
, *irelend
;
1130 Elf_Internal_Sym
*isymbuf
, *isym
, *isymend
;
1131 struct elf_link_hash_entry
**sym_hashes
;
1132 struct elf_link_hash_entry
**end_hashes
;
1133 unsigned int symcount
;
1135 symtab_hdr
= &elf_tdata (abfd
)->symtab_hdr
;
1136 isymbuf
= (Elf_Internal_Sym
*) symtab_hdr
->contents
;
1138 sec_shndx
= _bfd_elf_section_from_bfd_section (abfd
, sec
);
1140 contents
= elf_section_data (sec
)->this_hdr
.contents
;
1144 irel
= elf_section_data (sec
)->relocs
;
1145 irelend
= irel
+ sec
->reloc_count
;
1147 /* Actually delete the bytes. */
1148 memmove (contents
+ addr
, contents
+ addr
+ count
,
1149 (size_t) (toaddr
- addr
- count
));
1153 /* Adjust all the relocs. */
1154 for (irel
= elf_section_data (sec
)->relocs
; irel
< irelend
; irel
++)
1157 unsigned char offset
;
1158 unsigned short raddr
;
1159 unsigned long old_offset
;
1162 old_offset
= irel
->r_offset
;
1164 /* See if this reloc was for the bytes we have deleted, in which
1165 case we no longer care about it. Don't delete relocs which
1166 represent addresses, though. */
1167 if (ELF32_R_TYPE (irel
->r_info
) != R_M68HC11_RL_JUMP
1168 && irel
->r_offset
>= addr
&& irel
->r_offset
< addr
+ count
)
1169 irel
->r_info
= ELF32_R_INFO (ELF32_R_SYM (irel
->r_info
),
1172 if (ELF32_R_TYPE (irel
->r_info
) == R_M68HC11_NONE
)
1175 /* Get the new reloc address. */
1176 if ((irel
->r_offset
> addr
1177 && irel
->r_offset
< toaddr
))
1178 irel
->r_offset
-= count
;
1180 /* If this is a PC relative reloc, see if the range it covers
1181 includes the bytes we have deleted. */
1182 switch (ELF32_R_TYPE (irel
->r_info
))
1187 case R_M68HC11_RL_JUMP
:
1188 code
= bfd_get_8 (abfd
, contents
+ irel
->r_offset
);
1191 /* jsr and jmp instruction are also marked with RL_JUMP
1192 relocs but no adjustment must be made. */
1203 /* Special case when we translate a brclr N,y into brclr *<addr>
1204 In this case, the 0x18 page2 prefix is removed.
1205 The reloc offset is not modified but the instruction
1206 size is reduced by 1. */
1207 if (old_offset
== addr
)
1227 offset
= bfd_get_8 (abfd
, contents
+ irel
->r_offset
+ branch_pos
);
1228 raddr
+= old_offset
;
1229 raddr
+= ((unsigned short) offset
| ((offset
& 0x80) ? 0xff00 : 0));
1230 if (irel
->r_offset
< addr
&& raddr
> addr
)
1233 bfd_put_8 (abfd
, offset
, contents
+ irel
->r_offset
+ branch_pos
);
1235 else if (irel
->r_offset
>= addr
&& raddr
<= addr
)
1238 bfd_put_8 (abfd
, offset
, contents
+ irel
->r_offset
+ branch_pos
);
1242 /*printf ("Not adjusted 0x%04x [0x%4x 0x%4x]\n", raddr,
1243 irel->r_offset, addr);*/
1250 /* Adjust the local symbols defined in this section. */
1251 isymend
= isymbuf
+ symtab_hdr
->sh_info
;
1252 for (isym
= isymbuf
; isym
< isymend
; isym
++)
1254 if (isym
->st_shndx
== sec_shndx
1255 && isym
->st_value
> addr
1256 && isym
->st_value
<= toaddr
)
1257 isym
->st_value
-= count
;
1260 /* Now adjust the global symbols defined in this section. */
1261 symcount
= (symtab_hdr
->sh_size
/ sizeof (Elf32_External_Sym
)
1262 - symtab_hdr
->sh_info
);
1263 sym_hashes
= elf_sym_hashes (abfd
);
1264 end_hashes
= sym_hashes
+ symcount
;
1265 for (; sym_hashes
< end_hashes
; sym_hashes
++)
1267 struct elf_link_hash_entry
*sym_hash
= *sym_hashes
;
1268 if ((sym_hash
->root
.type
== bfd_link_hash_defined
1269 || sym_hash
->root
.type
== bfd_link_hash_defweak
)
1270 && sym_hash
->root
.u
.def
.section
== sec
1271 && sym_hash
->root
.u
.def
.value
> addr
1272 && sym_hash
->root
.u
.def
.value
<= toaddr
)
1274 sym_hash
->root
.u
.def
.value
-= count
;
1279 /* Specific sections:
1280 - The .page0 is a data section that is mapped in [0x0000..0x00FF].
1281 Page0 accesses are faster on the M68HC11. Soft registers used by GCC-m6811
1282 are located in .page0.
1283 - The .vectors is the section that represents the interrupt
1285 static const struct bfd_elf_special_section elf32_m68hc11_special_sections
[] =
1287 { STRING_COMMA_LEN (".eeprom"), 0, SHT_PROGBITS
, SHF_ALLOC
+ SHF_WRITE
},
1288 { STRING_COMMA_LEN (".page0"), 0, SHT_PROGBITS
, SHF_ALLOC
+ SHF_WRITE
},
1289 { STRING_COMMA_LEN (".softregs"), 0, SHT_NOBITS
, SHF_ALLOC
+ SHF_WRITE
},
1290 { STRING_COMMA_LEN (".vectors"), 0, SHT_PROGBITS
, SHF_ALLOC
},
1291 { NULL
, 0, 0, 0, 0 }
1294 #define ELF_ARCH bfd_arch_m68hc11
1295 #define ELF_TARGET_ID M68HC11_ELF_DATA
1296 #define ELF_MACHINE_CODE EM_68HC11
1297 #define ELF_MAXPAGESIZE 0x1000
1299 #define TARGET_BIG_SYM m68hc11_elf32_vec
1300 #define TARGET_BIG_NAME "elf32-m68hc11"
1302 #define elf_info_to_howto NULL
1303 #define elf_info_to_howto_rel m68hc11_info_to_howto_rel
1304 #define bfd_elf32_bfd_relax_section m68hc11_elf_relax_section
1305 #define elf_backend_check_relocs elf32_m68hc11_check_relocs
1306 #define elf_backend_relocate_section elf32_m68hc11_relocate_section
1307 #define elf_backend_add_symbol_hook elf32_m68hc11_add_symbol_hook
1308 #define elf_backend_object_p 0
1309 #define elf_backend_final_write_processing 0
1310 #define elf_backend_can_gc_sections 1
1311 #define elf_backend_special_sections elf32_m68hc11_special_sections
1312 #define elf_backend_merge_symbol_attribute elf32_m68hc11_merge_symbol_attribute
1314 #define bfd_elf32_bfd_link_hash_table_create \
1315 m68hc11_elf_bfd_link_hash_table_create
1316 #define bfd_elf32_bfd_merge_private_bfd_data \
1317 _bfd_m68hc11_elf_merge_private_bfd_data
1318 #define bfd_elf32_bfd_set_private_flags _bfd_m68hc11_elf_set_private_flags
1319 #define bfd_elf32_bfd_print_private_bfd_data \
1320 _bfd_m68hc11_elf_print_private_bfd_data
1322 #include "elf32-target.h"