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 "libbfd.h"
00030 #include "bfdlink.h"
00031 #include "genlink.h"
00032 #include "coff/h8300.h"
00033 #include "coff/internal.h"
00034 #include "libcoff.h"
00035 #include "libiberty.h"
00036
00037 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (1)
00038
00039
00040
00041
00042
00043
00044
00045 struct funcvec_hash_entry
00046 {
00047
00048 struct bfd_hash_entry root;
00049
00050
00051
00052 bfd_vma offset;
00053 };
00054
00055 struct funcvec_hash_table
00056 {
00057
00058 struct bfd_hash_table root;
00059
00060 bfd *abfd;
00061
00062
00063 unsigned int offset;
00064 };
00065
00066 static struct bfd_hash_entry *
00067 funcvec_hash_newfunc
00068 (struct bfd_hash_entry *, struct bfd_hash_table *, const char *);
00069
00070 static bfd_boolean
00071 funcvec_hash_table_init
00072 (struct funcvec_hash_table *, bfd *,
00073 struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
00074 struct bfd_hash_table *,
00075 const char *));
00076
00077 static bfd_reloc_status_type special
00078 (bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **);
00079 static int select_reloc
00080 (reloc_howto_type *);
00081 static void rtype2howto
00082 (arelent *, struct internal_reloc *);
00083 static void reloc_processing
00084 (arelent *, struct internal_reloc *, asymbol **, bfd *, asection *);
00085 static bfd_boolean h8300_symbol_address_p
00086 (bfd *, asection *, bfd_vma);
00087 static int h8300_reloc16_estimate
00088 (bfd *, asection *, arelent *, unsigned int,
00089 struct bfd_link_info *);
00090 static void h8300_reloc16_extra_cases
00091 (bfd *, struct bfd_link_info *, struct bfd_link_order *, arelent *,
00092 bfd_byte *, unsigned int *, unsigned int *);
00093 static bfd_boolean h8300_bfd_link_add_symbols
00094 (bfd *, struct bfd_link_info *);
00095
00096
00097 #define funcvec_hash_lookup(table, string, create, copy) \
00098 ((struct funcvec_hash_entry *) \
00099 bfd_hash_lookup (&(table)->root, (string), (create), (copy)))
00100
00101
00102
00103
00104
00105 struct h8300_coff_link_hash_table {
00106
00107 struct generic_link_hash_table root;
00108
00109
00110
00111 asection *vectors_sec;
00112
00113
00114
00115 struct funcvec_hash_table *funcvec_hash_table;
00116 };
00117
00118 static struct bfd_link_hash_table *h8300_coff_link_hash_table_create (bfd *);
00119
00120
00121
00122 #define h8300_coff_hash_table(p) \
00123 ((struct h8300_coff_link_hash_table *) ((coff_hash_table (p))))
00124
00125
00126
00127
00128 static struct bfd_hash_entry *
00129 funcvec_hash_newfunc (struct bfd_hash_entry *entry,
00130 struct bfd_hash_table *gen_table,
00131 const char *string)
00132 {
00133 struct funcvec_hash_entry *ret;
00134 struct funcvec_hash_table *table;
00135
00136 ret = (struct funcvec_hash_entry *) entry;
00137 table = (struct funcvec_hash_table *) gen_table;
00138
00139
00140
00141 if (ret == NULL)
00142 ret = ((struct funcvec_hash_entry *)
00143 bfd_hash_allocate (gen_table,
00144 sizeof (struct funcvec_hash_entry)));
00145 if (ret == NULL)
00146 return NULL;
00147
00148
00149 ret = ((struct funcvec_hash_entry *)
00150 bfd_hash_newfunc ((struct bfd_hash_entry *) ret, gen_table, string));
00151
00152 if (ret == NULL)
00153 return NULL;
00154
00155
00156 ret->offset = table->offset;
00157
00158
00159
00160
00161 switch (bfd_get_mach (table->abfd))
00162 {
00163 case bfd_mach_h8300:
00164 case bfd_mach_h8300hn:
00165 case bfd_mach_h8300sn:
00166 table->offset += 2;
00167 break;
00168 case bfd_mach_h8300h:
00169 case bfd_mach_h8300s:
00170 table->offset += 4;
00171 break;
00172 default:
00173 return NULL;
00174 }
00175
00176
00177 return (struct bfd_hash_entry *) ret;
00178 }
00179
00180
00181
00182 static bfd_boolean
00183 funcvec_hash_table_init (struct funcvec_hash_table *table,
00184 bfd *abfd,
00185 struct bfd_hash_entry *(*newfunc)
00186 (struct bfd_hash_entry *,
00187 struct bfd_hash_table *,
00188 const char *))
00189 {
00190
00191
00192 table->offset = 0;
00193 table->abfd = abfd;
00194 return (bfd_hash_table_init (&table->root, newfunc));
00195 }
00196
00197
00198
00199
00200
00201 static struct bfd_link_hash_table *
00202 h8300_coff_link_hash_table_create (bfd *abfd)
00203 {
00204 struct h8300_coff_link_hash_table *ret;
00205 bfd_size_type amt = sizeof (struct h8300_coff_link_hash_table);
00206
00207 ret = (struct h8300_coff_link_hash_table *) bfd_malloc (amt);
00208 if (ret == NULL)
00209 return NULL;
00210 if (!_bfd_link_hash_table_init (&ret->root.root, abfd,
00211 _bfd_generic_link_hash_newfunc))
00212 {
00213 free (ret);
00214 return NULL;
00215 }
00216
00217
00218 ret->vectors_sec = NULL;
00219 ret->funcvec_hash_table = NULL;
00220
00221
00222 return &ret->root.root;
00223 }
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234 static bfd_reloc_status_type
00235 special (bfd *abfd ATTRIBUTE_UNUSED,
00236 arelent *reloc_entry ATTRIBUTE_UNUSED,
00237 asymbol *symbol ATTRIBUTE_UNUSED,
00238 PTR data ATTRIBUTE_UNUSED,
00239 asection *input_section ATTRIBUTE_UNUSED,
00240 bfd *output_bfd,
00241 char **error_message ATTRIBUTE_UNUSED)
00242 {
00243 if (output_bfd == (bfd *) NULL)
00244 return bfd_reloc_continue;
00245
00246
00247 reloc_entry->address += input_section->output_offset;
00248 return bfd_reloc_ok;
00249 }
00250
00251 static reloc_howto_type howto_table[] = {
00252 HOWTO (R_RELBYTE, 0, 0, 8, FALSE, 0, complain_overflow_bitfield, special, "8", FALSE, 0x000000ff, 0x000000ff, FALSE),
00253 HOWTO (R_RELWORD, 0, 1, 16, FALSE, 0, complain_overflow_bitfield, special, "16", FALSE, 0x0000ffff, 0x0000ffff, FALSE),
00254 HOWTO (R_RELLONG, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, special, "32", FALSE, 0xffffffff, 0xffffffff, FALSE),
00255 HOWTO (R_PCRBYTE, 0, 0, 8, TRUE, 0, complain_overflow_signed, special, "DISP8", FALSE, 0x000000ff, 0x000000ff, TRUE),
00256 HOWTO (R_PCRWORD, 0, 1, 16, TRUE, 0, complain_overflow_signed, special, "DISP16", FALSE, 0x0000ffff, 0x0000ffff, TRUE),
00257 HOWTO (R_PCRLONG, 0, 2, 32, TRUE, 0, complain_overflow_signed, special, "DISP32", FALSE, 0xffffffff, 0xffffffff, TRUE),
00258 HOWTO (R_MOV16B1, 0, 1, 16, FALSE, 0, complain_overflow_bitfield, special, "relaxable mov.b:16", FALSE, 0x0000ffff, 0x0000ffff, FALSE),
00259 HOWTO (R_MOV16B2, 0, 1, 8, FALSE, 0, complain_overflow_bitfield, special, "relaxed mov.b:16", FALSE, 0x000000ff, 0x000000ff, FALSE),
00260 HOWTO (R_JMP1, 0, 1, 16, FALSE, 0, complain_overflow_bitfield, special, "16/pcrel", FALSE, 0x0000ffff, 0x0000ffff, FALSE),
00261 HOWTO (R_JMP2, 0, 0, 8, FALSE, 0, complain_overflow_bitfield, special, "pcrecl/16", FALSE, 0x000000ff, 0x000000ff, FALSE),
00262 HOWTO (R_JMPL1, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, special, "24/pcrell", FALSE, 0x00ffffff, 0x00ffffff, FALSE),
00263 HOWTO (R_JMPL2, 0, 0, 8, FALSE, 0, complain_overflow_bitfield, special, "pc8/24", FALSE, 0x000000ff, 0x000000ff, FALSE),
00264 HOWTO (R_MOV24B1, 0, 1, 32, FALSE, 0, complain_overflow_bitfield, special, "relaxable mov.b:24", FALSE, 0xffffffff, 0xffffffff, FALSE),
00265 HOWTO (R_MOV24B2, 0, 1, 8, FALSE, 0, complain_overflow_bitfield, special, "relaxed mov.b:24", FALSE, 0x0000ffff, 0x0000ffff, FALSE),
00266
00267
00268
00269
00270 HOWTO (R_MEM_INDIRECT, 0, 0, 8, FALSE, 0, complain_overflow_bitfield, special, "8/indirect", FALSE, 0x000000ff, 0x000000ff, FALSE),
00271
00272
00273
00274 HOWTO (R_PCRWORD_B, 0, 0, 8, TRUE, 0, complain_overflow_bitfield, special, "relaxed bCC:16", FALSE, 0x000000ff, 0x000000ff, FALSE),
00275
00276 HOWTO (R_MOVL1, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,special, "32/24 relaxable move", FALSE, 0xffffffff, 0xffffffff, FALSE),
00277
00278 HOWTO (R_MOVL2, 0, 1, 16, FALSE, 0, complain_overflow_bitfield, special, "32/24 relaxed move", FALSE, 0x0000ffff, 0x0000ffff, FALSE),
00279
00280 HOWTO (R_BCC_INV, 0, 0, 8, TRUE, 0, complain_overflow_signed, special, "DISP8 inverted", FALSE, 0x000000ff, 0x000000ff, TRUE),
00281
00282 HOWTO (R_JMP_DEL, 0, 0, 8, TRUE, 0, complain_overflow_signed, special, "Deleted jump", FALSE, 0x000000ff, 0x000000ff, TRUE),
00283 };
00284
00285
00286
00287 #define SELECT_RELOC(x,howto) \
00288 { x.r_type = select_reloc (howto); }
00289
00290 #define BADMAG(x) (H8300BADMAG (x) && H8300HBADMAG (x) && H8300SBADMAG (x) \
00291 && H8300HNBADMAG(x) && H8300SNBADMAG(x))
00292 #define H8300 1
00293 #define __A_MAGIC_SET__
00294
00295
00296 #define SWAP_IN_RELOC_OFFSET H_GET_32
00297 #define SWAP_OUT_RELOC_OFFSET H_PUT_32
00298 #define SWAP_OUT_RELOC_EXTRA(abfd, src, dst) \
00299 dst->r_stuff[0] = 'S'; \
00300 dst->r_stuff[1] = 'C';
00301
00302 static int
00303 select_reloc (reloc_howto_type *howto)
00304 {
00305 return howto->type;
00306 }
00307
00308
00309
00310 static void
00311 rtype2howto (arelent *internal, struct internal_reloc *dst)
00312 {
00313 switch (dst->r_type)
00314 {
00315 case R_RELBYTE:
00316 internal->howto = howto_table + 0;
00317 break;
00318 case R_RELWORD:
00319 internal->howto = howto_table + 1;
00320 break;
00321 case R_RELLONG:
00322 internal->howto = howto_table + 2;
00323 break;
00324 case R_PCRBYTE:
00325 internal->howto = howto_table + 3;
00326 break;
00327 case R_PCRWORD:
00328 internal->howto = howto_table + 4;
00329 break;
00330 case R_PCRLONG:
00331 internal->howto = howto_table + 5;
00332 break;
00333 case R_MOV16B1:
00334 internal->howto = howto_table + 6;
00335 break;
00336 case R_MOV16B2:
00337 internal->howto = howto_table + 7;
00338 break;
00339 case R_JMP1:
00340 internal->howto = howto_table + 8;
00341 break;
00342 case R_JMP2:
00343 internal->howto = howto_table + 9;
00344 break;
00345 case R_JMPL1:
00346 internal->howto = howto_table + 10;
00347 break;
00348 case R_JMPL2:
00349 internal->howto = howto_table + 11;
00350 break;
00351 case R_MOV24B1:
00352 internal->howto = howto_table + 12;
00353 break;
00354 case R_MOV24B2:
00355 internal->howto = howto_table + 13;
00356 break;
00357 case R_MEM_INDIRECT:
00358 internal->howto = howto_table + 14;
00359 break;
00360 case R_PCRWORD_B:
00361 internal->howto = howto_table + 15;
00362 break;
00363 case R_MOVL1:
00364 internal->howto = howto_table + 16;
00365 break;
00366 case R_MOVL2:
00367 internal->howto = howto_table + 17;
00368 break;
00369 case R_BCC_INV:
00370 internal->howto = howto_table + 18;
00371 break;
00372 case R_JMP_DEL:
00373 internal->howto = howto_table + 19;
00374 break;
00375 default:
00376 abort ();
00377 break;
00378 }
00379 }
00380
00381 #define RTYPE2HOWTO(internal, relocentry) rtype2howto (internal, relocentry)
00382
00383
00384
00385 #define CALC_ADDEND(abfd, symbol, ext_reloc, cache_ptr) \
00386 cache_ptr->addend = ext_reloc.r_offset;
00387
00388 #define RELOC_PROCESSING(relent,reloc,symbols,abfd,section) \
00389 reloc_processing (relent, reloc, symbols, abfd, section)
00390
00391 static void
00392 reloc_processing (arelent *relent, struct internal_reloc *reloc,
00393 asymbol **symbols, bfd *abfd, asection *section)
00394 {
00395 relent->address = reloc->r_vaddr;
00396 rtype2howto (relent, reloc);
00397
00398 if (((int) reloc->r_symndx) > 0)
00399 relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx];
00400 else
00401 relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
00402
00403 relent->addend = reloc->r_offset;
00404 relent->address -= section->vma;
00405 }
00406
00407 static bfd_boolean
00408 h8300_symbol_address_p (bfd *abfd, asection *input_section, bfd_vma address)
00409 {
00410 asymbol **s;
00411
00412 s = _bfd_generic_link_get_symbols (abfd);
00413 BFD_ASSERT (s != (asymbol **) NULL);
00414
00415
00416
00417 while (*s)
00418 {
00419 asymbol *p = *s;
00420
00421 if (p->section == input_section
00422 && (input_section->output_section->vma
00423 + input_section->output_offset
00424 + p->value) == address)
00425 return TRUE;
00426 s++;
00427 }
00428 return FALSE;
00429 }
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439 static int
00440 h8300_reloc16_estimate (bfd *abfd, asection *input_section, arelent *reloc,
00441 unsigned int shrink, struct bfd_link_info *link_info)
00442 {
00443 bfd_vma value;
00444 bfd_vma dot;
00445 bfd_vma gap;
00446 static asection *last_input_section = NULL;
00447 static arelent *last_reloc = NULL;
00448
00449
00450
00451
00452
00453 bfd_vma address = reloc->address - shrink;
00454
00455 if (input_section != last_input_section)
00456 last_reloc = NULL;
00457
00458
00459 switch (reloc->howto->type)
00460 {
00461
00462
00463 case R_JMP1:
00464 case R_JMPL1:
00465
00466 value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
00467
00468
00469 dot = (input_section->output_section->vma
00470 + input_section->output_offset + address);
00471
00472
00473 dot += (reloc->howto->type == R_JMP1 ? 1 : 2);
00474
00475
00476 gap = value - dot;
00477
00478
00479
00480
00481 if ((int) gap >= -128 && (int) gap <= 128)
00482 {
00483 bfd_byte code;
00484
00485 if (!bfd_get_section_contents (abfd, input_section, & code,
00486 reloc->address, 1))
00487 break;
00488 code = bfd_get_8 (abfd, & code);
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518 if (code == 0x5a
00519 && gap <= 126
00520 && last_reloc
00521 && last_reloc->howto->type == R_PCRBYTE)
00522 {
00523 bfd_vma last_value;
00524 last_value = bfd_coff_reloc16_get_value (last_reloc, link_info,
00525 input_section) + 1;
00526
00527 if (last_value == dot + 2
00528 && last_reloc->address + 1 == reloc->address
00529 && !h8300_symbol_address_p (abfd, input_section, dot - 2))
00530 {
00531 reloc->howto = howto_table + 19;
00532 last_reloc->howto = howto_table + 18;
00533 last_reloc->sym_ptr_ptr = reloc->sym_ptr_ptr;
00534 last_reloc->addend = reloc->addend;
00535 shrink += 4;
00536 bfd_perform_slip (abfd, 4, input_section, address);
00537 break;
00538 }
00539 }
00540
00541
00542 reloc->howto = reloc->howto + 1;
00543
00544
00545 shrink += 2;
00546 bfd_perform_slip (abfd, 2, input_section, address);
00547 }
00548 break;
00549
00550
00551
00552 case R_PCRWORD:
00553
00554
00555 value = bfd_coff_reloc16_get_value (reloc, link_info, input_section) + 1;
00556
00557
00558 dot = input_section->output_section->vma +
00559 input_section->output_offset + address;
00560
00561
00562 gap = value - dot;
00563
00564
00565
00566
00567 if ((int) gap >= -128 && (int) gap <= 128)
00568 {
00569
00570 reloc->howto = howto_table + 15;
00571
00572
00573 shrink += 2;
00574 bfd_perform_slip (abfd, 2, input_section, address);
00575 }
00576 break;
00577
00578
00579
00580 case R_MOV16B1:
00581
00582 value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
00583 value = bfd_h8300_pad_address (abfd, value);
00584
00585
00586
00587 if (value >= 0xffffff00u)
00588 {
00589
00590 reloc->howto = reloc->howto + 1;
00591
00592
00593 shrink += 2;
00594 bfd_perform_slip (abfd, 2, input_section, address);
00595 }
00596 break;
00597
00598
00599
00600
00601 case R_MOV24B1:
00602
00603 value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
00604 value = bfd_h8300_pad_address (abfd, value);
00605
00606 if (value >= 0xffffff00u)
00607 {
00608
00609 reloc->howto = reloc->howto + 1;
00610
00611
00612 shrink += 4;
00613 bfd_perform_slip (abfd, 4, input_section, address);
00614
00615
00616 break;
00617 }
00618
00619
00620
00621
00622
00623
00624 case R_MOVL1:
00625
00626 value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
00627 value = bfd_h8300_pad_address (abfd, value);
00628
00629
00630
00631 if (value <= 0x7fff || value >= 0xffff8000u)
00632 {
00633
00634 reloc->howto = howto_table + 17;
00635
00636
00637 shrink += 2;
00638 bfd_perform_slip (abfd, 2, input_section, address);
00639 }
00640 break;
00641
00642
00643 default:
00644 break;
00645 }
00646
00647 last_reloc = reloc;
00648 last_input_section = input_section;
00649 return shrink;
00650 }
00651
00652
00653
00654
00655
00656
00657 static void
00658 h8300_reloc16_extra_cases (bfd *abfd, struct bfd_link_info *link_info,
00659 struct bfd_link_order *link_order, arelent *reloc,
00660 bfd_byte *data, unsigned int *src_ptr,
00661 unsigned int *dst_ptr)
00662 {
00663 unsigned int src_address = *src_ptr;
00664 unsigned int dst_address = *dst_ptr;
00665 asection *input_section = link_order->u.indirect.section;
00666 bfd_vma value;
00667 bfd_vma dot;
00668 int gap, tmp;
00669 unsigned char temp_code;
00670
00671 switch (reloc->howto->type)
00672 {
00673
00674 case R_PCRBYTE:
00675
00676 value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
00677
00678 dot = (link_order->offset
00679 + dst_address
00680 + link_order->u.indirect.section->output_section->vma);
00681
00682 gap = value - dot;
00683
00684
00685 if (gap < -128 || gap > 126)
00686 {
00687 if (! ((*link_info->callbacks->reloc_overflow)
00688 (link_info, NULL,
00689 bfd_asymbol_name (*reloc->sym_ptr_ptr),
00690 reloc->howto->name, reloc->addend, input_section->owner,
00691 input_section, reloc->address)))
00692 abort ();
00693 }
00694
00695
00696
00697 bfd_put_8 (abfd, gap, data + dst_address);
00698 dst_address++;
00699 src_address++;
00700
00701
00702 break;
00703
00704
00705 case R_PCRWORD:
00706
00707 value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
00708
00709
00710 dot = (link_order->offset
00711 + dst_address
00712 + link_order->u.indirect.section->output_section->vma + 1);
00713
00714 gap = value - dot;
00715
00716
00717 if (gap > 32766 || gap < -32768)
00718 {
00719 if (! ((*link_info->callbacks->reloc_overflow)
00720 (link_info, NULL,
00721 bfd_asymbol_name (*reloc->sym_ptr_ptr),
00722 reloc->howto->name, reloc->addend, input_section->owner,
00723 input_section, reloc->address)))
00724 abort ();
00725 }
00726
00727
00728
00729 bfd_put_16 (abfd, (bfd_vma) gap, data + dst_address);
00730 dst_address += 2;
00731 src_address += 2;
00732
00733
00734 break;
00735
00736
00737 case R_RELBYTE:
00738
00739 value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
00740
00741 bfd_put_8 (abfd, value & 0xff, data + dst_address);
00742 dst_address += 1;
00743 src_address += 1;
00744
00745
00746 break;
00747
00748
00749 case R_MOV16B1:
00750 case R_JMP1:
00751 case R_RELWORD:
00752 value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
00753 bfd_put_16 (abfd, value, data + dst_address);
00754 dst_address += 2;
00755 src_address += 2;
00756 break;
00757
00758
00759 case R_MOV24B1:
00760 case R_MOVL1:
00761 case R_RELLONG:
00762
00763 value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
00764 bfd_put_32 (abfd, value, data + dst_address);
00765 dst_address += 4;
00766 src_address += 4;
00767 break;
00768
00769
00770 case R_JMPL1:
00771
00772 value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
00773
00774 value = ((value & 0x00ffffff)
00775 | (bfd_get_32 (abfd, data + src_address) & 0xff000000));
00776 bfd_put_32 (abfd, value, data + dst_address);
00777 dst_address += 4;
00778 src_address += 4;
00779 break;
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790 case R_MOVL2:
00791 value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
00792 value = bfd_h8300_pad_address (abfd, value);
00793
00794
00795 if (value <= 0x7fff || value >= 0xffff8000u)
00796 {
00797
00798 bfd_put_16 (abfd, value, data + dst_address);
00799
00800
00801
00802
00803 data[dst_address - 1] &= ~0x20;
00804 dst_address += 2;
00805 src_address += 4;
00806 }
00807 else
00808 {
00809 if (! ((*link_info->callbacks->reloc_overflow)
00810 (link_info, NULL,
00811 bfd_asymbol_name (*reloc->sym_ptr_ptr),
00812 reloc->howto->name, reloc->addend, input_section->owner,
00813 input_section, reloc->address)))
00814 abort ();
00815 }
00816 break;
00817
00818
00819 case R_JMP2:
00820
00821 value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
00822
00823
00824 dot = (link_order->offset
00825 + dst_address
00826 + link_order->u.indirect.section->output_section->vma + 1);
00827
00828 gap = value - dot;
00829
00830
00831 if (gap < -128 || gap > 126)
00832 {
00833 if (! ((*link_info->callbacks->reloc_overflow)
00834 (link_info, NULL,
00835 bfd_asymbol_name (*reloc->sym_ptr_ptr),
00836 reloc->howto->name, reloc->addend, input_section->owner,
00837 input_section, reloc->address)))
00838 abort ();
00839 }
00840
00841
00842 switch (data[dst_address - 1])
00843 {
00844 case 0x5e:
00845
00846 bfd_put_8 (abfd, 0x55, data + dst_address - 1);
00847 break;
00848 case 0x5a:
00849
00850 bfd_put_8 (abfd, 0x40, data + dst_address - 1);
00851 break;
00852
00853 default:
00854 abort ();
00855 }
00856
00857
00858 bfd_put_8 (abfd, gap, data + dst_address);
00859
00860 dst_address += 1;
00861 src_address += 3;
00862
00863 break;
00864
00865
00866 case R_PCRWORD_B:
00867
00868 value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
00869
00870
00871 dot = (link_order->offset
00872 + dst_address
00873 + link_order->u.indirect.section->output_section->vma - 1);
00874
00875 gap = value - dot;
00876
00877
00878 if (gap < -128 || gap > 126)
00879 {
00880 if (! ((*link_info->callbacks->reloc_overflow)
00881 (link_info, NULL,
00882 bfd_asymbol_name (*reloc->sym_ptr_ptr),
00883 reloc->howto->name, reloc->addend, input_section->owner,
00884 input_section, reloc->address)))
00885 abort ();
00886 }
00887
00888
00889 switch (data[dst_address - 2])
00890 {
00891 case 0x58:
00892
00893
00894
00895 tmp = data[dst_address - 1];
00896
00897
00898
00899
00900 tmp &= 0xf0;
00901 tmp >>= 4;
00902 tmp |= 0x40;
00903
00904
00905 bfd_put_8 (abfd, tmp, data + dst_address - 2);
00906 break;
00907
00908 case 0x5c:
00909
00910 bfd_put_8 (abfd, 0x55, data + dst_address - 2);
00911 break;
00912
00913 default:
00914 abort ();
00915 }
00916
00917
00918 bfd_put_8 (abfd, gap, data + dst_address - 1);
00919
00920
00921
00922 src_address += 2;
00923
00924 break;
00925
00926
00927 case R_JMPL2:
00928
00929 value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
00930
00931
00932 dot = (link_order->offset
00933 + dst_address
00934 + link_order->u.indirect.section->output_section->vma + 2);
00935
00936 gap = value - dot;
00937
00938
00939 switch (data[src_address])
00940 {
00941 case 0x5e:
00942
00943 bfd_put_8 (abfd, 0x55, data + dst_address);
00944 break;
00945 case 0x5a:
00946
00947 bfd_put_8 (abfd, 0x40, data + dst_address);
00948 break;
00949 default:
00950 abort ();
00951 }
00952
00953 bfd_put_8 (abfd, gap, data + dst_address + 1);
00954 dst_address += 2;
00955 src_address += 4;
00956
00957 break;
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968 case R_MOV16B2:
00969 value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
00970
00971
00972 if (data[dst_address - 2] != 0x6a)
00973 abort ();
00974
00975 temp_code = data[src_address - 1];
00976
00977
00978
00979 if ((temp_code & 0x10) != 0x10)
00980 temp_code &= 0xf0;
00981
00982
00983 switch (temp_code)
00984 {
00985 case 0x00:
00986
00987 data[dst_address - 2] = (data[src_address - 1] & 0xf) | 0x20;
00988 break;
00989 case 0x80:
00990
00991 data[dst_address - 2] = (data[src_address - 1] & 0xf) | 0x30;
00992 break;
00993 case 0x18:
00994
00995
00996
00997 data[dst_address - 2] = 0x7f;
00998 break;
00999 case 0x10:
01000
01001
01002
01003 data[dst_address - 2] = 0x7e;
01004 break;
01005 default:
01006 abort ();
01007 }
01008
01009 bfd_put_8 (abfd, value & 0xff, data + dst_address - 1);
01010 src_address += 2;
01011 break;
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022 case R_MOV24B2:
01023 value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
01024
01025
01026 if (data[dst_address - 2] != 0x6a)
01027 abort ();
01028
01029 temp_code = data[src_address - 1];
01030
01031
01032
01033 if ((temp_code & 0x30) != 0x30)
01034 temp_code &= 0xf0;
01035
01036
01037 switch (temp_code)
01038 {
01039 case 0x20:
01040
01041 data[dst_address - 2] = (data[src_address - 1] & 0xf) | 0x20;
01042 break;
01043 case 0xa0:
01044
01045 data[dst_address - 2] = (data[src_address - 1] & 0xf) | 0x30;
01046 break;
01047 case 0x38:
01048
01049
01050
01051 data[dst_address - 2] = 0x7f;
01052 break;
01053 case 0x30:
01054
01055
01056
01057 data[dst_address - 2] = 0x7e;
01058 break;
01059 default:
01060 abort ();
01061 }
01062
01063 bfd_put_8 (abfd, value & 0xff, data + dst_address - 1);
01064 src_address += 4;
01065 break;
01066
01067 case R_BCC_INV:
01068
01069 value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
01070
01071 dot = (link_order->offset
01072 + dst_address
01073 + link_order->u.indirect.section->output_section->vma) + 1;
01074
01075 gap = value - dot;
01076
01077
01078 if (gap < -128 || gap > 126)
01079 {
01080 if (! ((*link_info->callbacks->reloc_overflow)
01081 (link_info, NULL,
01082 bfd_asymbol_name (*reloc->sym_ptr_ptr),
01083 reloc->howto->name, reloc->addend, input_section->owner,
01084 input_section, reloc->address)))
01085 abort ();
01086 }
01087
01088
01089
01090
01091 bfd_put_8 (abfd, bfd_get_8 (abfd, data + dst_address - 1) ^ 1,
01092 data + dst_address - 1);
01093 bfd_put_8 (abfd, gap, data + dst_address);
01094 dst_address++;
01095 src_address++;
01096
01097
01098 break;
01099
01100 case R_JMP_DEL:
01101 src_address += 4;
01102 break;
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116 case R_MEM_INDIRECT:
01117 {
01118
01119
01120 asymbol *symbol;
01121 const char *name;
01122 struct funcvec_hash_table *ftab;
01123 struct funcvec_hash_entry *h;
01124 struct h8300_coff_link_hash_table *htab;
01125 asection *vectors_sec;
01126
01127 if (link_info->hash->creator != abfd->xvec)
01128 {
01129 (*_bfd_error_handler)
01130 (_("cannot handle R_MEM_INDIRECT reloc when using %s output"),
01131 link_info->hash->creator->name);
01132
01133
01134
01135
01136 #ifndef EXIT_FAILURE
01137 #define EXIT_FAILURE 1
01138 #endif
01139 xexit (EXIT_FAILURE);
01140 }
01141 htab = h8300_coff_hash_table (link_info);
01142 vectors_sec = htab->vectors_sec;
01143
01144
01145
01146 symbol = *(reloc->sym_ptr_ptr);
01147 value = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
01148 if (symbol == bfd_abs_section_ptr->symbol
01149 || value <= 0xff)
01150 {
01151
01152
01153
01154
01155 if (value <= 0xff)
01156 {
01157 bfd_put_8 (abfd, value, data + dst_address);
01158 dst_address += 1;
01159 src_address += 1;
01160 }
01161 else
01162 {
01163 if (! ((*link_info->callbacks->reloc_overflow)
01164 (link_info, NULL,
01165 bfd_asymbol_name (*reloc->sym_ptr_ptr),
01166 reloc->howto->name, reloc->addend, input_section->owner,
01167 input_section, reloc->address)))
01168 abort ();
01169 }
01170 break;
01171 }
01172
01173
01174
01175
01176
01177
01178
01179 name = symbol->name;
01180 if (symbol->flags & BSF_LOCAL)
01181 {
01182 char *new_name = bfd_malloc ((bfd_size_type) strlen (name) + 10);
01183
01184 if (new_name == NULL)
01185 abort ();
01186
01187 sprintf (new_name, "%s_%08x", name, symbol->section->id);
01188 name = new_name;
01189 }
01190
01191 ftab = htab->funcvec_hash_table;
01192 h = funcvec_hash_lookup (ftab, name, FALSE, FALSE);
01193
01194
01195
01196
01197 if (h == NULL || vectors_sec == NULL)
01198 abort ();
01199
01200
01201
01202 bfd_put_8 (abfd,
01203 vectors_sec->output_offset + h->offset,
01204 data + dst_address);
01205
01206 dst_address++;
01207 src_address++;
01208
01209
01210 switch (bfd_get_mach (input_section->owner))
01211 {
01212 case bfd_mach_h8300:
01213 case bfd_mach_h8300hn:
01214 case bfd_mach_h8300sn:
01215 bfd_put_16 (abfd,
01216 bfd_coff_reloc16_get_value (reloc,
01217 link_info,
01218 input_section),
01219 vectors_sec->contents + h->offset);
01220 break;
01221 case bfd_mach_h8300h:
01222 case bfd_mach_h8300s:
01223 bfd_put_32 (abfd,
01224 bfd_coff_reloc16_get_value (reloc,
01225 link_info,
01226 input_section),
01227 vectors_sec->contents + h->offset);
01228 break;
01229 default:
01230 abort ();
01231 }
01232
01233
01234
01235 bfd_set_section_contents (vectors_sec->output_section->owner,
01236 vectors_sec->output_section,
01237 vectors_sec->contents,
01238 (file_ptr) vectors_sec->output_offset,
01239 vectors_sec->size);
01240 break;
01241 }
01242
01243 default:
01244 abort ();
01245 break;
01246
01247 }
01248
01249 *src_ptr = src_address;
01250 *dst_ptr = dst_address;
01251 }
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264 static bfd_boolean
01265 h8300_bfd_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
01266 {
01267 asection *sec;
01268 struct funcvec_hash_table *funcvec_hash_table;
01269 bfd_size_type amt;
01270 struct h8300_coff_link_hash_table *htab;
01271
01272
01273 _bfd_generic_link_add_symbols (abfd, info);
01274
01275 if (info->hash->creator != abfd->xvec)
01276 return TRUE;
01277
01278 htab = h8300_coff_hash_table (info);
01279
01280
01281 if (!htab->vectors_sec)
01282 {
01283 flagword flags;
01284
01285
01286 flags = (SEC_ALLOC | SEC_LOAD
01287 | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_READONLY);
01288 htab->vectors_sec = bfd_make_section (abfd, ".vectors");
01289
01290
01291
01292 if (!htab->vectors_sec
01293 || !bfd_set_section_flags (abfd, htab->vectors_sec, flags))
01294 return FALSE;
01295
01296
01297 amt = sizeof (struct funcvec_hash_table);
01298 funcvec_hash_table = (struct funcvec_hash_table *) bfd_alloc (abfd, amt);
01299
01300 if (!funcvec_hash_table)
01301 return FALSE;
01302
01303
01304 if (!funcvec_hash_table_init (funcvec_hash_table, abfd,
01305 funcvec_hash_newfunc))
01306 {
01307 bfd_release (abfd, funcvec_hash_table);
01308 return FALSE;
01309 }
01310
01311
01312 htab->funcvec_hash_table = funcvec_hash_table;
01313 }
01314
01315
01316 funcvec_hash_table = htab->funcvec_hash_table;
01317
01318
01319
01320 for (sec = abfd->sections; sec; sec = sec->next)
01321 {
01322 long reloc_size, reloc_count, i;
01323 asymbol **symbols;
01324 arelent **relocs;
01325
01326
01327 reloc_size = bfd_get_reloc_upper_bound (abfd, sec);
01328 if (reloc_size <= 0)
01329 continue;
01330
01331 relocs = (arelent **) bfd_malloc ((bfd_size_type) reloc_size);
01332 if (!relocs)
01333 return FALSE;
01334
01335
01336
01337
01338 symbols = _bfd_generic_link_get_symbols(abfd);
01339 reloc_count = bfd_canonicalize_reloc (abfd, sec, relocs, symbols);
01340 if (reloc_count <= 0)
01341 {
01342 free (relocs);
01343 continue;
01344 }
01345
01346
01347 for (i = 0; i < reloc_count; i++)
01348 {
01349 arelent *reloc = relocs[i];
01350 asymbol *symbol = *(reloc->sym_ptr_ptr);
01351 const char *name;
01352
01353
01354
01355
01356
01357
01358 if (reloc->howto->type == R_MEM_INDIRECT
01359 && symbol != bfd_abs_section_ptr->symbol)
01360
01361 {
01362 struct funcvec_hash_table *ftab;
01363 struct funcvec_hash_entry *h;
01364
01365 name = symbol->name;
01366 if (symbol->flags & BSF_LOCAL)
01367 {
01368 char *new_name;
01369
01370 new_name = bfd_malloc ((bfd_size_type) strlen (name) + 10);
01371 if (new_name == NULL)
01372 abort ();
01373
01374 sprintf (new_name, "%s_%08x", name, symbol->section->id);
01375 name = new_name;
01376 }
01377
01378
01379 ftab = htab->funcvec_hash_table;
01380 h = funcvec_hash_lookup (ftab, name, FALSE, FALSE);
01381
01382
01383
01384 if (h == NULL)
01385 {
01386 h = funcvec_hash_lookup (ftab, name, TRUE, TRUE);
01387 if (h == NULL)
01388 {
01389 free (relocs);
01390 return FALSE;
01391 }
01392
01393
01394
01395 switch (bfd_get_mach (abfd))
01396 {
01397 case bfd_mach_h8300:
01398 case bfd_mach_h8300hn:
01399 case bfd_mach_h8300sn:
01400 htab->vectors_sec->size += 2;
01401 break;
01402 case bfd_mach_h8300h:
01403 case bfd_mach_h8300s:
01404 htab->vectors_sec->size += 4;
01405 break;
01406 default:
01407 abort ();
01408 }
01409 }
01410 }
01411 }
01412
01413
01414 free (relocs);
01415 }
01416
01417
01418
01419 sec = htab->vectors_sec;
01420 if (sec->size != 0)
01421 {
01422
01423 if (sec->contents)
01424 free (sec->contents);
01425
01426
01427 sec->contents = bfd_malloc (sec->size);
01428 }
01429
01430 return TRUE;
01431 }
01432
01433 #define coff_reloc16_extra_cases h8300_reloc16_extra_cases
01434 #define coff_reloc16_estimate h8300_reloc16_estimate
01435 #define coff_bfd_link_add_symbols h8300_bfd_link_add_symbols
01436 #define coff_bfd_link_hash_table_create h8300_coff_link_hash_table_create
01437
01438 #define COFF_LONG_FILENAMES
01439 #include "coffcode.h"
01440
01441 #undef coff_bfd_get_relocated_section_contents
01442 #undef coff_bfd_relax_section
01443 #define coff_bfd_get_relocated_section_contents \
01444 bfd_coff_reloc16_get_relocated_section_contents
01445 #define coff_bfd_relax_section bfd_coff_reloc16_relax_section
01446
01447 CREATE_BIG_COFF_TARGET_VEC (h8300coff_vec, "coff-h8300", BFD_IS_RELAXABLE, 0, '_', NULL, COFF_SWAP_TABLE)