Revisão | 7d37558a1c3f7b3b67022872a27b5e4e71c9e2e4 (tree) |
---|---|
Hora | 2022-12-08 12:30:02 |
Autor | Yoshinori Sato <ysato@user...> |
Commiter | Yoshinori Sato |
wip: bfd rx-fdpic
Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
@@ -4441,6 +4441,9 @@ number for the SBIC, SBIS, SBI and CBI instructions */ | ||
4441 | 4441 | BFD_RELOC_RX_GOTOFF, |
4442 | 4442 | BFD_RELOC_RX_PLT, |
4443 | 4443 | BFD_RELOC_RX_GOTPC, |
4444 | + BFD_RELOC_RX_GOTFUNCDESC, | |
4445 | + BFD_RELOC_RX_GOTOFFFUNCDESC, | |
4446 | + BFD_RELOC_RX_FUNCDESC, | |
4444 | 4447 | |
4445 | 4448 | /* Direct 12 bit. */ |
4446 | 4449 | BFD_RELOC_390_12, |
@@ -39,6 +39,16 @@ char * rx_get_reloc (long); | ||
39 | 39 | void rx_dump_symtab (bfd *, void *, void *); |
40 | 40 | #endif |
41 | 41 | |
42 | +/* Return true if OUTPUT_BFD is an FDPIC object. */ | |
43 | + | |
44 | +static bool | |
45 | +fdpic_object_p (bfd *abfd ATTRIBUTE_UNUSED) | |
46 | +{ | |
47 | + extern const bfd_target rx_elf32_linux_le_vec; | |
48 | + | |
49 | + return (abfd->xvec == &rx_elf32_linux_le_vec); | |
50 | +} | |
51 | + | |
42 | 52 | #define RXREL(n,sz,bit,shift,complain,pcrel) \ |
43 | 53 | HOWTO (R_RX_##n, shift, sz, bit, pcrel, 0, complain_overflow_ ## complain, \ |
44 | 54 | bfd_elf_generic_reloc, "R_RX_" #n, false, 0, ~0, false) |
@@ -76,15 +86,11 @@ static reloc_howto_type rx_elf_howto_table [] = | ||
76 | 86 | RXREL (RELATIVE, 2, 32, 0, bitfield, false), |
77 | 87 | RXREL (GOTOFF, 2, 32, 0, bitfield, false), |
78 | 88 | RXREL (GOTPC, 2, 32, 0, bitfield, false), |
89 | + RXREL (GOTFUNCDESC, 2, 32, 0, signed, false), | |
90 | + RXREL (GOTOFFFUNCDESC, 2, 32, 0, signed, false), | |
91 | + RXREL (FUNCDESC, 2, 32, 0, signed, false), | |
92 | + RXREL (FUNCDESC_VALUE, 2, 64, 0, signed, false), | |
79 | 93 | |
80 | - EMPTY_HOWTO (0x17), | |
81 | - EMPTY_HOWTO (0x18), | |
82 | - EMPTY_HOWTO (0x19), | |
83 | - EMPTY_HOWTO (0x1a), | |
84 | - EMPTY_HOWTO (0x1b), | |
85 | - EMPTY_HOWTO (0x1c), | |
86 | - EMPTY_HOWTO (0x1d), | |
87 | - EMPTY_HOWTO (0x1e), | |
88 | 94 | EMPTY_HOWTO (0x1f), |
89 | 95 | |
90 | 96 | RXREL (RH_3_PCREL, 1, 3, 0, signed, true), |
@@ -239,6 +245,18 @@ static reloc_howto_type rx_elf_howto_table [] = | ||
239 | 245 | RXREL (OPramtop, 4, 32, 0, dont, false) |
240 | 246 | }; |
241 | 247 | |
248 | +/* FDPIC binaries have a default 128K stack. */ | |
249 | +#define DEFAULT_STACK_SIZE 0x20000 | |
250 | + | |
251 | +#define MINUS_ONE ((bfd_vma) 0 - 1) | |
252 | + | |
253 | +/* Decide whether a reference to a symbol can be resolved locally or | |
254 | + not. If the symbol is protected, we want the local address, but | |
255 | + its function descriptor must be assigned by the dynamic linker. */ | |
256 | +#define SYMBOL_FUNCDESC_LOCAL(INFO, H) \ | |
257 | + (SYMBOL_REFERENCES_LOCAL (INFO, H) \ | |
258 | + || ! elf_hash_table (INFO)->dynamic_sections_created) | |
259 | + | |
242 | 260 | |
243 | 261 | /* Map BFD reloc types to RX ELF reloc types. */ |
244 | 262 |
@@ -270,6 +288,9 @@ static const struct rx_reloc_map rx_reloc_map [] = | ||
270 | 288 | { BFD_RELOC_RX_GOTPC, R_RX_GOTPC }, |
271 | 289 | { BFD_RELOC_32_GOTOFF, R_RX_GOTOFF }, |
272 | 290 | { BFD_RELOC_32_PLT_PCREL, R_RX_PLT }, |
291 | + { BFD_RELOC_RX_GOTFUNCDESC, R_RX_GOTFUNCDESC }, | |
292 | + { BFD_RELOC_RX_GOTOFFFUNCDESC, R_RX_GOTOFFFUNCDESC }, | |
293 | + { BFD_RELOC_RX_FUNCDESC, R_RX_FUNCDESC }, | |
273 | 294 | { BFD_RELOC_RX_24U, R_RX_RH_24_UNS }, |
274 | 295 | { BFD_RELOC_RX_NEG8, R_RX_RH_8_NEG }, |
275 | 296 | { BFD_RELOC_RX_NEG16, R_RX_RH_16_NEG }, |
@@ -401,6 +422,38 @@ static const struct elf_rx_plt_info elf_rx_plt_info[2] = | ||
401 | 422 | }, |
402 | 423 | |
403 | 424 | }; |
425 | + | |
426 | +#define FDPIC_PLT_ENTRY_SIZE 28 | |
427 | +#define FDPIC_PLT_LAZY_OFFSET 24 | |
428 | + | |
429 | +/* First entry in an absolute procedure linkage table look like this. */ | |
430 | +static const bfd_byte fdpic_elf_rx_plt_entry[FDPIC_PLT_ENTRY_SIZE] = | |
431 | +{ | |
432 | + 0xfb, 0xe2, /* mov #symoffset, r14 */ | |
433 | + 0, 0, 0, 0, | |
434 | + 0x4b, 0xde, /* add r13, r14 */ | |
435 | + 0xed, 0xed, 0x01, /* mov.l 4[r14], r13 */ | |
436 | + 0xec, 0xee, /* mov.l [r14], r14 */ | |
437 | + 0x7f, 0x0e, /* jmp r14 */ | |
438 | + 0x03, /* nop */ | |
439 | + 0xec, 0xde, /* mov.l [r13], r14 */ | |
440 | + 0xed, 0xd5, 0x01, /* mov.l 4[r13], r5 */ | |
441 | + 0x7f, 0x0e, /* jmp r14 */ | |
442 | + 0x03, /* nop */ | |
443 | + 0, 0, 0, 0, /* replaced with offset into relocation table. */ | |
444 | +}; | |
445 | + | |
446 | +static const struct elf_rx_plt_info fdpic_rx_plt_info = | |
447 | + { | |
448 | + NULL, | |
449 | + 0, | |
450 | + { 0, 0, 0 }, | |
451 | + fdpic_elf_rx_plt_entry, | |
452 | + FDPIC_PLT_ENTRY_SIZE, | |
453 | + { 2, 0, 0 }, | |
454 | + FDPIC_PLT_LAZY_OFFSET, | |
455 | + }; | |
456 | + | |
404 | 457 | struct elf_rx_pcrel_relocs_copied |
405 | 458 | { |
406 | 459 | /* Next section. */ |
@@ -414,6 +467,12 @@ struct elf_rx_pcrel_relocs_copied | ||
414 | 467 | /* Forward declaration. */ |
415 | 468 | struct elf_rx_got_entry; |
416 | 469 | |
470 | +union gotref | |
471 | +{ | |
472 | + bfd_signed_vma refcount; | |
473 | + bfd_vma offset; | |
474 | +}; | |
475 | + | |
417 | 476 | /* RX ELF linker hash entry. */ |
418 | 477 | |
419 | 478 | struct elf_rx_link_hash_entry |
@@ -422,8 +481,22 @@ struct elf_rx_link_hash_entry | ||
422 | 481 | |
423 | 482 | bfd_signed_vma gotplt_refcount; |
424 | 483 | |
484 | + /* A local function descriptor, for FDPIC. The refcount counts | |
485 | + R_RX_FUNCDESC, R_RX_GOTOFFFUNCDESC, and R_RX_GOTOFFFUNCDESC20 | |
486 | + relocations; the PLT and GOT entry are accounted | |
487 | + for separately. After adjust_dynamic_symbol, the offset is | |
488 | + MINUS_ONE if there is no local descriptor (dynamic linker | |
489 | + managed and no PLT entry, or undefined weak non-dynamic). | |
490 | + During check_relocs we do not yet know whether the local | |
491 | + descriptor will be canonical. */ | |
492 | + union gotref funcdesc; | |
493 | + | |
494 | + /* How many of the above refcounted relocations were R_SH_FUNCDESC, | |
495 | + and thus require fixups or relocations. */ | |
496 | + bfd_signed_vma abs_funcdesc_refcount; | |
497 | + | |
425 | 498 | enum got_type { |
426 | - GOT_UNKNOWN = 0, GOT_NORMAL, | |
499 | + GOT_UNKNOWN = 0, GOT_NORMAL, GOT_FUNCDESC, | |
427 | 500 | } got_type; |
428 | 501 | }; |
429 | 502 |
@@ -435,6 +508,9 @@ struct rx_elf_obj_tdata | ||
435 | 508 | |
436 | 509 | /* got_type for each local got entry. */ |
437 | 510 | char *local_got_type; |
511 | + | |
512 | + /* Function descriptor refcount and offset for each local symbol. */ | |
513 | + union gotref *local_funcdesc; | |
438 | 514 | }; |
439 | 515 | |
440 | 516 | #define rx_elf_tdata(abfd) \ |
@@ -443,7 +519,10 @@ struct rx_elf_obj_tdata | ||
443 | 519 | #define rx_elf_local_got_type(abfd) \ |
444 | 520 | (rx_elf_tdata (abfd)->local_got_type) |
445 | 521 | |
446 | -#define is_rx_elf(bfd) \ | |
522 | +#define rx_elf_local_funcdesc(abfd) \ | |
523 | + (rx_elf_tdata (abfd)->local_funcdesc) | |
524 | + | |
525 | +#define is_rx_elf(bfd) \ | |
447 | 526 | (bfd_get_flavour (bfd) == bfd_target_elf_flavour \ |
448 | 527 | && elf_tdata (bfd) != NULL \ |
449 | 528 | && elf_object_id (bfd) == RX_ELF_DATA) |
@@ -462,9 +541,16 @@ rx_elf_mkobject (bfd *abfd) | ||
462 | 541 | the object is position-independent. */ |
463 | 542 | |
464 | 543 | static const struct elf_rx_plt_info * |
465 | -get_plt_info (bfd *abfd ATTRIBUTE_UNUSED, bool pic) | |
544 | +get_plt_info (bfd *abfd, bool pic) | |
466 | 545 | { |
467 | - return &elf_rx_plt_info[pic]; | |
546 | + if (fdpic_object_p (abfd)) | |
547 | + { | |
548 | + return &fdpic_rx_plt_info; | |
549 | + } | |
550 | + else | |
551 | + { | |
552 | + return &elf_rx_plt_info[pic]; | |
553 | + } | |
468 | 554 | } |
469 | 555 | |
470 | 556 | /* Do the inverse operation. */ |
@@ -503,11 +589,15 @@ get_plt_index (const struct elf_rx_plt_info *info, bfd_vma offset) | ||
503 | 589 | struct elf_rx_link_hash_table |
504 | 590 | { |
505 | 591 | struct elf_link_hash_table root; |
506 | - | |
592 | + asection *sfuncdesc; | |
593 | + asection *srelfuncdesc; | |
594 | + asection *srofixup; | |
507 | 595 | |
508 | 596 | /* The type of PLT to use. */ |
509 | 597 | const struct elf_rx_plt_info *plt_info; |
510 | 598 | |
599 | + /* True if the target system uses FDPIC. */ | |
600 | + bool fdpic_p; | |
511 | 601 | }; |
512 | 602 | |
513 | 603 | /* Traverse an sh ELF linker hash table. */ |
@@ -551,6 +641,8 @@ rx_elf_link_hash_newfunc (struct bfd_hash_entry *entry, | ||
551 | 641 | if (ret != (struct elf_rx_link_hash_entry *) NULL) |
552 | 642 | { |
553 | 643 | ret->gotplt_refcount = 0; |
644 | + ret->funcdesc.refcount = 0; | |
645 | + ret->abs_funcdesc_refcount = 0; | |
554 | 646 | ret->got_type = GOT_UNKNOWN; |
555 | 647 | } |
556 | 648 |
@@ -578,9 +670,39 @@ rx_elf_link_hash_table_create (bfd *abfd) | ||
578 | 670 | return NULL; |
579 | 671 | } |
580 | 672 | |
673 | + ret->plt_info = NULL; | |
674 | + ret->fdpic_p = fdpic_object_p (abfd); | |
581 | 675 | return &ret->root.root; |
582 | 676 | } |
583 | 677 | |
678 | +static bool | |
679 | +rx_elf_omit_section_dynsym (bfd *output_bfd ATTRIBUTE_UNUSED, | |
680 | + struct bfd_link_info *info, asection *p) | |
681 | +{ | |
682 | + struct elf_rx_link_hash_table *htab = rx_elf_hash_table (info); | |
683 | + | |
684 | + /* Non-FDPIC binaries do not need dynamic symbols for sections. */ | |
685 | + if (!htab->fdpic_p) | |
686 | + return true; | |
687 | + | |
688 | + /* We need dynamic symbols for every section, since segments can | |
689 | + relocate independently. */ | |
690 | + switch (elf_section_data (p)->this_hdr.sh_type) | |
691 | + { | |
692 | + case SHT_PROGBITS: | |
693 | + case SHT_NOBITS: | |
694 | + /* If sh_type is yet undecided, assume it could be | |
695 | + SHT_PROGBITS/SHT_NOBITS. */ | |
696 | + case SHT_NULL: | |
697 | + return false; | |
698 | + | |
699 | + /* There shouldn't be section relative relocations | |
700 | + against any other section. */ | |
701 | + default: | |
702 | + return true; | |
703 | + } | |
704 | +} | |
705 | + | |
584 | 706 | /* Create .got, .gotplt, and .rela.got sections in DYNOBJ, and set up |
585 | 707 | shortcuts to them in our hash table. */ |
586 | 708 |
@@ -596,6 +718,37 @@ create_got_section (bfd *dynobj, struct bfd_link_info *info) | ||
596 | 718 | if (htab == NULL) |
597 | 719 | return false; |
598 | 720 | |
721 | + htab->sfuncdesc = bfd_make_section_anyway_with_flags (dynobj, ".got.funcdesc", | |
722 | + (SEC_ALLOC | SEC_LOAD | |
723 | + | SEC_HAS_CONTENTS | |
724 | + | SEC_IN_MEMORY | |
725 | + | SEC_LINKER_CREATED)); | |
726 | + if (htab->sfuncdesc == NULL | |
727 | + || !bfd_set_section_alignment (htab->sfuncdesc, 2)) | |
728 | + return false; | |
729 | + | |
730 | + htab->srelfuncdesc = bfd_make_section_anyway_with_flags (dynobj, | |
731 | + ".rela.got.funcdesc", | |
732 | + (SEC_ALLOC | SEC_LOAD | |
733 | + | SEC_HAS_CONTENTS | |
734 | + | SEC_IN_MEMORY | |
735 | + | SEC_LINKER_CREATED | |
736 | + | SEC_READONLY)); | |
737 | + if (htab->srelfuncdesc == NULL | |
738 | + || !bfd_set_section_alignment (htab->srelfuncdesc, 2)) | |
739 | + return false; | |
740 | + | |
741 | + /* Also create .rofixup. */ | |
742 | + htab->srofixup = bfd_make_section_anyway_with_flags (dynobj, ".rofixup", | |
743 | + (SEC_ALLOC | SEC_LOAD | |
744 | + | SEC_HAS_CONTENTS | |
745 | + | SEC_IN_MEMORY | |
746 | + | SEC_LINKER_CREATED | |
747 | + | SEC_READONLY)); | |
748 | + if (htab->srofixup == NULL | |
749 | + || !bfd_set_section_alignment (htab->srofixup, 2)) | |
750 | + return false; | |
751 | + | |
599 | 752 | return true; |
600 | 753 | } |
601 | 754 |
@@ -885,7 +1038,6 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) | ||
885 | 1038 | || WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, 0, h)) |
886 | 1039 | { |
887 | 1040 | asection *s = htab->root.splt; |
888 | - const struct elf_rx_plt_info *plt_info; | |
889 | 1041 | |
890 | 1042 | /* If this is the first .plt entry, make room for the special |
891 | 1043 | first entry. */ |
@@ -894,19 +1046,28 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) | ||
894 | 1046 | |
895 | 1047 | h->plt.offset = s->size; |
896 | 1048 | |
897 | - if (!bfd_link_pic (info) && !h->def_regular) | |
1049 | + /* If this symbol is not defined in a regular file, and we are | |
1050 | + not generating a shared library, then set the symbol to this | |
1051 | + location in the .plt. This is required to make function | |
1052 | + pointers compare as equal between the normal executable and | |
1053 | + the shared library. Skip this for FDPIC, since the | |
1054 | + function's address will be the address of the canonical | |
1055 | + function descriptor. */ | |
1056 | + if (!htab->fdpic_p && !bfd_link_pic (info) && !h->def_regular) | |
898 | 1057 | { |
899 | 1058 | h->root.u.def.section = s; |
900 | 1059 | h->root.u.def.value = h->plt.offset; |
901 | 1060 | } |
902 | 1061 | |
903 | 1062 | /* Make room for this entry. */ |
904 | - plt_info = htab->plt_info; | |
905 | - s->size += plt_info->symbol_entry_size; | |
1063 | + s->size += htab->plt_info->symbol_entry_size; | |
906 | 1064 | |
907 | 1065 | /* We also need to make an entry in the .got.plt section, which |
908 | 1066 | will be placed in the .got section by the linker script. */ |
909 | - htab->root.sgotplt->size += 4; | |
1067 | + if (!htab->fdpic_p) | |
1068 | + htab->root.sgotplt->size += 4; | |
1069 | + else | |
1070 | + htab->root.sgotplt->size += 8; | |
910 | 1071 | |
911 | 1072 | /* We also need to make an entry in the .rel.plt section. */ |
912 | 1073 | htab->root.srelplt->size += sizeof (Elf32_External_Rela); |
@@ -927,6 +1088,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) | ||
927 | 1088 | if (h->got.refcount > 0) |
928 | 1089 | { |
929 | 1090 | asection *s; |
1091 | + bool dyn; | |
1092 | + enum got_type got_type = rx_elf_hash_entry (h)->got_type; | |
930 | 1093 | |
931 | 1094 | /* Make sure this symbol is output as a dynamic symbol. |
932 | 1095 | Undefined weak syms won't yet be marked as dynamic. */ |
@@ -940,14 +1103,76 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) | ||
940 | 1103 | s = htab->root.sgot; |
941 | 1104 | h->got.offset = s->size; |
942 | 1105 | s->size += 4; |
943 | - if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT | |
1106 | + dyn = htab->root.dynamic_sections_created; | |
1107 | + if (!dyn) | |
1108 | + { | |
1109 | + /* No dynamic relocations required. */ | |
1110 | + if (htab->fdpic_p && !bfd_link_pic (info) | |
1111 | + && h->root.type != bfd_link_hash_undefweak | |
1112 | + && (got_type == GOT_NORMAL || got_type == GOT_FUNCDESC)) | |
1113 | + htab->srofixup->size += 4; | |
1114 | + } | |
1115 | + else if (got_type == GOT_FUNCDESC) | |
1116 | + { | |
1117 | + if (!bfd_link_pic (info) && SYMBOL_FUNCDESC_LOCAL (info, h)) | |
1118 | + htab->srofixup->size += 4; | |
1119 | + else | |
1120 | + htab->root.srelgot->size += sizeof (Elf32_External_Rela); | |
1121 | + } | |
1122 | + else if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT | |
944 | 1123 | || h->root.type != bfd_link_hash_undefweak) |
945 | 1124 | && (bfd_link_pic (info))) |
946 | 1125 | htab->root.srelgot->size += sizeof (Elf32_External_Rela); |
1126 | + else if (htab->fdpic_p | |
1127 | + && !bfd_link_pic (info) | |
1128 | + && got_type == GOT_NORMAL | |
1129 | + && (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT | |
1130 | + || h->root.type != bfd_link_hash_undefweak)) | |
1131 | + htab->srofixup->size += 4; | |
947 | 1132 | } |
948 | 1133 | else |
949 | 1134 | h->got.offset = (bfd_vma) -1; |
950 | 1135 | |
1136 | + /* Allocate space for any dynamic relocations to function | |
1137 | + descriptors, canonical or otherwise. We need to relocate the | |
1138 | + reference unless it resolves to zero, which only happens for | |
1139 | + undefined weak symbols (either non-default visibility, or when | |
1140 | + static linking). Any GOT slot is accounted for elsewhere. */ | |
1141 | + if (eh->abs_funcdesc_refcount > 0 | |
1142 | + && (h->root.type != bfd_link_hash_undefweak | |
1143 | + || (htab->root.dynamic_sections_created | |
1144 | + && ! SYMBOL_CALLS_LOCAL (info, h)))) | |
1145 | + { | |
1146 | + if (!bfd_link_pic (info) && SYMBOL_FUNCDESC_LOCAL (info, h)) | |
1147 | + htab->srofixup->size += eh->abs_funcdesc_refcount * 4; | |
1148 | + else | |
1149 | + htab->root.srelgot->size | |
1150 | + += eh->abs_funcdesc_refcount * sizeof (Elf32_External_Rela); | |
1151 | + } | |
1152 | + | |
1153 | + /* We must allocate a function descriptor if there are references to | |
1154 | + a canonical descriptor (R_SH_GOTFUNCDESC or R_SH_FUNCDESC) and | |
1155 | + the dynamic linker isn't going to allocate it. None of this | |
1156 | + applies if we already created one in .got.plt, but if the | |
1157 | + canonical function descriptor can be in this object, there | |
1158 | + won't be a PLT entry at all. */ | |
1159 | + if ((eh->funcdesc.refcount > 0 | |
1160 | + || (h->got.offset != MINUS_ONE && eh->got_type == GOT_FUNCDESC)) | |
1161 | + && h->root.type != bfd_link_hash_undefweak | |
1162 | + && SYMBOL_FUNCDESC_LOCAL (info, h)) | |
1163 | + { | |
1164 | + /* Make room for this function descriptor. */ | |
1165 | + eh->funcdesc.offset = htab->sfuncdesc->size; | |
1166 | + htab->sfuncdesc->size += 8; | |
1167 | + | |
1168 | + /* We will need a relocation or two fixups to initialize the | |
1169 | + function descriptor, so allocate those too. */ | |
1170 | + if (!bfd_link_pic(info) && SYMBOL_CALLS_LOCAL (info, h)) | |
1171 | + htab->srofixup->size += 8; | |
1172 | + else | |
1173 | + htab->srelfuncdesc->size += sizeof (Elf32_External_Rela); | |
1174 | + } | |
1175 | + | |
951 | 1176 | if (h->dyn_relocs == NULL) |
952 | 1177 | return true; |
953 | 1178 |
@@ -1044,11 +1269,32 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) | ||
1044 | 1269 | { |
1045 | 1270 | asection *sreloc = elf_section_data (p->sec)->sreloc; |
1046 | 1271 | sreloc->size += p->count * sizeof (Elf32_External_Rela); |
1272 | + | |
1273 | + /* If we need relocations, we do not need fixups. */ | |
1274 | + if (htab->fdpic_p && !bfd_link_pic(info)) | |
1275 | + htab->srofixup->size -= 4 * (p->count - p->pc_count); | |
1047 | 1276 | } |
1048 | 1277 | |
1049 | 1278 | return true; |
1050 | 1279 | } |
1051 | 1280 | |
1281 | +/* This function is called after all the input files have been read, | |
1282 | + and the input sections have been assigned to output sections. | |
1283 | + It's a convenient place to determine the PLT style. */ | |
1284 | + | |
1285 | +static bool | |
1286 | +rx_elf_always_size_sections (bfd *output_bfd, struct bfd_link_info *info) | |
1287 | +{ | |
1288 | + rx_elf_hash_table (info)->plt_info = get_plt_info (output_bfd, | |
1289 | + bfd_link_pic (info)); | |
1290 | + | |
1291 | + if (rx_elf_hash_table (info)->fdpic_p && !bfd_link_relocatable (info) | |
1292 | + && !bfd_elf_stack_segment_size (output_bfd, info, | |
1293 | + "__stacksize", DEFAULT_STACK_SIZE)) | |
1294 | + return false; | |
1295 | + return true; | |
1296 | +} | |
1297 | + | |
1052 | 1298 | static bool |
1053 | 1299 | rx_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, |
1054 | 1300 | struct bfd_link_info *info) |
@@ -1072,10 +1318,11 @@ rx_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, | ||
1072 | 1318 | { |
1073 | 1319 | bfd_signed_vma *local_got; |
1074 | 1320 | bfd_signed_vma *end_local_got; |
1075 | - char *local_got_type; | |
1076 | 1321 | bfd_size_type locsymcount; |
1077 | 1322 | Elf_Internal_Shdr *symtab_hdr; |
1078 | 1323 | asection *srel; |
1324 | + union gotref *local_funcdesc, *end_local_funcdesc; | |
1325 | + char *local_got_type; | |
1079 | 1326 | |
1080 | 1327 | if (! is_rx_elf (ibfd)) |
1081 | 1328 | continue; |
@@ -1113,6 +1360,10 @@ rx_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, | ||
1113 | 1360 | info->flags |= DF_TEXTREL; |
1114 | 1361 | info->callbacks->minfo (_("%pB: dynamic relocation in read-only section `%pA'\n"), |
1115 | 1362 | p->sec->owner, p->sec); |
1363 | + | |
1364 | + /* If we need relocations, we do not need fixups. */ | |
1365 | + if (htab->fdpic_p && !bfd_link_pic(info)) | |
1366 | + htab->srofixup->size -= 4 * (p->count - p->pc_count); | |
1116 | 1367 | } |
1117 | 1368 | } |
1118 | 1369 | } |
@@ -1128,26 +1379,88 @@ rx_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, | ||
1128 | 1379 | { |
1129 | 1380 | end_local_got = local_got + locsymcount; |
1130 | 1381 | local_got_type = rx_elf_local_got_type (ibfd); |
1382 | + local_funcdesc = rx_elf_local_funcdesc (ibfd); | |
1131 | 1383 | for (; local_got < end_local_got; ++local_got) |
1132 | 1384 | { |
1133 | 1385 | if (*local_got > 0) |
1134 | 1386 | { |
1135 | 1387 | *local_got = s->size; |
1136 | 1388 | s->size += 4; |
1137 | - if (bfd_link_pic (info)) | |
1389 | + if (bfd_link_pic(info)) | |
1138 | 1390 | srel->size += sizeof (Elf32_External_Rela); |
1391 | + else | |
1392 | + htab->srofixup->size += 4; | |
1393 | + | |
1394 | + if (*local_got_type == GOT_FUNCDESC) | |
1395 | + { | |
1396 | + if (local_funcdesc == NULL) | |
1397 | + { | |
1398 | + bfd_size_type size; | |
1399 | + | |
1400 | + size = locsymcount * sizeof (union gotref); | |
1401 | + local_funcdesc = (union gotref *) bfd_zalloc (ibfd, | |
1402 | + size); | |
1403 | + if (local_funcdesc == NULL) | |
1404 | + return false; | |
1405 | + rx_elf_local_funcdesc (ibfd) = local_funcdesc; | |
1406 | + local_funcdesc += (local_got | |
1407 | + - elf_local_got_refcounts (ibfd)); | |
1408 | + } | |
1409 | + local_funcdesc->refcount++; | |
1410 | + ++local_funcdesc; | |
1411 | + } | |
1139 | 1412 | } |
1140 | 1413 | else |
1141 | 1414 | *local_got = (bfd_vma) -1; |
1142 | 1415 | ++local_got_type; |
1143 | 1416 | } |
1144 | 1417 | } |
1418 | + local_funcdesc = rx_elf_local_funcdesc (ibfd); | |
1419 | + if (local_funcdesc) | |
1420 | + { | |
1421 | + end_local_funcdesc = local_funcdesc + locsymcount; | |
1422 | + | |
1423 | + for (; local_funcdesc < end_local_funcdesc; ++local_funcdesc) | |
1424 | + { | |
1425 | + if (local_funcdesc->refcount > 0) | |
1426 | + { | |
1427 | + local_funcdesc->offset = htab->sfuncdesc->size; | |
1428 | + htab->sfuncdesc->size += 8; | |
1429 | + if (!bfd_link_pic (info)) | |
1430 | + htab->srofixup->size += 8; | |
1431 | + else | |
1432 | + htab->srelfuncdesc->size += sizeof (Elf32_External_Rela); | |
1433 | + } | |
1434 | + else | |
1435 | + local_funcdesc->offset = MINUS_ONE; | |
1436 | + } | |
1437 | + } | |
1438 | + } | |
1439 | + | |
1440 | + /* Only the reserved entries should be present. For FDPIC, they go at | |
1441 | + the end of .got.plt. */ | |
1442 | + if (htab->fdpic_p) | |
1443 | + { | |
1444 | + BFD_ASSERT (htab->root.sgotplt && htab->root.sgotplt->size == 12); | |
1445 | + htab->root.sgotplt->size = 0; | |
1145 | 1446 | } |
1146 | 1447 | |
1147 | 1448 | /* Allocate global sym .plt and .got entries, and space for global |
1148 | 1449 | sym dynamic relocs. */ |
1149 | 1450 | elf_link_hash_traverse (&htab->root, allocate_dynrelocs, info); |
1150 | 1451 | |
1452 | + /* Move the reserved entries and the _GLOBAL_OFFSET_TABLE_ symbol to the | |
1453 | + end of the FDPIC .got.plt. */ | |
1454 | + if (htab->fdpic_p) | |
1455 | + { | |
1456 | + htab->root.hgot->root.u.def.value = htab->root.sgotplt->size; | |
1457 | + htab->root.sgotplt->size += 12; | |
1458 | + } | |
1459 | + | |
1460 | + /* At the very end of the .rofixup section is a pointer to the GOT. */ | |
1461 | + if (htab->fdpic_p && htab->srofixup != NULL) | |
1462 | + htab->srofixup->size += 4; | |
1463 | + | |
1151 | 1464 | /* We now have determined the sizes of the various dynamic sections. |
1152 | 1465 | Allocate memory for them. */ |
1153 | 1466 | relocs = false; |
@@ -1159,6 +1472,8 @@ rx_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, | ||
1159 | 1472 | if (s == htab->root.splt |
1160 | 1473 | || s == htab->root.sgot |
1161 | 1474 | || s == htab->root.sgotplt |
1475 | + || s == htab->sfuncdesc | |
1476 | + || s == htab->srofixup | |
1162 | 1477 | || s == htab->root.sdynbss) |
1163 | 1478 | { |
1164 | 1479 | /* Strip this section if we don't need it; see the |
@@ -1206,6 +1521,153 @@ rx_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, | ||
1206 | 1521 | return _bfd_elf_add_dynamic_tags (output_bfd, info, relocs); |
1207 | 1522 | } |
1208 | 1523 | |
1524 | +/* Add a dynamic relocation to the SRELOC section. */ | |
1525 | + | |
1526 | +inline static bfd_vma | |
1527 | +rx_elf_add_dyn_reloc (bfd *output_bfd, asection *sreloc, bfd_vma offset, | |
1528 | + int reloc_type, long dynindx, bfd_vma addend) | |
1529 | +{ | |
1530 | + Elf_Internal_Rela outrel; | |
1531 | + bfd_vma reloc_offset; | |
1532 | + | |
1533 | + outrel.r_offset = offset; | |
1534 | + outrel.r_info = ELF32_R_INFO (dynindx, reloc_type); | |
1535 | + outrel.r_addend = addend; | |
1536 | + | |
1537 | + reloc_offset = sreloc->reloc_count * sizeof (Elf32_External_Rela); | |
1538 | + BFD_ASSERT (reloc_offset < sreloc->size); | |
1539 | + bfd_elf32_swap_reloca_out (output_bfd, &outrel, | |
1540 | + sreloc->contents + reloc_offset); | |
1541 | + sreloc->reloc_count++; | |
1542 | + | |
1543 | + return reloc_offset; | |
1544 | +} | |
1545 | + | |
1546 | +/* Add an FDPIC read-only fixup. */ | |
1547 | + | |
1548 | +inline static void | |
1549 | +rx_elf_add_rofixup (bfd *output_bfd, asection *srofixup, bfd_vma offset) | |
1550 | +{ | |
1551 | + bfd_vma fixup_offset; | |
1552 | + | |
1553 | + fixup_offset = srofixup->reloc_count++ * 4; | |
1554 | + BFD_ASSERT (fixup_offset < srofixup->size); | |
1555 | + bfd_put_32 (output_bfd, offset, srofixup->contents + fixup_offset); | |
1556 | +} | |
1557 | + | |
1558 | +#if 0 | |
1559 | +/* Return the offset of the generated .got section from the | |
1560 | + _GLOBAL_OFFSET_TABLE_ symbol. */ | |
1561 | + | |
1562 | +static bfd_signed_vma | |
1563 | +rx_elf_got_offset (struct elf_rx_link_hash_table *htab) | |
1564 | +{ | |
1565 | + return (htab->root.sgot->output_offset - htab->root.sgotplt->output_offset | |
1566 | + - htab->root.hgot->root.u.def.value); | |
1567 | +} | |
1568 | +#endif | |
1569 | + | |
1570 | +/* Find the segment number in which OSEC, and output section, is | |
1571 | + located. */ | |
1572 | + | |
1573 | +static unsigned | |
1574 | +rx_elf_osec_to_segment (bfd *output_bfd, asection *osec) | |
1575 | +{ | |
1576 | + Elf_Internal_Phdr *p = NULL; | |
1577 | + | |
1578 | + if (output_bfd->xvec->flavour == bfd_target_elf_flavour | |
1579 | + /* PR ld/17110: Do not look for output segments in an input bfd. */ | |
1580 | + && output_bfd->direction != read_direction) | |
1581 | + p = _bfd_elf_find_segment_containing_section (output_bfd, osec); | |
1582 | + | |
1583 | + /* FIXME: Nothing ever says what this index is relative to. The kernel | |
1584 | + supplies data in terms of the number of load segments but this is | |
1585 | + a phdr index and the first phdr may not be a load segment. */ | |
1586 | + return (p != NULL) ? p - elf_tdata (output_bfd)->phdr : -1; | |
1587 | +} | |
1588 | + | |
1589 | +static bool | |
1590 | +rx_elf_osec_readonly_p (bfd *output_bfd, asection *osec) | |
1591 | +{ | |
1592 | + unsigned seg = rx_elf_osec_to_segment (output_bfd, osec); | |
1593 | + | |
1594 | + return (seg != (unsigned) -1 | |
1595 | + && ! (elf_tdata (output_bfd)->phdr[seg].p_flags & PF_W)); | |
1596 | +} | |
1597 | + | |
1598 | +/* Generate the initial contents of a local function descriptor, along | |
1599 | + with any relocations or fixups required. */ | |
1600 | +static bool | |
1601 | +rx_elf_initialize_funcdesc (bfd *output_bfd, | |
1602 | + struct bfd_link_info *info, | |
1603 | + struct elf_link_hash_entry *h, | |
1604 | + bfd_vma offset, | |
1605 | + asection *section, | |
1606 | + bfd_vma value) | |
1607 | +{ | |
1608 | + struct elf_rx_link_hash_table *htab; | |
1609 | + int dynindx; | |
1610 | + bfd_vma addr, seg; | |
1611 | + | |
1612 | + htab = rx_elf_hash_table (info); | |
1613 | + | |
1614 | + /* FIXME: The ABI says that the offset to the function goes in the | |
1615 | + descriptor, along with the segment index. We're RELA, so it could | |
1616 | + go in the reloc instead... */ | |
1617 | + | |
1618 | + if (h != NULL && SYMBOL_CALLS_LOCAL (info, h)) | |
1619 | + { | |
1620 | + section = h->root.u.def.section; | |
1621 | + value = h->root.u.def.value; | |
1622 | + } | |
1623 | + | |
1624 | + if (h == NULL || SYMBOL_CALLS_LOCAL (info, h)) | |
1625 | + { | |
1626 | + dynindx = elf_section_data (section->output_section)->dynindx; | |
1627 | + addr = value + section->output_offset; | |
1628 | + seg = rx_elf_osec_to_segment (output_bfd, section->output_section); | |
1629 | + } | |
1630 | + else | |
1631 | + { | |
1632 | + BFD_ASSERT (h->dynindx != -1); | |
1633 | + dynindx = h->dynindx; | |
1634 | + addr = seg = 0; | |
1635 | + } | |
1636 | + | |
1637 | + if (!bfd_link_pic (info) && SYMBOL_CALLS_LOCAL (info, h)) | |
1638 | + { | |
1639 | + if (h == NULL || h->root.type != bfd_link_hash_undefweak) | |
1640 | + { | |
1641 | + rx_elf_add_rofixup (output_bfd, htab->srofixup, | |
1642 | + offset | |
1643 | + + htab->sfuncdesc->output_section->vma | |
1644 | + + htab->sfuncdesc->output_offset); | |
1645 | + rx_elf_add_rofixup (output_bfd, htab->srofixup, | |
1646 | + offset + 4 | |
1647 | + + htab->sfuncdesc->output_section->vma | |
1648 | + + htab->sfuncdesc->output_offset); | |
1649 | + } | |
1650 | + | |
1651 | + /* There are no dynamic relocations so fill in the final | |
1652 | + address and gp value (barring fixups). */ | |
1653 | + addr += section->output_section->vma; | |
1654 | + seg = htab->root.hgot->root.u.def.value | |
1655 | + + htab->root.hgot->root.u.def.section->output_section->vma | |
1656 | + + htab->root.hgot->root.u.def.section->output_offset; | |
1657 | + } | |
1658 | + else | |
1659 | + rx_elf_add_dyn_reloc (output_bfd, htab->srelfuncdesc, | |
1660 | + offset | |
1661 | + + htab->sfuncdesc->output_section->vma | |
1662 | + + htab->sfuncdesc->output_offset, | |
1663 | + R_RX_FUNCDESC_VALUE, dynindx, 0); | |
1664 | + | |
1665 | + bfd_put_32 (output_bfd, addr, htab->sfuncdesc->contents + offset); | |
1666 | + bfd_put_32 (output_bfd, seg, htab->sfuncdesc->contents + offset + 4); | |
1667 | + | |
1668 | + return true; | |
1669 | +} | |
1670 | + | |
1209 | 1671 | /* Finish up dynamic symbol handling. We set the contents of various |
1210 | 1672 | dynamic sections here. */ |
1211 | 1673 |
@@ -1252,9 +1714,15 @@ rx_elf_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info, | ||
1252 | 1714 | |
1253 | 1715 | /* Get the offset into the .got table of the entry that |
1254 | 1716 | corresponds to this function. */ |
1255 | - /* Each .got entry is 4 bytes. The first three are | |
1256 | - reserved. */ | |
1257 | - got_offset = (plt_index + 3) * 4; | |
1717 | + if (htab->fdpic_p) | |
1718 | + /* The offset must be relative to the GOT symbol, twelve bytes | |
1719 | + before the end of .got.plt. Each descriptor is eight | |
1720 | + bytes. */ | |
1721 | + got_offset = plt_index * 8 + 12 - sgotplt->size; | |
1722 | + else | |
1723 | + /* Each .got entry is 4 bytes. The first three are | |
1724 | + reserved. */ | |
1725 | + got_offset = (plt_index + 3) * 4; | |
1258 | 1726 | |
1259 | 1727 | #ifdef GOT_BIAS |
1260 | 1728 | if (bfd_link_pic (info)) |
@@ -1266,7 +1734,7 @@ rx_elf_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info, | ||
1266 | 1734 | plt_info->symbol_entry, |
1267 | 1735 | plt_info->symbol_entry_size); |
1268 | 1736 | |
1269 | - if (bfd_link_pic (info)) | |
1737 | + if (bfd_link_pic (info) || htab->fdpic_p) | |
1270 | 1738 | { |
1271 | 1739 | install_plt_field (output_bfd, false, got_offset, |
1272 | 1740 | (splt->contents |
@@ -1294,6 +1762,16 @@ rx_elf_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info, | ||
1294 | 1762 | if (bfd_link_pic (info)) |
1295 | 1763 | got_offset += GOT_BIAS; |
1296 | 1764 | #endif |
1765 | + if (htab->fdpic_p) | |
1766 | + got_offset = plt_index * 8; | |
1767 | + | |
1768 | + if (plt_info->symbol_fields.reloc_offset != 0) | |
1769 | + install_plt_field (output_bfd, false, | |
1770 | + plt_index * sizeof (Elf32_External_Rela), | |
1771 | + (splt->contents | |
1772 | + + h->plt.offset | |
1773 | + + plt_info->symbol_fields.reloc_offset)); | |
1774 | + | |
1297 | 1775 | /* Fill in the entry in the global offset table. */ |
1298 | 1776 | bfd_put_32 (output_bfd, |
1299 | 1777 | (splt->output_section->vma |
@@ -1301,6 +1779,11 @@ rx_elf_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info, | ||
1301 | 1779 | + h->plt.offset |
1302 | 1780 | + plt_info->symbol_resolve_offset), |
1303 | 1781 | sgotplt->contents + got_offset); |
1782 | + if (htab->fdpic_p) | |
1783 | + bfd_put_32 (output_bfd, | |
1784 | + rx_elf_osec_to_segment (output_bfd, splt->output_section), | |
1785 | + sgotplt->contents + got_offset + 4); | |
1786 | + | |
1304 | 1787 | /* Fill in the entry in the .rela.plt section. */ |
1305 | 1788 | rel.r_offset = (sgotplt->output_section->vma |
1306 | 1789 | + sgotplt->output_offset |
@@ -1321,7 +1804,8 @@ rx_elf_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info, | ||
1321 | 1804 | } |
1322 | 1805 | } |
1323 | 1806 | |
1324 | - if (h->got.offset != (bfd_vma) -1) | |
1807 | + if (h->got.offset != (bfd_vma) -1 | |
1808 | + && rx_elf_hash_entry (h)->got_type != GOT_FUNCDESC) | |
1325 | 1809 | { |
1326 | 1810 | asection *sgot; |
1327 | 1811 | asection *srelgot; |
@@ -1462,7 +1946,7 @@ rx_elf_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) | ||
1462 | 1946 | |
1463 | 1947 | memcpy (splt->contents, |
1464 | 1948 | htab->plt_info->plt0_entry, |
1465 | - htab->plt_info->plt0_entry_size); | |
1949 | + htab->plt_info->plt0_entry_size); | |
1466 | 1950 | for (i = 0; i < ARRAY_SIZE (htab->plt_info->plt0_got_fields); i++) |
1467 | 1951 | if (htab->plt_info->plt0_got_fields[i] != 0) |
1468 | 1952 | install_plt_field (output_bfd, false, |
@@ -1494,6 +1978,28 @@ rx_elf_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) | ||
1494 | 1978 | if (sgotplt && sgotplt->size > 0) |
1495 | 1979 | elf_section_data (sgotplt->output_section)->this_hdr.sh_entsize = 4; |
1496 | 1980 | |
1981 | + /* At the very end of the .rofixup section is a pointer to the GOT. */ | |
1982 | + if (htab->fdpic_p && htab->srofixup != NULL) | |
1983 | + { | |
1984 | + struct elf_link_hash_entry *hgot = htab->root.hgot; | |
1985 | + bfd_vma got_value = hgot->root.u.def.value | |
1986 | + + hgot->root.u.def.section->output_section->vma | |
1987 | + + hgot->root.u.def.section->output_offset; | |
1988 | + | |
1989 | + rx_elf_add_rofixup (output_bfd, htab->srofixup, got_value); | |
1990 | + | |
1991 | + /* Make sure we allocated and generated the same number of fixups. */ | |
1992 | + BFD_ASSERT (htab->srofixup->reloc_count * 4 == htab->srofixup->size); | |
1993 | + } | |
1994 | + | |
1995 | + if (htab->srelfuncdesc) | |
1996 | + BFD_ASSERT (htab->srelfuncdesc->reloc_count * sizeof (Elf32_External_Rela) | |
1997 | + == htab->srelfuncdesc->size); | |
1998 | + | |
1999 | + if (htab->root.srelgot) | |
2000 | + BFD_ASSERT (htab->root.srelgot->reloc_count * sizeof (Elf32_External_Rela) | |
2001 | + == htab->root.srelgot->size); | |
2002 | + | |
1497 | 2003 | return true; |
1498 | 2004 | } |
1499 | 2005 |
@@ -1576,8 +2082,16 @@ rx_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec, | ||
1576 | 2082 | switch (r_type) |
1577 | 2083 | { |
1578 | 2084 | case R_RX_DIR32: |
2085 | + /* This may require an rofixup. */ | |
2086 | + if (!htab->fdpic_p) | |
2087 | + break; | |
2088 | + /* Fall through. */ | |
1579 | 2089 | case R_RX_GOT: |
1580 | 2090 | case R_RX_GOTOFF: |
2091 | + case R_RX_FUNCDESC: | |
2092 | + case R_RX_GOTFUNCDESC: | |
2093 | + case R_RX_GOTOFFFUNCDESC: | |
2094 | + case R_RX_GOTPC: | |
1581 | 2095 | if (htab->root.dynobj == NULL) |
1582 | 2096 | htab->root.dynobj = abfd; |
1583 | 2097 | if (!create_got_section (htab->root.dynobj, info)) |
@@ -1753,7 +2267,9 @@ rx_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec, | ||
1753 | 2267 | |
1754 | 2268 | p->count += 1; |
1755 | 2269 | } |
1756 | - | |
2270 | + if (htab->fdpic_p && !bfd_link_pic (info) | |
2271 | + && (sec->flags & SEC_ALLOC) != 0) | |
2272 | + htab->srofixup->size += 4; | |
1757 | 2273 | break; |
1758 | 2274 | |
1759 | 2275 | default: |
@@ -2005,8 +2521,10 @@ rx_elf_relocate_section | ||
2005 | 2521 | asection *sgotplt = NULL; |
2006 | 2522 | asection *splt = NULL; |
2007 | 2523 | asection *srelgot = NULL; |
2008 | - unsigned got_segment, plt_segment, check_segment[2]; | |
2524 | + asection *sreloc = NULL; | |
2525 | + unsigned isec_segment, got_segment, plt_segment, check_segment[2]; | |
2009 | 2526 | bfd_vma *local_got_offsets; |
2527 | + bool fdpic_p = false; | |
2010 | 2528 | |
2011 | 2529 | if (elf_elfheader (output_bfd)->e_flags & E_FLAG_RX_PID) |
2012 | 2530 | pid_mode = true; |
@@ -2020,13 +2538,25 @@ rx_elf_relocate_section | ||
2020 | 2538 | sgotplt = htab->root.sgotplt; |
2021 | 2539 | srelgot = htab->root.srelgot; |
2022 | 2540 | splt = htab->root.splt; |
2541 | + fdpic_p = htab->fdpic_p; | |
2023 | 2542 | } |
2024 | 2543 | symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr; |
2025 | 2544 | sym_hashes = elf_sym_hashes (input_bfd); |
2026 | 2545 | relend = relocs + input_section->reloc_count; |
2027 | 2546 | local_got_offsets = elf_local_got_offsets (input_bfd); |
2028 | - got_segment = -1; | |
2029 | - plt_segment = -1; | |
2547 | + | |
2548 | + isec_segment = rx_elf_osec_to_segment (output_bfd, | |
2549 | + input_section->output_section); | |
2550 | + if (fdpic_p && sgot) | |
2551 | + got_segment = rx_elf_osec_to_segment (output_bfd, | |
2552 | + sgot->output_section); | |
2553 | + else | |
2554 | + got_segment = -1; | |
2555 | + if (fdpic_p && splt) | |
2556 | + plt_segment = rx_elf_osec_to_segment (output_bfd, | |
2557 | + splt->output_section); | |
2558 | + else | |
2559 | + plt_segment = -1; | |
2030 | 2560 | |
2031 | 2561 | for (rel = relocs; rel < relend; rel ++) |
2032 | 2562 | { |
@@ -2311,6 +2841,9 @@ rx_elf_relocate_section | ||
2311 | 2841 | || (r_type == R_RX_PLT |
2312 | 2842 | && h->plt.offset != (bfd_vma) -1) |
2313 | 2843 | || ((r_type == R_RX_GOT |
2844 | + || r_type == R_RX_GOTFUNCDESC | |
2845 | + || r_type == R_RX_GOTOFFFUNCDESC | |
2846 | + || r_type == R_RX_FUNCDESC) | |
2314 | 2847 | && WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, |
2315 | 2848 | bfd_link_pic (info), |
2316 | 2849 | h) |
@@ -2339,7 +2872,7 @@ rx_elf_relocate_section | ||
2339 | 2872 | thus ld.so will not process them. */ |
2340 | 2873 | || (sec->output_section == NULL |
2341 | 2874 | && ((input_section->flags & SEC_DEBUGGING) != 0 |
2342 | - && h->def_dynamic)))) | |
2875 | + && h->def_dynamic))) | |
2343 | 2876 | ; |
2344 | 2877 | else if (sec->output_section != NULL) |
2345 | 2878 | relocation = (h->root.u.def.value |
@@ -2384,6 +2917,16 @@ rx_elf_relocate_section | ||
2384 | 2917 | if (bfd_link_relocatable (info)) |
2385 | 2918 | continue; |
2386 | 2919 | |
2920 | + /* Check for inter-segment relocations in FDPIC files. Most | |
2921 | + relocations connect the relocation site to the location of | |
2922 | + the target symbol, but there are some exceptions below. */ | |
2923 | + check_segment[0] = isec_segment; | |
2924 | + if (sec != NULL) | |
2925 | + check_segment[1] = rx_elf_osec_to_segment (output_bfd, | |
2926 | + sec->output_section); | |
2927 | + else | |
2928 | + check_segment[1] = -1; | |
2929 | + | |
2387 | 2930 | #define RANGE(a,b) \ |
2388 | 2931 | if (a > (long) relocation || (long) relocation > b) \ |
2389 | 2932 | r = bfd_reloc_overflow |
@@ -2646,6 +3189,108 @@ rx_elf_relocate_section | ||
2646 | 3189 | break; |
2647 | 3190 | |
2648 | 3191 | case R_RX_DIR32: |
3192 | + if (bfd_link_pic (info) | |
3193 | + && (h == NULL | |
3194 | + || (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT | |
3195 | + && !resolved_to_zero) | |
3196 | + || h->root.type != bfd_link_hash_undefweak) | |
3197 | + && r_symndx != STN_UNDEF | |
3198 | + && (input_section->flags & SEC_ALLOC) != 0 | |
3199 | + && !SYMBOL_CALLS_LOCAL (info, h)) | |
3200 | + { | |
3201 | + Elf_Internal_Rela outrel; | |
3202 | + bfd_byte *loc; | |
3203 | + bool skip, relocate; | |
3204 | + | |
3205 | + /* When generating a shared object, these relocations | |
3206 | + are copied into the output file to be resolved at run | |
3207 | + time. */ | |
3208 | + | |
3209 | + if (sreloc == NULL) | |
3210 | + { | |
3211 | + sreloc = _bfd_elf_get_dynamic_reloc_section | |
3212 | + (input_bfd, input_section, /*rela?*/ true); | |
3213 | + if (sreloc == NULL) | |
3214 | + return false; | |
3215 | + } | |
3216 | + | |
3217 | + skip = false; | |
3218 | + relocate = false; | |
3219 | + | |
3220 | + outrel.r_offset = | |
3221 | + _bfd_elf_section_offset (output_bfd, info, input_section, | |
3222 | + rel->r_offset); | |
3223 | + if (outrel.r_offset == (bfd_vma) -1) | |
3224 | + skip = true; | |
3225 | + else if (outrel.r_offset == (bfd_vma) -2) | |
3226 | + skip = true, relocate = true; | |
3227 | + outrel.r_offset += (input_section->output_section->vma | |
3228 | + + input_section->output_offset); | |
3229 | + | |
3230 | + if (skip) | |
3231 | + memset (&outrel, 0, sizeof outrel); | |
3232 | + else if (fdpic_p | |
3233 | + && (h == NULL | |
3234 | + || ((info->symbolic || h->dynindx == -1) | |
3235 | + && h->def_regular))) | |
3236 | + { | |
3237 | + int dynindx; | |
3238 | + | |
3239 | + BFD_ASSERT (sec != NULL); | |
3240 | + BFD_ASSERT (sec->output_section != NULL); | |
3241 | + dynindx = elf_section_data (sec->output_section)->dynindx; | |
3242 | + outrel.r_info = ELF32_R_INFO (dynindx, R_RX_DIR32); | |
3243 | + outrel.r_addend = relocation; | |
3244 | + outrel.r_addend | |
3245 | + += (howto->partial_inplace | |
3246 | + ? bfd_get_32 (input_bfd, contents + rel->r_offset) | |
3247 | + : addend); | |
3248 | + outrel.r_addend -= sec->output_section->vma; | |
3249 | + } | |
3250 | + loc = sreloc->contents; | |
3251 | + loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rela); | |
3252 | + bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); | |
3253 | + | |
3254 | + check_segment[0] = check_segment[1] = -1; | |
3255 | + | |
3256 | + /* If this reloc is against an external symbol, we do | |
3257 | + not want to fiddle with the addend. Otherwise, we | |
3258 | + need to include the symbol value so that it becomes | |
3259 | + an addend for the dynamic reloc. */ | |
3260 | + if (! relocate) | |
3261 | + continue; | |
3262 | + } | |
3263 | + else if (fdpic_p && !bfd_link_pic (info) | |
3264 | + && (input_section->flags & SEC_ALLOC) != 0) | |
3265 | + { | |
3266 | + bfd_vma offset; | |
3267 | + | |
3268 | + BFD_ASSERT (htab); | |
3269 | + | |
3270 | + if (rx_elf_osec_readonly_p (output_bfd, | |
3271 | + input_section->output_section)) | |
3272 | + { | |
3273 | + _bfd_error_handler | |
3274 | + /* xgettext:c-format */ | |
3275 | + (_("%pB(%pA+%#" PRIx64 "): " | |
3276 | + "cannot emit fixup to `%s' in read-only section"), | |
3277 | + input_bfd, | |
3278 | + input_section, | |
3279 | + (uint64_t) rel->r_offset, | |
3280 | + symname); | |
3281 | + return false; | |
3282 | + } | |
3283 | + | |
3284 | + offset = _bfd_elf_section_offset (output_bfd, info, | |
3285 | + input_section, rel->r_offset); | |
3286 | + if (offset != (bfd_vma)-1) | |
3287 | + rx_elf_add_rofixup (output_bfd, htab->srofixup, | |
3288 | + input_section->output_section->vma | |
3289 | + + input_section->output_offset | |
3290 | + + rel->r_offset); | |
3291 | + | |
3292 | + check_segment[0] = check_segment[1] = -1; | |
3293 | + } | |
2649 | 3294 | if (BIGE (output_bfd) && !(input_section->flags & SEC_CODE)) |
2650 | 3295 | { |
2651 | 3296 | OP (3) = relocation; |
@@ -3240,6 +3885,10 @@ rx_elf_relocate_section | ||
3240 | 3885 | #ifdef GOT_BIAS |
3241 | 3886 | relocation -= GOT_BIAS; |
3242 | 3887 | #endif |
3888 | + OP (0) = relocation; | |
3889 | + OP (1) = relocation >> 8; | |
3890 | + OP (2) = relocation >> 16; | |
3891 | + OP (3) = relocation >> 24; | |
3243 | 3892 | |
3244 | 3893 | break; |
3245 | 3894 |
@@ -3272,6 +3921,10 @@ rx_elf_relocate_section | ||
3272 | 3921 | #endif |
3273 | 3922 | |
3274 | 3923 | addend = rel->r_addend; |
3924 | + OP (0) = relocation; | |
3925 | + OP (1) = relocation >> 8; | |
3926 | + OP (2) = relocation >> 16; | |
3927 | + OP (3) = relocation >> 24; | |
3275 | 3928 | |
3276 | 3929 | break; |
3277 | 3930 |
@@ -3315,11 +3968,306 @@ rx_elf_relocate_section | ||
3315 | 3968 | OP (2) = relocation >> 16; |
3316 | 3969 | |
3317 | 3970 | break; |
3971 | + /* Relocation is to the canonical function descriptor for this | |
3972 | + symbol, possibly via the GOT. Initialize the GOT | |
3973 | + entry and function descriptor if necessary. */ | |
3974 | + case R_RX_GOTFUNCDESC: | |
3975 | + case R_RX_FUNCDESC: | |
3976 | + { | |
3977 | + int dynindx = -1; | |
3978 | + asection *reloc_section; | |
3979 | + bfd_vma reloc_offset; | |
3980 | + int reloc_type = R_RX_FUNCDESC; | |
3981 | + | |
3982 | + check_segment[0] = check_segment[1] = -1; | |
3983 | + | |
3984 | + /* FIXME: See what FRV does for global symbols in the | |
3985 | + executable, with --export-dynamic. Do they need ld.so | |
3986 | + to allocate official descriptors? See what this code | |
3987 | + does. */ | |
3988 | + | |
3989 | + relocation = 0; | |
3990 | + addend = 0; | |
3991 | + | |
3992 | + if (r_type == R_RX_FUNCDESC) | |
3993 | + { | |
3994 | + reloc_section = input_section; | |
3995 | + reloc_offset = rel->r_offset; | |
3996 | + } | |
3997 | + else | |
3998 | + { | |
3999 | + reloc_section = htab->root.sgot; | |
4000 | + | |
4001 | + if (h != NULL) | |
4002 | + reloc_offset = h->got.offset; | |
4003 | + else | |
4004 | + { | |
4005 | + BFD_ASSERT (local_got_offsets != NULL); | |
4006 | + reloc_offset = local_got_offsets[r_symndx]; | |
4007 | + } | |
4008 | + BFD_ASSERT (reloc_offset != MINUS_ONE); | |
4009 | + | |
4010 | + if (reloc_offset & 1) | |
4011 | + { | |
4012 | + reloc_offset &= ~1; | |
4013 | + goto funcdesc_done_got; | |
4014 | + } | |
4015 | + } | |
4016 | + | |
4017 | + if (h && h->root.type == bfd_link_hash_undefweak | |
4018 | + && (SYMBOL_CALLS_LOCAL (info, h) | |
4019 | + || !htab->root.dynamic_sections_created)) | |
4020 | + /* Undefined weak symbol which will not be dynamically | |
4021 | + resolved later; leave it at zero. */ | |
4022 | + goto funcdesc_leave_zero; | |
4023 | + else if (SYMBOL_CALLS_LOCAL (info, h) | |
4024 | + && ! SYMBOL_FUNCDESC_LOCAL (info, h)) | |
4025 | + { | |
4026 | + /* If the symbol needs a non-local function descriptor | |
4027 | + but binds locally (i.e., its visibility is | |
4028 | + protected), emit a dynamic relocation decayed to | |
4029 | + section+offset. This is an optimization; the dynamic | |
4030 | + linker would resolve our function descriptor request | |
4031 | + to our copy of the function anyway. */ | |
4032 | + dynindx = elf_section_data (h->root.u.def.section | |
4033 | + ->output_section)->dynindx; | |
4034 | + relocation += h->root.u.def.section->output_offset | |
4035 | + + h->root.u.def.value; | |
4036 | + } | |
4037 | + else if (! SYMBOL_FUNCDESC_LOCAL (info, h)) | |
4038 | + { | |
4039 | + /* If the symbol is dynamic and there will be dynamic | |
4040 | + symbol resolution because we are or are linked with a | |
4041 | + shared library, emit a FUNCDESC relocation such that | |
4042 | + the dynamic linker will allocate the function | |
4043 | + descriptor. */ | |
4044 | + BFD_ASSERT (h->dynindx != -1); | |
4045 | + dynindx = h->dynindx; | |
4046 | + } | |
4047 | + else | |
4048 | + { | |
4049 | + bfd_vma offset; | |
4050 | + | |
4051 | + /* Otherwise, we know we have a private function | |
4052 | + descriptor, so reference it directly. */ | |
4053 | + reloc_type = R_RX_DIR32; | |
4054 | + dynindx = elf_section_data (htab->sfuncdesc | |
4055 | + ->output_section)->dynindx; | |
4056 | + | |
4057 | + if (h) | |
4058 | + { | |
4059 | + offset = rx_elf_hash_entry (h)->funcdesc.offset; | |
4060 | + BFD_ASSERT (offset != MINUS_ONE); | |
4061 | + if ((offset & 1) == 0) | |
4062 | + { | |
4063 | + if (!rx_elf_initialize_funcdesc (output_bfd, info, h, | |
4064 | + offset, NULL, 0)) | |
4065 | + return false; | |
4066 | + rx_elf_hash_entry (h)->funcdesc.offset |= 1; | |
4067 | + } | |
4068 | + } | |
4069 | + else | |
4070 | + { | |
4071 | + union gotref *local_funcdesc; | |
4072 | + | |
4073 | + local_funcdesc = rx_elf_local_funcdesc (input_bfd); | |
4074 | + offset = local_funcdesc[r_symndx].offset; | |
4075 | + BFD_ASSERT (offset != MINUS_ONE); | |
4076 | + if ((offset & 1) == 0) | |
4077 | + { | |
4078 | + if (!rx_elf_initialize_funcdesc (output_bfd, info, NULL, | |
4079 | + offset, sec, | |
4080 | + sym->st_value)) | |
4081 | + return false; | |
4082 | + local_funcdesc[r_symndx].offset |= 1; | |
4083 | + } | |
4084 | + } | |
4085 | + | |
4086 | + relocation = htab->sfuncdesc->output_offset + (offset & ~1); | |
4087 | + } | |
4088 | + | |
4089 | + if (!bfd_link_pic(info) && SYMBOL_FUNCDESC_LOCAL (info, h)) | |
4090 | + { | |
4091 | + bfd_vma offset; | |
4092 | + | |
4093 | + BFD_ASSERT (htab); | |
4094 | + | |
4095 | + if (rx_elf_osec_readonly_p (output_bfd, | |
4096 | + input_section->output_section)) | |
4097 | + { | |
4098 | + _bfd_error_handler | |
4099 | + /* xgettext:c-format */ | |
4100 | + (_("%pB(%pA+%#" PRIx64 "): " | |
4101 | + "cannot emit fixup to `%s' in read-only section"), | |
4102 | + input_bfd, | |
4103 | + input_section, | |
4104 | + (uint64_t) rel->r_offset, | |
4105 | + symname); | |
4106 | + return false; | |
4107 | + } | |
4108 | + | |
4109 | + offset = _bfd_elf_section_offset (output_bfd, info, | |
4110 | + reloc_section, reloc_offset); | |
4111 | + | |
4112 | + if (offset != (bfd_vma)-1) | |
4113 | + rx_elf_add_rofixup (output_bfd, htab->srofixup, | |
4114 | + offset | |
4115 | + + reloc_section->output_section->vma | |
4116 | + + reloc_section->output_offset); | |
4117 | + } | |
4118 | + else if ((reloc_section->output_section->flags | |
4119 | + & (SEC_ALLOC | SEC_LOAD)) == (SEC_ALLOC | SEC_LOAD)) | |
4120 | + { | |
4121 | + bfd_vma offset; | |
4122 | + | |
4123 | + if (rx_elf_osec_readonly_p (output_bfd, | |
4124 | + reloc_section->output_section)) | |
4125 | + { | |
4126 | + info->callbacks->warning | |
4127 | + (info, | |
4128 | + _("cannot emit dynamic relocations in read-only section"), | |
4129 | + symname, input_bfd, reloc_section, reloc_offset); | |
4130 | + return false; | |
4131 | + } | |
4132 | + | |
4133 | + offset = _bfd_elf_section_offset (output_bfd, info, | |
4134 | + reloc_section, reloc_offset); | |
4135 | + | |
4136 | + if (offset != (bfd_vma)-1) | |
4137 | + rx_elf_add_dyn_reloc (output_bfd, srelgot, | |
4138 | + offset | |
4139 | + + reloc_section->output_section->vma | |
4140 | + + reloc_section->output_offset, | |
4141 | + reloc_type, dynindx, relocation); | |
4142 | + | |
4143 | + if (r_type == R_RX_FUNCDESC) | |
4144 | + { | |
4145 | + r = bfd_reloc_ok; | |
4146 | + break; | |
4147 | + } | |
4148 | + else | |
4149 | + { | |
4150 | + relocation = 0; | |
4151 | + goto funcdesc_leave_zero; | |
4152 | + } | |
4153 | + } | |
4154 | + if (SYMBOL_FUNCDESC_LOCAL (info, h)) | |
4155 | + relocation += htab->sfuncdesc->output_section->vma; | |
4156 | + funcdesc_leave_zero: | |
4157 | + if (r_type != R_RX_FUNCDESC) | |
4158 | + { | |
4159 | + bfd_put_32 (output_bfd, relocation, | |
4160 | + reloc_section->contents + reloc_offset); | |
4161 | + if (h != NULL) | |
4162 | + h->got.offset |= 1; | |
4163 | + else | |
4164 | + local_got_offsets[r_symndx] |= 1; | |
3318 | 4165 | |
4166 | + funcdesc_done_got: | |
4167 | + | |
4168 | + relocation = rx_elf_got_offset (htab) + reloc_offset; | |
4169 | +#ifdef GOT_BIAS | |
4170 | + relocation -= GOT_BIAS; | |
4171 | +#endif | |
4172 | + } | |
4173 | + OP (0) = relocation; | |
4174 | + OP (1) = relocation >> 8; | |
4175 | + OP (2) = relocation >> 16; | |
4176 | + OP (3) = relocation >> 24; | |
4177 | + } | |
4178 | + break; | |
4179 | + | |
4180 | + case R_RX_GOTOFFFUNCDESC: | |
4181 | + | |
4182 | + check_segment[0] = check_segment[1] = -1; | |
4183 | + relocation = 0; | |
4184 | + addend = rel->r_addend; | |
4185 | + | |
4186 | + if (h && (h->root.type == bfd_link_hash_undefweak | |
4187 | + || !SYMBOL_FUNCDESC_LOCAL (info, h))) | |
4188 | + { | |
4189 | + _bfd_error_handler | |
4190 | + /* xgettext:c-format */ | |
4191 | + (_("%pB(%pA+%#" PRIx64 "): " | |
4192 | + "%s relocation against external symbol \"%s\""), | |
4193 | + input_bfd, input_section, (uint64_t) rel->r_offset, | |
4194 | + howto->name, h->root.root.string); | |
4195 | + return false; | |
4196 | + } | |
4197 | + else | |
4198 | + { | |
4199 | + bfd_vma offset; | |
4200 | + | |
4201 | + /* Otherwise, we know we have a private function | |
4202 | + descriptor, so reference it directly. */ | |
4203 | + if (h) | |
4204 | + { | |
4205 | + offset = rx_elf_hash_entry (h)->funcdesc.offset; | |
4206 | + BFD_ASSERT (offset != MINUS_ONE); | |
4207 | + if ((offset & 1) == 0) | |
4208 | + { | |
4209 | + if (!rx_elf_initialize_funcdesc (output_bfd, info, h, | |
4210 | + offset, NULL, 0)) | |
4211 | + return false; | |
4212 | + rx_elf_hash_entry (h)->funcdesc.offset |= 1; | |
4213 | + } | |
4214 | + } | |
4215 | + else | |
4216 | + { | |
4217 | + union gotref *local_funcdesc; | |
4218 | + | |
4219 | + local_funcdesc = rx_elf_local_funcdesc (input_bfd); | |
4220 | + offset = local_funcdesc[r_symndx].offset; | |
4221 | + BFD_ASSERT (offset != MINUS_ONE); | |
4222 | + if ((offset & 1) == 0) | |
4223 | + { | |
4224 | + if (!rx_elf_initialize_funcdesc (output_bfd, info, NULL, | |
4225 | + offset, sec, | |
4226 | + sym->st_value)) | |
4227 | + return false; | |
4228 | + local_funcdesc[r_symndx].offset |= 1; | |
4229 | + } | |
4230 | + } | |
4231 | + | |
4232 | + relocation = htab->sfuncdesc->output_offset + (offset & ~1); | |
4233 | + } | |
4234 | + | |
4235 | + relocation -= htab->root.hgot->root.u.def.value | |
4236 | + + htab->root.sgotplt->output_offset; | |
4237 | +#ifdef GOT_BIAS | |
4238 | + relocation -= GOT_BIAS; | |
4239 | +#endif | |
4240 | + OP (0) = relocation; | |
4241 | + OP (1) = relocation >> 8; | |
4242 | + OP (2) = relocation >> 16; | |
4243 | + OP (3) = relocation >> 24; | |
4244 | + break; | |
4245 | + | |
3319 | 4246 | default: |
3320 | 4247 | r = bfd_reloc_notsupported; |
3321 | 4248 | break; |
3322 | 4249 | } |
4250 | + if (htab->fdpic_p && check_segment[0] != (unsigned) -1 | |
4251 | + && check_segment[0] != check_segment[1]) | |
4252 | + { | |
4253 | + /* We don't want duplicate errors for undefined symbols. */ | |
4254 | + if (!h || h->root.type != bfd_link_hash_undefined) | |
4255 | + { | |
4256 | + if (bfd_link_pic(info)) | |
4257 | + { | |
4258 | + info->callbacks->einfo | |
4259 | + (_("%X%C: relocation to \"%s\" references a different segment\n"), | |
4260 | + input_bfd, input_section, rel->r_offset, symname); | |
4261 | + return false; | |
4262 | + } | |
4263 | + else | |
4264 | + info->callbacks->einfo | |
4265 | + (_("%C: warning: relocation to \"%s\" references a different segment\n"), | |
4266 | + input_bfd, input_section, rel->r_offset, symname); | |
4267 | + } | |
4268 | + | |
4269 | + elf_elfheader (output_bfd)->e_flags &= ~EF_RX_PIC; | |
4270 | + } | |
3323 | 4271 | |
3324 | 4272 | if (r != bfd_reloc_ok) |
3325 | 4273 | { |
@@ -5974,6 +6922,8 @@ rx_additional_link_map_text (bfd *obfd, struct bfd_link_info *info, FILE *mapfil | ||
5974 | 6922 | #undef bfd_elf32_mkobject |
5975 | 6923 | #define bfd_elf32_mkobject rx_elf_mkobject |
5976 | 6924 | |
6925 | +#undef elf_backend_omit_section_dynsym | |
6926 | +#define elf_backend_omit_section_dynsym rx_elf_omit_section_dynsym | |
5977 | 6927 | #undef elf_backend_create_dynamic_sections |
5978 | 6928 | #define elf_backend_create_dynamic_sections \ |
5979 | 6929 | rx_elf_create_dynamic_sections |
@@ -5983,6 +6933,9 @@ rx_additional_link_map_text (bfd *obfd, struct bfd_link_info *info, FILE *mapfil | ||
5983 | 6933 | #undef elf_backend_adjust_dynamic_symbol |
5984 | 6934 | #define elf_backend_adjust_dynamic_symbol \ |
5985 | 6935 | rx_elf_adjust_dynamic_symbol |
6936 | +#undef elf_backend_always_size_sections | |
6937 | +#define elf_backend_always_size_sections \ | |
6938 | + rx_elf_always_size_sections | |
5986 | 6939 | #undef elf_backend_size_dynamic_sections |
5987 | 6940 | #define elf_backend_size_dynamic_sections \ |
5988 | 6941 | rx_elf_size_dynamic_sections |
@@ -5996,6 +6949,9 @@ rx_additional_link_map_text (bfd *obfd, struct bfd_link_info *info, FILE *mapfil | ||
5996 | 6949 | #define elf_backend_plt_sym_val rx_elf_plt_sym_val |
5997 | 6950 | #undef elf_backend_check_relocs |
5998 | 6951 | #define elf_backend_check_relocs rx_elf_check_relocs |
6952 | +#undef elf_backend_modify_program_headers | |
6953 | +#define elf_backend_modify_program_headers \ | |
6954 | + rx_elf_modify_program_headers | |
5999 | 6955 | |
6000 | 6956 | #undef elf_backend_want_got_plt |
6001 | 6957 | #define elf_backend_want_got_plt 1 |
@@ -2484,6 +2484,9 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", | ||
2484 | 2484 | "BFD_RELOC_RX_GOTOFF", |
2485 | 2485 | "BFD_RELOC_RX_PLT", |
2486 | 2486 | "BFD_RELOC_RX_GOTPC", |
2487 | + "BFD_RELOC_RX_GOTFUNCDESC", | |
2488 | + "BFD_RELOC_RX_GOTOFFFUNCDESC", | |
2489 | + "BFD_RELOC_RX_FUNCDESC", | |
2487 | 2490 | "BFD_RELOC_390_12", |
2488 | 2491 | "BFD_RELOC_390_GOT12", |
2489 | 2492 | "BFD_RELOC_390_PLT32", |
@@ -5369,6 +5369,12 @@ ENUMX | ||
5369 | 5369 | BFD_RELOC_RX_PLT |
5370 | 5370 | ENUMX |
5371 | 5371 | BFD_RELOC_RX_GOTPC |
5372 | +ENUMX | |
5373 | + BFD_RELOC_RX_GOTFUNCDESC | |
5374 | +ENUMX | |
5375 | + BFD_RELOC_RX_GOTOFFFUNCDESC | |
5376 | +ENUMX | |
5377 | + BFD_RELOC_RX_FUNCDESC | |
5372 | 5378 | ENUMDOC |
5373 | 5379 | Renesas RX Relocations. |
5374 | 5380 |
@@ -40,6 +40,9 @@ const char line_separator_chars[] = "!"; | ||
40 | 40 | |
41 | 41 | const char EXP_CHARS[] = "eE"; |
42 | 42 | const char FLT_CHARS[] = "dD"; |
43 | + | |
44 | +/* Whether --fdpic was given. */ | |
45 | +static bool fdpic = false; | |
43 | 46 | |
44 | 47 | #ifndef TE_LINUX |
45 | 48 | bool rx_use_conventional_section_names = false; |
@@ -76,6 +79,7 @@ enum options | ||
76 | 79 | OPTION_USES_RX_ABI, |
77 | 80 | OPTION_CPU, |
78 | 81 | OPTION_DISALLOW_STRING_INSNS, |
82 | + OPTION_FDPIC, | |
79 | 83 | }; |
80 | 84 | |
81 | 85 | #define RX_SHORTOPTS "" |
@@ -104,6 +108,7 @@ struct option md_longopts[] = | ||
104 | 108 | {"mrx-abi", no_argument, NULL, OPTION_USES_RX_ABI}, |
105 | 109 | {"mcpu", required_argument, NULL, OPTION_CPU}, |
106 | 110 | {"mno-allow-string-insns", no_argument, NULL, OPTION_DISALLOW_STRING_INSNS}, |
111 | + {"fdpic", no_argument, NULL, OPTION_FDPIC}, | |
107 | 112 | {NULL, no_argument, NULL, 0} |
108 | 113 | }; |
109 | 114 | size_t md_longopts_size = sizeof (md_longopts); |
@@ -199,6 +204,9 @@ md_parse_option (int c ATTRIBUTE_UNUSED, const char * arg ATTRIBUTE_UNUSED) | ||
199 | 204 | case OPTION_DISALLOW_STRING_INSNS: |
200 | 205 | elf_flags |= E_FLAG_RX_SINSNS_SET | E_FLAG_RX_SINSNS_NO; |
201 | 206 | return 1; |
207 | + case OPTION_FDPIC: | |
208 | + fdpic = true; | |
209 | + return 1; | |
202 | 210 | } |
203 | 211 | |
204 | 212 | return 0; |
@@ -219,7 +227,8 @@ md_show_usage (FILE * stream) | ||
219 | 227 | fprintf (stream, _(" --mpid\n")); |
220 | 228 | fprintf (stream, _(" --mint-register=<value>\n")); |
221 | 229 | fprintf (stream, _(" --mcpu=<rx100|rx200|rx600|rx610|rxv2|rxv3|rxv3-dfpu>\n")); |
222 | - fprintf (stream, _(" --mno-allow-string-insns")); | |
230 | + fprintf (stream, _(" --mno-allow-string-insns\n")); | |
231 | + fprintf (stream, _(" --fdpic")); | |
223 | 232 | } |
224 | 233 | |
225 | 234 | static void |
@@ -1162,6 +1171,9 @@ rx_parse_name (char const *name, expressionS *exprP, | ||
1162 | 1171 | { "GOT", BFD_RELOC_32_GOT_PCREL }, |
1163 | 1172 | { "PLT", BFD_RELOC_32_PLT_PCREL }, |
1164 | 1173 | { "PCREL", BFD_RELOC_32_PCREL }, |
1174 | + { "GOTFUNCDESC", BFD_RELOC_RX_GOTFUNCDESC }, | |
1175 | + { "GOTOFFFUNCDESC", BFD_RELOC_RX_GOTOFFFUNCDESC }, | |
1176 | + { "FUNCDESC", BFD_RELOC_RX_FUNCDESC }, | |
1165 | 1177 | { NULL, -1 }, |
1166 | 1178 | }; |
1167 | 1179 | const struct suffix_list *s; |
@@ -1276,7 +1288,8 @@ md_assemble (char * str) | ||
1276 | 1288 | APPEND (post, n_post); |
1277 | 1289 | |
1278 | 1290 | if (rx_bytes.link_relax && rx_bytes.n_fixups && |
1279 | - rx_bytes.fixups[0].exp.X_add_symbol != GOT_symbol) | |
1291 | + rx_bytes.fixups[0].exp.X_add_symbol != GOT_symbol && | |
1292 | + rx_bytes.fixups[0].exp.X_op != O_PIC_reloc) | |
1280 | 1293 | { |
1281 | 1294 | fixS * f; |
1282 | 1295 |
@@ -2207,6 +2220,15 @@ md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, | ||
2207 | 2220 | case BFD_RELOC_RX_GOTPC: |
2208 | 2221 | reloc_type = rxb->fixups[fi].exp.X_md; |
2209 | 2222 | break; |
2223 | + case BFD_RELOC_RX_GOTFUNCDESC: | |
2224 | + reloc_type = BFD_RELOC_RX_GOTFUNCDESC; | |
2225 | + break; | |
2226 | + case BFD_RELOC_RX_GOTOFFFUNCDESC: | |
2227 | + reloc_type = BFD_RELOC_RX_GOTOFFFUNCDESC; | |
2228 | + break; | |
2229 | + case BFD_RELOC_RX_FUNCDESC: | |
2230 | + reloc_type = BFD_RELOC_RX_FUNCDESC; | |
2231 | + break; | |
2210 | 2232 | } |
2211 | 2233 | } |
2212 | 2234 | switch (nbytes) |
@@ -2616,6 +2638,9 @@ md_apply_fix (struct fix * f ATTRIBUTE_UNUSED, | ||
2616 | 2638 | break; |
2617 | 2639 | |
2618 | 2640 | case BFD_RELOC_32_GOT_PCREL: |
2641 | + case BFD_RELOC_RX_GOTFUNCDESC: | |
2642 | + case BFD_RELOC_RX_GOTOFFFUNCDESC: | |
2643 | + case BFD_RELOC_RX_FUNCDESC: | |
2619 | 2644 | memset(op, 0x00, 4); |
2620 | 2645 | break; |
2621 | 2646 |
@@ -2880,7 +2905,10 @@ rx_fix_adjustable (fixS *fixP) | ||
2880 | 2905 | { |
2881 | 2906 | if (fixP->fx_r_type == BFD_RELOC_32_PLT_PCREL |
2882 | 2907 | || fixP->fx_r_type == BFD_RELOC_32_GOT_PCREL |
2883 | - || fixP->fx_r_type == BFD_RELOC_RX_GOTPC) | |
2908 | + || fixP->fx_r_type == BFD_RELOC_RX_GOTPC | |
2909 | + || fixP->fx_r_type == BFD_RELOC_RX_GOTFUNCDESC | |
2910 | + || fixP->fx_r_type == BFD_RELOC_RX_GOTOFFFUNCDESC | |
2911 | + || fixP->fx_r_type == BFD_RELOC_RX_FUNCDESC) | |
2884 | 2912 | return false; |
2885 | 2913 | |
2886 | 2914 | return true; |
@@ -2892,6 +2920,9 @@ void | ||
2892 | 2920 | rx_elf_final_processing (void) |
2893 | 2921 | { |
2894 | 2922 | elf_elfheader (stdoutput)->e_flags |= elf_flags; |
2923 | + | |
2924 | + if (fdpic) | |
2925 | + elf_elfheader (stdoutput)->e_flags |= EF_RX_FDPIC; | |
2895 | 2926 | } |
2896 | 2927 | |
2897 | 2928 | /* Scan the current input line for occurrences of Renesas |
@@ -64,6 +64,10 @@ START_RELOC_NUMBERS (elf_rx_reloc_type) | ||
64 | 64 | RELOC_NUMBER (R_RX_RELATIVE, 0x18) |
65 | 65 | RELOC_NUMBER (R_RX_GOTOFF, 0x19) |
66 | 66 | RELOC_NUMBER (R_RX_GOTPC, 0x1a) |
67 | + RELOC_NUMBER (R_RX_GOTFUNCDESC, 0x1b) | |
68 | + RELOC_NUMBER (R_RX_GOTOFFFUNCDESC, 0x1c) | |
69 | + RELOC_NUMBER (R_RX_FUNCDESC , 0x1d) | |
70 | + RELOC_NUMBER (R_RX_FUNCDESC_VALUE, 0x1e) | |
67 | 71 | |
68 | 72 | /* These are extensions added by Red Hat. */ |
69 | 73 | RELOC_NUMBER (R_RX_RH_3_PCREL, 0x20) /* Like R_RX_DIR8S_PCREL but only 3-bits. */ |
@@ -123,6 +127,8 @@ END_RELOC_NUMBERS (R_RX_max) | ||
123 | 127 | #define EF_RX_CPU_RX 0x00000079 /* FIXME: this collides with the E_FLAG_RX_... values below. */ |
124 | 128 | #define EF_RX_CPU_MASK 0x000003FF /* specific cpu bits. */ |
125 | 129 | #define EF_RX_ALL_FLAGS (EF_RX_CPU_MASK) |
130 | +#define EF_RX_PIC 0x1000 | |
131 | +#define EF_RX_FDPIC 0x2000 | |
126 | 132 | |
127 | 133 | /* Values for the e_flags field in the ELF header. */ |
128 | 134 | #define E_FLAG_RX_64BIT_DOUBLES (1 << 0) |