diff --git a/bfd/ChangeLog b/bfd/ChangeLog index d9b66b55d3..6ac3c0fb67 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,25 @@ +2020-06-22 Nelson Chu + + * elfxx-riscv.c (struct priv_spec_t priv_specs[]): Move them from + opcodes/riscv-opc.c to bfd/elfxx-riscv.c, since we need it in linker. + (riscv_get_priv_spec_class): Likewise. + (riscv_get_priv_spec_name): Likewise. + (riscv_get_priv_spec_class_from_numbers): New function, convert + the version numbers into string, then call riscv_get_priv_spec_class + to get the priv spec class. + * elfxx-riscv.h (riscv_get_priv_spec_class): Move forward declaration + from include/opcode/riscv.h to bfd/elfxx-riscv.h. + (riscv_get_priv_spec_name): Likewise. + (riscv_get_priv_spec_class_from_numbers): New forward declaration. + (opcode/riscv.h): Include it in the header rather than elfxx-riscv.c. + * elfnn-riscv.c (riscv_merge_attributes): Get the priv spec classes + of input and output objects form their priv spec attributes by + riscv_get_priv_spec_class_from_numbers. Report warning rather than + errors when linking objects with differnet priv spec versions. We do + know v1.9.1 may have conflicts to other versions, so report the + warning, too. After that, update the output priv spec version to the + newest one so far. + 2020-06-22 Nelson Chu * elfnn-riscv.c (riscv_merge_attributes): Once we meet one of the diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c index 280445945d..00553f7746 100644 --- a/bfd/elfnn-riscv.c +++ b/bfd/elfnn-riscv.c @@ -3052,25 +3052,31 @@ riscv_merge_attributes (bfd *ibfd, struct bfd_link_info *info) unsigned int Tag_a = Tag_RISCV_priv_spec; unsigned int Tag_b = Tag_RISCV_priv_spec_minor; unsigned int Tag_c = Tag_RISCV_priv_spec_revision; + enum riscv_priv_spec_class in_priv_spec; + enum riscv_priv_spec_class out_priv_spec; + + /* Get the priv spec class from elf attribute numbers. */ + riscv_get_priv_spec_class_from_numbers (in_attr[Tag_a].i, + in_attr[Tag_b].i, + in_attr[Tag_c].i, + &in_priv_spec); + riscv_get_priv_spec_class_from_numbers (out_attr[Tag_a].i, + out_attr[Tag_b].i, + out_attr[Tag_c].i, + &out_priv_spec); /* Allow to link the object without the priv specs. */ - if (out_attr[Tag_a].i == 0 - && out_attr[Tag_b].i == 0 - && out_attr[Tag_c].i == 0) + if (out_priv_spec == PRIV_SPEC_CLASS_NONE) { out_attr[Tag_a].i = in_attr[Tag_a].i; out_attr[Tag_b].i = in_attr[Tag_b].i; out_attr[Tag_c].i = in_attr[Tag_c].i; } - else if ((in_attr[Tag_a].i != 0 - || in_attr[Tag_b].i != 0 - || in_attr[Tag_c].i != 0) - && (out_attr[Tag_a].i != in_attr[Tag_a].i - || out_attr[Tag_b].i != in_attr[Tag_b].i - || out_attr[Tag_c].i != in_attr[Tag_c].i)) + else if (in_priv_spec != PRIV_SPEC_CLASS_NONE + && in_priv_spec != out_priv_spec) { _bfd_error_handler - (_("error: %pB use privilege spec version %u.%u.%u but " + (_("warning: %pB use privilege spec version %u.%u.%u but " "the output use version %u.%u.%u."), ibfd, in_attr[Tag_a].i, @@ -3079,7 +3085,26 @@ riscv_merge_attributes (bfd *ibfd, struct bfd_link_info *info) out_attr[Tag_a].i, out_attr[Tag_b].i, out_attr[Tag_c].i); - result = FALSE; + + /* The priv spec v1.9.1 can be linked with other spec + versions since the conflicts. We plan to drop the + v1.9.1 in a year or two, so this confict should be + removed in the future. */ + if (in_priv_spec == PRIV_SPEC_CLASS_1P9P1 + || out_priv_spec == PRIV_SPEC_CLASS_1P9P1) + { + _bfd_error_handler + (_("warning: privilege spec version 1.9.1 can not be " + "linked with other spec versions.")); + } + + /* Update the output priv attributes to the newest. */ + if (in_priv_spec > out_priv_spec) + { + out_attr[Tag_a].i = in_attr[Tag_a].i; + out_attr[Tag_b].i = in_attr[Tag_b].i; + out_attr[Tag_c].i = in_attr[Tag_c].i; + } } priv_attrs_merged = TRUE; } diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c index 5dd36ab965..fa46b06f8d 100644 --- a/bfd/elfxx-riscv.c +++ b/bfd/elfxx-riscv.c @@ -25,7 +25,6 @@ #include "libbfd.h" #include "elf-bfd.h" #include "elf/riscv.h" -#include "opcode/riscv.h" #include "libiberty.h" #include "elfxx-riscv.h" #include "safe-ctype.h" @@ -1750,3 +1749,98 @@ riscv_arch_str (unsigned xlen, const riscv_subset_list_t *subset) return attr_str; } + +/* Record the priv spec version string and the corresponding class. */ + +struct priv_spec_t +{ + const char *name; + enum riscv_priv_spec_class class; +}; + +/* List for all supported privilege versions. */ + +static const struct priv_spec_t priv_specs[] = +{ + {"1.9.1", PRIV_SPEC_CLASS_1P9P1}, + {"1.10", PRIV_SPEC_CLASS_1P10}, + {"1.11", PRIV_SPEC_CLASS_1P11}, + +/* Terminate the list. */ + {NULL, 0} +}; + +/* Get the corresponding CSR version class by giving a privilege + version string. */ + +int +riscv_get_priv_spec_class (const char *s, + enum riscv_priv_spec_class *class) +{ + const struct priv_spec_t *version; + + if (s == NULL) + return 0; + + for (version = &priv_specs[0]; version->name != NULL; ++version) + if (strcmp (version->name, s) == 0) + { + *class = version->class; + return 1; + } + + /* Can not find the supported privilege version. */ + return 0; +} + +/* Get the corresponding CSR version class by giving privilege + version numbers. It is usually used to convert the priv + attribute numbers into the corresponding class. */ + +int +riscv_get_priv_spec_class_from_numbers (unsigned int major, + unsigned int minor, + unsigned int revision, + enum riscv_priv_spec_class *class) +{ + size_t buf_size; + char *buf; + int result = 1; + + if (major == 0 && minor == 0 && revision == 0) + { + *class = PRIV_SPEC_CLASS_NONE; + return result; + } + + buf_size = riscv_estimate_digit (major) + + 1 /* '.' */ + + riscv_estimate_digit (minor) + + 1; /* string terminator */ + if (revision != 0) + { + buf_size += 1 /* '.' */ + + riscv_estimate_digit (revision); + buf = xmalloc (buf_size); + snprintf (buf, buf_size, "%d.%d.%d", major, minor, revision); + } + else + { + buf = xmalloc (buf_size); + snprintf (buf, buf_size, "%d.%d", major, minor); + } + + result = riscv_get_priv_spec_class (buf, class); + free (buf); + return result; +} + +/* Get the corresponding privilege version string by giving a CSR + version class. */ + +const char * +riscv_get_priv_spec_name (enum riscv_priv_spec_class class) +{ + /* The first enum is PRIV_SPEC_CLASS_NONE. */ + return priv_specs[class - 1].name; +} diff --git a/bfd/elfxx-riscv.h b/bfd/elfxx-riscv.h index 7b8f09b82c..c91b169e99 100644 --- a/bfd/elfxx-riscv.h +++ b/bfd/elfxx-riscv.h @@ -22,6 +22,7 @@ #include "elf/common.h" #include "elf/internal.h" +#include "opcode/riscv.h" extern reloc_howto_type * riscv_reloc_name_lookup (bfd *, const char *); @@ -109,3 +110,15 @@ typedef enum riscv_isa_ext_class riscv_isa_ext_class_t riscv_get_prefix_class (const char *); + +extern int +riscv_get_priv_spec_class (const char *, enum riscv_priv_spec_class *); + +extern int +riscv_get_priv_spec_class_from_numbers (unsigned int, + unsigned int, + unsigned int, + enum riscv_priv_spec_class *); + +extern const char * +riscv_get_priv_spec_name (enum riscv_priv_spec_class); diff --git a/gas/ChangeLog b/gas/ChangeLog index 56c2f63526..25d47147d6 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,9 @@ +2020-06-22 Nelson Chu + + * config/tc-riscv.c (buf_size, buf): Remove the unused variables. + (riscv_set_default_priv_spec): Get the priv spec version from the + priv spec attributes by riscv_get_priv_spec_class_from_numbers. + 2020-06-20 Alan Modra * configure.tgt: Set bfd_gas for all SH targets. diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c index cc77dbf6c0..b6c8c4eb23 100644 --- a/gas/config/tc-riscv.c +++ b/gas/config/tc-riscv.c @@ -126,8 +126,6 @@ riscv_set_default_priv_spec (const char *s) enum riscv_priv_spec_class class; unsigned major, minor, revision; obj_attribute *attr; - size_t buf_size; - char *buf; /* Find the corresponding priv spec class. */ if (riscv_get_priv_spec_class (s, &class)) @@ -149,40 +147,24 @@ riscv_set_default_priv_spec (const char *s) minor = (unsigned) attr[Tag_RISCV_priv_spec_minor].i; revision = (unsigned) attr[Tag_RISCV_priv_spec_revision].i; - /* The priv attributes setting 0.0.0 is meaningless. We should have set - the default_priv_spec by md_parse_option and riscv_after_parse_args, - so just skip the following setting. */ - if (major == 0 && minor == 0 && revision == 0) - return 1; + if (riscv_get_priv_spec_class_from_numbers (major, + minor, + revision, + &class)) + { + /* The priv attributes setting 0.0.0 is meaningless. We should have set + the default_priv_spec by md_parse_option and riscv_after_parse_args, + so just skip the following setting. */ + if (class == PRIV_SPEC_CLASS_NONE) + return 1; - buf_size = riscv_estimate_digit (major) - + 1 /* '.' */ - + riscv_estimate_digit (minor) - + 1; /* string terminator */ - if (revision != 0) - { - buf_size += 1 /* '.' */ - + riscv_estimate_digit (revision); - buf = xmalloc (buf_size); - snprintf (buf, buf_size, "%d.%d.%d", major, minor, revision); - } - else - { - buf = xmalloc (buf_size); - snprintf (buf, buf_size, "%d.%d", major, minor); - } - - if (riscv_get_priv_spec_class (buf, &class)) - { default_priv_spec = class; - free (buf); return 1; } /* Still can not find the priv spec class. */ as_bad (_("Unknown default privilege spec `%d.%d.%d' set by " "privilege attributes"), major, minor, revision); - free (buf); return 0; } diff --git a/include/ChangeLog b/include/ChangeLog index 7201be9f4d..65e8af867f 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,9 @@ +2020-06-22 Nelson Chu + + * opcode/riscv.h (riscv_get_priv_spec_class): Move the function + forward declarations to bfd/elfxx-riscv.h. + (riscv_get_priv_spec_name): Likewise. + 2020-06-15 Max Filippov * elf/xtensa.h (xtensa_abi_choice): New declaration. diff --git a/include/opcode/riscv.h b/include/opcode/riscv.h index f3bf173bde..ba993e7d34 100644 --- a/include/opcode/riscv.h +++ b/include/opcode/riscv.h @@ -490,9 +490,5 @@ extern const struct riscv_ext_version riscv_ext_version_table[]; extern int riscv_get_isa_spec_class (const char *, enum riscv_isa_spec_class *); -extern int -riscv_get_priv_spec_class (const char *, enum riscv_priv_spec_class *); -extern const char * -riscv_get_priv_spec_name (enum riscv_priv_spec_class); #endif /* _RISCV_H_ */ diff --git a/ld/ChangeLog b/ld/ChangeLog index 5d460cfefa..b67cd518a6 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,12 @@ +2020-06-22 Nelson Chu + + * testsuite/ld-riscv-elf/attr-merge-priv-spec-failed-01.d: Updated. + * testsuite/ld-riscv-elf/attr-merge-priv-spec-failed-02.d: Updated. + * testsuite/ld-riscv-elf/attr-merge-priv-spec-failed-03.d: Updated. + * testsuite/ld-riscv-elf/attr-merge-priv-spec-failed-04.d: Updated. + * testsuite/ld-riscv-elf/attr-merge-priv-spec-failed-05.d: Updated. + * testsuite/ld-riscv-elf/attr-merge-priv-spec-failed-06.d: Updated. + 2020-06-21 Alan Modra * ldfile.c: Replace uses of ENABLE_PLUGINS with BFD_SUPPORTS_PLUGINS. diff --git a/ld/testsuite/ld-riscv-elf/attr-merge-priv-spec-failed-01.d b/ld/testsuite/ld-riscv-elf/attr-merge-priv-spec-failed-01.d index c52ebac301..0d5d6dc4a0 100644 --- a/ld/testsuite/ld-riscv-elf/attr-merge-priv-spec-failed-01.d +++ b/ld/testsuite/ld-riscv-elf/attr-merge-priv-spec-failed-01.d @@ -2,4 +2,12 @@ #source: attr-merge-priv-spec-c.s #as: #ld: -r -#error: .*use privilege spec version 1.11.0 but the output use version 1.9.1. +#warning: .*warning: .*use privilege spec version 1.11.0 but the output use version 1.9.1. +#warning: .*warning: .*privilege spec version 1.9.1 can not be linked with other spec versions. +#readelf: -A + +Attribute Section: riscv +File Attributes + Tag_RISCV_arch: [a-zA-Z0-9_\"].* + Tag_RISCV_priv_spec: 1 + Tag_RISCV_priv_spec_minor: 11 diff --git a/ld/testsuite/ld-riscv-elf/attr-merge-priv-spec-failed-02.d b/ld/testsuite/ld-riscv-elf/attr-merge-priv-spec-failed-02.d index fc001459c6..f0f75b2ba5 100644 --- a/ld/testsuite/ld-riscv-elf/attr-merge-priv-spec-failed-02.d +++ b/ld/testsuite/ld-riscv-elf/attr-merge-priv-spec-failed-02.d @@ -2,4 +2,12 @@ #source: attr-merge-priv-spec-a.s #as: #ld: -r -#error: .*use privilege spec version 1.9.1 but the output use version 1.11.0. +#warning: .*warning: .*use privilege spec version 1.9.1 but the output use version 1.11.0. +#warning: .*warning: .*privilege spec version 1.9.1 can not be linked with other spec versions. +#readelf: -A + +Attribute Section: riscv +File Attributes + Tag_RISCV_arch: [a-zA-Z0-9_\"].* + Tag_RISCV_priv_spec: 1 + Tag_RISCV_priv_spec_minor: 11 diff --git a/ld/testsuite/ld-riscv-elf/attr-merge-priv-spec-failed-03.d b/ld/testsuite/ld-riscv-elf/attr-merge-priv-spec-failed-03.d index 1d40e905e3..af5155271e 100644 --- a/ld/testsuite/ld-riscv-elf/attr-merge-priv-spec-failed-03.d +++ b/ld/testsuite/ld-riscv-elf/attr-merge-priv-spec-failed-03.d @@ -3,4 +3,12 @@ #source: attr-merge-priv-spec-c.s #as: #ld: -r -#error: .*use privilege spec version 1.11.0 but the output use version 1.9.1. +#warning: .*warning: .*use privilege spec version 1.11.0 but the output use version 1.9.1. +#warning: .*warning: .*privilege spec version 1.9.1 can not be linked with other spec versions. +#readelf: -A + +Attribute Section: riscv +File Attributes + Tag_RISCV_arch: [a-zA-Z0-9_\"].* + Tag_RISCV_priv_spec: 1 + Tag_RISCV_priv_spec_minor: 11 diff --git a/ld/testsuite/ld-riscv-elf/attr-merge-priv-spec-failed-04.d b/ld/testsuite/ld-riscv-elf/attr-merge-priv-spec-failed-04.d index 0efee3ce24..2328807086 100644 --- a/ld/testsuite/ld-riscv-elf/attr-merge-priv-spec-failed-04.d +++ b/ld/testsuite/ld-riscv-elf/attr-merge-priv-spec-failed-04.d @@ -3,4 +3,12 @@ #source: attr-merge-priv-spec-c.s #as: #ld: -r -#error: .*use privilege spec version 1.11.0 but the output use version 1.9.1. +#warning: .*warning: .*use privilege spec version 1.11.0 but the output use version 1.9.1. +#warning: .*warning: .*privilege spec version 1.9.1 can not be linked with other spec versions. +#readelf: -A + +Attribute Section: riscv +File Attributes + Tag_RISCV_arch: [a-zA-Z0-9_\"].* + Tag_RISCV_priv_spec: 1 + Tag_RISCV_priv_spec_minor: 11 diff --git a/ld/testsuite/ld-riscv-elf/attr-merge-priv-spec-failed-05.d b/ld/testsuite/ld-riscv-elf/attr-merge-priv-spec-failed-05.d index 5b9b8d08ed..cabaab68f5 100644 --- a/ld/testsuite/ld-riscv-elf/attr-merge-priv-spec-failed-05.d +++ b/ld/testsuite/ld-riscv-elf/attr-merge-priv-spec-failed-05.d @@ -3,4 +3,12 @@ #source: attr-merge-priv-spec-a.s #as: #ld: -r -#error: .*use privilege spec version 1.9.1 but the output use version 1.11.0. +#warning: .*warning: .*use privilege spec version 1.9.1 but the output use version 1.11.0. +#warning: .*warning: .*privilege spec version 1.9.1 can not be linked with other spec versions. +#readelf: -A + +Attribute Section: riscv +File Attributes + Tag_RISCV_arch: [a-zA-Z0-9_\"].* + Tag_RISCV_priv_spec: 1 + Tag_RISCV_priv_spec_minor: 11 diff --git a/ld/testsuite/ld-riscv-elf/attr-merge-priv-spec-failed-06.d b/ld/testsuite/ld-riscv-elf/attr-merge-priv-spec-failed-06.d index dab7eb6b34..e774748888 100644 --- a/ld/testsuite/ld-riscv-elf/attr-merge-priv-spec-failed-06.d +++ b/ld/testsuite/ld-riscv-elf/attr-merge-priv-spec-failed-06.d @@ -3,4 +3,12 @@ #source: attr-merge-priv-spec-a.s #as: #ld: -r -#error: .*use privilege spec version 1.9.1 but the output use version 1.11.0. +#warning: .*warning: .*use privilege spec version 1.9.1 but the output use version 1.11.0. +#warning: .*warning: .*privilege spec version 1.9.1 can not be linked with other spec versions. +#readelf: -A + +Attribute Section: riscv +File Attributes + Tag_RISCV_arch: [a-zA-Z0-9_\"].* + Tag_RISCV_priv_spec: 1 + Tag_RISCV_priv_spec_minor: 11 diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index 542b2c1086..ba0febec55 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,8 @@ +2020-06-22 Nelson Chu + + * riscv-opc.c: Move the structures and functions to bfd/elfxx-riscv.c. + * riscv-dis.c: Include elfxx-riscv.h. + 2020-06-18 H.J. Lu * i386-dis.c (prefix_table): Revert the last vmgexit change. diff --git a/opcodes/riscv-dis.c b/opcodes/riscv-dis.c index f26a46e0b3..0855de39e8 100644 --- a/opcodes/riscv-dis.c +++ b/opcodes/riscv-dis.c @@ -27,6 +27,7 @@ #include "opintl.h" #include "elf-bfd.h" #include "elf/riscv.h" +#include "elfxx-riscv.h" #include "bfd_stdint.h" #include diff --git a/opcodes/riscv-opc.c b/opcodes/riscv-opc.c index 25b35baaf3..03e3bd7c05 100644 --- a/opcodes/riscv-opc.c +++ b/opcodes/riscv-opc.c @@ -977,53 +977,3 @@ riscv_get_isa_spec_class (const char *s, /* Can not find the supported ISA spec. */ return 0; } - -struct priv_spec_t -{ - const char *name; - enum riscv_priv_spec_class class; -}; - -/* List for all supported privilege versions. */ -static const struct priv_spec_t priv_specs[] = -{ - {"1.9.1", PRIV_SPEC_CLASS_1P9P1}, - {"1.10", PRIV_SPEC_CLASS_1P10}, - {"1.11", PRIV_SPEC_CLASS_1P11}, - -/* Terminate the list. */ - {NULL, 0} -}; - -/* Get the corresponding CSR version class by giving a privilege - version string. */ - -int -riscv_get_priv_spec_class (const char *s, - enum riscv_priv_spec_class *class) -{ - const struct priv_spec_t *version; - - if (s == NULL) - return 0; - - for (version = &priv_specs[0]; version->name != NULL; ++version) - if (strcmp (version->name, s) == 0) - { - *class = version->class; - return 1; - } - - /* Can not find the supported privilege version. */ - return 0; -} - -/* Get the corresponding privilege version string by giving a CSR - version class. */ - -const char * -riscv_get_priv_spec_name (enum riscv_priv_spec_class class) -{ - /* The first enum is PRIV_SPEC_CLASS_NONE. */ - return priv_specs[class - 1].name; -}