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
00032
00033
00034
00035
00036
00037
00038
00039
00040 #include "bfd.h"
00041 #include "sysdep.h"
00042
00043 #include "libbfd.h"
00044
00045 #include "coff/powerpc.h"
00046 #include "coff/internal.h"
00047
00048 #include "coff/pe.h"
00049
00050 #ifdef BADMAG
00051 #undef BADMAG
00052 #endif
00053
00054 #define BADMAG(x) PPCBADMAG(x)
00055
00056 #include "libcoff.h"
00057
00058
00059
00060 extern bfd_boolean ppc_bfd_coff_final_link
00061 PARAMS ((bfd *, struct bfd_link_info *));
00062 extern void dump_toc PARAMS ((PTR));
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074 #define SET_UNALLOCATED(x) ((x) = 1)
00075 #define IS_UNALLOCATED(x) ((x) == 1)
00076
00077 #define IS_WRITTEN(x) ((x) & 1)
00078 #define MARK_AS_WRITTEN(x) ((x) |= 1)
00079 #define MAKE_ADDR_AGAIN(x) ((x) &= ~1)
00080
00081
00082 #ifdef DEBUG_HASH
00083
00084
00085 #define EYE "krkjunk"
00086
00087 #define HASH_CHECK_DCL char eye_catcher[8];
00088 #define HASH_CHECK_INIT(ret) strcpy(ret->eye_catcher, EYE)
00089 #define HASH_CHECK(addr) \
00090 if (strcmp(addr->eye_catcher, EYE) != 0) \
00091 { \
00092 fprintf (stderr,\
00093 _("File %s, line %d, Hash check failure, bad eye %8s\n"), \
00094 __FILE__, __LINE__, addr->eye_catcher); \
00095 abort (); \
00096 }
00097
00098 #else
00099
00100 #define HASH_CHECK_DCL
00101 #define HASH_CHECK_INIT(ret)
00102 #define HASH_CHECK(addr)
00103
00104 #endif
00105
00106
00107
00108
00109
00110
00111 struct ppc_coff_link_hash_entry
00112 {
00113 struct coff_link_hash_entry root;
00114
00115
00116
00117 bfd_vma toc_offset;
00118 int symbol_is_glue;
00119 unsigned long int glue_insn;
00120
00121 HASH_CHECK_DCL
00122 };
00123
00124
00125
00126 struct ppc_coff_link_hash_table
00127 {
00128 struct coff_link_hash_table root;
00129 };
00130
00131 static struct bfd_hash_entry *ppc_coff_link_hash_newfunc
00132 PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *,
00133 const char *));
00134 static bfd_boolean ppc_coff_link_hash_table_init
00135 PARAMS ((struct ppc_coff_link_hash_table *, bfd *,
00136 struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
00137 struct bfd_hash_table *,
00138 const char *)));
00139 static struct bfd_link_hash_table *ppc_coff_link_hash_table_create
00140 PARAMS ((bfd *));
00141 static bfd_boolean coff_ppc_relocate_section
00142 PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
00143 struct internal_reloc *, struct internal_syment *, asection **));
00144 static reloc_howto_type *coff_ppc_rtype_to_howto
00145 PARAMS ((bfd *, asection *, struct internal_reloc *,
00146 struct coff_link_hash_entry *, struct internal_syment *,
00147 bfd_vma *));
00148
00149
00150
00151 static struct bfd_hash_entry *
00152 ppc_coff_link_hash_newfunc (entry, table, string)
00153 struct bfd_hash_entry *entry;
00154 struct bfd_hash_table *table;
00155 const char *string;
00156 {
00157 struct ppc_coff_link_hash_entry *ret =
00158 (struct ppc_coff_link_hash_entry *) entry;
00159
00160
00161
00162 if (ret == (struct ppc_coff_link_hash_entry *) NULL)
00163 ret = (struct ppc_coff_link_hash_entry *)
00164 bfd_hash_allocate (table,
00165 sizeof (struct ppc_coff_link_hash_entry));
00166
00167 if (ret == (struct ppc_coff_link_hash_entry *) NULL)
00168 return NULL;
00169
00170
00171 ret = ((struct ppc_coff_link_hash_entry *)
00172 _bfd_coff_link_hash_newfunc ((struct bfd_hash_entry *) ret,
00173 table, string));
00174
00175 if (ret)
00176 {
00177
00178 SET_UNALLOCATED (ret->toc_offset);
00179 ret->symbol_is_glue = 0;
00180 ret->glue_insn = 0;
00181
00182 HASH_CHECK_INIT (ret);
00183 }
00184
00185 return (struct bfd_hash_entry *) ret;
00186 }
00187
00188
00189
00190 static bfd_boolean
00191 ppc_coff_link_hash_table_init (table, abfd, newfunc)
00192 struct ppc_coff_link_hash_table *table;
00193 bfd *abfd;
00194 struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *,
00195 struct bfd_hash_table *,
00196 const char *));
00197 {
00198 return _bfd_coff_link_hash_table_init (&table->root, abfd, newfunc);
00199 }
00200
00201
00202
00203 static struct bfd_link_hash_table *
00204 ppc_coff_link_hash_table_create (abfd)
00205 bfd *abfd;
00206 {
00207 struct ppc_coff_link_hash_table *ret;
00208 bfd_size_type amt = sizeof (struct ppc_coff_link_hash_table);
00209
00210 ret = (struct ppc_coff_link_hash_table *) bfd_malloc (amt);
00211 if (ret == NULL)
00212 return NULL;
00213 if (! ppc_coff_link_hash_table_init (ret, abfd,
00214 ppc_coff_link_hash_newfunc))
00215 {
00216 free (ret);
00217 return (struct bfd_link_hash_table *) NULL;
00218 }
00219 return &ret->root.root;
00220 }
00221
00222
00223
00224 #define coff_bfd_link_hash_table_create ppc_coff_link_hash_table_create
00225
00226
00227
00228
00229 #define TOC_LOAD_ADJUSTMENT (-32768)
00230 #define TOC_SECTION_NAME ".private.toc"
00231
00232
00233
00234 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (3)
00235
00236
00237
00238 #define MINUS_ONE (((bfd_vma)0) - 1)
00239
00240
00241
00242
00243 #define IMAGE_REL_PPC_ABSOLUTE 0x0000
00244
00245
00246 #define IMAGE_REL_PPC_ADDR64 0x0001
00247
00248
00249 #define IMAGE_REL_PPC_ADDR32 0x0002
00250
00251
00252 #define IMAGE_REL_PPC_ADDR24 0x0003
00253
00254
00255 #define IMAGE_REL_PPC_ADDR16 0x0004
00256
00257
00258 #define IMAGE_REL_PPC_ADDR14 0x0005
00259
00260
00261 #define IMAGE_REL_PPC_REL24 0x0006
00262
00263
00264 #define IMAGE_REL_PPC_REL14 0x0007
00265
00266
00267 #define IMAGE_REL_PPC_TOCREL16 0x0008
00268
00269
00270 #define IMAGE_REL_PPC_TOCREL14 0x0009
00271
00272
00273 #define IMAGE_REL_PPC_ADDR32NB 0x000A
00274
00275
00276 #define IMAGE_REL_PPC_SECREL 0x000B
00277
00278
00279 #define IMAGE_REL_PPC_SECTION 0x000C
00280
00281
00282 #define IMAGE_REL_PPC_IFGLUE 0x000D
00283
00284
00285 #define IMAGE_REL_PPC_IMGLUE 0x000E
00286
00287
00288 #define IMAGE_REL_PPC_SECREL16 0x000F
00289
00290
00291
00292
00293 #define IMAGE_REL_PPC_REFHI 0x0010
00294 #define IMAGE_REL_PPC_REFLO 0x0011
00295 #define IMAGE_REL_PPC_PAIR 0x0012
00296
00297
00298 #define IMAGE_REL_PPC_TOCREL16_DEFN 0x0013
00299
00300
00301
00302
00303 #define IMAGE_REL_PPC_NEG 0x0100
00304
00305
00306 #define IMAGE_REL_PPC_BRTAKEN 0x0200
00307
00308
00309 #define IMAGE_REL_PPC_BRNTAKEN 0x0400
00310
00311
00312 #define IMAGE_REL_PPC_TOCDEFN 0x0800
00313
00314
00315 #define IMAGE_REL_PPC_TYPEMASK 0x00FF
00316 #define IMAGE_REL_PPC_FLAGMASK 0x0F00
00317
00318 #define EXTRACT_TYPE(x) ((x) & IMAGE_REL_PPC_TYPEMASK)
00319 #define EXTRACT_FLAGS(x) ((x) & IMAGE_REL_PPC_FLAGMASK)
00320 #define EXTRACT_JUNK(x) \
00321 ((x) & ~(IMAGE_REL_PPC_TYPEMASK | IMAGE_REL_PPC_FLAGMASK))
00322
00323
00324
00325
00326 static bfd_reloc_status_type ppc_refhi_reloc PARAMS ((bfd *abfd,
00327 arelent *reloc,
00328 asymbol *symbol,
00329 PTR data,
00330 asection *section,
00331 bfd *output_bfd,
00332 char **error));
00333 static bfd_reloc_status_type ppc_pair_reloc PARAMS ((bfd *abfd,
00334 arelent *reloc,
00335 asymbol *symbol,
00336 PTR data,
00337 asection *section,
00338 bfd *output_bfd,
00339 char **error));
00340
00341 static bfd_reloc_status_type ppc_toc16_reloc PARAMS ((bfd *abfd,
00342 arelent *reloc,
00343 asymbol *symbol,
00344 PTR data,
00345 asection *section,
00346 bfd *output_bfd,
00347 char **error));
00348
00349 static bfd_reloc_status_type ppc_section_reloc PARAMS ((bfd *abfd,
00350 arelent *reloc,
00351 asymbol *symbol,
00352 PTR data,
00353 asection *section,
00354 bfd *output_bfd,
00355 char **error));
00356
00357 static bfd_reloc_status_type ppc_secrel_reloc PARAMS ((bfd *abfd,
00358 arelent *reloc,
00359 asymbol *symbol,
00360 PTR data,
00361 asection *section,
00362 bfd *output_bfd,
00363 char **error));
00364
00365 static bfd_reloc_status_type ppc_imglue_reloc PARAMS ((bfd *abfd,
00366 arelent *reloc,
00367 asymbol *symbol,
00368 PTR data,
00369 asection *section,
00370 bfd *output_bfd,
00371 char **error));
00372
00373 static bfd_boolean in_reloc_p PARAMS((bfd *abfd, reloc_howto_type *howto));
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408 static reloc_howto_type ppc_coff_howto_table[] =
00409 {
00410
00411
00412 HOWTO (IMAGE_REL_PPC_ABSOLUTE,
00413 0,
00414 0,
00415 0,
00416 FALSE,
00417 0,
00418 complain_overflow_dont,
00419 0,
00420 "ABSOLUTE",
00421 FALSE,
00422 0x00,
00423 0x00,
00424 FALSE),
00425
00426
00427
00428 HOWTO(IMAGE_REL_PPC_ADDR64,
00429 0,
00430 3,
00431 64,
00432 FALSE,
00433 0,
00434 complain_overflow_bitfield,
00435 0,
00436 "ADDR64",
00437 TRUE,
00438 MINUS_ONE,
00439 MINUS_ONE,
00440 FALSE),
00441
00442
00443
00444 HOWTO (IMAGE_REL_PPC_ADDR32,
00445 0,
00446 2,
00447 32,
00448 FALSE,
00449 0,
00450 complain_overflow_bitfield,
00451 0,
00452 "ADDR32",
00453 TRUE,
00454 0xffffffff,
00455 0xffffffff,
00456 FALSE),
00457
00458
00459
00460
00461
00462
00463 HOWTO (IMAGE_REL_PPC_ADDR24,
00464 0,
00465 2,
00466 26,
00467 FALSE,
00468 0,
00469 complain_overflow_bitfield,
00470 0,
00471 "ADDR24",
00472 TRUE,
00473 0x07fffffc,
00474 0x07fffffc,
00475 FALSE),
00476
00477
00478
00479 HOWTO (IMAGE_REL_PPC_ADDR16,
00480 0,
00481 1,
00482 16,
00483 FALSE,
00484 0,
00485 complain_overflow_signed,
00486 0,
00487 "ADDR16",
00488 TRUE,
00489 0xffff,
00490 0xffff,
00491 FALSE),
00492
00493
00494
00495
00496
00497 HOWTO (IMAGE_REL_PPC_ADDR14,
00498 1,
00499 1,
00500 16,
00501 FALSE,
00502 0,
00503 complain_overflow_signed,
00504 0,
00505 "ADDR16",
00506 TRUE,
00507 0xffff,
00508 0xffff,
00509 FALSE),
00510
00511
00512
00513
00514 HOWTO (IMAGE_REL_PPC_REL24,
00515 0,
00516 2,
00517 26,
00518 TRUE,
00519 0,
00520 complain_overflow_signed,
00521 0,
00522 "REL24",
00523 TRUE,
00524 0x3fffffc,
00525 0x3fffffc,
00526 FALSE),
00527
00528
00529
00530
00531
00532
00533 HOWTO (IMAGE_REL_PPC_ADDR14,
00534 1,
00535 1,
00536 16,
00537 FALSE,
00538 0,
00539 complain_overflow_signed,
00540 0,
00541 "ADDR16",
00542 TRUE,
00543 0xffff,
00544 0xffff,
00545 TRUE),
00546
00547
00548
00549
00550 HOWTO (IMAGE_REL_PPC_TOCREL16,
00551 0,
00552 1,
00553 16,
00554 FALSE,
00555 0,
00556 complain_overflow_dont,
00557 ppc_toc16_reloc,
00558 "TOCREL16",
00559 FALSE,
00560 0xffff,
00561 0xffff,
00562 FALSE),
00563
00564
00565
00566
00567 HOWTO (IMAGE_REL_PPC_TOCREL14,
00568 1,
00569 1,
00570 16,
00571 FALSE,
00572 0,
00573 complain_overflow_signed,
00574 0,
00575 "TOCREL14",
00576 FALSE,
00577 0xffff,
00578 0xffff,
00579 FALSE),
00580
00581
00582
00583
00584 HOWTO (IMAGE_REL_PPC_ADDR32NB,
00585 0,
00586 2,
00587 32,
00588 FALSE,
00589 0,
00590 complain_overflow_signed,
00591 0,
00592 "ADDR32NB",
00593 TRUE,
00594 0xffffffff,
00595 0xffffffff,
00596 FALSE),
00597
00598
00599
00600
00601 HOWTO (IMAGE_REL_PPC_SECREL,
00602 0,
00603 2,
00604 32,
00605 FALSE,
00606 0,
00607 complain_overflow_signed,
00608 ppc_secrel_reloc,
00609 "SECREL",
00610 TRUE,
00611 0xffffffff,
00612 0xffffffff,
00613 TRUE),
00614
00615
00616
00617
00618 HOWTO (IMAGE_REL_PPC_SECTION,
00619 0,
00620 2,
00621 32,
00622 FALSE,
00623 0,
00624 complain_overflow_signed,
00625 ppc_section_reloc,
00626 "SECTION",
00627 TRUE,
00628 0xffffffff,
00629 0xffffffff,
00630 TRUE),
00631
00632
00633
00634
00635 HOWTO (IMAGE_REL_PPC_IFGLUE,
00636 0,
00637 2,
00638 32,
00639 FALSE,
00640 0,
00641 complain_overflow_signed,
00642 0,
00643 "IFGLUE",
00644 TRUE,
00645 0xffffffff,
00646 0xffffffff,
00647 FALSE),
00648
00649
00650
00651
00652 HOWTO (IMAGE_REL_PPC_IMGLUE,
00653 0,
00654 2,
00655 32,
00656 FALSE,
00657 0,
00658 complain_overflow_dont,
00659 ppc_imglue_reloc,
00660 "IMGLUE",
00661 FALSE,
00662 0xffffffff,
00663 0xffffffff,
00664 FALSE),
00665
00666
00667
00668
00669 HOWTO (IMAGE_REL_PPC_SECREL16,
00670 0,
00671 1,
00672 16,
00673 FALSE,
00674 0,
00675 complain_overflow_signed,
00676 0,
00677 "SECREL16",
00678 TRUE,
00679 0xffff,
00680 0xffff,
00681 TRUE),
00682
00683
00684
00685 HOWTO (IMAGE_REL_PPC_REFHI,
00686 0,
00687 1,
00688 16,
00689 FALSE,
00690 0,
00691 complain_overflow_signed,
00692 ppc_refhi_reloc,
00693 "REFHI",
00694 TRUE,
00695 0xffffffff,
00696 0xffffffff,
00697 FALSE),
00698
00699
00700
00701 HOWTO (IMAGE_REL_PPC_REFLO,
00702 0,
00703 1,
00704 16,
00705 FALSE,
00706 0,
00707 complain_overflow_signed,
00708 ppc_refhi_reloc,
00709 "REFLO",
00710 TRUE,
00711 0xffffffff,
00712 0xffffffff,
00713 FALSE),
00714
00715
00716
00717 HOWTO (IMAGE_REL_PPC_PAIR,
00718 0,
00719 1,
00720 16,
00721 FALSE,
00722 0,
00723 complain_overflow_signed,
00724 ppc_pair_reloc,
00725 "PAIR",
00726 TRUE,
00727 0xffffffff,
00728 0xffffffff,
00729 FALSE),
00730
00731
00732
00733
00734 HOWTO ( (IMAGE_REL_PPC_TOCREL16 | IMAGE_REL_PPC_TOCDEFN),
00735 0,
00736 1,
00737 16,
00738 FALSE,
00739 0,
00740 complain_overflow_dont,
00741 0,
00742 "TOCREL16, TOCDEFN",
00743 FALSE,
00744 0xffff,
00745 0xffff,
00746 FALSE),
00747
00748 };
00749
00750
00751
00752 #ifdef DEBUG_RELOC
00753 #define UN_IMPL(x) \
00754 { \
00755 static int i; \
00756 if (i == 0) \
00757 { \
00758 i = 1; \
00759 fprintf (stderr,_("Unimplemented Relocation -- %s\n"),x); \
00760 } \
00761 }
00762
00763 #define DUMP_RELOC(n,r) \
00764 { \
00765 fprintf (stderr,"%s sym %d, addr %d, addend %d\n", \
00766 n, (*(r->sym_ptr_ptr))->name, \
00767 r->address, r->addend); \
00768 }
00769
00770
00771
00772
00773
00774
00775
00776
00777 #define DUMP_RELOC2(n,r) \
00778 { \
00779 fprintf (stderr,"%s sym %d, r_vaddr %d %s\n", \
00780 n, r->r_symndx, r->r_vaddr, \
00781 (((r->r_type) & IMAGE_REL_PPC_TOCDEFN) == 0) \
00782 ?" ":" TOCDEFN" ); \
00783 }
00784
00785 #else
00786 #define UN_IMPL(x)
00787 #define DUMP_RELOC(n,r)
00788 #define DUMP_RELOC2(n,r)
00789 #endif
00790
00791
00792
00793
00794
00795
00796 extern bfd * bfd_of_toc_owner;
00797 extern long int global_toc_size;
00798 extern long int import_table_size;
00799 extern long int first_thunk_address;
00800 extern long int thunk_size;
00801
00802 enum toc_type
00803 {
00804 default_toc,
00805 toc_32,
00806 toc_64
00807 };
00808
00809 enum ref_category
00810 {
00811 priv,
00812 pub,
00813 tocdata
00814 };
00815
00816 struct list_ele
00817 {
00818 struct list_ele *next;
00819 bfd_vma addr;
00820 enum ref_category cat;
00821 int offset;
00822 const char *name;
00823 };
00824
00825 extern struct list_ele *head;
00826 extern struct list_ele *tail;
00827
00828 static void record_toc
00829 PARAMS ((asection *, bfd_signed_vma, enum ref_category, const char *));
00830
00831 static void
00832 record_toc (toc_section, our_toc_offset, cat, name)
00833 asection *toc_section;
00834 bfd_signed_vma our_toc_offset;
00835 enum ref_category cat;
00836 const char *name;
00837 {
00838
00839 bfd_size_type amt = sizeof (struct list_ele);
00840 struct list_ele *t = (struct list_ele *) bfd_malloc (amt);
00841
00842 if (t == NULL)
00843 abort ();
00844 t->next = 0;
00845 t->offset = our_toc_offset;
00846 t->name = name;
00847 t->cat = cat;
00848 t->addr = toc_section->output_offset + our_toc_offset;
00849
00850 if (head == 0)
00851 {
00852 head = t;
00853 tail = t;
00854 }
00855 else
00856 {
00857 tail->next = t;
00858 tail = t;
00859 }
00860 }
00861
00862 #ifdef COFF_IMAGE_WITH_PE
00863
00864 static bfd_boolean ppc_record_toc_entry
00865 PARAMS ((bfd *, struct bfd_link_info *, asection *, int, enum toc_type));
00866 static void ppc_mark_symbol_as_glue
00867 PARAMS ((bfd *, int, struct internal_reloc *));
00868
00869
00870 static bfd_boolean
00871 ppc_record_toc_entry(abfd, info, sec, sym, toc_kind)
00872 bfd *abfd;
00873 struct bfd_link_info *info ATTRIBUTE_UNUSED;
00874 asection *sec ATTRIBUTE_UNUSED;
00875 int sym;
00876 enum toc_type toc_kind ATTRIBUTE_UNUSED;
00877 {
00878 struct ppc_coff_link_hash_entry *h;
00879 const char *name;
00880
00881 int *local_syms;
00882
00883 h = 0;
00884
00885 h = (struct ppc_coff_link_hash_entry *) (obj_coff_sym_hashes (abfd)[sym]);
00886 if (h != 0)
00887 {
00888 HASH_CHECK(h);
00889 }
00890
00891 if (h == 0)
00892 {
00893 local_syms = obj_coff_local_toc_table(abfd);
00894
00895 if (local_syms == 0)
00896 {
00897 unsigned int i;
00898 bfd_size_type amt;
00899
00900
00901 amt = (bfd_size_type) obj_raw_syment_count (abfd) * sizeof (int);
00902 local_syms = (int *) bfd_zalloc (abfd, amt);
00903 if (local_syms == 0)
00904 return FALSE;
00905 obj_coff_local_toc_table (abfd) = local_syms;
00906
00907 for (i = 0; i < obj_raw_syment_count (abfd); ++i)
00908 {
00909 SET_UNALLOCATED (local_syms[i]);
00910 }
00911 }
00912
00913 if (IS_UNALLOCATED(local_syms[sym]))
00914 {
00915 local_syms[sym] = global_toc_size;
00916 global_toc_size += 4;
00917
00918
00919 if (global_toc_size > 65535)
00920 {
00921 (*_bfd_error_handler) (_("TOC overflow"));
00922 bfd_set_error (bfd_error_file_too_big);
00923 return FALSE;
00924 }
00925 }
00926 }
00927 else
00928 {
00929 name = h->root.root.root.string;
00930
00931
00932
00933 if (IS_UNALLOCATED(h->toc_offset))
00934 {
00935 h->toc_offset = global_toc_size;
00936 global_toc_size += 4;
00937
00938
00939 if (global_toc_size >= 65535)
00940 {
00941 (*_bfd_error_handler) (_("TOC overflow"));
00942 bfd_set_error (bfd_error_file_too_big);
00943 return FALSE;
00944 }
00945 }
00946 }
00947
00948 return TRUE;
00949 }
00950
00951
00952 static void
00953 ppc_mark_symbol_as_glue(abfd, sym, rel)
00954 bfd *abfd;
00955 int sym;
00956 struct internal_reloc *rel;
00957 {
00958 struct ppc_coff_link_hash_entry *h;
00959
00960 h = (struct ppc_coff_link_hash_entry *) (obj_coff_sym_hashes (abfd)[sym]);
00961
00962 HASH_CHECK(h);
00963
00964 h->symbol_is_glue = 1;
00965 h->glue_insn = bfd_get_32 (abfd, (bfd_byte *) &rel->r_vaddr);
00966
00967 return;
00968 }
00969
00970 #endif
00971
00972
00973
00974
00975 static bfd_boolean in_reloc_p(abfd, howto)
00976 bfd * abfd ATTRIBUTE_UNUSED;
00977 reloc_howto_type *howto;
00978 {
00979 return
00980 (! howto->pc_relative)
00981 && (howto->type != IMAGE_REL_PPC_ADDR32NB)
00982 && (howto->type != IMAGE_REL_PPC_TOCREL16)
00983 && (howto->type != IMAGE_REL_PPC_IMGLUE)
00984 && (howto->type != IMAGE_REL_PPC_IFGLUE)
00985 && (howto->type != IMAGE_REL_PPC_SECREL)
00986 && (howto->type != IMAGE_REL_PPC_SECTION)
00987 && (howto->type != IMAGE_REL_PPC_SECREL16)
00988 && (howto->type != IMAGE_REL_PPC_REFHI)
00989 && (howto->type != IMAGE_REL_PPC_REFLO)
00990 && (howto->type != IMAGE_REL_PPC_PAIR)
00991 && (howto->type != IMAGE_REL_PPC_TOCREL16_DEFN) ;
00992 }
00993
00994
00995
00996 static bfd_boolean
00997 coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
00998 contents, relocs, syms, sections)
00999 bfd *output_bfd;
01000 struct bfd_link_info *info;
01001 bfd *input_bfd;
01002 asection *input_section;
01003 bfd_byte *contents;
01004 struct internal_reloc *relocs;
01005 struct internal_syment *syms;
01006 asection **sections;
01007 {
01008 struct internal_reloc *rel;
01009 struct internal_reloc *relend;
01010 bfd_boolean hihalf;
01011 bfd_vma hihalf_val;
01012 asection *toc_section = 0;
01013 bfd_vma relocation;
01014 reloc_howto_type *howto = 0;
01015
01016
01017
01018
01019 if (info->relocatable)
01020 return TRUE;
01021
01022 hihalf = FALSE;
01023 hihalf_val = 0;
01024
01025 rel = relocs;
01026 relend = rel + input_section->reloc_count;
01027 for (; rel < relend; rel++)
01028 {
01029 long symndx;
01030 struct ppc_coff_link_hash_entry *h;
01031 struct internal_syment *sym;
01032 bfd_vma val;
01033
01034 asection *sec;
01035 bfd_reloc_status_type rstat;
01036 bfd_byte *loc;
01037
01038 unsigned short r_type = EXTRACT_TYPE (rel->r_type);
01039 unsigned short r_flags = EXTRACT_FLAGS(rel->r_type);
01040
01041 symndx = rel->r_symndx;
01042 loc = contents + rel->r_vaddr - input_section->vma;
01043
01044
01045 howto = ppc_coff_howto_table + r_type;
01046
01047 if (symndx == -1)
01048 {
01049 h = NULL;
01050 sym = NULL;
01051 }
01052 else
01053 {
01054 h = (struct ppc_coff_link_hash_entry *)
01055 (obj_coff_sym_hashes (input_bfd)[symndx]);
01056 if (h != 0)
01057 {
01058 HASH_CHECK(h);
01059 }
01060
01061 sym = syms + symndx;
01062 }
01063
01064 if (r_type == IMAGE_REL_PPC_IMGLUE && h == 0)
01065 {
01066
01067 abort ();
01068 }
01069
01070 sec = NULL;
01071 val = 0;
01072
01073
01074 if (h == NULL)
01075 {
01076 if (symndx == -1)
01077 sec = bfd_abs_section_ptr;
01078 else
01079 {
01080 sec = sections[symndx];
01081 val = (sec->output_section->vma
01082 + sec->output_offset
01083 + sym->n_value);
01084 if (! obj_pe (output_bfd))
01085 val -= sec->vma;
01086 }
01087 }
01088 else
01089 {
01090 HASH_CHECK(h);
01091
01092 if (h->root.root.type == bfd_link_hash_defined
01093 || h->root.root.type == bfd_link_hash_defweak)
01094 {
01095 sec = h->root.root.u.def.section;
01096 val = (h->root.root.u.def.value
01097 + sec->output_section->vma
01098 + sec->output_offset);
01099 }
01100 else
01101 {
01102 if (! ((*info->callbacks->undefined_symbol)
01103 (info, h->root.root.root.string, input_bfd, input_section,
01104 rel->r_vaddr - input_section->vma, TRUE)))
01105 return FALSE;
01106 }
01107 }
01108
01109 rstat = bfd_reloc_ok;
01110
01111
01112 switch (r_type)
01113 {
01114 default:
01115 (*_bfd_error_handler)
01116 (_("%B: unsupported relocation type 0x%02x"), input_bfd, r_type);
01117 bfd_set_error (bfd_error_bad_value);
01118 return FALSE;
01119 case IMAGE_REL_PPC_TOCREL16:
01120 {
01121 bfd_signed_vma our_toc_offset;
01122 int fixit;
01123
01124 DUMP_RELOC2(howto->name, rel);
01125
01126 if (toc_section == 0)
01127 {
01128 toc_section = bfd_get_section_by_name (bfd_of_toc_owner,
01129 TOC_SECTION_NAME);
01130
01131 if ( toc_section == NULL )
01132 {
01133
01134 abort ();
01135 }
01136 }
01137
01138
01139
01140
01141
01142
01143 fixit = FALSE;
01144 if (h == 0)
01145 {
01146
01147 int *local_toc_table;
01148 const char *name;
01149
01150 sym = syms + symndx;
01151 name = sym->_n._n_name;
01152
01153 local_toc_table = obj_coff_local_toc_table(input_bfd);
01154 our_toc_offset = local_toc_table[symndx];
01155
01156 if (IS_WRITTEN(our_toc_offset))
01157 {
01158
01159
01160
01161 MAKE_ADDR_AGAIN(our_toc_offset);
01162 }
01163 else
01164 {
01165
01166 record_toc (toc_section, our_toc_offset, priv,
01167 strdup (name));
01168
01169 bfd_put_32 (output_bfd, val,
01170 toc_section->contents + our_toc_offset);
01171
01172 MARK_AS_WRITTEN(local_toc_table[symndx]);
01173 fixit = TRUE;
01174 }
01175 }
01176 else
01177 {
01178 const char *name = h->root.root.root.string;
01179 our_toc_offset = h->toc_offset;
01180
01181 if ((r_flags & IMAGE_REL_PPC_TOCDEFN)
01182 == IMAGE_REL_PPC_TOCDEFN )
01183 {
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198 our_toc_offset = val - (toc_section->output_section->vma
01199 + toc_section->output_offset);
01200
01201
01202 if ((bfd_vma) our_toc_offset >= 65535)
01203 {
01204 (*_bfd_error_handler)
01205 (_("%B: Relocation for %s of %lx exceeds Toc size limit"),
01206 input_bfd, name,
01207 (unsigned long) our_toc_offset);
01208 bfd_set_error (bfd_error_bad_value);
01209 return FALSE;
01210 }
01211
01212 record_toc (toc_section, our_toc_offset, pub,
01213 strdup (name));
01214 }
01215 else if (IS_WRITTEN (our_toc_offset))
01216 {
01217
01218
01219
01220 MAKE_ADDR_AGAIN(our_toc_offset);
01221 }
01222 else
01223 {
01224 record_toc(toc_section, our_toc_offset, pub,
01225 strdup (name));
01226
01227
01228 bfd_put_32 (output_bfd, val,
01229 toc_section->contents + our_toc_offset);
01230
01231 MARK_AS_WRITTEN(h->toc_offset);
01232
01233
01234 fixit = TRUE;
01235 }
01236 }
01237
01238 if (fixit && info->base_file)
01239 {
01240
01241
01242
01243
01244
01245
01246 bfd_vma addr = (toc_section->output_section->vma
01247 + toc_section->output_offset + our_toc_offset);
01248
01249 if (coff_data (output_bfd)->pe)
01250 addr -= pe_data(output_bfd)->pe_opthdr.ImageBase;
01251
01252 fwrite (&addr, 1,4, (FILE *) info->base_file);
01253 }
01254
01255
01256 if ((r_flags & IMAGE_REL_PPC_TOCDEFN) != IMAGE_REL_PPC_TOCDEFN
01257 && (bfd_vma) our_toc_offset > toc_section->size)
01258 {
01259 (*_bfd_error_handler)
01260 (_("%B: Relocation exceeds allocated TOC (%lx)"),
01261 input_bfd, (unsigned long) toc_section->size);
01262 bfd_set_error (bfd_error_bad_value);
01263 return FALSE;
01264 }
01265
01266
01267 relocation = our_toc_offset + TOC_LOAD_ADJUSTMENT;
01268 rstat = _bfd_relocate_contents (howto, input_bfd, relocation, loc);
01269 }
01270 break;
01271 case IMAGE_REL_PPC_IFGLUE:
01272 {
01273
01274
01275
01276
01277 bfd_vma x;
01278 const char *my_name;
01279
01280 DUMP_RELOC2 (howto->name, rel);
01281
01282 if (h != 0)
01283 {
01284 my_name = h->root.root.root.string;
01285 if (h->symbol_is_glue == 1)
01286 {
01287 x = bfd_get_32 (input_bfd, loc);
01288 bfd_put_32 (input_bfd, (bfd_vma) h->glue_insn, loc);
01289 }
01290 }
01291 }
01292 break;
01293 case IMAGE_REL_PPC_SECREL:
01294
01295
01296
01297 break;
01298 case IMAGE_REL_PPC_SECTION:
01299
01300
01301
01302
01303 break;
01304 case IMAGE_REL_PPC_ABSOLUTE:
01305 {
01306 const char *my_name;
01307
01308 if (h == 0)
01309 my_name = (syms+symndx)->_n._n_name;
01310 else
01311 my_name = h->root.root.root.string;
01312
01313 (*_bfd_error_handler)
01314 (_("Warning: unsupported reloc %s <file %B, section %A>\n"
01315 "sym %ld (%s), r_vaddr %ld (%lx)"),
01316 input_bfd, input_section, howto->name,
01317 rel->r_symndx, my_name, (long) rel->r_vaddr,
01318 (unsigned long) rel->r_vaddr);
01319 }
01320 break;
01321 case IMAGE_REL_PPC_IMGLUE:
01322 {
01323
01324
01325 const char *my_name;
01326
01327 if (h->symbol_is_glue == 1)
01328 break;
01329 my_name = h->root.root.root.string;
01330
01331 (*_bfd_error_handler)
01332 (_("%B: Out of order IMGLUE reloc for %s"), input_bfd, my_name);
01333 bfd_set_error (bfd_error_bad_value);
01334 return FALSE;
01335 }
01336
01337 case IMAGE_REL_PPC_ADDR32NB:
01338 {
01339 const char *name = 0;
01340
01341 DUMP_RELOC2 (howto->name, rel);
01342
01343 if (strncmp(".idata$2",input_section->name,8) == 0 && first_thunk_address == 0)
01344 {
01345
01346 int idata5offset;
01347 struct coff_link_hash_entry *myh;
01348
01349 myh = coff_link_hash_lookup (coff_hash_table (info),
01350 "__idata5_magic__",
01351 FALSE, FALSE, TRUE);
01352 first_thunk_address = myh->root.u.def.value +
01353 sec->output_section->vma +
01354 sec->output_offset -
01355 pe_data(output_bfd)->pe_opthdr.ImageBase;
01356
01357 idata5offset = myh->root.u.def.value;
01358 myh = coff_link_hash_lookup (coff_hash_table (info),
01359 "__idata6_magic__",
01360 FALSE, FALSE, TRUE);
01361
01362 thunk_size = myh->root.u.def.value - idata5offset;
01363 myh = coff_link_hash_lookup (coff_hash_table (info),
01364 "__idata4_magic__",
01365 FALSE, FALSE, TRUE);
01366 import_table_size = myh->root.u.def.value;
01367 }
01368
01369 if (h == 0)
01370 {
01371
01372 sym = syms + symndx;
01373 name = sym->_n._n_name;
01374 }
01375 else
01376 {
01377 char *target = 0;
01378
01379 name = h->root.root.root.string;
01380 if (strcmp (".idata$2", name) == 0)
01381 target = "__idata2_magic__";
01382 else if (strcmp (".idata$4", name) == 0)
01383 target = "__idata4_magic__";
01384 else if (strcmp (".idata$5", name) == 0)
01385 target = "__idata5_magic__";
01386
01387 if (target != 0)
01388 {
01389 struct coff_link_hash_entry *myh;
01390
01391 myh = coff_link_hash_lookup (coff_hash_table (info),
01392 target,
01393 FALSE, FALSE, TRUE);
01394 if (myh == 0)
01395 {
01396
01397 abort ();
01398 }
01399
01400 val = myh->root.u.def.value +
01401 sec->output_section->vma + sec->output_offset;
01402 if (first_thunk_address == 0)
01403 {
01404 int idata5offset;
01405 myh = coff_link_hash_lookup (coff_hash_table (info),
01406 "__idata5_magic__",
01407 FALSE, FALSE, TRUE);
01408 first_thunk_address = myh->root.u.def.value +
01409 sec->output_section->vma +
01410 sec->output_offset -
01411 pe_data(output_bfd)->pe_opthdr.ImageBase;
01412
01413 idata5offset = myh->root.u.def.value;
01414 myh = coff_link_hash_lookup (coff_hash_table (info),
01415 "__idata6_magic__",
01416 FALSE, FALSE, TRUE);
01417
01418 thunk_size = myh->root.u.def.value - idata5offset;
01419 myh = coff_link_hash_lookup (coff_hash_table (info),
01420 "__idata4_magic__",
01421 FALSE, FALSE, TRUE);
01422 import_table_size = myh->root.u.def.value;
01423 }
01424 }
01425 }
01426
01427 rstat = _bfd_relocate_contents (howto,
01428 input_bfd,
01429 val -
01430 pe_data (output_bfd)->pe_opthdr.ImageBase,
01431 loc);
01432 }
01433 break;
01434
01435 case IMAGE_REL_PPC_REL24:
01436 DUMP_RELOC2(howto->name, rel);
01437 val -= (input_section->output_section->vma
01438 + input_section->output_offset);
01439
01440 rstat = _bfd_relocate_contents (howto,
01441 input_bfd,
01442 val,
01443 loc);
01444 break;
01445 case IMAGE_REL_PPC_ADDR16:
01446 case IMAGE_REL_PPC_ADDR24:
01447 case IMAGE_REL_PPC_ADDR32:
01448 DUMP_RELOC2(howto->name, rel);
01449 rstat = _bfd_relocate_contents (howto,
01450 input_bfd,
01451 val,
01452 loc);
01453 break;
01454 }
01455
01456 if (info->base_file)
01457 {
01458
01459
01460 if (sym && pe_data(output_bfd)->in_reloc_p (output_bfd, howto))
01461 {
01462
01463
01464
01465 bfd_vma addr = rel->r_vaddr
01466 - input_section->vma
01467 + input_section->output_offset
01468 + input_section->output_section->vma;
01469
01470 if (coff_data (output_bfd)->pe)
01471 addr -= pe_data (output_bfd)->pe_opthdr.ImageBase;
01472
01473 fwrite (&addr, 1,4, (FILE *) info->base_file);
01474 }
01475 }
01476
01477 switch (rstat)
01478 {
01479 default:
01480 abort ();
01481 case bfd_reloc_ok:
01482 break;
01483 case bfd_reloc_overflow:
01484 {
01485 const char *name;
01486 char buf[SYMNMLEN + 1];
01487
01488 if (symndx == -1)
01489 name = "*ABS*";
01490 else if (h != NULL)
01491 name = NULL;
01492 else if (sym == NULL)
01493 name = "*unknown*";
01494 else if (sym->_n._n_n._n_zeroes == 0
01495 && sym->_n._n_n._n_offset != 0)
01496 name = obj_coff_strings (input_bfd) + sym->_n._n_n._n_offset;
01497 else
01498 {
01499 strncpy (buf, sym->_n._n_name, SYMNMLEN);
01500 buf[SYMNMLEN] = '\0';
01501 name = buf;
01502 }
01503
01504 if (! ((*info->callbacks->reloc_overflow)
01505 (info, (h ? &h->root.root : NULL), name, howto->name,
01506 (bfd_vma) 0, input_bfd,
01507 input_section, rel->r_vaddr - input_section->vma)))
01508 return FALSE;
01509 }
01510 }
01511 }
01512
01513 return TRUE;
01514 }
01515
01516 #ifdef COFF_IMAGE_WITH_PE
01517
01518
01519
01520
01521
01522 long int global_toc_size = 4;
01523
01524 bfd* bfd_of_toc_owner = 0;
01525
01526 long int import_table_size;
01527 long int first_thunk_address;
01528 long int thunk_size;
01529
01530 struct list_ele *head;
01531 struct list_ele *tail;
01532
01533 static char *
01534 h1 = N_("\n\t\t\tTOC MAPPING\n\n");
01535 static char *
01536 h2 = N_(" TOC disassembly Comments Name\n");
01537 static char *
01538 h3 = N_(" Offset spelling (if present)\n");
01539
01540 void
01541 dump_toc (vfile)
01542 PTR vfile;
01543 {
01544 FILE *file = (FILE *) vfile;
01545 struct list_ele *t;
01546
01547 fprintf (file, _(h1));
01548 fprintf (file, _(h2));
01549 fprintf (file, _(h3));
01550
01551 for (t = head; t != 0; t=t->next)
01552 {
01553 const char *cat = "";
01554
01555 if (t->cat == priv)
01556 cat = _("private ");
01557 else if (t->cat == pub)
01558 cat = _("public ");
01559 else if (t->cat == tocdata)
01560 cat = _("data-in-toc ");
01561
01562 if (t->offset > global_toc_size)
01563 {
01564 if (t->offset <= global_toc_size + thunk_size)
01565 cat = _("IAT reference ");
01566 else
01567 {
01568 fprintf (file,
01569 _("**** global_toc_size %ld(%lx), thunk_size %ld(%lx)\n"),
01570 global_toc_size, global_toc_size,
01571 thunk_size, thunk_size);
01572 cat = _("Out of bounds!");
01573 }
01574 }
01575
01576 fprintf (file,
01577 " %04lx (%d)", (unsigned long) t->offset, t->offset - 32768);
01578 fprintf (file,
01579 " %s %s\n",
01580 cat, t->name);
01581
01582 }
01583
01584 fprintf (file, "\n");
01585 }
01586
01587 bfd_boolean
01588 ppc_allocate_toc_section (info)
01589 struct bfd_link_info *info ATTRIBUTE_UNUSED;
01590 {
01591 asection *s;
01592 bfd_byte *foo;
01593 bfd_size_type amt;
01594 static char test_char = '1';
01595
01596 if ( global_toc_size == 0 )
01597 return TRUE;
01598
01599 if (bfd_of_toc_owner == 0)
01600
01601 abort ();
01602
01603 s = bfd_get_section_by_name ( bfd_of_toc_owner , TOC_SECTION_NAME);
01604 if (s == NULL)
01605
01606 abort ();
01607
01608 amt = global_toc_size;
01609 foo = (bfd_byte *) bfd_alloc (bfd_of_toc_owner, amt);
01610 memset(foo, test_char, (size_t) global_toc_size);
01611
01612 s->size = global_toc_size;
01613 s->contents = foo;
01614
01615 return TRUE;
01616 }
01617
01618 bfd_boolean
01619 ppc_process_before_allocation (abfd, info)
01620 bfd *abfd;
01621 struct bfd_link_info *info;
01622 {
01623 asection *sec;
01624 struct internal_reloc *i, *rel;
01625
01626
01627
01628 _bfd_coff_get_external_symbols (abfd);
01629
01630
01631 sec = abfd->sections;
01632
01633 if (sec == 0)
01634 return TRUE;
01635
01636 for (; sec != 0; sec = sec->next)
01637 {
01638 if (sec->reloc_count == 0)
01639 continue;
01640
01641
01642
01643 i=_bfd_coff_read_internal_relocs(abfd,sec,1,0,0,0);
01644
01645 if (i == 0)
01646 abort ();
01647
01648 for (rel = i; rel < i + sec->reloc_count; ++rel)
01649 {
01650 unsigned short r_type = EXTRACT_TYPE (rel->r_type);
01651 unsigned short r_flags = EXTRACT_FLAGS (rel->r_type);
01652 bfd_boolean ok = TRUE;
01653
01654 DUMP_RELOC2 (ppc_coff_howto_table[r_type].name, rel);
01655
01656 switch(r_type)
01657 {
01658 case IMAGE_REL_PPC_TOCREL16:
01659
01660
01661 if ((r_flags & IMAGE_REL_PPC_TOCDEFN) != IMAGE_REL_PPC_TOCDEFN)
01662 ok = ppc_record_toc_entry(abfd, info, sec,
01663 rel->r_symndx, default_toc);
01664 if (!ok)
01665 return FALSE;
01666 break;
01667 case IMAGE_REL_PPC_IMGLUE:
01668 ppc_mark_symbol_as_glue (abfd, rel->r_symndx, rel);
01669 break;
01670 default:
01671 break;
01672 }
01673 }
01674 }
01675
01676 return TRUE;
01677 }
01678
01679 #endif
01680
01681 static bfd_reloc_status_type
01682 ppc_refhi_reloc (abfd, reloc_entry, symbol, data,
01683 input_section, output_bfd, error_message)
01684 bfd *abfd ATTRIBUTE_UNUSED;
01685 arelent *reloc_entry ATTRIBUTE_UNUSED;
01686 asymbol *symbol ATTRIBUTE_UNUSED;
01687 PTR data ATTRIBUTE_UNUSED;
01688 asection *input_section ATTRIBUTE_UNUSED;
01689 bfd *output_bfd;
01690 char **error_message ATTRIBUTE_UNUSED;
01691 {
01692 UN_IMPL("REFHI");
01693 DUMP_RELOC("REFHI",reloc_entry);
01694
01695 if (output_bfd == (bfd *) NULL)
01696 return bfd_reloc_continue;
01697
01698 return bfd_reloc_undefined;
01699 }
01700
01701 static bfd_reloc_status_type
01702 ppc_pair_reloc (abfd, reloc_entry, symbol, data,
01703 input_section, output_bfd, error_message)
01704 bfd *abfd ATTRIBUTE_UNUSED;
01705 arelent *reloc_entry ATTRIBUTE_UNUSED;
01706 asymbol *symbol ATTRIBUTE_UNUSED;
01707 PTR data ATTRIBUTE_UNUSED;
01708 asection *input_section ATTRIBUTE_UNUSED;
01709 bfd *output_bfd;
01710 char **error_message ATTRIBUTE_UNUSED;
01711 {
01712 UN_IMPL("PAIR");
01713 DUMP_RELOC("PAIR",reloc_entry);
01714
01715 if (output_bfd == (bfd *) NULL)
01716 return bfd_reloc_continue;
01717
01718 return bfd_reloc_undefined;
01719 }
01720
01721 static bfd_reloc_status_type
01722 ppc_toc16_reloc (abfd, reloc_entry, symbol, data,
01723 input_section, output_bfd, error_message)
01724 bfd *abfd ATTRIBUTE_UNUSED;
01725 arelent *reloc_entry ATTRIBUTE_UNUSED;
01726 asymbol *symbol ATTRIBUTE_UNUSED;
01727 PTR data ATTRIBUTE_UNUSED;
01728 asection *input_section ATTRIBUTE_UNUSED;
01729 bfd *output_bfd;
01730 char **error_message ATTRIBUTE_UNUSED;
01731 {
01732 UN_IMPL ("TOCREL16");
01733 DUMP_RELOC ("TOCREL16",reloc_entry);
01734
01735 if (output_bfd == (bfd *) NULL)
01736 return bfd_reloc_continue;
01737
01738 return bfd_reloc_ok;
01739 }
01740
01741 static bfd_reloc_status_type
01742 ppc_secrel_reloc (abfd, reloc_entry, symbol, data,
01743 input_section, output_bfd, error_message)
01744 bfd *abfd ATTRIBUTE_UNUSED;
01745 arelent *reloc_entry ATTRIBUTE_UNUSED;
01746 asymbol *symbol ATTRIBUTE_UNUSED;
01747 PTR data ATTRIBUTE_UNUSED;
01748 asection *input_section ATTRIBUTE_UNUSED;
01749 bfd *output_bfd;
01750 char **error_message ATTRIBUTE_UNUSED;
01751 {
01752 UN_IMPL("SECREL");
01753 DUMP_RELOC("SECREL",reloc_entry);
01754
01755 if (output_bfd == (bfd *) NULL)
01756 return bfd_reloc_continue;
01757
01758 return bfd_reloc_ok;
01759 }
01760
01761 static bfd_reloc_status_type
01762 ppc_section_reloc (abfd, reloc_entry, symbol, data,
01763 input_section, output_bfd, error_message)
01764 bfd *abfd ATTRIBUTE_UNUSED;
01765 arelent *reloc_entry ATTRIBUTE_UNUSED;
01766 asymbol *symbol ATTRIBUTE_UNUSED;
01767 PTR data ATTRIBUTE_UNUSED;
01768 asection *input_section ATTRIBUTE_UNUSED;
01769 bfd *output_bfd;
01770 char **error_message ATTRIBUTE_UNUSED;
01771 {
01772 UN_IMPL("SECTION");
01773 DUMP_RELOC("SECTION",reloc_entry);
01774
01775 if (output_bfd == (bfd *) NULL)
01776 return bfd_reloc_continue;
01777
01778 return bfd_reloc_ok;
01779 }
01780
01781 static bfd_reloc_status_type
01782 ppc_imglue_reloc (abfd, reloc_entry, symbol, data,
01783 input_section, output_bfd, error_message)
01784 bfd *abfd ATTRIBUTE_UNUSED;
01785 arelent *reloc_entry ATTRIBUTE_UNUSED;
01786 asymbol *symbol ATTRIBUTE_UNUSED;
01787 PTR data ATTRIBUTE_UNUSED;
01788 asection *input_section ATTRIBUTE_UNUSED;
01789 bfd *output_bfd;
01790 char **error_message ATTRIBUTE_UNUSED;
01791 {
01792 UN_IMPL("IMGLUE");
01793 DUMP_RELOC("IMGLUE",reloc_entry);
01794
01795 if (output_bfd == (bfd *) NULL)
01796 return bfd_reloc_continue;
01797
01798 return bfd_reloc_ok;
01799 }
01800
01801 #define MAX_RELOC_INDEX \
01802 (sizeof (ppc_coff_howto_table) / sizeof (ppc_coff_howto_table[0]) - 1)
01803
01804
01805
01806
01807 static void ppc_coff_rtype2howto PARAMS ((arelent *, struct internal_reloc *));
01808
01809 static void
01810 ppc_coff_rtype2howto (relent, internal)
01811 arelent *relent;
01812 struct internal_reloc *internal;
01813 {
01814
01815
01816
01817
01818
01819
01820
01821
01822
01823 reloc_howto_type *howto;
01824 unsigned short r_type = EXTRACT_TYPE (internal->r_type);
01825 unsigned short r_flags = EXTRACT_FLAGS(internal->r_type);
01826 unsigned short junk = EXTRACT_JUNK (internal->r_type);
01827
01828
01829 if ( r_type > MAX_RELOC_INDEX )
01830 abort ();
01831
01832
01833 if (junk != 0)
01834 abort ();
01835
01836 switch(r_type)
01837 {
01838 case IMAGE_REL_PPC_ADDR16:
01839 case IMAGE_REL_PPC_REL24:
01840 case IMAGE_REL_PPC_ADDR24:
01841 case IMAGE_REL_PPC_ADDR32:
01842 case IMAGE_REL_PPC_IFGLUE:
01843 case IMAGE_REL_PPC_ADDR32NB:
01844 case IMAGE_REL_PPC_SECTION:
01845 case IMAGE_REL_PPC_SECREL:
01846 DUMP_RELOC2 (ppc_coff_howto_table[r_type].name, internal);
01847 howto = ppc_coff_howto_table + r_type;
01848 break;
01849 case IMAGE_REL_PPC_IMGLUE:
01850 DUMP_RELOC2 (ppc_coff_howto_table[r_type].name, internal);
01851 howto = ppc_coff_howto_table + r_type;
01852 break;
01853 case IMAGE_REL_PPC_TOCREL16:
01854 DUMP_RELOC2 (ppc_coff_howto_table[r_type].name, internal);
01855 if (r_flags & IMAGE_REL_PPC_TOCDEFN)
01856 howto = ppc_coff_howto_table + IMAGE_REL_PPC_TOCREL16_DEFN;
01857 else
01858 howto = ppc_coff_howto_table + IMAGE_REL_PPC_TOCREL16;
01859 break;
01860 default:
01861 fprintf (stderr,
01862 _("Warning: Unsupported reloc %s [%d] used -- it may not work.\n"),
01863 ppc_coff_howto_table[r_type].name,
01864 r_type);
01865 howto = ppc_coff_howto_table + r_type;
01866 break;
01867 }
01868
01869 relent->howto = howto;
01870 }
01871
01872 static reloc_howto_type *
01873 coff_ppc_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
01874 bfd *abfd ATTRIBUTE_UNUSED;
01875 asection *sec;
01876 struct internal_reloc *rel;
01877 struct coff_link_hash_entry *h ATTRIBUTE_UNUSED;
01878 struct internal_syment *sym ATTRIBUTE_UNUSED;
01879 bfd_vma *addendp;
01880 {
01881 reloc_howto_type *howto;
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891
01892
01893 unsigned short r_type = EXTRACT_TYPE (rel->r_type);
01894 unsigned short r_flags = EXTRACT_FLAGS (rel->r_type);
01895 unsigned short junk = EXTRACT_JUNK (rel->r_type);
01896
01897
01898 if (r_type > MAX_RELOC_INDEX)
01899 abort ();
01900
01901
01902 if (junk != 0)
01903 abort ();
01904
01905 switch(r_type)
01906 {
01907 case IMAGE_REL_PPC_ADDR32NB:
01908 DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel);
01909 *addendp -= pe_data(sec->output_section->owner)->pe_opthdr.ImageBase;
01910 howto = ppc_coff_howto_table + r_type;
01911 break;
01912 case IMAGE_REL_PPC_TOCREL16:
01913 DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel);
01914 if (r_flags & IMAGE_REL_PPC_TOCDEFN)
01915 howto = ppc_coff_howto_table + IMAGE_REL_PPC_TOCREL16_DEFN;
01916 else
01917 howto = ppc_coff_howto_table + IMAGE_REL_PPC_TOCREL16;
01918 break;
01919 case IMAGE_REL_PPC_ADDR16:
01920 case IMAGE_REL_PPC_REL24:
01921 case IMAGE_REL_PPC_ADDR24:
01922 case IMAGE_REL_PPC_ADDR32:
01923 case IMAGE_REL_PPC_IFGLUE:
01924 case IMAGE_REL_PPC_SECTION:
01925 case IMAGE_REL_PPC_SECREL:
01926 DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel);
01927 howto = ppc_coff_howto_table + r_type;
01928 break;
01929 case IMAGE_REL_PPC_IMGLUE:
01930 DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel);
01931 howto = ppc_coff_howto_table + r_type;
01932 break;
01933 default:
01934 fprintf (stderr,
01935 _("Warning: Unsupported reloc %s [%d] used -- it may not work.\n"),
01936 ppc_coff_howto_table[r_type].name,
01937 r_type);
01938 howto = ppc_coff_howto_table + r_type;
01939 break;
01940 }
01941
01942 return howto;
01943 }
01944
01945
01946 #define HOW2MAP(bfd_rtype,ppc_rtype) \
01947 case bfd_rtype: return &ppc_coff_howto_table[ppc_rtype]
01948
01949 static reloc_howto_type *ppc_coff_reloc_type_lookup
01950 PARAMS ((bfd *, bfd_reloc_code_real_type));
01951
01952 static reloc_howto_type *
01953 ppc_coff_reloc_type_lookup (abfd, code)
01954 bfd *abfd ATTRIBUTE_UNUSED;
01955 bfd_reloc_code_real_type code;
01956 {
01957 switch (code)
01958 {
01959 HOW2MAP(BFD_RELOC_32_GOTOFF, IMAGE_REL_PPC_IMGLUE);
01960 HOW2MAP(BFD_RELOC_16_GOT_PCREL, IMAGE_REL_PPC_IFGLUE);
01961 HOW2MAP(BFD_RELOC_16, IMAGE_REL_PPC_ADDR16);
01962 HOW2MAP(BFD_RELOC_PPC_B26, IMAGE_REL_PPC_REL24);
01963 HOW2MAP(BFD_RELOC_PPC_BA26, IMAGE_REL_PPC_ADDR24);
01964 HOW2MAP(BFD_RELOC_PPC_TOC16, IMAGE_REL_PPC_TOCREL16);
01965 HOW2MAP(BFD_RELOC_16_GOTOFF, IMAGE_REL_PPC_TOCREL16_DEFN);
01966 HOW2MAP(BFD_RELOC_32, IMAGE_REL_PPC_ADDR32);
01967 HOW2MAP(BFD_RELOC_RVA, IMAGE_REL_PPC_ADDR32NB);
01968 default:
01969 return NULL;
01970 }
01971 }
01972
01973 #undef HOW2MAP
01974
01975
01976
01977 #define RTYPE2HOWTO(cache_ptr, dst) ppc_coff_rtype2howto (cache_ptr, dst)
01978
01979
01980
01981 #define coff_bfd_reloc_type_lookup ppc_coff_reloc_type_lookup
01982 #define coff_rtype_to_howto coff_ppc_rtype_to_howto
01983 #define coff_relocate_section coff_ppc_relocate_section
01984 #define coff_bfd_final_link ppc_bfd_coff_final_link
01985
01986 #ifndef COFF_IMAGE_WITH_PE
01987 #endif
01988
01989 #define SELECT_RELOC(internal, howto) {internal.r_type=howto->type;}
01990
01991 #define COFF_PAGE_SIZE 0x1000
01992
01993
01994
01995
01996 #define POWERPC_LE_PE
01997
01998 #define COFF_SECTION_ALIGNMENT_ENTRIES \
01999 { COFF_SECTION_NAME_EXACT_MATCH (".idata$2"), \
02000 COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }, \
02001 { COFF_SECTION_NAME_EXACT_MATCH (".idata$3"), \
02002 COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }, \
02003 { COFF_SECTION_NAME_EXACT_MATCH (".idata$4"), \
02004 COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
02005 { COFF_SECTION_NAME_EXACT_MATCH (".idata$5"), \
02006 COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
02007 { COFF_SECTION_NAME_EXACT_MATCH (".idata$6"), \
02008 COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 1 }, \
02009 { COFF_SECTION_NAME_EXACT_MATCH (".reloc"), \
02010 COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 1 }
02011
02012 #include "coffcode.h"
02013
02014 #ifndef COFF_IMAGE_WITH_PE
02015
02016 static bfd_boolean ppc_do_last PARAMS ((bfd *));
02017 static bfd *ppc_get_last PARAMS ((void));
02018
02019 static bfd_boolean
02020 ppc_do_last (abfd)
02021 bfd *abfd;
02022 {
02023 if (abfd == bfd_of_toc_owner)
02024 return TRUE;
02025 else
02026 return FALSE;
02027 }
02028
02029 static bfd *
02030 ppc_get_last()
02031 {
02032 return bfd_of_toc_owner;
02033 }
02034
02035
02036
02037
02038
02039
02040
02041
02042
02043
02044
02045
02046
02047
02048 bfd_boolean
02049 ppc_bfd_coff_final_link (abfd, info)
02050 bfd *abfd;
02051 struct bfd_link_info *info;
02052 {
02053 bfd_size_type symesz;
02054 struct coff_final_link_info finfo;
02055 bfd_boolean debug_merge_allocated;
02056 asection *o;
02057 struct bfd_link_order *p;
02058 bfd_size_type max_sym_count;
02059 bfd_size_type max_lineno_count;
02060 bfd_size_type max_reloc_count;
02061 bfd_size_type max_output_reloc_count;
02062 bfd_size_type max_contents_size;
02063 file_ptr rel_filepos;
02064 unsigned int relsz;
02065 file_ptr line_filepos;
02066 unsigned int linesz;
02067 bfd *sub;
02068 bfd_byte *external_relocs = NULL;
02069 char strbuf[STRING_SIZE_SIZE];
02070 bfd_size_type amt;
02071
02072 symesz = bfd_coff_symesz (abfd);
02073
02074 finfo.info = info;
02075 finfo.output_bfd = abfd;
02076 finfo.strtab = NULL;
02077 finfo.section_info = NULL;
02078 finfo.last_file_index = -1;
02079 finfo.last_bf_index = -1;
02080 finfo.internal_syms = NULL;
02081 finfo.sec_ptrs = NULL;
02082 finfo.sym_indices = NULL;
02083 finfo.outsyms = NULL;
02084 finfo.linenos = NULL;
02085 finfo.contents = NULL;
02086 finfo.external_relocs = NULL;
02087 finfo.internal_relocs = NULL;
02088 debug_merge_allocated = FALSE;
02089
02090 coff_data (abfd)->link_info = info;
02091
02092 finfo.strtab = _bfd_stringtab_init ();
02093 if (finfo.strtab == NULL)
02094 goto error_return;
02095
02096 if (! coff_debug_merge_hash_table_init (&finfo.debug_merge))
02097 goto error_return;
02098 debug_merge_allocated = TRUE;
02099
02100
02101 if (! abfd->output_has_begun)
02102 {
02103 if (! bfd_coff_compute_section_file_positions (abfd))
02104 return FALSE;
02105 }
02106
02107
02108
02109 rel_filepos = obj_relocbase (abfd);
02110 relsz = bfd_coff_relsz (abfd);
02111 max_contents_size = 0;
02112 max_lineno_count = 0;
02113 max_reloc_count = 0;
02114
02115 for (o = abfd->sections; o != NULL; o = o->next)
02116 {
02117 o->reloc_count = 0;
02118 o->lineno_count = 0;
02119
02120 for (p = o->link_order_head; p != NULL; p = p->next)
02121 {
02122 if (p->type == bfd_indirect_link_order)
02123 {
02124 asection *sec;
02125
02126 sec = p->u.indirect.section;
02127
02128
02129
02130
02131
02132 sec->linker_mark = TRUE;
02133
02134 if (info->strip == strip_none
02135 || info->strip == strip_some)
02136 o->lineno_count += sec->lineno_count;
02137
02138 if (info->relocatable)
02139 o->reloc_count += sec->reloc_count;
02140
02141 if (sec->rawsize > max_contents_size)
02142 max_contents_size = sec->rawsize;
02143 if (sec->size > max_contents_size)
02144 max_contents_size = sec->size;
02145 if (sec->lineno_count > max_lineno_count)
02146 max_lineno_count = sec->lineno_count;
02147 if (sec->reloc_count > max_reloc_count)
02148 max_reloc_count = sec->reloc_count;
02149 }
02150 else if (info->relocatable
02151 && (p->type == bfd_section_reloc_link_order
02152 || p->type == bfd_symbol_reloc_link_order))
02153 ++o->reloc_count;
02154 }
02155 if (o->reloc_count == 0)
02156 o->rel_filepos = 0;
02157 else
02158 {
02159 o->flags |= SEC_RELOC;
02160 o->rel_filepos = rel_filepos;
02161 rel_filepos += o->reloc_count * relsz;
02162 }
02163 }
02164
02165
02166
02167 if (info->relocatable)
02168 {
02169 unsigned int i;
02170
02171
02172
02173 amt = abfd->section_count + 1;
02174 amt *= sizeof (struct coff_link_section_info);
02175 finfo.section_info = (struct coff_link_section_info *) bfd_malloc (amt);
02176
02177 if (finfo.section_info == NULL)
02178 goto error_return;
02179
02180 for (i = 0; i <= abfd->section_count; i++)
02181 {
02182 finfo.section_info[i].relocs = NULL;
02183 finfo.section_info[i].rel_hashes = NULL;
02184 }
02185 }
02186
02187
02188
02189 line_filepos = rel_filepos;
02190 linesz = bfd_coff_linesz (abfd);
02191 max_output_reloc_count = 0;
02192
02193 for (o = abfd->sections; o != NULL; o = o->next)
02194 {
02195 if (o->lineno_count == 0)
02196 o->line_filepos = 0;
02197 else
02198 {
02199 o->line_filepos = line_filepos;
02200 line_filepos += o->lineno_count * linesz;
02201 }
02202
02203 if (o->reloc_count != 0)
02204 {
02205
02206
02207
02208
02209
02210
02211
02212
02213
02214
02215
02216
02217
02218 BFD_ASSERT (info->relocatable);
02219 amt = o->reloc_count;
02220 amt *= sizeof (struct internal_reloc);
02221 finfo.section_info[o->target_index].relocs =
02222 (struct internal_reloc *) bfd_malloc (amt);
02223 amt = o->reloc_count;
02224 amt *= sizeof (struct coff_link_hash_entry *);
02225 finfo.section_info[o->target_index].rel_hashes =
02226 (struct coff_link_hash_entry **) bfd_malloc (amt);
02227 if (finfo.section_info[o->target_index].relocs == NULL
02228 || finfo.section_info[o->target_index].rel_hashes == NULL)
02229 goto error_return;
02230
02231 if (o->reloc_count > max_output_reloc_count)
02232 max_output_reloc_count = o->reloc_count;
02233 }
02234
02235
02236
02237 o->reloc_count = 0;
02238 o->lineno_count = 0;
02239 }
02240
02241 obj_sym_filepos (abfd) = line_filepos;
02242
02243
02244
02245
02246 max_sym_count = 0;
02247 for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
02248 {
02249 bfd_size_type sz;
02250
02251 sub->output_has_begun = FALSE;
02252 sz = obj_raw_syment_count (sub);
02253 if (sz > max_sym_count)
02254 max_sym_count = sz;
02255 }
02256
02257
02258 amt = max_sym_count * sizeof (struct internal_syment);
02259 finfo.internal_syms = (struct internal_syment *) bfd_malloc (amt);
02260 amt = max_sym_count * sizeof (asection *);
02261 finfo.sec_ptrs = (asection **) bfd_malloc (amt);
02262 amt = max_sym_count * sizeof (long);
02263 finfo.sym_indices = (long *) bfd_malloc (amt);
02264 amt = (max_sym_count + 1) * symesz;
02265 finfo.outsyms = (bfd_byte *) bfd_malloc (amt);
02266 amt = max_lineno_count * bfd_coff_linesz (abfd);
02267 finfo.linenos = (bfd_byte *) bfd_malloc (amt);
02268 finfo.contents = (bfd_byte *) bfd_malloc (max_contents_size);
02269 finfo.external_relocs = (bfd_byte *) bfd_malloc (max_reloc_count * relsz);
02270 if (! info->relocatable)
02271 {
02272 amt = max_reloc_count * sizeof (struct internal_reloc);
02273 finfo.internal_relocs = (struct internal_reloc *) bfd_malloc (amt);
02274 }
02275 if ((finfo.internal_syms == NULL && max_sym_count > 0)
02276 || (finfo.sec_ptrs == NULL && max_sym_count > 0)
02277 || (finfo.sym_indices == NULL && max_sym_count > 0)
02278 || finfo.outsyms == NULL
02279 || (finfo.linenos == NULL && max_lineno_count > 0)
02280 || (finfo.contents == NULL && max_contents_size > 0)
02281 || (finfo.external_relocs == NULL && max_reloc_count > 0)
02282 || (! info->relocatable
02283 && finfo.internal_relocs == NULL
02284 && max_reloc_count > 0))
02285 goto error_return;
02286
02287
02288
02289
02290
02291
02292 obj_raw_syment_count (abfd) = 0;
02293
02294 if (coff_backend_info (abfd)->_bfd_coff_start_final_link)
02295 {
02296 if (! bfd_coff_start_final_link (abfd, info))
02297 goto error_return;
02298 }
02299
02300 for (o = abfd->sections; o != NULL; o = o->next)
02301 {
02302 for (p = o->link_order_head; p != NULL; p = p->next)
02303 {
02304 if (p->type == bfd_indirect_link_order
02305 && (bfd_get_flavour (p->u.indirect.section->owner)
02306 == bfd_target_coff_flavour))
02307 {
02308 sub = p->u.indirect.section->owner;
02309 #ifdef POWERPC_LE_PE
02310 if (! sub->output_has_begun && !ppc_do_last(sub))
02311 #else
02312 if (! sub->output_has_begun)
02313 #endif
02314 {
02315 if (! _bfd_coff_link_input_bfd (&finfo, sub))
02316 goto error_return;
02317 sub->output_has_begun = TRUE;
02318 }
02319 }
02320 else if (p->type == bfd_section_reloc_link_order
02321 || p->type == bfd_symbol_reloc_link_order)
02322 {
02323 if (! _bfd_coff_reloc_link_order (abfd, &finfo, o, p))
02324 goto error_return;
02325 }
02326 else
02327 {
02328 if (! _bfd_default_link_order (abfd, info, o, p))
02329 goto error_return;
02330 }
02331 }
02332 }
02333
02334 #ifdef POWERPC_LE_PE
02335 {
02336 bfd* last_one = ppc_get_last();
02337 if (last_one)
02338 {
02339 if (! _bfd_coff_link_input_bfd (&finfo, last_one))
02340 goto error_return;
02341 }
02342 last_one->output_has_begun = TRUE;
02343 }
02344 #endif
02345
02346
02347 coff_debug_merge_hash_table_free (&finfo.debug_merge);
02348 debug_merge_allocated = FALSE;
02349
02350 if (finfo.internal_syms != NULL)
02351 {
02352 free (finfo.internal_syms);
02353 finfo.internal_syms = NULL;
02354 }
02355 if (finfo.sec_ptrs != NULL)
02356 {
02357 free (finfo.sec_ptrs);
02358 finfo.sec_ptrs = NULL;
02359 }
02360 if (finfo.sym_indices != NULL)
02361 {
02362 free (finfo.sym_indices);
02363 finfo.sym_indices = NULL;
02364 }
02365 if (finfo.linenos != NULL)
02366 {
02367 free (finfo.linenos);
02368 finfo.linenos = NULL;
02369 }
02370 if (finfo.contents != NULL)
02371 {
02372 free (finfo.contents);
02373 finfo.contents = NULL;
02374 }
02375 if (finfo.external_relocs != NULL)
02376 {
02377 free (finfo.external_relocs);
02378 finfo.external_relocs = NULL;
02379 }
02380 if (finfo.internal_relocs != NULL)
02381 {
02382 free (finfo.internal_relocs);
02383 finfo.internal_relocs = NULL;
02384 }
02385
02386
02387
02388
02389 if (finfo.last_file_index != -1
02390 && (unsigned int) finfo.last_file.n_value != obj_raw_syment_count (abfd))
02391 {
02392 file_ptr pos;
02393
02394 finfo.last_file.n_value = obj_raw_syment_count (abfd);
02395 bfd_coff_swap_sym_out (abfd, (PTR) &finfo.last_file,
02396 (PTR) finfo.outsyms);
02397 pos = obj_sym_filepos (abfd) + finfo.last_file_index * symesz;
02398 if (bfd_seek (abfd, pos, SEEK_SET) != 0
02399 || bfd_bwrite (finfo.outsyms, symesz, abfd) != symesz)
02400 return FALSE;
02401 }
02402
02403
02404 finfo.failed = FALSE;
02405 coff_link_hash_traverse (coff_hash_table (info), _bfd_coff_write_global_sym,
02406 (PTR) &finfo);
02407 if (finfo.failed)
02408 goto error_return;
02409
02410
02411 if (finfo.outsyms != NULL)
02412 {
02413 free (finfo.outsyms);
02414 finfo.outsyms = NULL;
02415 }
02416
02417 if (info->relocatable)
02418 {
02419
02420
02421
02422 amt = max_output_reloc_count * relsz;
02423 external_relocs = (bfd_byte *) bfd_malloc (amt);
02424 if (external_relocs == NULL)
02425 goto error_return;
02426
02427 for (o = abfd->sections; o != NULL; o = o->next)
02428 {
02429 struct internal_reloc *irel;
02430 struct internal_reloc *irelend;
02431 struct coff_link_hash_entry **rel_hash;
02432 bfd_byte *erel;
02433
02434 if (o->reloc_count == 0)
02435 continue;
02436
02437 irel = finfo.section_info[o->target_index].relocs;
02438 irelend = irel + o->reloc_count;
02439 rel_hash = finfo.section_info[o->target_index].rel_hashes;
02440 erel = external_relocs;
02441 for (; irel < irelend; irel++, rel_hash++, erel += relsz)
02442 {
02443 if (*rel_hash != NULL)
02444 {
02445 BFD_ASSERT ((*rel_hash)->indx >= 0);
02446 irel->r_symndx = (*rel_hash)->indx;
02447 }
02448 bfd_coff_swap_reloc_out (abfd, (PTR) irel, (PTR) erel);
02449 }
02450
02451 amt = relsz * o->reloc_count;
02452 if (bfd_seek (abfd, o->rel_filepos, SEEK_SET) != 0
02453 || bfd_bwrite ((PTR) external_relocs, amt, abfd) != amt)
02454 goto error_return;
02455 }
02456
02457 free (external_relocs);
02458 external_relocs = NULL;
02459 }
02460
02461
02462 if (finfo.section_info != NULL)
02463 {
02464 unsigned int i;
02465
02466 for (i = 0; i < abfd->section_count; i++)
02467 {
02468 if (finfo.section_info[i].relocs != NULL)
02469 free (finfo.section_info[i].relocs);
02470 if (finfo.section_info[i].rel_hashes != NULL)
02471 free (finfo.section_info[i].rel_hashes);
02472 }
02473 free (finfo.section_info);
02474 finfo.section_info = NULL;
02475 }
02476
02477
02478 if (coff_hash_table (info)->stab_info.stabstr != NULL)
02479 {
02480 if (! _bfd_write_stab_strings (abfd, &coff_hash_table (info)->stab_info))
02481 return FALSE;
02482 }
02483
02484
02485 if (obj_raw_syment_count (abfd) != 0)
02486 {
02487 file_ptr pos;
02488
02489 pos = obj_sym_filepos (abfd) + obj_raw_syment_count (abfd) * symesz;
02490 if (bfd_seek (abfd, pos, SEEK_SET) != 0)
02491 return FALSE;
02492
02493 #if STRING_SIZE_SIZE == 4
02494 H_PUT_32 (abfd,
02495 _bfd_stringtab_size (finfo.strtab) + STRING_SIZE_SIZE,
02496 strbuf);
02497 #else
02498 #error Change H_PUT_32 above
02499 #endif
02500
02501 if (bfd_bwrite (strbuf, (bfd_size_type) STRING_SIZE_SIZE, abfd)
02502 != STRING_SIZE_SIZE)
02503 return FALSE;
02504
02505 if (! _bfd_stringtab_emit (abfd, finfo.strtab))
02506 return FALSE;
02507 }
02508
02509 _bfd_stringtab_free (finfo.strtab);
02510
02511
02512
02513 bfd_get_symcount (abfd) = 0;
02514
02515 return TRUE;
02516
02517 error_return:
02518 if (debug_merge_allocated)
02519 coff_debug_merge_hash_table_free (&finfo.debug_merge);
02520 if (finfo.strtab != NULL)
02521 _bfd_stringtab_free (finfo.strtab);
02522 if (finfo.section_info != NULL)
02523 {
02524 unsigned int i;
02525
02526 for (i = 0; i < abfd->section_count; i++)
02527 {
02528 if (finfo.section_info[i].relocs != NULL)
02529 free (finfo.section_info[i].relocs);
02530 if (finfo.section_info[i].rel_hashes != NULL)
02531 free (finfo.section_info[i].rel_hashes);
02532 }
02533 free (finfo.section_info);
02534 }
02535 if (finfo.internal_syms != NULL)
02536 free (finfo.internal_syms);
02537 if (finfo.sec_ptrs != NULL)
02538 free (finfo.sec_ptrs);
02539 if (finfo.sym_indices != NULL)
02540 free (finfo.sym_indices);
02541 if (finfo.outsyms != NULL)
02542 free (finfo.outsyms);
02543 if (finfo.linenos != NULL)
02544 free (finfo.linenos);
02545 if (finfo.contents != NULL)
02546 free (finfo.contents);
02547 if (finfo.external_relocs != NULL)
02548 free (finfo.external_relocs);
02549 if (finfo.internal_relocs != NULL)
02550 free (finfo.internal_relocs);
02551 if (external_relocs != NULL)
02552 free (external_relocs);
02553 return FALSE;
02554 }
02555 #endif
02556
02557
02558 #ifdef TARGET_BIG_SYM
02559 extern const bfd_target TARGET_BIG_SYM;
02560 #endif
02561
02562
02563
02564 #ifdef TARGET_LITTLE_SYM
02565 const bfd_target TARGET_LITTLE_SYM =
02566 {
02567 TARGET_LITTLE_NAME,
02568 bfd_target_coff_flavour,
02569 BFD_ENDIAN_LITTLE,
02570 BFD_ENDIAN_LITTLE,
02571
02572 (HAS_RELOC | EXEC_P |
02573 HAS_LINENO | HAS_DEBUG |
02574 HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
02575
02576 #ifndef COFF_WITH_PE
02577 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC),
02578 #else
02579 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC
02580 | SEC_LINK_ONCE | SEC_LINK_DUPLICATES),
02581 #endif
02582
02583 0,
02584 '/',
02585 15,
02586
02587 bfd_getl64, bfd_getl_signed_64, bfd_putl64,
02588 bfd_getl32, bfd_getl_signed_32, bfd_putl32,
02589 bfd_getl16, bfd_getl_signed_16, bfd_putl16,
02590
02591 bfd_getl64, bfd_getl_signed_64, bfd_putl64,
02592 bfd_getl32, bfd_getl_signed_32, bfd_putl32,
02593 bfd_getl16, bfd_getl_signed_16, bfd_putl16,
02594
02595 {_bfd_dummy_target, coff_object_p,
02596 bfd_generic_archive_p, coff_object_p },
02597 {bfd_false, coff_mkobject, _bfd_generic_mkarchive,
02598 bfd_false},
02599 {bfd_false, coff_write_object_contents,
02600 _bfd_write_archive_contents, bfd_false},
02601
02602 BFD_JUMP_TABLE_GENERIC (coff),
02603 BFD_JUMP_TABLE_COPY (coff),
02604 BFD_JUMP_TABLE_CORE (_bfd_nocore),
02605 BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
02606 BFD_JUMP_TABLE_SYMBOLS (coff),
02607 BFD_JUMP_TABLE_RELOCS (coff),
02608 BFD_JUMP_TABLE_WRITE (coff),
02609 BFD_JUMP_TABLE_LINK (coff),
02610 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
02611
02612
02613 #ifdef TARGET_BIG_SYM
02614 & TARGET_BIG_SYM,
02615 #else
02616 NULL,
02617 #endif
02618
02619 COFF_SWAP_TABLE
02620 };
02621 #endif
02622
02623 #ifdef TARGET_BIG_SYM
02624 const bfd_target TARGET_BIG_SYM =
02625 {
02626 TARGET_BIG_NAME,
02627 bfd_target_coff_flavour,
02628 BFD_ENDIAN_BIG,
02629 BFD_ENDIAN_BIG,
02630
02631 (HAS_RELOC | EXEC_P |
02632 HAS_LINENO | HAS_DEBUG |
02633 HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
02634
02635 #ifndef COFF_WITH_PE
02636 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC),
02637 #else
02638 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC
02639 | SEC_LINK_ONCE | SEC_LINK_DUPLICATES),
02640 #endif
02641
02642 0,
02643 '/',
02644 15,
02645
02646 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
02647 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
02648 bfd_getb16, bfd_getb_signed_16, bfd_putb16,
02649
02650 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
02651 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
02652 bfd_getb16, bfd_getb_signed_16, bfd_putb16,
02653
02654 {_bfd_dummy_target, coff_object_p,
02655 bfd_generic_archive_p, coff_object_p },
02656 {bfd_false, coff_mkobject, _bfd_generic_mkarchive,
02657 bfd_false},
02658 {bfd_false, coff_write_object_contents,
02659 _bfd_write_archive_contents, bfd_false},
02660
02661 BFD_JUMP_TABLE_GENERIC (coff),
02662 BFD_JUMP_TABLE_COPY (coff),
02663 BFD_JUMP_TABLE_CORE (_bfd_nocore),
02664 BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
02665 BFD_JUMP_TABLE_SYMBOLS (coff),
02666 BFD_JUMP_TABLE_RELOCS (coff),
02667 BFD_JUMP_TABLE_WRITE (coff),
02668 BFD_JUMP_TABLE_LINK (coff),
02669 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
02670
02671
02672 #ifdef TARGET_LITTLE_SYM
02673 & TARGET_LITTLE_SYM,
02674 #else
02675 NULL,
02676 #endif
02677
02678 COFF_SWAP_TABLE
02679 };
02680
02681 #endif