1250199Sgrehan/* Motorola 68HC11-specific support for 32-bit ELF 2324461Ssephe Copyright (C) 1999-2022 Free Software Foundation, Inc. 3250199Sgrehan Contributed by Stephane Carrez (stcarrez@nerim.fr) 4250199Sgrehan (Heavily copied from the D10V port by Martin Hunt (hunt@cygnus.com)) 5250199Sgrehan 6250199Sgrehan This file is part of BFD, the Binary File Descriptor library. 7250199Sgrehan 8250199Sgrehan This program is free software; you can redistribute it and/or modify 9250199Sgrehan it under the terms of the GNU General Public License as published by 10250199Sgrehan the Free Software Foundation; either version 3 of the License, or 11250199Sgrehan (at your option) any later version. 12250199Sgrehan 13250199Sgrehan This program is distributed in the hope that it will be useful, 14250199Sgrehan but WITHOUT ANY WARRANTY; without even the implied warranty of 15250199Sgrehan MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16250199Sgrehan GNU General Public License for more details. 17250199Sgrehan 18250199Sgrehan You should have received a copy of the GNU General Public License 19250199Sgrehan along with this program; if not, write to the Free Software 20250199Sgrehan Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 21250199Sgrehan MA 02110-1301, USA. */ 22250199Sgrehan 23250199Sgrehan#include "sysdep.h" 24250199Sgrehan#include "bfd.h" 25250199Sgrehan#include "bfdlink.h" 26250199Sgrehan#include "libbfd.h" 27250199Sgrehan#include "elf-bfd.h" 28250199Sgrehan#include "elf32-m68hc1x.h" 29308504Ssephe#include "elf/m68hc11.h" 30308504Ssephe#include "opcode/m68hc11.h" 31250199Sgrehan 32250199Sgrehan/* Relocation functions. */ 33308504Ssephestatic reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup 34308504Ssephe (bfd *, bfd_reloc_code_real_type); 35250199Sgrehanstatic bool m68hc11_info_to_howto_rel 36308504Ssephe (bfd *, arelent *, Elf_Internal_Rela *); 37308504Ssephe 38308504Ssephe/* Trampoline generation. */ 39250199Sgrehanstatic bool m68hc11_elf_size_one_stub 40250199Sgrehan (struct bfd_hash_entry *gen_entry, void *in_arg); 41308504Ssephestatic bool m68hc11_elf_build_one_stub 42250199Sgrehan (struct bfd_hash_entry *gen_entry, void *in_arg); 43308504Ssephestatic struct bfd_link_hash_table* m68hc11_elf_bfd_link_hash_table_create 44308504Ssephe (bfd* abfd); 45308504Ssephe 46324466Ssephe/* Linker relaxation. */ 47250199Sgrehanstatic bool m68hc11_elf_relax_section 48250199Sgrehan (bfd *, asection *, struct bfd_link_info *, bool *); 49308504Ssephestatic void m68hc11_elf_relax_delete_bytes 50250199Sgrehan (bfd *, asection *, bfd_vma, int); 51308504Ssephestatic void m68hc11_relax_group 52308504Ssephe (bfd *, asection *, bfd_byte *, unsigned, unsigned long, unsigned long); 53308504Ssephestatic int compare_reloc (const void *, const void *); 54250199Sgrehan 55308504Ssephe/* Use REL instead of RELA to save space */ 56308504Ssephe#define USE_REL 1 57307164Ssephe 58308504Ssephe/* The Motorola 68HC11 microcontroller only addresses 64Kb but we also 59308504Ssephe support a memory bank switching mechanism similar to 68HC12. 60307164Ssephe We must handle 8 and 16-bit relocations. The 32-bit relocation 61307199Ssephe are used for debugging sections (DWARF2) to represent a virtual 62308505Ssephe address. 63250199Sgrehan The 3-bit and 16-bit PC rel relocation is only used by 68HC12. */ 64308504Ssephestatic reloc_howto_type elf_m68hc11_howto_table[] = { 65308504Ssephe /* This reloc does nothing. */ 66310757Ssephe HOWTO (R_M68HC11_NONE, /* type */ 67310757Ssephe 0, /* rightshift */ 68308504Ssephe 0, /* size */ 69308504Ssephe 0, /* bitsize */ 70308504Ssephe false, /* pc_relative */ 71308504Ssephe 0, /* bitpos */ 72308504Ssephe complain_overflow_dont,/* complain_on_overflow */ 73308504Ssephe bfd_elf_generic_reloc, /* special_function */ 74308504Ssephe "R_M68HC11_NONE", /* name */ 75308504Ssephe false, /* partial_inplace */ 76308504Ssephe 0, /* src_mask */ 77308504Ssephe 0, /* dst_mask */ 78250199Sgrehan false), /* pcrel_offset */ 79308504Ssephe 80308504Ssephe /* A 8 bit absolute relocation */ 81307161Ssephe HOWTO (R_M68HC11_8, /* type */ 82307200Ssephe 0, /* rightshift */ 83307200Ssephe 1, /* size */ 84307200Ssephe 8, /* bitsize */ 85307200Ssephe false, /* pc_relative */ 86307200Ssephe 0, /* bitpos */ 87307200Ssephe complain_overflow_bitfield, /* complain_on_overflow */ 88307200Ssephe bfd_elf_generic_reloc, /* special_function */ 89307206Ssephe "R_M68HC11_8", /* name */ 90307174Ssephe false, /* partial_inplace */ 91307186Ssephe 0x00ff, /* src_mask */ 92285236Swhu 0x00ff, /* dst_mask */ 93308504Ssephe false), /* pcrel_offset */ 94307186Ssephe 95307186Ssephe /* A 8 bit absolute relocation (upper address) */ 96307174Ssephe HOWTO (R_M68HC11_HI8, /* type */ 97285236Swhu 8, /* rightshift */ 98307186Ssephe 1, /* size */ 99307186Ssephe 8, /* bitsize */ 100307186Ssephe false, /* pc_relative */ 101307186Ssephe 0, /* bitpos */ 102307186Ssephe complain_overflow_bitfield, /* complain_on_overflow */ 103307186Ssephe bfd_elf_generic_reloc, /* special_function */ 104308504Ssephe "R_M68HC11_HI8", /* name */ 105307186Ssephe false, /* partial_inplace */ 106307174Ssephe 0x00ff, /* src_mask */ 107307174Ssephe 0x00ff, /* dst_mask */ 108307174Ssephe false), /* pcrel_offset */ 109307174Ssephe 110307174Ssephe /* A 8 bit absolute relocation (upper address) */ 111307186Ssephe HOWTO (R_M68HC11_LO8, /* type */ 112307174Ssephe 0, /* rightshift */ 113310757Ssephe 1, /* size */ 114310757Ssephe 8, /* bitsize */ 115307186Ssephe false, /* pc_relative */ 116307186Ssephe 0, /* bitpos */ 117307186Ssephe complain_overflow_dont, /* complain_on_overflow */ 118307186Ssephe bfd_elf_generic_reloc, /* special_function */ 119307186Ssephe "R_M68HC11_LO8", /* name */ 120307186Ssephe false, /* partial_inplace */ 121307186Ssephe 0x00ff, /* src_mask */ 122307186Ssephe 0x00ff, /* dst_mask */ 123307186Ssephe false), /* pcrel_offset */ 124307186Ssephe 125307186Ssephe /* A 8 bit PC-rel relocation */ 126307186Ssephe HOWTO (R_M68HC11_PCREL_8, /* type */ 127307186Ssephe 0, /* rightshift */ 128307186Ssephe 1, /* size */ 129307186Ssephe 8, /* bitsize */ 130307186Ssephe true, /* pc_relative */ 131307174Ssephe 0, /* bitpos */ 132285236Swhu complain_overflow_bitfield, /* complain_on_overflow */ 133307174Ssephe bfd_elf_generic_reloc, /* special_function */ 134307174Ssephe "R_M68HC11_PCREL_8", /* name */ 135307174Ssephe false, /* partial_inplace */ 136285236Swhu 0x00ff, /* src_mask */ 137307174Ssephe 0x00ff, /* dst_mask */ 138308504Ssephe true), /* pcrel_offset */ 139285236Swhu 140285236Swhu /* A 16 bit absolute relocation */ 141250199Sgrehan HOWTO (R_M68HC11_16, /* type */ 142307206Ssephe 0, /* rightshift */ 143250199Sgrehan 2, /* size */ 144307174Ssephe 16, /* bitsize */ 145307164Ssephe false, /* pc_relative */ 146307164Ssephe 0, /* bitpos */ 147307164Ssephe complain_overflow_dont /*bitfield */ , /* complain_on_overflow */ 148307164Ssephe bfd_elf_generic_reloc, /* special_function */ 149307200Ssephe "R_M68HC11_16", /* name */ 150250199Sgrehan false, /* partial_inplace */ 151307200Ssephe 0xffff, /* src_mask */ 152307200Ssephe 0xffff, /* dst_mask */ 153307200Ssephe false), /* pcrel_offset */ 154307200Ssephe 155308504Ssephe /* A 32 bit absolute relocation. This one is never used for the 156307200Ssephe code relocation. It's used by gas for -gstabs generation. */ 157308504Ssephe HOWTO (R_M68HC11_32, /* type */ 158250199Sgrehan 0, /* rightshift */ 159250199Sgrehan 4, /* size */ 160307081Ssephe 32, /* bitsize */ 161307081Ssephe false, /* pc_relative */ 162307081Ssephe 0, /* bitpos */ 163307081Ssephe complain_overflow_bitfield, /* complain_on_overflow */ 164307081Ssephe bfd_elf_generic_reloc, /* special_function */ 165250199Sgrehan "R_M68HC11_32", /* name */ 166307164Ssephe false, /* partial_inplace */ 167307174Ssephe 0xffffffff, /* src_mask */ 168307164Ssephe 0xffffffff, /* dst_mask */ 169307206Ssephe false), /* pcrel_offset */ 170307164Ssephe 171250199Sgrehan /* A 3 bit absolute relocation */ 172250199Sgrehan HOWTO (R_M68HC11_3B, /* type */ 173250199Sgrehan 0, /* rightshift */ 174307164Ssephe 1, /* size */ 175307164Ssephe 3, /* bitsize */ 176307164Ssephe false, /* pc_relative */ 177250199Sgrehan 0, /* bitpos */ 178307164Ssephe complain_overflow_bitfield, /* complain_on_overflow */ 179307164Ssephe bfd_elf_generic_reloc, /* special_function */ 180307164Ssephe "R_M68HC11_4B", /* name */ 181307164Ssephe false, /* partial_inplace */ 182307164Ssephe 0x003, /* src_mask */ 183307164Ssephe 0x003, /* dst_mask */ 184307164Ssephe false), /* pcrel_offset */ 185307164Ssephe 186307174Ssephe /* A 16 bit PC-rel relocation */ 187307164Ssephe HOWTO (R_M68HC11_PCREL_16, /* type */ 188250199Sgrehan 0, /* rightshift */ 189307186Ssephe 2, /* size */ 190307186Ssephe 16, /* bitsize */ 191307186Ssephe true, /* pc_relative */ 192307174Ssephe 0, /* bitpos */ 193307206Ssephe complain_overflow_dont, /* complain_on_overflow */ 194307174Ssephe bfd_elf_generic_reloc, /* special_function */ 195250199Sgrehan "R_M68HC11_PCREL_16", /* name */ 196250199Sgrehan false, /* partial_inplace */ 197250199Sgrehan 0xffff, /* src_mask */ 198307164Ssephe 0xffff, /* dst_mask */ 199307164Ssephe true), /* pcrel_offset */ 200307174Ssephe 201250199Sgrehan /* GNU extension to record C++ vtable hierarchy */ 202307164Ssephe HOWTO (R_M68HC11_GNU_VTINHERIT, /* type */ 203307206Ssephe 0, /* rightshift */ 204307164Ssephe 2, /* size */ 205250199Sgrehan 0, /* bitsize */ 206250199Sgrehan false, /* pc_relative */ 207307174Ssephe 0, /* bitpos */ 208250199Sgrehan complain_overflow_dont, /* complain_on_overflow */ 209307164Ssephe NULL, /* special_function */ 210250199Sgrehan "R_M68HC11_GNU_VTINHERIT", /* name */ 211250199Sgrehan false, /* partial_inplace */ 212307174Ssephe 0, /* src_mask */ 213307174Ssephe 0, /* dst_mask */ 214307206Ssephe false), /* pcrel_offset */ 215307164Ssephe 216250199Sgrehan /* GNU extension to record C++ vtable member usage */ 217250199Sgrehan HOWTO (R_M68HC11_GNU_VTENTRY, /* type */ 218250199Sgrehan 0, /* rightshift */ 219307206Ssephe 2, /* size */ 220250199Sgrehan 0, /* bitsize */ 221307174Ssephe false, /* pc_relative */ 222307164Ssephe 0, /* bitpos */ 223307164Ssephe complain_overflow_dont, /* complain_on_overflow */ 224307164Ssephe _bfd_elf_rel_vtable_reloc_fn, /* special_function */ 225307164Ssephe "R_M68HC11_GNU_VTENTRY", /* name */ 226307164Ssephe false, /* partial_inplace */ 227250199Sgrehan 0, /* src_mask */ 228250199Sgrehan 0, /* dst_mask */ 229307081Ssephe false), /* pcrel_offset */ 230307081Ssephe 231307081Ssephe /* A 24 bit relocation */ 232307081Ssephe HOWTO (R_M68HC11_24, /* type */ 233307081Ssephe 0, /* rightshift */ 234250199Sgrehan 2, /* size */ 235307164Ssephe 24, /* bitsize */ 236308504Ssephe false, /* pc_relative */ 237307164Ssephe 0, /* bitpos */ 238307206Ssephe complain_overflow_bitfield, /* complain_on_overflow */ 239250199Sgrehan bfd_elf_generic_reloc, /* special_function */ 240250199Sgrehan "R_M68HC11_24", /* name */ 241250199Sgrehan false, /* partial_inplace */ 242307164Ssephe 0xffffff, /* src_mask */ 243307164Ssephe 0xffffff, /* dst_mask */ 244307164Ssephe false), /* pcrel_offset */ 245250199Sgrehan 246307164Ssephe /* A 16-bit low relocation */ 247307164Ssephe HOWTO (R_M68HC11_LO16, /* type */ 248307164Ssephe 0, /* rightshift */ 249307164Ssephe 2, /* size */ 250307164Ssephe 16, /* bitsize */ 251307164Ssephe false, /* pc_relative */ 252307164Ssephe 0, /* bitpos */ 253307164Ssephe complain_overflow_bitfield, /* complain_on_overflow */ 254307174Ssephe bfd_elf_generic_reloc, /* special_function */ 255307164Ssephe "R_M68HC11_LO16", /* name */ 256250199Sgrehan false, /* partial_inplace */ 257307186Ssephe 0xffff, /* src_mask */ 258307186Ssephe 0xffff, /* dst_mask */ 259307186Ssephe false), /* pcrel_offset */ 260307174Ssephe 261307206Ssephe /* A page relocation */ 262307174Ssephe HOWTO (R_M68HC11_PAGE, /* type */ 263250199Sgrehan 0, /* rightshift */ 264250199Sgrehan 1, /* size */ 265250199Sgrehan 8, /* bitsize */ 266307164Ssephe false, /* pc_relative */ 267307164Ssephe 0, /* bitpos */ 268307164Ssephe complain_overflow_bitfield, /* complain_on_overflow */ 269307174Ssephe bfd_elf_generic_reloc, /* special_function */ 270307164Ssephe "R_M68HC11_PAGE", /* name */ 271307164Ssephe false, /* partial_inplace */ 272307206Ssephe 0x00ff, /* src_mask */ 273307164Ssephe 0x00ff, /* dst_mask */ 274250199Sgrehan false), /* pcrel_offset */ 275250199Sgrehan 276315437Ssephe EMPTY_HOWTO (14), 277310757Ssephe EMPTY_HOWTO (15), 278310757Ssephe EMPTY_HOWTO (16), 279310757Ssephe EMPTY_HOWTO (17), 280315437Ssephe EMPTY_HOWTO (18), 281315437Ssephe EMPTY_HOWTO (19), 282315437Ssephe 283315437Ssephe /* Mark beginning of a jump instruction (any form). */ 284315437Ssephe HOWTO (R_M68HC11_RL_JUMP, /* type */ 285315437Ssephe 0, /* rightshift */ 286315437Ssephe 2, /* size */ 287310757Ssephe 0, /* bitsize */ 288310757Ssephe false, /* pc_relative */ 289310757Ssephe 0, /* bitpos */ 290307206Ssephe complain_overflow_dont, /* complain_on_overflow */ 291307164Ssephe m68hc11_elf_ignore_reloc, /* special_function */ 292250199Sgrehan "R_M68HC11_RL_JUMP", /* name */ 293307174Ssephe true, /* partial_inplace */ 294308504Ssephe 0, /* src_mask */ 295308504Ssephe 0, /* dst_mask */ 296307174Ssephe true), /* pcrel_offset */ 297307174Ssephe 298307174Ssephe /* Mark beginning of Gcc relaxation group instruction. */ 299307174Ssephe HOWTO (R_M68HC11_RL_GROUP, /* type */ 300307174Ssephe 0, /* rightshift */ 301307174Ssephe 2, /* size */ 302307174Ssephe 0, /* bitsize */ 303250199Sgrehan false, /* pc_relative */ 304307174Ssephe 0, /* bitpos */ 305307174Ssephe complain_overflow_dont, /* complain_on_overflow */ 306308503Ssephe m68hc11_elf_ignore_reloc, /* special_function */ 307307174Ssephe "R_M68HC11_RL_GROUP", /* name */ 308307174Ssephe true, /* partial_inplace */ 309307174Ssephe 0, /* src_mask */ 310307164Ssephe 0, /* dst_mask */ 311307174Ssephe true), /* pcrel_offset */ 312307174Ssephe}; 313307164Ssephe 314307206Ssephe/* Map BFD reloc types to M68HC11 ELF reloc types. */ 315250199Sgrehan 316250199Sgrehanstruct m68hc11_reloc_map 317307174Ssephe{ 318307174Ssephe bfd_reloc_code_real_type bfd_reloc_val; 319307206Ssephe unsigned char elf_reloc_val; 320307164Ssephe}; 321250199Sgrehan 322250199Sgrehanstatic const struct m68hc11_reloc_map m68hc11_reloc_map[] = { 323310757Ssephe {BFD_RELOC_NONE, R_M68HC11_NONE,}, 324307206Ssephe {BFD_RELOC_8, R_M68HC11_8}, 325250199Sgrehan {BFD_RELOC_M68HC11_HI8, R_M68HC11_HI8}, 326307206Ssephe {BFD_RELOC_M68HC11_LO8, R_M68HC11_LO8}, 327250199Sgrehan {BFD_RELOC_8_PCREL, R_M68HC11_PCREL_8}, 328307174Ssephe {BFD_RELOC_16_PCREL, R_M68HC11_PCREL_16}, 329307164Ssephe {BFD_RELOC_16, R_M68HC11_16}, 330250199Sgrehan {BFD_RELOC_32, R_M68HC11_32}, 331307164Ssephe {BFD_RELOC_M68HC11_3B, R_M68HC11_3B}, 332307164Ssephe 333307164Ssephe {BFD_RELOC_VTABLE_INHERIT, R_M68HC11_GNU_VTINHERIT}, 334307164Ssephe {BFD_RELOC_VTABLE_ENTRY, R_M68HC11_GNU_VTENTRY}, 335307164Ssephe 336307164Ssephe {BFD_RELOC_M68HC11_LO16, R_M68HC11_LO16}, 337250199Sgrehan {BFD_RELOC_M68HC11_PAGE, R_M68HC11_PAGE}, 338307167Ssephe {BFD_RELOC_M68HC11_24, R_M68HC11_24}, 339307206Ssephe 340307206Ssephe {BFD_RELOC_M68HC11_RL_JUMP, R_M68HC11_RL_JUMP}, 341307174Ssephe {BFD_RELOC_M68HC11_RL_GROUP, R_M68HC11_RL_GROUP}, 342307206Ssephe}; 343310757Ssephe 344310757Ssephestatic reloc_howto_type * 345310757Ssephebfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, 346310757Ssephe bfd_reloc_code_real_type code) 347310757Ssephe{ 348310757Ssephe unsigned int i; 349250199Sgrehan 350307174Ssephe for (i = 0; 351307250Ssephe i < sizeof (m68hc11_reloc_map) / sizeof (struct m68hc11_reloc_map); 352307250Ssephe i++) 353307250Ssephe { 354310743Ssephe if (m68hc11_reloc_map[i].bfd_reloc_val == code) 355310743Ssephe return &elf_m68hc11_howto_table[m68hc11_reloc_map[i].elf_reloc_val]; 356310743Ssephe } 357310743Ssephe 358307250Ssephe return NULL; 359310743Ssephe} 360310743Ssephe 361307250Ssephestatic reloc_howto_type * 362307250Ssephebfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, 363307250Ssephe const char *r_name) 364307250Ssephe{ 365307250Ssephe unsigned int i; 366250199Sgrehan 367307206Ssephe for (i = 0; 368307174Ssephe i < (sizeof (elf_m68hc11_howto_table) 369250199Sgrehan / sizeof (elf_m68hc11_howto_table[0])); 370307174Ssephe i++) 371250199Sgrehan if (elf_m68hc11_howto_table[i].name != NULL 372307206Ssephe && strcasecmp (elf_m68hc11_howto_table[i].name, r_name) == 0) 373307174Ssephe return &elf_m68hc11_howto_table[i]; 374307206Ssephe 375307174Ssephe return NULL; 376307206Ssephe} 377310757Ssephe 378250199Sgrehan/* Set the howto pointer for an M68HC11 ELF reloc. */ 379307174Ssephe 380250199Sgrehanstatic bool 381250199Sgrehanm68hc11_info_to_howto_rel (bfd *abfd, 382250199Sgrehan arelent *cache_ptr, Elf_Internal_Rela *dst) 383310757Ssephe{ 384307206Ssephe unsigned int r_type; 385250199Sgrehan 386307206Ssephe r_type = ELF32_R_TYPE (dst->r_info); 387250199Sgrehan if (r_type >= (unsigned int) R_M68HC11_max) 388307174Ssephe { 389307164Ssephe /* xgettext:c-format */ 390250199Sgrehan _bfd_error_handler (_("%pB: unsupported relocation type %#x"), 391307164Ssephe abfd, r_type); 392307164Ssephe bfd_set_error (bfd_error_bad_value); 393307164Ssephe return false; 394307164Ssephe } 395307164Ssephe cache_ptr->howto = &elf_m68hc11_howto_table[r_type]; 396307164Ssephe return true; 397250199Sgrehan} 398307167Ssephe 399307206Ssephe 400307206Ssephe/* Far trampoline generation. */ 401307174Ssephe 402307206Ssephe/* Build a 68HC11 trampoline stub. */ 403310757Ssephestatic bool 404310757Ssephem68hc11_elf_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) 405310757Ssephe{ 406310757Ssephe struct elf32_m68hc11_stub_hash_entry *stub_entry; 407310757Ssephe struct bfd_link_info *info; 408310757Ssephe struct m68hc11_elf_link_hash_table *htab; 409250199Sgrehan asection *stub_sec; 410307174Ssephe bfd *stub_bfd; 411307250Ssephe bfd_byte *loc; 412307250Ssephe bfd_vma sym_value, phys_page, phys_addr; 413307250Ssephe 414310743Ssephe /* Massage our args to the form they really have. */ 415310743Ssephe stub_entry = (struct elf32_m68hc11_stub_hash_entry *) gen_entry; 416310743Ssephe info = (struct bfd_link_info *) in_arg; 417310743Ssephe 418307250Ssephe /* Fail if the target section could not be assigned to an output 419310743Ssephe section. The user should fix his linker script. */ 420310743Ssephe if (stub_entry->target_section->output_section == NULL 421307250Ssephe && info->non_contiguous_regions) 422307250Ssephe info->callbacks->einfo (_("%F%P: Could not assign '%pA' to an output section. " 423307250Ssephe "Retry without --enable-non-contiguous-regions.\n"), 424307250Ssephe stub_entry->target_section); 425307250Ssephe 426307250Ssephe htab = m68hc11_elf_hash_table (info); 427250199Sgrehan if (htab == NULL) 428307206Ssephe return false; 429307174Ssephe 430250199Sgrehan stub_sec = stub_entry->stub_sec; 431307174Ssephe 432250199Sgrehan /* Make a note of the offset within the stubs for this entry. */ 433307206Ssephe stub_entry->stub_offset = stub_sec->size; 434307174Ssephe stub_sec->size += 10; 435307206Ssephe loc = stub_sec->contents + stub_entry->stub_offset; 436307174Ssephe 437307206Ssephe stub_bfd = stub_sec->owner; 438310757Ssephe 439250199Sgrehan /* Create the trampoline call stub: 440307174Ssephe 441250199Sgrehan pshb 442250199Sgrehan ldab #%page(symbol) 443307174Ssephe ldy #%addr(symbol) 444308503Ssephe jmp __trampoline 445307174Ssephe 446310757Ssephe */ 447250199Sgrehan sym_value = (stub_entry->target_value 448250199Sgrehan + stub_entry->target_section->output_offset 449250199Sgrehan + stub_entry->target_section->output_section->vma); 450250199Sgrehan phys_addr = m68hc11_phys_addr (&htab->pinfo, sym_value); 451307200Ssephe phys_page = m68hc11_phys_page (&htab->pinfo, sym_value); 452250199Sgrehan 453307164Ssephe /* pshb; ldab #%page(sym) */ 454307164Ssephe bfd_put_8 (stub_bfd, 0x37, loc); 455307164Ssephe bfd_put_8 (stub_bfd, 0xC6, loc + 1); 456307164Ssephe bfd_put_8 (stub_bfd, phys_page, loc + 2); 457307164Ssephe loc += 3; 458250199Sgrehan 459307164Ssephe /* ldy #%addr(sym) */ 460307164Ssephe bfd_put_8 (stub_bfd, 0x18, loc); 461307164Ssephe bfd_put_8 (stub_bfd, 0xCE, loc + 1); 462307164Ssephe bfd_put_16 (stub_bfd, phys_addr, loc + 2); 463307164Ssephe loc += 4; 464307164Ssephe 465307164Ssephe /* jmp __trampoline */ 466307164Ssephe bfd_put_8 (stub_bfd, 0x7E, loc); 467307164Ssephe bfd_put_16 (stub_bfd, htab->pinfo.trampoline_addr, loc + 1); 468250199Sgrehan 469307186Ssephe return true; 470307186Ssephe} 471307186Ssephe 472307174Ssephe/* As above, but don't actually build the stub. Just bump offset so 473307174Ssephe we know stub section sizes. */ 474307164Ssephe 475307174Ssephestatic bool 476307164Ssephem68hc11_elf_size_one_stub (struct bfd_hash_entry *gen_entry, 477250199Sgrehan void *in_arg ATTRIBUTE_UNUSED) 478307164Ssephe{ 479307164Ssephe struct elf32_m68hc11_stub_hash_entry *stub_entry; 480307164Ssephe 481307164Ssephe /* Massage our args to the form they really have. */ 482307246Ssephe stub_entry = (struct elf32_m68hc11_stub_hash_entry *) gen_entry; 483307246Ssephe 484307246Ssephe stub_entry->stub_sec->size += 10; 485307246Ssephe return true; 486307246Ssephe} 487307246Ssephe 488307246Ssephe/* Create a 68HC11 ELF linker hash table. */ 489307246Ssephe 490307246Ssephestatic struct bfd_link_hash_table * 491250199Sgrehanm68hc11_elf_bfd_link_hash_table_create (bfd *abfd) 492307164Ssephe{ 493250199Sgrehan struct m68hc11_elf_link_hash_table *ret; 494250199Sgrehan 495250199Sgrehan ret = m68hc11_elf_hash_table_create (abfd); 496250199Sgrehan if (ret == (struct m68hc11_elf_link_hash_table *) NULL) 497307202Ssephe return NULL; 498250199Sgrehan 499250199Sgrehan ret->size_one_stub = m68hc11_elf_size_one_stub; 500307202Ssephe ret->build_one_stub = m68hc11_elf_build_one_stub; 501250199Sgrehan 502307164Ssephe return &ret->root.root; 503307164Ssephe} 504250199Sgrehan 505307164Ssephe 506307164Ssephe/* 68HC11 Linker Relaxation. */ 507324466Ssephe 508307164Ssepheconst struct m68hc11_direct_relax 509314123Sdexuan{ 510314123Sdexuan const char *name; 511250199Sgrehan unsigned char code; 512307167Ssephe unsigned char direct_code; 513307174Ssephe} m68hc11_direct_relax_table[] = { 514307245Ssephe { "adca", 0xB9, 0x99 }, 515307164Ssephe { "adcb", 0xF9, 0xD9 }, 516307245Ssephe { "adda", 0xBB, 0x9B }, 517307245Ssephe { "addb", 0xFB, 0xDB }, 518307245Ssephe { "addd", 0xF3, 0xD3 }, 519307245Ssephe { "anda", 0xB4, 0x94 }, 520307245Ssephe { "andb", 0xF4, 0xD4 }, 521307245Ssephe { "cmpa", 0xB1, 0x91 }, 522307245Ssephe { "cmpb", 0xF1, 0xD1 }, 523250199Sgrehan { "cpd", 0xB3, 0x93 }, 524250199Sgrehan { "cpxy", 0xBC, 0x9C }, 525250199Sgrehan/* { "cpy", 0xBC, 0x9C }, */ 526307202Ssephe { "eora", 0xB8, 0x98 }, 527307202Ssephe { "eorb", 0xF8, 0xD8 }, 528307202Ssephe { "jsr", 0xBD, 0x9D }, 529307202Ssephe { "ldaa", 0xB6, 0x96 }, 530307202Ssephe { "ldab", 0xF6, 0xD6 }, 531307202Ssephe { "ldd", 0xFC, 0xDC }, 532307202Ssephe { "lds", 0xBE, 0x9E }, 533307202Ssephe { "ldxy", 0xFE, 0xDE }, 534307202Ssephe /* { "ldy", 0xFE, 0xDE },*/ 535307202Ssephe { "oraa", 0xBA, 0x9A }, 536307202Ssephe { "orab", 0xFA, 0xDA }, 537307202Ssephe { "sbca", 0xB2, 0x92 }, 538307202Ssephe { "sbcb", 0xF2, 0xD2 }, 539307202Ssephe { "staa", 0xB7, 0x97 }, 540307202Ssephe { "stab", 0xF7, 0xD7 }, 541307202Ssephe { "std", 0xFD, 0xDD }, 542307202Ssephe { "sts", 0xBF, 0x9F }, 543307202Ssephe { "stxy", 0xFF, 0xDF }, 544307200Ssephe /* { "sty", 0xFF, 0xDF },*/ 545250199Sgrehan { "suba", 0xB0, 0x90 }, 546307246Ssephe { "subb", 0xF0, 0xD0 }, 547250199Sgrehan { "subd", 0xB3, 0x93 }, 548307245Ssephe { 0, 0, 0 } 549307245Ssephe}; 550307245Ssephe 551307245Ssephestatic const struct m68hc11_direct_relax * 552307245Ssephefind_relaxable_insn (unsigned char code) 553307245Ssephe{ 554307245Ssephe int i; 555307245Ssephe 556307245Ssephe for (i = 0; m68hc11_direct_relax_table[i].name; i++) 557307245Ssephe if (m68hc11_direct_relax_table[i].code == code) 558307246Ssephe return &m68hc11_direct_relax_table[i]; 559307246Ssephe 560307246Ssephe return 0; 561307246Ssephe} 562307246Ssephe 563308494Ssephestatic int 564307246Ssephecompare_reloc (const void *e1, const void *e2) 565308494Ssephe{ 566307245Ssephe const Elf_Internal_Rela *i1 = (const Elf_Internal_Rela *) e1; 567307245Ssephe const Elf_Internal_Rela *i2 = (const Elf_Internal_Rela *) e2; 568307245Ssephe 569307245Ssephe if (i1->r_offset == i2->r_offset) 570307245Ssephe return 0; 571307200Ssephe else 572307200Ssephe return i1->r_offset < i2->r_offset ? -1 : 1; 573307200Ssephe} 574307200Ssephe 575307200Ssephe#define M6811_OP_LDX_IMMEDIATE (0xCE) 576307200Ssephe 577307199Ssephestatic void 578307200Ssephem68hc11_relax_group (bfd *abfd, asection *sec, bfd_byte *contents, 579307199Ssephe unsigned value, unsigned long offset, 580307200Ssephe unsigned long end_group) 581307174Ssephe{ 582307181Ssephe unsigned char code; 583307200Ssephe unsigned long start_offset; 584307199Ssephe unsigned long ldx_offset = offset; 585307199Ssephe unsigned long ldx_size; 586307174Ssephe int can_delete_ldx; 587308494Ssephe int relax_ldy = 0; 588250199Sgrehan 589250199Sgrehan /* First instruction of the relax group must be a 590307200Ssephe LDX #value or LDY #value. If this is not the case, 591307200Ssephe ignore the relax group. */ 592308494Ssephe code = bfd_get_8 (abfd, contents + offset); 593308494Ssephe if (code == 0x18) 594308494Ssephe { 595308494Ssephe relax_ldy++; 596308494Ssephe offset++; 597307200Ssephe code = bfd_get_8 (abfd, contents + offset); 598250199Sgrehan } 599307206Ssephe ldx_size = offset - ldx_offset + 3; 600307206Ssephe offset += 3; 601307200Ssephe if (code != M6811_OP_LDX_IMMEDIATE || offset >= end_group) 602307206Ssephe return; 603285236Swhu 604324574Ssephe 605324574Ssephe /* We can remove the LDX/LDY only when all bset/brclr instructions 606324574Ssephe of the relax group have been converted to use direct addressing 607324574Ssephe mode. */ 608324574Ssephe can_delete_ldx = 1; 609307202Ssephe while (offset < end_group) 610307202Ssephe { 611307202Ssephe unsigned isize; 612307206Ssephe unsigned new_value; 613307206Ssephe int bset_use_y; 614307206Ssephe 615307200Ssephe bset_use_y = 0; 616307202Ssephe start_offset = offset; 617307202Ssephe code = bfd_get_8 (abfd, contents + offset); 618307202Ssephe if (code == 0x18) 619307202Ssephe { 620307206Ssephe bset_use_y++; 621307206Ssephe offset++; 622307206Ssephe code = bfd_get_8 (abfd, contents + offset); 623307202Ssephe } 624250199Sgrehan 625250199Sgrehan /* Check the instruction and translate to use direct addressing mode. */ 626307164Ssephe switch (code) 627250199Sgrehan { 628307206Ssephe /* bset */ 629307206Ssephe case 0x1C: 630307206Ssephe code = 0x14; 631250199Sgrehan isize = 3; 632307206Ssephe break; 633307206Ssephe 634307206Ssephe /* brclr */ 635307206Ssephe case 0x1F: 636307206Ssephe code = 0x13; 637307206Ssephe isize = 4; 638307206Ssephe break; 639307206Ssephe 640307206Ssephe /* brset */ 641307206Ssephe case 0x1E: 642307206Ssephe code = 0x12; 643310757Ssephe isize = 4; 644310757Ssephe break; 645307206Ssephe 646310757Ssephe /* bclr */ 647307206Ssephe case 0x1D: 648250199Sgrehan code = 0x15; 649250199Sgrehan isize = 3; 650307250Ssephe break; 651307250Ssephe 652250199Sgrehan /* This instruction is not recognized and we are not 653307250Ssephe at end of the relax group. Ignore and don't remove 654307250Ssephe the first LDX (we don't know what it is used for...). */ 655307206Ssephe default: 656307206Ssephe return; 657250199Sgrehan } 658250199Sgrehan new_value = (unsigned) bfd_get_8 (abfd, contents + offset + 1); 659307185Ssephe new_value += value; 660308504Ssephe if ((new_value & 0xff00) == 0 && bset_use_y == relax_ldy) 661307174Ssephe { 662307167Ssephe bfd_put_8 (abfd, code, contents + offset); 663307161Ssephe bfd_put_8 (abfd, new_value, contents + offset + 1); 664307164Ssephe if (start_offset != offset) 665307167Ssephe { 666307161Ssephe m68hc11_elf_relax_delete_bytes (abfd, sec, start_offset, 667307161Ssephe offset - start_offset); 668307161Ssephe end_group--; 669308504Ssephe } 670307174Ssephe } 671307167Ssephe else 672307161Ssephe { 673307161Ssephe can_delete_ldx = 0; 674307161Ssephe } 675307161Ssephe offset = start_offset + isize; 676250199Sgrehan } 677307206Ssephe if (can_delete_ldx) 678307206Ssephe { 679307206Ssephe /* Remove the move instruction (3 or 4 bytes win). */ 680307206Ssephe m68hc11_elf_relax_delete_bytes (abfd, sec, ldx_offset, ldx_size); 681307206Ssephe } 682307206Ssephe} 683307206Ssephe 684307206Ssephe/* This function handles relaxing for the 68HC11. 685307206Ssephe 686307206Ssephe 687307206Ssephe and somewhat more difficult to support. */ 688307206Ssephe 689307206Ssephestatic bool 690307206Ssephem68hc11_elf_relax_section (bfd *abfd, asection *sec, 691307206Ssephe struct bfd_link_info *link_info, bool *again) 692307206Ssephe{ 693307206Ssephe Elf_Internal_Shdr *symtab_hdr; 694307206Ssephe Elf_Internal_Rela *internal_relocs; 695307206Ssephe Elf_Internal_Rela *free_relocs = NULL; 696307206Ssephe Elf_Internal_Rela *irel, *irelend; 697307206Ssephe bfd_byte *contents = NULL; 698307206Ssephe bfd_byte *free_contents = NULL; 699307206Ssephe Elf32_External_Sym *free_extsyms = NULL; 700307206Ssephe Elf_Internal_Rela *prev_insn_branch = NULL; 701307206Ssephe Elf_Internal_Rela *prev_insn_group = NULL; 702307206Ssephe unsigned insn_group_value = 0; 703307206Ssephe Elf_Internal_Sym *isymbuf = NULL; 704307206Ssephe 705307206Ssephe /* Assume nothing changes. */ 706307206Ssephe *again = false; 707307206Ssephe 708307206Ssephe /* We don't have to do anything for a relocatable link, if 709307206Ssephe this section does not have relocs, or if this is not a 710307206Ssephe code section. */ 711307206Ssephe if (bfd_link_relocatable (link_info) 712307206Ssephe || (sec->flags & SEC_RELOC) == 0 713307206Ssephe || sec->reloc_count == 0 714307206Ssephe || (sec->flags & SEC_CODE) == 0) 715307206Ssephe return true; 716307206Ssephe 717307206Ssephe symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 718307206Ssephe 719307206Ssephe /* Get a copy of the native relocations. */ 720307206Ssephe internal_relocs = (_bfd_elf_link_read_relocs 721307206Ssephe (abfd, sec, NULL, (Elf_Internal_Rela *) NULL, 722307206Ssephe link_info->keep_memory)); 723307206Ssephe if (internal_relocs == NULL) 724307206Ssephe goto error_return; 725307206Ssephe if (! link_info->keep_memory) 726308504Ssephe free_relocs = internal_relocs; 727308504Ssephe 728308504Ssephe /* Checking for branch relaxation relies on the relocations to 729308504Ssephe be sorted on 'r_offset'. This is not guaranteed so we must sort. */ 730308504Ssephe qsort (internal_relocs, sec->reloc_count, sizeof (Elf_Internal_Rela), 731308504Ssephe compare_reloc); 732308504Ssephe 733308504Ssephe /* Walk through them looking for relaxing opportunities. */ 734308504Ssephe irelend = internal_relocs + sec->reloc_count; 735314123Sdexuan for (irel = internal_relocs; irel < irelend; irel++) 736314123Sdexuan { 737314123Sdexuan bfd_vma symval; 738314123Sdexuan bfd_vma value; 739314123Sdexuan Elf_Internal_Sym *isym; 740314123Sdexuan asection *sym_sec; 741314123Sdexuan int is_far = 0; 742314123Sdexuan 743314123Sdexuan /* If this isn't something that can be relaxed, then ignore 744314123Sdexuan this reloc. */ 745314123Sdexuan if (ELF32_R_TYPE (irel->r_info) != (int) R_M68HC11_16 746314123Sdexuan && ELF32_R_TYPE (irel->r_info) != (int) R_M68HC11_RL_JUMP 747 && ELF32_R_TYPE (irel->r_info) != (int) R_M68HC11_RL_GROUP) 748 { 749 prev_insn_branch = 0; 750 prev_insn_group = 0; 751 continue; 752 } 753 754 /* Get the section contents if we haven't done so already. */ 755 if (contents == NULL) 756 { 757 /* Get cached copy if it exists. */ 758 if (elf_section_data (sec)->this_hdr.contents != NULL) 759 contents = elf_section_data (sec)->this_hdr.contents; 760 else 761 { 762 /* Go get them off disk. */ 763 if (!bfd_malloc_and_get_section (abfd, sec, &contents)) 764 goto error_return; 765 } 766 } 767 768 /* Try to eliminate an unconditional 8 bit pc-relative branch 769 which immediately follows a conditional 8 bit pc-relative 770 branch around the unconditional branch. 771 772 original: new: 773 bCC lab1 bCC' lab2 774 bra lab2 775 lab1: lab1: 776 777 This happens when the bCC can't reach lab2 at assembly time, 778 but due to other relaxations it can reach at link time. */ 779 if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_RL_JUMP) 780 { 781 Elf_Internal_Rela *nrel; 782 unsigned char code; 783 unsigned char roffset; 784 785 prev_insn_branch = 0; 786 prev_insn_group = 0; 787 788 /* Do nothing if this reloc is the last byte in the section. */ 789 if (irel->r_offset + 2 >= sec->size) 790 continue; 791 792 /* See if the next instruction is an unconditional pc-relative 793 branch, more often than not this test will fail, so we 794 test it first to speed things up. */ 795 code = bfd_get_8 (abfd, contents + irel->r_offset + 2); 796 if (code != 0x7e) 797 continue; 798 799 /* Also make sure the next relocation applies to the next 800 instruction and that it's a pc-relative 8 bit branch. */ 801 nrel = irel + 1; 802 if (nrel == irelend 803 || irel->r_offset + 3 != nrel->r_offset 804 || ELF32_R_TYPE (nrel->r_info) != (int) R_M68HC11_16) 805 continue; 806 807 /* Make sure our destination immediately follows the 808 unconditional branch. */ 809 roffset = bfd_get_8 (abfd, contents + irel->r_offset + 1); 810 if (roffset != 3) 811 continue; 812 813 prev_insn_branch = irel; 814 prev_insn_group = 0; 815 continue; 816 } 817 818 /* Read this BFD's symbols if we haven't done so already. */ 819 if (isymbuf == NULL && symtab_hdr->sh_info != 0) 820 { 821 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; 822 if (isymbuf == NULL) 823 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, 824 symtab_hdr->sh_info, 0, 825 NULL, NULL, NULL); 826 if (isymbuf == NULL) 827 goto error_return; 828 } 829 830 /* Get the value of the symbol referred to by the reloc. */ 831 if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info) 832 { 833 /* A local symbol. */ 834 isym = isymbuf + ELF32_R_SYM (irel->r_info); 835 is_far = isym->st_other & STO_M68HC12_FAR; 836 sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx); 837 symval = (isym->st_value 838 + sym_sec->output_section->vma 839 + sym_sec->output_offset); 840 } 841 else 842 { 843 unsigned long indx; 844 struct elf_link_hash_entry *h; 845 846 /* An external symbol. */ 847 indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info; 848 h = elf_sym_hashes (abfd)[indx]; 849 BFD_ASSERT (h != NULL); 850 if (h->root.type != bfd_link_hash_defined 851 && h->root.type != bfd_link_hash_defweak) 852 { 853 /* This appears to be a reference to an undefined 854 symbol. Just ignore it--it will be caught by the 855 regular reloc processing. */ 856 prev_insn_branch = 0; 857 prev_insn_group = 0; 858 continue; 859 } 860 861 is_far = h->other & STO_M68HC12_FAR; 862 isym = 0; 863 sym_sec = h->root.u.def.section; 864 symval = (h->root.u.def.value 865 + sym_sec->output_section->vma 866 + sym_sec->output_offset); 867 } 868 869 if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_RL_GROUP) 870 { 871 prev_insn_branch = 0; 872 prev_insn_group = 0; 873 874 /* Do nothing if this reloc is the last byte in the section. */ 875 if (irel->r_offset == sec->size) 876 continue; 877 878 prev_insn_group = irel; 879 insn_group_value = isym->st_value; 880 continue; 881 } 882 883 /* When we relax some bytes, the size of our section changes. 884 This affects the layout of next input sections that go in our 885 output section. When the symbol is part of another section that 886 will go in the same output section as the current one, it's 887 final address may now be incorrect (too far). We must let the 888 linker re-compute all section offsets before processing this 889 reloc. Code example: 890 891 Initial Final 892 .sect .text section size = 6 section size = 4 893 jmp foo 894 jmp bar 895 .sect .text.foo_bar output_offset = 6 output_offset = 4 896 foo: rts 897 bar: rts 898 899 If we process the reloc now, the jmp bar is replaced by a 900 relative branch to the initial bar address (output_offset 6). */ 901 if (*again && sym_sec != sec 902 && sym_sec->output_section == sec->output_section) 903 { 904 prev_insn_group = 0; 905 prev_insn_branch = 0; 906 continue; 907 } 908 909 value = symval; 910 /* Try to turn a far branch to a near branch. */ 911 if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_16 912 && prev_insn_branch) 913 { 914 bfd_vma offset; 915 unsigned char code; 916 917 offset = value - (prev_insn_branch->r_offset 918 + sec->output_section->vma 919 + sec->output_offset + 2); 920 921 /* If the offset is still out of -128..+127 range, 922 leave that far branch unchanged. */ 923 if ((offset & 0xff80) != 0 && (offset & 0xff80) != 0xff80) 924 { 925 prev_insn_branch = 0; 926 continue; 927 } 928 929 /* Shrink the branch. */ 930 code = bfd_get_8 (abfd, contents + prev_insn_branch->r_offset); 931 if (code == 0x7e) 932 { 933 code = 0x20; 934 bfd_put_8 (abfd, code, contents + prev_insn_branch->r_offset); 935 bfd_put_8 (abfd, 0xff, 936 contents + prev_insn_branch->r_offset + 1); 937 irel->r_offset = prev_insn_branch->r_offset + 1; 938 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), 939 R_M68HC11_PCREL_8); 940 m68hc11_elf_relax_delete_bytes (abfd, sec, 941 irel->r_offset + 1, 1); 942 } 943 else 944 { 945 code ^= 0x1; 946 bfd_put_8 (abfd, code, contents + prev_insn_branch->r_offset); 947 bfd_put_8 (abfd, 0xff, 948 contents + prev_insn_branch->r_offset + 1); 949 irel->r_offset = prev_insn_branch->r_offset + 1; 950 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), 951 R_M68HC11_PCREL_8); 952 m68hc11_elf_relax_delete_bytes (abfd, sec, 953 irel->r_offset + 1, 3); 954 } 955 prev_insn_branch = 0; 956 *again = true; 957 } 958 959 /* Try to turn a 16 bit address into a 8 bit page0 address. */ 960 else if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_16 961 && (value & 0xff00) == 0) 962 { 963 unsigned char code; 964 unsigned short offset; 965 const struct m68hc11_direct_relax *rinfo; 966 967 prev_insn_branch = 0; 968 offset = bfd_get_16 (abfd, contents + irel->r_offset); 969 offset += value; 970 if ((offset & 0xff00) != 0) 971 { 972 prev_insn_group = 0; 973 continue; 974 } 975 976 if (prev_insn_group) 977 { 978 unsigned long old_sec_size = sec->size; 979 980 /* Note that we've changed the relocation contents, etc. */ 981 elf_section_data (sec)->relocs = internal_relocs; 982 free_relocs = NULL; 983 984 elf_section_data (sec)->this_hdr.contents = contents; 985 free_contents = NULL; 986 987 symtab_hdr->contents = (bfd_byte *) isymbuf; 988 free_extsyms = NULL; 989 990 m68hc11_relax_group (abfd, sec, contents, offset, 991 prev_insn_group->r_offset, 992 insn_group_value); 993 irel = prev_insn_group; 994 prev_insn_group = 0; 995 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), 996 R_M68HC11_NONE); 997 if (sec->size != old_sec_size) 998 *again = true; 999 continue; 1000 } 1001 1002 /* Get the opcode. */ 1003 code = bfd_get_8 (abfd, contents + irel->r_offset - 1); 1004 rinfo = find_relaxable_insn (code); 1005 if (rinfo == 0) 1006 { 1007 prev_insn_group = 0; 1008 continue; 1009 } 1010 1011 /* Note that we've changed the relocation contents, etc. */ 1012 elf_section_data (sec)->relocs = internal_relocs; 1013 free_relocs = NULL; 1014 1015 elf_section_data (sec)->this_hdr.contents = contents; 1016 free_contents = NULL; 1017 1018 symtab_hdr->contents = (bfd_byte *) isymbuf; 1019 free_extsyms = NULL; 1020 1021 /* Fix the opcode. */ 1022 /* printf ("A relaxable case : 0x%02x (%s)\n", 1023 code, rinfo->name); */ 1024 bfd_put_8 (abfd, rinfo->direct_code, 1025 contents + irel->r_offset - 1); 1026 1027 /* Delete one byte of data (upper byte of address). */ 1028 m68hc11_elf_relax_delete_bytes (abfd, sec, irel->r_offset, 1); 1029 1030 /* Fix the relocation's type. */ 1031 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), 1032 R_M68HC11_8); 1033 1034 /* That will change things, so, we should relax again. */ 1035 *again = true; 1036 } 1037 else if (ELF32_R_TYPE (irel->r_info) == R_M68HC11_16 && !is_far) 1038 { 1039 unsigned char code; 1040 bfd_vma offset; 1041 1042 prev_insn_branch = 0; 1043 code = bfd_get_8 (abfd, contents + irel->r_offset - 1); 1044 if (code == 0x7e || code == 0xbd) 1045 { 1046 offset = value - (irel->r_offset 1047 + sec->output_section->vma 1048 + sec->output_offset + 1); 1049 offset += bfd_get_16 (abfd, contents + irel->r_offset); 1050 1051 /* If the offset is still out of -128..+127 range, 1052 leave that far branch unchanged. */ 1053 if ((offset & 0xff80) == 0 || (offset & 0xff80) == 0xff80) 1054 { 1055 1056 /* Note that we've changed the relocation contents, etc. */ 1057 elf_section_data (sec)->relocs = internal_relocs; 1058 free_relocs = NULL; 1059 1060 elf_section_data (sec)->this_hdr.contents = contents; 1061 free_contents = NULL; 1062 1063 symtab_hdr->contents = (bfd_byte *) isymbuf; 1064 free_extsyms = NULL; 1065 1066 /* Shrink the branch. */ 1067 code = (code == 0x7e) ? 0x20 : 0x8d; 1068 bfd_put_8 (abfd, code, 1069 contents + irel->r_offset - 1); 1070 bfd_put_8 (abfd, 0xff, 1071 contents + irel->r_offset); 1072 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), 1073 R_M68HC11_PCREL_8); 1074 m68hc11_elf_relax_delete_bytes (abfd, sec, 1075 irel->r_offset + 1, 1); 1076 /* That will change things, so, we should relax again. */ 1077 *again = true; 1078 } 1079 } 1080 } 1081 prev_insn_branch = 0; 1082 prev_insn_group = 0; 1083 } 1084 1085 free (free_relocs); 1086 free_relocs = NULL; 1087 1088 if (free_contents != NULL) 1089 { 1090 if (! link_info->keep_memory) 1091 free (free_contents); 1092 else 1093 { 1094 /* Cache the section contents for elf_link_input_bfd. */ 1095 elf_section_data (sec)->this_hdr.contents = contents; 1096 } 1097 free_contents = NULL; 1098 } 1099 1100 if (free_extsyms != NULL) 1101 { 1102 if (! link_info->keep_memory) 1103 free (free_extsyms); 1104 else 1105 { 1106 /* Cache the symbols for elf_link_input_bfd. */ 1107 symtab_hdr->contents = (unsigned char *) isymbuf; 1108 } 1109 free_extsyms = NULL; 1110 } 1111 1112 return true; 1113 1114 error_return: 1115 free (free_relocs); 1116 free (free_contents); 1117 free (free_extsyms); 1118 return false; 1119} 1120 1121/* Delete some bytes from a section while relaxing. */ 1122 1123static void 1124m68hc11_elf_relax_delete_bytes (bfd *abfd, asection *sec, 1125 bfd_vma addr, int count) 1126{ 1127 Elf_Internal_Shdr *symtab_hdr; 1128 unsigned int sec_shndx; 1129 bfd_byte *contents; 1130 Elf_Internal_Rela *irel, *irelend; 1131 bfd_vma toaddr; 1132 Elf_Internal_Sym *isymbuf, *isym, *isymend; 1133 struct elf_link_hash_entry **sym_hashes; 1134 struct elf_link_hash_entry **end_hashes; 1135 unsigned int symcount; 1136 1137 symtab_hdr = &elf_tdata (abfd)->symtab_hdr; 1138 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; 1139 1140 sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec); 1141 1142 contents = elf_section_data (sec)->this_hdr.contents; 1143 1144 toaddr = sec->size; 1145 1146 irel = elf_section_data (sec)->relocs; 1147 irelend = irel + sec->reloc_count; 1148 1149 /* Actually delete the bytes. */ 1150 memmove (contents + addr, contents + addr + count, 1151 (size_t) (toaddr - addr - count)); 1152 1153 sec->size -= count; 1154 1155 /* Adjust all the relocs. */ 1156 for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++) 1157 { 1158 unsigned char code; 1159 unsigned char offset; 1160 unsigned short raddr; 1161 unsigned long old_offset; 1162 int branch_pos; 1163 1164 old_offset = irel->r_offset; 1165 1166 /* See if this reloc was for the bytes we have deleted, in which 1167 case we no longer care about it. Don't delete relocs which 1168 represent addresses, though. */ 1169 if (ELF32_R_TYPE (irel->r_info) != R_M68HC11_RL_JUMP 1170 && irel->r_offset >= addr && irel->r_offset < addr + count) 1171 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), 1172 R_M68HC11_NONE); 1173 1174 if (ELF32_R_TYPE (irel->r_info) == R_M68HC11_NONE) 1175 continue; 1176 1177 /* Get the new reloc address. */ 1178 if ((irel->r_offset > addr 1179 && irel->r_offset < toaddr)) 1180 irel->r_offset -= count; 1181 1182 /* If this is a PC relative reloc, see if the range it covers 1183 includes the bytes we have deleted. */ 1184 switch (ELF32_R_TYPE (irel->r_info)) 1185 { 1186 default: 1187 break; 1188 1189 case R_M68HC11_RL_JUMP: 1190 code = bfd_get_8 (abfd, contents + irel->r_offset); 1191 switch (code) 1192 { 1193 /* jsr and jmp instruction are also marked with RL_JUMP 1194 relocs but no adjustment must be made. */ 1195 case 0x7e: 1196 case 0x9d: 1197 case 0xbd: 1198 continue; 1199 1200 case 0x12: 1201 case 0x13: 1202 branch_pos = 3; 1203 raddr = 4; 1204 1205 /* Special case when we translate a brclr N,y into brclr *<addr> 1206 In this case, the 0x18 page2 prefix is removed. 1207 The reloc offset is not modified but the instruction 1208 size is reduced by 1. */ 1209 if (old_offset == addr) 1210 raddr++; 1211 break; 1212 1213 case 0x1e: 1214 case 0x1f: 1215 branch_pos = 3; 1216 raddr = 4; 1217 break; 1218 1219 case 0x18: 1220 branch_pos = 4; 1221 raddr = 5; 1222 break; 1223 1224 default: 1225 branch_pos = 1; 1226 raddr = 2; 1227 break; 1228 } 1229 offset = bfd_get_8 (abfd, contents + irel->r_offset + branch_pos); 1230 raddr += old_offset; 1231 raddr += ((unsigned short) offset | ((offset & 0x80) ? 0xff00 : 0)); 1232 if (irel->r_offset < addr && raddr > addr) 1233 { 1234 offset -= count; 1235 bfd_put_8 (abfd, offset, contents + irel->r_offset + branch_pos); 1236 } 1237 else if (irel->r_offset >= addr && raddr <= addr) 1238 { 1239 offset += count; 1240 bfd_put_8 (abfd, offset, contents + irel->r_offset + branch_pos); 1241 } 1242 else 1243 { 1244 /*printf ("Not adjusted 0x%04x [0x%4x 0x%4x]\n", raddr, 1245 irel->r_offset, addr);*/ 1246 } 1247 1248 break; 1249 } 1250 } 1251 1252 /* Adjust the local symbols defined in this section. */ 1253 isymend = isymbuf + symtab_hdr->sh_info; 1254 for (isym = isymbuf; isym < isymend; isym++) 1255 { 1256 if (isym->st_shndx == sec_shndx 1257 && isym->st_value > addr 1258 && isym->st_value <= toaddr) 1259 isym->st_value -= count; 1260 } 1261 1262 /* Now adjust the global symbols defined in this section. */ 1263 symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym) 1264 - symtab_hdr->sh_info); 1265 sym_hashes = elf_sym_hashes (abfd); 1266 end_hashes = sym_hashes + symcount; 1267 for (; sym_hashes < end_hashes; sym_hashes++) 1268 { 1269 struct elf_link_hash_entry *sym_hash = *sym_hashes; 1270 if ((sym_hash->root.type == bfd_link_hash_defined 1271 || sym_hash->root.type == bfd_link_hash_defweak) 1272 && sym_hash->root.u.def.section == sec 1273 && sym_hash->root.u.def.value > addr 1274 && sym_hash->root.u.def.value <= toaddr) 1275 { 1276 sym_hash->root.u.def.value -= count; 1277 } 1278 } 1279} 1280 1281/* Specific sections: 1282 - The .page0 is a data section that is mapped in [0x0000..0x00FF]. 1283 Page0 accesses are faster on the M68HC11. Soft registers used by GCC-m6811 1284 are located in .page0. 1285 - The .vectors is the section that represents the interrupt 1286 vectors. */ 1287static const struct bfd_elf_special_section elf32_m68hc11_special_sections[] = 1288{ 1289 { STRING_COMMA_LEN (".eeprom"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, 1290 { STRING_COMMA_LEN (".page0"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, 1291 { STRING_COMMA_LEN (".softregs"), 0, SHT_NOBITS, SHF_ALLOC + SHF_WRITE }, 1292 { STRING_COMMA_LEN (".vectors"), 0, SHT_PROGBITS, SHF_ALLOC }, 1293 { NULL, 0, 0, 0, 0 } 1294}; 1295 1296#define ELF_ARCH bfd_arch_m68hc11 1297#define ELF_TARGET_ID M68HC11_ELF_DATA 1298#define ELF_MACHINE_CODE EM_68HC11 1299#define ELF_MAXPAGESIZE 0x1000 1300 1301#define TARGET_BIG_SYM m68hc11_elf32_vec 1302#define TARGET_BIG_NAME "elf32-m68hc11" 1303 1304#define elf_info_to_howto NULL 1305#define elf_info_to_howto_rel m68hc11_info_to_howto_rel 1306#define bfd_elf32_bfd_relax_section m68hc11_elf_relax_section 1307#define elf_backend_check_relocs elf32_m68hc11_check_relocs 1308#define elf_backend_relocate_section elf32_m68hc11_relocate_section 1309#define elf_backend_add_symbol_hook elf32_m68hc11_add_symbol_hook 1310#define elf_backend_object_p 0 1311#define elf_backend_can_gc_sections 1 1312#define elf_backend_special_sections elf32_m68hc11_special_sections 1313#define elf_backend_merge_symbol_attribute elf32_m68hc11_merge_symbol_attribute 1314 1315#define bfd_elf32_bfd_link_hash_table_create \ 1316 m68hc11_elf_bfd_link_hash_table_create 1317#define bfd_elf32_bfd_merge_private_bfd_data \ 1318 _bfd_m68hc11_elf_merge_private_bfd_data 1319#define bfd_elf32_bfd_set_private_flags _bfd_m68hc11_elf_set_private_flags 1320#define bfd_elf32_bfd_print_private_bfd_data \ 1321 _bfd_m68hc11_elf_print_private_bfd_data 1322 1323#include "elf32-target.h" 1324