From ce77d76ae5d673ae18d8e4c143980b4fe00f4171 Mon Sep 17 00:00:00 2001 From: Hau Hsu Date: Tue, 24 Oct 2023 10:05:33 +0800 Subject: [PATCH] SiFive: Add -z force-zicfilp option --- bfd/elfnn-riscv.c | 49 +++++++++++++++++++ bfd/elfxx-riscv.c | 14 ++++-- bfd/elfxx-riscv.h | 15 ++++++ ld/emultempl/riscvelf.em | 11 +++++ ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp | 2 + .../property-force-zicfilp-all-missing.d | 16 ++++++ .../ld-riscv-elf/property-force-zicfilp.d | 17 +++++++ 7 files changed, 121 insertions(+), 3 deletions(-) create mode 100644 ld/testsuite/ld-riscv-elf/property-force-zicfilp-all-missing.d create mode 100644 ld/testsuite/ld-riscv-elf/property-force-zicfilp.d diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c index 9c9006de2db8..7fcea61a84f1 100644 --- a/bfd/elfnn-riscv.c +++ b/bfd/elfnn-riscv.c @@ -184,6 +184,13 @@ struct _bfd_riscv_elf_obj_tdata /* All GNU_PROPERTY_RISCV_FEATURE_2_OR properties. */ uint32_t gnu_or_prop; + + /* True to warn when linking objects with incompatible + GNU_PROPERTY_RISCV_FEATURE_1_ZICFILP. */ + bool zicfilp_warn; + + /* PLT type based on security. */ + riscv_plt_type plt_type; }; #define _bfd_riscv_elf_tdata(abfd) \ @@ -265,9 +272,22 @@ void riscv_elfNN_set_options (struct bfd_link_info *link_info, struct riscv_elf_params *params) { + struct bfd *output_bfd = link_info->output_bfd; riscv_elf_hash_table (link_info)->params = params; + switch (params->plt_type) + { + case PLT_ZICFILP: + _bfd_riscv_elf_tdata (output_bfd)->zicfilp_warn = true; + _bfd_riscv_elf_tdata (output_bfd)->gnu_and_prop + |= GNU_PROPERTY_RISCV_FEATURE_1_ZICFILP; + break; + + default: + break; + } } + static bool riscv_info_to_howto_rela (bfd *abfd, arelent *cache_ptr, @@ -5544,6 +5564,21 @@ elfNN_riscv_link_setup_gnu_properties (struct bfd_link_info *info) return pbfd; } +/* Warn Zicfilp when -z force-zicfilp is enabled but the bfd doesn't have + the property in NOTE. */ +static void +riscv_warn_zicfilp_if_necessary(const elf_property* prop, const bfd *abfd) +{ + if ((prop && !(prop->u.number & GNU_PROPERTY_RISCV_FEATURE_1_ZICFILP)) + || !prop) + { + _bfd_error_handler (_("%pB: warning: Zicfilp turned on by -z force-zicfilp when " + "all inputs do not have ZICFILP in NOTE section."), + abfd); + } +} + + /* 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. */ @@ -5555,6 +5590,20 @@ elfNN_riscv_merge_gnu_properties (struct bfd_link_info *info, { uint32_t and_prop = _bfd_riscv_elf_tdata (info->output_bfd)->gnu_and_prop; + + /* If output has been marked with CFILP using command line argument, give out + warning if necessary. */ + /* Properties are merged per type, hence only check for warnings when merging + GNU_PROPERTY_RISCV_FEATURE_1_ZICFILP. */ + if (((aprop && aprop->pr_type == GNU_PROPERTY_RISCV_FEATURE_1_AND) + || (bprop && bprop->pr_type == GNU_PROPERTY_RISCV_FEATURE_1_AND)) + && (and_prop & GNU_PROPERTY_RISCV_FEATURE_1_ZICFILP) + && (_bfd_riscv_elf_tdata (info->output_bfd)->zicfilp_warn)) + { + riscv_warn_zicfilp_if_necessary(aprop, abfd); + riscv_warn_zicfilp_if_necessary(bprop, bbfd); + } + uint32_t or_prop = _bfd_riscv_elf_tdata (info->output_bfd)->gnu_or_prop; return _bfd_riscv_elf_merge_gnu_properties (info, abfd, aprop, diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c index 516f0152f0e8..e30320fcfac8 100644 --- a/bfd/elfxx-riscv.c +++ b/bfd/elfxx-riscv.c @@ -2777,11 +2777,19 @@ _bfd_riscv_elf_link_setup_gnu_properties (struct bfd_link_info *info, if (ebfd != NULL && (and_prop || or_prop)) { prop = _bfd_elf_get_property (ebfd, - GNU_PROPERTY_RISCV_FEATURE_1_AND, - 4); + GNU_PROPERTY_RISCV_FEATURE_1_AND, + 4); + + if (and_prop & GNU_PROPERTY_RISCV_FEATURE_1_ZICFILP + && !(prop->u.number & GNU_PROPERTY_RISCV_FEATURE_1_ZICFILP)) + { + _bfd_error_handler (_("%pB: warning: Zicfilp turned on by -z force-zicfilp " + "when all inputs do not have ZICFILP in NOTE " + "section."), ebfd); + } + prop->u.number |= and_prop; prop->pr_kind = property_number; - prop = _bfd_elf_get_property (ebfd, GNU_PROPERTY_RISCV_FEATURE_2_OR, 4); diff --git a/bfd/elfxx-riscv.h b/bfd/elfxx-riscv.h index 271b48860ad3..4c4fee240315 100644 --- a/bfd/elfxx-riscv.h +++ b/bfd/elfxx-riscv.h @@ -27,10 +27,25 @@ #define RISCV_UNKNOWN_VERSION -1 +typedef enum +{ + PLT_NORMAL = 0x0, /* Normal plts. */ + PLT_ZICFILP = 0x1 /* Landing pad plts. */ +} riscv_plt_type; + +/* To indicate if LP is enabled with/without warning. */ +typedef enum +{ + ZICFILP_NONE = 0, /* LP is not enabled. */ + ZICFILP_WARN = 1, /* LP is enabled with -z force-zicfilp. */ +} riscv_enable_zicfilp_type; + struct riscv_elf_params { /* Whether to relax code sequences to GP-relative addressing. */ bool relax_gp; + riscv_plt_type plt_type; + riscv_enable_zicfilp_type zicfilp_type; }; extern void riscv_elf32_set_options (struct bfd_link_info *, diff --git a/ld/emultempl/riscvelf.em b/ld/emultempl/riscvelf.em index bb6298d3e8d4..d8984c558cb1 100644 --- a/ld/emultempl/riscvelf.em +++ b/ld/emultempl/riscvelf.em @@ -46,8 +46,19 @@ PARSE_AND_LIST_LONGOPTS=${PARSE_AND_LIST_LONGOPTS}' PARSE_AND_LIST_OPTIONS=${PARSE_AND_LIST_OPTIONS}' fprintf (file, _(" --relax-gp Perform GP relaxation\n")); fprintf (file, _(" --no-relax-gp Don'\''t perform GP relaxation\n")); + fprintf (file, _(" -z force-zicfilp Turn on Zicfilp mechanism and generate PLTs with landing pad. Generate warnings for missing Zicfilp on inputs\n\n")); ' +PARSE_AND_LIST_ARGS_CASE_Z_RISCV=' + else if (strcmp (optarg, "force-zicfilp") == 0) + { + params.plt_type |= PLT_ZICFILP; + params.zicfilp_type = ZICFILP_WARN; + } +' +PARSE_AND_LIST_ARGS_CASE_Z="$PARSE_AND_LIST_ARGS_CASE_Z $PARSE_AND_LIST_ARGS_CASE_Z_RISCV" + + PARSE_AND_LIST_ARGS_CASES=${PARSE_AND_LIST_ARGS_CASES}' case OPTION_RELAX_GP: params.relax_gp = 1; diff --git a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp index d96590ecf107..33c656b800e3 100644 --- a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp +++ b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp @@ -232,6 +232,8 @@ if [istarget "riscv*-*-*"] { run_dump_test "property-zicfilp" run_dump_test "property-zicfiss" run_dump_test "property-combine-and-1" + run_dump_test "property-force-zicfilp" + run_dump_test "property-force-zicfilp-all-missing" # IFUNC testcases. # Check IFUNC by single type relocs. diff --git a/ld/testsuite/ld-riscv-elf/property-force-zicfilp-all-missing.d b/ld/testsuite/ld-riscv-elf/property-force-zicfilp-all-missing.d new file mode 100644 index 000000000000..f7f5b2a6baaa --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/property-force-zicfilp-all-missing.d @@ -0,0 +1,16 @@ +#name: Warn with all missing GNU NOTE Zicfilp input +#source: property1.s +#source: property2.s +#as: -mabi=lp64 +#ld: -shared -z force-zicfilp +#warning: .*: warning: Zicfilp turned on by -z force-zicfilp.*$ +#readelf: -n + +# Should warn about the missing input ZICFILP NOTE but should +# still mark output as ZICFILP + +Displaying notes found in: .note.gnu.property +[ ]+Owner[ ]+Data size[ ]+Description +[ ]+GNU[ ]+0x00000020[ ]+NT_GNU_PROPERTY_TYPE_0 +[ ]+Properties: RISC-V AND feature: ZICFILP +[ ]+RISC-V OR feature: diff --git a/ld/testsuite/ld-riscv-elf/property-force-zicfilp.d b/ld/testsuite/ld-riscv-elf/property-force-zicfilp.d new file mode 100644 index 000000000000..e94a86e64d33 --- /dev/null +++ b/ld/testsuite/ld-riscv-elf/property-force-zicfilp.d @@ -0,0 +1,17 @@ +#name: Warn with one missing GNU NOTE Zicfilp input +#source: property1.s +#source: property2.s +#as: -mabi=lp64 -defsym __property_zicfilp__=1 -defsym __property_zicfiss__=1 +#ld: -shared -z force-zicfilp +#warning: .*: warning: Zicfilp turned on by -z force-zicfilp.*$ +#readelf: -n + +# Should warn about the missing input ZICFILP NOTE but should +# still mark output as ZICFILP + +Displaying notes found in: .note.gnu.property +[ ]+Owner[ ]+Data size[ ]+Description +[ ]+GNU[ ]+0x00000020[ ]+NT_GNU_PROPERTY_TYPE_0 +[ ]+Properties: RISC-V AND feature: ZICFILP +[ ]+RISC-V OR feature: ZICFISS +