From 394c62b21b1988b103ba61eb1b4dee534072fab4 Mon Sep 17 00:00:00 2001 From: Giulio Benetti Date: Mon, 3 May 2021 13:13:43 +0200 Subject: [PATCH] package/binutils: add upstream backported patches to support -mcmodel=large gcc option Add upstream backported patches that allows using -mcmodel=large gcc option that in order allows fixing build failure due to binutils bug 21464: https://sourceware.org/bugzilla/show_bug.cgi?id=21464 Signed-off-by: Giulio Benetti Signed-off-by: Arnout Vandecappelle (Essensium/Mind) [Arnout: remove the PATCH M/N parts - cfr. check-package] --- ...elocation-R_OR1K_GOT_AHI16-for-gotha.patch | 256 +++++++++ ...K_GOT16-overflow-failures-in-presenc.patch | 61 +++ ...ge-plt_relocs-when-generating-plt-en.patch | 500 ++++++++++++++++++ ...elocation-R_OR1K_GOT_AHI16-for-gotha.patch | 256 +++++++++ ...K_GOT16-overflow-failures-in-presenc.patch | 61 +++ ...ge-plt_relocs-when-generating-plt-en.patch | 500 ++++++++++++++++++ ...elocation-R_OR1K_GOT_AHI16-for-gotha.patch | 256 +++++++++ ...K_GOT16-overflow-failures-in-presenc.patch | 61 +++ ...ge-plt_relocs-when-generating-plt-en.patch | 500 ++++++++++++++++++ ...elocation-R_OR1K_GOT_AHI16-for-gotha.patch | 256 +++++++++ ...K_GOT16-overflow-failures-in-presenc.patch | 61 +++ ...ge-plt_relocs-when-generating-plt-en.patch | 500 ++++++++++++++++++ 12 files changed, 3268 insertions(+) create mode 100644 package/binutils/2.32/0011-or1k-Implement-relocation-R_OR1K_GOT_AHI16-for-gotha.patch create mode 100644 package/binutils/2.32/0012-or1k-Avoid-R_OR1K_GOT16-overflow-failures-in-presenc.patch create mode 100644 package/binutils/2.32/0013-or1k-Support-large-plt_relocs-when-generating-plt-en.patch create mode 100644 package/binutils/2.34/0004-or1k-Implement-relocation-R_OR1K_GOT_AHI16-for-gotha.patch create mode 100644 package/binutils/2.34/0005-or1k-Avoid-R_OR1K_GOT16-overflow-failures-in-presenc.patch create mode 100644 package/binutils/2.34/0006-or1k-Support-large-plt_relocs-when-generating-plt-en.patch create mode 100644 package/binutils/2.35.2/0004-or1k-Implement-relocation-R_OR1K_GOT_AHI16-for-gotha.patch create mode 100644 package/binutils/2.35.2/0005-or1k-Avoid-R_OR1K_GOT16-overflow-failures-in-presenc.patch create mode 100644 package/binutils/2.35.2/0006-or1k-Support-large-plt_relocs-when-generating-plt-en.patch create mode 100644 package/binutils/2.36.1/0004-or1k-Implement-relocation-R_OR1K_GOT_AHI16-for-gotha.patch create mode 100644 package/binutils/2.36.1/0005-or1k-Avoid-R_OR1K_GOT16-overflow-failures-in-presenc.patch create mode 100644 package/binutils/2.36.1/0006-or1k-Support-large-plt_relocs-when-generating-plt-en.patch diff --git a/package/binutils/2.32/0011-or1k-Implement-relocation-R_OR1K_GOT_AHI16-for-gotha.patch b/package/binutils/2.32/0011-or1k-Implement-relocation-R_OR1K_GOT_AHI16-for-gotha.patch new file mode 100644 index 0000000000..5a2b91fe8e --- /dev/null +++ b/package/binutils/2.32/0011-or1k-Implement-relocation-R_OR1K_GOT_AHI16-for-gotha.patch @@ -0,0 +1,256 @@ +From b10e6230dea0015bf3b7748580b82c551f9a3a4a Mon Sep 17 00:00:00 2001 +From: Stafford Horne +Date: Sun, 2 May 2021 06:02:15 +0900 +Subject: [PATCH] or1k: Implement relocation R_OR1K_GOT_AHI16 for gotha() + +The gotha() relocation mnemonic will be outputted by OpenRISC GCC when +using the -mcmodel=large option. This relocation is used along with +got() to generate 32-bit GOT offsets. This increases the previous GOT +offset limit from the previous 16-bit (64K) limit. + +This is needed on large binaries where the GOT grows larger than 64k. + +bfd/ChangeLog: + + PR 21464 + * bfd-in2.h: Add BFD_RELOC_OR1K_GOT_AHI16 relocation. + * elf32-or1k.c (or1k_elf_howto_table, or1k_reloc_map): Likewise. + (or1k_final_link_relocate, or1k_elf_relocate_section, + or1k_elf_check_relocs): Likewise. + * libbfd.h (bfd_reloc_code_real_names): Likewise. + * reloc.c: Likewise. + +cpu/ChangeLog: + + PR 21464 + * or1k.opc (or1k_imm16_relocs, parse_reloc): Define parse logic + for gotha() relocation. + +include/ChangeLog: + + PR 21464 + * elf/or1k.h (elf_or1k_reloc_type): Define R_OR1K_GOT_AHI16 number. + +opcodes/ChangeLog: + + PR 21464 + * or1k-asm.c: Regenerate. + +gas/ChangeLog: + + PR 21464 + * testsuite/gas/or1k/reloc-1.s: Add test for new relocation. + * testsuite/gas/or1k/reloc-1.d: Add test result for new + relocation. + +Cc: Giulio Benetti + +fixup reloc, add tests + +Signed-off-by: Giulio Benetti +--- + bfd/bfd-in2.h | 1 + + bfd/elf32-or1k.c | 21 ++++++++++++++++++++- + bfd/libbfd.h | 1 + + bfd/reloc.c | 2 ++ + cpu/or1k.opc | 7 ++++++- + gas/testsuite/gas/or1k/reloc-1.d | 4 +++- + gas/testsuite/gas/or1k/reloc-1.s | 4 ++++ + include/elf/or1k.h | 1 + + opcodes/or1k-asm.c | 7 ++++++- + 9 files changed, 44 insertions(+), 4 deletions(-) + +diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h +index e25da50aafb..530a41fca43 100644 +--- a/bfd/bfd-in2.h ++++ b/bfd/bfd-in2.h +@@ -5517,6 +5517,7 @@ then it may be truncated to 8 bits. */ + BFD_RELOC_OR1K_TLS_TPOFF, + BFD_RELOC_OR1K_TLS_DTPOFF, + BFD_RELOC_OR1K_TLS_DTPMOD, ++ BFD_RELOC_OR1K_GOT_AHI16, + + /* H8 elf Relocations. */ + BFD_RELOC_H8_DIR16A8, +diff --git a/bfd/elf32-or1k.c b/bfd/elf32-or1k.c +index 1f2c88b0b3a..a4a64f73b7c 100644 +--- a/bfd/elf32-or1k.c ++++ b/bfd/elf32-or1k.c +@@ -808,6 +808,20 @@ static reloc_howto_type or1k_elf_howto_table[] = + 0, /* Source Mask. */ + 0x03ffffff, /* Dest Mask. */ + TRUE), /* PC relative offset? */ ++ ++ HOWTO (R_OR1K_GOT_AHI16, /* type */ ++ 16, /* rightshift */ ++ 2, /* size (0 = byte, 1 = short, 2 = long) */ ++ 16, /* bitsize */ ++ FALSE, /* pc_relative */ ++ 0, /* bitpos */ ++ complain_overflow_signed, /* complain_on_overflow */ ++ bfd_elf_generic_reloc, /* special_function */ ++ "R_OR1K_GOT_AHI16", /* name */ ++ FALSE, /* partial_inplace */ ++ 0, /* src_mask */ ++ 0xffff, /* dst_mask */ ++ FALSE), /* pcrel_offset */ + }; + + /* Map BFD reloc types to Or1k ELF reloc types. */ +@@ -871,6 +885,7 @@ static const struct or1k_reloc_map or1k_reloc_map[] = + { BFD_RELOC_OR1K_TLS_IE_LO13, R_OR1K_TLS_IE_LO13 }, + { BFD_RELOC_OR1K_SLO13, R_OR1K_SLO13 }, + { BFD_RELOC_OR1K_PLTA26, R_OR1K_PLTA26 }, ++ { BFD_RELOC_OR1K_GOT_AHI16, R_OR1K_GOT_AHI16 }, + }; + + #define TLS_UNKNOWN 0 +@@ -1080,6 +1095,7 @@ or1k_final_link_relocate (reloc_howto_type *howto, bfd *input_bfd, + switch (howto->type) + { + case R_OR1K_AHI16: ++ case R_OR1K_GOT_AHI16: + case R_OR1K_GOTOFF_AHI16: + case R_OR1K_TLS_IE_AHI16: + case R_OR1K_TLS_LE_AHI16: +@@ -1344,6 +1360,7 @@ or1k_elf_relocate_section (bfd *output_bfd, + } + break; + ++ case R_OR1K_GOT_AHI16: + case R_OR1K_GOT16: + case R_OR1K_GOT_PG21: + case R_OR1K_GOT_LO13: +@@ -1435,7 +1452,8 @@ or1k_elf_relocate_section (bfd *output_bfd, + /* The GOT_PG21 and GOT_LO13 relocs are pc-relative, + while the GOT16 reloc is GOT relative. */ + relocation = got_base + off; +- if (r_type == R_OR1K_GOT16) ++ if (r_type == R_OR1K_GOT16 ++ || r_type == R_OR1K_GOT_AHI16) + relocation -= got_sym_value; + + /* Addend should be zero. */ +@@ -1945,6 +1963,7 @@ or1k_elf_check_relocs (bfd *abfd, + } + break; + ++ case R_OR1K_GOT_AHI16: + case R_OR1K_GOT16: + case R_OR1K_GOT_PG21: + case R_OR1K_GOT_LO13: +diff --git a/bfd/libbfd.h b/bfd/libbfd.h +index 36284d71a9b..6e9e3190bb8 100644 +--- a/bfd/libbfd.h ++++ b/bfd/libbfd.h +@@ -2702,6 +2702,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", + "BFD_RELOC_OR1K_TLS_TPOFF", + "BFD_RELOC_OR1K_TLS_DTPOFF", + "BFD_RELOC_OR1K_TLS_DTPMOD", ++ "BFD_RELOC_OR1K_GOT_AHI16", + "BFD_RELOC_H8_DIR16A8", + "BFD_RELOC_H8_DIR16R8", + "BFD_RELOC_H8_DIR24A8", +diff --git a/bfd/reloc.c b/bfd/reloc.c +index e6446a78098..b0003ab1175 100644 +--- a/bfd/reloc.c ++++ b/bfd/reloc.c +@@ -6164,6 +6164,8 @@ ENUMX + BFD_RELOC_OR1K_GOTPC_HI16 + ENUMX + BFD_RELOC_OR1K_GOTPC_LO16 ++ENUMX ++ BFD_RELOC_OR1K_GOT_AHI16 + ENUMX + BFD_RELOC_OR1K_GOT16 + ENUMX +diff --git a/cpu/or1k.opc b/cpu/or1k.opc +index 5082a30cee1..85163fc96c9 100644 +--- a/cpu/or1k.opc ++++ b/cpu/or1k.opc +@@ -173,7 +173,7 @@ static const bfd_reloc_code_real_type or1k_imm16_relocs[][6] = { + BFD_RELOC_OR1K_GOT_LO13, + BFD_RELOC_UNUSED, + BFD_RELOC_UNUSED, +- BFD_RELOC_UNUSED }, ++ BFD_RELOC_OR1K_GOT_AHI16 }, + { BFD_RELOC_OR1K_GOTPC_LO16, + BFD_RELOC_UNUSED, + BFD_RELOC_UNUSED, +@@ -276,6 +276,11 @@ parse_reloc (const char **strp) + str += 5; + cls = RCLASS_TPOFF; + } ++ else if (strncasecmp (str, "got", 3) == 0) ++ { ++ str += 3; ++ cls = RCLASS_GOT; ++ } + + if (strncasecmp (str, "hi(", 3) == 0) + { +diff --git a/gas/testsuite/gas/or1k/reloc-1.d b/gas/testsuite/gas/or1k/reloc-1.d +index d1bcf5608bb..3a001c4ed99 100644 +--- a/gas/testsuite/gas/or1k/reloc-1.d ++++ b/gas/testsuite/gas/or1k/reloc-1.d +@@ -68,5 +68,7 @@ OFFSET TYPE VALUE + 000000ec R_OR1K_LO13 x + 000000f0 R_OR1K_GOT_LO13 x + 000000f4 R_OR1K_SLO13 x +- ++000000f8 R_OR1K_GOT_AHI16 x ++000000fc R_OR1K_GOT_AHI16 x ++00000100 R_OR1K_GOT_AHI16 x + +diff --git a/gas/testsuite/gas/or1k/reloc-1.s b/gas/testsuite/gas/or1k/reloc-1.s +index e76abef6532..562609aa869 100644 +--- a/gas/testsuite/gas/or1k/reloc-1.s ++++ b/gas/testsuite/gas/or1k/reloc-1.s +@@ -74,3 +74,7 @@ + l.lbz r5,po(x)(r3) + l.lbz r5,gotpo(x)(r3) + l.sb po(x)(r3),r6 ++ ++ l.movhi r4,gotha(x) ++ l.ori r3,r4,gotha(x) ++ l.addi r3,r4,gotha(x) +diff --git a/include/elf/or1k.h b/include/elf/or1k.h +index 0abef046202..7db3cad18eb 100644 +--- a/include/elf/or1k.h ++++ b/include/elf/or1k.h +@@ -77,6 +77,7 @@ START_RELOC_NUMBERS (elf_or1k_reloc_type) + RELOC_NUMBER (R_OR1K_TLS_IE_LO13, 51) + RELOC_NUMBER (R_OR1K_SLO13, 52) + RELOC_NUMBER (R_OR1K_PLTA26, 53) ++ RELOC_NUMBER (R_OR1K_GOT_AHI16, 54) + END_RELOC_NUMBERS (R_OR1K_max) + + #define EF_OR1K_NODELAY (1UL << 0) +diff --git a/opcodes/or1k-asm.c b/opcodes/or1k-asm.c +index 7d058d03f5f..332f4b7a9b5 100644 +--- a/opcodes/or1k-asm.c ++++ b/opcodes/or1k-asm.c +@@ -177,7 +177,7 @@ static const bfd_reloc_code_real_type or1k_imm16_relocs[][6] = { + BFD_RELOC_OR1K_GOT_LO13, + BFD_RELOC_UNUSED, + BFD_RELOC_UNUSED, +- BFD_RELOC_UNUSED }, ++ BFD_RELOC_OR1K_GOT_AHI16 }, + { BFD_RELOC_OR1K_GOTPC_LO16, + BFD_RELOC_UNUSED, + BFD_RELOC_UNUSED, +@@ -280,6 +280,11 @@ parse_reloc (const char **strp) + str += 5; + cls = RCLASS_TPOFF; + } ++ else if (strncasecmp (str, "got", 3) == 0) ++ { ++ str += 3; ++ cls = RCLASS_GOT; ++ } + + if (strncasecmp (str, "hi(", 3) == 0) + { +-- +2.25.1 + diff --git a/package/binutils/2.32/0012-or1k-Avoid-R_OR1K_GOT16-overflow-failures-in-presenc.patch b/package/binutils/2.32/0012-or1k-Avoid-R_OR1K_GOT16-overflow-failures-in-presenc.patch new file mode 100644 index 0000000000..adc6f5f8b9 --- /dev/null +++ b/package/binutils/2.32/0012-or1k-Avoid-R_OR1K_GOT16-overflow-failures-in-presenc.patch @@ -0,0 +1,61 @@ +From 0f61f76454a9420f158f626cb09a4fbc08c3709e Mon Sep 17 00:00:00 2001 +From: Stafford Horne +Date: Sun, 2 May 2021 06:02:16 +0900 +Subject: [PATCH] or1k: Avoid R_OR1K_GOT16 overflow failures in presence + of R_OR1K_GOT_AHI16 + +Now that we support R_OR1K_GOT_AHI16 we can relax the R_OR1K_GOT16 +overflow validation check if the section has R_OR1K_GOT_AHI16. + +We cannot simple disable R_OR1K_GOT16 overflow validation as there will +still be binaries that will have only R_OR1K_GOT16. The +R_OR1K_GOT_AHI16 relocation will only be added by GCC when building with +the option -mcmodel=large. + +This assumes that R_OR1K_GOT_AHI16 will come before R_OR1K_GOT16, which +is the code pattern that will be emitted by GCC. + +bfd/ChangeLog: + + PR 21464 + * elf32-or1k.c (or1k_elf_relocate_section): Relax R_OR1K_GOT16 + overflow check if we have R_OR1K_GOT_AHI16 followed by + R_OR1K_GOT16. + +Signed-off-by: Giulio Benetti +--- + bfd/elf32-or1k.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/bfd/elf32-or1k.c b/bfd/elf32-or1k.c +index a4a64f73b7c..07fff3602a3 100644 +--- a/bfd/elf32-or1k.c ++++ b/bfd/elf32-or1k.c +@@ -1248,6 +1248,7 @@ or1k_elf_relocate_section (bfd *output_bfd, + asection *sgot, *splt; + bfd_vma plt_base, got_base, got_sym_value; + bfd_boolean ret_val = TRUE; ++ bfd_boolean saw_gotha = FALSE; + + if (htab == NULL) + return FALSE; +@@ -1456,6 +1457,16 @@ or1k_elf_relocate_section (bfd *output_bfd, + || r_type == R_OR1K_GOT_AHI16) + relocation -= got_sym_value; + ++ if (r_type == R_OR1K_GOT_AHI16) ++ saw_gotha = TRUE; ++ ++ /* If we have a R_OR1K_GOT16 followed by a R_OR1K_GOT_AHI16 ++ relocation we assume the code is doing the right thing to avoid ++ overflows. Here we mask the lower 16-bit of the relocation to ++ avoid overflow validation failures. */ ++ if (r_type == R_OR1K_GOT16 && saw_gotha) ++ relocation &= 0xffff; ++ + /* Addend should be zero. */ + if (rel->r_addend != 0) + { +-- +2.25.1 + diff --git a/package/binutils/2.32/0013-or1k-Support-large-plt_relocs-when-generating-plt-en.patch b/package/binutils/2.32/0013-or1k-Support-large-plt_relocs-when-generating-plt-en.patch new file mode 100644 index 0000000000..dc0431e0af --- /dev/null +++ b/package/binutils/2.32/0013-or1k-Support-large-plt_relocs-when-generating-plt-en.patch @@ -0,0 +1,500 @@ +From 36c7de7ef77ab0c30cb33e2c7ea7a6f4e3052c73 Mon Sep 17 00:00:00 2001 +From: Stafford Horne +Date: Sun, 2 May 2021 06:02:17 +0900 +Subject: [PATCH] or1k: Support large plt_relocs when generating plt + entries + +The current PLT generation code will generate invalid code when the PLT +relocation offset exceeds 64k. This fixes the issue by detecting large +plt_reloc offsets and generare code sequences to create larger plt +relocations. + +The "large" plt code needs 2 extra instructions to create 32-bit offsets. + +bfd/ChangeLog: + + PR 27746 + * elf32-or1k.c (PLT_ENTRY_SIZE_LARGE, PLT_MAX_INSN_COUNT, + OR1K_ADD, OR1K_ORI): New macros to help with plt creation. + (elf_or1k_link_hash_table): New field plt_count. + (elf_or1k_link_hash_entry): New field plt_index. + (elf_or1k_plt_entry_size): New function. + (or1k_write_plt_entry): Update to support variable size PLTs. + (or1k_elf_finish_dynamic_sections): Use new or1k_write_plt_entry + API. + (or1k_elf_finish_dynamic_symbol): Update to write large PLTs + when needed. + (allocate_dynrelocs): Use elf_or1k_plt_entry_size to account for + PLT size. + +ld/ChangeLog: + + PR 27746 + testsuite/ld-or1k/or1k.exp (or1kplttests): Add tests for linking + along with gotha() relocations. + testsuite/ld-or1k/gotha1.dd: New file. + testsuite/ld-or1k/gotha1.s: New file. + testsuite/ld-or1k/gotha2.dd: New file. + testsuite/ld-or1k/gotha2.s: New file + testsuite/ld-or1k/pltlib.s (x): Define size to avoid link + failure. + +Signed-off-by: Giulio Benetti +--- + bfd/elf32-or1k.c | 149 ++++++++++++++++++++++++--------- + ld/testsuite/ld-or1k/gotha1.dd | 34 ++++++++ + ld/testsuite/ld-or1k/gotha1.s | 24 ++++++ + ld/testsuite/ld-or1k/gotha2.dd | 21 +++++ + ld/testsuite/ld-or1k/gotha2.s | 22 +++++ + ld/testsuite/ld-or1k/or1k.exp | 8 ++ + ld/testsuite/ld-or1k/pltlib.s | 1 + + 7 files changed, 220 insertions(+), 39 deletions(-) + create mode 100644 ld/testsuite/ld-or1k/gotha1.dd + create mode 100644 ld/testsuite/ld-or1k/gotha1.s + create mode 100644 ld/testsuite/ld-or1k/gotha2.dd + create mode 100644 ld/testsuite/ld-or1k/gotha2.s + +diff --git a/bfd/elf32-or1k.c b/bfd/elf32-or1k.c +index 07fff3602a3..fcebbe5f23a 100644 +--- a/bfd/elf32-or1k.c ++++ b/bfd/elf32-or1k.c +@@ -30,10 +30,14 @@ + #define N_ONES(X) (((bfd_vma)2 << (X)) - 1) + + #define PLT_ENTRY_SIZE 16 ++#define PLT_ENTRY_SIZE_LARGE (6*4) ++#define PLT_MAX_INSN_COUNT 6 + + #define OR1K_MOVHI(D) (0x18000000 | (D << 21)) + #define OR1K_ADRP(D) (0x08000000 | (D << 21)) + #define OR1K_LWZ(D,A) (0x84000000 | (D << 21) | (A << 16)) ++#define OR1K_ADD(D,A,B) (0xE0000000 | (D << 21) | (A << 16) | (B << 11)) ++#define OR1K_ORI(D,A) (0xA8000000 | (D << 21) | (A << 16)) + #define OR1K_ORI0(D) (0xA8000000 | (D << 21)) + #define OR1K_JR(B) (0x44000000 | (B << 11)) + #define OR1K_NOP 0x15000000 +@@ -903,6 +907,8 @@ struct elf_or1k_link_hash_entry + /* Track dynamic relocs copied for this symbol. */ + struct elf_dyn_relocs *dyn_relocs; + ++ /* For calculating PLT size. */ ++ bfd_vma plt_index; + /* Track type of TLS access. */ + unsigned char tls_type; + }; +@@ -930,9 +936,20 @@ struct elf_or1k_link_hash_table + /* Small local sym to section mapping cache. */ + struct sym_cache sym_sec; + ++ bfd_vma plt_count; + bfd_boolean saw_plta; + }; + ++static size_t ++elf_or1k_plt_entry_size (bfd_vma plt_index) ++{ ++ bfd_vma plt_reloc; ++ ++ plt_reloc = plt_index * sizeof (Elf32_External_Rela); ++ ++ return (plt_reloc > 0xffff) ? PLT_ENTRY_SIZE_LARGE : PLT_ENTRY_SIZE; ++} ++ + /* Get the ELF linker hash table from a link_info structure. */ + #define or1k_elf_hash_table(p) \ + (elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) \ +@@ -2176,33 +2193,46 @@ or1k_elf_check_relocs (bfd *abfd, + } + + static void +-or1k_write_plt_entry (bfd *output_bfd, bfd_byte *contents, unsigned insn1, +- unsigned insn2, unsigned insn3, unsigned insnj) ++or1k_write_plt_entry (bfd *output_bfd, bfd_byte *contents, unsigned insnj, ++ unsigned insns[], size_t insn_count) + { + unsigned nodelay = elf_elfheader (output_bfd)->e_flags & EF_OR1K_NODELAY; +- unsigned insn4; ++ unsigned output_insns[PLT_MAX_INSN_COUNT]; ++ ++ /* Copy instructions into the output buffer. */ ++ for (size_t i = 0; i < insn_count; i++) ++ output_insns[i] = insns[i]; + + /* Honor the no-delay-slot setting. */ +- if (insn3 == OR1K_NOP) ++ if (insns[insn_count-1] == OR1K_NOP) + { +- insn4 = insn3; ++ unsigned slot1, slot2; ++ + if (nodelay) +- insn3 = insnj; ++ slot1 = insns[insn_count-2], slot2 = insnj; + else +- insn3 = insn2, insn2 = insnj; ++ slot1 = insnj, slot2 = insns[insn_count-2]; ++ ++ output_insns[insn_count-2] = slot1; ++ output_insns[insn_count-1] = slot2; ++ output_insns[insn_count] = OR1K_NOP; + } + else + { ++ unsigned slot1, slot2; ++ + if (nodelay) +- insn4 = insnj; ++ slot1 = insns[insn_count-1], slot2 = insnj; + else +- insn4 = insn3, insn3 = insnj; ++ slot1 = insnj, slot2 = insns[insn_count-1]; ++ ++ output_insns[insn_count-1] = slot1; ++ output_insns[insn_count] = slot2; + } + +- bfd_put_32 (output_bfd, insn1, contents); +- bfd_put_32 (output_bfd, insn2, contents + 4); +- bfd_put_32 (output_bfd, insn3, contents + 8); +- bfd_put_32 (output_bfd, insn4, contents + 12); ++ /* Write out the output buffer. */ ++ for (size_t i = 0; i < (insn_count+1); i++) ++ bfd_put_32 (output_bfd, output_insns[i], contents + (i*4)); + } + + /* Finish up the dynamic sections. */ +@@ -2269,7 +2299,8 @@ or1k_elf_finish_dynamic_sections (bfd *output_bfd, + splt = htab->root.splt; + if (splt && splt->size > 0) + { +- unsigned plt0, plt1, plt2; ++ unsigned plt[PLT_MAX_INSN_COUNT]; ++ size_t plt_insn_count = 3; + bfd_vma got_addr = sgot->output_section->vma + sgot->output_offset; + + /* Note we force 16 byte alignment on the .got, so that +@@ -2280,27 +2311,27 @@ or1k_elf_finish_dynamic_sections (bfd *output_bfd, + bfd_vma pc = splt->output_section->vma + splt->output_offset; + unsigned pa = ((got_addr >> 13) - (pc >> 13)) & 0x1fffff; + unsigned po = got_addr & 0x1fff; +- plt0 = OR1K_ADRP(12) | pa; +- plt1 = OR1K_LWZ(15,12) | (po + 8); +- plt2 = OR1K_LWZ(12,12) | (po + 4); ++ plt[0] = OR1K_ADRP(12) | pa; ++ plt[1] = OR1K_LWZ(15,12) | (po + 8); ++ plt[2] = OR1K_LWZ(12,12) | (po + 4); + } + else if (bfd_link_pic (info)) + { +- plt0 = OR1K_LWZ(15, 16) | 8; /* .got+8 */ +- plt1 = OR1K_LWZ(12, 16) | 4; /* .got+4 */ +- plt2 = OR1K_NOP; ++ plt[0] = OR1K_LWZ(15, 16) | 8; /* .got+8 */ ++ plt[1] = OR1K_LWZ(12, 16) | 4; /* .got+4 */ ++ plt[2] = OR1K_NOP; + } + else + { + unsigned ha = ((got_addr + 0x8000) >> 16) & 0xffff; + unsigned lo = got_addr & 0xffff; +- plt0 = OR1K_MOVHI(12) | ha; +- plt1 = OR1K_LWZ(15,12) | (lo + 8); +- plt2 = OR1K_LWZ(12,12) | (lo + 4); ++ plt[0] = OR1K_MOVHI(12) | ha; ++ plt[1] = OR1K_LWZ(15,12) | (lo + 8); ++ plt[2] = OR1K_LWZ(12,12) | (lo + 4); + } + +- or1k_write_plt_entry (output_bfd, splt->contents, +- plt0, plt1, plt2, OR1K_JR(15)); ++ or1k_write_plt_entry (output_bfd, splt->contents, OR1K_JR(15), ++ plt, plt_insn_count); + + elf_section_data (splt->output_section)->this_hdr.sh_entsize = 4; + } +@@ -2343,7 +2374,8 @@ or1k_elf_finish_dynamic_symbol (bfd *output_bfd, + + if (h->plt.offset != (bfd_vma) -1) + { +- unsigned int plt0, plt1, plt2; ++ unsigned int plt[PLT_MAX_INSN_COUNT]; ++ size_t plt_insn_count = 3; + asection *splt; + asection *sgot; + asection *srela; +@@ -2355,6 +2387,7 @@ or1k_elf_finish_dynamic_symbol (bfd *output_bfd, + bfd_vma got_offset; + bfd_vma got_addr; + Elf_Internal_Rela rela; ++ bfd_boolean large_plt_entry; + + /* This symbol has an entry in the procedure linkage table. Set + it up. */ +@@ -2372,10 +2405,13 @@ or1k_elf_finish_dynamic_symbol (bfd *output_bfd, + corresponds to this symbol. This is the index of this symbol + in all the symbols for which we are making plt entries. The + first entry in the procedure linkage table is reserved. */ +- plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1; ++ plt_index = ((struct elf_or1k_link_hash_entry *) h)->plt_index; + plt_addr = plt_base_addr + h->plt.offset; + plt_reloc = plt_index * sizeof (Elf32_External_Rela); + ++ large_plt_entry = (elf_or1k_plt_entry_size (plt_index) ++ == PLT_ENTRY_SIZE_LARGE); ++ + /* Get the offset into the .got table of the entry that + corresponds to this function. Each .got entry is 4 bytes. + The first three are reserved. */ +@@ -2387,27 +2423,57 @@ or1k_elf_finish_dynamic_symbol (bfd *output_bfd, + { + unsigned pa = ((got_addr >> 13) - (plt_addr >> 13)) & 0x1fffff; + unsigned po = (got_addr & 0x1fff); +- plt0 = OR1K_ADRP(12) | pa; +- plt1 = OR1K_LWZ(12,12) | po; +- plt2 = OR1K_ORI0(11) | plt_reloc; ++ plt[0] = OR1K_ADRP(12) | pa; ++ plt[1] = OR1K_LWZ(12,12) | po; ++ plt[2] = OR1K_ORI0(11) | plt_reloc; + } + else if (bfd_link_pic (info)) + { +- plt0 = OR1K_LWZ(12,16) | got_offset; +- plt1 = OR1K_ORI0(11) | plt_reloc; +- plt2 = OR1K_NOP; ++ if (large_plt_entry) ++ { ++ unsigned gotha = ((got_offset + 0x8000) >> 16) & 0xffff; ++ unsigned got = got_offset & 0xffff; ++ unsigned pltrelhi = (plt_reloc >> 16) & 0xffff; ++ unsigned pltrello = plt_reloc & 0xffff; ++ ++ plt[0] = OR1K_MOVHI(12) | gotha; ++ plt[1] = OR1K_ADD(12,12,16); ++ plt[2] = OR1K_LWZ(12,12) | got; ++ plt[3] = OR1K_MOVHI(11) | pltrelhi; ++ plt[4] = OR1K_ORI(11,11) | pltrello; ++ plt_insn_count = 5; ++ } ++ else ++ { ++ plt[0] = OR1K_LWZ(12,16) | got_offset; ++ plt[1] = OR1K_ORI0(11) | plt_reloc; ++ plt[2] = OR1K_NOP; ++ } + } + else + { + unsigned ha = ((got_addr + 0x8000) >> 16) & 0xffff; + unsigned lo = got_addr & 0xffff; +- plt0 = OR1K_MOVHI(12) | ha; +- plt1 = OR1K_LWZ(12,12) | lo; +- plt2 = OR1K_ORI0(11) | plt_reloc; ++ plt[0] = OR1K_MOVHI(12) | ha; ++ plt[1] = OR1K_LWZ(12,12) | lo; ++ plt[2] = OR1K_ORI0(11) | plt_reloc; ++ } ++ ++ /* For large code model we fixup the non-PIC PLT relocation instructions ++ here. */ ++ if (large_plt_entry && !bfd_link_pic (info)) ++ { ++ unsigned pltrelhi = (plt_reloc >> 16) & 0xffff; ++ unsigned pltrello = plt_reloc & 0xffff; ++ ++ plt[2] = OR1K_MOVHI(11) | pltrelhi; ++ plt[3] = OR1K_ORI(11,11) | pltrello; ++ plt[4] = OR1K_NOP; ++ plt_insn_count = 5; + } + + or1k_write_plt_entry (output_bfd, splt->contents + h->plt.offset, +- plt0, plt1, plt2, OR1K_JR(12)); ++ OR1K_JR(12), plt, plt_insn_count); + + /* Fill in the entry in the global offset table. */ + bfd_put_32 (output_bfd, plt_addr, sgot->contents + got_offset); +@@ -2699,11 +2765,16 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) + if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info), h)) + { + asection *s = htab->root.splt; ++ bfd_vma plt_index; ++ ++ /* Track the index of our plt entry for use in calculating size. */ ++ plt_index = htab->plt_count++; ++ ((struct elf_or1k_link_hash_entry *) h)->plt_index = plt_index; + + /* If this is the first .plt entry, make room for the special + first entry. */ + if (s->size == 0) +- s->size = PLT_ENTRY_SIZE; ++ s->size = elf_or1k_plt_entry_size (plt_index); + + h->plt.offset = s->size; + +@@ -2720,7 +2791,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) + } + + /* Make room for this entry. */ +- s->size += PLT_ENTRY_SIZE; ++ s->size += elf_or1k_plt_entry_size (plt_index); + + /* We also need to make an entry in the .got.plt section, which + will be placed in the .got section by the linker script. */ +diff --git a/ld/testsuite/ld-or1k/gotha1.dd b/ld/testsuite/ld-or1k/gotha1.dd +new file mode 100644 +index 00000000000..0ad1f8f5399 +--- /dev/null ++++ b/ld/testsuite/ld-or1k/gotha1.dd +@@ -0,0 +1,34 @@ ++ ++.*\.x: file format elf32-or1k ++ ++ ++Disassembly of section \.plt: ++ ++[0-9a-f]+ <\.plt>: ++ +[0-9a-f]+: 19 80 00 00 l\.movhi r12,0x0 ++ +[0-9a-f]+: 85 ec [0-9a-f]+ [0-9a-f]+ l\.lwz r15,[0-9]+\(r12\) ++ +[0-9a-f]+: 44 00 78 00 l\.jr r15 ++ +[0-9a-f]+: 85 8c [0-9a-f]+ [0-9a-f]+ l\.lwz r12,[0-9]+\(r12\) ++ +[0-9a-f]+: 19 80 00 00 l\.movhi r12,0x0 ++ +[0-9a-f]+: 85 8c [0-9a-f]+ [0-9a-f]+ l\.lwz r12,[0-9]+\(r12\) ++ +[0-9a-f]+: 44 00 60 00 l\.jr r12 ++ +[0-9a-f]+: a9 60 00 00 l\.ori r11,r0,0x0 ++ ++Disassembly of section \.text: ++ ++[0-9a-f]+ <_start>: ++ +[0-9a-f]+: 9c 21 ff fc l\.addi r1,r1,-4 ++ +[0-9a-f]+: d4 01 48 00 l\.sw 0\(r1\),r9 ++ +[0-9a-f]+: 04 00 00 02 l\.jal [0-9a-f]+ <_start\+0x10> ++ +[0-9a-f]+: 1a 60 00 00 l\.movhi r19,0x0 ++ +[0-9a-f]+: aa 73 [0-9a-f]+ [0-9a-f]+ l\.ori r19,r19,0x[0-9a-f]+ ++ +[0-9a-f]+: e2 73 48 00 l\.add r19,r19,r9 ++ +[0-9a-f]+: 1a 20 00 00 l\.movhi r17,0x0 ++ +[0-9a-f]+: e2 31 98 00 l\.add r17,r17,r19 ++ +[0-9a-f]+: 86 31 00 10 l\.lwz r17,16\(r17\) ++ +[0-9a-f]+: 84 71 00 00 l\.lwz r3,0\(r17\) ++ +[0-9a-f]+: 07 ff ff f2 l\.jal [0-9a-f]+ <\.plt\+0x10> ++ +[0-9a-f]+: 15 00 00 00 l\.nop 0x0 ++ +[0-9a-f]+: 85 21 00 00 l\.lwz r9,0\(r1\) ++ +[0-9a-f]+: 44 00 48 00 l\.jr r9 ++ +[0-9a-f]+: 9c 21 00 04 l\.addi r1,r1,4 +diff --git a/ld/testsuite/ld-or1k/gotha1.s b/ld/testsuite/ld-or1k/gotha1.s +new file mode 100644 +index 00000000000..42b16db425c +--- /dev/null ++++ b/ld/testsuite/ld-or1k/gotha1.s +@@ -0,0 +1,24 @@ ++ .data ++ .p2align 16 ++ ++ .text ++ .globl _start ++_start: ++ l.addi r1, r1, -4 ++ l.sw 0(r1), r9 ++ ++ l.jal 8 ++ l.movhi r19, gotpchi(_GLOBAL_OFFSET_TABLE_-4) ++ l.ori r19, r19, gotpclo(_GLOBAL_OFFSET_TABLE_+0) ++ l.add r19, r19, r9 ++ ++ l.movhi r17, gotha(x) ++ l.add r17, r17, r19 ++ l.lwz r17, got(x)(r17) ++ l.lwz r3, 0(r17) ++ ++ l.jal plt(func) ++ l.nop ++ l.lwz r9, 0(r1) ++ l.jr r9 ++ l.addi r1, r1, 4 +diff --git a/ld/testsuite/ld-or1k/gotha2.dd b/ld/testsuite/ld-or1k/gotha2.dd +new file mode 100644 +index 00000000000..fe09da5466b +--- /dev/null ++++ b/ld/testsuite/ld-or1k/gotha2.dd +@@ -0,0 +1,21 @@ ++ ++.*\.x: file format elf32-or1k ++ ++ ++Disassembly of section \.text: ++ ++[0-9a-f]+ : ++ +[0-9a-f]+: 9c 21 ff f8 l\.addi r1,r1,-8 ++ +[0-9a-f]+: d4 01 80 00 l\.sw 0\(r1\),r16 ++ +[0-9a-f]+: d4 01 48 04 l\.sw 4\(r1\),r9 ++ +[0-9a-f]+: 04 00 [0-9a-f]+ [0-9a-f]+ l\.jal [0-9a-f]+ ++ +[0-9a-f]+: 1a 00 00 00 l\.movhi r16,0x0 ++ +[0-9a-f]+: aa 10 [0-9a-f]+ [0-9a-f]+ l\.ori r16,r16,0x[0-9a-f]+ ++ +[0-9a-f]+: e2 10 48 00 l\.add r16,r16,r9 ++ +[0-9a-f]+: 1a 20 00 00 l\.movhi r17,0x0 ++ +[0-9a-f]+: e2 31 80 00 l\.add r17,r17,r16 ++ +[0-9a-f]+: 86 31 00 0c l\.lwz r17,12\(r17\) ++ +[0-9a-f]+: 85 21 00 04 l\.lwz r9,4\(r1\) ++ +[0-9a-f]+: 86 01 00 00 l\.lwz r16,0\(r1\) ++ +[0-9a-f]+: 44 00 48 00 l\.jr r9 ++ +[0-9a-f]+: 9c 21 00 08 l\.addi r1,r1,8 +diff --git a/ld/testsuite/ld-or1k/gotha2.s b/ld/testsuite/ld-or1k/gotha2.s +new file mode 100644 +index 00000000000..164b282f2dd +--- /dev/null ++++ b/ld/testsuite/ld-or1k/gotha2.s +@@ -0,0 +1,22 @@ ++ .section .text ++ .align 4 ++ .global test ++ .type test, @function ++test: ++ l.addi r1, r1, -8 ++ l.sw 0(r1), r16 ++ l.sw 4(r1), r9 ++ ++ l.jal 8 ++ l.movhi r16, gotpchi(_GLOBAL_OFFSET_TABLE_-4) ++ l.ori r16, r16, gotpclo(_GLOBAL_OFFSET_TABLE_+0) ++ l.add r16, r16, r9 ++ ++ l.movhi r17, gotha(i) ++ l.add r17, r17, r16 ++ l.lwz r17, got(i)(r17) ++ ++ l.lwz r9, 4(r1) ++ l.lwz r16, 0(r1) ++ l.jr r9 ++ l.addi r1, r1, 8 +diff --git a/ld/testsuite/ld-or1k/or1k.exp b/ld/testsuite/ld-or1k/or1k.exp +index 24cdbe5fbf3..9cebc49b946 100644 +--- a/ld/testsuite/ld-or1k/or1k.exp ++++ b/ld/testsuite/ld-or1k/or1k.exp +@@ -53,6 +53,14 @@ set or1kplttests { + "" {plt1.s} + {{objdump -dr plt1.x.dd}} + "plt1.x"} ++ {"gotha exec plt" "tmpdir/libpltlib.so" "" ++ "" {gotha1.s} ++ {{objdump -dr gotha1.dd}} ++ "gotha1.x"} ++ {"gotha -fpic -shared" "-fpic -shared" "" ++ "" {gotha2.s} ++ {{objdump -dr gotha2.dd}} ++ "gotha2.x"} + } + + # Not implemented yet +diff --git a/ld/testsuite/ld-or1k/pltlib.s b/ld/testsuite/ld-or1k/pltlib.s +index baf76ca1af7..8b4d7ba48fd 100644 +--- a/ld/testsuite/ld-or1k/pltlib.s ++++ b/ld/testsuite/ld-or1k/pltlib.s +@@ -1,5 +1,6 @@ + .section .data + .globl x, y ++ .size x, 4 + x: .long 33 + y: .long 44 + +-- +2.25.1 + diff --git a/package/binutils/2.34/0004-or1k-Implement-relocation-R_OR1K_GOT_AHI16-for-gotha.patch b/package/binutils/2.34/0004-or1k-Implement-relocation-R_OR1K_GOT_AHI16-for-gotha.patch new file mode 100644 index 0000000000..5edef90e1d --- /dev/null +++ b/package/binutils/2.34/0004-or1k-Implement-relocation-R_OR1K_GOT_AHI16-for-gotha.patch @@ -0,0 +1,256 @@ +From 5fb945116ba058eb8f032f94ab2e0c71024388ec Mon Sep 17 00:00:00 2001 +From: Stafford Horne +Date: Sun, 2 May 2021 06:02:15 +0900 +Subject: [PATCH] or1k: Implement relocation R_OR1K_GOT_AHI16 for gotha() + +The gotha() relocation mnemonic will be outputted by OpenRISC GCC when +using the -mcmodel=large option. This relocation is used along with +got() to generate 32-bit GOT offsets. This increases the previous GOT +offset limit from the previous 16-bit (64K) limit. + +This is needed on large binaries where the GOT grows larger than 64k. + +bfd/ChangeLog: + + PR 21464 + * bfd-in2.h: Add BFD_RELOC_OR1K_GOT_AHI16 relocation. + * elf32-or1k.c (or1k_elf_howto_table, or1k_reloc_map): Likewise. + (or1k_final_link_relocate, or1k_elf_relocate_section, + or1k_elf_check_relocs): Likewise. + * libbfd.h (bfd_reloc_code_real_names): Likewise. + * reloc.c: Likewise. + +cpu/ChangeLog: + + PR 21464 + * or1k.opc (or1k_imm16_relocs, parse_reloc): Define parse logic + for gotha() relocation. + +include/ChangeLog: + + PR 21464 + * elf/or1k.h (elf_or1k_reloc_type): Define R_OR1K_GOT_AHI16 number. + +opcodes/ChangeLog: + + PR 21464 + * or1k-asm.c: Regenerate. + +gas/ChangeLog: + + PR 21464 + * testsuite/gas/or1k/reloc-1.s: Add test for new relocation. + * testsuite/gas/or1k/reloc-1.d: Add test result for new + relocation. + +Cc: Giulio Benetti + +fixup reloc, add tests + +Signed-off-by: Giulio Benetti +--- + bfd/bfd-in2.h | 1 + + bfd/elf32-or1k.c | 21 ++++++++++++++++++++- + bfd/libbfd.h | 1 + + bfd/reloc.c | 2 ++ + cpu/or1k.opc | 7 ++++++- + gas/testsuite/gas/or1k/reloc-1.d | 4 +++- + gas/testsuite/gas/or1k/reloc-1.s | 4 ++++ + include/elf/or1k.h | 1 + + opcodes/or1k-asm.c | 7 ++++++- + 9 files changed, 44 insertions(+), 4 deletions(-) + +diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h +index 7c13bc8c91a..ae1082a67c2 100644 +--- a/bfd/bfd-in2.h ++++ b/bfd/bfd-in2.h +@@ -5017,6 +5017,7 @@ then it may be truncated to 8 bits. */ + BFD_RELOC_OR1K_TLS_TPOFF, + BFD_RELOC_OR1K_TLS_DTPOFF, + BFD_RELOC_OR1K_TLS_DTPMOD, ++ BFD_RELOC_OR1K_GOT_AHI16, + + /* H8 elf Relocations. */ + BFD_RELOC_H8_DIR16A8, +diff --git a/bfd/elf32-or1k.c b/bfd/elf32-or1k.c +index 58246875546..1273fbacb3c 100644 +--- a/bfd/elf32-or1k.c ++++ b/bfd/elf32-or1k.c +@@ -808,6 +808,20 @@ static reloc_howto_type or1k_elf_howto_table[] = + 0, /* Source Mask. */ + 0x03ffffff, /* Dest Mask. */ + TRUE), /* PC relative offset? */ ++ ++ HOWTO (R_OR1K_GOT_AHI16, /* type */ ++ 16, /* rightshift */ ++ 2, /* size (0 = byte, 1 = short, 2 = long) */ ++ 16, /* bitsize */ ++ FALSE, /* pc_relative */ ++ 0, /* bitpos */ ++ complain_overflow_signed, /* complain_on_overflow */ ++ bfd_elf_generic_reloc, /* special_function */ ++ "R_OR1K_GOT_AHI16", /* name */ ++ FALSE, /* partial_inplace */ ++ 0, /* src_mask */ ++ 0xffff, /* dst_mask */ ++ FALSE), /* pcrel_offset */ + }; + + /* Map BFD reloc types to Or1k ELF reloc types. */ +@@ -871,6 +885,7 @@ static const struct or1k_reloc_map or1k_reloc_map[] = + { BFD_RELOC_OR1K_TLS_IE_LO13, R_OR1K_TLS_IE_LO13 }, + { BFD_RELOC_OR1K_SLO13, R_OR1K_SLO13 }, + { BFD_RELOC_OR1K_PLTA26, R_OR1K_PLTA26 }, ++ { BFD_RELOC_OR1K_GOT_AHI16, R_OR1K_GOT_AHI16 }, + }; + + #define TLS_UNKNOWN 0 +@@ -1080,6 +1095,7 @@ or1k_final_link_relocate (reloc_howto_type *howto, bfd *input_bfd, + switch (howto->type) + { + case R_OR1K_AHI16: ++ case R_OR1K_GOT_AHI16: + case R_OR1K_GOTOFF_AHI16: + case R_OR1K_TLS_IE_AHI16: + case R_OR1K_TLS_LE_AHI16: +@@ -1344,6 +1360,7 @@ or1k_elf_relocate_section (bfd *output_bfd, + } + break; + ++ case R_OR1K_GOT_AHI16: + case R_OR1K_GOT16: + case R_OR1K_GOT_PG21: + case R_OR1K_GOT_LO13: +@@ -1435,7 +1452,8 @@ or1k_elf_relocate_section (bfd *output_bfd, + /* The GOT_PG21 and GOT_LO13 relocs are pc-relative, + while the GOT16 reloc is GOT relative. */ + relocation = got_base + off; +- if (r_type == R_OR1K_GOT16) ++ if (r_type == R_OR1K_GOT16 ++ || r_type == R_OR1K_GOT_AHI16) + relocation -= got_sym_value; + + /* Addend should be zero. */ +@@ -1943,6 +1961,7 @@ or1k_elf_check_relocs (bfd *abfd, + } + break; + ++ case R_OR1K_GOT_AHI16: + case R_OR1K_GOT16: + case R_OR1K_GOT_PG21: + case R_OR1K_GOT_LO13: +diff --git a/bfd/libbfd.h b/bfd/libbfd.h +index d97d4e57a77..9edc71e0558 100644 +--- a/bfd/libbfd.h ++++ b/bfd/libbfd.h +@@ -2704,6 +2704,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", + "BFD_RELOC_OR1K_TLS_TPOFF", + "BFD_RELOC_OR1K_TLS_DTPOFF", + "BFD_RELOC_OR1K_TLS_DTPMOD", ++ "BFD_RELOC_OR1K_GOT_AHI16", + "BFD_RELOC_H8_DIR16A8", + "BFD_RELOC_H8_DIR16R8", + "BFD_RELOC_H8_DIR24A8", +diff --git a/bfd/reloc.c b/bfd/reloc.c +index 33cd67150cf..f57ad14a501 100644 +--- a/bfd/reloc.c ++++ b/bfd/reloc.c +@@ -6175,6 +6175,8 @@ ENUMX + BFD_RELOC_OR1K_GOTPC_HI16 + ENUMX + BFD_RELOC_OR1K_GOTPC_LO16 ++ENUMX ++ BFD_RELOC_OR1K_GOT_AHI16 + ENUMX + BFD_RELOC_OR1K_GOT16 + ENUMX +diff --git a/cpu/or1k.opc b/cpu/or1k.opc +index f0adcbb00a5..5d20a1f33a7 100644 +--- a/cpu/or1k.opc ++++ b/cpu/or1k.opc +@@ -193,7 +193,7 @@ static const bfd_reloc_code_real_type or1k_imm16_relocs[][6] = { + BFD_RELOC_OR1K_GOT_LO13, + BFD_RELOC_UNUSED, + BFD_RELOC_UNUSED, +- BFD_RELOC_UNUSED }, ++ BFD_RELOC_OR1K_GOT_AHI16 }, + { BFD_RELOC_OR1K_GOTPC_LO16, + BFD_RELOC_UNUSED, + BFD_RELOC_UNUSED, +@@ -296,6 +296,11 @@ parse_reloc (const char **strp) + str += 5; + cls = RCLASS_TPOFF; + } ++ else if (strncasecmp (str, "got", 3) == 0) ++ { ++ str += 3; ++ cls = RCLASS_GOT; ++ } + + if (strncasecmp (str, "hi(", 3) == 0) + { +diff --git a/gas/testsuite/gas/or1k/reloc-1.d b/gas/testsuite/gas/or1k/reloc-1.d +index d1bcf5608bb..3a001c4ed99 100644 +--- a/gas/testsuite/gas/or1k/reloc-1.d ++++ b/gas/testsuite/gas/or1k/reloc-1.d +@@ -68,5 +68,7 @@ OFFSET TYPE VALUE + 000000ec R_OR1K_LO13 x + 000000f0 R_OR1K_GOT_LO13 x + 000000f4 R_OR1K_SLO13 x +- ++000000f8 R_OR1K_GOT_AHI16 x ++000000fc R_OR1K_GOT_AHI16 x ++00000100 R_OR1K_GOT_AHI16 x + +diff --git a/gas/testsuite/gas/or1k/reloc-1.s b/gas/testsuite/gas/or1k/reloc-1.s +index e76abef6532..562609aa869 100644 +--- a/gas/testsuite/gas/or1k/reloc-1.s ++++ b/gas/testsuite/gas/or1k/reloc-1.s +@@ -74,3 +74,7 @@ + l.lbz r5,po(x)(r3) + l.lbz r5,gotpo(x)(r3) + l.sb po(x)(r3),r6 ++ ++ l.movhi r4,gotha(x) ++ l.ori r3,r4,gotha(x) ++ l.addi r3,r4,gotha(x) +diff --git a/include/elf/or1k.h b/include/elf/or1k.h +index a215ef5c17e..dff37d875f2 100644 +--- a/include/elf/or1k.h ++++ b/include/elf/or1k.h +@@ -77,6 +77,7 @@ START_RELOC_NUMBERS (elf_or1k_reloc_type) + RELOC_NUMBER (R_OR1K_TLS_IE_LO13, 51) + RELOC_NUMBER (R_OR1K_SLO13, 52) + RELOC_NUMBER (R_OR1K_PLTA26, 53) ++ RELOC_NUMBER (R_OR1K_GOT_AHI16, 54) + END_RELOC_NUMBERS (R_OR1K_max) + + #define EF_OR1K_NODELAY (1UL << 0) +diff --git a/opcodes/or1k-asm.c b/opcodes/or1k-asm.c +index 4715c4f2826..a72a4e85363 100644 +--- a/opcodes/or1k-asm.c ++++ b/opcodes/or1k-asm.c +@@ -177,7 +177,7 @@ static const bfd_reloc_code_real_type or1k_imm16_relocs[][6] = { + BFD_RELOC_OR1K_GOT_LO13, + BFD_RELOC_UNUSED, + BFD_RELOC_UNUSED, +- BFD_RELOC_UNUSED }, ++ BFD_RELOC_OR1K_GOT_AHI16 }, + { BFD_RELOC_OR1K_GOTPC_LO16, + BFD_RELOC_UNUSED, + BFD_RELOC_UNUSED, +@@ -280,6 +280,11 @@ parse_reloc (const char **strp) + str += 5; + cls = RCLASS_TPOFF; + } ++ else if (strncasecmp (str, "got", 3) == 0) ++ { ++ str += 3; ++ cls = RCLASS_GOT; ++ } + + if (strncasecmp (str, "hi(", 3) == 0) + { +-- +2.25.1 + diff --git a/package/binutils/2.34/0005-or1k-Avoid-R_OR1K_GOT16-overflow-failures-in-presenc.patch b/package/binutils/2.34/0005-or1k-Avoid-R_OR1K_GOT16-overflow-failures-in-presenc.patch new file mode 100644 index 0000000000..e292c9cb48 --- /dev/null +++ b/package/binutils/2.34/0005-or1k-Avoid-R_OR1K_GOT16-overflow-failures-in-presenc.patch @@ -0,0 +1,61 @@ +From d92116c7df340ff40063c5c97d202e7e87400027 Mon Sep 17 00:00:00 2001 +From: Stafford Horne +Date: Sun, 2 May 2021 06:02:16 +0900 +Subject: [PATCH] or1k: Avoid R_OR1K_GOT16 overflow failures in presence of + R_OR1K_GOT_AHI16 + +Now that we support R_OR1K_GOT_AHI16 we can relax the R_OR1K_GOT16 +overflow validation check if the section has R_OR1K_GOT_AHI16. + +We cannot simple disable R_OR1K_GOT16 overflow validation as there will +still be binaries that will have only R_OR1K_GOT16. The +R_OR1K_GOT_AHI16 relocation will only be added by GCC when building with +the option -mcmodel=large. + +This assumes that R_OR1K_GOT_AHI16 will come before R_OR1K_GOT16, which +is the code pattern that will be emitted by GCC. + +bfd/ChangeLog: + + PR 21464 + * elf32-or1k.c (or1k_elf_relocate_section): Relax R_OR1K_GOT16 + overflow check if we have R_OR1K_GOT_AHI16 followed by + R_OR1K_GOT16. + +Signed-off-by: Giulio Benetti +--- + bfd/elf32-or1k.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/bfd/elf32-or1k.c b/bfd/elf32-or1k.c +index 1273fbacb3c..ce2c4fdb3bd 100644 +--- a/bfd/elf32-or1k.c ++++ b/bfd/elf32-or1k.c +@@ -1248,6 +1248,7 @@ or1k_elf_relocate_section (bfd *output_bfd, + asection *sgot, *splt; + bfd_vma plt_base, got_base, got_sym_value; + bfd_boolean ret_val = TRUE; ++ bfd_boolean saw_gotha = FALSE; + + if (htab == NULL) + return FALSE; +@@ -1456,6 +1457,16 @@ or1k_elf_relocate_section (bfd *output_bfd, + || r_type == R_OR1K_GOT_AHI16) + relocation -= got_sym_value; + ++ if (r_type == R_OR1K_GOT_AHI16) ++ saw_gotha = TRUE; ++ ++ /* If we have a R_OR1K_GOT16 followed by a R_OR1K_GOT_AHI16 ++ relocation we assume the code is doing the right thing to avoid ++ overflows. Here we mask the lower 16-bit of the relocation to ++ avoid overflow validation failures. */ ++ if (r_type == R_OR1K_GOT16 && saw_gotha) ++ relocation &= 0xffff; ++ + /* Addend should be zero. */ + if (rel->r_addend != 0) + { +-- +2.25.1 + diff --git a/package/binutils/2.34/0006-or1k-Support-large-plt_relocs-when-generating-plt-en.patch b/package/binutils/2.34/0006-or1k-Support-large-plt_relocs-when-generating-plt-en.patch new file mode 100644 index 0000000000..d6695d4159 --- /dev/null +++ b/package/binutils/2.34/0006-or1k-Support-large-plt_relocs-when-generating-plt-en.patch @@ -0,0 +1,500 @@ +From cba29e387040eaa401c52eb20e7cab5a4401185c Mon Sep 17 00:00:00 2001 +From: Stafford Horne +Date: Sun, 2 May 2021 06:02:17 +0900 +Subject: [PATCH] or1k: Support large plt_relocs when generating plt + entries + +The current PLT generation code will generate invalid code when the PLT +relocation offset exceeds 64k. This fixes the issue by detecting large +plt_reloc offsets and generare code sequences to create larger plt +relocations. + +The "large" plt code needs 2 extra instructions to create 32-bit offsets. + +bfd/ChangeLog: + + PR 27746 + * elf32-or1k.c (PLT_ENTRY_SIZE_LARGE, PLT_MAX_INSN_COUNT, + OR1K_ADD, OR1K_ORI): New macros to help with plt creation. + (elf_or1k_link_hash_table): New field plt_count. + (elf_or1k_link_hash_entry): New field plt_index. + (elf_or1k_plt_entry_size): New function. + (or1k_write_plt_entry): Update to support variable size PLTs. + (or1k_elf_finish_dynamic_sections): Use new or1k_write_plt_entry + API. + (or1k_elf_finish_dynamic_symbol): Update to write large PLTs + when needed. + (allocate_dynrelocs): Use elf_or1k_plt_entry_size to account for + PLT size. + +ld/ChangeLog: + + PR 27746 + testsuite/ld-or1k/or1k.exp (or1kplttests): Add tests for linking + along with gotha() relocations. + testsuite/ld-or1k/gotha1.dd: New file. + testsuite/ld-or1k/gotha1.s: New file. + testsuite/ld-or1k/gotha2.dd: New file. + testsuite/ld-or1k/gotha2.s: New file + testsuite/ld-or1k/pltlib.s (x): Define size to avoid link + failure. + +Signed-off-by: Giulio Benetti +--- + bfd/elf32-or1k.c | 149 ++++++++++++++++++++++++--------- + ld/testsuite/ld-or1k/gotha1.dd | 34 ++++++++ + ld/testsuite/ld-or1k/gotha1.s | 24 ++++++ + ld/testsuite/ld-or1k/gotha2.dd | 21 +++++ + ld/testsuite/ld-or1k/gotha2.s | 22 +++++ + ld/testsuite/ld-or1k/or1k.exp | 8 ++ + ld/testsuite/ld-or1k/pltlib.s | 1 + + 7 files changed, 220 insertions(+), 39 deletions(-) + create mode 100644 ld/testsuite/ld-or1k/gotha1.dd + create mode 100644 ld/testsuite/ld-or1k/gotha1.s + create mode 100644 ld/testsuite/ld-or1k/gotha2.dd + create mode 100644 ld/testsuite/ld-or1k/gotha2.s + +diff --git a/bfd/elf32-or1k.c b/bfd/elf32-or1k.c +index ce2c4fdb3bd..8b021b79d92 100644 +--- a/bfd/elf32-or1k.c ++++ b/bfd/elf32-or1k.c +@@ -30,10 +30,14 @@ + #define N_ONES(X) (((bfd_vma)2 << (X)) - 1) + + #define PLT_ENTRY_SIZE 16 ++#define PLT_ENTRY_SIZE_LARGE (6*4) ++#define PLT_MAX_INSN_COUNT 6 + + #define OR1K_MOVHI(D) (0x18000000 | (D << 21)) + #define OR1K_ADRP(D) (0x08000000 | (D << 21)) + #define OR1K_LWZ(D,A) (0x84000000 | (D << 21) | (A << 16)) ++#define OR1K_ADD(D,A,B) (0xE0000000 | (D << 21) | (A << 16) | (B << 11)) ++#define OR1K_ORI(D,A) (0xA8000000 | (D << 21) | (A << 16)) + #define OR1K_ORI0(D) (0xA8000000 | (D << 21)) + #define OR1K_JR(B) (0x44000000 | (B << 11)) + #define OR1K_NOP 0x15000000 +@@ -903,6 +907,8 @@ struct elf_or1k_link_hash_entry + /* Track dynamic relocs copied for this symbol. */ + struct elf_dyn_relocs *dyn_relocs; + ++ /* For calculating PLT size. */ ++ bfd_vma plt_index; + /* Track type of TLS access. */ + unsigned char tls_type; + }; +@@ -930,9 +936,20 @@ struct elf_or1k_link_hash_table + /* Small local sym to section mapping cache. */ + struct sym_cache sym_sec; + ++ bfd_vma plt_count; + bfd_boolean saw_plta; + }; + ++static size_t ++elf_or1k_plt_entry_size (bfd_vma plt_index) ++{ ++ bfd_vma plt_reloc; ++ ++ plt_reloc = plt_index * sizeof (Elf32_External_Rela); ++ ++ return (plt_reloc > 0xffff) ? PLT_ENTRY_SIZE_LARGE : PLT_ENTRY_SIZE; ++} ++ + /* Get the ELF linker hash table from a link_info structure. */ + #define or1k_elf_hash_table(p) \ + (elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) \ +@@ -2173,33 +2190,46 @@ or1k_elf_check_relocs (bfd *abfd, + } + + static void +-or1k_write_plt_entry (bfd *output_bfd, bfd_byte *contents, unsigned insn1, +- unsigned insn2, unsigned insn3, unsigned insnj) ++or1k_write_plt_entry (bfd *output_bfd, bfd_byte *contents, unsigned insnj, ++ unsigned insns[], size_t insn_count) + { + unsigned nodelay = elf_elfheader (output_bfd)->e_flags & EF_OR1K_NODELAY; +- unsigned insn4; ++ unsigned output_insns[PLT_MAX_INSN_COUNT]; ++ ++ /* Copy instructions into the output buffer. */ ++ for (size_t i = 0; i < insn_count; i++) ++ output_insns[i] = insns[i]; + + /* Honor the no-delay-slot setting. */ +- if (insn3 == OR1K_NOP) ++ if (insns[insn_count-1] == OR1K_NOP) + { +- insn4 = insn3; ++ unsigned slot1, slot2; ++ + if (nodelay) +- insn3 = insnj; ++ slot1 = insns[insn_count-2], slot2 = insnj; + else +- insn3 = insn2, insn2 = insnj; ++ slot1 = insnj, slot2 = insns[insn_count-2]; ++ ++ output_insns[insn_count-2] = slot1; ++ output_insns[insn_count-1] = slot2; ++ output_insns[insn_count] = OR1K_NOP; + } + else + { ++ unsigned slot1, slot2; ++ + if (nodelay) +- insn4 = insnj; ++ slot1 = insns[insn_count-1], slot2 = insnj; + else +- insn4 = insn3, insn3 = insnj; ++ slot1 = insnj, slot2 = insns[insn_count-1]; ++ ++ output_insns[insn_count-1] = slot1; ++ output_insns[insn_count] = slot2; + } + +- bfd_put_32 (output_bfd, insn1, contents); +- bfd_put_32 (output_bfd, insn2, contents + 4); +- bfd_put_32 (output_bfd, insn3, contents + 8); +- bfd_put_32 (output_bfd, insn4, contents + 12); ++ /* Write out the output buffer. */ ++ for (size_t i = 0; i < (insn_count+1); i++) ++ bfd_put_32 (output_bfd, output_insns[i], contents + (i*4)); + } + + /* Finish up the dynamic sections. */ +@@ -2266,7 +2296,8 @@ or1k_elf_finish_dynamic_sections (bfd *output_bfd, + splt = htab->root.splt; + if (splt && splt->size > 0) + { +- unsigned plt0, plt1, plt2; ++ unsigned plt[PLT_MAX_INSN_COUNT]; ++ size_t plt_insn_count = 3; + bfd_vma got_addr = sgot->output_section->vma + sgot->output_offset; + + /* Note we force 16 byte alignment on the .got, so that +@@ -2277,27 +2308,27 @@ or1k_elf_finish_dynamic_sections (bfd *output_bfd, + bfd_vma pc = splt->output_section->vma + splt->output_offset; + unsigned pa = ((got_addr >> 13) - (pc >> 13)) & 0x1fffff; + unsigned po = got_addr & 0x1fff; +- plt0 = OR1K_ADRP(12) | pa; +- plt1 = OR1K_LWZ(15,12) | (po + 8); +- plt2 = OR1K_LWZ(12,12) | (po + 4); ++ plt[0] = OR1K_ADRP(12) | pa; ++ plt[1] = OR1K_LWZ(15,12) | (po + 8); ++ plt[2] = OR1K_LWZ(12,12) | (po + 4); + } + else if (bfd_link_pic (info)) + { +- plt0 = OR1K_LWZ(15, 16) | 8; /* .got+8 */ +- plt1 = OR1K_LWZ(12, 16) | 4; /* .got+4 */ +- plt2 = OR1K_NOP; ++ plt[0] = OR1K_LWZ(15, 16) | 8; /* .got+8 */ ++ plt[1] = OR1K_LWZ(12, 16) | 4; /* .got+4 */ ++ plt[2] = OR1K_NOP; + } + else + { + unsigned ha = ((got_addr + 0x8000) >> 16) & 0xffff; + unsigned lo = got_addr & 0xffff; +- plt0 = OR1K_MOVHI(12) | ha; +- plt1 = OR1K_LWZ(15,12) | (lo + 8); +- plt2 = OR1K_LWZ(12,12) | (lo + 4); ++ plt[0] = OR1K_MOVHI(12) | ha; ++ plt[1] = OR1K_LWZ(15,12) | (lo + 8); ++ plt[2] = OR1K_LWZ(12,12) | (lo + 4); + } + +- or1k_write_plt_entry (output_bfd, splt->contents, +- plt0, plt1, plt2, OR1K_JR(15)); ++ or1k_write_plt_entry (output_bfd, splt->contents, OR1K_JR(15), ++ plt, plt_insn_count); + + elf_section_data (splt->output_section)->this_hdr.sh_entsize = 4; + } +@@ -2340,7 +2371,8 @@ or1k_elf_finish_dynamic_symbol (bfd *output_bfd, + + if (h->plt.offset != (bfd_vma) -1) + { +- unsigned int plt0, plt1, plt2; ++ unsigned int plt[PLT_MAX_INSN_COUNT]; ++ size_t plt_insn_count = 3; + asection *splt; + asection *sgot; + asection *srela; +@@ -2352,6 +2384,7 @@ or1k_elf_finish_dynamic_symbol (bfd *output_bfd, + bfd_vma got_offset; + bfd_vma got_addr; + Elf_Internal_Rela rela; ++ bfd_boolean large_plt_entry; + + /* This symbol has an entry in the procedure linkage table. Set + it up. */ +@@ -2369,10 +2402,13 @@ or1k_elf_finish_dynamic_symbol (bfd *output_bfd, + corresponds to this symbol. This is the index of this symbol + in all the symbols for which we are making plt entries. The + first entry in the procedure linkage table is reserved. */ +- plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1; ++ plt_index = ((struct elf_or1k_link_hash_entry *) h)->plt_index; + plt_addr = plt_base_addr + h->plt.offset; + plt_reloc = plt_index * sizeof (Elf32_External_Rela); + ++ large_plt_entry = (elf_or1k_plt_entry_size (plt_index) ++ == PLT_ENTRY_SIZE_LARGE); ++ + /* Get the offset into the .got table of the entry that + corresponds to this function. Each .got entry is 4 bytes. + The first three are reserved. */ +@@ -2384,27 +2420,57 @@ or1k_elf_finish_dynamic_symbol (bfd *output_bfd, + { + unsigned pa = ((got_addr >> 13) - (plt_addr >> 13)) & 0x1fffff; + unsigned po = (got_addr & 0x1fff); +- plt0 = OR1K_ADRP(12) | pa; +- plt1 = OR1K_LWZ(12,12) | po; +- plt2 = OR1K_ORI0(11) | plt_reloc; ++ plt[0] = OR1K_ADRP(12) | pa; ++ plt[1] = OR1K_LWZ(12,12) | po; ++ plt[2] = OR1K_ORI0(11) | plt_reloc; + } + else if (bfd_link_pic (info)) + { +- plt0 = OR1K_LWZ(12,16) | got_offset; +- plt1 = OR1K_ORI0(11) | plt_reloc; +- plt2 = OR1K_NOP; ++ if (large_plt_entry) ++ { ++ unsigned gotha = ((got_offset + 0x8000) >> 16) & 0xffff; ++ unsigned got = got_offset & 0xffff; ++ unsigned pltrelhi = (plt_reloc >> 16) & 0xffff; ++ unsigned pltrello = plt_reloc & 0xffff; ++ ++ plt[0] = OR1K_MOVHI(12) | gotha; ++ plt[1] = OR1K_ADD(12,12,16); ++ plt[2] = OR1K_LWZ(12,12) | got; ++ plt[3] = OR1K_MOVHI(11) | pltrelhi; ++ plt[4] = OR1K_ORI(11,11) | pltrello; ++ plt_insn_count = 5; ++ } ++ else ++ { ++ plt[0] = OR1K_LWZ(12,16) | got_offset; ++ plt[1] = OR1K_ORI0(11) | plt_reloc; ++ plt[2] = OR1K_NOP; ++ } + } + else + { + unsigned ha = ((got_addr + 0x8000) >> 16) & 0xffff; + unsigned lo = got_addr & 0xffff; +- plt0 = OR1K_MOVHI(12) | ha; +- plt1 = OR1K_LWZ(12,12) | lo; +- plt2 = OR1K_ORI0(11) | plt_reloc; ++ plt[0] = OR1K_MOVHI(12) | ha; ++ plt[1] = OR1K_LWZ(12,12) | lo; ++ plt[2] = OR1K_ORI0(11) | plt_reloc; ++ } ++ ++ /* For large code model we fixup the non-PIC PLT relocation instructions ++ here. */ ++ if (large_plt_entry && !bfd_link_pic (info)) ++ { ++ unsigned pltrelhi = (plt_reloc >> 16) & 0xffff; ++ unsigned pltrello = plt_reloc & 0xffff; ++ ++ plt[2] = OR1K_MOVHI(11) | pltrelhi; ++ plt[3] = OR1K_ORI(11,11) | pltrello; ++ plt[4] = OR1K_NOP; ++ plt_insn_count = 5; + } + + or1k_write_plt_entry (output_bfd, splt->contents + h->plt.offset, +- plt0, plt1, plt2, OR1K_JR(12)); ++ OR1K_JR(12), plt, plt_insn_count); + + /* Fill in the entry in the global offset table. We initialize it to + point to the top of the plt. This is done to lazy lookup the actual +@@ -2699,11 +2765,16 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) + if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info), h)) + { + asection *s = htab->root.splt; ++ bfd_vma plt_index; ++ ++ /* Track the index of our plt entry for use in calculating size. */ ++ plt_index = htab->plt_count++; ++ ((struct elf_or1k_link_hash_entry *) h)->plt_index = plt_index; + + /* If this is the first .plt entry, make room for the special + first entry. */ + if (s->size == 0) +- s->size = PLT_ENTRY_SIZE; ++ s->size = elf_or1k_plt_entry_size (plt_index); + + h->plt.offset = s->size; + +@@ -2720,7 +2791,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) + } + + /* Make room for this entry. */ +- s->size += PLT_ENTRY_SIZE; ++ s->size += elf_or1k_plt_entry_size (plt_index); + + /* We also need to make an entry in the .got.plt section, which + will be placed in the .got section by the linker script. */ +diff --git a/ld/testsuite/ld-or1k/gotha1.dd b/ld/testsuite/ld-or1k/gotha1.dd +new file mode 100644 +index 00000000000..0ad1f8f5399 +--- /dev/null ++++ b/ld/testsuite/ld-or1k/gotha1.dd +@@ -0,0 +1,34 @@ ++ ++.*\.x: file format elf32-or1k ++ ++ ++Disassembly of section \.plt: ++ ++[0-9a-f]+ <\.plt>: ++ +[0-9a-f]+: 19 80 00 00 l\.movhi r12,0x0 ++ +[0-9a-f]+: 85 ec [0-9a-f]+ [0-9a-f]+ l\.lwz r15,[0-9]+\(r12\) ++ +[0-9a-f]+: 44 00 78 00 l\.jr r15 ++ +[0-9a-f]+: 85 8c [0-9a-f]+ [0-9a-f]+ l\.lwz r12,[0-9]+\(r12\) ++ +[0-9a-f]+: 19 80 00 00 l\.movhi r12,0x0 ++ +[0-9a-f]+: 85 8c [0-9a-f]+ [0-9a-f]+ l\.lwz r12,[0-9]+\(r12\) ++ +[0-9a-f]+: 44 00 60 00 l\.jr r12 ++ +[0-9a-f]+: a9 60 00 00 l\.ori r11,r0,0x0 ++ ++Disassembly of section \.text: ++ ++[0-9a-f]+ <_start>: ++ +[0-9a-f]+: 9c 21 ff fc l\.addi r1,r1,-4 ++ +[0-9a-f]+: d4 01 48 00 l\.sw 0\(r1\),r9 ++ +[0-9a-f]+: 04 00 00 02 l\.jal [0-9a-f]+ <_start\+0x10> ++ +[0-9a-f]+: 1a 60 00 00 l\.movhi r19,0x0 ++ +[0-9a-f]+: aa 73 [0-9a-f]+ [0-9a-f]+ l\.ori r19,r19,0x[0-9a-f]+ ++ +[0-9a-f]+: e2 73 48 00 l\.add r19,r19,r9 ++ +[0-9a-f]+: 1a 20 00 00 l\.movhi r17,0x0 ++ +[0-9a-f]+: e2 31 98 00 l\.add r17,r17,r19 ++ +[0-9a-f]+: 86 31 00 10 l\.lwz r17,16\(r17\) ++ +[0-9a-f]+: 84 71 00 00 l\.lwz r3,0\(r17\) ++ +[0-9a-f]+: 07 ff ff f2 l\.jal [0-9a-f]+ <\.plt\+0x10> ++ +[0-9a-f]+: 15 00 00 00 l\.nop 0x0 ++ +[0-9a-f]+: 85 21 00 00 l\.lwz r9,0\(r1\) ++ +[0-9a-f]+: 44 00 48 00 l\.jr r9 ++ +[0-9a-f]+: 9c 21 00 04 l\.addi r1,r1,4 +diff --git a/ld/testsuite/ld-or1k/gotha1.s b/ld/testsuite/ld-or1k/gotha1.s +new file mode 100644 +index 00000000000..42b16db425c +--- /dev/null ++++ b/ld/testsuite/ld-or1k/gotha1.s +@@ -0,0 +1,24 @@ ++ .data ++ .p2align 16 ++ ++ .text ++ .globl _start ++_start: ++ l.addi r1, r1, -4 ++ l.sw 0(r1), r9 ++ ++ l.jal 8 ++ l.movhi r19, gotpchi(_GLOBAL_OFFSET_TABLE_-4) ++ l.ori r19, r19, gotpclo(_GLOBAL_OFFSET_TABLE_+0) ++ l.add r19, r19, r9 ++ ++ l.movhi r17, gotha(x) ++ l.add r17, r17, r19 ++ l.lwz r17, got(x)(r17) ++ l.lwz r3, 0(r17) ++ ++ l.jal plt(func) ++ l.nop ++ l.lwz r9, 0(r1) ++ l.jr r9 ++ l.addi r1, r1, 4 +diff --git a/ld/testsuite/ld-or1k/gotha2.dd b/ld/testsuite/ld-or1k/gotha2.dd +new file mode 100644 +index 00000000000..fe09da5466b +--- /dev/null ++++ b/ld/testsuite/ld-or1k/gotha2.dd +@@ -0,0 +1,21 @@ ++ ++.*\.x: file format elf32-or1k ++ ++ ++Disassembly of section \.text: ++ ++[0-9a-f]+ : ++ +[0-9a-f]+: 9c 21 ff f8 l\.addi r1,r1,-8 ++ +[0-9a-f]+: d4 01 80 00 l\.sw 0\(r1\),r16 ++ +[0-9a-f]+: d4 01 48 04 l\.sw 4\(r1\),r9 ++ +[0-9a-f]+: 04 00 [0-9a-f]+ [0-9a-f]+ l\.jal [0-9a-f]+ ++ +[0-9a-f]+: 1a 00 00 00 l\.movhi r16,0x0 ++ +[0-9a-f]+: aa 10 [0-9a-f]+ [0-9a-f]+ l\.ori r16,r16,0x[0-9a-f]+ ++ +[0-9a-f]+: e2 10 48 00 l\.add r16,r16,r9 ++ +[0-9a-f]+: 1a 20 00 00 l\.movhi r17,0x0 ++ +[0-9a-f]+: e2 31 80 00 l\.add r17,r17,r16 ++ +[0-9a-f]+: 86 31 00 0c l\.lwz r17,12\(r17\) ++ +[0-9a-f]+: 85 21 00 04 l\.lwz r9,4\(r1\) ++ +[0-9a-f]+: 86 01 00 00 l\.lwz r16,0\(r1\) ++ +[0-9a-f]+: 44 00 48 00 l\.jr r9 ++ +[0-9a-f]+: 9c 21 00 08 l\.addi r1,r1,8 +diff --git a/ld/testsuite/ld-or1k/gotha2.s b/ld/testsuite/ld-or1k/gotha2.s +new file mode 100644 +index 00000000000..164b282f2dd +--- /dev/null ++++ b/ld/testsuite/ld-or1k/gotha2.s +@@ -0,0 +1,22 @@ ++ .section .text ++ .align 4 ++ .global test ++ .type test, @function ++test: ++ l.addi r1, r1, -8 ++ l.sw 0(r1), r16 ++ l.sw 4(r1), r9 ++ ++ l.jal 8 ++ l.movhi r16, gotpchi(_GLOBAL_OFFSET_TABLE_-4) ++ l.ori r16, r16, gotpclo(_GLOBAL_OFFSET_TABLE_+0) ++ l.add r16, r16, r9 ++ ++ l.movhi r17, gotha(i) ++ l.add r17, r17, r16 ++ l.lwz r17, got(i)(r17) ++ ++ l.lwz r9, 4(r1) ++ l.lwz r16, 0(r1) ++ l.jr r9 ++ l.addi r1, r1, 8 +diff --git a/ld/testsuite/ld-or1k/or1k.exp b/ld/testsuite/ld-or1k/or1k.exp +index 7592e8307c1..8e19ec6c31a 100644 +--- a/ld/testsuite/ld-or1k/or1k.exp ++++ b/ld/testsuite/ld-or1k/or1k.exp +@@ -53,6 +53,14 @@ set or1kplttests { + "" {plt1.s} + {{objdump -dr plt1.x.dd}} + "plt1.x"} ++ {"gotha exec plt" "tmpdir/libpltlib.so" "" ++ "" {gotha1.s} ++ {{objdump -dr gotha1.dd}} ++ "gotha1.x"} ++ {"gotha -fpic -shared" "-fpic -shared" "" ++ "" {gotha2.s} ++ {{objdump -dr gotha2.dd}} ++ "gotha2.x"} + } + + # Not implemented yet +diff --git a/ld/testsuite/ld-or1k/pltlib.s b/ld/testsuite/ld-or1k/pltlib.s +index baf76ca1af7..8b4d7ba48fd 100644 +--- a/ld/testsuite/ld-or1k/pltlib.s ++++ b/ld/testsuite/ld-or1k/pltlib.s +@@ -1,5 +1,6 @@ + .section .data + .globl x, y ++ .size x, 4 + x: .long 33 + y: .long 44 + +-- +2.25.1 + diff --git a/package/binutils/2.35.2/0004-or1k-Implement-relocation-R_OR1K_GOT_AHI16-for-gotha.patch b/package/binutils/2.35.2/0004-or1k-Implement-relocation-R_OR1K_GOT_AHI16-for-gotha.patch new file mode 100644 index 0000000000..a4af57d546 --- /dev/null +++ b/package/binutils/2.35.2/0004-or1k-Implement-relocation-R_OR1K_GOT_AHI16-for-gotha.patch @@ -0,0 +1,256 @@ +From c67656e248d6dadaa2729975a17c8dd03afe48d0 Mon Sep 17 00:00:00 2001 +From: Stafford Horne +Date: Sun, 2 May 2021 06:02:15 +0900 +Subject: [PATCH] or1k: Implement relocation R_OR1K_GOT_AHI16 for gotha() + +The gotha() relocation mnemonic will be outputted by OpenRISC GCC when +using the -mcmodel=large option. This relocation is used along with +got() to generate 32-bit GOT offsets. This increases the previous GOT +offset limit from the previous 16-bit (64K) limit. + +This is needed on large binaries where the GOT grows larger than 64k. + +bfd/ChangeLog: + + PR 21464 + * bfd-in2.h: Add BFD_RELOC_OR1K_GOT_AHI16 relocation. + * elf32-or1k.c (or1k_elf_howto_table, or1k_reloc_map): Likewise. + (or1k_final_link_relocate, or1k_elf_relocate_section, + or1k_elf_check_relocs): Likewise. + * libbfd.h (bfd_reloc_code_real_names): Likewise. + * reloc.c: Likewise. + +cpu/ChangeLog: + + PR 21464 + * or1k.opc (or1k_imm16_relocs, parse_reloc): Define parse logic + for gotha() relocation. + +include/ChangeLog: + + PR 21464 + * elf/or1k.h (elf_or1k_reloc_type): Define R_OR1K_GOT_AHI16 number. + +opcodes/ChangeLog: + + PR 21464 + * or1k-asm.c: Regenerate. + +gas/ChangeLog: + + PR 21464 + * testsuite/gas/or1k/reloc-1.s: Add test for new relocation. + * testsuite/gas/or1k/reloc-1.d: Add test result for new + relocation. + +Cc: Giulio Benetti + +fixup reloc, add tests + +Signed-off-by: Giulio Benetti +--- + bfd/bfd-in2.h | 1 + + bfd/elf32-or1k.c | 21 ++++++++++++++++++++- + bfd/libbfd.h | 1 + + bfd/reloc.c | 2 ++ + cpu/or1k.opc | 7 ++++++- + gas/testsuite/gas/or1k/reloc-1.d | 4 +++- + gas/testsuite/gas/or1k/reloc-1.s | 4 ++++ + include/elf/or1k.h | 1 + + opcodes/or1k-asm.c | 7 ++++++- + 9 files changed, 44 insertions(+), 4 deletions(-) + +diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h +index df6f9f45673..ab861395e93 100644 +--- a/bfd/bfd-in2.h ++++ b/bfd/bfd-in2.h +@@ -5041,6 +5041,7 @@ then it may be truncated to 8 bits. */ + BFD_RELOC_OR1K_TLS_TPOFF, + BFD_RELOC_OR1K_TLS_DTPOFF, + BFD_RELOC_OR1K_TLS_DTPMOD, ++ BFD_RELOC_OR1K_GOT_AHI16, + + /* H8 elf Relocations. */ + BFD_RELOC_H8_DIR16A8, +diff --git a/bfd/elf32-or1k.c b/bfd/elf32-or1k.c +index bbfa2bfe614..8e395827123 100644 +--- a/bfd/elf32-or1k.c ++++ b/bfd/elf32-or1k.c +@@ -808,6 +808,20 @@ static reloc_howto_type or1k_elf_howto_table[] = + 0, /* Source Mask. */ + 0x03ffffff, /* Dest Mask. */ + TRUE), /* PC relative offset? */ ++ ++ HOWTO (R_OR1K_GOT_AHI16, /* type */ ++ 16, /* rightshift */ ++ 2, /* size (0 = byte, 1 = short, 2 = long) */ ++ 16, /* bitsize */ ++ FALSE, /* pc_relative */ ++ 0, /* bitpos */ ++ complain_overflow_signed, /* complain_on_overflow */ ++ bfd_elf_generic_reloc, /* special_function */ ++ "R_OR1K_GOT_AHI16", /* name */ ++ FALSE, /* partial_inplace */ ++ 0, /* src_mask */ ++ 0xffff, /* dst_mask */ ++ FALSE), /* pcrel_offset */ + }; + + /* Map BFD reloc types to Or1k ELF reloc types. */ +@@ -871,6 +885,7 @@ static const struct or1k_reloc_map or1k_reloc_map[] = + { BFD_RELOC_OR1K_TLS_IE_LO13, R_OR1K_TLS_IE_LO13 }, + { BFD_RELOC_OR1K_SLO13, R_OR1K_SLO13 }, + { BFD_RELOC_OR1K_PLTA26, R_OR1K_PLTA26 }, ++ { BFD_RELOC_OR1K_GOT_AHI16, R_OR1K_GOT_AHI16 }, + }; + + /* tls_type is a mask used to track how each symbol is accessed, +@@ -1113,6 +1128,7 @@ or1k_final_link_relocate (reloc_howto_type *howto, bfd *input_bfd, + switch (howto->type) + { + case R_OR1K_AHI16: ++ case R_OR1K_GOT_AHI16: + case R_OR1K_GOTOFF_AHI16: + case R_OR1K_TLS_IE_AHI16: + case R_OR1K_TLS_LE_AHI16: +@@ -1375,6 +1391,7 @@ or1k_elf_relocate_section (bfd *output_bfd, + } + break; + ++ case R_OR1K_GOT_AHI16: + case R_OR1K_GOT16: + case R_OR1K_GOT_PG21: + case R_OR1K_GOT_LO13: +@@ -1466,7 +1483,8 @@ or1k_elf_relocate_section (bfd *output_bfd, + /* The GOT_PG21 and GOT_LO13 relocs are pc-relative, + while the GOT16 reloc is GOT relative. */ + relocation = got_base + off; +- if (r_type == R_OR1K_GOT16) ++ if (r_type == R_OR1K_GOT16 ++ || r_type == R_OR1K_GOT_AHI16) + relocation -= got_sym_value; + + /* Addend should be zero. */ +@@ -1992,6 +2010,7 @@ or1k_elf_check_relocs (bfd *abfd, + } + break; + ++ case R_OR1K_GOT_AHI16: + case R_OR1K_GOT16: + case R_OR1K_GOT_PG21: + case R_OR1K_GOT_LO13: +diff --git a/bfd/libbfd.h b/bfd/libbfd.h +index b97534fc9fe..795c9b9d27f 100644 +--- a/bfd/libbfd.h ++++ b/bfd/libbfd.h +@@ -2755,6 +2755,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", + "BFD_RELOC_OR1K_TLS_TPOFF", + "BFD_RELOC_OR1K_TLS_DTPOFF", + "BFD_RELOC_OR1K_TLS_DTPMOD", ++ "BFD_RELOC_OR1K_GOT_AHI16", + "BFD_RELOC_H8_DIR16A8", + "BFD_RELOC_H8_DIR16R8", + "BFD_RELOC_H8_DIR24A8", +diff --git a/bfd/reloc.c b/bfd/reloc.c +index 9aba84ca81e..1e021febef2 100644 +--- a/bfd/reloc.c ++++ b/bfd/reloc.c +@@ -6175,6 +6175,8 @@ ENUMX + BFD_RELOC_OR1K_GOTPC_HI16 + ENUMX + BFD_RELOC_OR1K_GOTPC_LO16 ++ENUMX ++ BFD_RELOC_OR1K_GOT_AHI16 + ENUMX + BFD_RELOC_OR1K_GOT16 + ENUMX +diff --git a/cpu/or1k.opc b/cpu/or1k.opc +index f0adcbb00a5..5d20a1f33a7 100644 +--- a/cpu/or1k.opc ++++ b/cpu/or1k.opc +@@ -193,7 +193,7 @@ static const bfd_reloc_code_real_type or1k_imm16_relocs[][6] = { + BFD_RELOC_OR1K_GOT_LO13, + BFD_RELOC_UNUSED, + BFD_RELOC_UNUSED, +- BFD_RELOC_UNUSED }, ++ BFD_RELOC_OR1K_GOT_AHI16 }, + { BFD_RELOC_OR1K_GOTPC_LO16, + BFD_RELOC_UNUSED, + BFD_RELOC_UNUSED, +@@ -296,6 +296,11 @@ parse_reloc (const char **strp) + str += 5; + cls = RCLASS_TPOFF; + } ++ else if (strncasecmp (str, "got", 3) == 0) ++ { ++ str += 3; ++ cls = RCLASS_GOT; ++ } + + if (strncasecmp (str, "hi(", 3) == 0) + { +diff --git a/gas/testsuite/gas/or1k/reloc-1.d b/gas/testsuite/gas/or1k/reloc-1.d +index d1bcf5608bb..3a001c4ed99 100644 +--- a/gas/testsuite/gas/or1k/reloc-1.d ++++ b/gas/testsuite/gas/or1k/reloc-1.d +@@ -68,5 +68,7 @@ OFFSET TYPE VALUE + 000000ec R_OR1K_LO13 x + 000000f0 R_OR1K_GOT_LO13 x + 000000f4 R_OR1K_SLO13 x +- ++000000f8 R_OR1K_GOT_AHI16 x ++000000fc R_OR1K_GOT_AHI16 x ++00000100 R_OR1K_GOT_AHI16 x + +diff --git a/gas/testsuite/gas/or1k/reloc-1.s b/gas/testsuite/gas/or1k/reloc-1.s +index e76abef6532..562609aa869 100644 +--- a/gas/testsuite/gas/or1k/reloc-1.s ++++ b/gas/testsuite/gas/or1k/reloc-1.s +@@ -74,3 +74,7 @@ + l.lbz r5,po(x)(r3) + l.lbz r5,gotpo(x)(r3) + l.sb po(x)(r3),r6 ++ ++ l.movhi r4,gotha(x) ++ l.ori r3,r4,gotha(x) ++ l.addi r3,r4,gotha(x) +diff --git a/include/elf/or1k.h b/include/elf/or1k.h +index a215ef5c17e..dff37d875f2 100644 +--- a/include/elf/or1k.h ++++ b/include/elf/or1k.h +@@ -77,6 +77,7 @@ START_RELOC_NUMBERS (elf_or1k_reloc_type) + RELOC_NUMBER (R_OR1K_TLS_IE_LO13, 51) + RELOC_NUMBER (R_OR1K_SLO13, 52) + RELOC_NUMBER (R_OR1K_PLTA26, 53) ++ RELOC_NUMBER (R_OR1K_GOT_AHI16, 54) + END_RELOC_NUMBERS (R_OR1K_max) + + #define EF_OR1K_NODELAY (1UL << 0) +diff --git a/opcodes/or1k-asm.c b/opcodes/or1k-asm.c +index 5f3c6c74b12..e0c49b3b8cd 100644 +--- a/opcodes/or1k-asm.c ++++ b/opcodes/or1k-asm.c +@@ -177,7 +177,7 @@ static const bfd_reloc_code_real_type or1k_imm16_relocs[][6] = { + BFD_RELOC_OR1K_GOT_LO13, + BFD_RELOC_UNUSED, + BFD_RELOC_UNUSED, +- BFD_RELOC_UNUSED }, ++ BFD_RELOC_OR1K_GOT_AHI16 }, + { BFD_RELOC_OR1K_GOTPC_LO16, + BFD_RELOC_UNUSED, + BFD_RELOC_UNUSED, +@@ -280,6 +280,11 @@ parse_reloc (const char **strp) + str += 5; + cls = RCLASS_TPOFF; + } ++ else if (strncasecmp (str, "got", 3) == 0) ++ { ++ str += 3; ++ cls = RCLASS_GOT; ++ } + + if (strncasecmp (str, "hi(", 3) == 0) + { +-- +2.25.1 + diff --git a/package/binutils/2.35.2/0005-or1k-Avoid-R_OR1K_GOT16-overflow-failures-in-presenc.patch b/package/binutils/2.35.2/0005-or1k-Avoid-R_OR1K_GOT16-overflow-failures-in-presenc.patch new file mode 100644 index 0000000000..82198dd373 --- /dev/null +++ b/package/binutils/2.35.2/0005-or1k-Avoid-R_OR1K_GOT16-overflow-failures-in-presenc.patch @@ -0,0 +1,61 @@ +From 097b83a1c9c694a14e6081cee034bf24f16875c1 Mon Sep 17 00:00:00 2001 +From: Stafford Horne +Date: Sun, 2 May 2021 06:02:16 +0900 +Subject: [PATCH] or1k: Avoid R_OR1K_GOT16 overflow failures in presence of + R_OR1K_GOT_AHI16 + +Now that we support R_OR1K_GOT_AHI16 we can relax the R_OR1K_GOT16 +overflow validation check if the section has R_OR1K_GOT_AHI16. + +We cannot simple disable R_OR1K_GOT16 overflow validation as there will +still be binaries that will have only R_OR1K_GOT16. The +R_OR1K_GOT_AHI16 relocation will only be added by GCC when building with +the option -mcmodel=large. + +This assumes that R_OR1K_GOT_AHI16 will come before R_OR1K_GOT16, which +is the code pattern that will be emitted by GCC. + +bfd/ChangeLog: + + PR 21464 + * elf32-or1k.c (or1k_elf_relocate_section): Relax R_OR1K_GOT16 + overflow check if we have R_OR1K_GOT_AHI16 followed by + R_OR1K_GOT16. + +Signed-off-by: Giulio Benetti +--- + bfd/elf32-or1k.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/bfd/elf32-or1k.c b/bfd/elf32-or1k.c +index 8e395827123..9f315bfda99 100644 +--- a/bfd/elf32-or1k.c ++++ b/bfd/elf32-or1k.c +@@ -1280,6 +1280,7 @@ or1k_elf_relocate_section (bfd *output_bfd, + asection *sgot, *splt; + bfd_vma plt_base, got_base, got_sym_value; + bfd_boolean ret_val = TRUE; ++ bfd_boolean saw_gotha = FALSE; + + if (htab == NULL) + return FALSE; +@@ -1487,6 +1488,16 @@ or1k_elf_relocate_section (bfd *output_bfd, + || r_type == R_OR1K_GOT_AHI16) + relocation -= got_sym_value; + ++ if (r_type == R_OR1K_GOT_AHI16) ++ saw_gotha = TRUE; ++ ++ /* If we have a R_OR1K_GOT16 followed by a R_OR1K_GOT_AHI16 ++ relocation we assume the code is doing the right thing to avoid ++ overflows. Here we mask the lower 16-bit of the relocation to ++ avoid overflow validation failures. */ ++ if (r_type == R_OR1K_GOT16 && saw_gotha) ++ relocation &= 0xffff; ++ + /* Addend should be zero. */ + if (rel->r_addend != 0) + { +-- +2.25.1 + diff --git a/package/binutils/2.35.2/0006-or1k-Support-large-plt_relocs-when-generating-plt-en.patch b/package/binutils/2.35.2/0006-or1k-Support-large-plt_relocs-when-generating-plt-en.patch new file mode 100644 index 0000000000..c884ab874d --- /dev/null +++ b/package/binutils/2.35.2/0006-or1k-Support-large-plt_relocs-when-generating-plt-en.patch @@ -0,0 +1,500 @@ +From c87692eb894b4b86eced7b7ba205f9bf27c2c213 Mon Sep 17 00:00:00 2001 +From: Stafford Horne +Date: Sun, 2 May 2021 06:02:17 +0900 +Subject: [PATCH] or1k: Support large plt_relocs when generating plt + entries + +The current PLT generation code will generate invalid code when the PLT +relocation offset exceeds 64k. This fixes the issue by detecting large +plt_reloc offsets and generare code sequences to create larger plt +relocations. + +The "large" plt code needs 2 extra instructions to create 32-bit offsets. + +bfd/ChangeLog: + + PR 27746 + * elf32-or1k.c (PLT_ENTRY_SIZE_LARGE, PLT_MAX_INSN_COUNT, + OR1K_ADD, OR1K_ORI): New macros to help with plt creation. + (elf_or1k_link_hash_table): New field plt_count. + (elf_or1k_link_hash_entry): New field plt_index. + (elf_or1k_plt_entry_size): New function. + (or1k_write_plt_entry): Update to support variable size PLTs. + (or1k_elf_finish_dynamic_sections): Use new or1k_write_plt_entry + API. + (or1k_elf_finish_dynamic_symbol): Update to write large PLTs + when needed. + (allocate_dynrelocs): Use elf_or1k_plt_entry_size to account for + PLT size. + +ld/ChangeLog: + + PR 27746 + testsuite/ld-or1k/or1k.exp (or1kplttests): Add tests for linking + along with gotha() relocations. + testsuite/ld-or1k/gotha1.dd: New file. + testsuite/ld-or1k/gotha1.s: New file. + testsuite/ld-or1k/gotha2.dd: New file. + testsuite/ld-or1k/gotha2.s: New file + testsuite/ld-or1k/pltlib.s (x): Define size to avoid link + failure. + +Signed-off-by: Giulio Benetti +--- + bfd/elf32-or1k.c | 149 ++++++++++++++++++++++++--------- + ld/testsuite/ld-or1k/gotha1.dd | 34 ++++++++ + ld/testsuite/ld-or1k/gotha1.s | 24 ++++++ + ld/testsuite/ld-or1k/gotha2.dd | 21 +++++ + ld/testsuite/ld-or1k/gotha2.s | 22 +++++ + ld/testsuite/ld-or1k/or1k.exp | 8 ++ + ld/testsuite/ld-or1k/pltlib.s | 1 + + 7 files changed, 220 insertions(+), 39 deletions(-) + create mode 100644 ld/testsuite/ld-or1k/gotha1.dd + create mode 100644 ld/testsuite/ld-or1k/gotha1.s + create mode 100644 ld/testsuite/ld-or1k/gotha2.dd + create mode 100644 ld/testsuite/ld-or1k/gotha2.s + +diff --git a/bfd/elf32-or1k.c b/bfd/elf32-or1k.c +index 9f315bfda99..7a14eaa3a46 100644 +--- a/bfd/elf32-or1k.c ++++ b/bfd/elf32-or1k.c +@@ -30,10 +30,14 @@ + #define N_ONES(X) (((bfd_vma)2 << (X)) - 1) + + #define PLT_ENTRY_SIZE 16 ++#define PLT_ENTRY_SIZE_LARGE (6*4) ++#define PLT_MAX_INSN_COUNT 6 + + #define OR1K_MOVHI(D) (0x18000000 | (D << 21)) + #define OR1K_ADRP(D) (0x08000000 | (D << 21)) + #define OR1K_LWZ(D,A) (0x84000000 | (D << 21) | (A << 16)) ++#define OR1K_ADD(D,A,B) (0xE0000000 | (D << 21) | (A << 16) | (B << 11)) ++#define OR1K_ORI(D,A) (0xA8000000 | (D << 21) | (A << 16)) + #define OR1K_ORI0(D) (0xA8000000 | (D << 21)) + #define OR1K_JR(B) (0x44000000 | (B << 11)) + #define OR1K_NOP 0x15000000 +@@ -907,6 +911,8 @@ struct elf_or1k_link_hash_entry + { + struct elf_link_hash_entry root; + ++ /* For calculating PLT size. */ ++ bfd_vma plt_index; + /* Track type of TLS access. */ + unsigned char tls_type; + }; +@@ -934,9 +940,20 @@ struct elf_or1k_link_hash_table + /* Small local sym to section mapping cache. */ + struct sym_cache sym_sec; + ++ bfd_vma plt_count; + bfd_boolean saw_plta; + }; + ++static size_t ++elf_or1k_plt_entry_size (bfd_vma plt_index) ++{ ++ bfd_vma plt_reloc; ++ ++ plt_reloc = plt_index * sizeof (Elf32_External_Rela); ++ ++ return (plt_reloc > 0xffff) ? PLT_ENTRY_SIZE_LARGE : PLT_ENTRY_SIZE; ++} ++ + /* Get the ELF linker hash table from a link_info structure. */ + #define or1k_elf_hash_table(p) \ + (elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) \ +@@ -2224,33 +2241,46 @@ or1k_elf_check_relocs (bfd *abfd, + } + + static void +-or1k_write_plt_entry (bfd *output_bfd, bfd_byte *contents, unsigned insn1, +- unsigned insn2, unsigned insn3, unsigned insnj) ++or1k_write_plt_entry (bfd *output_bfd, bfd_byte *contents, unsigned insnj, ++ unsigned insns[], size_t insn_count) + { + unsigned nodelay = elf_elfheader (output_bfd)->e_flags & EF_OR1K_NODELAY; +- unsigned insn4; ++ unsigned output_insns[PLT_MAX_INSN_COUNT]; ++ ++ /* Copy instructions into the output buffer. */ ++ for (size_t i = 0; i < insn_count; i++) ++ output_insns[i] = insns[i]; + + /* Honor the no-delay-slot setting. */ +- if (insn3 == OR1K_NOP) ++ if (insns[insn_count-1] == OR1K_NOP) + { +- insn4 = insn3; ++ unsigned slot1, slot2; ++ + if (nodelay) +- insn3 = insnj; ++ slot1 = insns[insn_count-2], slot2 = insnj; + else +- insn3 = insn2, insn2 = insnj; ++ slot1 = insnj, slot2 = insns[insn_count-2]; ++ ++ output_insns[insn_count-2] = slot1; ++ output_insns[insn_count-1] = slot2; ++ output_insns[insn_count] = OR1K_NOP; + } + else + { ++ unsigned slot1, slot2; ++ + if (nodelay) +- insn4 = insnj; ++ slot1 = insns[insn_count-1], slot2 = insnj; + else +- insn4 = insn3, insn3 = insnj; ++ slot1 = insnj, slot2 = insns[insn_count-1]; ++ ++ output_insns[insn_count-1] = slot1; ++ output_insns[insn_count] = slot2; + } + +- bfd_put_32 (output_bfd, insn1, contents); +- bfd_put_32 (output_bfd, insn2, contents + 4); +- bfd_put_32 (output_bfd, insn3, contents + 8); +- bfd_put_32 (output_bfd, insn4, contents + 12); ++ /* Write out the output buffer. */ ++ for (size_t i = 0; i < (insn_count+1); i++) ++ bfd_put_32 (output_bfd, output_insns[i], contents + (i*4)); + } + + /* Finish up the dynamic sections. */ +@@ -2317,7 +2347,8 @@ or1k_elf_finish_dynamic_sections (bfd *output_bfd, + splt = htab->root.splt; + if (splt && splt->size > 0) + { +- unsigned plt0, plt1, plt2; ++ unsigned plt[PLT_MAX_INSN_COUNT]; ++ size_t plt_insn_count = 3; + bfd_vma got_addr = sgot->output_section->vma + sgot->output_offset; + + /* Note we force 16 byte alignment on the .got, so that +@@ -2328,27 +2359,27 @@ or1k_elf_finish_dynamic_sections (bfd *output_bfd, + bfd_vma pc = splt->output_section->vma + splt->output_offset; + unsigned pa = ((got_addr >> 13) - (pc >> 13)) & 0x1fffff; + unsigned po = got_addr & 0x1fff; +- plt0 = OR1K_ADRP(12) | pa; +- plt1 = OR1K_LWZ(15,12) | (po + 8); +- plt2 = OR1K_LWZ(12,12) | (po + 4); ++ plt[0] = OR1K_ADRP(12) | pa; ++ plt[1] = OR1K_LWZ(15,12) | (po + 8); ++ plt[2] = OR1K_LWZ(12,12) | (po + 4); + } + else if (bfd_link_pic (info)) + { +- plt0 = OR1K_LWZ(15, 16) | 8; /* .got+8 */ +- plt1 = OR1K_LWZ(12, 16) | 4; /* .got+4 */ +- plt2 = OR1K_NOP; ++ plt[0] = OR1K_LWZ(15, 16) | 8; /* .got+8 */ ++ plt[1] = OR1K_LWZ(12, 16) | 4; /* .got+4 */ ++ plt[2] = OR1K_NOP; + } + else + { + unsigned ha = ((got_addr + 0x8000) >> 16) & 0xffff; + unsigned lo = got_addr & 0xffff; +- plt0 = OR1K_MOVHI(12) | ha; +- plt1 = OR1K_LWZ(15,12) | (lo + 8); +- plt2 = OR1K_LWZ(12,12) | (lo + 4); ++ plt[0] = OR1K_MOVHI(12) | ha; ++ plt[1] = OR1K_LWZ(15,12) | (lo + 8); ++ plt[2] = OR1K_LWZ(12,12) | (lo + 4); + } + +- or1k_write_plt_entry (output_bfd, splt->contents, +- plt0, plt1, plt2, OR1K_JR(15)); ++ or1k_write_plt_entry (output_bfd, splt->contents, OR1K_JR(15), ++ plt, plt_insn_count); + + elf_section_data (splt->output_section)->this_hdr.sh_entsize = 4; + } +@@ -2391,7 +2422,8 @@ or1k_elf_finish_dynamic_symbol (bfd *output_bfd, + + if (h->plt.offset != (bfd_vma) -1) + { +- unsigned int plt0, plt1, plt2; ++ unsigned int plt[PLT_MAX_INSN_COUNT]; ++ size_t plt_insn_count = 3; + asection *splt; + asection *sgot; + asection *srela; +@@ -2403,6 +2435,7 @@ or1k_elf_finish_dynamic_symbol (bfd *output_bfd, + bfd_vma got_offset; + bfd_vma got_addr; + Elf_Internal_Rela rela; ++ bfd_boolean large_plt_entry; + + /* This symbol has an entry in the procedure linkage table. Set + it up. */ +@@ -2420,10 +2453,13 @@ or1k_elf_finish_dynamic_symbol (bfd *output_bfd, + corresponds to this symbol. This is the index of this symbol + in all the symbols for which we are making plt entries. The + first entry in the procedure linkage table is reserved. */ +- plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1; ++ plt_index = ((struct elf_or1k_link_hash_entry *) h)->plt_index; + plt_addr = plt_base_addr + h->plt.offset; + plt_reloc = plt_index * sizeof (Elf32_External_Rela); + ++ large_plt_entry = (elf_or1k_plt_entry_size (plt_index) ++ == PLT_ENTRY_SIZE_LARGE); ++ + /* Get the offset into the .got table of the entry that + corresponds to this function. Each .got entry is 4 bytes. + The first three are reserved. */ +@@ -2435,27 +2471,57 @@ or1k_elf_finish_dynamic_symbol (bfd *output_bfd, + { + unsigned pa = ((got_addr >> 13) - (plt_addr >> 13)) & 0x1fffff; + unsigned po = (got_addr & 0x1fff); +- plt0 = OR1K_ADRP(12) | pa; +- plt1 = OR1K_LWZ(12,12) | po; +- plt2 = OR1K_ORI0(11) | plt_reloc; ++ plt[0] = OR1K_ADRP(12) | pa; ++ plt[1] = OR1K_LWZ(12,12) | po; ++ plt[2] = OR1K_ORI0(11) | plt_reloc; + } + else if (bfd_link_pic (info)) + { +- plt0 = OR1K_LWZ(12,16) | got_offset; +- plt1 = OR1K_ORI0(11) | plt_reloc; +- plt2 = OR1K_NOP; ++ if (large_plt_entry) ++ { ++ unsigned gotha = ((got_offset + 0x8000) >> 16) & 0xffff; ++ unsigned got = got_offset & 0xffff; ++ unsigned pltrelhi = (plt_reloc >> 16) & 0xffff; ++ unsigned pltrello = plt_reloc & 0xffff; ++ ++ plt[0] = OR1K_MOVHI(12) | gotha; ++ plt[1] = OR1K_ADD(12,12,16); ++ plt[2] = OR1K_LWZ(12,12) | got; ++ plt[3] = OR1K_MOVHI(11) | pltrelhi; ++ plt[4] = OR1K_ORI(11,11) | pltrello; ++ plt_insn_count = 5; ++ } ++ else ++ { ++ plt[0] = OR1K_LWZ(12,16) | got_offset; ++ plt[1] = OR1K_ORI0(11) | plt_reloc; ++ plt[2] = OR1K_NOP; ++ } + } + else + { + unsigned ha = ((got_addr + 0x8000) >> 16) & 0xffff; + unsigned lo = got_addr & 0xffff; +- plt0 = OR1K_MOVHI(12) | ha; +- plt1 = OR1K_LWZ(12,12) | lo; +- plt2 = OR1K_ORI0(11) | plt_reloc; ++ plt[0] = OR1K_MOVHI(12) | ha; ++ plt[1] = OR1K_LWZ(12,12) | lo; ++ plt[2] = OR1K_ORI0(11) | plt_reloc; ++ } ++ ++ /* For large code model we fixup the non-PIC PLT relocation instructions ++ here. */ ++ if (large_plt_entry && !bfd_link_pic (info)) ++ { ++ unsigned pltrelhi = (plt_reloc >> 16) & 0xffff; ++ unsigned pltrello = plt_reloc & 0xffff; ++ ++ plt[2] = OR1K_MOVHI(11) | pltrelhi; ++ plt[3] = OR1K_ORI(11,11) | pltrello; ++ plt[4] = OR1K_NOP; ++ plt_insn_count = 5; + } + + or1k_write_plt_entry (output_bfd, splt->contents + h->plt.offset, +- plt0, plt1, plt2, OR1K_JR(12)); ++ OR1K_JR(12), plt, plt_insn_count); + + /* Fill in the entry in the global offset table. We initialize it to + point to the top of the plt. This is done to lazy lookup the actual +@@ -2779,11 +2845,16 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) + if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info), h)) + { + asection *splt = htab->root.splt; ++ bfd_vma plt_index; ++ ++ /* Track the index of our plt entry for use in calculating size. */ ++ plt_index = htab->plt_count++; ++ ((struct elf_or1k_link_hash_entry *) h)->plt_index = plt_index; + + /* If this is the first .plt entry, make room for the special + first entry. */ + if (splt->size == 0) +- splt->size = PLT_ENTRY_SIZE; ++ splt->size = elf_or1k_plt_entry_size (plt_index); + + h->plt.offset = splt->size; + +@@ -2800,7 +2871,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) + } + + /* Make room for this entry. */ +- splt->size += PLT_ENTRY_SIZE; ++ splt->size += elf_or1k_plt_entry_size (plt_index); + + /* We also need to make an entry in the .got.plt section, which + will be placed in the .got section by the linker script. */ +diff --git a/ld/testsuite/ld-or1k/gotha1.dd b/ld/testsuite/ld-or1k/gotha1.dd +new file mode 100644 +index 00000000000..0ad1f8f5399 +--- /dev/null ++++ b/ld/testsuite/ld-or1k/gotha1.dd +@@ -0,0 +1,34 @@ ++ ++.*\.x: file format elf32-or1k ++ ++ ++Disassembly of section \.plt: ++ ++[0-9a-f]+ <\.plt>: ++ +[0-9a-f]+: 19 80 00 00 l\.movhi r12,0x0 ++ +[0-9a-f]+: 85 ec [0-9a-f]+ [0-9a-f]+ l\.lwz r15,[0-9]+\(r12\) ++ +[0-9a-f]+: 44 00 78 00 l\.jr r15 ++ +[0-9a-f]+: 85 8c [0-9a-f]+ [0-9a-f]+ l\.lwz r12,[0-9]+\(r12\) ++ +[0-9a-f]+: 19 80 00 00 l\.movhi r12,0x0 ++ +[0-9a-f]+: 85 8c [0-9a-f]+ [0-9a-f]+ l\.lwz r12,[0-9]+\(r12\) ++ +[0-9a-f]+: 44 00 60 00 l\.jr r12 ++ +[0-9a-f]+: a9 60 00 00 l\.ori r11,r0,0x0 ++ ++Disassembly of section \.text: ++ ++[0-9a-f]+ <_start>: ++ +[0-9a-f]+: 9c 21 ff fc l\.addi r1,r1,-4 ++ +[0-9a-f]+: d4 01 48 00 l\.sw 0\(r1\),r9 ++ +[0-9a-f]+: 04 00 00 02 l\.jal [0-9a-f]+ <_start\+0x10> ++ +[0-9a-f]+: 1a 60 00 00 l\.movhi r19,0x0 ++ +[0-9a-f]+: aa 73 [0-9a-f]+ [0-9a-f]+ l\.ori r19,r19,0x[0-9a-f]+ ++ +[0-9a-f]+: e2 73 48 00 l\.add r19,r19,r9 ++ +[0-9a-f]+: 1a 20 00 00 l\.movhi r17,0x0 ++ +[0-9a-f]+: e2 31 98 00 l\.add r17,r17,r19 ++ +[0-9a-f]+: 86 31 00 10 l\.lwz r17,16\(r17\) ++ +[0-9a-f]+: 84 71 00 00 l\.lwz r3,0\(r17\) ++ +[0-9a-f]+: 07 ff ff f2 l\.jal [0-9a-f]+ <\.plt\+0x10> ++ +[0-9a-f]+: 15 00 00 00 l\.nop 0x0 ++ +[0-9a-f]+: 85 21 00 00 l\.lwz r9,0\(r1\) ++ +[0-9a-f]+: 44 00 48 00 l\.jr r9 ++ +[0-9a-f]+: 9c 21 00 04 l\.addi r1,r1,4 +diff --git a/ld/testsuite/ld-or1k/gotha1.s b/ld/testsuite/ld-or1k/gotha1.s +new file mode 100644 +index 00000000000..42b16db425c +--- /dev/null ++++ b/ld/testsuite/ld-or1k/gotha1.s +@@ -0,0 +1,24 @@ ++ .data ++ .p2align 16 ++ ++ .text ++ .globl _start ++_start: ++ l.addi r1, r1, -4 ++ l.sw 0(r1), r9 ++ ++ l.jal 8 ++ l.movhi r19, gotpchi(_GLOBAL_OFFSET_TABLE_-4) ++ l.ori r19, r19, gotpclo(_GLOBAL_OFFSET_TABLE_+0) ++ l.add r19, r19, r9 ++ ++ l.movhi r17, gotha(x) ++ l.add r17, r17, r19 ++ l.lwz r17, got(x)(r17) ++ l.lwz r3, 0(r17) ++ ++ l.jal plt(func) ++ l.nop ++ l.lwz r9, 0(r1) ++ l.jr r9 ++ l.addi r1, r1, 4 +diff --git a/ld/testsuite/ld-or1k/gotha2.dd b/ld/testsuite/ld-or1k/gotha2.dd +new file mode 100644 +index 00000000000..fe09da5466b +--- /dev/null ++++ b/ld/testsuite/ld-or1k/gotha2.dd +@@ -0,0 +1,21 @@ ++ ++.*\.x: file format elf32-or1k ++ ++ ++Disassembly of section \.text: ++ ++[0-9a-f]+ : ++ +[0-9a-f]+: 9c 21 ff f8 l\.addi r1,r1,-8 ++ +[0-9a-f]+: d4 01 80 00 l\.sw 0\(r1\),r16 ++ +[0-9a-f]+: d4 01 48 04 l\.sw 4\(r1\),r9 ++ +[0-9a-f]+: 04 00 [0-9a-f]+ [0-9a-f]+ l\.jal [0-9a-f]+ ++ +[0-9a-f]+: 1a 00 00 00 l\.movhi r16,0x0 ++ +[0-9a-f]+: aa 10 [0-9a-f]+ [0-9a-f]+ l\.ori r16,r16,0x[0-9a-f]+ ++ +[0-9a-f]+: e2 10 48 00 l\.add r16,r16,r9 ++ +[0-9a-f]+: 1a 20 00 00 l\.movhi r17,0x0 ++ +[0-9a-f]+: e2 31 80 00 l\.add r17,r17,r16 ++ +[0-9a-f]+: 86 31 00 0c l\.lwz r17,12\(r17\) ++ +[0-9a-f]+: 85 21 00 04 l\.lwz r9,4\(r1\) ++ +[0-9a-f]+: 86 01 00 00 l\.lwz r16,0\(r1\) ++ +[0-9a-f]+: 44 00 48 00 l\.jr r9 ++ +[0-9a-f]+: 9c 21 00 08 l\.addi r1,r1,8 +diff --git a/ld/testsuite/ld-or1k/gotha2.s b/ld/testsuite/ld-or1k/gotha2.s +new file mode 100644 +index 00000000000..164b282f2dd +--- /dev/null ++++ b/ld/testsuite/ld-or1k/gotha2.s +@@ -0,0 +1,22 @@ ++ .section .text ++ .align 4 ++ .global test ++ .type test, @function ++test: ++ l.addi r1, r1, -8 ++ l.sw 0(r1), r16 ++ l.sw 4(r1), r9 ++ ++ l.jal 8 ++ l.movhi r16, gotpchi(_GLOBAL_OFFSET_TABLE_-4) ++ l.ori r16, r16, gotpclo(_GLOBAL_OFFSET_TABLE_+0) ++ l.add r16, r16, r9 ++ ++ l.movhi r17, gotha(i) ++ l.add r17, r17, r16 ++ l.lwz r17, got(i)(r17) ++ ++ l.lwz r9, 4(r1) ++ l.lwz r16, 0(r1) ++ l.jr r9 ++ l.addi r1, r1, 8 +diff --git a/ld/testsuite/ld-or1k/or1k.exp b/ld/testsuite/ld-or1k/or1k.exp +index 7592e8307c1..8e19ec6c31a 100644 +--- a/ld/testsuite/ld-or1k/or1k.exp ++++ b/ld/testsuite/ld-or1k/or1k.exp +@@ -53,6 +53,14 @@ set or1kplttests { + "" {plt1.s} + {{objdump -dr plt1.x.dd}} + "plt1.x"} ++ {"gotha exec plt" "tmpdir/libpltlib.so" "" ++ "" {gotha1.s} ++ {{objdump -dr gotha1.dd}} ++ "gotha1.x"} ++ {"gotha -fpic -shared" "-fpic -shared" "" ++ "" {gotha2.s} ++ {{objdump -dr gotha2.dd}} ++ "gotha2.x"} + } + + # Not implemented yet +diff --git a/ld/testsuite/ld-or1k/pltlib.s b/ld/testsuite/ld-or1k/pltlib.s +index baf76ca1af7..8b4d7ba48fd 100644 +--- a/ld/testsuite/ld-or1k/pltlib.s ++++ b/ld/testsuite/ld-or1k/pltlib.s +@@ -1,5 +1,6 @@ + .section .data + .globl x, y ++ .size x, 4 + x: .long 33 + y: .long 44 + +-- +2.25.1 + diff --git a/package/binutils/2.36.1/0004-or1k-Implement-relocation-R_OR1K_GOT_AHI16-for-gotha.patch b/package/binutils/2.36.1/0004-or1k-Implement-relocation-R_OR1K_GOT_AHI16-for-gotha.patch new file mode 100644 index 0000000000..08c23d2760 --- /dev/null +++ b/package/binutils/2.36.1/0004-or1k-Implement-relocation-R_OR1K_GOT_AHI16-for-gotha.patch @@ -0,0 +1,256 @@ +From 141dee7402871c7b3994838c3eddf64a92d67be7 Mon Sep 17 00:00:00 2001 +From: Stafford Horne +Date: Sun, 2 May 2021 06:02:15 +0900 +Subject: [PATCH] or1k: Implement relocation R_OR1K_GOT_AHI16 for gotha() + +The gotha() relocation mnemonic will be outputted by OpenRISC GCC when +using the -mcmodel=large option. This relocation is used along with +got() to generate 32-bit GOT offsets. This increases the previous GOT +offset limit from the previous 16-bit (64K) limit. + +This is needed on large binaries where the GOT grows larger than 64k. + +bfd/ChangeLog: + + PR 21464 + * bfd-in2.h: Add BFD_RELOC_OR1K_GOT_AHI16 relocation. + * elf32-or1k.c (or1k_elf_howto_table, or1k_reloc_map): Likewise. + (or1k_final_link_relocate, or1k_elf_relocate_section, + or1k_elf_check_relocs): Likewise. + * libbfd.h (bfd_reloc_code_real_names): Likewise. + * reloc.c: Likewise. + +cpu/ChangeLog: + + PR 21464 + * or1k.opc (or1k_imm16_relocs, parse_reloc): Define parse logic + for gotha() relocation. + +include/ChangeLog: + + PR 21464 + * elf/or1k.h (elf_or1k_reloc_type): Define R_OR1K_GOT_AHI16 number. + +opcodes/ChangeLog: + + PR 21464 + * or1k-asm.c: Regenerate. + +gas/ChangeLog: + + PR 21464 + * testsuite/gas/or1k/reloc-1.s: Add test for new relocation. + * testsuite/gas/or1k/reloc-1.d: Add test result for new + relocation. + +Cc: Giulio Benetti + +fixup reloc, add tests + +Signed-off-by: Giulio Benetti +--- + bfd/bfd-in2.h | 1 + + bfd/elf32-or1k.c | 21 ++++++++++++++++++++- + bfd/libbfd.h | 1 + + bfd/reloc.c | 2 ++ + cpu/or1k.opc | 7 ++++++- + gas/testsuite/gas/or1k/reloc-1.d | 4 +++- + gas/testsuite/gas/or1k/reloc-1.s | 4 ++++ + include/elf/or1k.h | 1 + + opcodes/or1k-asm.c | 7 ++++++- + 9 files changed, 44 insertions(+), 4 deletions(-) + +diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h +index 7eff85b7eaa..e76b9e7a319 100644 +--- a/bfd/bfd-in2.h ++++ b/bfd/bfd-in2.h +@@ -5048,6 +5048,7 @@ then it may be truncated to 8 bits. */ + BFD_RELOC_OR1K_TLS_TPOFF, + BFD_RELOC_OR1K_TLS_DTPOFF, + BFD_RELOC_OR1K_TLS_DTPMOD, ++ BFD_RELOC_OR1K_GOT_AHI16, + + /* H8 elf Relocations. */ + BFD_RELOC_H8_DIR16A8, +diff --git a/bfd/elf32-or1k.c b/bfd/elf32-or1k.c +index 4f82cc4c667..48461854a96 100644 +--- a/bfd/elf32-or1k.c ++++ b/bfd/elf32-or1k.c +@@ -808,6 +808,20 @@ static reloc_howto_type or1k_elf_howto_table[] = + 0, /* Source Mask. */ + 0x03ffffff, /* Dest Mask. */ + TRUE), /* PC relative offset? */ ++ ++ HOWTO (R_OR1K_GOT_AHI16, /* type */ ++ 16, /* rightshift */ ++ 2, /* size (0 = byte, 1 = short, 2 = long) */ ++ 16, /* bitsize */ ++ FALSE, /* pc_relative */ ++ 0, /* bitpos */ ++ complain_overflow_signed, /* complain_on_overflow */ ++ bfd_elf_generic_reloc, /* special_function */ ++ "R_OR1K_GOT_AHI16", /* name */ ++ FALSE, /* partial_inplace */ ++ 0, /* src_mask */ ++ 0xffff, /* dst_mask */ ++ FALSE), /* pcrel_offset */ + }; + + /* Map BFD reloc types to Or1k ELF reloc types. */ +@@ -871,6 +885,7 @@ static const struct or1k_reloc_map or1k_reloc_map[] = + { BFD_RELOC_OR1K_TLS_IE_LO13, R_OR1K_TLS_IE_LO13 }, + { BFD_RELOC_OR1K_SLO13, R_OR1K_SLO13 }, + { BFD_RELOC_OR1K_PLTA26, R_OR1K_PLTA26 }, ++ { BFD_RELOC_OR1K_GOT_AHI16, R_OR1K_GOT_AHI16 }, + }; + + /* tls_type is a mask used to track how each symbol is accessed, +@@ -1111,6 +1126,7 @@ or1k_final_link_relocate (reloc_howto_type *howto, bfd *input_bfd, + switch (howto->type) + { + case R_OR1K_AHI16: ++ case R_OR1K_GOT_AHI16: + case R_OR1K_GOTOFF_AHI16: + case R_OR1K_TLS_IE_AHI16: + case R_OR1K_TLS_LE_AHI16: +@@ -1373,6 +1389,7 @@ or1k_elf_relocate_section (bfd *output_bfd, + } + break; + ++ case R_OR1K_GOT_AHI16: + case R_OR1K_GOT16: + case R_OR1K_GOT_PG21: + case R_OR1K_GOT_LO13: +@@ -1464,7 +1481,8 @@ or1k_elf_relocate_section (bfd *output_bfd, + /* The GOT_PG21 and GOT_LO13 relocs are pc-relative, + while the GOT16 reloc is GOT relative. */ + relocation = got_base + off; +- if (r_type == R_OR1K_GOT16) ++ if (r_type == R_OR1K_GOT16 ++ || r_type == R_OR1K_GOT_AHI16) + relocation -= got_sym_value; + + /* Addend should be zero. */ +@@ -1990,6 +2008,7 @@ or1k_elf_check_relocs (bfd *abfd, + } + break; + ++ case R_OR1K_GOT_AHI16: + case R_OR1K_GOT16: + case R_OR1K_GOT_PG21: + case R_OR1K_GOT_LO13: +diff --git a/bfd/libbfd.h b/bfd/libbfd.h +index 7271a2ad5a1..e0ee2dafc07 100644 +--- a/bfd/libbfd.h ++++ b/bfd/libbfd.h +@@ -2757,6 +2757,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", + "BFD_RELOC_OR1K_TLS_TPOFF", + "BFD_RELOC_OR1K_TLS_DTPOFF", + "BFD_RELOC_OR1K_TLS_DTPMOD", ++ "BFD_RELOC_OR1K_GOT_AHI16", + "BFD_RELOC_H8_DIR16A8", + "BFD_RELOC_H8_DIR16R8", + "BFD_RELOC_H8_DIR24A8", +diff --git a/bfd/reloc.c b/bfd/reloc.c +index 4f4b95a0b7f..fe94e0d8f91 100644 +--- a/bfd/reloc.c ++++ b/bfd/reloc.c +@@ -6204,6 +6204,8 @@ ENUMX + BFD_RELOC_OR1K_GOTPC_HI16 + ENUMX + BFD_RELOC_OR1K_GOTPC_LO16 ++ENUMX ++ BFD_RELOC_OR1K_GOT_AHI16 + ENUMX + BFD_RELOC_OR1K_GOT16 + ENUMX +diff --git a/cpu/or1k.opc b/cpu/or1k.opc +index f0adcbb00a5..5d20a1f33a7 100644 +--- a/cpu/or1k.opc ++++ b/cpu/or1k.opc +@@ -193,7 +193,7 @@ static const bfd_reloc_code_real_type or1k_imm16_relocs[][6] = { + BFD_RELOC_OR1K_GOT_LO13, + BFD_RELOC_UNUSED, + BFD_RELOC_UNUSED, +- BFD_RELOC_UNUSED }, ++ BFD_RELOC_OR1K_GOT_AHI16 }, + { BFD_RELOC_OR1K_GOTPC_LO16, + BFD_RELOC_UNUSED, + BFD_RELOC_UNUSED, +@@ -296,6 +296,11 @@ parse_reloc (const char **strp) + str += 5; + cls = RCLASS_TPOFF; + } ++ else if (strncasecmp (str, "got", 3) == 0) ++ { ++ str += 3; ++ cls = RCLASS_GOT; ++ } + + if (strncasecmp (str, "hi(", 3) == 0) + { +diff --git a/gas/testsuite/gas/or1k/reloc-1.d b/gas/testsuite/gas/or1k/reloc-1.d +index d1bcf5608bb..3a001c4ed99 100644 +--- a/gas/testsuite/gas/or1k/reloc-1.d ++++ b/gas/testsuite/gas/or1k/reloc-1.d +@@ -68,5 +68,7 @@ OFFSET TYPE VALUE + 000000ec R_OR1K_LO13 x + 000000f0 R_OR1K_GOT_LO13 x + 000000f4 R_OR1K_SLO13 x +- ++000000f8 R_OR1K_GOT_AHI16 x ++000000fc R_OR1K_GOT_AHI16 x ++00000100 R_OR1K_GOT_AHI16 x + +diff --git a/gas/testsuite/gas/or1k/reloc-1.s b/gas/testsuite/gas/or1k/reloc-1.s +index e76abef6532..562609aa869 100644 +--- a/gas/testsuite/gas/or1k/reloc-1.s ++++ b/gas/testsuite/gas/or1k/reloc-1.s +@@ -74,3 +74,7 @@ + l.lbz r5,po(x)(r3) + l.lbz r5,gotpo(x)(r3) + l.sb po(x)(r3),r6 ++ ++ l.movhi r4,gotha(x) ++ l.ori r3,r4,gotha(x) ++ l.addi r3,r4,gotha(x) +diff --git a/include/elf/or1k.h b/include/elf/or1k.h +index 7f281481061..69ab90584a2 100644 +--- a/include/elf/or1k.h ++++ b/include/elf/or1k.h +@@ -77,6 +77,7 @@ START_RELOC_NUMBERS (elf_or1k_reloc_type) + RELOC_NUMBER (R_OR1K_TLS_IE_LO13, 51) + RELOC_NUMBER (R_OR1K_SLO13, 52) + RELOC_NUMBER (R_OR1K_PLTA26, 53) ++ RELOC_NUMBER (R_OR1K_GOT_AHI16, 54) + END_RELOC_NUMBERS (R_OR1K_max) + + #define EF_OR1K_NODELAY (1UL << 0) +diff --git a/opcodes/or1k-asm.c b/opcodes/or1k-asm.c +index 045ab6230b6..fdccf67f9e1 100644 +--- a/opcodes/or1k-asm.c ++++ b/opcodes/or1k-asm.c +@@ -177,7 +177,7 @@ static const bfd_reloc_code_real_type or1k_imm16_relocs[][6] = { + BFD_RELOC_OR1K_GOT_LO13, + BFD_RELOC_UNUSED, + BFD_RELOC_UNUSED, +- BFD_RELOC_UNUSED }, ++ BFD_RELOC_OR1K_GOT_AHI16 }, + { BFD_RELOC_OR1K_GOTPC_LO16, + BFD_RELOC_UNUSED, + BFD_RELOC_UNUSED, +@@ -280,6 +280,11 @@ parse_reloc (const char **strp) + str += 5; + cls = RCLASS_TPOFF; + } ++ else if (strncasecmp (str, "got", 3) == 0) ++ { ++ str += 3; ++ cls = RCLASS_GOT; ++ } + + if (strncasecmp (str, "hi(", 3) == 0) + { +-- +2.25.1 + diff --git a/package/binutils/2.36.1/0005-or1k-Avoid-R_OR1K_GOT16-overflow-failures-in-presenc.patch b/package/binutils/2.36.1/0005-or1k-Avoid-R_OR1K_GOT16-overflow-failures-in-presenc.patch new file mode 100644 index 0000000000..618072fb10 --- /dev/null +++ b/package/binutils/2.36.1/0005-or1k-Avoid-R_OR1K_GOT16-overflow-failures-in-presenc.patch @@ -0,0 +1,61 @@ +From de914df5f2ba23a9f6f1fbf6efdc22e1b045901c Mon Sep 17 00:00:00 2001 +From: Stafford Horne +Date: Sun, 2 May 2021 06:02:16 +0900 +Subject: [PATCH] or1k: Avoid R_OR1K_GOT16 overflow failures in presence of + R_OR1K_GOT_AHI16 + +Now that we support R_OR1K_GOT_AHI16 we can relax the R_OR1K_GOT16 +overflow validation check if the section has R_OR1K_GOT_AHI16. + +We cannot simple disable R_OR1K_GOT16 overflow validation as there will +still be binaries that will have only R_OR1K_GOT16. The +R_OR1K_GOT_AHI16 relocation will only be added by GCC when building with +the option -mcmodel=large. + +This assumes that R_OR1K_GOT_AHI16 will come before R_OR1K_GOT16, which +is the code pattern that will be emitted by GCC. + +bfd/ChangeLog: + + PR 21464 + * elf32-or1k.c (or1k_elf_relocate_section): Relax R_OR1K_GOT16 + overflow check if we have R_OR1K_GOT_AHI16 followed by + R_OR1K_GOT16. + +Signed-off-by: Giulio Benetti +--- + bfd/elf32-or1k.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/bfd/elf32-or1k.c b/bfd/elf32-or1k.c +index 48461854a96..44e67f2b84b 100644 +--- a/bfd/elf32-or1k.c ++++ b/bfd/elf32-or1k.c +@@ -1278,6 +1278,7 @@ or1k_elf_relocate_section (bfd *output_bfd, + asection *sgot, *splt; + bfd_vma plt_base, got_base, got_sym_value; + bfd_boolean ret_val = TRUE; ++ bfd_boolean saw_gotha = FALSE; + + if (htab == NULL) + return FALSE; +@@ -1485,6 +1486,16 @@ or1k_elf_relocate_section (bfd *output_bfd, + || r_type == R_OR1K_GOT_AHI16) + relocation -= got_sym_value; + ++ if (r_type == R_OR1K_GOT_AHI16) ++ saw_gotha = TRUE; ++ ++ /* If we have a R_OR1K_GOT16 followed by a R_OR1K_GOT_AHI16 ++ relocation we assume the code is doing the right thing to avoid ++ overflows. Here we mask the lower 16-bit of the relocation to ++ avoid overflow validation failures. */ ++ if (r_type == R_OR1K_GOT16 && saw_gotha) ++ relocation &= 0xffff; ++ + /* Addend should be zero. */ + if (rel->r_addend != 0) + { +-- +2.25.1 + diff --git a/package/binutils/2.36.1/0006-or1k-Support-large-plt_relocs-when-generating-plt-en.patch b/package/binutils/2.36.1/0006-or1k-Support-large-plt_relocs-when-generating-plt-en.patch new file mode 100644 index 0000000000..6d50852fe9 --- /dev/null +++ b/package/binutils/2.36.1/0006-or1k-Support-large-plt_relocs-when-generating-plt-en.patch @@ -0,0 +1,500 @@ +From 4a7b357d0c802685bee7706bafb9702c821286e1 Mon Sep 17 00:00:00 2001 +From: Stafford Horne +Date: Sun, 2 May 2021 06:02:17 +0900 +Subject: [PATCH] or1k: Support large plt_relocs when generating plt + entries + +The current PLT generation code will generate invalid code when the PLT +relocation offset exceeds 64k. This fixes the issue by detecting large +plt_reloc offsets and generare code sequences to create larger plt +relocations. + +The "large" plt code needs 2 extra instructions to create 32-bit offsets. + +bfd/ChangeLog: + + PR 27746 + * elf32-or1k.c (PLT_ENTRY_SIZE_LARGE, PLT_MAX_INSN_COUNT, + OR1K_ADD, OR1K_ORI): New macros to help with plt creation. + (elf_or1k_link_hash_table): New field plt_count. + (elf_or1k_link_hash_entry): New field plt_index. + (elf_or1k_plt_entry_size): New function. + (or1k_write_plt_entry): Update to support variable size PLTs. + (or1k_elf_finish_dynamic_sections): Use new or1k_write_plt_entry + API. + (or1k_elf_finish_dynamic_symbol): Update to write large PLTs + when needed. + (allocate_dynrelocs): Use elf_or1k_plt_entry_size to account for + PLT size. + +ld/ChangeLog: + + PR 27746 + testsuite/ld-or1k/or1k.exp (or1kplttests): Add tests for linking + along with gotha() relocations. + testsuite/ld-or1k/gotha1.dd: New file. + testsuite/ld-or1k/gotha1.s: New file. + testsuite/ld-or1k/gotha2.dd: New file. + testsuite/ld-or1k/gotha2.s: New file + testsuite/ld-or1k/pltlib.s (x): Define size to avoid link + failure. + +Signed-off-by: Giulio Benetti +--- + bfd/elf32-or1k.c | 149 ++++++++++++++++++++++++--------- + ld/testsuite/ld-or1k/gotha1.dd | 34 ++++++++ + ld/testsuite/ld-or1k/gotha1.s | 24 ++++++ + ld/testsuite/ld-or1k/gotha2.dd | 21 +++++ + ld/testsuite/ld-or1k/gotha2.s | 22 +++++ + ld/testsuite/ld-or1k/or1k.exp | 8 ++ + ld/testsuite/ld-or1k/pltlib.s | 1 + + 7 files changed, 220 insertions(+), 39 deletions(-) + create mode 100644 ld/testsuite/ld-or1k/gotha1.dd + create mode 100644 ld/testsuite/ld-or1k/gotha1.s + create mode 100644 ld/testsuite/ld-or1k/gotha2.dd + create mode 100644 ld/testsuite/ld-or1k/gotha2.s + +diff --git a/bfd/elf32-or1k.c b/bfd/elf32-or1k.c +index 44e67f2b84b..3da68e52425 100644 +--- a/bfd/elf32-or1k.c ++++ b/bfd/elf32-or1k.c +@@ -30,10 +30,14 @@ + #define N_ONES(X) (((bfd_vma)2 << (X)) - 1) + + #define PLT_ENTRY_SIZE 16 ++#define PLT_ENTRY_SIZE_LARGE (6*4) ++#define PLT_MAX_INSN_COUNT 6 + + #define OR1K_MOVHI(D) (0x18000000 | (D << 21)) + #define OR1K_ADRP(D) (0x08000000 | (D << 21)) + #define OR1K_LWZ(D,A) (0x84000000 | (D << 21) | (A << 16)) ++#define OR1K_ADD(D,A,B) (0xE0000000 | (D << 21) | (A << 16) | (B << 11)) ++#define OR1K_ORI(D,A) (0xA8000000 | (D << 21) | (A << 16)) + #define OR1K_ORI0(D) (0xA8000000 | (D << 21)) + #define OR1K_JR(B) (0x44000000 | (B << 11)) + #define OR1K_NOP 0x15000000 +@@ -907,6 +911,8 @@ struct elf_or1k_link_hash_entry + { + struct elf_link_hash_entry root; + ++ /* For calculating PLT size. */ ++ bfd_vma plt_index; + /* Track type of TLS access. */ + unsigned char tls_type; + }; +@@ -931,9 +937,20 @@ struct elf_or1k_link_hash_table + { + struct elf_link_hash_table root; + ++ bfd_vma plt_count; + bfd_boolean saw_plta; + }; + ++static size_t ++elf_or1k_plt_entry_size (bfd_vma plt_index) ++{ ++ bfd_vma plt_reloc; ++ ++ plt_reloc = plt_index * sizeof (Elf32_External_Rela); ++ ++ return (plt_reloc > 0xffff) ? PLT_ENTRY_SIZE_LARGE : PLT_ENTRY_SIZE; ++} ++ + /* Get the ELF linker hash table from a link_info structure. */ + #define or1k_elf_hash_table(p) \ + ((is_elf_hash_table ((p)->hash) \ +@@ -2222,33 +2239,46 @@ or1k_elf_check_relocs (bfd *abfd, + } + + static void +-or1k_write_plt_entry (bfd *output_bfd, bfd_byte *contents, unsigned insn1, +- unsigned insn2, unsigned insn3, unsigned insnj) ++or1k_write_plt_entry (bfd *output_bfd, bfd_byte *contents, unsigned insnj, ++ unsigned insns[], size_t insn_count) + { + unsigned nodelay = elf_elfheader (output_bfd)->e_flags & EF_OR1K_NODELAY; +- unsigned insn4; ++ unsigned output_insns[PLT_MAX_INSN_COUNT]; ++ ++ /* Copy instructions into the output buffer. */ ++ for (size_t i = 0; i < insn_count; i++) ++ output_insns[i] = insns[i]; + + /* Honor the no-delay-slot setting. */ +- if (insn3 == OR1K_NOP) ++ if (insns[insn_count-1] == OR1K_NOP) + { +- insn4 = insn3; ++ unsigned slot1, slot2; ++ + if (nodelay) +- insn3 = insnj; ++ slot1 = insns[insn_count-2], slot2 = insnj; + else +- insn3 = insn2, insn2 = insnj; ++ slot1 = insnj, slot2 = insns[insn_count-2]; ++ ++ output_insns[insn_count-2] = slot1; ++ output_insns[insn_count-1] = slot2; ++ output_insns[insn_count] = OR1K_NOP; + } + else + { ++ unsigned slot1, slot2; ++ + if (nodelay) +- insn4 = insnj; ++ slot1 = insns[insn_count-1], slot2 = insnj; + else +- insn4 = insn3, insn3 = insnj; ++ slot1 = insnj, slot2 = insns[insn_count-1]; ++ ++ output_insns[insn_count-1] = slot1; ++ output_insns[insn_count] = slot2; + } + +- bfd_put_32 (output_bfd, insn1, contents); +- bfd_put_32 (output_bfd, insn2, contents + 4); +- bfd_put_32 (output_bfd, insn3, contents + 8); +- bfd_put_32 (output_bfd, insn4, contents + 12); ++ /* Write out the output buffer. */ ++ for (size_t i = 0; i < (insn_count+1); i++) ++ bfd_put_32 (output_bfd, output_insns[i], contents + (i*4)); + } + + /* Finish up the dynamic sections. */ +@@ -2315,7 +2345,8 @@ or1k_elf_finish_dynamic_sections (bfd *output_bfd, + splt = htab->root.splt; + if (splt && splt->size > 0) + { +- unsigned plt0, plt1, plt2; ++ unsigned plt[PLT_MAX_INSN_COUNT]; ++ size_t plt_insn_count = 3; + bfd_vma got_addr = sgot->output_section->vma + sgot->output_offset; + + /* Note we force 16 byte alignment on the .got, so that +@@ -2326,27 +2357,27 @@ or1k_elf_finish_dynamic_sections (bfd *output_bfd, + bfd_vma pc = splt->output_section->vma + splt->output_offset; + unsigned pa = ((got_addr >> 13) - (pc >> 13)) & 0x1fffff; + unsigned po = got_addr & 0x1fff; +- plt0 = OR1K_ADRP(12) | pa; +- plt1 = OR1K_LWZ(15,12) | (po + 8); +- plt2 = OR1K_LWZ(12,12) | (po + 4); ++ plt[0] = OR1K_ADRP(12) | pa; ++ plt[1] = OR1K_LWZ(15,12) | (po + 8); ++ plt[2] = OR1K_LWZ(12,12) | (po + 4); + } + else if (bfd_link_pic (info)) + { +- plt0 = OR1K_LWZ(15, 16) | 8; /* .got+8 */ +- plt1 = OR1K_LWZ(12, 16) | 4; /* .got+4 */ +- plt2 = OR1K_NOP; ++ plt[0] = OR1K_LWZ(15, 16) | 8; /* .got+8 */ ++ plt[1] = OR1K_LWZ(12, 16) | 4; /* .got+4 */ ++ plt[2] = OR1K_NOP; + } + else + { + unsigned ha = ((got_addr + 0x8000) >> 16) & 0xffff; + unsigned lo = got_addr & 0xffff; +- plt0 = OR1K_MOVHI(12) | ha; +- plt1 = OR1K_LWZ(15,12) | (lo + 8); +- plt2 = OR1K_LWZ(12,12) | (lo + 4); ++ plt[0] = OR1K_MOVHI(12) | ha; ++ plt[1] = OR1K_LWZ(15,12) | (lo + 8); ++ plt[2] = OR1K_LWZ(12,12) | (lo + 4); + } + +- or1k_write_plt_entry (output_bfd, splt->contents, +- plt0, plt1, plt2, OR1K_JR(15)); ++ or1k_write_plt_entry (output_bfd, splt->contents, OR1K_JR(15), ++ plt, plt_insn_count); + + elf_section_data (splt->output_section)->this_hdr.sh_entsize = 4; + } +@@ -2389,7 +2420,8 @@ or1k_elf_finish_dynamic_symbol (bfd *output_bfd, + + if (h->plt.offset != (bfd_vma) -1) + { +- unsigned int plt0, plt1, plt2; ++ unsigned int plt[PLT_MAX_INSN_COUNT]; ++ size_t plt_insn_count = 3; + asection *splt; + asection *sgot; + asection *srela; +@@ -2401,6 +2433,7 @@ or1k_elf_finish_dynamic_symbol (bfd *output_bfd, + bfd_vma got_offset; + bfd_vma got_addr; + Elf_Internal_Rela rela; ++ bfd_boolean large_plt_entry; + + /* This symbol has an entry in the procedure linkage table. Set + it up. */ +@@ -2418,10 +2451,13 @@ or1k_elf_finish_dynamic_symbol (bfd *output_bfd, + corresponds to this symbol. This is the index of this symbol + in all the symbols for which we are making plt entries. The + first entry in the procedure linkage table is reserved. */ +- plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1; ++ plt_index = ((struct elf_or1k_link_hash_entry *) h)->plt_index; + plt_addr = plt_base_addr + h->plt.offset; + plt_reloc = plt_index * sizeof (Elf32_External_Rela); + ++ large_plt_entry = (elf_or1k_plt_entry_size (plt_index) ++ == PLT_ENTRY_SIZE_LARGE); ++ + /* Get the offset into the .got table of the entry that + corresponds to this function. Each .got entry is 4 bytes. + The first three are reserved. */ +@@ -2433,27 +2469,57 @@ or1k_elf_finish_dynamic_symbol (bfd *output_bfd, + { + unsigned pa = ((got_addr >> 13) - (plt_addr >> 13)) & 0x1fffff; + unsigned po = (got_addr & 0x1fff); +- plt0 = OR1K_ADRP(12) | pa; +- plt1 = OR1K_LWZ(12,12) | po; +- plt2 = OR1K_ORI0(11) | plt_reloc; ++ plt[0] = OR1K_ADRP(12) | pa; ++ plt[1] = OR1K_LWZ(12,12) | po; ++ plt[2] = OR1K_ORI0(11) | plt_reloc; + } + else if (bfd_link_pic (info)) + { +- plt0 = OR1K_LWZ(12,16) | got_offset; +- plt1 = OR1K_ORI0(11) | plt_reloc; +- plt2 = OR1K_NOP; ++ if (large_plt_entry) ++ { ++ unsigned gotha = ((got_offset + 0x8000) >> 16) & 0xffff; ++ unsigned got = got_offset & 0xffff; ++ unsigned pltrelhi = (plt_reloc >> 16) & 0xffff; ++ unsigned pltrello = plt_reloc & 0xffff; ++ ++ plt[0] = OR1K_MOVHI(12) | gotha; ++ plt[1] = OR1K_ADD(12,12,16); ++ plt[2] = OR1K_LWZ(12,12) | got; ++ plt[3] = OR1K_MOVHI(11) | pltrelhi; ++ plt[4] = OR1K_ORI(11,11) | pltrello; ++ plt_insn_count = 5; ++ } ++ else ++ { ++ plt[0] = OR1K_LWZ(12,16) | got_offset; ++ plt[1] = OR1K_ORI0(11) | plt_reloc; ++ plt[2] = OR1K_NOP; ++ } + } + else + { + unsigned ha = ((got_addr + 0x8000) >> 16) & 0xffff; + unsigned lo = got_addr & 0xffff; +- plt0 = OR1K_MOVHI(12) | ha; +- plt1 = OR1K_LWZ(12,12) | lo; +- plt2 = OR1K_ORI0(11) | plt_reloc; ++ plt[0] = OR1K_MOVHI(12) | ha; ++ plt[1] = OR1K_LWZ(12,12) | lo; ++ plt[2] = OR1K_ORI0(11) | plt_reloc; ++ } ++ ++ /* For large code model we fixup the non-PIC PLT relocation instructions ++ here. */ ++ if (large_plt_entry && !bfd_link_pic (info)) ++ { ++ unsigned pltrelhi = (plt_reloc >> 16) & 0xffff; ++ unsigned pltrello = plt_reloc & 0xffff; ++ ++ plt[2] = OR1K_MOVHI(11) | pltrelhi; ++ plt[3] = OR1K_ORI(11,11) | pltrello; ++ plt[4] = OR1K_NOP; ++ plt_insn_count = 5; + } + + or1k_write_plt_entry (output_bfd, splt->contents + h->plt.offset, +- plt0, plt1, plt2, OR1K_JR(12)); ++ OR1K_JR(12), plt, plt_insn_count); + + /* Fill in the entry in the global offset table. We initialize it to + point to the top of the plt. This is done to lazy lookup the actual +@@ -2777,11 +2843,16 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) + if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info), h)) + { + asection *splt = htab->root.splt; ++ bfd_vma plt_index; ++ ++ /* Track the index of our plt entry for use in calculating size. */ ++ plt_index = htab->plt_count++; ++ ((struct elf_or1k_link_hash_entry *) h)->plt_index = plt_index; + + /* If this is the first .plt entry, make room for the special + first entry. */ + if (splt->size == 0) +- splt->size = PLT_ENTRY_SIZE; ++ splt->size = elf_or1k_plt_entry_size (plt_index); + + h->plt.offset = splt->size; + +@@ -2798,7 +2869,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) + } + + /* Make room for this entry. */ +- splt->size += PLT_ENTRY_SIZE; ++ splt->size += elf_or1k_plt_entry_size (plt_index); + + /* We also need to make an entry in the .got.plt section, which + will be placed in the .got section by the linker script. */ +diff --git a/ld/testsuite/ld-or1k/gotha1.dd b/ld/testsuite/ld-or1k/gotha1.dd +new file mode 100644 +index 00000000000..0ad1f8f5399 +--- /dev/null ++++ b/ld/testsuite/ld-or1k/gotha1.dd +@@ -0,0 +1,34 @@ ++ ++.*\.x: file format elf32-or1k ++ ++ ++Disassembly of section \.plt: ++ ++[0-9a-f]+ <\.plt>: ++ +[0-9a-f]+: 19 80 00 00 l\.movhi r12,0x0 ++ +[0-9a-f]+: 85 ec [0-9a-f]+ [0-9a-f]+ l\.lwz r15,[0-9]+\(r12\) ++ +[0-9a-f]+: 44 00 78 00 l\.jr r15 ++ +[0-9a-f]+: 85 8c [0-9a-f]+ [0-9a-f]+ l\.lwz r12,[0-9]+\(r12\) ++ +[0-9a-f]+: 19 80 00 00 l\.movhi r12,0x0 ++ +[0-9a-f]+: 85 8c [0-9a-f]+ [0-9a-f]+ l\.lwz r12,[0-9]+\(r12\) ++ +[0-9a-f]+: 44 00 60 00 l\.jr r12 ++ +[0-9a-f]+: a9 60 00 00 l\.ori r11,r0,0x0 ++ ++Disassembly of section \.text: ++ ++[0-9a-f]+ <_start>: ++ +[0-9a-f]+: 9c 21 ff fc l\.addi r1,r1,-4 ++ +[0-9a-f]+: d4 01 48 00 l\.sw 0\(r1\),r9 ++ +[0-9a-f]+: 04 00 00 02 l\.jal [0-9a-f]+ <_start\+0x10> ++ +[0-9a-f]+: 1a 60 00 00 l\.movhi r19,0x0 ++ +[0-9a-f]+: aa 73 [0-9a-f]+ [0-9a-f]+ l\.ori r19,r19,0x[0-9a-f]+ ++ +[0-9a-f]+: e2 73 48 00 l\.add r19,r19,r9 ++ +[0-9a-f]+: 1a 20 00 00 l\.movhi r17,0x0 ++ +[0-9a-f]+: e2 31 98 00 l\.add r17,r17,r19 ++ +[0-9a-f]+: 86 31 00 10 l\.lwz r17,16\(r17\) ++ +[0-9a-f]+: 84 71 00 00 l\.lwz r3,0\(r17\) ++ +[0-9a-f]+: 07 ff ff f2 l\.jal [0-9a-f]+ <\.plt\+0x10> ++ +[0-9a-f]+: 15 00 00 00 l\.nop 0x0 ++ +[0-9a-f]+: 85 21 00 00 l\.lwz r9,0\(r1\) ++ +[0-9a-f]+: 44 00 48 00 l\.jr r9 ++ +[0-9a-f]+: 9c 21 00 04 l\.addi r1,r1,4 +diff --git a/ld/testsuite/ld-or1k/gotha1.s b/ld/testsuite/ld-or1k/gotha1.s +new file mode 100644 +index 00000000000..42b16db425c +--- /dev/null ++++ b/ld/testsuite/ld-or1k/gotha1.s +@@ -0,0 +1,24 @@ ++ .data ++ .p2align 16 ++ ++ .text ++ .globl _start ++_start: ++ l.addi r1, r1, -4 ++ l.sw 0(r1), r9 ++ ++ l.jal 8 ++ l.movhi r19, gotpchi(_GLOBAL_OFFSET_TABLE_-4) ++ l.ori r19, r19, gotpclo(_GLOBAL_OFFSET_TABLE_+0) ++ l.add r19, r19, r9 ++ ++ l.movhi r17, gotha(x) ++ l.add r17, r17, r19 ++ l.lwz r17, got(x)(r17) ++ l.lwz r3, 0(r17) ++ ++ l.jal plt(func) ++ l.nop ++ l.lwz r9, 0(r1) ++ l.jr r9 ++ l.addi r1, r1, 4 +diff --git a/ld/testsuite/ld-or1k/gotha2.dd b/ld/testsuite/ld-or1k/gotha2.dd +new file mode 100644 +index 00000000000..fe09da5466b +--- /dev/null ++++ b/ld/testsuite/ld-or1k/gotha2.dd +@@ -0,0 +1,21 @@ ++ ++.*\.x: file format elf32-or1k ++ ++ ++Disassembly of section \.text: ++ ++[0-9a-f]+ : ++ +[0-9a-f]+: 9c 21 ff f8 l\.addi r1,r1,-8 ++ +[0-9a-f]+: d4 01 80 00 l\.sw 0\(r1\),r16 ++ +[0-9a-f]+: d4 01 48 04 l\.sw 4\(r1\),r9 ++ +[0-9a-f]+: 04 00 [0-9a-f]+ [0-9a-f]+ l\.jal [0-9a-f]+ ++ +[0-9a-f]+: 1a 00 00 00 l\.movhi r16,0x0 ++ +[0-9a-f]+: aa 10 [0-9a-f]+ [0-9a-f]+ l\.ori r16,r16,0x[0-9a-f]+ ++ +[0-9a-f]+: e2 10 48 00 l\.add r16,r16,r9 ++ +[0-9a-f]+: 1a 20 00 00 l\.movhi r17,0x0 ++ +[0-9a-f]+: e2 31 80 00 l\.add r17,r17,r16 ++ +[0-9a-f]+: 86 31 00 0c l\.lwz r17,12\(r17\) ++ +[0-9a-f]+: 85 21 00 04 l\.lwz r9,4\(r1\) ++ +[0-9a-f]+: 86 01 00 00 l\.lwz r16,0\(r1\) ++ +[0-9a-f]+: 44 00 48 00 l\.jr r9 ++ +[0-9a-f]+: 9c 21 00 08 l\.addi r1,r1,8 +diff --git a/ld/testsuite/ld-or1k/gotha2.s b/ld/testsuite/ld-or1k/gotha2.s +new file mode 100644 +index 00000000000..164b282f2dd +--- /dev/null ++++ b/ld/testsuite/ld-or1k/gotha2.s +@@ -0,0 +1,22 @@ ++ .section .text ++ .align 4 ++ .global test ++ .type test, @function ++test: ++ l.addi r1, r1, -8 ++ l.sw 0(r1), r16 ++ l.sw 4(r1), r9 ++ ++ l.jal 8 ++ l.movhi r16, gotpchi(_GLOBAL_OFFSET_TABLE_-4) ++ l.ori r16, r16, gotpclo(_GLOBAL_OFFSET_TABLE_+0) ++ l.add r16, r16, r9 ++ ++ l.movhi r17, gotha(i) ++ l.add r17, r17, r16 ++ l.lwz r17, got(i)(r17) ++ ++ l.lwz r9, 4(r1) ++ l.lwz r16, 0(r1) ++ l.jr r9 ++ l.addi r1, r1, 8 +diff --git a/ld/testsuite/ld-or1k/or1k.exp b/ld/testsuite/ld-or1k/or1k.exp +index 8bb943aacc9..f10949e89aa 100644 +--- a/ld/testsuite/ld-or1k/or1k.exp ++++ b/ld/testsuite/ld-or1k/or1k.exp +@@ -53,6 +53,14 @@ set or1kplttests { + "" {plt1.s} + {{objdump -dr plt1.x.dd}} + "plt1.x"} ++ {"gotha exec plt" "tmpdir/libpltlib.so" "" ++ "" {gotha1.s} ++ {{objdump -dr gotha1.dd}} ++ "gotha1.x"} ++ {"gotha -fpic -shared" "-fpic -shared" "" ++ "" {gotha2.s} ++ {{objdump -dr gotha2.dd}} ++ "gotha2.x"} + } + + # Not implemented yet +diff --git a/ld/testsuite/ld-or1k/pltlib.s b/ld/testsuite/ld-or1k/pltlib.s +index baf76ca1af7..8b4d7ba48fd 100644 +--- a/ld/testsuite/ld-or1k/pltlib.s ++++ b/ld/testsuite/ld-or1k/pltlib.s +@@ -1,5 +1,6 @@ + .section .data + .globl x, y ++ .size x, 4 + x: .long 33 + y: .long 44 + +-- +2.25.1 + -- 2.30.2