diff options
Diffstat (limited to 'bfd/elfnn-riscv.c')
-rw-r--r-- | bfd/elfnn-riscv.c | 430 |
1 files changed, 340 insertions, 90 deletions
diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c index 1c494f5..af08f7d 100644 --- a/bfd/elfnn-riscv.c +++ b/bfd/elfnn-riscv.c @@ -99,7 +99,7 @@ ((H) != NULL \ && (H)->dynindx != -1 \ && (!bfd_link_pic (INFO) \ - || !SYMBOLIC_BIND ((INFO), (H)) \ + || !(bfd_link_pie ((INFO)) || SYMBOLIC_BIND ((INFO), (H))) \ || !(H)->def_regular)) /* True if this is actually a static link, or it is a -Bsymbolic link @@ -176,6 +176,11 @@ struct _bfd_riscv_elf_obj_tdata /* tls_type for each local got entry. */ char *local_got_tls_type; + + /* All GNU_PROPERTY_RISCV_FEATURE_1_AND properties. */ + uint32_t gnu_and_prop; + /* PLT type. */ + riscv_plt_type plt_type; }; #define _bfd_riscv_elf_tdata(abfd) \ @@ -232,6 +237,15 @@ struct riscv_elf_link_hash_table /* Relocations for variant CC symbols may be present. */ int variant_cc; + + /* The number of bytes in the PLT header and enties. */ + bfd_size_type plt_header_size; + bfd_size_type plt_entry_size; + + /* Functions to make PLT header and entries. */ + bool (*make_plt_header) (bfd *output_bfd, struct riscv_elf_link_hash_table *htab); + bool (*make_plt_entry) (bfd *output_bfd, asection *got, bfd_vma got_offset, + asection *plt, bfd_vma plt_offset); }; /* Instruction access functions. */ @@ -252,6 +266,12 @@ struct riscv_elf_link_hash_table && elf_hash_table_id (elf_hash_table (p)) == RISCV_ELF_DATA) \ ? (struct riscv_elf_link_hash_table *) (p)->hash : NULL) +/* Forward declaration PLT related functions. */ +static bool +riscv_make_plt_header (bfd *, struct riscv_elf_link_hash_table *); +static bool +riscv_make_plt_entry (bfd *, asection *, bfd_vma, asection *, bfd_vma); + void riscv_elfNN_set_options (struct bfd_link_info *link_info, struct riscv_elf_params *params) @@ -297,6 +317,12 @@ riscv_is_insn_reloc (const reloc_howto_type *howto) #define PLT_ENTRY_INSNS 4 #define PLT_HEADER_SIZE (PLT_HEADER_INSNS * 4) #define PLT_ENTRY_SIZE (PLT_ENTRY_INSNS * 4) + +#define PLT_ZICFILP_UNLABELED_HEADER_INSNS 12 +#define PLT_ZICFILP_UNLABELED_ENTRY_INSNS 4 +#define PLT_ZICFILP_UNLABELED_HEADER_SIZE (PLT_ZICFILP_UNLABELED_HEADER_INSNS * 4) +#define PLT_ZICFILP_UNLABELED_ENTRY_SIZE (PLT_ZICFILP_UNLABELED_ENTRY_INSNS * 4) + #define GOT_ENTRY_SIZE RISCV_ELF_WORD_BYTES #define TLS_GD_GOT_ENTRY_SIZE (RISCV_ELF_WORD_BYTES * 2) #define TLS_IE_GOT_ENTRY_SIZE RISCV_ELF_WORD_BYTES @@ -314,12 +340,42 @@ riscv_is_insn_reloc (const reloc_howto_type *howto) # define MATCH_LREG MATCH_LD #endif + +/* Check whether the compact PLT is used in this object. Tools need this + to dump the correct PLT header contents. */ + +static long +elfNN_riscv_get_synthetic_symtab (bfd *abfd, + long symcount, + asymbol **syms, + long dynsymcount, + asymbol **dynsyms, + asymbol **ret) +{ + /* Check Zicfilp PLT. */ + elf_property *prop; + prop = _bfd_elf_get_property (abfd, GNU_PROPERTY_RISCV_FEATURE_1_AND, 4); + if (prop) + { + if (prop->u.number & GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED) + _bfd_riscv_elf_tdata (abfd)->plt_type |= PLT_ZICFILP_UNLABELED; + } + + return _bfd_elf_get_synthetic_symtab (abfd, symcount, syms, + dynsymcount, dynsyms, ret); +} + /* Generate a PLT header. */ static bool -riscv_make_plt_header (bfd *output_bfd, bfd_vma gotplt_addr, bfd_vma addr, - uint32_t *entry) +riscv_make_plt_header (bfd *output_bfd, struct riscv_elf_link_hash_table *htab) { + asection *splt = htab->elf.splt; + bfd_vma addr = sec_addr (splt); + + asection *sgotplt = htab->elf.sgotplt; + bfd_vma gotplt_addr = sec_addr (sgotplt); + bfd_vma gotplt_offset_high = RISCV_PCREL_HIGH_PART (gotplt_addr, addr); bfd_vma gotplt_offset_low = RISCV_PCREL_LOW_PART (gotplt_addr, addr); @@ -340,6 +396,7 @@ riscv_make_plt_header (bfd *output_bfd, bfd_vma gotplt_addr, bfd_vma addr, l[w|d] t0, PTRSIZE(t0) # link map jr t3 */ + uint32_t entry[PLT_HEADER_INSNS]; entry[0] = RISCV_UTYPE (AUIPC, X_T2, gotplt_offset_high); entry[1] = RISCV_RTYPE (SUB, X_T1, X_T1, X_T3); entry[2] = RISCV_ITYPE (LREG, X_T3, X_T2, gotplt_offset_low); @@ -349,15 +406,78 @@ riscv_make_plt_header (bfd *output_bfd, bfd_vma gotplt_addr, bfd_vma addr, entry[6] = RISCV_ITYPE (LREG, X_T0, X_T0, RISCV_ELF_WORD_BYTES); entry[7] = RISCV_ITYPE (JALR, 0, X_T3, 0); + for (int i = 0; i < PLT_HEADER_INSNS; i++) + bfd_putl32 (entry[i], splt->contents + 4 * i); + + return true; +} + +static bool +riscv_make_plt_zicfilp_unlabeled_header (bfd *output_bfd, + struct riscv_elf_link_hash_table *htab) +{ + /* + lpad 0 # disable label checking + auipc t2, %hi(.got.plt) # Rewrite this to using + sub t1, t1, t3 # shifted .got.plt offset + hdr size + 16 + l[w|d] t3, %lo(1b)(t2) # _dl_runtime_resolve + addi t1, t1, -(hdr size + 12) # shifted .got.plt offset + addi t0, t2, %pcrel_lo(1b) # &.got.plt + srli t1, t1, log2(16/PTRSIZE) # .got.plt offset + l[w|d] t0, PTRSIZE(t0) # link map + jr t3 + nop + nop + nop */ + + /* RVE has no t3 register, so this won't work, and is not supported. */ + if (elf_elfheader (output_bfd)->e_flags & EF_RISCV_RVE) + { + _bfd_error_handler (_("%pB: warning: RVE PLT generation not supported"), + output_bfd); + return false; + } + + asection *gotplt = htab->elf.sgotplt; + bfd_vma gotplt_addr = sec_addr (gotplt); + + asection *splt = htab->elf.splt; + bfd_vma plt_header_addr = sec_addr (splt); + + bfd_vma auipc_addr = plt_header_addr + 4; + /* Add INSN_BYTES to skip the lpad instruction. */ + bfd_vma gotplt_offset_high = RISCV_PCREL_HIGH_PART (gotplt_addr, auipc_addr); + bfd_vma gotplt_offset_low = RISCV_PCREL_LOW_PART (gotplt_addr, auipc_addr); + + uint32_t header[PLT_ZICFILP_UNLABELED_HEADER_INSNS]; + header[0] = RISCV_UTYPE (LPAD, X_ZERO, 0); + header[1] = RISCV_UTYPE (AUIPC, X_T2, gotplt_offset_high); + header[2] = RISCV_RTYPE (SUB, X_T1, X_T1, X_T3); + header[3] = RISCV_ITYPE (LREG, X_T3, X_T2, gotplt_offset_low); + header[4] = RISCV_ITYPE (ADDI, X_T1, X_T1, + (uint32_t) -(PLT_ZICFILP_UNLABELED_HEADER_SIZE + 16)); + header[5] = RISCV_ITYPE (ADDI, X_T0, X_T2, gotplt_offset_low); + header[6] = RISCV_ITYPE (SRLI, X_T1, X_T1, 4 - RISCV_ELF_LOG_WORD_BYTES); + header[7] = RISCV_ITYPE (LREG, X_T0, X_T0, RISCV_ELF_WORD_BYTES); + header[8] = RISCV_ITYPE (JALR, 0, X_T3, 0); + header[9] = RISCV_NOP; + header[10] = RISCV_NOP; + header[11] = RISCV_NOP; + + for (int i = 0; i < PLT_ZICFILP_UNLABELED_HEADER_INSNS; i++) + bfd_putl32 (header[i], splt->contents + 4 * i); + return true; } /* Generate a PLT entry. */ static bool -riscv_make_plt_entry (bfd *output_bfd, bfd_vma got, bfd_vma addr, - uint32_t *entry) +riscv_make_plt_entry (bfd *output_bfd, asection *gotsec, bfd_vma got_offset, + asection *pltsec, bfd_vma plt_offset) { + bfd_vma got = sec_addr (gotsec) + got_offset; + bfd_vma addr = sec_addr (pltsec) + plt_offset; /* RVE has no t3 register, so this won't work, and is not supported. */ if (elf_elfheader (output_bfd)->e_flags & EF_RISCV_RVE) { @@ -371,11 +491,50 @@ riscv_make_plt_entry (bfd *output_bfd, bfd_vma got, bfd_vma addr, jalr t1, t3 nop */ + uint32_t entry[PLT_ENTRY_INSNS]; entry[0] = RISCV_UTYPE (AUIPC, X_T3, RISCV_PCREL_HIGH_PART (got, addr)); entry[1] = RISCV_ITYPE (LREG, X_T3, X_T3, RISCV_PCREL_LOW_PART (got, addr)); entry[2] = RISCV_ITYPE (JALR, X_T1, X_T3, 0); entry[3] = RISCV_NOP; + bfd_byte *loc = pltsec->contents + plt_offset; + for (int i = 0; i < PLT_ENTRY_INSNS; i++) + bfd_putl32 (entry[i], loc + 4 * i); + + return true; +} + +static bool +riscv_make_plt_zicfilp_unlabeled_entry (bfd *output_bfd, asection *got, + bfd_vma got_offset, asection *plt, + bfd_vma plt_offset) +{ + /* lpad 0 + 1: auipc t3, %pcrel_hi(function@.got.plt) + l[w|d] t3, %pcrel_lo(1b)(t3) + jalr t1, t3 */ + + /* RVE has no t3 register, so this won't work, and is not supported. */ + if (elf_elfheader (output_bfd)->e_flags & EF_RISCV_RVE) + { + _bfd_error_handler (_("%pB: warning: RVE PLT generation not supported"), + output_bfd); + return false; + } + + bfd_vma got_entry_addr = sec_addr(got) + got_offset; + bfd_vma plt_entry_addr = sec_addr(plt) + plt_offset; + bfd_vma auipc_addr = plt_entry_addr + 4; + uint32_t entry[PLT_ZICFILP_UNLABELED_ENTRY_INSNS]; + entry[0] = RISCV_UTYPE (LPAD, X_ZERO, 0); + entry[1] = RISCV_UTYPE (AUIPC, X_T3, RISCV_PCREL_HIGH_PART (got_entry_addr, auipc_addr)); + entry[2] = RISCV_ITYPE (LREG, X_T3, X_T3, RISCV_PCREL_LOW_PART (got_entry_addr, auipc_addr)); + entry[3] = RISCV_ITYPE (JALR, X_T1, X_T3, 0); + + bfd_byte *loc = plt->contents + plt_offset; + for (int i = 0; i < PLT_ZICFILP_UNLABELED_ENTRY_INSNS; i++) + bfd_putl32 (entry[i], loc + 4 * i); + return true; } @@ -489,6 +648,38 @@ riscv_elf_link_hash_table_free (bfd *obfd) _bfd_elf_link_hash_table_free (obfd); } +/* Set up the PLT generation stubs in the hash table. */ + +static void +setup_plt_values (struct bfd *output_bfd, + struct riscv_elf_link_hash_table *htab, + unsigned plt_type) +{ + switch (plt_type) + { + case PLT_NORMAL: + htab->plt_header_size = PLT_HEADER_SIZE; + htab->plt_entry_size = PLT_ENTRY_SIZE; + htab->make_plt_header = riscv_make_plt_header; + htab->make_plt_entry = riscv_make_plt_entry; + break; + + case PLT_ZICFILP_UNLABELED: + htab->plt_header_size = PLT_ZICFILP_UNLABELED_HEADER_SIZE; + htab->plt_entry_size = PLT_ZICFILP_UNLABELED_ENTRY_SIZE; + htab->make_plt_header = riscv_make_plt_zicfilp_unlabeled_header; + htab->make_plt_entry = riscv_make_plt_zicfilp_unlabeled_entry; + break; + + default: + _bfd_error_handler (_("%pB: error: unsupported PLT type: %u"), + output_bfd, + plt_type); + bfd_set_error (bfd_error_bad_value); + break; + } +} + /* Create a RISC-V ELF linker hash table. */ static struct bfd_link_hash_table * @@ -511,6 +702,8 @@ riscv_elf_link_hash_table_create (bfd *abfd) ret->max_alignment = (bfd_vma) -1; ret->max_alignment_for_gp = (bfd_vma) -1; + setup_plt_values (abfd, ret, PLT_NORMAL); + /* Create hash table for local ifunc. */ ret->loc_hash_table = htab_try_create (1024, riscv_elf_local_htab_hash, @@ -1248,23 +1441,22 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) /* Make sure this symbol is output as a dynamic symbol. Undefined weak syms won't yet be marked as dynamic. */ if (h->dynindx == -1 - && !h->forced_local) - { - if (! bfd_elf_link_record_dynamic_symbol (info, h)) - return false; - } + && !h->forced_local + && h->root.type == bfd_link_hash_undefweak + && !bfd_elf_link_record_dynamic_symbol (info, h)) + return false; if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info), h)) { asection *s = htab->elf.splt; if (s->size == 0) - s->size = PLT_HEADER_SIZE; + s->size = htab->plt_header_size; h->plt.offset = s->size; /* Make room for this entry. */ - s->size += PLT_ENTRY_SIZE; + s->size += htab->plt_entry_size; /* We also need to make an entry in the .got.plt section. */ htab->elf.sgotplt->size += GOT_ENTRY_SIZE; @@ -1304,21 +1496,20 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) if (h->got.refcount > 0) { asection *s; - bool dyn; + bool dyn = htab->elf.dynamic_sections_created; int tls_type = riscv_elf_hash_entry (h)->tls_type; /* Make sure this symbol is output as a dynamic symbol. Undefined weak syms won't yet be marked as dynamic. */ - if (h->dynindx == -1 - && !h->forced_local) - { - if (! bfd_elf_link_record_dynamic_symbol (info, h)) - return false; - } + if (dyn + && h->dynindx == -1 + && !h->forced_local + && h->root.type == bfd_link_hash_undefweak + && !bfd_elf_link_record_dynamic_symbol (info, h)) + return false; s = htab->elf.sgot; h->got.offset = s->size; - dyn = htab->elf.dynamic_sections_created; if (tls_type & (GOT_TLS_GD | GOT_TLS_IE | GOT_TLSDESC)) { int indx = 0; @@ -1352,7 +1543,10 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) else { s->size += GOT_ENTRY_SIZE; - if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, bfd_link_pic (info), h) + if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT + || h->root.type != bfd_link_hash_undefweak) + && (bfd_link_pic (info) + || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)) && ! UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)) htab->elf.srelgot->size += sizeof (ElfNN_External_Rela); } @@ -1398,11 +1592,9 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) /* Make sure undefined weak symbols are output as a dynamic symbol in PIEs. */ else if (h->dynindx == -1 - && !h->forced_local) - { - if (! bfd_elf_link_record_dynamic_symbol (info, h)) - return false; - } + && !h->forced_local + && !bfd_elf_link_record_dynamic_symbol (info, h)) + return false; } } else @@ -1421,11 +1613,10 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) /* Make sure this symbol is output as a dynamic symbol. Undefined weak syms won't yet be marked as dynamic. */ if (h->dynindx == -1 - && !h->forced_local) - { - if (! bfd_elf_link_record_dynamic_symbol (info, h)) - return false; - } + && !h->forced_local + && h->root.type == bfd_link_hash_undefweak + && !bfd_elf_link_record_dynamic_symbol (info, h)) + return false; /* If that succeeded, we know we'll be keeping all the relocs. */ @@ -1441,6 +1632,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) /* Finally, allocate space. */ for (p = h->dyn_relocs; p != NULL; p = p->next) { + if (discarded_section (p->sec)) + continue; asection *sreloc = elf_section_data (p->sec)->sreloc; sreloc->size += p->count * sizeof (ElfNN_External_Rela); } @@ -1456,6 +1649,7 @@ allocate_ifunc_dynrelocs (struct elf_link_hash_entry *h, void *inf) { struct bfd_link_info *info; + struct riscv_elf_link_hash_table *htab; if (h->root.type == bfd_link_hash_indirect) return true; @@ -1464,6 +1658,7 @@ allocate_ifunc_dynrelocs (struct elf_link_hash_entry *h, h = (struct elf_link_hash_entry *) h->root.u.i.link; info = (struct bfd_link_info *) inf; + htab = riscv_elf_hash_table (info); /* Since STT_GNU_IFUNC symbol must go through PLT, we handle it here if it is defined and referenced in a non-shared object. */ @@ -1471,8 +1666,8 @@ allocate_ifunc_dynrelocs (struct elf_link_hash_entry *h, && h->def_regular) return _bfd_elf_allocate_ifunc_dyn_relocs (info, h, &h->dyn_relocs, - PLT_ENTRY_SIZE, - PLT_HEADER_SIZE, + htab->plt_entry_size, + htab->plt_header_size, GOT_ENTRY_SIZE, true); return true; @@ -2264,6 +2459,7 @@ riscv_elf_relocate_section (bfd *output_bfd, const char *msg = NULL; bool resolved_to_zero; bool via_plt = false; + bool relative_got = false; if (howto == NULL) continue; @@ -2315,7 +2511,8 @@ riscv_elf_relocate_section (bfd *output_bfd, if (sec != NULL && discarded_section (sec)) RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, - rel, 1, relend, howto, 0, contents); + rel, 1, relend, R_RISCV_NONE, + howto, 0, contents); if (bfd_link_relocatable (info)) continue; @@ -2472,14 +2669,14 @@ riscv_elf_relocate_section (bfd *output_bfd, if (htab->elf.splt != NULL) { - plt_idx = (h->plt.offset - PLT_HEADER_SIZE) - / PLT_ENTRY_SIZE; + plt_idx = (h->plt.offset - htab->plt_header_size) + / htab->plt_entry_size; off = GOTPLT_HEADER_SIZE + (plt_idx * GOT_ENTRY_SIZE); base_got = htab->elf.sgotplt; } else { - plt_idx = h->plt.offset / PLT_ENTRY_SIZE; + plt_idx = h->plt.offset / htab->plt_entry_size; off = plt_idx * GOT_ENTRY_SIZE; base_got = htab->elf.igotplt; } @@ -2677,6 +2874,15 @@ riscv_elf_relocate_section (bfd *output_bfd, off &= ~1; else { + /* If a symbol is not dynamic and is not undefined weak, + bind it locally and generate a RELATIVE relocation + under PIC mode. */ + if (h->dynindx == -1 + && !h->forced_local + && h->root.type != bfd_link_hash_undefweak + && bfd_link_pic (info)) + relative_got = true; + bfd_put_NN (output_bfd, relocation, htab->elf.sgot->contents + off); h->got.offset |= 1; @@ -2700,22 +2906,7 @@ riscv_elf_relocate_section (bfd *output_bfd, else { if (bfd_link_pic (info)) - { - asection *s; - Elf_Internal_Rela outrel; - - /* We need to generate a R_RISCV_RELATIVE reloc - for the dynamic linker. */ - s = htab->elf.srelgot; - BFD_ASSERT (s != NULL); - - outrel.r_offset = sec_addr (htab->elf.sgot) + off; - outrel.r_info = - ELFNN_R_INFO (0, R_RISCV_RELATIVE); - outrel.r_addend = relocation; - relocation = 0; - riscv_elf_append_rela (output_bfd, s, &outrel); - } + relative_got = true; bfd_put_NN (output_bfd, relocation, htab->elf.sgot->contents + off); @@ -2723,6 +2914,21 @@ riscv_elf_relocate_section (bfd *output_bfd, } } + /* We need to generate a R_RISCV_RELATIVE relocation later in the + riscv_elf_finish_dynamic_symbol if h->dynindx != -1; Otherwise, + generate a R_RISCV_RELATIVE relocation here now. */ + if (relative_got) + { + asection *s = htab->elf.srelgot; + BFD_ASSERT (s != NULL); + + Elf_Internal_Rela outrel; + outrel.r_offset = sec_addr (htab->elf.sgot) + off; + outrel.r_info = ELFNN_R_INFO (0, R_RISCV_RELATIVE); + outrel.r_addend = relocation; + riscv_elf_append_rela (output_bfd, s, &outrel); + } + if (rel->r_addend != 0) { msg = _("The addend isn't allowed for R_RISCV_GOT_HI20"); @@ -3247,8 +3453,7 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd, { /* We've decided to create a PLT entry for this symbol. */ bfd_byte *loc; - bfd_vma i, header_address, plt_idx, got_offset, got_address; - uint32_t plt_entry[PLT_ENTRY_INSNS]; + bfd_vma plt_idx, got_offset, got_address; Elf_Internal_Rela rela; asection *plt, *gotplt, *relplt; @@ -3278,36 +3483,29 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd, || relplt == NULL) abort (); - /* Calculate the address of the PLT header. */ - header_address = sec_addr (plt); - /* Calculate the index of the entry and the offset of .got.plt entry. For static executables, we don't reserve anything. */ if (plt == htab->elf.splt) { - plt_idx = (h->plt.offset - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE; + plt_idx = (h->plt.offset - htab->plt_header_size) + / htab->plt_entry_size; got_offset = GOTPLT_HEADER_SIZE + (plt_idx * GOT_ENTRY_SIZE); } else { - plt_idx = h->plt.offset / PLT_ENTRY_SIZE; + plt_idx = h->plt.offset / htab->plt_entry_size; got_offset = plt_idx * GOT_ENTRY_SIZE; } /* Calculate the address of the .got.plt entry. */ got_address = sec_addr (gotplt) + got_offset; - /* Find out where the .plt entry should go. */ - loc = plt->contents + h->plt.offset; /* Fill in the PLT entry itself. */ - if (! riscv_make_plt_entry (output_bfd, got_address, - header_address + h->plt.offset, - plt_entry)) + if (! htab->make_plt_entry (output_bfd, gotplt, got_offset, + plt, h->plt.offset)) return false; - for (i = 0; i < PLT_ENTRY_INSNS; i++) - bfd_putl32 (plt_entry[i], loc + 4*i); /* Fill in the initial value of the .got.plt entry. */ loc = gotplt->contents + (got_address - sec_addr (gotplt)); @@ -3595,19 +3793,12 @@ riscv_elf_finish_dynamic_sections (bfd *output_bfd, /* Fill in the head and tail entries in the procedure linkage table. */ if (splt->size > 0) { - int i; - uint32_t plt_header[PLT_HEADER_INSNS]; - ret = riscv_make_plt_header (output_bfd, - sec_addr (htab->elf.sgotplt), - sec_addr (splt), plt_header); + ret = htab->make_plt_header (output_bfd, htab); if (!ret) return ret; - for (i = 0; i < PLT_HEADER_INSNS; i++) - bfd_putl32 (plt_header[i], splt->contents + 4*i); - elf_section_data (splt->output_section)->this_hdr.sh_entsize - = PLT_ENTRY_SIZE; + = htab->plt_entry_size; } } @@ -3661,7 +3852,18 @@ static bfd_vma riscv_elf_plt_sym_val (bfd_vma i, const asection *plt, const arelent *rel ATTRIBUTE_UNUSED) { - return plt->vma + PLT_HEADER_SIZE + i * PLT_ENTRY_SIZE; + unsigned plt_type = _bfd_riscv_elf_tdata (plt->owner)->plt_type; + switch (plt_type) + { + case PLT_NORMAL: + return plt->vma + (PLT_HEADER_SIZE) + (i * PLT_ENTRY_SIZE); + + case PLT_ZICFILP_UNLABELED: + return plt->vma + PLT_ZICFILP_UNLABELED_HEADER_SIZE + (i * PLT_ZICFILP_UNLABELED_ENTRY_SIZE); + + default: + abort (); + } } /* Used to decide how to sort relocs in an optimal manner for the @@ -5753,44 +5955,91 @@ riscv_elf_merge_symbol_attribute (struct elf_link_hash_entry *h, h->other |= STO_RISCV_VARIANT_CC; } +/* Implement elf_backend_setup_gnu_properties for RISC-V. It serves as a + wrapper function for _bfd_riscv_elf_link_setup_gnu_properties to account + for the effect of GNU properties of the output_bfd. */ + +static bfd * +elfNN_riscv_link_setup_gnu_properties (struct bfd_link_info *info) +{ + uint32_t and_prop = _bfd_riscv_elf_tdata (info->output_bfd)->gnu_and_prop; + + bfd *pbfd = _bfd_riscv_elf_link_setup_gnu_properties (info, &and_prop); + + _bfd_riscv_elf_tdata (info->output_bfd)->gnu_and_prop = and_prop; + + if (and_prop & GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED) + _bfd_riscv_elf_tdata (info->output_bfd)->plt_type = PLT_ZICFILP_UNLABELED; + + setup_plt_values (info->output_bfd, riscv_elf_hash_table (info), + _bfd_riscv_elf_tdata (info->output_bfd)->plt_type); + + return pbfd; +} + +/* Implement elf_backend_merge_gnu_properties for RISC-V. It serves as a + wrapper function for _bfd_riscv_elf_merge_gnu_properties to account + for the effect of GNU properties of the output_bfd. */ + +static bool +elfNN_riscv_merge_gnu_properties (struct bfd_link_info *info, bfd *abfd, + bfd *bbfd ATTRIBUTE_UNUSED, + elf_property *aprop, elf_property *bprop) +{ + uint32_t and_prop = _bfd_riscv_elf_tdata (info->output_bfd)->gnu_and_prop; + + return _bfd_riscv_elf_merge_gnu_properties (info, abfd, aprop, bprop, + and_prop); +} + #define TARGET_LITTLE_SYM riscv_elfNN_vec #define TARGET_LITTLE_NAME "elfNN-littleriscv" #define TARGET_BIG_SYM riscv_elfNN_be_vec #define TARGET_BIG_NAME "elfNN-bigriscv" -#define elf_backend_reloc_type_class riscv_reloc_type_class +#define elf_info_to_howto_rel NULL +#define elf_info_to_howto riscv_info_to_howto_rela #define bfd_elfNN_bfd_reloc_name_lookup riscv_reloc_name_lookup -#define bfd_elfNN_bfd_link_hash_table_create riscv_elf_link_hash_table_create +#define bfd_elfNN_bfd_link_hash_table_create \ + riscv_elf_link_hash_table_create #define bfd_elfNN_bfd_reloc_type_lookup riscv_reloc_type_lookup -#define bfd_elfNN_bfd_merge_private_bfd_data \ +#define bfd_elfNN_bfd_merge_private_bfd_data \ _bfd_riscv_elf_merge_private_bfd_data -#define bfd_elfNN_bfd_is_target_special_symbol riscv_elf_is_target_special_symbol +#define bfd_elfNN_bfd_is_target_special_symbol \ + riscv_elf_is_target_special_symbol +#define bfd_elfNN_bfd_relax_section _bfd_riscv_relax_section +#define bfd_elfNN_mkobject elfNN_riscv_mkobject +#define bfd_elfNN_get_synthetic_symtab \ + elfNN_riscv_get_synthetic_symtab +#define elf_backend_reloc_type_class riscv_reloc_type_class #define elf_backend_copy_indirect_symbol riscv_elf_copy_indirect_symbol -#define elf_backend_create_dynamic_sections riscv_elf_create_dynamic_sections +#define elf_backend_create_dynamic_sections \ + riscv_elf_create_dynamic_sections #define elf_backend_check_relocs riscv_elf_check_relocs #define elf_backend_adjust_dynamic_symbol riscv_elf_adjust_dynamic_symbol #define elf_backend_late_size_sections riscv_elf_late_size_sections #define elf_backend_relocate_section riscv_elf_relocate_section #define elf_backend_finish_dynamic_symbol riscv_elf_finish_dynamic_symbol -#define elf_backend_finish_dynamic_sections riscv_elf_finish_dynamic_sections +#define elf_backend_finish_dynamic_sections \ + riscv_elf_finish_dynamic_sections #define elf_backend_plt_sym_val riscv_elf_plt_sym_val #define elf_backend_grok_prstatus riscv_elf_grok_prstatus #define elf_backend_grok_psinfo riscv_elf_grok_psinfo #define elf_backend_object_p riscv_elf_object_p #define elf_backend_write_core_note riscv_write_core_note #define elf_backend_maybe_function_sym riscv_maybe_function_sym -#define elf_info_to_howto_rel NULL -#define elf_info_to_howto riscv_info_to_howto_rela -#define bfd_elfNN_bfd_relax_section _bfd_riscv_relax_section -#define bfd_elfNN_mkobject elfNN_riscv_mkobject #define elf_backend_additional_program_headers \ riscv_elf_additional_program_headers #define elf_backend_modify_segment_map riscv_elf_modify_segment_map -#define elf_backend_merge_symbol_attribute riscv_elf_merge_symbol_attribute - +#define elf_backend_merge_symbol_attribute \ + riscv_elf_merge_symbol_attribute #define elf_backend_init_index_section _bfd_elf_init_1_index_section +#define elf_backend_setup_gnu_properties \ + elfNN_riscv_link_setup_gnu_properties +#define elf_backend_merge_gnu_properties \ + elfNN_riscv_merge_gnu_properties #define elf_backend_can_gc_sections 1 #define elf_backend_can_refcount 1 @@ -5811,6 +6060,7 @@ riscv_elf_merge_symbol_attribute (struct elf_link_hash_entry *h, #define elf_backend_obj_attrs_section_type SHT_RISCV_ATTRIBUTES #undef elf_backend_obj_attrs_section #define elf_backend_obj_attrs_section RISCV_ATTRIBUTES_SECTION_NAME -#define elf_backend_obj_attrs_handle_unknown riscv_elf_obj_attrs_handle_unknown +#define elf_backend_obj_attrs_handle_unknown \ + riscv_elf_obj_attrs_handle_unknown #include "elfNN-target.h" |