diff options
-rw-r--r-- | bfd/ChangeLog | 9 | ||||
-rw-r--r-- | bfd/elfnn-riscv.c | 46 | ||||
-rw-r--r-- | ld/ChangeLog | 9 | ||||
-rw-r--r-- | ld/testsuite/ld-riscv-elf/ifunc-plt-got-overwrite-exe.rd | 4 | ||||
-rw-r--r-- | ld/testsuite/ld-riscv-elf/ifunc-plt-got-overwrite-pic.rd | 8 | ||||
-rw-r--r-- | ld/testsuite/ld-riscv-elf/ifunc-plt-got-overwrite-pie.rd | 7 | ||||
-rw-r--r-- | ld/testsuite/ld-riscv-elf/ifunc-plt-got-overwrite.d | 19 | ||||
-rw-r--r-- | ld/testsuite/ld-riscv-elf/ifunc-plt-got-overwrite.s | 38 | ||||
-rw-r--r-- | ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp | 7 |
9 files changed, 140 insertions, 7 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index b0cd8b8..7fb6181 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,5 +1,14 @@ 2020-10-16 Nelson Chu <nelson.chu@sifive.com> + * elfnn-riscv.c (riscv_elf_link_hash_table): Add last_iplt_index. + (riscv_elf_size_dynamic_sections): Initialize the last_iplt_index. + (riscv_elf_relocate_section): Use riscv_elf_append_rela. + (riscv_elf_finish_dynamic_symbol): If the use_elf_append_rela is + false, then we should add the dynamic relocs from the last of + the .rela.iplt, and don't use the riscv_elf_append_rela to add. + +2020-10-16 Nelson Chu <nelson.chu@sifive.com> + * elfnn-riscv.c: Include "objalloc.h" since we need objalloc_alloc. (riscv_elf_link_hash_table): Add loc_hash_table and loc_hash_memory for local STT_GNU_IFUNC symbols. diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c index a26cd3f..a5b2c8a 100644 --- a/bfd/elfnn-riscv.c +++ b/bfd/elfnn-riscv.c @@ -120,6 +120,9 @@ struct riscv_elf_link_hash_table /* Used by local STT_GNU_IFUNC symbols. */ htab_t loc_hash_table; void * loc_hash_memory; + + /* The index of the last unused .rel.iplt slot. */ + bfd_vma last_iplt_index; }; @@ -1424,6 +1427,11 @@ riscv_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) local ifunc symbols. */ htab_traverse (htab->loc_hash_table, allocate_local_ifunc_dynrelocs, info); + /* Used to resolve the dynamic relocs overwite problems when + generating static executable. */ + if (htab->elf.irelplt) + htab->last_iplt_index = htab->elf.irelplt->reloc_count - 1; + if (htab->elf.sgotplt) { struct elf_link_hash_entry *got; @@ -2904,6 +2912,7 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd, asection *sgot; asection *srela; Elf_Internal_Rela rela; + bfd_boolean use_elf_append_rela = TRUE; /* This symbol has an entry in the GOT. Set it up. */ @@ -2920,12 +2929,18 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd, if (h->plt.offset == (bfd_vma) -1) { /* STT_GNU_IFUNC is referenced without PLT. */ + if (htab->elf.splt == NULL) { - /* use .rel[a].iplt section to store .got relocations + /* Use .rela.iplt section to store .got relocations in static executable. */ srela = htab->elf.irelplt; + + /* Do not use riscv_elf_append_rela to add dynamic + relocs. */ + use_elf_append_rela = FALSE; } + if (SYMBOL_REFERENCES_LOCAL (info, h)) { info->callbacks->minfo (_("Local IFUNC function `%s' in %pB\n"), @@ -2973,14 +2988,14 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd, return TRUE; } } - /* If this is a local symbol reference, we just want to emit a RELATIVE - reloc. This can happen if it is a -Bsymbolic link, or a pie link, or - the symbol was forced to be local because of a version file. - The entry in the global offset table will already have been - initialized in the relocate_section function. */ else if (bfd_link_pic (info) && SYMBOL_REFERENCES_LOCAL (info, h)) { + /* If this is a local symbol reference, we just want to emit + a RELATIVE reloc. This can happen if it is a -Bsymbolic link, + or a pie link, or the symbol was forced to be local because + of a version file. The entry in the global offset table will + already have been initialized in the relocate_section function. */ BFD_ASSERT((h->got.offset & 1) != 0); asection *sec = h->root.u.def.section; rela.r_info = ELFNN_R_INFO (0, R_RISCV_RELATIVE); @@ -2998,7 +3013,24 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd, bfd_put_NN (output_bfd, 0, sgot->contents + (h->got.offset & ~(bfd_vma) 1)); - riscv_elf_append_rela (output_bfd, srela, &rela); + + if (use_elf_append_rela) + riscv_elf_append_rela (output_bfd, srela, &rela); + else + { + /* Use riscv_elf_append_rela to add the dynamic relocs into + .rela.iplt may cause the overwrite problems. Since we insert + the relocs for PLT didn't handle the reloc_index of .rela.iplt, + but the riscv_elf_append_rela adds the relocs to the place + that are calculated from the reloc_index (in seqential). + + One solution is that add these dynamic relocs (GOT IFUNC) + from the last of .rela.iplt section. */ + bfd_vma iplt_idx = htab->last_iplt_index--; + bfd_byte *loc = srela->contents + + iplt_idx * sizeof (ElfNN_External_Rela); + bed->s->swap_reloca_out (output_bfd, &rela, loc); + } } if (h->needs_copy) diff --git a/ld/ChangeLog b/ld/ChangeLog index 3a9d381..780bb4b 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,5 +1,14 @@ 2020-10-16 Nelson Chu <nelson.chu@sifive.com> + * testsuite/ld-riscv-elf/ifunc-plt-got-overwrite.s: New testcase. + * testsuite/ld-riscv-elf/ifunc-plt-got-overwrite.d: Likewise. + * testsuite/ld-riscv-elf/ifunc-plt-got-overwrite-exe.rd: Likewise. + * testsuite/ld-riscv-elf/ifunc-plt-got-overwrite-pic.rd: Likewise. + * testsuite/ld-riscv-elf/ifunc-plt-got-overwrite-pie.rd: Likewise. + * testsuite/ld-riscv-elf/ld-riscv-elf.exp: Updated. + +2020-10-16 Nelson Chu <nelson.chu@sifive.com> + * emulparams/elf32lriscv-defs.sh: Add IREL_IN_PLT. * testsuite/ld-ifunc/ifunc.exp: Enable ifunc tests for RISC-V. * testsuite/ld-riscv-elf/ld-riscv-elf.exp (run_dump_test_ifunc): diff --git a/ld/testsuite/ld-riscv-elf/ifunc-plt-got-overwrite-exe.rd b/ld/testsuite/ld-riscv-elf/ifunc-plt-got-overwrite-exe.rd new file mode 100644 index 0000000..0de47a4 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-plt-got-overwrite-exe.rd @@ -0,0 +1,4 @@ +Relocation section '.rela.plt' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_IRELATIVE[ ]+[0-9a-f]* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_IRELATIVE[ ]+[0-9a-f]* diff --git a/ld/testsuite/ld-riscv-elf/ifunc-plt-got-overwrite-pic.rd b/ld/testsuite/ld-riscv-elf/ifunc-plt-got-overwrite-pic.rd new file mode 100644 index 0000000..f65d789 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-plt-got-overwrite-pic.rd @@ -0,0 +1,8 @@ +Relocation section '.rela.got' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_(32|64)[ ]+foo2\(\)[ ]+foo2 \+ 0 +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_(32|64)[ ]+foo1\(\)[ ]+foo1 \+ 0 +#... +Relocation section '.rela.plt' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_JUMP_SLOT[ ]+foo1\(\)[ ]+foo1 \+ 0 diff --git a/ld/testsuite/ld-riscv-elf/ifunc-plt-got-overwrite-pie.rd b/ld/testsuite/ld-riscv-elf/ifunc-plt-got-overwrite-pie.rd new file mode 100644 index 0000000..32e66f0 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-plt-got-overwrite-pie.rd @@ -0,0 +1,7 @@ +Relocation section '.rela.got' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_IRELATIVE[ ]+[0-9a-f]* + +Relocation section '.rela.plt' at .* +[ ]+Offset[ ]+Info[ ]+Type[ ]+.* +[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_RISCV_IRELATIVE[ ]+[0-9a-f]* diff --git a/ld/testsuite/ld-riscv-elf/ifunc-plt-got-overwrite.d b/ld/testsuite/ld-riscv-elf/ifunc-plt-got-overwrite.d new file mode 100644 index 0000000..333dea3 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-plt-got-overwrite.d @@ -0,0 +1,19 @@ +#... +Disassembly of section .plt: +#... +0+[0-9a-f]+ <(\*ABS\*\+0x[0-9a-f]+@plt|foo@plt|.plt)>: +#... +Disassembly of section .text: +#... +0+[0-9a-f]+ <foo_resolver>: +#... +0+[0-9a-f]+ <bar>: +.*:[ ]+[0-9a-f]+[ ]+auipc[ ]+.* +.*:[ ]+[0-9a-f]+[ ]+(lw|ld)[ ]+.*<(_GLOBAL_OFFSET_TABLE_.*|.*)> +.*:[ ]+[0-9a-f]+[ ]+auipc[ ]+.* +.*:[ ]+[0-9a-f]+[ ]+jalr[ ]+.*<(.*plt.*)> +.*:[ ]+[0-9a-f]+[ ]+auipc[ ]+.* +.*:[ ]+[0-9a-f]+[ ]+jalr[ ]+.*<(.*plt.*)> +.*:[ ]+[0-9a-f]+[ ]+auipc[ ]+.* +.*:[ ]+[0-9a-f]+[ ]+(lw|ld)[ ]+.*<(_GLOBAL_OFFSET_TABLE_.*|.*)> +#... diff --git a/ld/testsuite/ld-riscv-elf/ifunc-plt-got-overwrite.s b/ld/testsuite/ld-riscv-elf/ifunc-plt-got-overwrite.s new file mode 100644 index 0000000..6c2f8e8 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/ifunc-plt-got-overwrite.s @@ -0,0 +1,38 @@ + .text + + .type foo_resolver, @function +foo_resolver: + ret + .size foo_resolver, .-foo_resolver + + .globl foo1 + .type foo1, %gnu_indirect_function + .set foo1, foo_resolver + + .globl foo2 + .type foo2, %gnu_indirect_function + .set foo2, foo_resolver + + .globl bar + .type bar, @function +bar: +.L1: + auipc x1, %got_pcrel_hi (foo1) +.ifdef __64_bit__ + ld x1, %pcrel_lo (.L1) (x1) +.else + lw x1, %pcrel_lo (.L1) (x1) +.endif + + call foo1 + call foo1@plt + +.L2: + auipc x2, %got_pcrel_hi (foo2) +.ifdef __64_bit__ + ld x2, %pcrel_lo (.L2) (x2) +.else + lw x2, %pcrel_lo (.L2) (x2) +.endif + ret + .size bar, .-bar diff --git a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp index b82e092..9834041 100644 --- a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp +++ b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp @@ -175,6 +175,13 @@ if [istarget "riscv*-*-*"] { run_dump_test_ifunc "ifunc-plt-02" rv64 exe run_dump_test_ifunc "ifunc-plt-02" rv64 pie run_dump_test_ifunc "ifunc-plt-02" rv64 pic + # Check the .rela.iplt overwrite issue. + run_dump_test_ifunc "ifunc-plt-got-overwrite" rv32 exe + run_dump_test_ifunc "ifunc-plt-got-overwrite" rv32 pie + run_dump_test_ifunc "ifunc-plt-got-overwrite" rv32 pic + run_dump_test_ifunc "ifunc-plt-got-overwrite" rv64 exe + run_dump_test_ifunc "ifunc-plt-got-overwrite" rv64 pie + run_dump_test_ifunc "ifunc-plt-got-overwrite" rv64 pic # Setup shared libraries. run_ld_link_tests { |