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 #include "bfd.h"
00027 #include "sysdep.h"
00028 #include "bfdlink.h"
00029 #include "libbfd.h"
00030 #include "elf-bfd.h"
00031 #include "elf32-m68hc1x.h"
00032 #include "elf/m68hc11.h"
00033 #include "opcode/m68hc11.h"
00034
00035
00036 #define m68hc12_stub_hash_lookup(table, string, create, copy) \
00037 ((struct elf32_m68hc11_stub_hash_entry *) \
00038 bfd_hash_lookup ((table), (string), (create), (copy)))
00039
00040 static struct elf32_m68hc11_stub_hash_entry* m68hc12_add_stub
00041 (const char *stub_name,
00042 asection *section,
00043 struct m68hc11_elf_link_hash_table *htab);
00044
00045 static struct bfd_hash_entry *stub_hash_newfunc
00046 (struct bfd_hash_entry *, struct bfd_hash_table *, const char *);
00047
00048 static void m68hc11_elf_set_symbol (bfd* abfd, struct bfd_link_info *info,
00049 const char* name, bfd_vma value,
00050 asection* sec);
00051
00052 static bfd_boolean m68hc11_elf_export_one_stub
00053 (struct bfd_hash_entry *gen_entry, void *in_arg);
00054
00055 static void scan_sections_for_abi (bfd*, asection*, PTR);
00056
00057 struct m68hc11_scan_param
00058 {
00059 struct m68hc11_page_info* pinfo;
00060 bfd_boolean use_memory_banks;
00061 };
00062
00063
00064
00065
00066 struct m68hc11_elf_link_hash_table*
00067 m68hc11_elf_hash_table_create (bfd *abfd)
00068 {
00069 struct m68hc11_elf_link_hash_table *ret;
00070 bfd_size_type amt = sizeof (struct m68hc11_elf_link_hash_table);
00071
00072 ret = (struct m68hc11_elf_link_hash_table *) bfd_malloc (amt);
00073 if (ret == (struct m68hc11_elf_link_hash_table *) NULL)
00074 return NULL;
00075
00076 memset (ret, 0, amt);
00077 if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,
00078 _bfd_elf_link_hash_newfunc))
00079 {
00080 free (ret);
00081 return NULL;
00082 }
00083
00084
00085 amt = sizeof (struct bfd_hash_table);
00086 ret->stub_hash_table = (struct bfd_hash_table*) bfd_malloc (amt);
00087 if (ret->stub_hash_table == NULL)
00088 {
00089 free (ret);
00090 return NULL;
00091 }
00092 if (!bfd_hash_table_init (ret->stub_hash_table, stub_hash_newfunc))
00093 return NULL;
00094
00095 ret->stub_bfd = NULL;
00096 ret->stub_section = 0;
00097 ret->add_stub_section = NULL;
00098 ret->sym_sec.abfd = NULL;
00099
00100 return ret;
00101 }
00102
00103
00104
00105 void
00106 m68hc11_elf_bfd_link_hash_table_free (struct bfd_link_hash_table *hash)
00107 {
00108 struct m68hc11_elf_link_hash_table *ret
00109 = (struct m68hc11_elf_link_hash_table *) hash;
00110
00111 bfd_hash_table_free (ret->stub_hash_table);
00112 free (ret->stub_hash_table);
00113 _bfd_generic_link_hash_table_free (hash);
00114 }
00115
00116
00117
00118
00119
00120 static struct bfd_hash_entry *
00121 stub_hash_newfunc (struct bfd_hash_entry *entry, struct bfd_hash_table *table,
00122 const char *string)
00123 {
00124
00125
00126 if (entry == NULL)
00127 {
00128 entry = bfd_hash_allocate (table,
00129 sizeof (struct elf32_m68hc11_stub_hash_entry));
00130 if (entry == NULL)
00131 return entry;
00132 }
00133
00134
00135 entry = bfd_hash_newfunc (entry, table, string);
00136 if (entry != NULL)
00137 {
00138 struct elf32_m68hc11_stub_hash_entry *eh;
00139
00140
00141 eh = (struct elf32_m68hc11_stub_hash_entry *) entry;
00142 eh->stub_sec = NULL;
00143 eh->stub_offset = 0;
00144 eh->target_value = 0;
00145 eh->target_section = NULL;
00146 }
00147
00148 return entry;
00149 }
00150
00151
00152
00153
00154 static struct elf32_m68hc11_stub_hash_entry *
00155 m68hc12_add_stub (const char *stub_name, asection *section,
00156 struct m68hc11_elf_link_hash_table *htab)
00157 {
00158 struct elf32_m68hc11_stub_hash_entry *stub_entry;
00159
00160
00161 stub_entry = m68hc12_stub_hash_lookup (htab->stub_hash_table, stub_name,
00162 TRUE, FALSE);
00163 if (stub_entry == NULL)
00164 {
00165 (*_bfd_error_handler) (_("%B: cannot create stub entry %s"),
00166 section->owner, stub_name);
00167 return NULL;
00168 }
00169
00170 if (htab->stub_section == 0)
00171 {
00172 htab->stub_section = (*htab->add_stub_section) (".tramp",
00173 htab->tramp_section);
00174 }
00175
00176 stub_entry->stub_sec = htab->stub_section;
00177 stub_entry->stub_offset = 0;
00178 return stub_entry;
00179 }
00180
00181
00182
00183
00184
00185 bfd_boolean
00186 elf32_m68hc11_add_symbol_hook (bfd *abfd, struct bfd_link_info *info,
00187 Elf_Internal_Sym *sym,
00188 const char **namep ATTRIBUTE_UNUSED,
00189 flagword *flagsp ATTRIBUTE_UNUSED,
00190 asection **secp ATTRIBUTE_UNUSED,
00191 bfd_vma *valp ATTRIBUTE_UNUSED)
00192 {
00193 if (sym->st_other & STO_M68HC12_FAR)
00194 {
00195 struct elf_link_hash_entry *h;
00196
00197 h = (struct elf_link_hash_entry *)
00198 bfd_link_hash_lookup (info->hash, "__far_trampoline",
00199 FALSE, FALSE, FALSE);
00200 if (h == NULL)
00201 {
00202 struct bfd_link_hash_entry* entry = NULL;
00203
00204 _bfd_generic_link_add_one_symbol (info, abfd,
00205 "__far_trampoline",
00206 BSF_GLOBAL,
00207 bfd_und_section_ptr,
00208 (bfd_vma) 0, (const char*) NULL,
00209 FALSE, FALSE, &entry);
00210 }
00211
00212 }
00213 return TRUE;
00214 }
00215
00216
00217
00218
00219
00220
00221
00222 int
00223 elf32_m68hc11_setup_section_lists (bfd *output_bfd, struct bfd_link_info *info)
00224 {
00225 bfd *input_bfd;
00226 unsigned int bfd_count;
00227 int top_id, top_index;
00228 asection *section;
00229 asection **input_list, **list;
00230 bfd_size_type amt;
00231 asection *text_section;
00232 struct m68hc11_elf_link_hash_table *htab;
00233
00234 htab = m68hc11_elf_hash_table (info);
00235
00236 if (htab->root.root.creator->flavour != bfd_target_elf_flavour)
00237 return 0;
00238
00239
00240
00241
00242
00243 htab->tramp_section = 0;
00244 text_section = 0;
00245 for (input_bfd = info->input_bfds, bfd_count = 0, top_id = 0;
00246 input_bfd != NULL;
00247 input_bfd = input_bfd->link_next)
00248 {
00249 bfd_count += 1;
00250 for (section = input_bfd->sections;
00251 section != NULL;
00252 section = section->next)
00253 {
00254 const char* name = bfd_get_section_name (input_bfd, section);
00255
00256 if (!strcmp (name, ".tramp"))
00257 htab->tramp_section = section;
00258
00259 if (!strcmp (name, ".text"))
00260 text_section = section;
00261
00262 if (top_id < section->id)
00263 top_id = section->id;
00264 }
00265 }
00266 htab->bfd_count = bfd_count;
00267 if (htab->tramp_section == 0)
00268 htab->tramp_section = text_section;
00269
00270
00271
00272
00273 for (section = output_bfd->sections, top_index = 0;
00274 section != NULL;
00275 section = section->next)
00276 {
00277 if (top_index < section->index)
00278 top_index = section->index;
00279 }
00280
00281 htab->top_index = top_index;
00282 amt = sizeof (asection *) * (top_index + 1);
00283 input_list = (asection **) bfd_malloc (amt);
00284 htab->input_list = input_list;
00285 if (input_list == NULL)
00286 return -1;
00287
00288
00289
00290 list = input_list + top_index;
00291 do
00292 *list = bfd_abs_section_ptr;
00293 while (list-- != input_list);
00294
00295 for (section = output_bfd->sections;
00296 section != NULL;
00297 section = section->next)
00298 {
00299 if ((section->flags & SEC_CODE) != 0)
00300 input_list[section->index] = NULL;
00301 }
00302
00303 return 1;
00304 }
00305
00306
00307
00308
00309
00310
00311
00312 bfd_boolean
00313 elf32_m68hc11_size_stubs (bfd *output_bfd, bfd *stub_bfd,
00314 struct bfd_link_info *info,
00315 asection * (*add_stub_section) (const char*, asection*))
00316 {
00317 bfd *input_bfd;
00318 asection *section;
00319 Elf_Internal_Sym *local_syms, **all_local_syms;
00320 unsigned int bfd_indx, bfd_count;
00321 bfd_size_type amt;
00322 asection *stub_sec;
00323
00324 struct m68hc11_elf_link_hash_table *htab = m68hc11_elf_hash_table (info);
00325
00326
00327 htab->stub_bfd = stub_bfd;
00328 htab->add_stub_section = add_stub_section;
00329
00330
00331 for (input_bfd = info->input_bfds, bfd_count = 0;
00332 input_bfd != NULL;
00333 input_bfd = input_bfd->link_next)
00334 {
00335 bfd_count += 1;
00336 }
00337
00338
00339
00340
00341 amt = sizeof (Elf_Internal_Sym *) * bfd_count;
00342 all_local_syms = (Elf_Internal_Sym **) bfd_zmalloc (amt);
00343 if (all_local_syms == NULL)
00344 return FALSE;
00345
00346
00347 for (input_bfd = info->input_bfds, bfd_indx = 0;
00348 input_bfd != NULL;
00349 input_bfd = input_bfd->link_next, bfd_indx++)
00350 {
00351 Elf_Internal_Shdr *symtab_hdr;
00352
00353
00354 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
00355 if (symtab_hdr->sh_info == 0)
00356 continue;
00357
00358
00359 local_syms = (Elf_Internal_Sym *) symtab_hdr->contents;
00360 if (local_syms == NULL)
00361 {
00362 local_syms = bfd_elf_get_elf_syms (input_bfd, symtab_hdr,
00363 symtab_hdr->sh_info, 0,
00364 NULL, NULL, NULL);
00365
00366 symtab_hdr->contents = (unsigned char *) local_syms;
00367 }
00368 if (local_syms == NULL)
00369 {
00370 free (all_local_syms);
00371 return FALSE;
00372 }
00373
00374 all_local_syms[bfd_indx] = local_syms;
00375 }
00376
00377 for (input_bfd = info->input_bfds, bfd_indx = 0;
00378 input_bfd != NULL;
00379 input_bfd = input_bfd->link_next, bfd_indx++)
00380 {
00381 Elf_Internal_Shdr *symtab_hdr;
00382 Elf_Internal_Sym *local_syms;
00383 struct elf_link_hash_entry ** sym_hashes;
00384
00385 sym_hashes = elf_sym_hashes (input_bfd);
00386
00387
00388 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
00389 if (symtab_hdr->sh_info == 0)
00390 continue;
00391
00392 local_syms = all_local_syms[bfd_indx];
00393
00394
00395 for (section = input_bfd->sections;
00396 section != NULL;
00397 section = section->next)
00398 {
00399 Elf_Internal_Rela *internal_relocs, *irelaend, *irela;
00400
00401
00402
00403 if ((section->flags & SEC_RELOC) == 0
00404 || section->reloc_count == 0)
00405 continue;
00406
00407
00408
00409 if (section->output_section == NULL
00410 || section->output_section->owner != output_bfd)
00411 continue;
00412
00413
00414 internal_relocs
00415 = _bfd_elf_link_read_relocs (input_bfd, section, NULL,
00416 (Elf_Internal_Rela *) NULL,
00417 info->keep_memory);
00418 if (internal_relocs == NULL)
00419 goto error_ret_free_local;
00420
00421
00422 irela = internal_relocs;
00423 irelaend = irela + section->reloc_count;
00424 for (; irela < irelaend; irela++)
00425 {
00426 unsigned int r_type, r_indx;
00427 struct elf32_m68hc11_stub_hash_entry *stub_entry;
00428 asection *sym_sec;
00429 bfd_vma sym_value;
00430 struct elf_link_hash_entry *hash;
00431 const char *stub_name;
00432 Elf_Internal_Sym *sym;
00433
00434 r_type = ELF32_R_TYPE (irela->r_info);
00435
00436
00437 if (r_type != (unsigned int) R_M68HC11_16)
00438 continue;
00439
00440
00441
00442 r_indx = ELF32_R_SYM (irela->r_info);
00443 if (r_indx < symtab_hdr->sh_info)
00444 {
00445
00446 Elf_Internal_Shdr *hdr;
00447 bfd_boolean is_far;
00448
00449 sym = local_syms + r_indx;
00450 is_far = (sym && (sym->st_other & STO_M68HC12_FAR));
00451 if (!is_far)
00452 continue;
00453
00454 hdr = elf_elfsections (input_bfd)[sym->st_shndx];
00455 sym_sec = hdr->bfd_section;
00456 stub_name = (bfd_elf_string_from_elf_section
00457 (input_bfd, symtab_hdr->sh_link,
00458 sym->st_name));
00459 sym_value = sym->st_value;
00460 hash = NULL;
00461 }
00462 else
00463 {
00464
00465 int e_indx;
00466
00467 e_indx = r_indx - symtab_hdr->sh_info;
00468 hash = (struct elf_link_hash_entry *)
00469 (sym_hashes[e_indx]);
00470
00471 while (hash->root.type == bfd_link_hash_indirect
00472 || hash->root.type == bfd_link_hash_warning)
00473 hash = ((struct elf_link_hash_entry *)
00474 hash->root.u.i.link);
00475
00476 if (hash->root.type == bfd_link_hash_defined
00477 || hash->root.type == bfd_link_hash_defweak
00478 || hash->root.type == bfd_link_hash_new)
00479 {
00480 if (!(hash->other & STO_M68HC12_FAR))
00481 continue;
00482 }
00483 else if (hash->root.type == bfd_link_hash_undefweak)
00484 {
00485 continue;
00486 }
00487 else if (hash->root.type == bfd_link_hash_undefined)
00488 {
00489 continue;
00490 }
00491 else
00492 {
00493 bfd_set_error (bfd_error_bad_value);
00494 goto error_ret_free_internal;
00495 }
00496 sym_sec = hash->root.u.def.section;
00497 sym_value = hash->root.u.def.value;
00498 stub_name = hash->root.root.string;
00499 }
00500
00501 if (!stub_name)
00502 goto error_ret_free_internal;
00503
00504 stub_entry = m68hc12_stub_hash_lookup
00505 (htab->stub_hash_table,
00506 stub_name,
00507 FALSE, FALSE);
00508 if (stub_entry == NULL)
00509 {
00510 if (add_stub_section == 0)
00511 continue;
00512
00513 stub_entry = m68hc12_add_stub (stub_name, section, htab);
00514 if (stub_entry == NULL)
00515 {
00516 error_ret_free_internal:
00517 if (elf_section_data (section)->relocs == NULL)
00518 free (internal_relocs);
00519 goto error_ret_free_local;
00520 }
00521 }
00522
00523 stub_entry->target_value = sym_value;
00524 stub_entry->target_section = sym_sec;
00525 }
00526
00527
00528 if (elf_section_data (section)->relocs == NULL)
00529 free (internal_relocs);
00530 }
00531 }
00532
00533 if (add_stub_section)
00534 {
00535
00536
00537 for (stub_sec = htab->stub_bfd->sections;
00538 stub_sec != NULL;
00539 stub_sec = stub_sec->next)
00540 {
00541 stub_sec->size = 0;
00542 }
00543
00544 bfd_hash_traverse (htab->stub_hash_table, htab->size_one_stub, htab);
00545 }
00546 free (all_local_syms);
00547 return TRUE;
00548
00549 error_ret_free_local:
00550 free (all_local_syms);
00551 return FALSE;
00552 }
00553
00554
00555 static bfd_boolean
00556 m68hc11_elf_export_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
00557 {
00558 struct bfd_link_info *info;
00559 struct m68hc11_elf_link_hash_table *htab;
00560 struct elf32_m68hc11_stub_hash_entry *stub_entry;
00561 char* name;
00562 bfd_boolean result;
00563
00564 info = (struct bfd_link_info *) in_arg;
00565 htab = m68hc11_elf_hash_table (info);
00566
00567
00568 stub_entry = (struct elf32_m68hc11_stub_hash_entry *) gen_entry;
00569
00570
00571 result = (* htab->build_one_stub) (gen_entry, in_arg);
00572
00573
00574 name = alloca (strlen (stub_entry->root.string) + 16);
00575 sprintf (name, "tramp.%s", stub_entry->root.string);
00576
00577
00578 m68hc11_elf_set_symbol (htab->stub_bfd, info, name,
00579 stub_entry->stub_offset,
00580 stub_entry->stub_sec);
00581 return result;
00582 }
00583
00584
00585 static void
00586 m68hc11_elf_set_symbol (bfd *abfd, struct bfd_link_info *info,
00587 const char *name, bfd_vma value, asection *sec)
00588 {
00589 struct elf_link_hash_entry *h;
00590
00591 h = (struct elf_link_hash_entry *)
00592 bfd_link_hash_lookup (info->hash, name, FALSE, FALSE, FALSE);
00593 if (h == NULL)
00594 {
00595 _bfd_generic_link_add_one_symbol (info, abfd,
00596 name,
00597 BSF_GLOBAL,
00598 sec,
00599 value,
00600 (const char*) NULL,
00601 TRUE, FALSE, NULL);
00602 }
00603 else
00604 {
00605 h->root.type = bfd_link_hash_defined;
00606 h->root.u.def.value = value;
00607 h->root.u.def.section = sec;
00608 }
00609 }
00610
00611
00612
00613
00614
00615
00616
00617 bfd_boolean
00618 elf32_m68hc11_build_stubs (bfd *abfd, struct bfd_link_info *info)
00619 {
00620 asection *stub_sec;
00621 struct bfd_hash_table *table;
00622 struct m68hc11_elf_link_hash_table *htab;
00623 struct m68hc11_scan_param param;
00624
00625 m68hc11_elf_get_bank_parameters (info);
00626 htab = m68hc11_elf_hash_table (info);
00627
00628 for (stub_sec = htab->stub_bfd->sections;
00629 stub_sec != NULL;
00630 stub_sec = stub_sec->next)
00631 {
00632 bfd_size_type size;
00633
00634
00635 size = stub_sec->size;
00636 stub_sec->contents = (unsigned char *) bfd_zalloc (htab->stub_bfd, size);
00637 if (stub_sec->contents == NULL && size != 0)
00638 return FALSE;
00639 stub_sec->size = 0;
00640 }
00641
00642
00643 table = htab->stub_hash_table;
00644 bfd_hash_traverse (table, m68hc11_elf_export_one_stub, info);
00645
00646
00647
00648
00649
00650
00651 param.use_memory_banks = FALSE;
00652 param.pinfo = &htab->pinfo;
00653 bfd_map_over_sections (abfd, scan_sections_for_abi, ¶m);
00654 if (param.use_memory_banks)
00655 {
00656 m68hc11_elf_set_symbol (abfd, info, BFD_M68HC11_BANK_START_NAME,
00657 htab->pinfo.bank_physical,
00658 bfd_abs_section_ptr);
00659 m68hc11_elf_set_symbol (abfd, info, BFD_M68HC11_BANK_VIRTUAL_NAME,
00660 htab->pinfo.bank_virtual,
00661 bfd_abs_section_ptr);
00662 m68hc11_elf_set_symbol (abfd, info, BFD_M68HC11_BANK_SIZE_NAME,
00663 htab->pinfo.bank_size,
00664 bfd_abs_section_ptr);
00665 }
00666
00667 return TRUE;
00668 }
00669
00670 void
00671 m68hc11_elf_get_bank_parameters (struct bfd_link_info *info)
00672 {
00673 unsigned i;
00674 struct m68hc11_page_info *pinfo;
00675 struct bfd_link_hash_entry *h;
00676
00677 pinfo = &m68hc11_elf_hash_table (info)->pinfo;
00678 if (pinfo->bank_param_initialized)
00679 return;
00680
00681 pinfo->bank_virtual = M68HC12_BANK_VIRT;
00682 pinfo->bank_mask = M68HC12_BANK_MASK;
00683 pinfo->bank_physical = M68HC12_BANK_BASE;
00684 pinfo->bank_shift = M68HC12_BANK_SHIFT;
00685 pinfo->bank_size = 1 << M68HC12_BANK_SHIFT;
00686
00687 h = bfd_link_hash_lookup (info->hash, BFD_M68HC11_BANK_START_NAME,
00688 FALSE, FALSE, TRUE);
00689 if (h != (struct bfd_link_hash_entry*) NULL
00690 && h->type == bfd_link_hash_defined)
00691 pinfo->bank_physical = (h->u.def.value
00692 + h->u.def.section->output_section->vma
00693 + h->u.def.section->output_offset);
00694
00695 h = bfd_link_hash_lookup (info->hash, BFD_M68HC11_BANK_VIRTUAL_NAME,
00696 FALSE, FALSE, TRUE);
00697 if (h != (struct bfd_link_hash_entry*) NULL
00698 && h->type == bfd_link_hash_defined)
00699 pinfo->bank_virtual = (h->u.def.value
00700 + h->u.def.section->output_section->vma
00701 + h->u.def.section->output_offset);
00702
00703 h = bfd_link_hash_lookup (info->hash, BFD_M68HC11_BANK_SIZE_NAME,
00704 FALSE, FALSE, TRUE);
00705 if (h != (struct bfd_link_hash_entry*) NULL
00706 && h->type == bfd_link_hash_defined)
00707 pinfo->bank_size = (h->u.def.value
00708 + h->u.def.section->output_section->vma
00709 + h->u.def.section->output_offset);
00710
00711 pinfo->bank_shift = 0;
00712 for (i = pinfo->bank_size; i != 0; i >>= 1)
00713 pinfo->bank_shift++;
00714 pinfo->bank_shift--;
00715 pinfo->bank_mask = (1 << pinfo->bank_shift) - 1;
00716 pinfo->bank_physical_end = pinfo->bank_physical + pinfo->bank_size;
00717 pinfo->bank_param_initialized = 1;
00718
00719 h = bfd_link_hash_lookup (info->hash, "__far_trampoline", FALSE,
00720 FALSE, TRUE);
00721 if (h != (struct bfd_link_hash_entry*) NULL
00722 && h->type == bfd_link_hash_defined)
00723 pinfo->trampoline_addr = (h->u.def.value
00724 + h->u.def.section->output_section->vma
00725 + h->u.def.section->output_offset);
00726 }
00727
00728
00729
00730 int
00731 m68hc11_addr_is_banked (struct m68hc11_page_info *pinfo, bfd_vma addr)
00732 {
00733 if (addr >= pinfo->bank_virtual)
00734 return 1;
00735
00736 if (addr >= pinfo->bank_physical && addr <= pinfo->bank_physical_end)
00737 return 1;
00738
00739 return 0;
00740 }
00741
00742
00743
00744 bfd_vma
00745 m68hc11_phys_addr (struct m68hc11_page_info *pinfo, bfd_vma addr)
00746 {
00747 if (addr < pinfo->bank_virtual)
00748 return addr;
00749
00750
00751 addr -= pinfo->bank_virtual;
00752 addr &= pinfo->bank_mask;
00753 addr += pinfo->bank_physical;
00754 return addr;
00755 }
00756
00757
00758 bfd_vma
00759 m68hc11_phys_page (struct m68hc11_page_info *pinfo, bfd_vma addr)
00760 {
00761 if (addr < pinfo->bank_virtual)
00762 return 0;
00763
00764
00765 addr -= pinfo->bank_virtual;
00766 addr >>= pinfo->bank_shift;
00767 addr &= 0x0ff;
00768 return addr;
00769 }
00770
00771
00772
00773
00774 bfd_reloc_status_type
00775 m68hc11_elf_ignore_reloc (bfd *abfd ATTRIBUTE_UNUSED,
00776 arelent *reloc_entry,
00777 asymbol *symbol ATTRIBUTE_UNUSED,
00778 void *data ATTRIBUTE_UNUSED,
00779 asection *input_section,
00780 bfd *output_bfd,
00781 char **error_message ATTRIBUTE_UNUSED)
00782 {
00783 if (output_bfd != NULL)
00784 reloc_entry->address += input_section->output_offset;
00785 return bfd_reloc_ok;
00786 }
00787
00788 bfd_reloc_status_type
00789 m68hc11_elf_special_reloc (bfd *abfd ATTRIBUTE_UNUSED,
00790 arelent *reloc_entry,
00791 asymbol *symbol,
00792 void *data ATTRIBUTE_UNUSED,
00793 asection *input_section,
00794 bfd *output_bfd,
00795 char **error_message ATTRIBUTE_UNUSED)
00796 {
00797 if (output_bfd != (bfd *) NULL
00798 && (symbol->flags & BSF_SECTION_SYM) == 0
00799 && (! reloc_entry->howto->partial_inplace
00800 || reloc_entry->addend == 0))
00801 {
00802 reloc_entry->address += input_section->output_offset;
00803 return bfd_reloc_ok;
00804 }
00805
00806 if (output_bfd != NULL)
00807 return bfd_reloc_continue;
00808
00809 if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
00810 return bfd_reloc_outofrange;
00811
00812 abort();
00813 }
00814
00815 asection *
00816 elf32_m68hc11_gc_mark_hook (asection *sec,
00817 struct bfd_link_info *info ATTRIBUTE_UNUSED,
00818 Elf_Internal_Rela *rel,
00819 struct elf_link_hash_entry *h,
00820 Elf_Internal_Sym *sym)
00821 {
00822 if (h != NULL)
00823 {
00824 switch (ELF32_R_TYPE (rel->r_info))
00825 {
00826 default:
00827 switch (h->root.type)
00828 {
00829 case bfd_link_hash_defined:
00830 case bfd_link_hash_defweak:
00831 return h->root.u.def.section;
00832
00833 case bfd_link_hash_common:
00834 return h->root.u.c.p->section;
00835
00836 default:
00837 break;
00838 }
00839 }
00840 }
00841 else
00842 return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
00843
00844 return NULL;
00845 }
00846
00847 bfd_boolean
00848 elf32_m68hc11_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED,
00849 struct bfd_link_info *info ATTRIBUTE_UNUSED,
00850 asection *sec ATTRIBUTE_UNUSED,
00851 const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED)
00852 {
00853
00854 return TRUE;
00855 }
00856
00857
00858
00859
00860
00861 bfd_boolean
00862 elf32_m68hc11_check_relocs (bfd *abfd, struct bfd_link_info *info,
00863 asection *sec, const Elf_Internal_Rela *relocs)
00864 {
00865 Elf_Internal_Shdr * symtab_hdr;
00866 struct elf_link_hash_entry ** sym_hashes;
00867 struct elf_link_hash_entry ** sym_hashes_end;
00868 const Elf_Internal_Rela * rel;
00869 const Elf_Internal_Rela * rel_end;
00870
00871 if (info->relocatable)
00872 return TRUE;
00873
00874 symtab_hdr = & elf_tdata (abfd)->symtab_hdr;
00875 sym_hashes = elf_sym_hashes (abfd);
00876 sym_hashes_end = sym_hashes + symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
00877 if (!elf_bad_symtab (abfd))
00878 sym_hashes_end -= symtab_hdr->sh_info;
00879
00880 rel_end = relocs + sec->reloc_count;
00881
00882 for (rel = relocs; rel < rel_end; rel++)
00883 {
00884 struct elf_link_hash_entry * h;
00885 unsigned long r_symndx;
00886
00887 r_symndx = ELF32_R_SYM (rel->r_info);
00888
00889 if (r_symndx < symtab_hdr->sh_info)
00890 h = NULL;
00891 else
00892 h = sym_hashes [r_symndx - symtab_hdr->sh_info];
00893
00894 switch (ELF32_R_TYPE (rel->r_info))
00895 {
00896
00897
00898 case R_M68HC11_GNU_VTINHERIT:
00899 if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
00900 return FALSE;
00901 break;
00902
00903
00904
00905 case R_M68HC11_GNU_VTENTRY:
00906 if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
00907 return FALSE;
00908 break;
00909 }
00910 }
00911
00912 return TRUE;
00913 }
00914
00915 static bfd_boolean
00916 m68hc11_get_relocation_value (bfd *input_bfd, struct bfd_link_info *info,
00917 asection *input_section,
00918 asection **local_sections,
00919 Elf_Internal_Sym *local_syms,
00920 Elf_Internal_Rela *rel,
00921 const char **name,
00922 bfd_vma *relocation, bfd_boolean *is_far)
00923 {
00924 Elf_Internal_Shdr *symtab_hdr;
00925 struct elf_link_hash_entry **sym_hashes;
00926 unsigned long r_symndx;
00927 asection *sec;
00928 struct elf_link_hash_entry *h;
00929 Elf_Internal_Sym *sym;
00930 const char* stub_name = 0;
00931
00932 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
00933 sym_hashes = elf_sym_hashes (input_bfd);
00934
00935 r_symndx = ELF32_R_SYM (rel->r_info);
00936
00937
00938 h = NULL;
00939 sym = NULL;
00940 sec = NULL;
00941 if (r_symndx < symtab_hdr->sh_info)
00942 {
00943 sym = local_syms + r_symndx;
00944 sec = local_sections[r_symndx];
00945 *relocation = (sec->output_section->vma
00946 + sec->output_offset
00947 + sym->st_value);
00948 *is_far = (sym && (sym->st_other & STO_M68HC12_FAR));
00949 if (*is_far)
00950 stub_name = (bfd_elf_string_from_elf_section
00951 (input_bfd, symtab_hdr->sh_link,
00952 sym->st_name));
00953 }
00954 else
00955 {
00956 bfd_boolean unresolved_reloc, warned;
00957
00958 RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
00959 r_symndx, symtab_hdr, sym_hashes,
00960 h, sec, *relocation, unresolved_reloc, warned);
00961
00962 *is_far = (h && (h->other & STO_M68HC12_FAR));
00963 stub_name = h->root.root.string;
00964 }
00965
00966 if (h != NULL)
00967 *name = h->root.root.string;
00968 else
00969 {
00970 *name = (bfd_elf_string_from_elf_section
00971 (input_bfd, symtab_hdr->sh_link, sym->st_name));
00972 if (*name == NULL || **name == '\0')
00973 *name = bfd_section_name (input_bfd, sec);
00974 }
00975
00976 if (*is_far && ELF32_R_TYPE (rel->r_info) == R_M68HC11_16)
00977 {
00978 struct elf32_m68hc11_stub_hash_entry* stub;
00979 struct m68hc11_elf_link_hash_table *htab;
00980
00981 htab = m68hc11_elf_hash_table (info);
00982 stub = m68hc12_stub_hash_lookup (htab->stub_hash_table,
00983 *name, FALSE, FALSE);
00984 if (stub)
00985 {
00986 *relocation = stub->stub_offset
00987 + stub->stub_sec->output_section->vma
00988 + stub->stub_sec->output_offset;
00989 *is_far = FALSE;
00990 }
00991 }
00992 return TRUE;
00993 }
00994
00995
00996 bfd_boolean
00997 elf32_m68hc11_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
00998 struct bfd_link_info *info,
00999 bfd *input_bfd, asection *input_section,
01000 bfd_byte *contents, Elf_Internal_Rela *relocs,
01001 Elf_Internal_Sym *local_syms,
01002 asection **local_sections)
01003 {
01004 Elf_Internal_Shdr *symtab_hdr;
01005 struct elf_link_hash_entry **sym_hashes;
01006 Elf_Internal_Rela *rel, *relend;
01007 const char *name = NULL;
01008 struct m68hc11_page_info *pinfo;
01009 const struct elf_backend_data * const ebd = get_elf_backend_data (input_bfd);
01010
01011 symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
01012 sym_hashes = elf_sym_hashes (input_bfd);
01013
01014
01015 m68hc11_elf_get_bank_parameters (info);
01016 pinfo = &m68hc11_elf_hash_table (info)->pinfo;
01017
01018 rel = relocs;
01019 relend = relocs + input_section->reloc_count;
01020 for (; rel < relend; rel++)
01021 {
01022 int r_type;
01023 arelent arel;
01024 reloc_howto_type *howto;
01025 unsigned long r_symndx;
01026 Elf_Internal_Sym *sym;
01027 asection *sec;
01028 bfd_vma relocation = 0;
01029 bfd_reloc_status_type r = bfd_reloc_undefined;
01030 bfd_vma phys_page;
01031 bfd_vma phys_addr;
01032 bfd_vma insn_addr;
01033 bfd_vma insn_page;
01034 bfd_boolean is_far = FALSE;
01035
01036 r_symndx = ELF32_R_SYM (rel->r_info);
01037 r_type = ELF32_R_TYPE (rel->r_info);
01038
01039 if (r_type == R_M68HC11_GNU_VTENTRY
01040 || r_type == R_M68HC11_GNU_VTINHERIT )
01041 continue;
01042
01043 if (info->relocatable)
01044 {
01045
01046
01047
01048
01049 if (r_symndx < symtab_hdr->sh_info)
01050 {
01051 sym = local_syms + r_symndx;
01052 if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
01053 {
01054 sec = local_sections[r_symndx];
01055 rel->r_addend += sec->output_offset + sym->st_value;
01056 }
01057 }
01058
01059 continue;
01060 }
01061 (*ebd->elf_info_to_howto_rel) (input_bfd, &arel, rel);
01062 howto = arel.howto;
01063
01064 m68hc11_get_relocation_value (input_bfd, info, input_section,
01065 local_sections, local_syms,
01066 rel, &name, &relocation, &is_far);
01067
01068
01069 phys_addr = m68hc11_phys_addr (pinfo, relocation + rel->r_addend);
01070 phys_page = m68hc11_phys_page (pinfo, relocation + rel->r_addend);
01071 switch (r_type)
01072 {
01073 case R_M68HC11_24:
01074
01075 bfd_put_16 (input_bfd, phys_addr,
01076 (bfd_byte*) contents + rel->r_offset);
01077 bfd_put_8 (input_bfd, phys_page,
01078 (bfd_byte*) contents + rel->r_offset + 2);
01079 r = bfd_reloc_ok;
01080 r_type = R_M68HC11_NONE;
01081 break;
01082
01083 case R_M68HC11_NONE:
01084 r = bfd_reloc_ok;
01085 break;
01086
01087 case R_M68HC11_LO16:
01088
01089
01090 relocation = phys_addr;
01091 break;
01092
01093 case R_M68HC11_PAGE:
01094
01095
01096 relocation = phys_page;
01097 break;
01098
01099 case R_M68HC11_16:
01100
01101 if (is_far)
01102 {
01103 const char* msg;
01104 char* buf;
01105 msg = _("Reference to the far symbol `%s' using a wrong "
01106 "relocation may result in incorrect execution");
01107 buf = alloca (strlen (msg) + strlen (name) + 10);
01108 sprintf (buf, msg, name);
01109
01110 (* info->callbacks->warning)
01111 (info, buf, name, input_bfd, NULL, rel->r_offset);
01112 }
01113
01114
01115 insn_addr = input_section->output_section->vma
01116 + input_section->output_offset
01117 + rel->r_offset;
01118
01119 insn_page = m68hc11_phys_page (pinfo, insn_addr);
01120
01121 if (m68hc11_addr_is_banked (pinfo, relocation + rel->r_addend)
01122 && m68hc11_addr_is_banked (pinfo, insn_addr)
01123 && phys_page != insn_page)
01124 {
01125 const char* msg;
01126 char* buf;
01127
01128 msg = _("banked address [%lx:%04lx] (%lx) is not in the same bank "
01129 "as current banked address [%lx:%04lx] (%lx)");
01130
01131 buf = alloca (strlen (msg) + 128);
01132 sprintf (buf, msg, phys_page, phys_addr,
01133 (long) (relocation + rel->r_addend),
01134 insn_page, m68hc11_phys_addr (pinfo, insn_addr),
01135 (long) (insn_addr));
01136 if (!((*info->callbacks->warning)
01137 (info, buf, name, input_bfd, input_section,
01138 rel->r_offset)))
01139 return FALSE;
01140 break;
01141 }
01142 if (phys_page != 0 && insn_page == 0)
01143 {
01144 const char* msg;
01145 char* buf;
01146
01147 msg = _("reference to a banked address [%lx:%04lx] in the "
01148 "normal address space at %04lx");
01149
01150 buf = alloca (strlen (msg) + 128);
01151 sprintf (buf, msg, phys_page, phys_addr, insn_addr);
01152 if (!((*info->callbacks->warning)
01153 (info, buf, name, input_bfd, input_section,
01154 insn_addr)))
01155 return FALSE;
01156
01157 relocation = phys_addr;
01158 break;
01159 }
01160
01161
01162
01163 if (m68hc11_addr_is_banked (pinfo, relocation + rel->r_addend))
01164 relocation = phys_addr;
01165 break;
01166 }
01167 if (r_type != R_M68HC11_NONE)
01168 r = _bfd_final_link_relocate (howto, input_bfd, input_section,
01169 contents, rel->r_offset,
01170 relocation, rel->r_addend);
01171
01172 if (r != bfd_reloc_ok)
01173 {
01174 const char * msg = (const char *) 0;
01175
01176 switch (r)
01177 {
01178 case bfd_reloc_overflow:
01179 if (!((*info->callbacks->reloc_overflow)
01180 (info, NULL, name, howto->name, (bfd_vma) 0,
01181 input_bfd, input_section, rel->r_offset)))
01182 return FALSE;
01183 break;
01184
01185 case bfd_reloc_undefined:
01186 if (!((*info->callbacks->undefined_symbol)
01187 (info, name, input_bfd, input_section,
01188 rel->r_offset, TRUE)))
01189 return FALSE;
01190 break;
01191
01192 case bfd_reloc_outofrange:
01193 msg = _ ("internal error: out of range error");
01194 goto common_error;
01195
01196 case bfd_reloc_notsupported:
01197 msg = _ ("internal error: unsupported relocation error");
01198 goto common_error;
01199
01200 case bfd_reloc_dangerous:
01201 msg = _ ("internal error: dangerous error");
01202 goto common_error;
01203
01204 default:
01205 msg = _ ("internal error: unknown error");
01206
01207
01208 common_error:
01209 if (!((*info->callbacks->warning)
01210 (info, msg, name, input_bfd, input_section,
01211 rel->r_offset)))
01212 return FALSE;
01213 break;
01214 }
01215 }
01216 }
01217
01218 return TRUE;
01219 }
01220
01221
01222
01223
01224
01225 bfd_boolean
01226 _bfd_m68hc11_elf_set_private_flags (bfd *abfd, flagword flags)
01227 {
01228 BFD_ASSERT (!elf_flags_init (abfd)
01229 || elf_elfheader (abfd)->e_flags == flags);
01230
01231 elf_elfheader (abfd)->e_flags = flags;
01232 elf_flags_init (abfd) = TRUE;
01233 return TRUE;
01234 }
01235
01236
01237
01238
01239 bfd_boolean
01240 _bfd_m68hc11_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
01241 {
01242 flagword old_flags;
01243 flagword new_flags;
01244 bfd_boolean ok = TRUE;
01245
01246
01247 if (!_bfd_generic_verify_endian_match (ibfd, obfd))
01248 return FALSE;
01249
01250 if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
01251 || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
01252 return TRUE;
01253
01254 new_flags = elf_elfheader (ibfd)->e_flags;
01255 elf_elfheader (obfd)->e_flags |= new_flags & EF_M68HC11_ABI;
01256 old_flags = elf_elfheader (obfd)->e_flags;
01257
01258 if (! elf_flags_init (obfd))
01259 {
01260 elf_flags_init (obfd) = TRUE;
01261 elf_elfheader (obfd)->e_flags = new_flags;
01262 elf_elfheader (obfd)->e_ident[EI_CLASS]
01263 = elf_elfheader (ibfd)->e_ident[EI_CLASS];
01264
01265 if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
01266 && bfd_get_arch_info (obfd)->the_default)
01267 {
01268 if (! bfd_set_arch_mach (obfd, bfd_get_arch (ibfd),
01269 bfd_get_mach (ibfd)))
01270 return FALSE;
01271 }
01272
01273 return TRUE;
01274 }
01275
01276
01277 if ((new_flags & E_M68HC11_I32) != (old_flags & E_M68HC11_I32))
01278 {
01279 (*_bfd_error_handler)
01280 (_("%B: linking files compiled for 16-bit integers (-mshort) "
01281 "and others for 32-bit integers"), ibfd);
01282 ok = FALSE;
01283 }
01284 if ((new_flags & E_M68HC11_F64) != (old_flags & E_M68HC11_F64))
01285 {
01286 (*_bfd_error_handler)
01287 (_("%B: linking files compiled for 32-bit double (-fshort-double) "
01288 "and others for 64-bit double"), ibfd);
01289 ok = FALSE;
01290 }
01291
01292
01293 if (!EF_M68HC11_CAN_MERGE_MACH (new_flags, old_flags))
01294 {
01295 (*_bfd_error_handler)
01296 (_("%B: linking files compiled for HCS12 with "
01297 "others compiled for HC12"), ibfd);
01298 ok = FALSE;
01299 }
01300 new_flags = ((new_flags & ~EF_M68HC11_MACH_MASK)
01301 | (EF_M68HC11_MERGE_MACH (new_flags, old_flags)));
01302
01303 elf_elfheader (obfd)->e_flags = new_flags;
01304
01305 new_flags &= ~(EF_M68HC11_ABI | EF_M68HC11_MACH_MASK);
01306 old_flags &= ~(EF_M68HC11_ABI | EF_M68HC11_MACH_MASK);
01307
01308
01309 if (new_flags != old_flags)
01310 {
01311 (*_bfd_error_handler)
01312 (_("%B: uses different e_flags (0x%lx) fields than previous modules (0x%lx)"),
01313 ibfd, (unsigned long) new_flags, (unsigned long) old_flags);
01314 ok = FALSE;
01315 }
01316
01317 if (! ok)
01318 {
01319 bfd_set_error (bfd_error_bad_value);
01320 return FALSE;
01321 }
01322
01323 return TRUE;
01324 }
01325
01326 bfd_boolean
01327 _bfd_m68hc11_elf_print_private_bfd_data (bfd *abfd, void *ptr)
01328 {
01329 FILE *file = (FILE *) ptr;
01330
01331 BFD_ASSERT (abfd != NULL && ptr != NULL);
01332
01333
01334 _bfd_elf_print_private_bfd_data (abfd, ptr);
01335
01336
01337 fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags);
01338
01339 if (elf_elfheader (abfd)->e_flags & E_M68HC11_I32)
01340 fprintf (file, _("[abi=32-bit int, "));
01341 else
01342 fprintf (file, _("[abi=16-bit int, "));
01343
01344 if (elf_elfheader (abfd)->e_flags & E_M68HC11_F64)
01345 fprintf (file, _("64-bit double, "));
01346 else
01347 fprintf (file, _("32-bit double, "));
01348
01349 if (strcmp (bfd_get_target (abfd), "elf32-m68hc11") == 0)
01350 fprintf (file, _("cpu=HC11]"));
01351 else if (elf_elfheader (abfd)->e_flags & EF_M68HCS12_MACH)
01352 fprintf (file, _("cpu=HCS12]"));
01353 else
01354 fprintf (file, _("cpu=HC12]"));
01355
01356 if (elf_elfheader (abfd)->e_flags & E_M68HC12_BANKS)
01357 fprintf (file, _(" [memory=bank-model]"));
01358 else
01359 fprintf (file, _(" [memory=flat]"));
01360
01361 fputc ('\n', file);
01362
01363 return TRUE;
01364 }
01365
01366 static void scan_sections_for_abi (bfd *abfd ATTRIBUTE_UNUSED,
01367 asection *asect, void *arg)
01368 {
01369 struct m68hc11_scan_param* p = (struct m68hc11_scan_param*) arg;
01370
01371 if (asect->vma >= p->pinfo->bank_virtual)
01372 p->use_memory_banks = TRUE;
01373 }
01374
01375
01376
01377 void
01378 elf32_m68hc11_post_process_headers (bfd *abfd, struct bfd_link_info *link_info)
01379 {
01380 struct m68hc11_scan_param param;
01381
01382 if (link_info == 0)
01383 return;
01384
01385 m68hc11_elf_get_bank_parameters (link_info);
01386
01387 param.use_memory_banks = FALSE;
01388 param.pinfo = &m68hc11_elf_hash_table (link_info)->pinfo;
01389 bfd_map_over_sections (abfd, scan_sections_for_abi, ¶m);
01390 if (param.use_memory_banks)
01391 {
01392 Elf_Internal_Ehdr * i_ehdrp;
01393
01394 i_ehdrp = elf_elfheader (abfd);
01395 i_ehdrp->e_flags |= E_M68HC12_BANKS;
01396 }
01397 }
01398