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/arm.h"
00032
00033 #include "coff/internal.h"
00034
00035 #ifdef COFF_WITH_PE
00036 #include "coff/pe.h"
00037 #endif
00038
00039 #include "libcoff.h"
00040
00041
00042
00043 #define APCS_26_FLAG(abfd) \
00044 (coff_data (abfd)->flags & F_APCS_26)
00045
00046 #define APCS_FLOAT_FLAG(abfd) \
00047 (coff_data (abfd)->flags & F_APCS_FLOAT)
00048
00049 #define PIC_FLAG(abfd) \
00050 (coff_data (abfd)->flags & F_PIC)
00051
00052 #define APCS_SET(abfd) \
00053 (coff_data (abfd)->flags & F_APCS_SET)
00054
00055 #define SET_APCS_FLAGS(abfd, flgs) \
00056 do \
00057 { \
00058 coff_data (abfd)->flags &= ~(F_APCS_26 | F_APCS_FLOAT | F_PIC); \
00059 coff_data (abfd)->flags |= (flgs) | F_APCS_SET; \
00060 } \
00061 while (0)
00062
00063 #define INTERWORK_FLAG(abfd) \
00064 (coff_data (abfd)->flags & F_INTERWORK)
00065
00066 #define INTERWORK_SET(abfd) \
00067 (coff_data (abfd)->flags & F_INTERWORK_SET)
00068
00069 #define SET_INTERWORK_FLAG(abfd, flg) \
00070 do \
00071 { \
00072 coff_data (abfd)->flags &= ~F_INTERWORK; \
00073 coff_data (abfd)->flags |= (flg) | F_INTERWORK_SET; \
00074 } \
00075 while (0)
00076
00077 #ifndef NUM_ELEM
00078 #define NUM_ELEM(a) ((sizeof (a)) / sizeof ((a)[0]))
00079 #endif
00080
00081 typedef enum {bunknown, b9, b12, b23} thumb_pcrel_branchtype;
00082
00083 typedef unsigned long int insn32;
00084 typedef unsigned short int insn16;
00085
00086
00087 static bfd_boolean coff_arm_relocate_section
00088 PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
00089 struct internal_reloc *, struct internal_syment *, asection **));
00090 static bfd_reloc_status_type aoutarm_fix_pcrel_26_done
00091 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
00092 static bfd_reloc_status_type aoutarm_fix_pcrel_26
00093 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
00094 #ifndef ARM_WINCE
00095 static bfd_reloc_status_type coff_thumb_pcrel_23
00096 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
00097 static bfd_reloc_status_type coff_thumb_pcrel_9
00098 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
00099 static insn32 insert_thumb_branch
00100 PARAMS ((insn32, int));
00101 #endif
00102 static bfd_reloc_status_type coff_thumb_pcrel_12
00103 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
00104 static bfd_reloc_status_type coff_arm_reloc
00105 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
00106 static bfd_boolean coff_arm_adjust_symndx
00107 PARAMS ((bfd *, struct bfd_link_info *, bfd *,
00108 asection *, struct internal_reloc *, bfd_boolean *));
00109 static reloc_howto_type * coff_arm_rtype_to_howto
00110 PARAMS ((bfd *, asection *, struct internal_reloc *,
00111 struct coff_link_hash_entry *, struct internal_syment *,
00112 bfd_vma *));
00113 static bfd_reloc_status_type coff_thumb_pcrel_common
00114 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **,
00115 thumb_pcrel_branchtype));
00116 static const struct reloc_howto_struct * coff_arm_reloc_type_lookup
00117 PARAMS ((bfd *, bfd_reloc_code_real_type));
00118 static struct bfd_link_hash_table * coff_arm_link_hash_table_create
00119 PARAMS ((bfd *));
00120 static struct coff_link_hash_entry * find_thumb_glue
00121 PARAMS ((struct bfd_link_info *, const char *, bfd *));
00122 static struct coff_link_hash_entry * find_arm_glue
00123 PARAMS ((struct bfd_link_info *, const char *, bfd *));
00124 #ifndef COFF_IMAGE_WITH_PE
00125 static void record_arm_to_thumb_glue
00126 PARAMS ((struct bfd_link_info *, struct coff_link_hash_entry *));
00127 #ifndef ARM_WINCE
00128 static void record_thumb_to_arm_glue
00129 PARAMS ((struct bfd_link_info *, struct coff_link_hash_entry *));
00130 #endif
00131 #endif
00132 static bfd_boolean coff_arm_merge_private_bfd_data
00133 PARAMS ((bfd *, bfd *));
00134 static bfd_boolean coff_arm_print_private_bfd_data
00135 PARAMS ((bfd *, PTR));
00136 static bfd_boolean _bfd_coff_arm_set_private_flags
00137 PARAMS ((bfd *, flagword));
00138 static bfd_boolean coff_arm_copy_private_bfd_data
00139 PARAMS ((bfd *, bfd *));
00140 static bfd_boolean coff_arm_is_local_label_name
00141 PARAMS ((bfd *, const char *));
00142 static bfd_boolean coff_arm_link_output_has_begun
00143 PARAMS ((bfd *, struct coff_final_link_info *));
00144 static bfd_boolean coff_arm_final_link_postscript
00145 PARAMS ((bfd *, struct coff_final_link_info *));
00146 static void arm_emit_base_file_entry
00147 PARAMS ((struct bfd_link_info *, bfd *, asection *, bfd_vma));
00148
00149
00150
00151
00152
00153
00154 #define THUMB2ARM_GLUE_SECTION_NAME ".glue_7t"
00155 #define THUMB2ARM_GLUE_ENTRY_NAME "__%s_from_thumb"
00156
00157 #define ARM2THUMB_GLUE_SECTION_NAME ".glue_7"
00158 #define ARM2THUMB_GLUE_ENTRY_NAME "__%s_from_arm"
00159
00160
00161
00162 static bfd_reloc_status_type
00163 coff_arm_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd,
00164 error_message)
00165 bfd *abfd;
00166 arelent *reloc_entry;
00167 asymbol *symbol ATTRIBUTE_UNUSED;
00168 PTR data;
00169 asection *input_section ATTRIBUTE_UNUSED;
00170 bfd *output_bfd;
00171 char **error_message ATTRIBUTE_UNUSED;
00172 {
00173 symvalue diff;
00174 if (output_bfd == (bfd *) NULL)
00175 return bfd_reloc_continue;
00176
00177 diff = reloc_entry->addend;
00178
00179 #define DOIT(x) \
00180 x = ((x & ~howto->dst_mask) \
00181 | (((x & howto->src_mask) + diff) & howto->dst_mask))
00182
00183 if (diff != 0)
00184 {
00185 reloc_howto_type *howto = reloc_entry->howto;
00186 unsigned char *addr = (unsigned char *) data + reloc_entry->address;
00187
00188 switch (howto->size)
00189 {
00190 case 0:
00191 {
00192 char x = bfd_get_8 (abfd, addr);
00193 DOIT (x);
00194 bfd_put_8 (abfd, x, addr);
00195 }
00196 break;
00197
00198 case 1:
00199 {
00200 short x = bfd_get_16 (abfd, addr);
00201 DOIT (x);
00202 bfd_put_16 (abfd, (bfd_vma) x, addr);
00203 }
00204 break;
00205
00206 case 2:
00207 {
00208 long x = bfd_get_32 (abfd, addr);
00209 DOIT (x);
00210 bfd_put_32 (abfd, (bfd_vma) x, addr);
00211 }
00212 break;
00213
00214 default:
00215 abort ();
00216 }
00217 }
00218
00219
00220 return bfd_reloc_continue;
00221 }
00222
00223
00224
00225
00226 #ifndef TARGET_UNDERSCORE
00227 #define TARGET_UNDERSCORE '_'
00228 #endif
00229
00230 #ifndef PCRELOFFSET
00231 #define PCRELOFFSET TRUE
00232 #endif
00233
00234
00235
00236 #define ARM_8 0
00237 #define ARM_16 1
00238 #define ARM_32 2
00239 #define ARM_26 3
00240 #define ARM_DISP8 4
00241 #define ARM_DISP16 5
00242 #define ARM_DISP32 6
00243 #define ARM_26D 7
00244
00245 #define ARM_NEG16 9
00246 #define ARM_NEG32 10
00247 #define ARM_RVA32 11
00248 #define ARM_THUMB9 12
00249 #define ARM_THUMB12 13
00250 #define ARM_THUMB23 14
00251
00252 #ifdef ARM_WINCE
00253 #undef ARM_32
00254 #undef ARM_RVA32
00255 #undef ARM_26
00256 #undef ARM_THUMB12
00257 #undef ARM_26D
00258
00259 #define ARM_26D 0
00260 #define ARM_32 1
00261 #define ARM_RVA32 2
00262 #define ARM_26 3
00263 #define ARM_THUMB12 4
00264 #define ARM_SECTION 14
00265 #define ARM_SECREL 15
00266 #endif
00267
00268 static reloc_howto_type aoutarm_std_reloc_howto[] =
00269 {
00270 #ifdef ARM_WINCE
00271 HOWTO (ARM_26D,
00272 2,
00273 2,
00274 24,
00275 TRUE,
00276 0,
00277 complain_overflow_dont,
00278 aoutarm_fix_pcrel_26_done,
00279 "ARM_26D",
00280 FALSE,
00281 0x00ffffff,
00282 0x0,
00283 PCRELOFFSET),
00284 HOWTO (ARM_32,
00285 0,
00286 2,
00287 32,
00288 FALSE,
00289 0,
00290 complain_overflow_bitfield,
00291 coff_arm_reloc,
00292 "ARM_32",
00293 FALSE,
00294 0xffffffff,
00295 0xffffffff,
00296 PCRELOFFSET),
00297 HOWTO (ARM_RVA32,
00298 0,
00299 2,
00300 32,
00301 FALSE,
00302 0,
00303 complain_overflow_bitfield,
00304 coff_arm_reloc,
00305 "ARM_RVA32",
00306 FALSE,
00307 0xffffffff,
00308 0xffffffff,
00309 PCRELOFFSET),
00310 HOWTO (ARM_26,
00311 2,
00312 2,
00313 24,
00314 TRUE,
00315 0,
00316 complain_overflow_signed,
00317 aoutarm_fix_pcrel_26 ,
00318 "ARM_26",
00319 FALSE,
00320 0x00ffffff,
00321 0x00ffffff,
00322 PCRELOFFSET),
00323 HOWTO (ARM_THUMB12,
00324 1,
00325 1,
00326 11,
00327 TRUE,
00328 0,
00329 complain_overflow_signed,
00330 coff_thumb_pcrel_12 ,
00331 "ARM_THUMB12",
00332 FALSE,
00333 0x000007ff,
00334 0x000007ff,
00335 PCRELOFFSET),
00336 EMPTY_HOWTO (-1),
00337 EMPTY_HOWTO (-1),
00338 EMPTY_HOWTO (-1),
00339 EMPTY_HOWTO (-1),
00340 EMPTY_HOWTO (-1),
00341 EMPTY_HOWTO (-1),
00342 EMPTY_HOWTO (-1),
00343 EMPTY_HOWTO (-1),
00344 EMPTY_HOWTO (-1),
00345 HOWTO (ARM_SECTION,
00346 0,
00347 1,
00348 16,
00349 FALSE,
00350 0,
00351 complain_overflow_bitfield,
00352 coff_arm_reloc,
00353 "ARM_SECTION",
00354 FALSE,
00355 0x0000ffff,
00356 0x0000ffff,
00357 PCRELOFFSET),
00358 HOWTO (ARM_SECREL,
00359 0,
00360 2,
00361 32,
00362 FALSE,
00363 0,
00364 complain_overflow_bitfield,
00365 coff_arm_reloc,
00366 "ARM_SECREL",
00367 FALSE,
00368 0xffffffff,
00369 0xffffffff,
00370 PCRELOFFSET),
00371 #else
00372 HOWTO (ARM_8,
00373 0,
00374 0,
00375 8,
00376 FALSE,
00377 0,
00378 complain_overflow_bitfield,
00379 coff_arm_reloc,
00380 "ARM_8",
00381 TRUE,
00382 0x000000ff,
00383 0x000000ff,
00384 PCRELOFFSET ),
00385 HOWTO (ARM_16,
00386 0,
00387 1,
00388 16,
00389 FALSE,
00390 0,
00391 complain_overflow_bitfield,
00392 coff_arm_reloc,
00393 "ARM_16",
00394 TRUE,
00395 0x0000ffff,
00396 0x0000ffff,
00397 PCRELOFFSET),
00398 HOWTO (ARM_32,
00399 0,
00400 2,
00401 32,
00402 FALSE,
00403 0,
00404 complain_overflow_bitfield,
00405 coff_arm_reloc,
00406 "ARM_32",
00407 TRUE,
00408 0xffffffff,
00409 0xffffffff,
00410 PCRELOFFSET),
00411 HOWTO (ARM_26,
00412 2,
00413 2,
00414 24,
00415 TRUE,
00416 0,
00417 complain_overflow_signed,
00418 aoutarm_fix_pcrel_26 ,
00419 "ARM_26",
00420 FALSE,
00421 0x00ffffff,
00422 0x00ffffff,
00423 PCRELOFFSET),
00424 HOWTO (ARM_DISP8,
00425 0,
00426 0,
00427 8,
00428 TRUE,
00429 0,
00430 complain_overflow_signed,
00431 coff_arm_reloc,
00432 "ARM_DISP8",
00433 TRUE,
00434 0x000000ff,
00435 0x000000ff,
00436 TRUE),
00437 HOWTO (ARM_DISP16,
00438 0,
00439 1,
00440 16,
00441 TRUE,
00442 0,
00443 complain_overflow_signed,
00444 coff_arm_reloc,
00445 "ARM_DISP16",
00446 TRUE,
00447 0x0000ffff,
00448 0x0000ffff,
00449 TRUE),
00450 HOWTO (ARM_DISP32,
00451 0,
00452 2,
00453 32,
00454 TRUE,
00455 0,
00456 complain_overflow_signed,
00457 coff_arm_reloc,
00458 "ARM_DISP32",
00459 TRUE,
00460 0xffffffff,
00461 0xffffffff,
00462 TRUE),
00463 HOWTO (ARM_26D,
00464 2,
00465 2,
00466 24,
00467 FALSE,
00468 0,
00469 complain_overflow_dont,
00470 aoutarm_fix_pcrel_26_done,
00471 "ARM_26D",
00472 TRUE,
00473 0x00ffffff,
00474 0x0,
00475 FALSE),
00476
00477 EMPTY_HOWTO (-1),
00478 HOWTO (ARM_NEG16,
00479 0,
00480 -1,
00481 16,
00482 FALSE,
00483 0,
00484 complain_overflow_bitfield,
00485 coff_arm_reloc,
00486 "ARM_NEG16",
00487 TRUE,
00488 0x0000ffff,
00489 0x0000ffff,
00490 FALSE),
00491 HOWTO (ARM_NEG32,
00492 0,
00493 -2,
00494 32,
00495 FALSE,
00496 0,
00497 complain_overflow_bitfield,
00498 coff_arm_reloc,
00499 "ARM_NEG32",
00500 TRUE,
00501 0xffffffff,
00502 0xffffffff,
00503 FALSE),
00504 HOWTO (ARM_RVA32,
00505 0,
00506 2,
00507 32,
00508 FALSE,
00509 0,
00510 complain_overflow_bitfield,
00511 coff_arm_reloc,
00512 "ARM_RVA32",
00513 TRUE,
00514 0xffffffff,
00515 0xffffffff,
00516 PCRELOFFSET),
00517 HOWTO (ARM_THUMB9,
00518 1,
00519 1,
00520 8,
00521 TRUE,
00522 0,
00523 complain_overflow_signed,
00524 coff_thumb_pcrel_9 ,
00525 "ARM_THUMB9",
00526 FALSE,
00527 0x000000ff,
00528 0x000000ff,
00529 PCRELOFFSET),
00530 HOWTO (ARM_THUMB12,
00531 1,
00532 1,
00533 11,
00534 TRUE,
00535 0,
00536 complain_overflow_signed,
00537 coff_thumb_pcrel_12 ,
00538 "ARM_THUMB12",
00539 FALSE,
00540 0x000007ff,
00541 0x000007ff,
00542 PCRELOFFSET),
00543 HOWTO (ARM_THUMB23,
00544 1,
00545 2,
00546 22,
00547 TRUE,
00548 0,
00549 complain_overflow_signed,
00550 coff_thumb_pcrel_23 ,
00551 "ARM_THUMB23",
00552 FALSE,
00553 0x07ff07ff,
00554 0x07ff07ff,
00555 PCRELOFFSET)
00556 #endif
00557 };
00558
00559 #define NUM_RELOCS NUM_ELEM (aoutarm_std_reloc_howto)
00560
00561 #ifdef COFF_WITH_PE
00562 static bfd_boolean in_reloc_p PARAMS ((bfd *, reloc_howto_type *));
00563
00564
00565
00566 static bfd_boolean
00567 in_reloc_p (abfd, howto)
00568 bfd * abfd ATTRIBUTE_UNUSED;
00569 reloc_howto_type * howto;
00570 {
00571 return !howto->pc_relative && howto->type != ARM_RVA32;
00572 }
00573 #endif
00574
00575 #define RTYPE2HOWTO(cache_ptr, dst) \
00576 (cache_ptr)->howto = \
00577 (dst)->r_type < NUM_RELOCS \
00578 ? aoutarm_std_reloc_howto + (dst)->r_type \
00579 : NULL
00580
00581 #define coff_rtype_to_howto coff_arm_rtype_to_howto
00582
00583 static reloc_howto_type *
00584 coff_arm_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
00585 bfd *abfd ATTRIBUTE_UNUSED;
00586 asection *sec;
00587 struct internal_reloc *rel;
00588 struct coff_link_hash_entry *h ATTRIBUTE_UNUSED;
00589 struct internal_syment *sym ATTRIBUTE_UNUSED;
00590 bfd_vma *addendp;
00591 {
00592 reloc_howto_type * howto;
00593
00594 if (rel->r_type >= NUM_RELOCS)
00595 return NULL;
00596
00597 howto = aoutarm_std_reloc_howto + rel->r_type;
00598
00599 if (rel->r_type == ARM_RVA32)
00600 *addendp -= pe_data (sec->output_section->owner)->pe_opthdr.ImageBase;
00601
00602 return howto;
00603 }
00604
00605
00606
00607 static bfd_reloc_status_type
00608 aoutarm_fix_pcrel_26_done (abfd, reloc_entry, symbol, data, input_section,
00609 output_bfd, error_message)
00610 bfd *abfd ATTRIBUTE_UNUSED;
00611 arelent *reloc_entry ATTRIBUTE_UNUSED;
00612 asymbol *symbol ATTRIBUTE_UNUSED;
00613 PTR data ATTRIBUTE_UNUSED;
00614 asection *input_section ATTRIBUTE_UNUSED;
00615 bfd *output_bfd ATTRIBUTE_UNUSED;
00616 char **error_message ATTRIBUTE_UNUSED;
00617 {
00618
00619 return bfd_reloc_ok;
00620 }
00621
00622
00623
00624 static bfd_reloc_status_type
00625 aoutarm_fix_pcrel_26 (abfd, reloc_entry, symbol, data, input_section,
00626 output_bfd, error_message)
00627 bfd *abfd;
00628 arelent *reloc_entry;
00629 asymbol *symbol;
00630 PTR data;
00631 asection *input_section;
00632 bfd *output_bfd;
00633 char **error_message ATTRIBUTE_UNUSED;
00634 {
00635 bfd_vma relocation;
00636 bfd_size_type addr = reloc_entry->address;
00637 long target = bfd_get_32 (abfd, (bfd_byte *) data + addr);
00638 bfd_reloc_status_type flag = bfd_reloc_ok;
00639
00640
00641 if (symbol->section == &bfd_und_section
00642 && (symbol->flags & BSF_WEAK) == 0)
00643 return output_bfd ? bfd_reloc_continue : bfd_reloc_undefined;
00644
00645
00646
00647 if (symbol->section->name != input_section->name
00648 && output_bfd != (bfd *)NULL)
00649 return bfd_reloc_continue;
00650
00651 relocation = (target & 0x00ffffff) << 2;
00652 relocation = (relocation ^ 0x02000000) - 0x02000000;
00653 relocation += symbol->value;
00654 relocation += symbol->section->output_section->vma;
00655 relocation += symbol->section->output_offset;
00656 relocation += reloc_entry->addend;
00657 relocation -= input_section->output_section->vma;
00658 relocation -= input_section->output_offset;
00659 relocation -= addr;
00660
00661 if (relocation & 3)
00662 return bfd_reloc_overflow;
00663
00664
00665 if (relocation & 0x02000000)
00666 {
00667 if ((relocation & ~ (bfd_vma) 0x03ffffff) != ~ (bfd_vma) 0x03ffffff)
00668 flag = bfd_reloc_overflow;
00669 }
00670 else if (relocation & ~(bfd_vma) 0x03ffffff)
00671 flag = bfd_reloc_overflow;
00672
00673 target &= ~0x00ffffff;
00674 target |= (relocation >> 2) & 0x00ffffff;
00675 bfd_put_32 (abfd, (bfd_vma) target, (bfd_byte *) data + addr);
00676
00677
00678
00679 reloc_entry->howto = &aoutarm_std_reloc_howto[ARM_26D];
00680
00681 return flag;
00682 }
00683
00684 static bfd_reloc_status_type
00685 coff_thumb_pcrel_common (abfd, reloc_entry, symbol, data, input_section,
00686 output_bfd, error_message, btype)
00687 bfd *abfd;
00688 arelent *reloc_entry;
00689 asymbol *symbol;
00690 PTR data;
00691 asection *input_section;
00692 bfd *output_bfd;
00693 char **error_message ATTRIBUTE_UNUSED;
00694 thumb_pcrel_branchtype btype;
00695 {
00696 bfd_vma relocation = 0;
00697 bfd_size_type addr = reloc_entry->address;
00698 long target = bfd_get_32 (abfd, (bfd_byte *) data + addr);
00699 bfd_reloc_status_type flag = bfd_reloc_ok;
00700 bfd_vma dstmsk;
00701 bfd_vma offmsk;
00702 bfd_vma signbit;
00703
00704
00705
00706
00707 switch (btype)
00708 {
00709 case b9:
00710 dstmsk = 0x000000ff;
00711 offmsk = 0x000001fe;
00712 signbit = 0x00000100;
00713 break;
00714
00715 case b12:
00716 dstmsk = 0x000007ff;
00717 offmsk = 0x00000ffe;
00718 signbit = 0x00000800;
00719 break;
00720
00721 case b23:
00722 dstmsk = 0x07ff07ff;
00723 offmsk = 0x007fffff;
00724 signbit = 0x00400000;
00725 break;
00726
00727 default:
00728 abort ();
00729 }
00730
00731
00732 if (symbol->section == &bfd_und_section
00733 && (symbol->flags & BSF_WEAK) == 0)
00734 return output_bfd ? bfd_reloc_continue : bfd_reloc_undefined;
00735
00736
00737
00738 if (symbol->section->name != input_section->name
00739 && output_bfd != (bfd *)NULL)
00740 return bfd_reloc_continue;
00741
00742 switch (btype)
00743 {
00744 case b9:
00745 case b12:
00746 relocation = ((target & dstmsk) << 1);
00747 break;
00748
00749 case b23:
00750 if (bfd_big_endian (abfd))
00751 relocation = ((target & 0x7ff) << 1) | ((target & 0x07ff0000) >> 4);
00752 else
00753 relocation = ((target & 0x7ff) << 12) | ((target & 0x07ff0000) >> 15);
00754 break;
00755
00756 default:
00757 abort ();
00758 }
00759
00760 relocation = (relocation ^ signbit) - signbit;
00761 relocation += symbol->value;
00762 relocation += symbol->section->output_section->vma;
00763 relocation += symbol->section->output_offset;
00764 relocation += reloc_entry->addend;
00765 relocation -= input_section->output_section->vma;
00766 relocation -= input_section->output_offset;
00767 relocation -= addr;
00768
00769 if (relocation & 1)
00770 return bfd_reloc_overflow;
00771
00772
00773 if (relocation & signbit)
00774 {
00775 if ((relocation & ~offmsk) != ~offmsk)
00776 flag = bfd_reloc_overflow;
00777 }
00778 else if (relocation & ~offmsk)
00779 flag = bfd_reloc_overflow;
00780
00781 target &= ~dstmsk;
00782 switch (btype)
00783 {
00784 case b9:
00785 case b12:
00786 target |= (relocation >> 1);
00787 break;
00788
00789 case b23:
00790 if (bfd_big_endian (abfd))
00791 target |= (((relocation & 0xfff) >> 1)
00792 | ((relocation << 4) & 0x07ff0000));
00793 else
00794 target |= (((relocation & 0xffe) << 15)
00795 | ((relocation >> 12) & 0x7ff));
00796 break;
00797
00798 default:
00799 abort ();
00800 }
00801
00802 bfd_put_32 (abfd, (bfd_vma) target, (bfd_byte *) data + addr);
00803
00804
00805
00806 reloc_entry->howto = & aoutarm_std_reloc_howto [ARM_26D];
00807
00808
00809 return flag;
00810 }
00811
00812 #ifndef ARM_WINCE
00813 static bfd_reloc_status_type
00814 coff_thumb_pcrel_23 (abfd, reloc_entry, symbol, data, input_section,
00815 output_bfd, error_message)
00816 bfd *abfd;
00817 arelent *reloc_entry;
00818 asymbol *symbol;
00819 PTR data;
00820 asection *input_section;
00821 bfd *output_bfd;
00822 char **error_message;
00823 {
00824 return coff_thumb_pcrel_common (abfd, reloc_entry, symbol, data,
00825 input_section, output_bfd, error_message,
00826 b23);
00827 }
00828
00829 static bfd_reloc_status_type
00830 coff_thumb_pcrel_9 (abfd, reloc_entry, symbol, data, input_section,
00831 output_bfd, error_message)
00832 bfd *abfd;
00833 arelent *reloc_entry;
00834 asymbol *symbol;
00835 PTR data;
00836 asection *input_section;
00837 bfd *output_bfd;
00838 char **error_message;
00839 {
00840 return coff_thumb_pcrel_common (abfd, reloc_entry, symbol, data,
00841 input_section, output_bfd, error_message,
00842 b9);
00843 }
00844 #endif
00845
00846 static bfd_reloc_status_type
00847 coff_thumb_pcrel_12 (abfd, reloc_entry, symbol, data, input_section,
00848 output_bfd, error_message)
00849 bfd *abfd;
00850 arelent *reloc_entry;
00851 asymbol *symbol;
00852 PTR data;
00853 asection *input_section;
00854 bfd *output_bfd;
00855 char **error_message;
00856 {
00857 return coff_thumb_pcrel_common (abfd, reloc_entry, symbol, data,
00858 input_section, output_bfd, error_message,
00859 b12);
00860 }
00861
00862 static const struct reloc_howto_struct *
00863 coff_arm_reloc_type_lookup (abfd, code)
00864 bfd * abfd;
00865 bfd_reloc_code_real_type code;
00866 {
00867 #define ASTD(i,j) case i: return aoutarm_std_reloc_howto + j
00868
00869 if (code == BFD_RELOC_CTOR)
00870 switch (bfd_get_arch_info (abfd)->bits_per_address)
00871 {
00872 case 32:
00873 code = BFD_RELOC_32;
00874 break;
00875 default:
00876 return (const struct reloc_howto_struct *) 0;
00877 }
00878
00879 switch (code)
00880 {
00881 #ifdef ARM_WINCE
00882 ASTD (BFD_RELOC_32, ARM_32);
00883 ASTD (BFD_RELOC_RVA, ARM_RVA32);
00884 ASTD (BFD_RELOC_ARM_PCREL_BRANCH, ARM_26);
00885 ASTD (BFD_RELOC_THUMB_PCREL_BRANCH12, ARM_THUMB12);
00886 #else
00887 ASTD (BFD_RELOC_8, ARM_8);
00888 ASTD (BFD_RELOC_16, ARM_16);
00889 ASTD (BFD_RELOC_32, ARM_32);
00890 ASTD (BFD_RELOC_ARM_PCREL_BRANCH, ARM_26);
00891 ASTD (BFD_RELOC_ARM_PCREL_BLX, ARM_26);
00892 ASTD (BFD_RELOC_8_PCREL, ARM_DISP8);
00893 ASTD (BFD_RELOC_16_PCREL, ARM_DISP16);
00894 ASTD (BFD_RELOC_32_PCREL, ARM_DISP32);
00895 ASTD (BFD_RELOC_RVA, ARM_RVA32);
00896 ASTD (BFD_RELOC_THUMB_PCREL_BRANCH9, ARM_THUMB9);
00897 ASTD (BFD_RELOC_THUMB_PCREL_BRANCH12, ARM_THUMB12);
00898 ASTD (BFD_RELOC_THUMB_PCREL_BRANCH23, ARM_THUMB23);
00899 ASTD (BFD_RELOC_THUMB_PCREL_BLX, ARM_THUMB23);
00900 #endif
00901 default: return (const struct reloc_howto_struct *) 0;
00902 }
00903 }
00904
00905 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
00906 #define COFF_PAGE_SIZE 0x1000
00907
00908
00909 #define SELECT_RELOC(x,howto) { x.r_type = howto->type; }
00910 #define BADMAG(x) ARMBADMAG(x)
00911 #define ARM 1
00912
00913 #ifndef ARM_WINCE
00914
00915
00916 #define SWAP_IN_RELOC_OFFSET H_GET_32
00917 #define SWAP_OUT_RELOC_OFFSET H_PUT_32
00918 #endif
00919
00920
00921
00922
00923 struct coff_arm_link_hash_table
00924 {
00925
00926 struct coff_link_hash_table root;
00927
00928
00929 bfd_size_type thumb_glue_size;
00930
00931
00932 bfd_size_type arm_glue_size;
00933
00934
00935 bfd * bfd_of_glue_owner;
00936
00937
00938 int support_old_code;
00939 };
00940
00941
00942 #define coff_arm_hash_table(info) \
00943 ((struct coff_arm_link_hash_table *) ((info)->hash))
00944
00945
00946
00947 static struct bfd_link_hash_table *
00948 coff_arm_link_hash_table_create (abfd)
00949 bfd * abfd;
00950 {
00951 struct coff_arm_link_hash_table * ret;
00952 bfd_size_type amt = sizeof (struct coff_arm_link_hash_table);
00953
00954 ret = (struct coff_arm_link_hash_table *) bfd_malloc (amt);
00955 if (ret == (struct coff_arm_link_hash_table *) NULL)
00956 return NULL;
00957
00958 if (! _bfd_coff_link_hash_table_init
00959 (& ret->root, abfd, _bfd_coff_link_hash_newfunc))
00960 {
00961 free (ret);
00962 return (struct bfd_link_hash_table *) NULL;
00963 }
00964
00965 ret->thumb_glue_size = 0;
00966 ret->arm_glue_size = 0;
00967 ret->bfd_of_glue_owner = NULL;
00968
00969 return & ret->root.root;
00970 }
00971
00972 static void
00973 arm_emit_base_file_entry (info, output_bfd, input_section, reloc_offset)
00974 struct bfd_link_info *info;
00975 bfd *output_bfd;
00976 asection *input_section;
00977 bfd_vma reloc_offset;
00978 {
00979 bfd_vma addr = reloc_offset
00980 - input_section->vma
00981 + input_section->output_offset
00982 + input_section->output_section->vma;
00983
00984 if (coff_data (output_bfd)->pe)
00985 addr -= pe_data (output_bfd)->pe_opthdr.ImageBase;
00986 fwrite (& addr, 1, sizeof (addr), (FILE *) info->base_file);
00987
00988 }
00989
00990 #ifndef ARM_WINCE
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019 #define LOW_HI_ORDER 0xF800F000
01020 #define HI_LOW_ORDER 0xF000F800
01021
01022 static insn32
01023 insert_thumb_branch (br_insn, rel_off)
01024 insn32 br_insn;
01025 int rel_off;
01026 {
01027 unsigned int low_bits;
01028 unsigned int high_bits;
01029
01030 BFD_ASSERT((rel_off & 1) != 1);
01031
01032 rel_off >>= 1;
01033 low_bits = rel_off & 0x000007FF;
01034 high_bits = (rel_off >> 11) & 0x000007FF;
01035
01036 if ((br_insn & LOW_HI_ORDER) == LOW_HI_ORDER)
01037 br_insn = LOW_HI_ORDER | (low_bits << 16) | high_bits;
01038 else if ((br_insn & HI_LOW_ORDER) == HI_LOW_ORDER)
01039 br_insn = HI_LOW_ORDER | (high_bits << 16) | low_bits;
01040 else
01041
01042
01043 abort ();
01044
01045 return br_insn;
01046 }
01047
01048
01049 static struct coff_link_hash_entry *
01050 find_thumb_glue (info, name, input_bfd)
01051 struct bfd_link_info *info;
01052 const char *name;
01053 bfd *input_bfd;
01054 {
01055 char *tmp_name;
01056 struct coff_link_hash_entry *myh;
01057 bfd_size_type amt = strlen (name) + strlen (THUMB2ARM_GLUE_ENTRY_NAME) + 1;
01058
01059 tmp_name = (char *) bfd_malloc (amt);
01060
01061 BFD_ASSERT (tmp_name);
01062
01063 sprintf (tmp_name, THUMB2ARM_GLUE_ENTRY_NAME, name);
01064
01065 myh = coff_link_hash_lookup
01066 (coff_hash_table (info), tmp_name, FALSE, FALSE, TRUE);
01067
01068 if (myh == NULL)
01069
01070 _bfd_error_handler (_("%B: unable to find THUMB glue '%s' for `%s'"),
01071 input_bfd, tmp_name, name);
01072
01073 free (tmp_name);
01074
01075 return myh;
01076 }
01077 #endif
01078
01079 static struct coff_link_hash_entry *
01080 find_arm_glue (info, name, input_bfd)
01081 struct bfd_link_info *info;
01082 const char *name;
01083 bfd *input_bfd;
01084 {
01085 char *tmp_name;
01086 struct coff_link_hash_entry * myh;
01087 bfd_size_type amt = strlen (name) + strlen (ARM2THUMB_GLUE_ENTRY_NAME) + 1;
01088
01089 tmp_name = (char *) bfd_malloc (amt);
01090
01091 BFD_ASSERT (tmp_name);
01092
01093 sprintf (tmp_name, ARM2THUMB_GLUE_ENTRY_NAME, name);
01094
01095 myh = coff_link_hash_lookup
01096 (coff_hash_table (info), tmp_name, FALSE, FALSE, TRUE);
01097
01098 if (myh == NULL)
01099
01100 _bfd_error_handler (_("%B: unable to find ARM glue '%s' for `%s'"),
01101 input_bfd, tmp_name, name);
01102
01103 free (tmp_name);
01104
01105 return myh;
01106 }
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119 #define ARM2THUMB_GLUE_SIZE 12
01120 static const insn32 a2t1_ldr_insn = 0xe59fc000;
01121 static const insn32 a2t2_bx_r12_insn = 0xe12fff1c;
01122 static const insn32 a2t3_func_addr_insn = 0x00000001;
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142 #define THUMB2ARM_GLUE_SIZE (globals->support_old_code ? 20 : 8)
01143 static const insn16 t2a1_bx_pc_insn = 0x4778;
01144 static const insn16 t2a2_noop_insn = 0x46c0;
01145 static const insn32 t2a3_b_insn = 0xea000000;
01146
01147 static const insn16 t2a1_push_insn = 0xb540;
01148 static const insn16 t2a2_ldr_insn = 0x4e03;
01149 static const insn16 t2a3_mov_insn = 0x46fe;
01150 static const insn16 t2a4_bx_insn = 0x4730;
01151 static const insn32 t2a5_pop_insn = 0xe8bd4040;
01152 static const insn32 t2a6_bx_insn = 0xe12fff1e;
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195 static bfd_boolean
01196 coff_arm_relocate_section (output_bfd, info, input_bfd, input_section,
01197 contents, relocs, syms, sections)
01198 bfd *output_bfd;
01199 struct bfd_link_info *info;
01200 bfd *input_bfd;
01201 asection *input_section;
01202 bfd_byte *contents;
01203 struct internal_reloc *relocs;
01204 struct internal_syment *syms;
01205 asection **sections;
01206 {
01207 struct internal_reloc * rel;
01208 struct internal_reloc * relend;
01209 bfd_vma high_address = bfd_get_section_limit (input_bfd, input_section);
01210
01211 rel = relocs;
01212 relend = rel + input_section->reloc_count;
01213
01214 for (; rel < relend; rel++)
01215 {
01216 int done = 0;
01217 long symndx;
01218 struct coff_link_hash_entry * h;
01219 struct internal_syment * sym;
01220 bfd_vma addend;
01221 bfd_vma val;
01222 reloc_howto_type * howto;
01223 bfd_reloc_status_type rstat;
01224 bfd_vma h_val;
01225
01226 symndx = rel->r_symndx;
01227
01228 if (symndx == -1)
01229 {
01230 h = NULL;
01231 sym = NULL;
01232 }
01233 else
01234 {
01235 h = obj_coff_sym_hashes (input_bfd)[symndx];
01236 sym = syms + symndx;
01237 }
01238
01239
01240
01241
01242
01243
01244 if (sym != NULL && sym->n_scnum != 0)
01245 addend = - sym->n_value;
01246 else
01247 addend = 0;
01248
01249 howto = coff_rtype_to_howto (input_bfd, input_section, rel, h,
01250 sym, &addend);
01251 if (howto == NULL)
01252 return FALSE;
01253
01254
01255
01256
01257
01258
01259
01260 if (rel->r_type == ARM_26
01261 && h != NULL
01262 && info->relocatable
01263 && (h->root.type == bfd_link_hash_defined
01264 || h->root.type == bfd_link_hash_defweak)
01265 && (h->root.u.def.section->output_section
01266 == input_section->output_section))
01267 {
01268 static reloc_howto_type fake_arm26_reloc =
01269 HOWTO (ARM_26,
01270 2,
01271 2,
01272 24,
01273 TRUE,
01274 0,
01275 complain_overflow_signed,
01276 aoutarm_fix_pcrel_26 ,
01277 "ARM_26",
01278 TRUE,
01279 0x00ffffff,
01280 0x00ffffff,
01281 FALSE);
01282
01283 addend -= rel->r_vaddr - input_section->vma;
01284 #ifdef ARM_WINCE
01285
01286
01287 addend -= 8;
01288 #endif
01289 howto = &fake_arm26_reloc;
01290 }
01291
01292 #ifdef ARM_WINCE
01293
01294
01295 #endif
01296
01297
01298
01299
01300
01301 if (howto->pc_relative && howto->pcrel_offset)
01302 {
01303 if (info->relocatable)
01304 continue;
01305
01306
01307
01308
01309
01310 #ifdef ARM_COFF_BUGFIX
01311
01312
01313
01314
01315
01316
01317 if (sym != NULL && sym->n_scnum != 0)
01318 addend += sym->n_value;
01319 #endif
01320 }
01321
01322 val = 0;
01323
01324 if (h == NULL)
01325 {
01326 asection *sec;
01327
01328 if (symndx == -1)
01329 {
01330 sec = bfd_abs_section_ptr;
01331 val = 0;
01332 }
01333 else
01334 {
01335 sec = sections[symndx];
01336 val = (sec->output_section->vma
01337 + sec->output_offset
01338 + sym->n_value
01339 - sec->vma);
01340 }
01341 }
01342 else
01343 {
01344
01345
01346
01347
01348
01349 if (! info->relocatable
01350 && ( h->root.type == bfd_link_hash_defined
01351 || h->root.type == bfd_link_hash_defweak))
01352 {
01353 asection * h_sec = h->root.u.def.section;
01354 const char * name = h->root.root.string;
01355
01356
01357 h_val = (h->root.u.def.value
01358 + h_sec->output_section->vma
01359 + h_sec->output_offset);
01360
01361 if (howto->type == ARM_26)
01362 {
01363 if ( h->class == C_THUMBSTATFUNC
01364 || h->class == C_THUMBEXTFUNC)
01365 {
01366
01367 unsigned long int tmp;
01368 bfd_vma my_offset;
01369 asection * s;
01370 long int ret_offset;
01371 struct coff_link_hash_entry * myh;
01372 struct coff_arm_link_hash_table * globals;
01373
01374 myh = find_arm_glue (info, name, input_bfd);
01375 if (myh == NULL)
01376 return FALSE;
01377
01378 globals = coff_arm_hash_table (info);
01379
01380 BFD_ASSERT (globals != NULL);
01381 BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
01382
01383 my_offset = myh->root.u.def.value;
01384
01385 s = bfd_get_section_by_name (globals->bfd_of_glue_owner,
01386 ARM2THUMB_GLUE_SECTION_NAME);
01387 BFD_ASSERT (s != NULL);
01388 BFD_ASSERT (s->contents != NULL);
01389 BFD_ASSERT (s->output_section != NULL);
01390
01391 if ((my_offset & 0x01) == 0x01)
01392 {
01393 if (h_sec->owner != NULL
01394 && INTERWORK_SET (h_sec->owner)
01395 && ! INTERWORK_FLAG (h_sec->owner))
01396 _bfd_error_handler
01397
01398 (_("%B(%s): warning: interworking not enabled.\n"
01399 " first occurrence: %B: arm call to thumb"),
01400 h_sec->owner, input_bfd, name);
01401
01402 --my_offset;
01403 myh->root.u.def.value = my_offset;
01404
01405 bfd_put_32 (output_bfd, (bfd_vma) a2t1_ldr_insn,
01406 s->contents + my_offset);
01407
01408 bfd_put_32 (output_bfd, (bfd_vma) a2t2_bx_r12_insn,
01409 s->contents + my_offset + 4);
01410
01411
01412 bfd_put_32 (output_bfd, h_val | a2t3_func_addr_insn,
01413 s->contents + my_offset + 8);
01414
01415 if (info->base_file)
01416 arm_emit_base_file_entry (info, output_bfd, s,
01417 my_offset + 8);
01418
01419 }
01420
01421 BFD_ASSERT (my_offset <= globals->arm_glue_size);
01422
01423 tmp = bfd_get_32 (input_bfd, contents + rel->r_vaddr
01424 - input_section->vma);
01425
01426 tmp = tmp & 0xFF000000;
01427
01428
01429 ret_offset =
01430 s->output_offset
01431 + my_offset
01432 + s->output_section->vma
01433 - (input_section->output_offset
01434 + input_section->output_section->vma
01435 + rel->r_vaddr)
01436 - 8;
01437
01438 tmp = tmp | ((ret_offset >> 2) & 0x00FFFFFF);
01439
01440 bfd_put_32 (output_bfd, (bfd_vma) tmp,
01441 contents + rel->r_vaddr - input_section->vma);
01442 done = 1;
01443 }
01444 }
01445
01446 #ifndef ARM_WINCE
01447
01448 else if (howto->type == ARM_THUMB23)
01449 {
01450 if ( h->class == C_EXT
01451 || h->class == C_STAT
01452 || h->class == C_LABEL)
01453 {
01454
01455 asection * s = 0;
01456 bfd_vma my_offset;
01457 unsigned long int tmp;
01458 long int ret_offset;
01459 struct coff_link_hash_entry * myh;
01460 struct coff_arm_link_hash_table * globals;
01461
01462 myh = find_thumb_glue (info, name, input_bfd);
01463 if (myh == NULL)
01464 return FALSE;
01465
01466 globals = coff_arm_hash_table (info);
01467
01468 BFD_ASSERT (globals != NULL);
01469 BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
01470
01471 my_offset = myh->root.u.def.value;
01472
01473 s = bfd_get_section_by_name (globals->bfd_of_glue_owner,
01474 THUMB2ARM_GLUE_SECTION_NAME);
01475
01476 BFD_ASSERT (s != NULL);
01477 BFD_ASSERT (s->contents != NULL);
01478 BFD_ASSERT (s->output_section != NULL);
01479
01480 if ((my_offset & 0x01) == 0x01)
01481 {
01482 if (h_sec->owner != NULL
01483 && INTERWORK_SET (h_sec->owner)
01484 && ! INTERWORK_FLAG (h_sec->owner)
01485 && ! globals->support_old_code)
01486 _bfd_error_handler
01487
01488 (_("%B(%s): warning: interworking not enabled.\n"
01489 " first occurrence: %B: thumb call to arm\n"
01490 " consider relinking with --support-old-code enabled"),
01491 h_sec->owner, input_bfd, name);
01492
01493 -- my_offset;
01494 myh->root.u.def.value = my_offset;
01495
01496 if (globals->support_old_code)
01497 {
01498 bfd_put_16 (output_bfd, (bfd_vma) t2a1_push_insn,
01499 s->contents + my_offset);
01500
01501 bfd_put_16 (output_bfd, (bfd_vma) t2a2_ldr_insn,
01502 s->contents + my_offset + 2);
01503
01504 bfd_put_16 (output_bfd, (bfd_vma) t2a3_mov_insn,
01505 s->contents + my_offset + 4);
01506
01507 bfd_put_16 (output_bfd, (bfd_vma) t2a4_bx_insn,
01508 s->contents + my_offset + 6);
01509
01510 bfd_put_32 (output_bfd, (bfd_vma) t2a5_pop_insn,
01511 s->contents + my_offset + 8);
01512
01513 bfd_put_32 (output_bfd, (bfd_vma) t2a6_bx_insn,
01514 s->contents + my_offset + 12);
01515
01516
01517 bfd_put_32 (output_bfd, h_val,
01518 s->contents + my_offset + 16);
01519
01520 if (info->base_file)
01521 arm_emit_base_file_entry (info, output_bfd, s,
01522 my_offset + 16);
01523 }
01524 else
01525 {
01526 bfd_put_16 (output_bfd, (bfd_vma) t2a1_bx_pc_insn,
01527 s->contents + my_offset);
01528
01529 bfd_put_16 (output_bfd, (bfd_vma) t2a2_noop_insn,
01530 s->contents + my_offset + 2);
01531
01532 ret_offset =
01533 ((bfd_signed_vma) h_val)
01534 - ((bfd_signed_vma)
01535 (s->output_offset
01536 + my_offset
01537 + s->output_section->vma)
01538 + 4
01539 + 8);
01540
01541 bfd_put_32 (output_bfd,
01542 (bfd_vma) t2a3_b_insn | ((ret_offset >> 2) & 0x00FFFFFF),
01543 s->contents + my_offset + 4);
01544
01545 }
01546 }
01547
01548 BFD_ASSERT (my_offset <= globals->thumb_glue_size);
01549
01550
01551
01552 ret_offset =
01553 s->output_offset
01554 + my_offset
01555 - (input_section->output_offset
01556 + rel->r_vaddr)
01557 -4;
01558
01559 tmp = bfd_get_32 (input_bfd, contents + rel->r_vaddr
01560 - input_section->vma);
01561
01562 bfd_put_32 (output_bfd,
01563 (bfd_vma) insert_thumb_branch (tmp,
01564 ret_offset),
01565 contents + rel->r_vaddr - input_section->vma);
01566
01567 done = 1;
01568 }
01569 }
01570 #endif
01571 }
01572
01573
01574
01575
01576
01577 if (done)
01578 rstat = bfd_reloc_ok;
01579 else
01580 if ( h->root.type == bfd_link_hash_defined
01581 || h->root.type == bfd_link_hash_defweak)
01582 {
01583 asection *sec;
01584
01585 sec = h->root.u.def.section;
01586 val = (h->root.u.def.value
01587 + sec->output_section->vma
01588 + sec->output_offset);
01589 }
01590
01591 else if (! info->relocatable)
01592 {
01593 if (! ((*info->callbacks->undefined_symbol)
01594 (info, h->root.root.string, input_bfd, input_section,
01595 rel->r_vaddr - input_section->vma, TRUE)))
01596 return FALSE;
01597 }
01598 }
01599
01600 if (info->base_file)
01601 {
01602
01603 if (sym && pe_data(output_bfd)->in_reloc_p(output_bfd, howto))
01604 arm_emit_base_file_entry (info, output_bfd, input_section,
01605 rel->r_vaddr);
01606 }
01607
01608 if (done)
01609 rstat = bfd_reloc_ok;
01610 #ifndef ARM_WINCE
01611
01612 else if (! info->relocatable
01613 && howto->type == ARM_THUMB23)
01614 {
01615
01616
01617
01618
01619
01620
01621
01622
01623 bfd_vma address = rel->r_vaddr - input_section->vma;
01624
01625 if (address > high_address)
01626 rstat = bfd_reloc_outofrange;
01627 else
01628 {
01629 bfd_vma relocation = val + addend;
01630 int size = bfd_get_reloc_size (howto);
01631 bfd_boolean overflow = FALSE;
01632 bfd_byte *location = contents + address;
01633 bfd_vma x = bfd_get_32 (input_bfd, location);
01634 bfd_vma src_mask = 0x007FFFFE;
01635 bfd_signed_vma reloc_signed_max = (1 << (howto->bitsize - 1)) - 1;
01636 bfd_signed_vma reloc_signed_min = ~reloc_signed_max;
01637 bfd_vma check;
01638 bfd_signed_vma signed_check;
01639 bfd_vma add;
01640 bfd_signed_vma signed_add;
01641
01642 BFD_ASSERT (size == 4);
01643
01644
01645 relocation -= (input_section->output_section->vma
01646 + input_section->output_offset);
01647
01648
01649 relocation -= address;
01650
01651
01652
01653
01654
01655
01656 check = relocation >> howto->rightshift;
01657
01658
01659
01660 if ((bfd_signed_vma) relocation >= 0)
01661 signed_check = check;
01662 else
01663 signed_check = (check
01664 | ((bfd_vma) - 1
01665 & ~((bfd_vma) - 1 >> howto->rightshift)));
01666
01667
01668 if (bfd_big_endian (input_bfd))
01669 add = (((x) & 0x07ff0000) >> 4) | (((x) & 0x7ff) << 1);
01670 else
01671 add = ((((x) & 0x7ff) << 12) | (((x) & 0x07ff0000) >> 15));
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681 signed_add = add;
01682
01683 if ((add & (((~ src_mask) >> 1) & src_mask)) != 0)
01684 signed_add -= (((~ src_mask) >> 1) & src_mask) << 1;
01685
01686
01687
01688
01689 signed_check += signed_add;
01690 relocation += signed_add;
01691
01692 BFD_ASSERT (howto->complain_on_overflow == complain_overflow_signed);
01693
01694
01695 if ( signed_check > reloc_signed_max
01696 || signed_check < reloc_signed_min)
01697 overflow = TRUE;
01698
01699
01700
01701
01702
01703
01704 if (bfd_big_endian (input_bfd))
01705 {
01706 if ((x & 0x1800) == 0x0800 && (relocation & 0x02))
01707 relocation += 2;
01708 relocation = (((relocation & 0xffe) >> 1) | ((relocation << 4) & 0x07ff0000));
01709 }
01710 else
01711 {
01712 if ((x & 0x18000000) == 0x08000000 && (relocation & 0x02))
01713 relocation += 2;
01714 relocation = (((relocation & 0xffe) << 15) | ((relocation >> 12) & 0x7ff));
01715 }
01716
01717
01718 x = ((x & ~howto->dst_mask) | relocation);
01719
01720
01721 bfd_put_32 (input_bfd, x, location);
01722
01723 rstat = overflow ? bfd_reloc_overflow : bfd_reloc_ok;
01724 }
01725 }
01726 #endif
01727 else
01728 if (info->relocatable && ! howto->partial_inplace)
01729 rstat = bfd_reloc_ok;
01730 else
01731 rstat = _bfd_final_link_relocate (howto, input_bfd, input_section,
01732 contents,
01733 rel->r_vaddr - input_section->vma,
01734 val, addend);
01735
01736
01737
01738
01739 if (! info->relocatable
01740 && (rel->r_type == ARM_32 || rel->r_type == ARM_RVA32))
01741 {
01742
01743
01744
01745 int patchit = FALSE;
01746
01747 if (h != NULL
01748 && ( h->class == C_THUMBSTATFUNC
01749 || h->class == C_THUMBEXTFUNC))
01750 {
01751 patchit = TRUE;
01752 }
01753 else if (sym != NULL
01754 && sym->n_scnum > N_UNDEF)
01755 {
01756
01757
01758 if ( sym->n_sclass == C_THUMBSTATFUNC
01759 || sym->n_sclass == C_THUMBEXTFUNC)
01760 patchit = TRUE;
01761 }
01762
01763 if (patchit)
01764 {
01765 bfd_byte * location = contents + rel->r_vaddr - input_section->vma;
01766 bfd_vma x = bfd_get_32 (input_bfd, location);
01767
01768 bfd_put_32 (input_bfd, x | 1, location);
01769 }
01770 }
01771
01772 switch (rstat)
01773 {
01774 default:
01775 abort ();
01776 case bfd_reloc_ok:
01777 break;
01778 case bfd_reloc_outofrange:
01779 (*_bfd_error_handler)
01780 (_("%B: bad reloc address 0x%lx in section `%A'"),
01781 input_bfd, input_section, (unsigned long) rel->r_vaddr);
01782 return FALSE;
01783 case bfd_reloc_overflow:
01784 {
01785 const char *name;
01786 char buf[SYMNMLEN + 1];
01787
01788 if (symndx == -1)
01789 name = "*ABS*";
01790 else if (h != NULL)
01791 name = NULL;
01792 else
01793 {
01794 name = _bfd_coff_internal_syment_name (input_bfd, sym, buf);
01795 if (name == NULL)
01796 return FALSE;
01797 }
01798
01799 if (! ((*info->callbacks->reloc_overflow)
01800 (info, (h ? &h->root : NULL), name, howto->name,
01801 (bfd_vma) 0, input_bfd, input_section,
01802 rel->r_vaddr - input_section->vma)))
01803 return FALSE;
01804 }
01805 }
01806 }
01807
01808 return TRUE;
01809 }
01810
01811 #ifndef COFF_IMAGE_WITH_PE
01812
01813 bfd_boolean
01814 bfd_arm_allocate_interworking_sections (info)
01815 struct bfd_link_info * info;
01816 {
01817 asection * s;
01818 bfd_byte * foo;
01819 struct coff_arm_link_hash_table * globals;
01820
01821 globals = coff_arm_hash_table (info);
01822
01823 BFD_ASSERT (globals != NULL);
01824
01825 if (globals->arm_glue_size != 0)
01826 {
01827 BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
01828
01829 s = bfd_get_section_by_name
01830 (globals->bfd_of_glue_owner, ARM2THUMB_GLUE_SECTION_NAME);
01831
01832 BFD_ASSERT (s != NULL);
01833
01834 foo = (bfd_byte *) bfd_alloc (globals->bfd_of_glue_owner,
01835 globals->arm_glue_size);
01836
01837 s->size = globals->arm_glue_size;
01838 s->contents = foo;
01839 }
01840
01841 if (globals->thumb_glue_size != 0)
01842 {
01843 BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
01844
01845 s = bfd_get_section_by_name
01846 (globals->bfd_of_glue_owner, THUMB2ARM_GLUE_SECTION_NAME);
01847
01848 BFD_ASSERT (s != NULL);
01849
01850 foo = (bfd_byte *) bfd_alloc (globals->bfd_of_glue_owner,
01851 globals->thumb_glue_size);
01852
01853 s->size = globals->thumb_glue_size;
01854 s->contents = foo;
01855 }
01856
01857 return TRUE;
01858 }
01859
01860 static void
01861 record_arm_to_thumb_glue (info, h)
01862 struct bfd_link_info * info;
01863 struct coff_link_hash_entry * h;
01864 {
01865 const char * name = h->root.root.string;
01866 register asection * s;
01867 char * tmp_name;
01868 struct coff_link_hash_entry * myh;
01869 struct bfd_link_hash_entry * bh;
01870 struct coff_arm_link_hash_table * globals;
01871 bfd_vma val;
01872 bfd_size_type amt;
01873
01874 globals = coff_arm_hash_table (info);
01875
01876 BFD_ASSERT (globals != NULL);
01877 BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
01878
01879 s = bfd_get_section_by_name
01880 (globals->bfd_of_glue_owner, ARM2THUMB_GLUE_SECTION_NAME);
01881
01882 BFD_ASSERT (s != NULL);
01883
01884 amt = strlen (name) + strlen (ARM2THUMB_GLUE_ENTRY_NAME) + 1;
01885 tmp_name = (char *) bfd_malloc (amt);
01886
01887 BFD_ASSERT (tmp_name);
01888
01889 sprintf (tmp_name, ARM2THUMB_GLUE_ENTRY_NAME, name);
01890
01891 myh = coff_link_hash_lookup
01892 (coff_hash_table (info), tmp_name, FALSE, FALSE, TRUE);
01893
01894 if (myh != NULL)
01895 {
01896 free (tmp_name);
01897 return;
01898 }
01899
01900
01901
01902
01903
01904 bh = NULL;
01905 val = globals->arm_glue_size + 1;
01906 bfd_coff_link_add_one_symbol (info, globals->bfd_of_glue_owner, tmp_name,
01907 BSF_GLOBAL, s, val, NULL, TRUE, FALSE, &bh);
01908
01909 free (tmp_name);
01910
01911 globals->arm_glue_size += ARM2THUMB_GLUE_SIZE;
01912
01913 return;
01914 }
01915
01916 #ifndef ARM_WINCE
01917 static void
01918 record_thumb_to_arm_glue (info, h)
01919 struct bfd_link_info * info;
01920 struct coff_link_hash_entry * h;
01921 {
01922 const char * name = h->root.root.string;
01923 register asection * s;
01924 char * tmp_name;
01925 struct coff_link_hash_entry * myh;
01926 struct bfd_link_hash_entry * bh;
01927 struct coff_arm_link_hash_table * globals;
01928 bfd_vma val;
01929 bfd_size_type amt;
01930
01931 globals = coff_arm_hash_table (info);
01932
01933 BFD_ASSERT (globals != NULL);
01934 BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
01935
01936 s = bfd_get_section_by_name
01937 (globals->bfd_of_glue_owner, THUMB2ARM_GLUE_SECTION_NAME);
01938
01939 BFD_ASSERT (s != NULL);
01940
01941 amt = strlen (name) + strlen (THUMB2ARM_GLUE_ENTRY_NAME) + 1;
01942 tmp_name = (char *) bfd_malloc (amt);
01943
01944 BFD_ASSERT (tmp_name);
01945
01946 sprintf (tmp_name, THUMB2ARM_GLUE_ENTRY_NAME, name);
01947
01948 myh = coff_link_hash_lookup
01949 (coff_hash_table (info), tmp_name, FALSE, FALSE, TRUE);
01950
01951 if (myh != NULL)
01952 {
01953 free (tmp_name);
01954 return;
01955 }
01956
01957 bh = NULL;
01958 val = globals->thumb_glue_size + 1;
01959 bfd_coff_link_add_one_symbol (info, globals->bfd_of_glue_owner, tmp_name,
01960 BSF_GLOBAL, s, val, NULL, TRUE, FALSE, &bh);
01961
01962
01963 myh = (struct coff_link_hash_entry *) bh;
01964 myh->class = C_THUMBEXTFUNC;
01965
01966 free (tmp_name);
01967
01968
01969
01970 #define CHANGE_TO_ARM "__%s_change_to_arm"
01971 #define BACK_FROM_ARM "__%s_back_from_arm"
01972
01973 amt = strlen (name) + strlen (CHANGE_TO_ARM) + 1;
01974 tmp_name = (char *) bfd_malloc (amt);
01975
01976 BFD_ASSERT (tmp_name);
01977
01978 sprintf (tmp_name, globals->support_old_code ? BACK_FROM_ARM : CHANGE_TO_ARM, name);
01979
01980 bh = NULL;
01981 val = globals->thumb_glue_size + (globals->support_old_code ? 8 : 4);
01982 bfd_coff_link_add_one_symbol (info, globals->bfd_of_glue_owner, tmp_name,
01983 BSF_LOCAL, s, val, NULL, TRUE, FALSE, &bh);
01984
01985 free (tmp_name);
01986
01987 globals->thumb_glue_size += THUMB2ARM_GLUE_SIZE;
01988
01989 return;
01990 }
01991 #endif
01992
01993
01994
01995
01996
01997 bfd_boolean
01998 bfd_arm_get_bfd_for_interworking (abfd, info)
01999 bfd * abfd;
02000 struct bfd_link_info * info;
02001 {
02002 struct coff_arm_link_hash_table * globals;
02003 flagword flags;
02004 asection * sec;
02005
02006
02007
02008 if (info->relocatable)
02009 return TRUE;
02010
02011 globals = coff_arm_hash_table (info);
02012
02013 BFD_ASSERT (globals != NULL);
02014
02015 if (globals->bfd_of_glue_owner != NULL)
02016 return TRUE;
02017
02018 sec = bfd_get_section_by_name (abfd, ARM2THUMB_GLUE_SECTION_NAME);
02019
02020 if (sec == NULL)
02021 {
02022 flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_CODE | SEC_READONLY;
02023
02024 sec = bfd_make_section (abfd, ARM2THUMB_GLUE_SECTION_NAME);
02025
02026 if (sec == NULL
02027 || ! bfd_set_section_flags (abfd, sec, flags)
02028 || ! bfd_set_section_alignment (abfd, sec, 2))
02029 return FALSE;
02030 }
02031
02032 sec = bfd_get_section_by_name (abfd, THUMB2ARM_GLUE_SECTION_NAME);
02033
02034 if (sec == NULL)
02035 {
02036 flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_CODE | SEC_READONLY;
02037
02038 sec = bfd_make_section (abfd, THUMB2ARM_GLUE_SECTION_NAME);
02039
02040 if (sec == NULL
02041 || ! bfd_set_section_flags (abfd, sec, flags)
02042 || ! bfd_set_section_alignment (abfd, sec, 2))
02043 return FALSE;
02044 }
02045
02046
02047 globals->bfd_of_glue_owner = abfd;
02048
02049 return TRUE;
02050 }
02051
02052 bfd_boolean
02053 bfd_arm_process_before_allocation (abfd, info, support_old_code)
02054 bfd * abfd;
02055 struct bfd_link_info * info;
02056 int support_old_code;
02057 {
02058 asection * sec;
02059 struct coff_arm_link_hash_table * globals;
02060
02061
02062
02063 if (info->relocatable)
02064 return TRUE;
02065
02066
02067
02068
02069 _bfd_coff_get_external_symbols (abfd);
02070
02071 globals = coff_arm_hash_table (info);
02072
02073 BFD_ASSERT (globals != NULL);
02074 BFD_ASSERT (globals->bfd_of_glue_owner != NULL);
02075
02076 globals->support_old_code = support_old_code;
02077
02078
02079 sec = abfd->sections;
02080
02081 if (sec == NULL)
02082 return TRUE;
02083
02084 for (; sec != NULL; sec = sec->next)
02085 {
02086 struct internal_reloc * i;
02087 struct internal_reloc * rel;
02088
02089 if (sec->reloc_count == 0)
02090 continue;
02091
02092
02093
02094
02095 i = _bfd_coff_read_internal_relocs (abfd, sec, 1, 0, 0, 0);
02096
02097 BFD_ASSERT (i != 0);
02098
02099 for (rel = i; rel < i + sec->reloc_count; ++rel)
02100 {
02101 unsigned short r_type = rel->r_type;
02102 long symndx;
02103 struct coff_link_hash_entry * h;
02104
02105 symndx = rel->r_symndx;
02106
02107
02108 if (symndx == -1)
02109 continue;
02110
02111
02112 if (symndx >= obj_conv_table_size (abfd))
02113 {
02114 _bfd_error_handler (_("%B: illegal symbol index in reloc: %d"),
02115 abfd, symndx);
02116 continue;
02117 }
02118
02119 h = obj_coff_sym_hashes (abfd)[symndx];
02120
02121
02122
02123 if (h == NULL)
02124 continue;
02125
02126 switch (r_type)
02127 {
02128 case ARM_26:
02129
02130
02131
02132
02133 if (h->class == C_THUMBEXTFUNC)
02134 record_arm_to_thumb_glue (info, h);
02135 break;
02136
02137 #ifndef ARM_WINCE
02138 case ARM_THUMB23:
02139
02140
02141
02142
02143
02144
02145
02146
02147 switch (h->class)
02148 {
02149 case C_EXT:
02150 case C_STAT:
02151 case C_LABEL:
02152 record_thumb_to_arm_glue (info, h);
02153 break;
02154 default:
02155 ;
02156 }
02157 break;
02158 #endif
02159
02160 default:
02161 break;
02162 }
02163 }
02164 }
02165
02166 return TRUE;
02167 }
02168
02169 #endif
02170
02171 #define coff_bfd_reloc_type_lookup coff_arm_reloc_type_lookup
02172 #define coff_relocate_section coff_arm_relocate_section
02173 #define coff_bfd_is_local_label_name coff_arm_is_local_label_name
02174 #define coff_adjust_symndx coff_arm_adjust_symndx
02175 #define coff_link_output_has_begun coff_arm_link_output_has_begun
02176 #define coff_final_link_postscript coff_arm_final_link_postscript
02177 #define coff_bfd_merge_private_bfd_data coff_arm_merge_private_bfd_data
02178 #define coff_bfd_print_private_bfd_data coff_arm_print_private_bfd_data
02179 #define coff_bfd_set_private_flags _bfd_coff_arm_set_private_flags
02180 #define coff_bfd_copy_private_bfd_data coff_arm_copy_private_bfd_data
02181 #define coff_bfd_link_hash_table_create coff_arm_link_hash_table_create
02182
02183
02184
02185
02186 static bfd_boolean
02187 coff_arm_adjust_symndx (obfd, info, ibfd, sec, irel, adjustedp)
02188 bfd *obfd ATTRIBUTE_UNUSED;
02189 struct bfd_link_info *info ATTRIBUTE_UNUSED;
02190 bfd *ibfd;
02191 asection *sec;
02192 struct internal_reloc *irel;
02193 bfd_boolean *adjustedp;
02194 {
02195 if (irel->r_type == ARM_26)
02196 {
02197 struct coff_link_hash_entry *h;
02198
02199 h = obj_coff_sym_hashes (ibfd)[irel->r_symndx];
02200 if (h != NULL
02201 && (h->root.type == bfd_link_hash_defined
02202 || h->root.type == bfd_link_hash_defweak)
02203 && h->root.u.def.section->output_section == sec->output_section)
02204 irel->r_type = ARM_26D;
02205 }
02206 *adjustedp = FALSE;
02207 return TRUE;
02208 }
02209
02210
02211
02212
02213
02214
02215 static bfd_boolean
02216 coff_arm_merge_private_bfd_data (ibfd, obfd)
02217 bfd * ibfd;
02218 bfd * obfd;
02219 {
02220 BFD_ASSERT (ibfd != NULL && obfd != NULL);
02221
02222 if (ibfd == obfd)
02223 return TRUE;
02224
02225
02226
02227
02228 if ( ibfd->xvec->flavour != bfd_target_coff_flavour
02229 || obfd->xvec->flavour != bfd_target_coff_flavour)
02230 return TRUE;
02231
02232
02233
02234 if (! bfd_arm_merge_machines (ibfd, obfd))
02235 return FALSE;
02236
02237
02238 if (APCS_SET (ibfd))
02239 {
02240 if (APCS_SET (obfd))
02241 {
02242
02243 if (APCS_26_FLAG (obfd) != APCS_26_FLAG (ibfd))
02244 {
02245 _bfd_error_handler
02246
02247 (_("ERROR: %B is compiled for APCS-%d, whereas %B is compiled for APCS-%d"),
02248 ibfd, obfd,
02249 APCS_26_FLAG (ibfd) ? 26 : 32,
02250 APCS_26_FLAG (obfd) ? 26 : 32
02251 );
02252
02253 bfd_set_error (bfd_error_wrong_format);
02254 return FALSE;
02255 }
02256
02257 if (APCS_FLOAT_FLAG (obfd) != APCS_FLOAT_FLAG (ibfd))
02258 {
02259 const char *msg;
02260
02261 if (APCS_FLOAT_FLAG (ibfd))
02262
02263 msg = _("ERROR: %B passes floats in float registers, whereas %B passes them in integer registers");
02264 else
02265
02266 msg = _("ERROR: %B passes floats in integer registers, whereas %B passes them in float registers");
02267
02268 _bfd_error_handler (msg, ibfd, obfd);
02269
02270 bfd_set_error (bfd_error_wrong_format);
02271 return FALSE;
02272 }
02273
02274 if (PIC_FLAG (obfd) != PIC_FLAG (ibfd))
02275 {
02276 const char * msg;
02277
02278 if (PIC_FLAG (ibfd))
02279
02280 msg = _("ERROR: %B is compiled as position independent code, whereas target %B is absolute position");
02281 else
02282
02283 msg = _("ERROR: %B is compiled as absolute position code, whereas target %B is position independent");
02284 _bfd_error_handler (msg, ibfd, obfd);
02285
02286 bfd_set_error (bfd_error_wrong_format);
02287 return FALSE;
02288 }
02289 }
02290 else
02291 {
02292 SET_APCS_FLAGS (obfd, APCS_26_FLAG (ibfd) | APCS_FLOAT_FLAG (ibfd) | PIC_FLAG (ibfd));
02293
02294
02295 bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), bfd_get_mach (ibfd));
02296 }
02297 }
02298
02299
02300 if (INTERWORK_SET (ibfd))
02301 {
02302 if (INTERWORK_SET (obfd))
02303 {
02304
02305 if (INTERWORK_FLAG (obfd) != INTERWORK_FLAG (ibfd))
02306 {
02307 const char * msg;
02308
02309 if (INTERWORK_FLAG (ibfd))
02310
02311 msg = _("Warning: %B supports interworking, whereas %B does not");
02312 else
02313
02314 msg = _("Warning: %B does not support interworking, whereas %B does");
02315
02316 _bfd_error_handler (msg, ibfd, obfd);
02317 }
02318 }
02319 else
02320 {
02321 SET_INTERWORK_FLAG (obfd, INTERWORK_FLAG (ibfd));
02322 }
02323 }
02324
02325 return TRUE;
02326 }
02327
02328
02329
02330 static bfd_boolean
02331 coff_arm_print_private_bfd_data (abfd, ptr)
02332 bfd * abfd;
02333 PTR ptr;
02334 {
02335 FILE * file = (FILE *) ptr;
02336
02337 BFD_ASSERT (abfd != NULL && ptr != NULL);
02338
02339
02340 fprintf (file, _("private flags = %x:"), coff_data (abfd)->flags);
02341
02342 if (APCS_SET (abfd))
02343 {
02344
02345 fprintf (file, " [APCS-%d]", APCS_26_FLAG (abfd) ? 26 : 32);
02346
02347 if (APCS_FLOAT_FLAG (abfd))
02348 fprintf (file, _(" [floats passed in float registers]"));
02349 else
02350 fprintf (file, _(" [floats passed in integer registers]"));
02351
02352 if (PIC_FLAG (abfd))
02353 fprintf (file, _(" [position independent]"));
02354 else
02355 fprintf (file, _(" [absolute position]"));
02356 }
02357
02358 if (! INTERWORK_SET (abfd))
02359 fprintf (file, _(" [interworking flag not initialised]"));
02360 else if (INTERWORK_FLAG (abfd))
02361 fprintf (file, _(" [interworking supported]"));
02362 else
02363 fprintf (file, _(" [interworking not supported]"));
02364
02365 fputc ('\n', file);
02366
02367 return TRUE;
02368 }
02369
02370
02371
02372
02373
02374
02375
02376
02377 static bfd_boolean
02378 _bfd_coff_arm_set_private_flags (abfd, flags)
02379 bfd * abfd;
02380 flagword flags;
02381 {
02382 flagword flag;
02383
02384 BFD_ASSERT (abfd != NULL);
02385
02386 flag = (flags & F_APCS26) ? F_APCS_26 : 0;
02387
02388
02389
02390 if (APCS_SET (abfd)
02391 && ( (APCS_26_FLAG (abfd) != flag)
02392 || (APCS_FLOAT_FLAG (abfd) != (flags & F_APCS_FLOAT))
02393 || (PIC_FLAG (abfd) != (flags & F_PIC))
02394 ))
02395 return FALSE;
02396
02397 flag |= (flags & (F_APCS_FLOAT | F_PIC));
02398
02399 SET_APCS_FLAGS (abfd, flag);
02400
02401 flag = (flags & F_INTERWORK);
02402
02403
02404
02405
02406
02407 if (INTERWORK_SET (abfd) && (INTERWORK_FLAG (abfd) != flag))
02408 {
02409 if (flag)
02410
02411 _bfd_error_handler (_("Warning: Not setting interworking flag of %B since it has already been specified as non-interworking"),
02412 abfd);
02413 else
02414
02415 _bfd_error_handler (_("Warning: Clearing the interworking flag of %B due to outside request"),
02416 abfd);
02417 flag = 0;
02418 }
02419
02420 SET_INTERWORK_FLAG (abfd, flag);
02421
02422 return TRUE;
02423 }
02424
02425
02426
02427
02428 static bfd_boolean
02429 coff_arm_copy_private_bfd_data (src, dest)
02430 bfd * src;
02431 bfd * dest;
02432 {
02433 BFD_ASSERT (src != NULL && dest != NULL);
02434
02435 if (src == dest)
02436 return TRUE;
02437
02438
02439
02440 if (src->xvec != dest->xvec)
02441 return TRUE;
02442
02443
02444 if (APCS_SET (src))
02445 {
02446 if (APCS_SET (dest))
02447 {
02448
02449 if (APCS_26_FLAG (dest) != APCS_26_FLAG (src))
02450 return FALSE;
02451
02452 if (APCS_FLOAT_FLAG (dest) != APCS_FLOAT_FLAG (src))
02453 return FALSE;
02454
02455 if (PIC_FLAG (dest) != PIC_FLAG (src))
02456 return FALSE;
02457 }
02458 else
02459 SET_APCS_FLAGS (dest, APCS_26_FLAG (src) | APCS_FLOAT_FLAG (src)
02460 | PIC_FLAG (src));
02461 }
02462
02463 if (INTERWORK_SET (src))
02464 {
02465 if (INTERWORK_SET (dest))
02466 {
02467
02468
02469 if (INTERWORK_FLAG (dest) != INTERWORK_FLAG (src))
02470 {
02471 if (INTERWORK_FLAG (dest))
02472 {
02473
02474 _bfd_error_handler (("\
02475 Warning: Clearing the interworking flag of %B because non-interworking code in %B has been linked with it"),
02476 dest, src);
02477 }
02478
02479 SET_INTERWORK_FLAG (dest, 0);
02480 }
02481 }
02482 else
02483 {
02484 SET_INTERWORK_FLAG (dest, INTERWORK_FLAG (src));
02485 }
02486 }
02487
02488 return TRUE;
02489 }
02490
02491
02492
02493 #define LOCAL_LABEL_PREFIX ""
02494 #ifndef USER_LABEL_PREFIX
02495 #define USER_LABEL_PREFIX "_"
02496 #endif
02497
02498
02499
02500
02501
02502
02503 static bfd_boolean
02504 coff_arm_is_local_label_name (abfd, name)
02505 bfd * abfd ATTRIBUTE_UNUSED;
02506 const char * name;
02507 {
02508 #ifdef USER_LABEL_PREFIX
02509 if (USER_LABEL_PREFIX[0] != 0)
02510 {
02511 size_t len = strlen (USER_LABEL_PREFIX);
02512
02513 if (strncmp (name, USER_LABEL_PREFIX, len) == 0)
02514 return FALSE;
02515 }
02516 #endif
02517
02518 #ifdef LOCAL_LABEL_PREFIX
02519
02520
02521
02522 if (LOCAL_LABEL_PREFIX[0] != 0)
02523 {
02524 size_t len = strlen (LOCAL_LABEL_PREFIX);
02525
02526 if (strncmp (name, LOCAL_LABEL_PREFIX, len) != 0)
02527 return FALSE;
02528
02529
02530 name += len;
02531 }
02532 #endif
02533
02534 return name[0] == 'L';
02535 }
02536
02537
02538
02539
02540
02541
02542
02543
02544
02545 static bfd_boolean
02546 coff_arm_link_output_has_begun (sub, info)
02547 bfd * sub;
02548 struct coff_final_link_info * info;
02549 {
02550 return (sub->output_has_begun
02551 || sub == coff_arm_hash_table (info->info)->bfd_of_glue_owner);
02552 }
02553
02554 static bfd_boolean
02555 coff_arm_final_link_postscript (abfd, pfinfo)
02556 bfd * abfd ATTRIBUTE_UNUSED;
02557 struct coff_final_link_info * pfinfo;
02558 {
02559 struct coff_arm_link_hash_table * globals;
02560
02561 globals = coff_arm_hash_table (pfinfo->info);
02562
02563 BFD_ASSERT (globals != NULL);
02564
02565 if (globals->bfd_of_glue_owner != NULL)
02566 {
02567 if (! _bfd_coff_link_input_bfd (pfinfo, globals->bfd_of_glue_owner))
02568 return FALSE;
02569
02570 globals->bfd_of_glue_owner->output_has_begun = TRUE;
02571 }
02572
02573 return bfd_arm_update_notes (abfd, ARM_NOTE_SECTION);
02574 }
02575
02576 #include "coffcode.h"
02577
02578 #ifndef TARGET_LITTLE_SYM
02579 #define TARGET_LITTLE_SYM armcoff_little_vec
02580 #endif
02581 #ifndef TARGET_LITTLE_NAME
02582 #define TARGET_LITTLE_NAME "coff-arm-little"
02583 #endif
02584 #ifndef TARGET_BIG_SYM
02585 #define TARGET_BIG_SYM armcoff_big_vec
02586 #endif
02587 #ifndef TARGET_BIG_NAME
02588 #define TARGET_BIG_NAME "coff-arm-big"
02589 #endif
02590
02591 #ifndef TARGET_UNDERSCORE
02592 #define TARGET_UNDERSCORE 0
02593 #endif
02594
02595 #ifndef EXTRA_S_FLAGS
02596 #ifdef COFF_WITH_PE
02597 #define EXTRA_S_FLAGS (SEC_CODE | SEC_LINK_ONCE | SEC_LINK_DUPLICATES)
02598 #else
02599 #define EXTRA_S_FLAGS SEC_CODE
02600 #endif
02601 #endif
02602
02603
02604 extern const bfd_target TARGET_BIG_SYM ;
02605
02606
02607 CREATE_LITTLE_COFF_TARGET_VEC (TARGET_LITTLE_SYM, TARGET_LITTLE_NAME, D_PAGED, EXTRA_S_FLAGS, TARGET_UNDERSCORE, & TARGET_BIG_SYM, COFF_SWAP_TABLE)
02608 CREATE_BIG_COFF_TARGET_VEC (TARGET_BIG_SYM, TARGET_BIG_NAME, D_PAGED, EXTRA_S_FLAGS, TARGET_UNDERSCORE, & TARGET_LITTLE_SYM, COFF_SWAP_TABLE)