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 #define I960 1
00027 #define BADMAG(x) I960BADMAG(x)
00028
00029 #include "bfd.h"
00030 #include "sysdep.h"
00031 #include "libbfd.h"
00032 #include "coff/i960.h"
00033 #include "coff/internal.h"
00034 #include "libcoff.h"
00035
00036 static bfd_boolean coff_i960_is_local_label_name
00037 PARAMS ((bfd *, const char *));
00038 static bfd_reloc_status_type optcall_callback
00039 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
00040 static bfd_reloc_status_type coff_i960_relocate
00041 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
00042 static reloc_howto_type *coff_i960_reloc_type_lookup
00043 PARAMS ((bfd *, bfd_reloc_code_real_type));
00044 static bfd_boolean coff_i960_start_final_link
00045 PARAMS ((bfd *, struct bfd_link_info *));
00046 static bfd_boolean coff_i960_relocate_section
00047 PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
00048 struct internal_reloc *, struct internal_syment *, asection **));
00049 static bfd_boolean coff_i960_adjust_symndx
00050 PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *,
00051 struct internal_reloc *, bfd_boolean *));
00052
00053 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (3)
00054 #define COFF_ALIGN_IN_SECTION_HEADER 1
00055
00056 #define GET_SCNHDR_ALIGN H_GET_32
00057 #define PUT_SCNHDR_ALIGN H_PUT_32
00058
00059
00060
00061 #define COFF_PAGE_SIZE 1
00062
00063 #define COFF_LONG_FILENAMES
00064
00065
00066
00067 static bfd_boolean
00068 coff_i960_is_local_label_name (abfd, name)
00069 bfd *abfd ATTRIBUTE_UNUSED;
00070 const char *name;
00071 {
00072 return (name[0] == 'L'
00073 || (name[0] == '.'
00074 && (name[1] == 'C'
00075 || name[1] == 'I'
00076 || name[1] == '.')));
00077 }
00078
00079
00080
00081 #ifndef CALC_ADDEND
00082 #define CALC_ADDEND(abfd, ptr, reloc, cache_ptr) \
00083 { \
00084 coff_symbol_type *coffsym = (coff_symbol_type *) NULL; \
00085 if (ptr && bfd_asymbol_bfd (ptr) != abfd) \
00086 coffsym = (obj_symbols (abfd) \
00087 + (cache_ptr->sym_ptr_ptr - symbols)); \
00088 else if (ptr) \
00089 coffsym = coff_symbol_from (abfd, ptr); \
00090 if (coffsym != (coff_symbol_type *) NULL \
00091 && coffsym->native->u.syment.n_scnum == 0) \
00092 cache_ptr->addend = 0; \
00093 else if (ptr && bfd_asymbol_bfd (ptr) == abfd \
00094 && ptr->section != (asection *) NULL) \
00095 cache_ptr->addend = - (ptr->section->vma + ptr->value); \
00096 else \
00097 cache_ptr->addend = 0; \
00098 if (ptr && (reloc.r_type == 25 || reloc.r_type == 27)) \
00099 cache_ptr->addend += asect->vma; \
00100 }
00101 #endif
00102
00103 #define CALLS 0x66003800
00104 #define BAL 0x0b000000
00105 #define BAL_MASK 0x00ffffff
00106
00107 static bfd_reloc_status_type
00108 optcall_callback (abfd, reloc_entry, symbol_in, data,
00109 input_section, ignore_bfd, error_message)
00110 bfd *abfd;
00111 arelent *reloc_entry;
00112 asymbol *symbol_in;
00113 PTR data;
00114 asection *input_section;
00115 bfd *ignore_bfd ATTRIBUTE_UNUSED;
00116 char **error_message;
00117 {
00118
00119
00120
00121 bfd_reloc_status_type result;
00122 coff_symbol_type *cs = coffsymbol(symbol_in);
00123
00124
00125
00126 if (bfd_is_und_section (cs->symbol.section)) {
00127 reloc_entry->address += input_section->output_offset;
00128 return bfd_reloc_ok;
00129 }
00130
00131
00132
00133 if ((bfd_asymbol_flavour(&cs->symbol) != bfd_target_coff_flavour)
00134 || (cs->native == (combined_entry_type *)NULL))
00135 {
00136
00137
00138
00139
00140 *error_message =
00141 (char *) _("uncertain calling convention for non-COFF symbol");
00142 result = bfd_reloc_dangerous;
00143 }
00144 else
00145 {
00146 switch (cs->native->u.syment.n_sclass)
00147 {
00148 case C_LEAFSTAT:
00149 case C_LEAFEXT:
00150
00151
00152 {
00153 union internal_auxent *aux = &((cs->native+2)->u.auxent);
00154 int word = bfd_get_32 (abfd, (bfd_byte *)data + reloc_entry->address);
00155 int olf = (aux->x_bal.x_balntry - cs->native->u.syment.n_value);
00156 BFD_ASSERT(cs->native->u.syment.n_numaux==2);
00157
00158
00159
00160
00161
00162
00163 word = ((word + olf) & BAL_MASK) | BAL;
00164 bfd_put_32 (abfd, (bfd_vma) word,
00165 (bfd_byte *) data + reloc_entry->address);
00166 }
00167 result = bfd_reloc_ok;
00168 break;
00169 case C_SCALL:
00170
00171 BFD_ASSERT(0);
00172 result = bfd_reloc_ok;
00173 break;
00174 default:
00175 result = bfd_reloc_ok;
00176 break;
00177 }
00178 }
00179 return result;
00180 }
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197 static bfd_reloc_status_type
00198 coff_i960_relocate (abfd, reloc_entry, symbol, data, input_section,
00199 output_bfd, error_message)
00200 bfd *abfd;
00201 arelent *reloc_entry;
00202 asymbol *symbol;
00203 PTR data ATTRIBUTE_UNUSED;
00204 asection *input_section ATTRIBUTE_UNUSED;
00205 bfd *output_bfd;
00206 char **error_message ATTRIBUTE_UNUSED;
00207 {
00208 asection *osec;
00209
00210 if (output_bfd == NULL)
00211 {
00212
00213 return bfd_reloc_continue;
00214 }
00215
00216 if (bfd_is_und_section (bfd_get_section (symbol)))
00217 {
00218
00219 return bfd_reloc_continue;
00220 }
00221
00222 if (bfd_is_com_section (bfd_get_section (symbol)))
00223 {
00224
00225
00226 return bfd_reloc_continue;
00227 }
00228
00229
00230
00231 osec = bfd_get_section (symbol)->output_section;
00232 if (coff_section_data (output_bfd, osec) != NULL
00233 && coff_section_data (output_bfd, osec)->tdata != NULL)
00234 reloc_entry->sym_ptr_ptr =
00235 (asymbol **) coff_section_data (output_bfd, osec)->tdata;
00236 else
00237 {
00238 const char *sec_name;
00239 asymbol **syms, **sym_end;
00240
00241 sec_name = bfd_get_section_name (output_bfd, osec);
00242 syms = bfd_get_outsymbols (output_bfd);
00243 sym_end = syms + bfd_get_symcount (output_bfd);
00244 for (; syms < sym_end; syms++)
00245 {
00246 if (bfd_asymbol_name (*syms) != NULL
00247 && (*syms)->value == 0
00248 && strcmp ((*syms)->section->output_section->name,
00249 sec_name) == 0)
00250 break;
00251 }
00252
00253 if (syms >= sym_end)
00254 abort ();
00255
00256 reloc_entry->sym_ptr_ptr = syms;
00257
00258 if (coff_section_data (output_bfd, osec) == NULL)
00259 {
00260 bfd_size_type amt = sizeof (struct coff_section_tdata);
00261 osec->used_by_bfd = (PTR) bfd_zalloc (abfd, amt);
00262 if (osec->used_by_bfd == NULL)
00263 return bfd_reloc_overflow;
00264 }
00265 coff_section_data (output_bfd, osec)->tdata = (PTR) syms;
00266 }
00267
00268
00269
00270 return bfd_reloc_continue;
00271 }
00272
00273 static reloc_howto_type howto_rellong =
00274 HOWTO ((unsigned int) R_RELLONG, 0, 2, 32,FALSE, 0,
00275 complain_overflow_bitfield, coff_i960_relocate,"rellong", TRUE,
00276 0xffffffff, 0xffffffff, 0);
00277 static reloc_howto_type howto_iprmed =
00278 HOWTO (R_IPRMED, 0, 2, 24,TRUE,0, complain_overflow_signed,
00279 coff_i960_relocate, "iprmed ", TRUE, 0x00ffffff, 0x00ffffff, 0);
00280 static reloc_howto_type howto_optcall =
00281 HOWTO (R_OPTCALL, 0,2,24,TRUE,0, complain_overflow_signed,
00282 optcall_callback, "optcall", TRUE, 0x00ffffff, 0x00ffffff, 0);
00283
00284 static reloc_howto_type *
00285 coff_i960_reloc_type_lookup (abfd, code)
00286 bfd *abfd ATTRIBUTE_UNUSED;
00287 bfd_reloc_code_real_type code;
00288 {
00289 switch (code)
00290 {
00291 default:
00292 return 0;
00293 case BFD_RELOC_I960_CALLJ:
00294 return &howto_optcall;
00295 case BFD_RELOC_32:
00296 case BFD_RELOC_CTOR:
00297 return &howto_rellong;
00298 case BFD_RELOC_24_PCREL:
00299 return &howto_iprmed;
00300 }
00301 }
00302
00303
00304
00305 #define RTYPE2HOWTO(cache_ptr, dst) \
00306 { \
00307 reloc_howto_type *howto_ptr; \
00308 switch ((dst)->r_type) { \
00309 case 17: howto_ptr = &howto_rellong; break; \
00310 case 25: howto_ptr = &howto_iprmed; break; \
00311 case 27: howto_ptr = &howto_optcall; break; \
00312 default: howto_ptr = 0; break; \
00313 } \
00314 (cache_ptr)->howto = howto_ptr; \
00315 }
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326 static bfd_boolean
00327 coff_i960_start_final_link (abfd, info)
00328 bfd *abfd;
00329 struct bfd_link_info *info;
00330 {
00331 bfd_size_type symesz = bfd_coff_symesz (abfd);
00332 asection *o;
00333 bfd_byte *esym;
00334
00335 if (! info->relocatable)
00336 return TRUE;
00337
00338 esym = (bfd_byte *) bfd_malloc (symesz);
00339 if (esym == NULL)
00340 return FALSE;
00341
00342 if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0)
00343 return FALSE;
00344
00345 for (o = abfd->sections; o != NULL; o = o->next)
00346 {
00347 struct internal_syment isym;
00348
00349 strncpy (isym._n._n_name, o->name, SYMNMLEN);
00350 isym.n_value = 0;
00351 isym.n_scnum = o->target_index;
00352 isym.n_type = T_NULL;
00353 isym.n_sclass = C_STAT;
00354 isym.n_numaux = 0;
00355
00356 bfd_coff_swap_sym_out (abfd, (PTR) &isym, (PTR) esym);
00357
00358 if (bfd_bwrite (esym, symesz, abfd) != symesz)
00359 {
00360 free (esym);
00361 return FALSE;
00362 }
00363
00364 obj_raw_syment_count (abfd) += 1;
00365 }
00366
00367 free (esym);
00368
00369 return TRUE;
00370 }
00371
00372
00373
00374 static bfd_boolean
00375 coff_i960_relocate_section (output_bfd, info, input_bfd, input_section,
00376 contents, relocs, syms, sections)
00377 bfd *output_bfd ATTRIBUTE_UNUSED;
00378 struct bfd_link_info *info;
00379 bfd *input_bfd;
00380 asection *input_section;
00381 bfd_byte *contents;
00382 struct internal_reloc *relocs;
00383 struct internal_syment *syms;
00384 asection **sections;
00385 {
00386 struct internal_reloc *rel;
00387 struct internal_reloc *relend;
00388
00389 rel = relocs;
00390 relend = rel + input_section->reloc_count;
00391 for (; rel < relend; rel++)
00392 {
00393 long symndx;
00394 struct coff_link_hash_entry *h;
00395 struct internal_syment *sym;
00396 bfd_vma addend;
00397 bfd_vma val;
00398 reloc_howto_type *howto;
00399 bfd_reloc_status_type rstat = bfd_reloc_ok;
00400 bfd_boolean done;
00401
00402 symndx = rel->r_symndx;
00403
00404 if (symndx == -1)
00405 {
00406 h = NULL;
00407 sym = NULL;
00408 }
00409 else
00410 {
00411 h = obj_coff_sym_hashes (input_bfd)[symndx];
00412 sym = syms + symndx;
00413 }
00414
00415 if (sym != NULL && sym->n_scnum != 0)
00416 addend = - sym->n_value;
00417 else
00418 addend = 0;
00419
00420 switch (rel->r_type)
00421 {
00422 case 17: howto = &howto_rellong; break;
00423 case 25: howto = &howto_iprmed; break;
00424 case 27: howto = &howto_optcall; break;
00425 default:
00426 bfd_set_error (bfd_error_bad_value);
00427 return FALSE;
00428 }
00429
00430 val = 0;
00431
00432 if (h == NULL)
00433 {
00434 asection *sec;
00435
00436 if (symndx == -1)
00437 {
00438 sec = bfd_abs_section_ptr;
00439 val = 0;
00440 }
00441 else
00442 {
00443 sec = sections[symndx];
00444 val = (sec->output_section->vma
00445 + sec->output_offset
00446 + sym->n_value
00447 - sec->vma);
00448 }
00449 }
00450 else
00451 {
00452 if (h->root.type == bfd_link_hash_defined
00453 || h->root.type == bfd_link_hash_defweak)
00454 {
00455 asection *sec;
00456
00457 sec = h->root.u.def.section;
00458 val = (h->root.u.def.value
00459 + sec->output_section->vma
00460 + sec->output_offset);
00461 }
00462 else if (! info->relocatable)
00463 {
00464 if (! ((*info->callbacks->undefined_symbol)
00465 (info, h->root.root.string, input_bfd, input_section,
00466 rel->r_vaddr - input_section->vma, TRUE)))
00467 return FALSE;
00468 }
00469 }
00470
00471 done = FALSE;
00472
00473 if (howto->type == R_OPTCALL && ! info->relocatable && symndx != -1)
00474 {
00475 int class;
00476
00477 if (h != NULL)
00478 class = h->class;
00479 else
00480 class = sym->n_sclass;
00481
00482 switch (class)
00483 {
00484 case C_NULL:
00485
00486
00487
00488 if (! ((*info->callbacks->reloc_dangerous)
00489 (info,
00490 _("uncertain calling convention for non-COFF symbol"),
00491 input_bfd, input_section,
00492 rel->r_vaddr - input_section->vma)))
00493 return FALSE;
00494 break;
00495 case C_LEAFSTAT:
00496 case C_LEAFEXT:
00497
00498
00499 {
00500 long olf;
00501 unsigned long word;
00502
00503 if (h != NULL)
00504 {
00505 BFD_ASSERT (h->numaux == 2);
00506 olf = h->aux[1].x_bal.x_balntry;
00507 }
00508 else
00509 {
00510 bfd_byte *esyms;
00511 union internal_auxent aux;
00512
00513 BFD_ASSERT (sym->n_numaux == 2);
00514 esyms = (bfd_byte *) obj_coff_external_syms (input_bfd);
00515 esyms += (symndx + 2) * bfd_coff_symesz (input_bfd);
00516 bfd_coff_swap_aux_in (input_bfd, (PTR) esyms, sym->n_type,
00517 sym->n_sclass, 1, sym->n_numaux,
00518 (PTR) &aux);
00519 olf = aux.x_bal.x_balntry;
00520 }
00521
00522 word = bfd_get_32 (input_bfd,
00523 (contents
00524 + (rel->r_vaddr - input_section->vma)));
00525 word = ((word + olf - val) & BAL_MASK) | BAL;
00526 bfd_put_32 (input_bfd,
00527 (bfd_vma) word,
00528 contents + (rel->r_vaddr - input_section->vma));
00529 done = TRUE;
00530 }
00531 break;
00532 case C_SCALL:
00533 BFD_ASSERT (0);
00534 break;
00535 }
00536 }
00537
00538 if (! done)
00539 {
00540 if (howto->pc_relative)
00541 addend += input_section->vma;
00542 rstat = _bfd_final_link_relocate (howto, input_bfd, input_section,
00543 contents,
00544 rel->r_vaddr - input_section->vma,
00545 val, addend);
00546 }
00547
00548 switch (rstat)
00549 {
00550 default:
00551 abort ();
00552 case bfd_reloc_ok:
00553 break;
00554 case bfd_reloc_overflow:
00555 {
00556 const char *name;
00557 char buf[SYMNMLEN + 1];
00558
00559 if (symndx == -1)
00560 name = "*ABS*";
00561 else if (h != NULL)
00562 name = NULL;
00563 else
00564 {
00565 name = _bfd_coff_internal_syment_name (input_bfd, sym, buf);
00566 if (name == NULL)
00567 return FALSE;
00568 }
00569
00570 if (! ((*info->callbacks->reloc_overflow)
00571 (info, (h ? &h->root : NULL), name, howto->name,
00572 (bfd_vma) 0, input_bfd, input_section,
00573 rel->r_vaddr - input_section->vma)))
00574 return FALSE;
00575 }
00576 }
00577 }
00578
00579 return TRUE;
00580 }
00581
00582
00583
00584
00585
00586 static bfd_boolean
00587 coff_i960_adjust_symndx (obfd, info, ibfd, sec, irel, adjustedp)
00588 bfd *obfd ATTRIBUTE_UNUSED;
00589 struct bfd_link_info *info ATTRIBUTE_UNUSED;
00590 bfd *ibfd;
00591 asection *sec ATTRIBUTE_UNUSED;
00592 struct internal_reloc *irel;
00593 bfd_boolean *adjustedp;
00594 {
00595 struct coff_link_hash_entry *h;
00596
00597 *adjustedp = FALSE;
00598
00599 h = obj_coff_sym_hashes (ibfd)[irel->r_symndx];
00600 if (h == NULL
00601 || (h->root.type != bfd_link_hash_defined
00602 && h->root.type != bfd_link_hash_defweak))
00603 return TRUE;
00604
00605 irel->r_symndx = h->root.u.def.section->output_section->target_index - 1;
00606 *adjustedp = TRUE;
00607
00608 return TRUE;
00609 }
00610
00611 #define coff_bfd_is_local_label_name coff_i960_is_local_label_name
00612
00613 #define coff_start_final_link coff_i960_start_final_link
00614
00615 #define coff_relocate_section coff_i960_relocate_section
00616
00617 #define coff_adjust_symndx coff_i960_adjust_symndx
00618
00619 #define coff_bfd_reloc_type_lookup coff_i960_reloc_type_lookup
00620
00621 #include "coffcode.h"
00622
00623 extern const bfd_target icoff_big_vec;
00624
00625 CREATE_LITTLE_COFF_TARGET_VEC (icoff_little_vec, "coff-Intel-little", 0, 0, '_', & icoff_big_vec, COFF_SWAP_TABLE)
00626
00627 const bfd_target icoff_big_vec =
00628 {
00629 "coff-Intel-big",
00630 bfd_target_coff_flavour,
00631 BFD_ENDIAN_LITTLE,
00632 BFD_ENDIAN_BIG,
00633
00634 (HAS_RELOC | EXEC_P |
00635 HAS_LINENO | HAS_DEBUG |
00636 HAS_SYMS | HAS_LOCALS | WP_TEXT),
00637
00638 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC),
00639 '_',
00640 '/',
00641 15,
00642
00643 bfd_getl64, bfd_getl_signed_64, bfd_putl64,
00644 bfd_getl32, bfd_getl_signed_32, bfd_putl32,
00645 bfd_getl16, bfd_getl_signed_16, bfd_putl16,
00646 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
00647 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
00648 bfd_getb16, bfd_getb_signed_16, bfd_putb16,
00649
00650 {_bfd_dummy_target, coff_object_p,
00651 bfd_generic_archive_p, _bfd_dummy_target},
00652 {bfd_false, coff_mkobject,
00653 _bfd_generic_mkarchive, bfd_false},
00654 {bfd_false, coff_write_object_contents,
00655 _bfd_write_archive_contents, bfd_false},
00656
00657 BFD_JUMP_TABLE_GENERIC (coff),
00658 BFD_JUMP_TABLE_COPY (coff),
00659 BFD_JUMP_TABLE_CORE (_bfd_nocore),
00660 BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
00661 BFD_JUMP_TABLE_SYMBOLS (coff),
00662 BFD_JUMP_TABLE_RELOCS (coff),
00663 BFD_JUMP_TABLE_WRITE (coff),
00664 BFD_JUMP_TABLE_LINK (coff),
00665 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
00666
00667 & icoff_little_vec,
00668
00669 COFF_SWAP_TABLE
00670 };