00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "bfd.h"
00028 #include "sysdep.h"
00029 #include "bfdlink.h"
00030 #include "libbfd.h"
00031 #include "elf-bfd.h"
00032 #include "elf32-m68hc1x.h"
00033 #include "elf/m68hc11.h"
00034 #include "opcode/m68hc11.h"
00035
00036
00037 static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
00038 (bfd *, bfd_reloc_code_real_type);
00039 static void m68hc11_info_to_howto_rel
00040 (bfd *, arelent *, Elf_Internal_Rela *);
00041
00042
00043 static bfd_boolean m68hc11_elf_size_one_stub
00044 (struct bfd_hash_entry *gen_entry, void *in_arg);
00045 static bfd_boolean m68hc11_elf_build_one_stub
00046 (struct bfd_hash_entry *gen_entry, void *in_arg);
00047 static struct bfd_link_hash_table* m68hc11_elf_bfd_link_hash_table_create
00048 (bfd* abfd);
00049
00050
00051 static bfd_boolean m68hc11_elf_relax_section
00052 (bfd *, asection *, struct bfd_link_info *, bfd_boolean *);
00053 static void m68hc11_elf_relax_delete_bytes
00054 (bfd *, asection *, bfd_vma, int);
00055 static void m68hc11_relax_group
00056 (bfd *, asection *, bfd_byte *, unsigned, unsigned long, unsigned long);
00057 static int compare_reloc (const void *, const void *);
00058
00059
00060 #define USE_REL 1
00061
00062
00063
00064
00065
00066
00067
00068 static reloc_howto_type elf_m68hc11_howto_table[] = {
00069
00070 HOWTO (R_M68HC11_NONE,
00071 0,
00072 2,
00073 32,
00074 FALSE,
00075 0,
00076 complain_overflow_dont,
00077 bfd_elf_generic_reloc,
00078 "R_M68HC11_NONE",
00079 FALSE,
00080 0,
00081 0,
00082 FALSE),
00083
00084
00085 HOWTO (R_M68HC11_8,
00086 0,
00087 0,
00088 8,
00089 FALSE,
00090 0,
00091 complain_overflow_bitfield,
00092 bfd_elf_generic_reloc,
00093 "R_M68HC11_8",
00094 FALSE,
00095 0x00ff,
00096 0x00ff,
00097 FALSE),
00098
00099
00100 HOWTO (R_M68HC11_HI8,
00101 8,
00102 0,
00103 8,
00104 FALSE,
00105 0,
00106 complain_overflow_bitfield,
00107 bfd_elf_generic_reloc,
00108 "R_M68HC11_HI8",
00109 FALSE,
00110 0x00ff,
00111 0x00ff,
00112 FALSE),
00113
00114
00115 HOWTO (R_M68HC11_LO8,
00116 0,
00117 0,
00118 8,
00119 FALSE,
00120 0,
00121 complain_overflow_dont,
00122 bfd_elf_generic_reloc,
00123 "R_M68HC11_LO8",
00124 FALSE,
00125 0x00ff,
00126 0x00ff,
00127 FALSE),
00128
00129
00130 HOWTO (R_M68HC11_PCREL_8,
00131 0,
00132 0,
00133 8,
00134 TRUE,
00135 0,
00136 complain_overflow_bitfield,
00137 bfd_elf_generic_reloc,
00138 "R_M68HC11_PCREL_8",
00139 FALSE,
00140 0x00ff,
00141 0x00ff,
00142 TRUE),
00143
00144
00145 HOWTO (R_M68HC11_16,
00146 0,
00147 1,
00148 16,
00149 FALSE,
00150 0,
00151 complain_overflow_dont ,
00152 bfd_elf_generic_reloc,
00153 "R_M68HC11_16",
00154 FALSE,
00155 0xffff,
00156 0xffff,
00157 FALSE),
00158
00159
00160
00161 HOWTO (R_M68HC11_32,
00162 0,
00163 2,
00164 32,
00165 FALSE,
00166 0,
00167 complain_overflow_bitfield,
00168 bfd_elf_generic_reloc,
00169 "R_M68HC11_32",
00170 FALSE,
00171 0xffffffff,
00172 0xffffffff,
00173 FALSE),
00174
00175
00176 HOWTO (R_M68HC11_3B,
00177 0,
00178 0,
00179 3,
00180 FALSE,
00181 0,
00182 complain_overflow_bitfield,
00183 bfd_elf_generic_reloc,
00184 "R_M68HC11_4B",
00185 FALSE,
00186 0x003,
00187 0x003,
00188 FALSE),
00189
00190
00191 HOWTO (R_M68HC11_PCREL_16,
00192 0,
00193 1,
00194 16,
00195 TRUE,
00196 0,
00197 complain_overflow_dont,
00198 bfd_elf_generic_reloc,
00199 "R_M68HC11_PCREL_16",
00200 FALSE,
00201 0xffff,
00202 0xffff,
00203 TRUE),
00204
00205
00206 HOWTO (R_M68HC11_GNU_VTINHERIT,
00207 0,
00208 1,
00209 0,
00210 FALSE,
00211 0,
00212 complain_overflow_dont,
00213 NULL,
00214 "R_M68HC11_GNU_VTINHERIT",
00215 FALSE,
00216 0,
00217 0,
00218 FALSE),
00219
00220
00221 HOWTO (R_M68HC11_GNU_VTENTRY,
00222 0,
00223 1,
00224 0,
00225 FALSE,
00226 0,
00227 complain_overflow_dont,
00228 _bfd_elf_rel_vtable_reloc_fn,
00229 "R_M68HC11_GNU_VTENTRY",
00230 FALSE,
00231 0,
00232 0,
00233 FALSE),
00234
00235
00236 HOWTO (R_M68HC11_24,
00237 0,
00238 1,
00239 24,
00240 FALSE,
00241 0,
00242 complain_overflow_bitfield,
00243 bfd_elf_generic_reloc,
00244 "R_M68HC11_24",
00245 FALSE,
00246 0xffffff,
00247 0xffffff,
00248 FALSE),
00249
00250
00251 HOWTO (R_M68HC11_LO16,
00252 0,
00253 1,
00254 16,
00255 FALSE,
00256 0,
00257 complain_overflow_bitfield,
00258 bfd_elf_generic_reloc,
00259 "R_M68HC11_LO16",
00260 FALSE,
00261 0xffff,
00262 0xffff,
00263 FALSE),
00264
00265
00266 HOWTO (R_M68HC11_PAGE,
00267 0,
00268 0,
00269 8,
00270 FALSE,
00271 0,
00272 complain_overflow_bitfield,
00273 bfd_elf_generic_reloc,
00274 "R_M68HC11_PAGE",
00275 FALSE,
00276 0x00ff,
00277 0x00ff,
00278 FALSE),
00279
00280 EMPTY_HOWTO (14),
00281 EMPTY_HOWTO (15),
00282 EMPTY_HOWTO (16),
00283 EMPTY_HOWTO (17),
00284 EMPTY_HOWTO (18),
00285 EMPTY_HOWTO (19),
00286
00287
00288 HOWTO (R_M68HC11_RL_JUMP,
00289 0,
00290 1,
00291 0,
00292 FALSE,
00293 0,
00294 complain_overflow_dont,
00295 m68hc11_elf_ignore_reloc,
00296 "R_M68HC11_RL_JUMP",
00297 TRUE,
00298 0,
00299 0,
00300 TRUE),
00301
00302
00303 HOWTO (R_M68HC11_RL_GROUP,
00304 0,
00305 1,
00306 0,
00307 FALSE,
00308 0,
00309 complain_overflow_dont,
00310 m68hc11_elf_ignore_reloc,
00311 "R_M68HC11_RL_GROUP",
00312 TRUE,
00313 0,
00314 0,
00315 TRUE),
00316 };
00317
00318
00319
00320 struct m68hc11_reloc_map
00321 {
00322 bfd_reloc_code_real_type bfd_reloc_val;
00323 unsigned char elf_reloc_val;
00324 };
00325
00326 static const struct m68hc11_reloc_map m68hc11_reloc_map[] = {
00327 {BFD_RELOC_NONE, R_M68HC11_NONE,},
00328 {BFD_RELOC_8, R_M68HC11_8},
00329 {BFD_RELOC_M68HC11_HI8, R_M68HC11_HI8},
00330 {BFD_RELOC_M68HC11_LO8, R_M68HC11_LO8},
00331 {BFD_RELOC_8_PCREL, R_M68HC11_PCREL_8},
00332 {BFD_RELOC_16_PCREL, R_M68HC11_PCREL_16},
00333 {BFD_RELOC_16, R_M68HC11_16},
00334 {BFD_RELOC_32, R_M68HC11_32},
00335 {BFD_RELOC_M68HC11_3B, R_M68HC11_3B},
00336
00337 {BFD_RELOC_VTABLE_INHERIT, R_M68HC11_GNU_VTINHERIT},
00338 {BFD_RELOC_VTABLE_ENTRY, R_M68HC11_GNU_VTENTRY},
00339
00340 {BFD_RELOC_M68HC11_LO16, R_M68HC11_LO16},
00341 {BFD_RELOC_M68HC11_PAGE, R_M68HC11_PAGE},
00342 {BFD_RELOC_M68HC11_24, R_M68HC11_24},
00343
00344 {BFD_RELOC_M68HC11_RL_JUMP, R_M68HC11_RL_JUMP},
00345 {BFD_RELOC_M68HC11_RL_GROUP, R_M68HC11_RL_GROUP},
00346 };
00347
00348 static reloc_howto_type *
00349 bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
00350 bfd_reloc_code_real_type code)
00351 {
00352 unsigned int i;
00353
00354 for (i = 0;
00355 i < sizeof (m68hc11_reloc_map) / sizeof (struct m68hc11_reloc_map);
00356 i++)
00357 {
00358 if (m68hc11_reloc_map[i].bfd_reloc_val == code)
00359 return &elf_m68hc11_howto_table[m68hc11_reloc_map[i].elf_reloc_val];
00360 }
00361
00362 return NULL;
00363 }
00364
00365
00366
00367 static void
00368 m68hc11_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
00369 arelent *cache_ptr, Elf_Internal_Rela *dst)
00370 {
00371 unsigned int r_type;
00372
00373 r_type = ELF32_R_TYPE (dst->r_info);
00374 BFD_ASSERT (r_type < (unsigned int) R_M68HC11_max);
00375 cache_ptr->howto = &elf_m68hc11_howto_table[r_type];
00376 }
00377
00378
00379
00380
00381
00382 static bfd_boolean
00383 m68hc11_elf_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
00384 {
00385 struct elf32_m68hc11_stub_hash_entry *stub_entry;
00386 struct bfd_link_info *info;
00387 struct m68hc11_elf_link_hash_table *htab;
00388 asection *stub_sec;
00389 bfd *stub_bfd;
00390 bfd_byte *loc;
00391 bfd_vma sym_value, phys_page, phys_addr;
00392
00393
00394 stub_entry = (struct elf32_m68hc11_stub_hash_entry *) gen_entry;
00395 info = (struct bfd_link_info *) in_arg;
00396
00397 htab = m68hc11_elf_hash_table (info);
00398
00399 stub_sec = stub_entry->stub_sec;
00400
00401
00402 stub_entry->stub_offset = stub_sec->size;
00403 stub_sec->size += 10;
00404 loc = stub_sec->contents + stub_entry->stub_offset;
00405
00406 stub_bfd = stub_sec->owner;
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416 sym_value = (stub_entry->target_value
00417 + stub_entry->target_section->output_offset
00418 + stub_entry->target_section->output_section->vma);
00419 phys_addr = m68hc11_phys_addr (&htab->pinfo, sym_value);
00420 phys_page = m68hc11_phys_page (&htab->pinfo, sym_value);
00421
00422
00423 bfd_put_8 (stub_bfd, 0x37, loc);
00424 bfd_put_8 (stub_bfd, 0xC6, loc + 1);
00425 bfd_put_8 (stub_bfd, phys_page, loc + 2);
00426 loc += 3;
00427
00428
00429 bfd_put_8 (stub_bfd, 0x18, loc);
00430 bfd_put_8 (stub_bfd, 0xCE, loc + 1);
00431 bfd_put_16 (stub_bfd, phys_addr, loc + 2);
00432 loc += 4;
00433
00434
00435 bfd_put_8 (stub_bfd, 0x7E, loc);
00436 bfd_put_16 (stub_bfd, htab->pinfo.trampoline_addr, loc + 1);
00437
00438 return TRUE;
00439 }
00440
00441
00442
00443
00444 static bfd_boolean
00445 m68hc11_elf_size_one_stub (struct bfd_hash_entry *gen_entry,
00446 void *in_arg ATTRIBUTE_UNUSED)
00447 {
00448 struct elf32_m68hc11_stub_hash_entry *stub_entry;
00449
00450
00451 stub_entry = (struct elf32_m68hc11_stub_hash_entry *) gen_entry;
00452
00453 stub_entry->stub_sec->size += 10;
00454 return TRUE;
00455 }
00456
00457
00458
00459 static struct bfd_link_hash_table *
00460 m68hc11_elf_bfd_link_hash_table_create (bfd *abfd)
00461 {
00462 struct m68hc11_elf_link_hash_table *ret;
00463
00464 ret = m68hc11_elf_hash_table_create (abfd);
00465 if (ret == (struct m68hc11_elf_link_hash_table *) NULL)
00466 return NULL;
00467
00468 ret->size_one_stub = m68hc11_elf_size_one_stub;
00469 ret->build_one_stub = m68hc11_elf_build_one_stub;
00470
00471 return &ret->root.root;
00472 }
00473
00474
00475
00476
00477 struct m68hc11_direct_relax
00478 {
00479 const char *name;
00480 unsigned char code;
00481 unsigned char direct_code;
00482 } m68hc11_direct_relax_table[] = {
00483 { "adca", 0xB9, 0x99 },
00484 { "adcb", 0xF9, 0xD9 },
00485 { "adda", 0xBB, 0x9B },
00486 { "addb", 0xFB, 0xDB },
00487 { "addd", 0xF3, 0xD3 },
00488 { "anda", 0xB4, 0x94 },
00489 { "andb", 0xF4, 0xD4 },
00490 { "cmpa", 0xB1, 0x91 },
00491 { "cmpb", 0xF1, 0xD1 },
00492 { "cpd", 0xB3, 0x93 },
00493 { "cpxy", 0xBC, 0x9C },
00494
00495 { "eora", 0xB8, 0x98 },
00496 { "eorb", 0xF8, 0xD8 },
00497 { "jsr", 0xBD, 0x9D },
00498 { "ldaa", 0xB6, 0x96 },
00499 { "ldab", 0xF6, 0xD6 },
00500 { "ldd", 0xFC, 0xDC },
00501 { "lds", 0xBE, 0x9E },
00502 { "ldxy", 0xFE, 0xDE },
00503
00504 { "oraa", 0xBA, 0x9A },
00505 { "orab", 0xFA, 0xDA },
00506 { "sbca", 0xB2, 0x92 },
00507 { "sbcb", 0xF2, 0xD2 },
00508 { "staa", 0xB7, 0x97 },
00509 { "stab", 0xF7, 0xD7 },
00510 { "std", 0xFD, 0xDD },
00511 { "sts", 0xBF, 0x9F },
00512 { "stxy", 0xFF, 0xDF },
00513
00514 { "suba", 0xB0, 0x90 },
00515 { "subb", 0xF0, 0xD0 },
00516 { "subd", 0xB3, 0x93 },
00517 { 0, 0, 0 }
00518 };
00519
00520 static struct m68hc11_direct_relax *
00521 find_relaxable_insn (unsigned char code)
00522 {
00523 int i;
00524
00525 for (i = 0; m68hc11_direct_relax_table[i].name; i++)
00526 if (m68hc11_direct_relax_table[i].code == code)
00527 return &m68hc11_direct_relax_table[i];
00528
00529 return 0;
00530 }
00531
00532 static int
00533 compare_reloc (const void *e1, const void *e2)
00534 {
00535 const Elf_Internal_Rela *i1 = (const Elf_Internal_Rela *) e1;
00536 const Elf_Internal_Rela *i2 = (const Elf_Internal_Rela *) e2;
00537
00538 if (i1->r_offset == i2->r_offset)
00539 return 0;
00540 else
00541 return i1->r_offset < i2->r_offset ? -1 : 1;
00542 }
00543
00544 #define M6811_OP_LDX_IMMEDIATE (0xCE)
00545
00546 static void
00547 m68hc11_relax_group (bfd *abfd, asection *sec, bfd_byte *contents,
00548 unsigned value, unsigned long offset,
00549 unsigned long end_group)
00550 {
00551 unsigned char code;
00552 unsigned long start_offset;
00553 unsigned long ldx_offset = offset;
00554 unsigned long ldx_size;
00555 int can_delete_ldx;
00556 int relax_ldy = 0;
00557
00558
00559
00560
00561 code = bfd_get_8 (abfd, contents + offset);
00562 if (code == 0x18)
00563 {
00564 relax_ldy++;
00565 offset++;
00566 code = bfd_get_8 (abfd, contents + offset);
00567 }
00568 ldx_size = offset - ldx_offset + 3;
00569 offset += 3;
00570 if (code != M6811_OP_LDX_IMMEDIATE || offset >= end_group)
00571 return;
00572
00573
00574
00575
00576
00577 can_delete_ldx = 1;
00578 while (offset < end_group)
00579 {
00580 unsigned isize;
00581 unsigned new_value;
00582 int bset_use_y;
00583
00584 bset_use_y = 0;
00585 start_offset = offset;
00586 code = bfd_get_8 (abfd, contents + offset);
00587 if (code == 0x18)
00588 {
00589 bset_use_y++;
00590 offset++;
00591 code = bfd_get_8 (abfd, contents + offset);
00592 }
00593
00594
00595 switch (code)
00596 {
00597
00598 case 0x1C:
00599 code = 0x14;
00600 isize = 3;
00601 break;
00602
00603
00604 case 0x1F:
00605 code = 0x13;
00606 isize = 4;
00607 break;
00608
00609
00610 case 0x1E:
00611 code = 0x12;
00612 isize = 4;
00613 break;
00614
00615
00616 case 0x1D:
00617 code = 0x15;
00618 isize = 3;
00619 break;
00620
00621
00622
00623
00624 default:
00625 return;
00626 }
00627 new_value = (unsigned) bfd_get_8 (abfd, contents + offset + 1);
00628 new_value += value;
00629 if ((new_value & 0xff00) == 0 && bset_use_y == relax_ldy)
00630 {
00631 bfd_put_8 (abfd, code, contents + offset);
00632 bfd_put_8 (abfd, new_value, contents + offset + 1);
00633 if (start_offset != offset)
00634 {
00635 m68hc11_elf_relax_delete_bytes (abfd, sec, start_offset,
00636 offset - start_offset);
00637 end_group--;
00638 }
00639 }
00640 else
00641 {
00642 can_delete_ldx = 0;
00643 }
00644 offset = start_offset + isize;
00645 }
00646 if (can_delete_ldx)
00647 {
00648
00649 m68hc11_elf_relax_delete_bytes (abfd, sec, ldx_offset, ldx_size);
00650 }
00651 }
00652
00653
00654
00655
00656
00657
00658 static bfd_boolean
00659 m68hc11_elf_relax_section (bfd *abfd, asection *sec,
00660 struct bfd_link_info *link_info, bfd_boolean *again)
00661 {
00662 Elf_Internal_Shdr *symtab_hdr;
00663 Elf_Internal_Shdr *shndx_hdr;
00664 Elf_Internal_Rela *internal_relocs;
00665 Elf_Internal_Rela *free_relocs = NULL;
00666 Elf_Internal_Rela *irel, *irelend;
00667 bfd_byte *contents = NULL;
00668 bfd_byte *free_contents = NULL;
00669 Elf32_External_Sym *free_extsyms = NULL;
00670 Elf_Internal_Rela *prev_insn_branch = NULL;
00671 Elf_Internal_Rela *prev_insn_group = NULL;
00672 unsigned insn_group_value = 0;
00673 Elf_Internal_Sym *isymbuf = NULL;
00674
00675
00676 *again = FALSE;
00677
00678
00679
00680
00681 if (link_info->relocatable
00682 || (sec->flags & SEC_RELOC) == 0
00683 || sec->reloc_count == 0
00684 || (sec->flags & SEC_CODE) == 0)
00685 return TRUE;
00686
00687 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
00688 shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
00689
00690
00691 internal_relocs = (_bfd_elf_link_read_relocs
00692 (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
00693 link_info->keep_memory));
00694 if (internal_relocs == NULL)
00695 goto error_return;
00696 if (! link_info->keep_memory)
00697 free_relocs = internal_relocs;
00698
00699
00700
00701 qsort (internal_relocs, sec->reloc_count, sizeof (Elf_Internal_Rela),
00702 compare_reloc);
00703
00704
00705 irelend = internal_relocs + sec->reloc_count;
00706 for (irel = internal_relocs; irel < irelend; irel++)
00707 {
00708 bfd_vma symval;
00709 bfd_vma value;
00710 Elf_Internal_Sym *isym;
00711 asection *sym_sec;
00712 int is_far = 0;
00713
00714
00715
00716 if (ELF32_R_TYPE (irel->r_info) != (int) R_M68HC11_16
00717 && ELF32_R_TYPE (irel->r_info) != (int) R_M68HC11_RL_JUMP
00718 && ELF32_R_TYPE (irel->r_info) != (int) R_M68HC11_RL_GROUP)
00719 {
00720 prev_insn_branch = 0;
00721 prev_insn_group = 0;
00722 continue;
00723 }
00724
00725
00726 if (contents == NULL)
00727 {
00728
00729 if (elf_section_data (sec)->this_hdr.contents != NULL)
00730 contents = elf_section_data (sec)->this_hdr.contents;
00731 else
00732 {
00733
00734 if (!bfd_malloc_and_get_section (abfd, sec, &contents))
00735 goto error_return;
00736 }
00737 }
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750 if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_RL_JUMP)
00751 {
00752 Elf_Internal_Rela *nrel;
00753 unsigned char code;
00754 unsigned char roffset;
00755
00756 prev_insn_branch = 0;
00757 prev_insn_group = 0;
00758
00759
00760 if (irel->r_offset + 2 >= sec->size)
00761 continue;
00762
00763
00764
00765
00766 code = bfd_get_8 (abfd, contents + irel->r_offset + 2);
00767 if (code != 0x7e)
00768 continue;
00769
00770
00771
00772 nrel = irel + 1;
00773 if (nrel == irelend
00774 || irel->r_offset + 3 != nrel->r_offset
00775 || ELF32_R_TYPE (nrel->r_info) != (int) R_M68HC11_16)
00776 continue;
00777
00778
00779
00780 roffset = bfd_get_8 (abfd, contents + irel->r_offset + 1);
00781 if (roffset != 3)
00782 continue;
00783
00784 prev_insn_branch = irel;
00785 prev_insn_group = 0;
00786 continue;
00787 }
00788
00789
00790 if (isymbuf == NULL && symtab_hdr->sh_info != 0)
00791 {
00792 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
00793 if (isymbuf == NULL)
00794 isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
00795 symtab_hdr->sh_info, 0,
00796 NULL, NULL, NULL);
00797 if (isymbuf == NULL)
00798 goto error_return;
00799 }
00800
00801
00802 if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
00803 {
00804
00805 isym = isymbuf + ELF32_R_SYM (irel->r_info);
00806 is_far = isym->st_other & STO_M68HC12_FAR;
00807 sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
00808 symval = (isym->st_value
00809 + sym_sec->output_section->vma
00810 + sym_sec->output_offset);
00811 }
00812 else
00813 {
00814 unsigned long indx;
00815 struct elf_link_hash_entry *h;
00816
00817
00818 indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
00819 h = elf_sym_hashes (abfd)[indx];
00820 BFD_ASSERT (h != NULL);
00821 if (h->root.type != bfd_link_hash_defined
00822 && h->root.type != bfd_link_hash_defweak)
00823 {
00824
00825
00826
00827 prev_insn_branch = 0;
00828 prev_insn_group = 0;
00829 continue;
00830 }
00831
00832 is_far = h->other & STO_M68HC12_FAR;
00833 isym = 0;
00834 sym_sec = h->root.u.def.section;
00835 symval = (h->root.u.def.value
00836 + sym_sec->output_section->vma
00837 + sym_sec->output_offset);
00838 }
00839
00840 if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_RL_GROUP)
00841 {
00842 prev_insn_branch = 0;
00843 prev_insn_group = 0;
00844
00845
00846 if (irel->r_offset == sec->size)
00847 continue;
00848
00849 prev_insn_group = irel;
00850 insn_group_value = isym->st_value;
00851 continue;
00852 }
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872 if (*again && sym_sec != sec
00873 && sym_sec->output_section == sec->output_section)
00874 {
00875 prev_insn_group = 0;
00876 prev_insn_branch = 0;
00877 continue;
00878 }
00879
00880 value = symval;
00881
00882 if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_16
00883 && prev_insn_branch)
00884 {
00885 bfd_vma offset;
00886 unsigned char code;
00887
00888 offset = value - (prev_insn_branch->r_offset
00889 + sec->output_section->vma
00890 + sec->output_offset + 2);
00891
00892
00893
00894 if ((offset & 0xff80) != 0 && (offset & 0xff80) != 0xff80)
00895 {
00896 prev_insn_branch = 0;
00897 continue;
00898 }
00899
00900
00901 code = bfd_get_8 (abfd, contents + prev_insn_branch->r_offset);
00902 if (code == 0x7e)
00903 {
00904 code = 0x20;
00905 bfd_put_8 (abfd, code, contents + prev_insn_branch->r_offset);
00906 bfd_put_8 (abfd, 0xff,
00907 contents + prev_insn_branch->r_offset + 1);
00908 irel->r_offset = prev_insn_branch->r_offset + 1;
00909 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
00910 R_M68HC11_PCREL_8);
00911 m68hc11_elf_relax_delete_bytes (abfd, sec,
00912 irel->r_offset + 1, 1);
00913 }
00914 else
00915 {
00916 code ^= 0x1;
00917 bfd_put_8 (abfd, code, contents + prev_insn_branch->r_offset);
00918 bfd_put_8 (abfd, 0xff,
00919 contents + prev_insn_branch->r_offset + 1);
00920 irel->r_offset = prev_insn_branch->r_offset + 1;
00921 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
00922 R_M68HC11_PCREL_8);
00923 m68hc11_elf_relax_delete_bytes (abfd, sec,
00924 irel->r_offset + 1, 3);
00925 }
00926 prev_insn_branch = 0;
00927 *again = TRUE;
00928 }
00929
00930
00931 else if (ELF32_R_TYPE (irel->r_info) == (int) R_M68HC11_16
00932 && (value & 0xff00) == 0)
00933 {
00934 unsigned char code;
00935 unsigned short offset;
00936 struct m68hc11_direct_relax *rinfo;
00937
00938 prev_insn_branch = 0;
00939 offset = bfd_get_16 (abfd, contents + irel->r_offset);
00940 offset += value;
00941 if ((offset & 0xff00) != 0)
00942 {
00943 prev_insn_group = 0;
00944 continue;
00945 }
00946
00947 if (prev_insn_group)
00948 {
00949 unsigned long old_sec_size = sec->size;
00950
00951
00952 elf_section_data (sec)->relocs = internal_relocs;
00953 free_relocs = NULL;
00954
00955 elf_section_data (sec)->this_hdr.contents = contents;
00956 free_contents = NULL;
00957
00958 symtab_hdr->contents = (bfd_byte *) isymbuf;
00959 free_extsyms = NULL;
00960
00961 m68hc11_relax_group (abfd, sec, contents, offset,
00962 prev_insn_group->r_offset,
00963 insn_group_value);
00964 irel = prev_insn_group;
00965 prev_insn_group = 0;
00966 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
00967 R_M68HC11_NONE);
00968 if (sec->size != old_sec_size)
00969 *again = TRUE;
00970 continue;
00971 }
00972
00973
00974 code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
00975 rinfo = find_relaxable_insn (code);
00976 if (rinfo == 0)
00977 {
00978 prev_insn_group = 0;
00979 continue;
00980 }
00981
00982
00983 elf_section_data (sec)->relocs = internal_relocs;
00984 free_relocs = NULL;
00985
00986 elf_section_data (sec)->this_hdr.contents = contents;
00987 free_contents = NULL;
00988
00989 symtab_hdr->contents = (bfd_byte *) isymbuf;
00990 free_extsyms = NULL;
00991
00992
00993
00994
00995 bfd_put_8 (abfd, rinfo->direct_code,
00996 contents + irel->r_offset - 1);
00997
00998
00999 m68hc11_elf_relax_delete_bytes (abfd, sec, irel->r_offset, 1);
01000
01001
01002 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
01003 R_M68HC11_8);
01004
01005
01006 *again = TRUE;
01007 }
01008 else if (ELF32_R_TYPE (irel->r_info) == R_M68HC11_16 && !is_far)
01009 {
01010 unsigned char code;
01011 bfd_vma offset;
01012
01013 prev_insn_branch = 0;
01014 code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
01015 if (code == 0x7e || code == 0xbd)
01016 {
01017 offset = value - (irel->r_offset
01018 + sec->output_section->vma
01019 + sec->output_offset + 1);
01020 offset += bfd_get_16 (abfd, contents + irel->r_offset);
01021
01022
01023
01024 if ((offset & 0xff80) == 0 || (offset & 0xff80) == 0xff80)
01025 {
01026
01027
01028 elf_section_data (sec)->relocs = internal_relocs;
01029 free_relocs = NULL;
01030
01031 elf_section_data (sec)->this_hdr.contents = contents;
01032 free_contents = NULL;
01033
01034 symtab_hdr->contents = (bfd_byte *) isymbuf;
01035 free_extsyms = NULL;
01036
01037
01038 code = (code == 0x7e) ? 0x20 : 0x8d;
01039 bfd_put_8 (abfd, code,
01040 contents + irel->r_offset - 1);
01041 bfd_put_8 (abfd, 0xff,
01042 contents + irel->r_offset);
01043 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
01044 R_M68HC11_PCREL_8);
01045 m68hc11_elf_relax_delete_bytes (abfd, sec,
01046 irel->r_offset + 1, 1);
01047
01048 *again = TRUE;
01049 }
01050 }
01051 }
01052 prev_insn_branch = 0;
01053 prev_insn_group = 0;
01054 }
01055
01056 if (free_relocs != NULL)
01057 {
01058 free (free_relocs);
01059 free_relocs = NULL;
01060 }
01061
01062 if (free_contents != NULL)
01063 {
01064 if (! link_info->keep_memory)
01065 free (free_contents);
01066 else
01067 {
01068
01069 elf_section_data (sec)->this_hdr.contents = contents;
01070 }
01071 free_contents = NULL;
01072 }
01073
01074 if (free_extsyms != NULL)
01075 {
01076 if (! link_info->keep_memory)
01077 free (free_extsyms);
01078 else
01079 {
01080
01081 symtab_hdr->contents = (unsigned char *) isymbuf;
01082 }
01083 free_extsyms = NULL;
01084 }
01085
01086 return TRUE;
01087
01088 error_return:
01089 if (free_relocs != NULL)
01090 free (free_relocs);
01091 if (free_contents != NULL)
01092 free (free_contents);
01093 if (free_extsyms != NULL)
01094 free (free_extsyms);
01095 return FALSE;
01096 }
01097
01098
01099
01100 static void
01101 m68hc11_elf_relax_delete_bytes (bfd *abfd, asection *sec,
01102 bfd_vma addr, int count)
01103 {
01104 Elf_Internal_Shdr *symtab_hdr;
01105 unsigned int sec_shndx;
01106 bfd_byte *contents;
01107 Elf_Internal_Rela *irel, *irelend;
01108 bfd_vma toaddr;
01109 Elf_Internal_Sym *isymbuf, *isym, *isymend;
01110 struct elf_link_hash_entry **sym_hashes;
01111 struct elf_link_hash_entry **end_hashes;
01112 unsigned int symcount;
01113
01114 symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
01115 isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
01116
01117 sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
01118
01119 contents = elf_section_data (sec)->this_hdr.contents;
01120
01121 toaddr = sec->size;
01122
01123 irel = elf_section_data (sec)->relocs;
01124 irelend = irel + sec->reloc_count;
01125
01126
01127 memmove (contents + addr, contents + addr + count,
01128 (size_t) (toaddr - addr - count));
01129
01130 sec->size -= count;
01131
01132
01133 for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
01134 {
01135 unsigned char code;
01136 unsigned char offset;
01137 unsigned short raddr;
01138 unsigned long old_offset;
01139 int branch_pos;
01140
01141 old_offset = irel->r_offset;
01142
01143
01144
01145
01146 if (ELF32_R_TYPE (irel->r_info) != R_M68HC11_RL_JUMP
01147 && irel->r_offset >= addr && irel->r_offset < addr + count)
01148 irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
01149 R_M68HC11_NONE);
01150
01151 if (ELF32_R_TYPE (irel->r_info) == R_M68HC11_NONE)
01152 continue;
01153
01154
01155 if ((irel->r_offset > addr
01156 && irel->r_offset < toaddr))
01157 irel->r_offset -= count;
01158
01159
01160
01161 switch (ELF32_R_TYPE (irel->r_info))
01162 {
01163 default:
01164 break;
01165
01166 case R_M68HC11_RL_JUMP:
01167 code = bfd_get_8 (abfd, contents + irel->r_offset);
01168 switch (code)
01169 {
01170
01171
01172 case 0x7e:
01173 case 0x9d:
01174 case 0xbd:
01175 continue;
01176
01177 case 0x12:
01178 case 0x13:
01179 branch_pos = 3;
01180 raddr = 4;
01181
01182
01183
01184
01185
01186 if (old_offset == addr)
01187 raddr++;
01188 break;
01189
01190 case 0x1e:
01191 case 0x1f:
01192 branch_pos = 3;
01193 raddr = 4;
01194 break;
01195
01196 case 0x18:
01197 branch_pos = 4;
01198 raddr = 5;
01199 break;
01200
01201 default:
01202 branch_pos = 1;
01203 raddr = 2;
01204 break;
01205 }
01206 offset = bfd_get_8 (abfd, contents + irel->r_offset + branch_pos);
01207 raddr += old_offset;
01208 raddr += ((unsigned short) offset | ((offset & 0x80) ? 0xff00 : 0));
01209 if (irel->r_offset < addr && raddr > addr)
01210 {
01211 offset -= count;
01212 bfd_put_8 (abfd, offset, contents + irel->r_offset + branch_pos);
01213 }
01214 else if (irel->r_offset >= addr && raddr <= addr)
01215 {
01216 offset += count;
01217 bfd_put_8 (abfd, offset, contents + irel->r_offset + branch_pos);
01218 }
01219 else
01220 {
01221
01222
01223 }
01224
01225 break;
01226 }
01227 }
01228
01229
01230 isymend = isymbuf + symtab_hdr->sh_info;
01231 for (isym = isymbuf; isym < isymend; isym++)
01232 {
01233 if (isym->st_shndx == sec_shndx
01234 && isym->st_value > addr
01235 && isym->st_value <= toaddr)
01236 isym->st_value -= count;
01237 }
01238
01239
01240 symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
01241 - symtab_hdr->sh_info);
01242 sym_hashes = elf_sym_hashes (abfd);
01243 end_hashes = sym_hashes + symcount;
01244 for (; sym_hashes < end_hashes; sym_hashes++)
01245 {
01246 struct elf_link_hash_entry *sym_hash = *sym_hashes;
01247 if ((sym_hash->root.type == bfd_link_hash_defined
01248 || sym_hash->root.type == bfd_link_hash_defweak)
01249 && sym_hash->root.u.def.section == sec
01250 && sym_hash->root.u.def.value > addr
01251 && sym_hash->root.u.def.value <= toaddr)
01252 {
01253 sym_hash->root.u.def.value -= count;
01254 }
01255 }
01256 }
01257
01258
01259
01260
01261
01262
01263
01264 static struct bfd_elf_special_section const elf32_m68hc11_special_sections[]=
01265 {
01266 { ".eeprom", 7, 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
01267 { ".softregs", 9, 0, SHT_NOBITS, SHF_ALLOC + SHF_WRITE },
01268 { ".page0", 6, 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
01269 { ".vectors", 8, 0, SHT_PROGBITS, SHF_ALLOC },
01270 { NULL, 0, 0, 0, 0 }
01271 };
01272
01273 #define ELF_ARCH bfd_arch_m68hc11
01274 #define ELF_MACHINE_CODE EM_68HC11
01275 #define ELF_MAXPAGESIZE 0x1000
01276
01277 #define TARGET_BIG_SYM bfd_elf32_m68hc11_vec
01278 #define TARGET_BIG_NAME "elf32-m68hc11"
01279
01280 #define elf_info_to_howto 0
01281 #define elf_info_to_howto_rel m68hc11_info_to_howto_rel
01282 #define bfd_elf32_bfd_relax_section m68hc11_elf_relax_section
01283 #define elf_backend_gc_mark_hook elf32_m68hc11_gc_mark_hook
01284 #define elf_backend_gc_sweep_hook elf32_m68hc11_gc_sweep_hook
01285 #define elf_backend_check_relocs elf32_m68hc11_check_relocs
01286 #define elf_backend_relocate_section elf32_m68hc11_relocate_section
01287 #define elf_backend_add_symbol_hook elf32_m68hc11_add_symbol_hook
01288 #define elf_backend_object_p 0
01289 #define elf_backend_final_write_processing 0
01290 #define elf_backend_can_gc_sections 1
01291 #define elf_backend_special_sections elf32_m68hc11_special_sections
01292
01293 #define bfd_elf32_bfd_link_hash_table_create \
01294 m68hc11_elf_bfd_link_hash_table_create
01295 #define bfd_elf32_bfd_link_hash_table_free \
01296 m68hc11_elf_bfd_link_hash_table_free
01297 #define bfd_elf32_bfd_merge_private_bfd_data \
01298 _bfd_m68hc11_elf_merge_private_bfd_data
01299 #define bfd_elf32_bfd_set_private_flags _bfd_m68hc11_elf_set_private_flags
01300 #define bfd_elf32_bfd_print_private_bfd_data \
01301 _bfd_m68hc11_elf_print_private_bfd_data
01302
01303 #include "elf32-target.h"