• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Commit MetaInfo

Revision7d37558a1c3f7b3b67022872a27b5e4e71c9e2e4 (tree)
Time2022-12-08 12:30:02
AuthorYoshinori Sato <ysato@user...>
CommiterYoshinori Sato

Log Message

wip: bfd rx-fdpic

Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>

Change Summary

Incremental Difference

--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -4441,6 +4441,9 @@ number for the SBIC, SBIS, SBI and CBI instructions */
44414441 BFD_RELOC_RX_GOTOFF,
44424442 BFD_RELOC_RX_PLT,
44434443 BFD_RELOC_RX_GOTPC,
4444+ BFD_RELOC_RX_GOTFUNCDESC,
4445+ BFD_RELOC_RX_GOTOFFFUNCDESC,
4446+ BFD_RELOC_RX_FUNCDESC,
44444447
44454448 /* Direct 12 bit. */
44464449 BFD_RELOC_390_12,
--- a/bfd/elf32-rx.c
+++ b/bfd/elf32-rx.c
@@ -39,6 +39,16 @@ char * rx_get_reloc (long);
3939 void rx_dump_symtab (bfd *, void *, void *);
4040 #endif
4141
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+
4252 #define RXREL(n,sz,bit,shift,complain,pcrel) \
4353 HOWTO (R_RX_##n, shift, sz, bit, pcrel, 0, complain_overflow_ ## complain, \
4454 bfd_elf_generic_reloc, "R_RX_" #n, false, 0, ~0, false)
@@ -76,15 +86,11 @@ static reloc_howto_type rx_elf_howto_table [] =
7686 RXREL (RELATIVE, 2, 32, 0, bitfield, false),
7787 RXREL (GOTOFF, 2, 32, 0, bitfield, false),
7888 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),
7993
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),
8894 EMPTY_HOWTO (0x1f),
8995
9096 RXREL (RH_3_PCREL, 1, 3, 0, signed, true),
@@ -239,6 +245,18 @@ static reloc_howto_type rx_elf_howto_table [] =
239245 RXREL (OPramtop, 4, 32, 0, dont, false)
240246 };
241247
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+
242260
243261 /* Map BFD reloc types to RX ELF reloc types. */
244262
@@ -270,6 +288,9 @@ static const struct rx_reloc_map rx_reloc_map [] =
270288 { BFD_RELOC_RX_GOTPC, R_RX_GOTPC },
271289 { BFD_RELOC_32_GOTOFF, R_RX_GOTOFF },
272290 { 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 },
273294 { BFD_RELOC_RX_24U, R_RX_RH_24_UNS },
274295 { BFD_RELOC_RX_NEG8, R_RX_RH_8_NEG },
275296 { 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] =
401422 },
402423
403424 };
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+
404457 struct elf_rx_pcrel_relocs_copied
405458 {
406459 /* Next section. */
@@ -414,6 +467,12 @@ struct elf_rx_pcrel_relocs_copied
414467 /* Forward declaration. */
415468 struct elf_rx_got_entry;
416469
470+union gotref
471+{
472+ bfd_signed_vma refcount;
473+ bfd_vma offset;
474+};
475+
417476 /* RX ELF linker hash entry. */
418477
419478 struct elf_rx_link_hash_entry
@@ -422,8 +481,22 @@ struct elf_rx_link_hash_entry
422481
423482 bfd_signed_vma gotplt_refcount;
424483
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+
425498 enum got_type {
426- GOT_UNKNOWN = 0, GOT_NORMAL,
499+ GOT_UNKNOWN = 0, GOT_NORMAL, GOT_FUNCDESC,
427500 } got_type;
428501 };
429502
@@ -435,6 +508,9 @@ struct rx_elf_obj_tdata
435508
436509 /* got_type for each local got entry. */
437510 char *local_got_type;
511+
512+ /* Function descriptor refcount and offset for each local symbol. */
513+ union gotref *local_funcdesc;
438514 };
439515
440516 #define rx_elf_tdata(abfd) \
@@ -443,7 +519,10 @@ struct rx_elf_obj_tdata
443519 #define rx_elf_local_got_type(abfd) \
444520 (rx_elf_tdata (abfd)->local_got_type)
445521
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) \
447526 (bfd_get_flavour (bfd) == bfd_target_elf_flavour \
448527 && elf_tdata (bfd) != NULL \
449528 && elf_object_id (bfd) == RX_ELF_DATA)
@@ -462,9 +541,16 @@ rx_elf_mkobject (bfd *abfd)
462541 the object is position-independent. */
463542
464543 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)
466545 {
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+ }
468554 }
469555
470556 /* Do the inverse operation. */
@@ -503,11 +589,15 @@ get_plt_index (const struct elf_rx_plt_info *info, bfd_vma offset)
503589 struct elf_rx_link_hash_table
504590 {
505591 struct elf_link_hash_table root;
506-
592+ asection *sfuncdesc;
593+ asection *srelfuncdesc;
594+ asection *srofixup;
507595
508596 /* The type of PLT to use. */
509597 const struct elf_rx_plt_info *plt_info;
510598
599+ /* True if the target system uses FDPIC. */
600+ bool fdpic_p;
511601 };
512602
513603 /* Traverse an sh ELF linker hash table. */
@@ -551,6 +641,8 @@ rx_elf_link_hash_newfunc (struct bfd_hash_entry *entry,
551641 if (ret != (struct elf_rx_link_hash_entry *) NULL)
552642 {
553643 ret->gotplt_refcount = 0;
644+ ret->funcdesc.refcount = 0;
645+ ret->abs_funcdesc_refcount = 0;
554646 ret->got_type = GOT_UNKNOWN;
555647 }
556648
@@ -578,9 +670,39 @@ rx_elf_link_hash_table_create (bfd *abfd)
578670 return NULL;
579671 }
580672
673+ ret->plt_info = NULL;
674+ ret->fdpic_p = fdpic_object_p (abfd);
581675 return &ret->root.root;
582676 }
583677
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+
584706 /* Create .got, .gotplt, and .rela.got sections in DYNOBJ, and set up
585707 shortcuts to them in our hash table. */
586708
@@ -596,6 +718,37 @@ create_got_section (bfd *dynobj, struct bfd_link_info *info)
596718 if (htab == NULL)
597719 return false;
598720
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+
599752 return true;
600753 }
601754
@@ -885,7 +1038,6 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
8851038 || WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, 0, h))
8861039 {
8871040 asection *s = htab->root.splt;
888- const struct elf_rx_plt_info *plt_info;
8891041
8901042 /* If this is the first .plt entry, make room for the special
8911043 first entry. */
@@ -894,19 +1046,28 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
8941046
8951047 h->plt.offset = s->size;
8961048
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)
8981057 {
8991058 h->root.u.def.section = s;
9001059 h->root.u.def.value = h->plt.offset;
9011060 }
9021061
9031062 /* 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;
9061064
9071065 /* We also need to make an entry in the .got.plt section, which
9081066 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;
9101071
9111072 /* We also need to make an entry in the .rel.plt section. */
9121073 htab->root.srelplt->size += sizeof (Elf32_External_Rela);
@@ -927,6 +1088,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
9271088 if (h->got.refcount > 0)
9281089 {
9291090 asection *s;
1091+ bool dyn;
1092+ enum got_type got_type = rx_elf_hash_entry (h)->got_type;
9301093
9311094 /* Make sure this symbol is output as a dynamic symbol.
9321095 Undefined weak syms won't yet be marked as dynamic. */
@@ -940,14 +1103,76 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
9401103 s = htab->root.sgot;
9411104 h->got.offset = s->size;
9421105 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
9441123 || h->root.type != bfd_link_hash_undefweak)
9451124 && (bfd_link_pic (info)))
9461125 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;
9471132 }
9481133 else
9491134 h->got.offset = (bfd_vma) -1;
9501135
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+
9511176 if (h->dyn_relocs == NULL)
9521177 return true;
9531178
@@ -1044,11 +1269,32 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
10441269 {
10451270 asection *sreloc = elf_section_data (p->sec)->sreloc;
10461271 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);
10471276 }
10481277
10491278 return true;
10501279 }
10511280
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+
10521298 static bool
10531299 rx_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
10541300 struct bfd_link_info *info)
@@ -1072,10 +1318,11 @@ rx_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
10721318 {
10731319 bfd_signed_vma *local_got;
10741320 bfd_signed_vma *end_local_got;
1075- char *local_got_type;
10761321 bfd_size_type locsymcount;
10771322 Elf_Internal_Shdr *symtab_hdr;
10781323 asection *srel;
1324+ union gotref *local_funcdesc, *end_local_funcdesc;
1325+ char *local_got_type;
10791326
10801327 if (! is_rx_elf (ibfd))
10811328 continue;
@@ -1113,6 +1360,10 @@ rx_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
11131360 info->flags |= DF_TEXTREL;
11141361 info->callbacks->minfo (_("%pB: dynamic relocation in read-only section `%pA'\n"),
11151362 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);
11161367 }
11171368 }
11181369 }
@@ -1128,26 +1379,88 @@ rx_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
11281379 {
11291380 end_local_got = local_got + locsymcount;
11301381 local_got_type = rx_elf_local_got_type (ibfd);
1382+ local_funcdesc = rx_elf_local_funcdesc (ibfd);
11311383 for (; local_got < end_local_got; ++local_got)
11321384 {
11331385 if (*local_got > 0)
11341386 {
11351387 *local_got = s->size;
11361388 s->size += 4;
1137- if (bfd_link_pic (info))
1389+ if (bfd_link_pic(info))
11381390 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+ }
11391412 }
11401413 else
11411414 *local_got = (bfd_vma) -1;
11421415 ++local_got_type;
11431416 }
11441417 }
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;
11451446 }
11461447
11471448 /* Allocate global sym .plt and .got entries, and space for global
11481449 sym dynamic relocs. */
11491450 elf_link_hash_traverse (&htab->root, allocate_dynrelocs, info);
11501451
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+
11511464 /* We now have determined the sizes of the various dynamic sections.
11521465 Allocate memory for them. */
11531466 relocs = false;
@@ -1159,6 +1472,8 @@ rx_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
11591472 if (s == htab->root.splt
11601473 || s == htab->root.sgot
11611474 || s == htab->root.sgotplt
1475+ || s == htab->sfuncdesc
1476+ || s == htab->srofixup
11621477 || s == htab->root.sdynbss)
11631478 {
11641479 /* 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,
12061521 return _bfd_elf_add_dynamic_tags (output_bfd, info, relocs);
12071522 }
12081523
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+
12091671 /* Finish up dynamic symbol handling. We set the contents of various
12101672 dynamic sections here. */
12111673
@@ -1252,9 +1714,15 @@ rx_elf_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info,
12521714
12531715 /* Get the offset into the .got table of the entry that
12541716 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;
12581726
12591727 #ifdef GOT_BIAS
12601728 if (bfd_link_pic (info))
@@ -1266,7 +1734,7 @@ rx_elf_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info,
12661734 plt_info->symbol_entry,
12671735 plt_info->symbol_entry_size);
12681736
1269- if (bfd_link_pic (info))
1737+ if (bfd_link_pic (info) || htab->fdpic_p)
12701738 {
12711739 install_plt_field (output_bfd, false, got_offset,
12721740 (splt->contents
@@ -1294,6 +1762,16 @@ rx_elf_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info,
12941762 if (bfd_link_pic (info))
12951763 got_offset += GOT_BIAS;
12961764 #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+
12971775 /* Fill in the entry in the global offset table. */
12981776 bfd_put_32 (output_bfd,
12991777 (splt->output_section->vma
@@ -1301,6 +1779,11 @@ rx_elf_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info,
13011779 + h->plt.offset
13021780 + plt_info->symbol_resolve_offset),
13031781 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+
13041787 /* Fill in the entry in the .rela.plt section. */
13051788 rel.r_offset = (sgotplt->output_section->vma
13061789 + sgotplt->output_offset
@@ -1321,7 +1804,8 @@ rx_elf_finish_dynamic_symbol (bfd *output_bfd, struct bfd_link_info *info,
13211804 }
13221805 }
13231806
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)
13251809 {
13261810 asection *sgot;
13271811 asection *srelgot;
@@ -1462,7 +1946,7 @@ rx_elf_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
14621946
14631947 memcpy (splt->contents,
14641948 htab->plt_info->plt0_entry,
1465- htab->plt_info->plt0_entry_size);
1949+ htab->plt_info->plt0_entry_size);
14661950 for (i = 0; i < ARRAY_SIZE (htab->plt_info->plt0_got_fields); i++)
14671951 if (htab->plt_info->plt0_got_fields[i] != 0)
14681952 install_plt_field (output_bfd, false,
@@ -1494,6 +1978,28 @@ rx_elf_finish_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
14941978 if (sgotplt && sgotplt->size > 0)
14951979 elf_section_data (sgotplt->output_section)->this_hdr.sh_entsize = 4;
14961980
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+
14972003 return true;
14982004 }
14992005
@@ -1576,8 +2082,16 @@ rx_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec,
15762082 switch (r_type)
15772083 {
15782084 case R_RX_DIR32:
2085+ /* This may require an rofixup. */
2086+ if (!htab->fdpic_p)
2087+ break;
2088+ /* Fall through. */
15792089 case R_RX_GOT:
15802090 case R_RX_GOTOFF:
2091+ case R_RX_FUNCDESC:
2092+ case R_RX_GOTFUNCDESC:
2093+ case R_RX_GOTOFFFUNCDESC:
2094+ case R_RX_GOTPC:
15812095 if (htab->root.dynobj == NULL)
15822096 htab->root.dynobj = abfd;
15832097 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,
17532267
17542268 p->count += 1;
17552269 }
1756-
2270+ if (htab->fdpic_p && !bfd_link_pic (info)
2271+ && (sec->flags & SEC_ALLOC) != 0)
2272+ htab->srofixup->size += 4;
17572273 break;
17582274
17592275 default:
@@ -2005,8 +2521,10 @@ rx_elf_relocate_section
20052521 asection *sgotplt = NULL;
20062522 asection *splt = NULL;
20072523 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];
20092526 bfd_vma *local_got_offsets;
2527+ bool fdpic_p = false;
20102528
20112529 if (elf_elfheader (output_bfd)->e_flags & E_FLAG_RX_PID)
20122530 pid_mode = true;
@@ -2020,13 +2538,25 @@ rx_elf_relocate_section
20202538 sgotplt = htab->root.sgotplt;
20212539 srelgot = htab->root.srelgot;
20222540 splt = htab->root.splt;
2541+ fdpic_p = htab->fdpic_p;
20232542 }
20242543 symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
20252544 sym_hashes = elf_sym_hashes (input_bfd);
20262545 relend = relocs + input_section->reloc_count;
20272546 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;
20302560
20312561 for (rel = relocs; rel < relend; rel ++)
20322562 {
@@ -2311,6 +2841,9 @@ rx_elf_relocate_section
23112841 || (r_type == R_RX_PLT
23122842 && h->plt.offset != (bfd_vma) -1)
23132843 || ((r_type == R_RX_GOT
2844+ || r_type == R_RX_GOTFUNCDESC
2845+ || r_type == R_RX_GOTOFFFUNCDESC
2846+ || r_type == R_RX_FUNCDESC)
23142847 && WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn,
23152848 bfd_link_pic (info),
23162849 h)
@@ -2339,7 +2872,7 @@ rx_elf_relocate_section
23392872 thus ld.so will not process them. */
23402873 || (sec->output_section == NULL
23412874 && ((input_section->flags & SEC_DEBUGGING) != 0
2342- && h->def_dynamic))))
2875+ && h->def_dynamic)))
23432876 ;
23442877 else if (sec->output_section != NULL)
23452878 relocation = (h->root.u.def.value
@@ -2384,6 +2917,16 @@ rx_elf_relocate_section
23842917 if (bfd_link_relocatable (info))
23852918 continue;
23862919
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+
23872930 #define RANGE(a,b) \
23882931 if (a > (long) relocation || (long) relocation > b) \
23892932 r = bfd_reloc_overflow
@@ -2646,6 +3189,108 @@ rx_elf_relocate_section
26463189 break;
26473190
26483191 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+ }
26493294 if (BIGE (output_bfd) && !(input_section->flags & SEC_CODE))
26503295 {
26513296 OP (3) = relocation;
@@ -3240,6 +3885,10 @@ rx_elf_relocate_section
32403885 #ifdef GOT_BIAS
32413886 relocation -= GOT_BIAS;
32423887 #endif
3888+ OP (0) = relocation;
3889+ OP (1) = relocation >> 8;
3890+ OP (2) = relocation >> 16;
3891+ OP (3) = relocation >> 24;
32433892
32443893 break;
32453894
@@ -3272,6 +3921,10 @@ rx_elf_relocate_section
32723921 #endif
32733922
32743923 addend = rel->r_addend;
3924+ OP (0) = relocation;
3925+ OP (1) = relocation >> 8;
3926+ OP (2) = relocation >> 16;
3927+ OP (3) = relocation >> 24;
32753928
32763929 break;
32773930
@@ -3315,11 +3968,306 @@ rx_elf_relocate_section
33153968 OP (2) = relocation >> 16;
33163969
33173970 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;
33184165
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+
33194246 default:
33204247 r = bfd_reloc_notsupported;
33214248 break;
33224249 }
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+ }
33234271
33244272 if (r != bfd_reloc_ok)
33254273 {
@@ -5974,6 +6922,8 @@ rx_additional_link_map_text (bfd *obfd, struct bfd_link_info *info, FILE *mapfil
59746922 #undef bfd_elf32_mkobject
59756923 #define bfd_elf32_mkobject rx_elf_mkobject
59766924
6925+#undef elf_backend_omit_section_dynsym
6926+#define elf_backend_omit_section_dynsym rx_elf_omit_section_dynsym
59776927 #undef elf_backend_create_dynamic_sections
59786928 #define elf_backend_create_dynamic_sections \
59796929 rx_elf_create_dynamic_sections
@@ -5983,6 +6933,9 @@ rx_additional_link_map_text (bfd *obfd, struct bfd_link_info *info, FILE *mapfil
59836933 #undef elf_backend_adjust_dynamic_symbol
59846934 #define elf_backend_adjust_dynamic_symbol \
59856935 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
59866939 #undef elf_backend_size_dynamic_sections
59876940 #define elf_backend_size_dynamic_sections \
59886941 rx_elf_size_dynamic_sections
@@ -5996,6 +6949,9 @@ rx_additional_link_map_text (bfd *obfd, struct bfd_link_info *info, FILE *mapfil
59966949 #define elf_backend_plt_sym_val rx_elf_plt_sym_val
59976950 #undef elf_backend_check_relocs
59986951 #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
59996955
60006956 #undef elf_backend_want_got_plt
60016957 #define elf_backend_want_got_plt 1
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -2484,6 +2484,9 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
24842484 "BFD_RELOC_RX_GOTOFF",
24852485 "BFD_RELOC_RX_PLT",
24862486 "BFD_RELOC_RX_GOTPC",
2487+ "BFD_RELOC_RX_GOTFUNCDESC",
2488+ "BFD_RELOC_RX_GOTOFFFUNCDESC",
2489+ "BFD_RELOC_RX_FUNCDESC",
24872490 "BFD_RELOC_390_12",
24882491 "BFD_RELOC_390_GOT12",
24892492 "BFD_RELOC_390_PLT32",
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -5369,6 +5369,12 @@ ENUMX
53695369 BFD_RELOC_RX_PLT
53705370 ENUMX
53715371 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
53725378 ENUMDOC
53735379 Renesas RX Relocations.
53745380
--- a/gas/config/tc-rx.c
+++ b/gas/config/tc-rx.c
@@ -40,6 +40,9 @@ const char line_separator_chars[] = "!";
4040
4141 const char EXP_CHARS[] = "eE";
4242 const char FLT_CHARS[] = "dD";
43+
44+/* Whether --fdpic was given. */
45+static bool fdpic = false;
4346
4447 #ifndef TE_LINUX
4548 bool rx_use_conventional_section_names = false;
@@ -76,6 +79,7 @@ enum options
7679 OPTION_USES_RX_ABI,
7780 OPTION_CPU,
7881 OPTION_DISALLOW_STRING_INSNS,
82+ OPTION_FDPIC,
7983 };
8084
8185 #define RX_SHORTOPTS ""
@@ -104,6 +108,7 @@ struct option md_longopts[] =
104108 {"mrx-abi", no_argument, NULL, OPTION_USES_RX_ABI},
105109 {"mcpu", required_argument, NULL, OPTION_CPU},
106110 {"mno-allow-string-insns", no_argument, NULL, OPTION_DISALLOW_STRING_INSNS},
111+ {"fdpic", no_argument, NULL, OPTION_FDPIC},
107112 {NULL, no_argument, NULL, 0}
108113 };
109114 size_t md_longopts_size = sizeof (md_longopts);
@@ -199,6 +204,9 @@ md_parse_option (int c ATTRIBUTE_UNUSED, const char * arg ATTRIBUTE_UNUSED)
199204 case OPTION_DISALLOW_STRING_INSNS:
200205 elf_flags |= E_FLAG_RX_SINSNS_SET | E_FLAG_RX_SINSNS_NO;
201206 return 1;
207+ case OPTION_FDPIC:
208+ fdpic = true;
209+ return 1;
202210 }
203211
204212 return 0;
@@ -219,7 +227,8 @@ md_show_usage (FILE * stream)
219227 fprintf (stream, _(" --mpid\n"));
220228 fprintf (stream, _(" --mint-register=<value>\n"));
221229 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"));
223232 }
224233
225234 static void
@@ -1162,6 +1171,9 @@ rx_parse_name (char const *name, expressionS *exprP,
11621171 { "GOT", BFD_RELOC_32_GOT_PCREL },
11631172 { "PLT", BFD_RELOC_32_PLT_PCREL },
11641173 { "PCREL", BFD_RELOC_32_PCREL },
1174+ { "GOTFUNCDESC", BFD_RELOC_RX_GOTFUNCDESC },
1175+ { "GOTOFFFUNCDESC", BFD_RELOC_RX_GOTOFFFUNCDESC },
1176+ { "FUNCDESC", BFD_RELOC_RX_FUNCDESC },
11651177 { NULL, -1 },
11661178 };
11671179 const struct suffix_list *s;
@@ -1276,7 +1288,8 @@ md_assemble (char * str)
12761288 APPEND (post, n_post);
12771289
12781290 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)
12801293 {
12811294 fixS * f;
12821295
@@ -2207,6 +2220,15 @@ md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
22072220 case BFD_RELOC_RX_GOTPC:
22082221 reloc_type = rxb->fixups[fi].exp.X_md;
22092222 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;
22102232 }
22112233 }
22122234 switch (nbytes)
@@ -2616,6 +2638,9 @@ md_apply_fix (struct fix * f ATTRIBUTE_UNUSED,
26162638 break;
26172639
26182640 case BFD_RELOC_32_GOT_PCREL:
2641+ case BFD_RELOC_RX_GOTFUNCDESC:
2642+ case BFD_RELOC_RX_GOTOFFFUNCDESC:
2643+ case BFD_RELOC_RX_FUNCDESC:
26192644 memset(op, 0x00, 4);
26202645 break;
26212646
@@ -2880,7 +2905,10 @@ rx_fix_adjustable (fixS *fixP)
28802905 {
28812906 if (fixP->fx_r_type == BFD_RELOC_32_PLT_PCREL
28822907 || 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)
28842912 return false;
28852913
28862914 return true;
@@ -2892,6 +2920,9 @@ void
28922920 rx_elf_final_processing (void)
28932921 {
28942922 elf_elfheader (stdoutput)->e_flags |= elf_flags;
2923+
2924+ if (fdpic)
2925+ elf_elfheader (stdoutput)->e_flags |= EF_RX_FDPIC;
28952926 }
28962927
28972928 /* Scan the current input line for occurrences of Renesas
--- a/include/elf/rx.h
+++ b/include/elf/rx.h
@@ -64,6 +64,10 @@ START_RELOC_NUMBERS (elf_rx_reloc_type)
6464 RELOC_NUMBER (R_RX_RELATIVE, 0x18)
6565 RELOC_NUMBER (R_RX_GOTOFF, 0x19)
6666 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)
6771
6872 /* These are extensions added by Red Hat. */
6973 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)
123127 #define EF_RX_CPU_RX 0x00000079 /* FIXME: this collides with the E_FLAG_RX_... values below. */
124128 #define EF_RX_CPU_MASK 0x000003FF /* specific cpu bits. */
125129 #define EF_RX_ALL_FLAGS (EF_RX_CPU_MASK)
130+#define EF_RX_PIC 0x1000
131+#define EF_RX_FDPIC 0x2000
126132
127133 /* Values for the e_flags field in the ELF header. */
128134 #define E_FLAG_RX_64BIT_DOUBLES (1 << 0)