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 "libbfd.h"
00029 #include "coff/mcore.h"
00030 #include "coff/internal.h"
00031 #include "coff/pe.h"
00032 #include "libcoff.h"
00033
00034 #ifdef BADMAG
00035 #undef BADMAG
00036 #endif
00037 #define BADMAG(x) MCOREBADMAG(x)
00038
00039 #ifndef NUM_ELEM
00040 #define NUM_ELEM(A) (sizeof (A) / sizeof (A)[0])
00041 #endif
00042
00043
00044
00045 extern bfd_boolean mcore_bfd_coff_final_link
00046 PARAMS ((bfd *, struct bfd_link_info *));
00047 static bfd_reloc_status_type mcore_coff_unsupported_reloc
00048 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
00049 static bfd_boolean coff_mcore_relocate_section
00050 PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
00051 struct internal_reloc *, struct internal_syment *, asection **));
00052 static reloc_howto_type *mcore_coff_reloc_type_lookup
00053 PARAMS ((bfd *, bfd_reloc_code_real_type));
00054 static reloc_howto_type *coff_mcore_rtype_to_howto
00055 PARAMS ((bfd *, asection *, struct internal_reloc *,
00056 struct coff_link_hash_entry *, struct internal_syment *,
00057 bfd_vma *));
00058 static void mcore_emit_base_file_entry
00059 PARAMS ((struct bfd_link_info *, bfd *, asection *, bfd_vma));
00060 static bfd_boolean in_reloc_p PARAMS ((bfd *, reloc_howto_type *));
00061
00062
00063
00064
00065 #define TOC_LOAD_ADJUSTMENT (-32768)
00066 #define TOC_SECTION_NAME ".private.toc"
00067
00068
00069 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER 2
00070
00071
00072
00073 #define MINUS_ONE (((bfd_vma)0) - 1)
00074
00075 static reloc_howto_type mcore_coff_howto_table[] =
00076 {
00077
00078 HOWTO (IMAGE_REL_MCORE_ABSOLUTE,
00079 0,
00080 0,
00081 0,
00082 FALSE,
00083 0,
00084 complain_overflow_dont,
00085 NULL,
00086 "ABSOLUTE",
00087 FALSE,
00088 0x00,
00089 0x00,
00090 FALSE),
00091
00092 HOWTO (IMAGE_REL_MCORE_ADDR32,
00093 0,
00094 2,
00095 32,
00096 FALSE,
00097 0,
00098 complain_overflow_bitfield,
00099 NULL,
00100 "ADDR32",
00101 TRUE,
00102 0xffffffff,
00103 0xffffffff,
00104 FALSE),
00105
00106
00107
00108 HOWTO (IMAGE_REL_MCORE_PCREL_IMM8BY4,
00109 2,
00110 1,
00111 8,
00112 TRUE,
00113 0,
00114 complain_overflow_bitfield,
00115 mcore_coff_unsupported_reloc,
00116 "IMM8BY4",
00117 FALSE,
00118 0,
00119 0,
00120 TRUE),
00121
00122
00123
00124
00125 HOWTO (IMAGE_REL_MCORE_PCREL_IMM11BY2,
00126 1,
00127 1,
00128 11,
00129 TRUE,
00130 0,
00131 complain_overflow_signed,
00132 NULL,
00133 "IMM11BY2",
00134 FALSE,
00135 0x0,
00136 0x7ff,
00137 TRUE),
00138
00139
00140 HOWTO (IMAGE_REL_MCORE_PCREL_IMM4BY2,
00141 1,
00142 1,
00143 4,
00144 TRUE,
00145 0,
00146 complain_overflow_bitfield,
00147 mcore_coff_unsupported_reloc,
00148 "IMM4BY2",
00149 FALSE,
00150 0,
00151 0,
00152 TRUE),
00153
00154
00155 HOWTO (IMAGE_REL_MCORE_PCREL_32,
00156 0,
00157 2,
00158 32,
00159 TRUE,
00160 0,
00161 complain_overflow_bitfield,
00162 NULL,
00163 "PCREL_32",
00164 FALSE,
00165 0x0,
00166 0xffffffff,
00167 TRUE),
00168
00169
00170
00171
00172
00173
00174
00175
00176 HOWTO (IMAGE_REL_MCORE_PCREL_JSR_IMM11BY2,
00177 1,
00178 1,
00179 11,
00180 TRUE,
00181 0,
00182 complain_overflow_signed,
00183 NULL,
00184 "JSR_IMM11BY2",
00185 FALSE,
00186 0x0,
00187 0x7ff,
00188 TRUE),
00189
00190 HOWTO (IMAGE_REL_MCORE_RVA,
00191 0,
00192 2,
00193 32,
00194 FALSE,
00195 0,
00196 complain_overflow_signed,
00197 NULL,
00198 "MCORE_RVA",
00199 TRUE,
00200 0xffffffff,
00201 0xffffffff,
00202 TRUE)
00203 };
00204
00205
00206
00207
00208 typedef struct coff_mcore_link_hash_table
00209 {
00210
00211 struct coff_link_hash_table root;
00212
00213 bfd * bfd_of_toc_owner;
00214 long int global_toc_size;
00215 long int import_table_size;
00216 long int first_thunk_address;
00217 long int thunk_size;
00218 }
00219 mcore_hash_table;
00220
00221
00222 #define coff_mcore_hash_table(info) \
00223 ((mcore_hash_table *) ((info)->hash))
00224
00225
00226
00227
00228 static void
00229 mcore_emit_base_file_entry (info, output_bfd, input_section, reloc_offset)
00230 struct bfd_link_info * info;
00231 bfd * output_bfd;
00232 asection * input_section;
00233 bfd_vma reloc_offset;
00234 {
00235 bfd_vma addr = reloc_offset
00236 - input_section->vma
00237 + input_section->output_offset
00238 + input_section->output_section->vma;
00239
00240 if (coff_data (output_bfd)->pe)
00241 addr -= pe_data (output_bfd)->pe_opthdr.ImageBase;
00242
00243 fwrite (&addr, 1, sizeof (addr), (FILE *) info->base_file);
00244 }
00245
00246 static bfd_reloc_status_type
00247 mcore_coff_unsupported_reloc (abfd, reloc_entry, symbol, data, input_section,
00248 output_bfd, error_message)
00249 bfd * abfd;
00250 arelent * reloc_entry;
00251 asymbol * symbol ATTRIBUTE_UNUSED;
00252 PTR data ATTRIBUTE_UNUSED;
00253 asection * input_section ATTRIBUTE_UNUSED;
00254 bfd * output_bfd ATTRIBUTE_UNUSED;
00255 char ** error_message ATTRIBUTE_UNUSED;
00256 {
00257 BFD_ASSERT (reloc_entry->howto != (reloc_howto_type *)0);
00258
00259 _bfd_error_handler (_("%B: Relocation %s (%d) is not currently supported.\n"),
00260 abfd,
00261 reloc_entry->howto->name,
00262 reloc_entry->howto->type);
00263
00264 return bfd_reloc_notsupported;
00265 }
00266
00267
00268 #define HOW2MAP(bfd_rtype, mcore_rtype) \
00269 case bfd_rtype: return & mcore_coff_howto_table [mcore_rtype]
00270
00271 static reloc_howto_type *
00272 mcore_coff_reloc_type_lookup (abfd, code)
00273 bfd * abfd ATTRIBUTE_UNUSED;
00274 bfd_reloc_code_real_type code;
00275 {
00276 switch (code)
00277 {
00278 HOW2MAP (BFD_RELOC_32, IMAGE_REL_MCORE_ADDR32);
00279 HOW2MAP (BFD_RELOC_MCORE_PCREL_IMM8BY4, IMAGE_REL_MCORE_PCREL_IMM8BY4);
00280 HOW2MAP (BFD_RELOC_MCORE_PCREL_IMM11BY2, IMAGE_REL_MCORE_PCREL_IMM11BY2);
00281 HOW2MAP (BFD_RELOC_MCORE_PCREL_IMM4BY2, IMAGE_REL_MCORE_PCREL_IMM4BY2);
00282 HOW2MAP (BFD_RELOC_32_PCREL, IMAGE_REL_MCORE_PCREL_32);
00283 HOW2MAP (BFD_RELOC_MCORE_PCREL_JSR_IMM11BY2, IMAGE_REL_MCORE_PCREL_JSR_IMM11BY2);
00284 HOW2MAP (BFD_RELOC_RVA, IMAGE_REL_MCORE_RVA);
00285 default:
00286 return NULL;
00287 }
00288
00289 }
00290
00291 #undef HOW2MAP
00292
00293 #define RTYPE2HOWTO(cache_ptr, dst) \
00294 (cache_ptr)->howto = mcore_coff_howto_table + (dst)->r_type;
00295
00296 static reloc_howto_type *
00297 coff_mcore_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
00298 bfd * abfd ATTRIBUTE_UNUSED;
00299 asection * sec;
00300 struct internal_reloc * rel;
00301 struct coff_link_hash_entry * h ATTRIBUTE_UNUSED;
00302 struct internal_syment * sym;
00303 bfd_vma * addendp;
00304 {
00305 reloc_howto_type * howto;
00306
00307 if (rel->r_type >= NUM_ELEM (mcore_coff_howto_table))
00308 return NULL;
00309
00310 howto = mcore_coff_howto_table + rel->r_type;
00311
00312 if (rel->r_type == IMAGE_REL_MCORE_RVA)
00313 * addendp -= pe_data (sec->output_section->owner)->pe_opthdr.ImageBase;
00314
00315 else if (howto->pc_relative)
00316 {
00317 * addendp = sec->vma - 2;
00318
00319
00320
00321
00322
00323
00324
00325 if (sym != NULL && sym->n_scnum != 0)
00326 * addendp -= sym->n_value;
00327 }
00328 else
00329 * addendp = 0;
00330
00331 return howto;
00332 }
00333
00334
00335
00336
00337 static bfd_boolean
00338 in_reloc_p (abfd, howto)
00339 bfd * abfd ATTRIBUTE_UNUSED;
00340 reloc_howto_type * howto;
00341 {
00342 return ! howto->pc_relative && howto->type != IMAGE_REL_MCORE_RVA;
00343 }
00344
00345
00346 static bfd_boolean
00347 coff_mcore_relocate_section (output_bfd, info, input_bfd, input_section,
00348 contents, relocs, syms, sections)
00349 bfd * output_bfd;
00350 struct bfd_link_info * info;
00351 bfd * input_bfd;
00352 asection * input_section;
00353 bfd_byte * contents;
00354 struct internal_reloc * relocs;
00355 struct internal_syment * syms;
00356 asection ** sections;
00357 {
00358 struct internal_reloc * rel;
00359 struct internal_reloc * relend;
00360 bfd_boolean hihalf;
00361 bfd_vma hihalf_val;
00362
00363
00364
00365
00366 if (info->relocatable)
00367 return TRUE;
00368
00369
00370 if ( input_bfd->xvec->byteorder != output_bfd->xvec->byteorder
00371 && output_bfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN)
00372 {
00373 (*_bfd_error_handler)
00374 (_("%B: compiled for a %s system and target is %s.\n"),
00375 input_bfd,
00376 bfd_big_endian (input_bfd) ? _("big endian") : _("little endian"),
00377 bfd_big_endian (output_bfd) ? _("big endian") : _("little endian"));
00378
00379 bfd_set_error (bfd_error_wrong_format);
00380 return FALSE;
00381 }
00382
00383 hihalf = FALSE;
00384 hihalf_val = 0;
00385
00386 rel = relocs;
00387 relend = rel + input_section->reloc_count;
00388
00389 for (; rel < relend; rel++)
00390 {
00391 long symndx;
00392 struct internal_syment * sym;
00393 bfd_vma val;
00394 bfd_vma addend;
00395 bfd_reloc_status_type rstat;
00396 bfd_byte * loc;
00397 unsigned short r_type = rel->r_type;
00398 reloc_howto_type * howto = NULL;
00399 struct coff_link_hash_entry * h;
00400 const char * my_name;
00401
00402 symndx = rel->r_symndx;
00403 loc = contents + rel->r_vaddr - input_section->vma;
00404
00405 if (symndx == -1)
00406 {
00407 h = NULL;
00408 sym = NULL;
00409 }
00410 else
00411 {
00412 h = obj_coff_sym_hashes (input_bfd)[symndx];
00413 sym = syms + symndx;
00414 }
00415
00416 addend = 0;
00417
00418
00419 howto = bfd_coff_rtype_to_howto (input_bfd, input_section, rel, h,
00420 sym, & addend);
00421 if (howto == NULL)
00422 return FALSE;
00423
00424 val = 0;
00425
00426 if (h == NULL)
00427 {
00428 if (symndx == -1)
00429 my_name = "*ABS*";
00430 else
00431 {
00432 asection * sec = sections[symndx];
00433
00434 val = (sym->n_value
00435 + sec->output_section->vma
00436 + sec->output_offset);
00437
00438 if (sym == NULL)
00439 my_name = "*unknown*";
00440 else if ( sym->_n._n_n._n_zeroes == 0
00441 && sym->_n._n_n._n_offset != 0)
00442 my_name = obj_coff_strings (input_bfd) + sym->_n._n_n._n_offset;
00443 else
00444 {
00445 static char buf [SYMNMLEN + 1];
00446
00447 strncpy (buf, sym->_n._n_name, SYMNMLEN);
00448 buf[SYMNMLEN] = '\0';
00449 my_name = buf;
00450 }
00451 }
00452 }
00453 else
00454 {
00455 if ( h->root.type == bfd_link_hash_defined
00456 || h->root.type == bfd_link_hash_defweak)
00457 {
00458 asection * sec = h->root.u.def.section;
00459
00460 val = (h->root.u.def.value
00461 + sec->output_section->vma
00462 + sec->output_offset);
00463 }
00464 else
00465 {
00466 if (! ((*info->callbacks->undefined_symbol)
00467 (info, h->root.root.string, input_bfd, input_section,
00468 rel->r_vaddr - input_section->vma, TRUE)))
00469 return FALSE;
00470 }
00471
00472 my_name = h->root.root.string;
00473 }
00474
00475 rstat = bfd_reloc_ok;
00476
00477
00478 switch (r_type)
00479 {
00480 default:
00481 _bfd_error_handler (_("%B: unsupported relocation type 0x%02x"),
00482 input_bfd, r_type);
00483 bfd_set_error (bfd_error_bad_value);
00484 return FALSE;
00485
00486 case IMAGE_REL_MCORE_ABSOLUTE:
00487 _bfd_error_handler
00488 (_("Warning: unsupported reloc %s <file %B, section %A>\n"
00489 "sym %ld (%s), r_vaddr %ld (%lx)"),
00490 input_bfd, input_section, howto->name,
00491 rel->r_symndx, my_name, (long) rel->r_vaddr,
00492 (unsigned long) rel->r_vaddr);
00493 break;
00494
00495 case IMAGE_REL_MCORE_PCREL_IMM8BY4:
00496 case IMAGE_REL_MCORE_PCREL_IMM11BY2:
00497 case IMAGE_REL_MCORE_PCREL_IMM4BY2:
00498 case IMAGE_REL_MCORE_PCREL_32:
00499 case IMAGE_REL_MCORE_PCREL_JSR_IMM11BY2:
00500 case IMAGE_REL_MCORE_ADDR32:
00501
00502 rstat = _bfd_relocate_contents (howto, input_bfd, val, loc);
00503 break;
00504
00505 case IMAGE_REL_MCORE_RVA:
00506 rstat = _bfd_final_link_relocate
00507 (howto, input_bfd,
00508 input_section, contents, rel->r_vaddr - input_section->vma,
00509 val, addend);
00510 break;
00511 }
00512
00513 if (info->base_file)
00514 {
00515
00516 if (sym && pe_data (output_bfd)->in_reloc_p (output_bfd, howto))
00517 mcore_emit_base_file_entry (info, output_bfd, input_section, rel->r_vaddr);
00518 }
00519
00520 switch (rstat)
00521 {
00522 default:
00523 abort ();
00524
00525 case bfd_reloc_ok:
00526 break;
00527
00528 case bfd_reloc_overflow:
00529 if (! ((*info->callbacks->reloc_overflow)
00530 (info, (h ? &h->root : NULL), my_name, howto->name,
00531 (bfd_vma) 0, input_bfd,
00532 input_section, rel->r_vaddr - input_section->vma)))
00533 return FALSE;
00534 }
00535 }
00536
00537 return TRUE;
00538 }
00539
00540
00541
00542
00543
00544 #define coff_bfd_reloc_type_lookup mcore_coff_reloc_type_lookup
00545 #define coff_relocate_section coff_mcore_relocate_section
00546 #define coff_rtype_to_howto coff_mcore_rtype_to_howto
00547
00548 #define SELECT_RELOC(internal, howto) {internal.r_type = howto->type;}
00549
00550
00551
00552 #define SWAP_IN_RELOC_OFFSET H_GET_32
00553 #define SWAP_OUT_RELOC_OFFSET H_PUT_32
00554
00555 #define COFF_PAGE_SIZE 0x1000
00556
00557 #include "coffcode.h"
00558
00559
00560 extern const bfd_target TARGET_LITTLE_SYM;
00561
00562
00563 CREATE_BIG_COFF_TARGET_VEC (TARGET_BIG_SYM, TARGET_BIG_NAME, D_PAGED,
00564 (SEC_CODE | SEC_DATA | SEC_DEBUGGING | SEC_READONLY | SEC_LINK_ONCE | SEC_LINK_DUPLICATES),
00565 0, & TARGET_LITTLE_SYM, COFF_SWAP_TABLE)
00566 CREATE_LITTLE_COFF_TARGET_VEC (TARGET_LITTLE_SYM, TARGET_LITTLE_NAME, D_PAGED,
00567 (SEC_CODE | SEC_DATA | SEC_DEBUGGING | SEC_READONLY | SEC_LINK_ONCE | SEC_LINK_DUPLICATES),
00568 0, & TARGET_BIG_SYM, COFF_SWAP_TABLE)