X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;ds=sidebyside;f=bfd%2Felfnn-riscv.c;h=8f9f0d8a86a3a793b627b0de653b83a5df3338db;hb=ddc01737d34f16074b2c9a92c5a808be5c91340f;hp=36cbf1ed15f5fd100f46396744926516265ec8cc;hpb=f786c359c1e3227fe8ecfcb2819bb3b80ed351ed;p=binutils-gdb.git diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c index 36cbf1ed15f..8f9f0d8a86a 100644 --- a/bfd/elfnn-riscv.c +++ b/bfd/elfnn-riscv.c @@ -1,5 +1,5 @@ /* RISC-V-specific support for NN-bit ELF. - Copyright (C) 2011-2021 Free Software Foundation, Inc. + Copyright (C) 2011-2022 Free Software Foundation, Inc. Contributed by Andrew Waterman (andrew@sifive.com). Based on TILE-Gx and MIPS targets. @@ -134,6 +134,9 @@ struct riscv_elf_link_hash_table /* The data segment phase, don't relax the section when it is exp_seg_relro_adjust. */ int *data_segment_phase; + + /* Relocations for variant CC symbols may be present. */ + int variant_cc; }; /* Instruction access functions. */ @@ -1172,6 +1175,11 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) h->root.u.def.section = s; h->root.u.def.value = h->plt.offset; } + + /* If the symbol has STO_RISCV_VARIANT_CC flag, then raise the + variant_cc flag of riscv_elf_link_hash_table. */ + if (h->other & STO_RISCV_VARIANT_CC) + htab->variant_cc = 1; } else { @@ -1555,7 +1563,18 @@ riscv_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) return false; } - return _bfd_elf_add_dynamic_tags (output_bfd, info, true); + /* Add dynamic entries. */ + if (elf_hash_table (info)->dynamic_sections_created) + { + if (!_bfd_elf_add_dynamic_tags (output_bfd, info, true)) + return false; + + if (htab->variant_cc + && !_bfd_elf_add_dynamic_entry (info, DT_RISCV_VARIANT_CC, 0)) + return false; + } + + return true; } #define TP_OFFSET 0 @@ -3352,52 +3371,27 @@ riscv_std_ext_p (const char *name) return (strlen (name) == 1) && (name[0] != 'x') && (name[0] != 's'); } -/* Check if the versions are compatible. */ +/* Update the output subset's version to match the input when the input + subset's version is newer. */ -static bool -riscv_version_mismatch (bfd *ibfd, - struct riscv_subset_t *in, - struct riscv_subset_t *out) +static void +riscv_update_subset_version (struct riscv_subset_t *in, + struct riscv_subset_t *out) { if (in == NULL || out == NULL) - return true; - - /* Since there are no version conflicts for now, we just report - warning when the versions are mis-matched. */ - if (in->major_version != out->major_version - || in->minor_version != out->minor_version) + return; + + /* Update the output ISA versions to the newest ones, but otherwise don't + provide any errors or warnings about mis-matched ISA versions as it's + generally too tricky to check for these at link time. */ + if ((in->major_version > out->major_version) + || (in->major_version == out->major_version + && in->minor_version > out->minor_version) + || (out->major_version == RISCV_UNKNOWN_VERSION)) { - if ((in->major_version == RISCV_UNKNOWN_VERSION - && in->minor_version == RISCV_UNKNOWN_VERSION) - || (out->major_version == RISCV_UNKNOWN_VERSION - && out->minor_version == RISCV_UNKNOWN_VERSION)) - { - /* Do not report the warning when the version of input - or output is RISCV_UNKNOWN_VERSION, since the extension - is added implicitly. */ - } - else - _bfd_error_handler - (_("warning: %pB: mis-matched ISA version %d.%d for '%s' " - "extension, the output version is %d.%d"), - ibfd, - in->major_version, - in->minor_version, - in->name, - out->major_version, - out->minor_version); - - /* Update the output ISA versions to the newest ones. */ - if ((in->major_version > out->major_version) - || (in->major_version == out->major_version - && in->minor_version > out->minor_version)) - { - out->major_version = in->major_version; - out->minor_version = in->minor_version; - } + out->major_version = in->major_version; + out->minor_version = in->minor_version; } - - return true; } /* Return true if subset is 'i' or 'e'. */ @@ -3458,11 +3452,10 @@ riscv_merge_std_ext (bfd *ibfd, ibfd, in->name, out->name); return false; } - else if (!riscv_version_mismatch (ibfd, in, out)) - return false; - else - riscv_add_subset (&merged_subsets, - out->name, out->major_version, out->minor_version); + + riscv_update_subset_version(in, out); + riscv_add_subset (&merged_subsets, + out->name, out->major_version, out->minor_version); in = in->next; out = out->next; @@ -3480,10 +3473,8 @@ riscv_merge_std_ext (bfd *ibfd, if (!find_in && !find_out) continue; - if (find_in - && find_out - && !riscv_version_mismatch (ibfd, ext_in, ext_out)) - return false; + if (find_in && find_out) + riscv_update_subset_version(ext_in, ext_out); ext_merged = find_out ? ext_out : ext_in; riscv_add_subset (&merged_subsets, ext_merged->name, @@ -3505,8 +3496,7 @@ riscv_merge_std_ext (bfd *ibfd, on success and FALSE when a conflict is found. */ static bool -riscv_merge_multi_letter_ext (bfd *ibfd, - riscv_subset_t **pin, +riscv_merge_multi_letter_ext (riscv_subset_t **pin, riscv_subset_t **pout) { riscv_subset_t *in = *pin; @@ -3536,8 +3526,7 @@ riscv_merge_multi_letter_ext (bfd *ibfd, else { /* Both present, check version and increment both. */ - if (!riscv_version_mismatch (ibfd, in, out)) - return false; + riscv_update_subset_version (in, out); riscv_add_subset (&merged_subsets, out->name, out->major_version, out->minor_version); @@ -3610,7 +3599,7 @@ riscv_merge_arch_attr_info (bfd *ibfd, char *in_arch, char *out_arch) return NULL; /* Merge all non-single letter extensions with single call. */ - if (!riscv_merge_multi_letter_ext (ibfd, &in, &out)) + if (!riscv_merge_multi_letter_ext (&in, &out)) return NULL; if (xlen_in != xlen_out) @@ -5227,6 +5216,28 @@ riscv_elf_modify_segment_map (bfd *abfd, return true; } +/* Merge non-visibility st_other attributes. */ + +static void +riscv_elf_merge_symbol_attribute (struct elf_link_hash_entry *h, + unsigned int st_other, + bool definition ATTRIBUTE_UNUSED, + bool dynamic ATTRIBUTE_UNUSED) +{ + unsigned int isym_sto = st_other & ~ELF_ST_VISIBILITY (-1); + unsigned int h_sto = h->other & ~ELF_ST_VISIBILITY (-1); + + if (isym_sto == h_sto) + return; + + if (isym_sto & ~STO_RISCV_VARIANT_CC) + _bfd_error_handler (_("unknown attribute for symbol `%s': 0x%02x"), + h->root.root.string, isym_sto); + + if (isym_sto & STO_RISCV_VARIANT_CC) + h->other |= STO_RISCV_VARIANT_CC; +} + #define TARGET_LITTLE_SYM riscv_elfNN_vec #define TARGET_LITTLE_NAME "elfNN-littleriscv" #define TARGET_BIG_SYM riscv_elfNN_be_vec @@ -5263,6 +5274,7 @@ riscv_elf_modify_segment_map (bfd *abfd, #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_init_index_section _bfd_elf_init_1_index_section