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
00031 #include "coff/i386.h"
00032
00033 #include "coff/internal.h"
00034
00035 #ifdef COFF_WITH_PE
00036 #include "coff/pe.h"
00037 #endif
00038
00039 #ifdef COFF_GO32_EXE
00040 #include "coff/go32exe.h"
00041 #endif
00042
00043 #include "libcoff.h"
00044
00045 static bfd_reloc_status_type coff_i386_reloc
00046 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
00047 static reloc_howto_type *coff_i386_rtype_to_howto
00048 PARAMS ((bfd *, asection *, struct internal_reloc *,
00049 struct coff_link_hash_entry *, struct internal_syment *,
00050 bfd_vma *));
00051 static reloc_howto_type *coff_i386_reloc_type_lookup
00052 PARAMS ((bfd *, bfd_reloc_code_real_type));
00053
00054 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
00055
00056
00057 #define COFF_PAGE_SIZE 0x1000
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 static bfd_reloc_status_type
00069 coff_i386_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd,
00070 error_message)
00071 bfd *abfd;
00072 arelent *reloc_entry;
00073 asymbol *symbol;
00074 PTR data;
00075 asection *input_section ATTRIBUTE_UNUSED;
00076 bfd *output_bfd;
00077 char **error_message ATTRIBUTE_UNUSED;
00078 {
00079 symvalue diff;
00080
00081 #ifndef COFF_WITH_PE
00082 if (output_bfd == (bfd *) NULL)
00083 return bfd_reloc_continue;
00084 #endif
00085
00086 if (bfd_is_com_section (symbol->section))
00087 {
00088 #ifndef COFF_WITH_PE
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 diff = symbol->value + reloc_entry->addend;
00101 #else
00102
00103 diff = reloc_entry->addend;
00104 #endif
00105 }
00106 else
00107 {
00108
00109
00110
00111
00112 #ifdef COFF_WITH_PE
00113 if (output_bfd == (bfd *) NULL)
00114 {
00115 reloc_howto_type *howto = reloc_entry->howto;
00116
00117
00118
00119
00120
00121
00122
00123
00124 if (howto->pc_relative && howto->pcrel_offset)
00125 diff = -(1 << howto->size);
00126 else if (symbol->flags & BSF_WEAK)
00127 diff = reloc_entry->addend - symbol->value;
00128 else
00129 diff = -reloc_entry->addend;
00130 }
00131 else
00132 #endif
00133 diff = reloc_entry->addend;
00134 }
00135
00136 #ifdef COFF_WITH_PE
00137
00138 if (reloc_entry->howto->type == R_IMAGEBASE
00139 && output_bfd != NULL
00140 && bfd_get_flavour(output_bfd) == bfd_target_coff_flavour)
00141 diff -= pe_data (output_bfd)->pe_opthdr.ImageBase;
00142 #endif
00143
00144 #define DOIT(x) \
00145 x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask))
00146
00147 if (diff != 0)
00148 {
00149 reloc_howto_type *howto = reloc_entry->howto;
00150 unsigned char *addr = (unsigned char *) data + reloc_entry->address;
00151
00152 switch (howto->size)
00153 {
00154 case 0:
00155 {
00156 char x = bfd_get_8 (abfd, addr);
00157 DOIT (x);
00158 bfd_put_8 (abfd, x, addr);
00159 }
00160 break;
00161
00162 case 1:
00163 {
00164 short x = bfd_get_16 (abfd, addr);
00165 DOIT (x);
00166 bfd_put_16 (abfd, (bfd_vma) x, addr);
00167 }
00168 break;
00169
00170 case 2:
00171 {
00172 long x = bfd_get_32 (abfd, addr);
00173 DOIT (x);
00174 bfd_put_32 (abfd, (bfd_vma) x, addr);
00175 }
00176 break;
00177
00178 default:
00179 abort ();
00180 }
00181 }
00182
00183
00184 return bfd_reloc_continue;
00185 }
00186
00187 #ifdef COFF_WITH_PE
00188
00189
00190
00191 static bfd_boolean in_reloc_p PARAMS ((bfd *, reloc_howto_type *));
00192
00193 static bfd_boolean in_reloc_p (abfd, howto)
00194 bfd * abfd ATTRIBUTE_UNUSED;
00195 reloc_howto_type *howto;
00196 {
00197 return ! howto->pc_relative && howto->type != R_IMAGEBASE;
00198 }
00199 #endif
00200
00201 #ifndef PCRELOFFSET
00202 #define PCRELOFFSET FALSE
00203 #endif
00204
00205 static reloc_howto_type howto_table[] =
00206 {
00207 EMPTY_HOWTO (0),
00208 EMPTY_HOWTO (1),
00209 EMPTY_HOWTO (2),
00210 EMPTY_HOWTO (3),
00211 EMPTY_HOWTO (4),
00212 EMPTY_HOWTO (5),
00213 HOWTO (R_DIR32,
00214 0,
00215 2,
00216 32,
00217 FALSE,
00218 0,
00219 complain_overflow_bitfield,
00220 coff_i386_reloc,
00221 "dir32",
00222 TRUE,
00223 0xffffffff,
00224 0xffffffff,
00225 TRUE),
00226
00227 HOWTO (R_IMAGEBASE,
00228 0,
00229 2,
00230 32,
00231 FALSE,
00232 0,
00233 complain_overflow_bitfield,
00234 coff_i386_reloc,
00235 "rva32",
00236 TRUE,
00237 0xffffffff,
00238 0xffffffff,
00239 FALSE),
00240 EMPTY_HOWTO (010),
00241 EMPTY_HOWTO (011),
00242 EMPTY_HOWTO (012),
00243 #ifdef COFF_WITH_PE
00244
00245 HOWTO (R_SECREL32,
00246 0,
00247 2,
00248 32,
00249 FALSE,
00250 0,
00251 complain_overflow_bitfield,
00252 coff_i386_reloc,
00253 "secrel32",
00254 TRUE,
00255 0xffffffff,
00256 0xffffffff,
00257 TRUE),
00258 #else
00259 EMPTY_HOWTO (013),
00260 #endif
00261 EMPTY_HOWTO (014),
00262 EMPTY_HOWTO (015),
00263 EMPTY_HOWTO (016),
00264
00265 HOWTO (R_RELBYTE,
00266 0,
00267 0,
00268 8,
00269 FALSE,
00270 0,
00271 complain_overflow_bitfield,
00272 coff_i386_reloc,
00273 "8",
00274 TRUE,
00275 0x000000ff,
00276 0x000000ff,
00277 PCRELOFFSET),
00278
00279 HOWTO (R_RELWORD,
00280 0,
00281 1,
00282 16,
00283 FALSE,
00284 0,
00285 complain_overflow_bitfield,
00286 coff_i386_reloc,
00287 "16",
00288 TRUE,
00289 0x0000ffff,
00290 0x0000ffff,
00291 PCRELOFFSET),
00292
00293 HOWTO (R_RELLONG,
00294 0,
00295 2,
00296 32,
00297 FALSE,
00298 0,
00299 complain_overflow_bitfield,
00300 coff_i386_reloc,
00301 "32",
00302 TRUE,
00303 0xffffffff,
00304 0xffffffff,
00305 PCRELOFFSET),
00306
00307 HOWTO (R_PCRBYTE,
00308 0,
00309 0,
00310 8,
00311 TRUE,
00312 0,
00313 complain_overflow_signed,
00314 coff_i386_reloc,
00315 "DISP8",
00316 TRUE,
00317 0x000000ff,
00318 0x000000ff,
00319 PCRELOFFSET),
00320
00321 HOWTO (R_PCRWORD,
00322 0,
00323 1,
00324 16,
00325 TRUE,
00326 0,
00327 complain_overflow_signed,
00328 coff_i386_reloc,
00329 "DISP16",
00330 TRUE,
00331 0x0000ffff,
00332 0x0000ffff,
00333 PCRELOFFSET),
00334
00335 HOWTO (R_PCRLONG,
00336 0,
00337 2,
00338 32,
00339 TRUE,
00340 0,
00341 complain_overflow_signed,
00342 coff_i386_reloc,
00343 "DISP32",
00344 TRUE,
00345 0xffffffff,
00346 0xffffffff,
00347 PCRELOFFSET)
00348 };
00349
00350
00351
00352 #define SELECT_RELOC(x,howto) { x.r_type = howto->type; }
00353 #define BADMAG(x) I386BADMAG(x)
00354 #define I386 1
00355
00356 #define RTYPE2HOWTO(cache_ptr, dst) \
00357 ((cache_ptr)->howto = \
00358 ((dst)->r_type < sizeof (howto_table) / sizeof (howto_table[0]) \
00359 ? howto_table + (dst)->r_type \
00360 : NULL))
00361
00362
00363
00364
00365 #define BSS_NOLOAD_IS_SHARED_LIBRARY
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380 #define CALC_ADDEND(abfd, ptr, reloc, cache_ptr) \
00381 { \
00382 coff_symbol_type *coffsym = (coff_symbol_type *) NULL; \
00383 if (ptr && bfd_asymbol_bfd (ptr) != abfd) \
00384 coffsym = (obj_symbols (abfd) \
00385 + (cache_ptr->sym_ptr_ptr - symbols)); \
00386 else if (ptr) \
00387 coffsym = coff_symbol_from (abfd, ptr); \
00388 if (coffsym != (coff_symbol_type *) NULL \
00389 && coffsym->native->u.syment.n_scnum == 0) \
00390 cache_ptr->addend = - coffsym->native->u.syment.n_value; \
00391 else if (ptr && bfd_asymbol_bfd (ptr) == abfd \
00392 && ptr->section != (asection *) NULL) \
00393 cache_ptr->addend = - (ptr->section->vma + ptr->value); \
00394 else \
00395 cache_ptr->addend = 0; \
00396 if (ptr && howto_table[reloc.r_type].pc_relative) \
00397 cache_ptr->addend += asect->vma; \
00398 }
00399
00400
00401
00402
00403
00404 #ifndef COFF_WITH_PE
00405
00406 #define coff_relocate_section _bfd_coff_generic_relocate_section
00407
00408 #else
00409
00410
00411
00412
00413
00414 static bfd_boolean coff_pe_i386_relocate_section
00415 PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
00416 struct internal_reloc *, struct internal_syment *, asection **));
00417
00418 static bfd_boolean
00419 coff_pe_i386_relocate_section (output_bfd, info, input_bfd,
00420 input_section, contents, relocs, syms,
00421 sections)
00422 bfd *output_bfd;
00423 struct bfd_link_info *info;
00424 bfd *input_bfd;
00425 asection *input_section;
00426 bfd_byte *contents;
00427 struct internal_reloc *relocs;
00428 struct internal_syment *syms;
00429 asection **sections;
00430 {
00431 if (info->relocatable)
00432 return TRUE;
00433
00434 return _bfd_coff_generic_relocate_section (output_bfd, info, input_bfd,
00435 input_section, contents,
00436 relocs, syms, sections);
00437 }
00438
00439 #define coff_relocate_section coff_pe_i386_relocate_section
00440
00441 #endif
00442
00443
00444
00445 static reloc_howto_type *
00446 coff_i386_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
00447 bfd *abfd ATTRIBUTE_UNUSED;
00448 asection *sec;
00449 struct internal_reloc *rel;
00450 struct coff_link_hash_entry *h;
00451 struct internal_syment *sym;
00452 bfd_vma *addendp;
00453 {
00454 reloc_howto_type *howto;
00455
00456 if (rel->r_type > sizeof (howto_table) / sizeof (howto_table[0]))
00457 {
00458 bfd_set_error (bfd_error_bad_value);
00459 return NULL;
00460 }
00461
00462 howto = howto_table + rel->r_type;
00463
00464 #ifdef COFF_WITH_PE
00465
00466 *addendp = 0;
00467 #endif
00468
00469 if (howto->pc_relative)
00470 *addendp += sec->vma;
00471
00472 if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
00473 {
00474
00475
00476
00477
00478
00479
00480 BFD_ASSERT (h != NULL);
00481
00482 #ifndef COFF_WITH_PE
00483
00484
00485
00486
00487
00488
00489
00490 *addendp -= sym->n_value;
00491 #endif
00492 }
00493
00494 #ifndef COFF_WITH_PE
00495
00496
00497
00498 if (h != NULL && h->root.type == bfd_link_hash_common)
00499 *addendp += h->root.u.c.size;
00500 #endif
00501
00502 #ifdef COFF_WITH_PE
00503 if (howto->pc_relative)
00504 {
00505 *addendp -= 4;
00506
00507
00508
00509
00510
00511
00512
00513 if (sym != NULL && sym->n_scnum != 0)
00514 *addendp -= sym->n_value;
00515 }
00516
00517 if (rel->r_type == R_IMAGEBASE
00518 && (bfd_get_flavour(sec->output_section->owner)
00519 == bfd_target_coff_flavour))
00520 {
00521 *addendp -= pe_data(sec->output_section->owner)->pe_opthdr.ImageBase;
00522 }
00523
00524 if (rel->r_type == R_SECREL32)
00525 {
00526 bfd_vma osect_vma;
00527
00528 if (h && (h->type == bfd_link_hash_defined
00529 || h->type == bfd_link_hash_defweak))
00530 osect_vma = h->root.u.def.section->output_section->vma;
00531 else
00532 {
00533 asection *sec;
00534 int i;
00535
00536
00537
00538
00539 for (sec = abfd->sections, i = 1; i < sym->n_scnum; i++)
00540 sec = sec->next;
00541
00542 osect_vma = sec->output_section->vma;
00543 }
00544
00545 *addendp -= osect_vma;
00546 }
00547 #endif
00548
00549 return howto;
00550 }
00551
00552 #define coff_bfd_reloc_type_lookup coff_i386_reloc_type_lookup
00553
00554 static reloc_howto_type *
00555 coff_i386_reloc_type_lookup (abfd, code)
00556 bfd *abfd ATTRIBUTE_UNUSED;
00557 bfd_reloc_code_real_type code;
00558 {
00559 switch (code)
00560 {
00561 case BFD_RELOC_RVA:
00562 return howto_table + R_IMAGEBASE;
00563 case BFD_RELOC_32:
00564 return howto_table + R_DIR32;
00565 case BFD_RELOC_32_PCREL:
00566 return howto_table + R_PCRLONG;
00567 case BFD_RELOC_16:
00568 return howto_table + R_RELWORD;
00569 case BFD_RELOC_16_PCREL:
00570 return howto_table + R_PCRWORD;
00571 case BFD_RELOC_8:
00572 return howto_table + R_RELBYTE;
00573 case BFD_RELOC_8_PCREL:
00574 return howto_table + R_PCRBYTE;
00575 #ifdef COFF_WITH_PE
00576 case BFD_RELOC_32_SECREL:
00577 return howto_table + R_SECREL32;
00578 #endif
00579 default:
00580 BFD_FAIL ();
00581 return 0;
00582 }
00583 }
00584
00585 #define coff_rtype_to_howto coff_i386_rtype_to_howto
00586
00587 #ifdef TARGET_UNDERSCORE
00588
00589
00590
00591
00592
00593 static bfd_boolean coff_i386_is_local_label_name
00594 PARAMS ((bfd *, const char *));
00595
00596 static bfd_boolean
00597 coff_i386_is_local_label_name (abfd, name)
00598 bfd *abfd;
00599 const char *name;
00600 {
00601 if (name[0] == 'L')
00602 return TRUE;
00603
00604 return _bfd_coff_is_local_label_name (abfd, name);
00605 }
00606
00607 #define coff_bfd_is_local_label_name coff_i386_is_local_label_name
00608
00609 #endif
00610
00611 #include "coffcode.h"
00612
00613 const bfd_target
00614 #ifdef TARGET_SYM
00615 TARGET_SYM =
00616 #else
00617 i386coff_vec =
00618 #endif
00619 {
00620 #ifdef TARGET_NAME
00621 TARGET_NAME,
00622 #else
00623 "coff-i386",
00624 #endif
00625 bfd_target_coff_flavour,
00626 BFD_ENDIAN_LITTLE,
00627 BFD_ENDIAN_LITTLE,
00628
00629 (HAS_RELOC | EXEC_P |
00630 HAS_LINENO | HAS_DEBUG |
00631 HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
00632
00633 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC
00634 #ifdef COFF_WITH_PE
00635 | SEC_LINK_ONCE | SEC_LINK_DUPLICATES | SEC_READONLY
00636 #endif
00637 | SEC_CODE | SEC_DATA),
00638
00639 #ifdef TARGET_UNDERSCORE
00640 TARGET_UNDERSCORE,
00641 #else
00642 0,
00643 #endif
00644 '/',
00645 15,
00646
00647 bfd_getl64, bfd_getl_signed_64, bfd_putl64,
00648 bfd_getl32, bfd_getl_signed_32, bfd_putl32,
00649 bfd_getl16, bfd_getl_signed_16, bfd_putl16,
00650 bfd_getl64, bfd_getl_signed_64, bfd_putl64,
00651 bfd_getl32, bfd_getl_signed_32, bfd_putl32,
00652 bfd_getl16, bfd_getl_signed_16, bfd_putl16,
00653
00654
00655 {_bfd_dummy_target, coff_object_p,
00656 bfd_generic_archive_p, coff_object_p},
00657 {bfd_false, coff_mkobject, _bfd_generic_mkarchive,
00658 bfd_false},
00659 {bfd_false, coff_write_object_contents,
00660 _bfd_write_archive_contents, bfd_false},
00661
00662 BFD_JUMP_TABLE_GENERIC (coff),
00663 BFD_JUMP_TABLE_COPY (coff),
00664 BFD_JUMP_TABLE_CORE (_bfd_nocore),
00665 BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
00666 BFD_JUMP_TABLE_SYMBOLS (coff),
00667 BFD_JUMP_TABLE_RELOCS (coff),
00668 BFD_JUMP_TABLE_WRITE (coff),
00669 BFD_JUMP_TABLE_LINK (coff),
00670 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
00671
00672 NULL,
00673
00674 COFF_SWAP_TABLE
00675 };