From 90af06793e9d391c0aa33994f21bba6971d084f7 Mon Sep 17 00:00:00 2001 From: Andrew Burgess Date: Mon, 3 Dec 2018 17:48:49 +0000 Subject: [PATCH] gdb/riscv: Improve logic for when h/w float abi should be used Currently, if the target announces that it has floating point registers in its target description then GDB assumes that the hardware float ABI should be used. However, there's nothing stopping a user compiling a program for the soft-float abi, and then trying to run this on a target with hardware floating point registers. This commit adjusts the logic that decides if GDB should use the hardware float abi. The primary decision now is based on what the ELF currently being executed says in its headers. If the file was compiled for h/w float abi, then GDB uses h/w float abi, otherwise s/w float is used. If the current BFD is not an ELF then we don't currently have a mechanism for figuring out if the file was compiled for float or not. In this case we disable the h/w float abi. This shouldn't be a problem as, right now, the RISC-V linker can only produce ELFs. If there is NO current BFD (can this happen?) then we will enable h/w float abi if the target has floating point hardware, otherwise, s/w float abi is used. This commit also adds some sanity checking that the features requested in the BFD (xlen and flen) match the target description. For testing I ran the testsuite on a target that returns a target description containing both integer and floating point registers, but used a compiler that didn't have floating point support. Before this commit I would see failures on may tests that made inferior calls using floating point arguments, after this commit, all of these issues are resolved. One example from the testsuite is gdb.base/infcall-nested-structs.exp. gdb/ChangeLog: * riscv-tdep.c (riscv_features_from_gdbarch_info): New function. (riscv_find_default_target_description): Use new function to extract feature from gdbarch_info. (riscv_gdbarch_init): Add error checks for xlen and flen between target description and bfd headers. Be smarter about when we think the hardware floating point abi should be used. --- gdb/ChangeLog | 9 +++++++++ gdb/riscv-tdep.c | 61 +++++++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 58 insertions(+), 12 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index d1f583d..da4d61d 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,12 @@ +2018-12-05 Andrew Burgess + + * riscv-tdep.c (riscv_features_from_gdbarch_info): New function. + (riscv_find_default_target_description): Use new function to + extract feature from gdbarch_info. + (riscv_gdbarch_init): Add error checks for xlen and flen between + target description and bfd headers. Be smarter about when we + think the hardware floating point abi should be used. + 2018-12-05 Alan Hayward * nat/aarch64-linux-hw-point.c diff --git a/gdb/riscv-tdep.c b/gdb/riscv-tdep.c index 30c777d..d812b7c 100644 --- a/gdb/riscv-tdep.c +++ b/gdb/riscv-tdep.c @@ -2789,20 +2789,16 @@ static const struct frame_unwind riscv_frame_unwind = /*.prev_arch =*/ NULL, }; -/* Find a suitable default target description. Use the contents of INFO, - specifically the bfd object being executed, to guide the selection of a - suitable default target description. */ +/* Extract a set of required target features out of INFO, specifically the + bfd being executed is examined to see what target features it requires. + IF there is no current bfd, or the bfd doesn't indicate any useful + features then a RISCV_GDBARCH_FEATURES is returned in its default state. */ -static const struct target_desc * -riscv_find_default_target_description (const struct gdbarch_info info) +static struct riscv_gdbarch_features +riscv_features_from_gdbarch_info (const struct gdbarch_info info) { struct riscv_gdbarch_features features; - /* Setup some arbitrary defaults. */ - features.xlen = 8; - features.flen = 0; - features.hw_float_abi = false; - /* Now try to improve on the defaults by looking at the binary we are going to execute. We assume the user knows what they are doing and that the target will match the binary. Remember, this code path is @@ -2847,6 +2843,26 @@ riscv_find_default_target_description (const struct gdbarch_info info) binfo->bits_per_word); } + return features; +} + +/* Find a suitable default target description. Use the contents of INFO, + specifically the bfd object being executed, to guide the selection of a + suitable default target description. */ + +static const struct target_desc * +riscv_find_default_target_description (const struct gdbarch_info info) +{ + /* Extract desired feature set from INFO. */ + struct riscv_gdbarch_features features + = riscv_features_from_gdbarch_info (info); + + /* If the XLEN field is still 0 then we got nothing useful from INFO. In + this case we fall back to a minimal useful target, 8-byte x-registers, + with no floating point. */ + if (features.xlen == 0) + features.xlen = 8; + /* Now build a target description based on the feature set. */ return riscv_create_target_description (features); } @@ -2981,7 +2997,6 @@ riscv_gdbarch_init (struct gdbarch_info info, int bitsize = tdesc_register_bitsize (feature_fpu, "ft0"); features.flen = (bitsize / 8); - features.hw_float_abi = true; if (riscv_debug_gdbarch) fprintf_filtered @@ -2991,7 +3006,6 @@ riscv_gdbarch_init (struct gdbarch_info info, else { features.flen = 0; - features.hw_float_abi = false; if (riscv_debug_gdbarch) fprintf_filtered @@ -3015,6 +3029,29 @@ riscv_gdbarch_init (struct gdbarch_info info, return NULL; } + /* Have a look at what the supplied (if any) bfd object requires of the + target, then check that this matches with what the target is + providing. */ + struct riscv_gdbarch_features info_features + = riscv_features_from_gdbarch_info (info); + if (info_features.xlen != 0 && info_features.xlen != features.xlen) + error (_("bfd requires xlen %d, but target has xlen %d"), + info_features.xlen, features.xlen); + if (info_features.flen != 0 && info_features.flen != features.flen) + error (_("bfd requires flen %d, but target has flen %d"), + info_features.flen, features.flen); + + /* If the xlen from INFO_FEATURES is 0 then this indicates either there + is no bfd object, or nothing useful could be extracted from it, in + this case we enable hardware float abi if the target has floating + point registers. + + If the xlen from INFO_FEATURES is not 0, and the flen in + INFO_FEATURES is also not 0, then this indicates that the supplied + bfd does require hardware floating point abi. */ + if (info_features.xlen == 0 || info_features.flen != 0) + features.hw_float_abi = (features.flen > 0); + /* Find a candidate among the list of pre-declared architectures. */ for (arches = gdbarch_list_lookup_by_info (arches, &info); arches != NULL; -- 2.7.4