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
00028
00029
00030
00031 #include "bfd.h"
00032 #include "bfdlink.h"
00033 #include "sysdep.h"
00034 #include "libbfd.h"
00035 #include "coff/tic80.h"
00036 #include "coff/internal.h"
00037 #include "libcoff.h"
00038
00039 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
00040 #define COFF_ALIGN_IN_SECTION_HEADER 1
00041 #define COFF_ALIGN_IN_SFLAGS 1
00042
00043 #define GET_SCNHDR_FLAGS H_GET_16
00044 #define PUT_SCNHDR_FLAGS H_PUT_16
00045
00046 static void rtype2howto
00047 PARAMS ((arelent *cache_ptr, struct internal_reloc *dst));
00048 static bfd_reloc_status_type ppbase_reloc
00049 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
00050 static bfd_reloc_status_type glob15_reloc
00051 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
00052 static bfd_reloc_status_type glob16_reloc
00053 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
00054 static bfd_reloc_status_type local16_reloc
00055 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
00056 static bfd_boolean coff_tic80_relocate_section
00057 PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
00058 struct internal_reloc *, struct internal_syment *, asection **));
00059 static reloc_howto_type * coff_tic80_rtype_to_howto
00060 PARAMS ((bfd *, asection *, struct internal_reloc *,
00061 struct coff_link_hash_entry *, struct internal_syment *,
00062 bfd_vma *));
00063
00064 static reloc_howto_type tic80_howto_table[] =
00065 {
00066
00067 HOWTO (R_RELLONG,
00068 0,
00069 2,
00070 32,
00071 FALSE,
00072 0,
00073 complain_overflow_bitfield,
00074 NULL,
00075 "RELLONG",
00076 TRUE,
00077 0xffffffff,
00078 0xffffffff,
00079 FALSE),
00080
00081 HOWTO (R_MPPCR,
00082 2,
00083 2,
00084 32,
00085 TRUE,
00086 0,
00087 complain_overflow_signed,
00088 NULL,
00089 "MPPCR",
00090 TRUE,
00091 0xffffffff,
00092 0xffffffff,
00093 TRUE),
00094
00095 HOWTO (R_ABS,
00096 0,
00097 2,
00098 32,
00099 FALSE,
00100 0,
00101 complain_overflow_bitfield,
00102 NULL,
00103 "ABS",
00104 TRUE,
00105 0xffffffff,
00106 0xffffffff,
00107 FALSE),
00108
00109 HOWTO (R_PPBASE,
00110 0,
00111 2,
00112 32,
00113 FALSE,
00114 0,
00115 complain_overflow_dont,
00116 ppbase_reloc,
00117 "PPBASE",
00118 TRUE,
00119 0xffffffff,
00120 0xffffffff,
00121 FALSE),
00122
00123 HOWTO (R_PPLBASE,
00124 0,
00125 2,
00126 32,
00127 FALSE,
00128 0,
00129 complain_overflow_dont,
00130 ppbase_reloc,
00131 "PPLBASE",
00132 TRUE,
00133 0xffffffff,
00134 0xffffffff,
00135 FALSE),
00136
00137 HOWTO (R_PP15,
00138 0,
00139 2,
00140 15,
00141 FALSE,
00142 6,
00143 complain_overflow_dont,
00144 glob15_reloc,
00145 "PP15",
00146 TRUE,
00147 0x1ffc0,
00148 0x1ffc0,
00149 FALSE),
00150
00151 HOWTO (R_PP15W,
00152 2,
00153 2,
00154 15,
00155 FALSE,
00156 6,
00157 complain_overflow_dont,
00158 glob15_reloc,
00159 "PP15W",
00160 TRUE,
00161 0x1ffc0,
00162 0x1ffc0,
00163 FALSE),
00164
00165 HOWTO (R_PP15H,
00166 1,
00167 2,
00168 15,
00169 FALSE,
00170 6,
00171 complain_overflow_dont,
00172 glob15_reloc,
00173 "PP15H",
00174 TRUE,
00175 0x1ffc0,
00176 0x1ffc0,
00177 FALSE),
00178
00179 HOWTO (R_PP16B,
00180 0,
00181 2,
00182 16,
00183 FALSE,
00184 6,
00185 complain_overflow_dont,
00186 glob16_reloc,
00187 "PP16B",
00188 TRUE,
00189 0x3ffc0,
00190 0x3ffc0,
00191 FALSE),
00192
00193 HOWTO (R_PPL15,
00194 0,
00195 2,
00196 15,
00197 FALSE,
00198 0,
00199 complain_overflow_dont,
00200 NULL,
00201 "PPL15",
00202 TRUE,
00203 0x7fff,
00204 0x7fff,
00205 FALSE),
00206
00207 HOWTO (R_PPL15W,
00208 2,
00209 2,
00210 15,
00211 FALSE,
00212 0,
00213 complain_overflow_dont,
00214 NULL,
00215 "PPL15W",
00216 TRUE,
00217 0x7fff,
00218 0x7fff,
00219 FALSE),
00220
00221 HOWTO (R_PPL15H,
00222 1,
00223 2,
00224 15,
00225 FALSE,
00226 0,
00227 complain_overflow_dont,
00228 NULL,
00229 "PPL15H",
00230 TRUE,
00231 0x7fff,
00232 0x7fff,
00233 FALSE),
00234
00235 HOWTO (R_PPL16B,
00236 0,
00237 2,
00238 16,
00239 FALSE,
00240 0,
00241 complain_overflow_dont,
00242 local16_reloc,
00243 "PPL16B",
00244 TRUE,
00245 0xffff,
00246 0xffff,
00247 FALSE),
00248
00249 HOWTO (R_PPN15,
00250 0,
00251 -2,
00252 15,
00253 FALSE,
00254 6,
00255 complain_overflow_dont,
00256 glob15_reloc,
00257 "PPN15",
00258 TRUE,
00259 0x1ffc0,
00260 0x1ffc0,
00261 FALSE),
00262
00263 HOWTO (R_PPN15W,
00264 2,
00265 -2,
00266 15,
00267 FALSE,
00268 6,
00269 complain_overflow_dont,
00270 glob15_reloc,
00271 "PPN15W",
00272 TRUE,
00273 0x1ffc0,
00274 0x1ffc0,
00275 FALSE),
00276
00277 HOWTO (R_PPN15H,
00278 1,
00279 -2,
00280 15,
00281 FALSE,
00282 6,
00283 complain_overflow_dont,
00284 glob15_reloc,
00285 "PPN15H",
00286 TRUE,
00287 0x1ffc0,
00288 0x1ffc0,
00289 FALSE),
00290
00291 HOWTO (R_PPN16B,
00292 0,
00293 -2,
00294 16,
00295 FALSE,
00296 6,
00297 complain_overflow_dont,
00298 glob16_reloc,
00299 "PPN16B",
00300 TRUE,
00301 0x3ffc0,
00302 0x3ffc0,
00303 FALSE),
00304
00305 HOWTO (R_PPLN15,
00306 0,
00307 -2,
00308 15,
00309 FALSE,
00310 0,
00311 complain_overflow_dont,
00312 NULL,
00313 "PPLN15",
00314 TRUE,
00315 0x7fff,
00316 0x7fff,
00317 FALSE),
00318
00319 HOWTO (R_PPLN15W,
00320 2,
00321 -2,
00322 15,
00323 FALSE,
00324 0,
00325 complain_overflow_dont,
00326 NULL,
00327 "PPLN15W",
00328 TRUE,
00329 0x7fff,
00330 0x7fff,
00331 FALSE),
00332
00333 HOWTO (R_PPLN15H,
00334 1,
00335 -2,
00336 15,
00337 FALSE,
00338 0,
00339 complain_overflow_dont,
00340 NULL,
00341 "PPLN15H",
00342 TRUE,
00343 0x7fff,
00344 0x7fff,
00345 FALSE),
00346
00347 HOWTO (R_PPLN16B,
00348 0,
00349 -2,
00350 15,
00351 FALSE,
00352 0,
00353 complain_overflow_dont,
00354 local16_reloc,
00355 "PPLN16B",
00356 TRUE,
00357 0xffff,
00358 0xffff,
00359 FALSE)
00360 };
00361
00362
00363
00364
00365
00366
00367
00368 static bfd_reloc_status_type
00369 ppbase_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
00370 error_message)
00371 bfd *abfd ATTRIBUTE_UNUSED;
00372 arelent *reloc_entry ATTRIBUTE_UNUSED;
00373 asymbol *symbol_in ATTRIBUTE_UNUSED;
00374 PTR data ATTRIBUTE_UNUSED;
00375 asection *input_section ATTRIBUTE_UNUSED;
00376 bfd *output_bfd ATTRIBUTE_UNUSED;
00377 char **error_message ATTRIBUTE_UNUSED;
00378 {
00379
00380 abort ();
00381 }
00382
00383
00384
00385 static bfd_reloc_status_type
00386 glob15_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
00387 error_message)
00388 bfd *abfd ATTRIBUTE_UNUSED;
00389 arelent *reloc_entry ATTRIBUTE_UNUSED;
00390 asymbol *symbol_in ATTRIBUTE_UNUSED;
00391 PTR data ATTRIBUTE_UNUSED;
00392 asection *input_section ATTRIBUTE_UNUSED;
00393 bfd *output_bfd ATTRIBUTE_UNUSED;
00394 char **error_message ATTRIBUTE_UNUSED;
00395 {
00396
00397 abort ();
00398 }
00399
00400
00401
00402 static bfd_reloc_status_type
00403 glob16_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
00404 error_message)
00405 bfd *abfd ATTRIBUTE_UNUSED;
00406 arelent *reloc_entry ATTRIBUTE_UNUSED;
00407 asymbol *symbol_in ATTRIBUTE_UNUSED;
00408 PTR data ATTRIBUTE_UNUSED;
00409 asection *input_section ATTRIBUTE_UNUSED;
00410 bfd *output_bfd ATTRIBUTE_UNUSED;
00411 char **error_message ATTRIBUTE_UNUSED;
00412 {
00413
00414 abort ();
00415 }
00416
00417
00418
00419 static bfd_reloc_status_type
00420 local16_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
00421 error_message)
00422 bfd *abfd ATTRIBUTE_UNUSED;
00423 arelent *reloc_entry ATTRIBUTE_UNUSED;
00424 asymbol *symbol_in ATTRIBUTE_UNUSED;
00425 PTR data ATTRIBUTE_UNUSED;
00426 asection *input_section ATTRIBUTE_UNUSED;
00427 bfd *output_bfd ATTRIBUTE_UNUSED;
00428 char **error_message ATTRIBUTE_UNUSED;
00429 {
00430
00431 abort ();
00432 }
00433
00434
00435
00436
00437
00438 static void
00439 rtype2howto (cache_ptr, dst)
00440 arelent *cache_ptr;
00441 struct internal_reloc *dst;
00442 {
00443 unsigned int i;
00444
00445 for (i = 0; i < sizeof tic80_howto_table / sizeof tic80_howto_table[0]; i++)
00446 {
00447 if (tic80_howto_table[i].type == dst->r_type)
00448 {
00449 cache_ptr->howto = tic80_howto_table + i;
00450 return;
00451 }
00452 }
00453
00454 (*_bfd_error_handler) (_("Unrecognized reloc type 0x%x"),
00455 (unsigned int) dst->r_type);
00456 cache_ptr->howto = tic80_howto_table + 0;
00457 }
00458
00459 #define RTYPE2HOWTO(cache_ptr, dst) rtype2howto (cache_ptr, dst)
00460 #define coff_rtype_to_howto coff_tic80_rtype_to_howto
00461
00462 static reloc_howto_type *
00463 coff_tic80_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
00464 bfd *abfd ATTRIBUTE_UNUSED;
00465 asection *sec;
00466 struct internal_reloc *rel;
00467 struct coff_link_hash_entry *h ATTRIBUTE_UNUSED;
00468 struct internal_syment *sym ATTRIBUTE_UNUSED;
00469 bfd_vma *addendp;
00470 {
00471 arelent genrel;
00472
00473 if (rel -> r_symndx == -1 && addendp != NULL)
00474 {
00475
00476
00477
00478 *addendp = (sec -> output_section -> vma + sec -> output_offset) - sec -> vma;
00479 }
00480 RTYPE2HOWTO (&genrel, rel);
00481 return genrel.howto;
00482 }
00483
00484 #ifndef BADMAG
00485 #define BADMAG(x) TIC80BADMAG(x)
00486 #endif
00487
00488 #define coff_relocate_section coff_tic80_relocate_section
00489
00490
00491
00492
00493 static bfd_boolean
00494 coff_tic80_relocate_section (output_bfd, info, input_bfd,
00495 input_section, contents, relocs, syms,
00496 sections)
00497 bfd *output_bfd;
00498 struct bfd_link_info *info;
00499 bfd *input_bfd;
00500 asection *input_section;
00501 bfd_byte *contents;
00502 struct internal_reloc *relocs;
00503 struct internal_syment *syms;
00504 asection **sections;
00505 {
00506 struct internal_reloc *rel;
00507 struct internal_reloc *relend;
00508
00509 rel = relocs;
00510 relend = rel + input_section->reloc_count;
00511 for (; rel < relend; rel++)
00512 {
00513 long symndx;
00514 struct coff_link_hash_entry *h;
00515 struct internal_syment *sym;
00516 bfd_vma addend;
00517 bfd_vma val;
00518 reloc_howto_type *howto;
00519 bfd_reloc_status_type rstat;
00520 bfd_vma addr;
00521
00522 symndx = rel->r_symndx;
00523
00524 if (symndx == -1)
00525 {
00526 h = NULL;
00527 sym = NULL;
00528 }
00529 else
00530 {
00531 h = obj_coff_sym_hashes (input_bfd)[symndx];
00532 sym = syms + symndx;
00533 }
00534
00535
00536
00537
00538
00539
00540 if (sym != NULL && sym->n_scnum != 0)
00541 addend = - sym->n_value;
00542 else
00543 addend = 0;
00544
00545 howto = bfd_coff_rtype_to_howto (input_bfd, input_section, rel, h,
00546 sym, &addend);
00547 if (howto == NULL)
00548 return FALSE;
00549
00550 val = 0;
00551
00552 if (h == NULL)
00553 {
00554 asection *sec;
00555
00556 if (symndx == -1)
00557 {
00558 sec = bfd_abs_section_ptr;
00559 val = 0;
00560 }
00561 else
00562 {
00563 sec = sections[symndx];
00564 val = (sec->output_section->vma
00565 + sec->output_offset
00566 + sym->n_value);
00567 if (! obj_pe (output_bfd))
00568 val -= sec->vma;
00569 }
00570 }
00571 else
00572 {
00573 if (h->root.type == bfd_link_hash_defined
00574 || h->root.type == bfd_link_hash_defweak)
00575 {
00576 asection *sec;
00577
00578 sec = h->root.u.def.section;
00579 val = (h->root.u.def.value
00580 + sec->output_section->vma
00581 + sec->output_offset);
00582 }
00583
00584 else if (! info->relocatable)
00585 {
00586 if (! ((*info->callbacks->undefined_symbol)
00587 (info, h->root.root.string, input_bfd, input_section,
00588 rel->r_vaddr - input_section->vma, TRUE)))
00589 return FALSE;
00590 }
00591 }
00592
00593 addr = rel->r_vaddr - input_section->vma;
00594
00595
00596
00597
00598 switch (howto->type)
00599 {
00600 default:
00601 case R_ABS:
00602 case R_RELLONGX:
00603 case R_PPL15:
00604 case R_PPL15W:
00605 case R_PPL15H:
00606 case R_PPLN15:
00607 case R_PPLN15W:
00608 case R_PPLN15H:
00609 rstat = _bfd_final_link_relocate (howto, input_bfd, input_section,
00610 contents, addr, val, addend);
00611 break;
00612
00613 case R_PP15:
00614 case R_PP15W:
00615 case R_PP15H:
00616 case R_PPN15:
00617 case R_PPN15W:
00618 case R_PPN15H:
00619
00620 rstat = _bfd_final_link_relocate (howto, input_bfd, input_section,
00621 contents + 2, addr, val, addend);
00622 break;
00623
00624 case R_PP16B:
00625 case R_PPN16B:
00626 {
00627
00628 bfd_byte hold;
00629
00630 hold = contents[addr + 4];
00631 contents[addr + 4] &=~ 0x20;
00632 contents[addr + 4] |= (contents[addr] >> 1) & 0x20;
00633 rstat = _bfd_final_link_relocate (howto, input_bfd, input_section,
00634 contents + 2, addr,
00635 val, addend);
00636 contents[addr] &=~ 0x40;
00637 contents[addr] |= (contents[addr + 4] << 1) & 0x40;
00638 contents[addr + 4] &=~ 0x20;
00639 contents[addr + 4] |= hold & 0x20;
00640 break;
00641 }
00642
00643 case R_PPL16B:
00644 case R_PPLN16B:
00645 {
00646
00647 bfd_byte hold;
00648
00649 hold = contents[addr + 1];
00650 contents[addr + 1] &=~ 0x80;
00651 contents[addr + 1] |= (contents[addr + 3] << 3) & 0x80;
00652 rstat = _bfd_final_link_relocate (howto, input_bfd, input_section,
00653 contents, addr,
00654 val, addend);
00655 contents[addr + 3] &= ~0x10;
00656 contents[addr + 3] |= (contents[addr + 1] >> 3) & 0x10;
00657 contents[addr + 1] &=~ 0x80;
00658 contents[addr + 1] |= hold & 0x80;
00659 break;
00660 }
00661
00662 case R_PPBASE:
00663
00664 contents[addr] &=~ 0x3;
00665 if (val >= 0x1000000 && val < 0x1000800)
00666 contents[addr] |= 0x3;
00667 else
00668 contents[addr] |= 0x2;
00669 rstat = bfd_reloc_ok;
00670 break;
00671
00672 case R_PPLBASE:
00673
00674 contents[addr + 2] &= ~0xc0;
00675 if (val >= 0x1000000 && val < 0x1000800)
00676 contents[addr + 2] |= 0xc0;
00677 else
00678 contents[addr + 2] |= 0x80;
00679 rstat = bfd_reloc_ok;
00680 break;
00681 }
00682
00683 switch (rstat)
00684 {
00685 default:
00686 abort ();
00687 case bfd_reloc_ok:
00688 break;
00689 case bfd_reloc_outofrange:
00690 (*_bfd_error_handler)
00691 (_("%B: bad reloc address 0x%lx in section `%A'"),
00692 input_bfd, input_section, (unsigned long) rel->r_vaddr);
00693 return FALSE;
00694 case bfd_reloc_overflow:
00695 {
00696 const char *name;
00697 char buf[SYMNMLEN + 1];
00698
00699 if (symndx == -1)
00700 name = "*ABS*";
00701 else if (h != NULL)
00702 name = NULL;
00703 else
00704 {
00705 name = _bfd_coff_internal_syment_name (input_bfd, sym, buf);
00706 if (name == NULL)
00707 return FALSE;
00708 }
00709
00710 if (! ((*info->callbacks->reloc_overflow)
00711 (info, (h ? &h->root : NULL), name, howto->name,
00712 (bfd_vma) 0, input_bfd, input_section,
00713 rel->r_vaddr - input_section->vma)))
00714 return FALSE;
00715 }
00716 }
00717 }
00718 return TRUE;
00719 }
00720
00721
00722 #define SWAP_OUT_RELOC_EXTRA(abfd,src,dst) \
00723 do \
00724 { \
00725 dst->r_reserved[0] = 0; \
00726 dst->r_reserved[1] = 0; \
00727 } \
00728 while (0)
00729
00730 #define TIC80COFF 1
00731 #undef C_AUTOARG
00732 #undef C_LASTENT
00733 #include "coffcode.h"
00734
00735 CREATE_LITTLE_COFF_TARGET_VEC (tic80coff_vec, "coff-tic80", D_PAGED, 0, '_', NULL, COFF_SWAP_TABLE)