aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Cohen <wcohen@redhat.com>2021-09-29 14:56:15 -0400
committerMark Wielaard <mark@klomp.org>2021-09-30 00:09:38 +0200
commit2e57301be1bbb9c34f8a59122ab500de46eb7acb (patch)
tree268c2ba306dc0b142157294f4be6948f486a9f53
parent28db5f16c44fa7bbd24b221b65aa4d133753355c (diff)
downloadelfutils-2e57301be1bbb9c34f8a59122ab500de46eb7acb.tar.gz
RISC-V: PR27925 Add support for LP64 and LP64F ABIs return values
The RISC-V Linux kernel is compiled without floating point (the LP64 ABI) and elfutils could not obtain return value locations for functions in the kernel. This issue was noticed when Systemtap generated RISC-V kernel modules for scripts that used $return target variables in function return probes. This patch adds the needed support to provide return value information for the LP64 and LP64F ABIs. Signed-off-by: William Cohen <wcohen@redhat.com>
-rw-r--r--backends/ChangeLog13
-rw-r--r--backends/riscv_init.c21
-rw-r--r--backends/riscv_retval.c86
3 files changed, 104 insertions, 16 deletions
diff --git a/backends/ChangeLog b/backends/ChangeLog
index ac0e3187..b48af4e1 100644
--- a/backends/ChangeLog
+++ b/backends/ChangeLog
@@ -1,3 +1,16 @@
+2021-09-29 William Cohen <wcohen@redhat.com>
+
+ * riscv_init.c (riscv_return_value_location_lp64f): New function
+ declaration.
+ (riscv_return_value_location_lp64): Likewise.
+ (riscv_init): Set return_value_location based on elf class and
+ ehdr flags.
+ * riscv_retval.c (riscv_return_value_location_lp64d): Renamed to...
+ (riscv_return_value_location_lp64ifd): ...this. Handle single,
+ double, float _Complex and double _Complex cases.
+ (riscv_return_value_location_lp64d): New function.
+ (riscv_return_value_location_lp64f): Likewise.
+
2021-04-19 Martin Liska <mliska@suse.cz>
* aarch64_symbol.c (aarch64_data_marker_symbol): Use startswith.
diff --git a/backends/riscv_init.c b/backends/riscv_init.c
index 551e7bb6..141e0821 100644
--- a/backends/riscv_init.c
+++ b/backends/riscv_init.c
@@ -41,6 +41,12 @@
extern __typeof (EBLHOOK (return_value_location))
riscv_return_value_location_lp64d attribute_hidden;
+extern __typeof (EBLHOOK (return_value_location))
+ riscv_return_value_location_lp64f attribute_hidden;
+
+extern __typeof (EBLHOOK (return_value_location))
+ riscv_return_value_location_lp64 attribute_hidden;
+
extern __typeof (EBLHOOK (core_note)) riscv64_core_note attribute_hidden;
Ebl *
@@ -63,10 +69,17 @@ riscv_init (Elf *elf,
eh->core_note = riscv64_core_note;
else
HOOK (eh, core_note);
- if (eh->class == ELFCLASS64
- && ((elf->state.elf64.ehdr->e_flags & EF_RISCV_FLOAT_ABI)
- == EF_RISCV_FLOAT_ABI_DOUBLE))
- eh->return_value_location = riscv_return_value_location_lp64d;
+ if (eh->class == ELFCLASS64)
+ {
+ if ((elf->state.elf64.ehdr->e_flags & EF_RISCV_FLOAT_ABI)
+ == EF_RISCV_FLOAT_ABI_DOUBLE)
+ eh->return_value_location = riscv_return_value_location_lp64d;
+ else if ((elf->state.elf64.ehdr->e_flags & EF_RISCV_FLOAT_ABI)
+ == EF_RISCV_FLOAT_ABI_SINGLE)
+ eh->return_value_location = riscv_return_value_location_lp64f;
+ else
+ eh->return_value_location = riscv_return_value_location_lp64;
+ }
return eh;
}
diff --git a/backends/riscv_retval.c b/backends/riscv_retval.c
index 35b6010b..34761486 100644
--- a/backends/riscv_retval.c
+++ b/backends/riscv_retval.c
@@ -125,8 +125,8 @@ pass_by_flattened_arg (const Dwarf_Op **locp __attribute__ ((unused)),
}
int
-riscv_return_value_location_lp64d (Dwarf_Die *functypedie,
- const Dwarf_Op **locp)
+riscv_return_value_location_lp64ifd (int fp, Dwarf_Die *functypedie,
+ const Dwarf_Op **locp)
{
/* Start with the function's type, and get the DW_AT_type attribute,
which is the type of the return value. */
@@ -211,10 +211,29 @@ riscv_return_value_location_lp64d (Dwarf_Die *functypedie,
switch (size)
{
case 4: /* single */
- case 8: /* double */
- return pass_in_fpr_lp64d (locp, size);
-
- case 16: /* quad */
+ switch (fp)
+ {
+ case EF_RISCV_FLOAT_ABI_DOUBLE:
+ case EF_RISCV_FLOAT_ABI_SINGLE:
+ return pass_in_fpr_lp64d (locp, size);
+ case EF_RISCV_FLOAT_ABI_SOFT:
+ return pass_in_gpr_lp64 (locp, size);
+ default:
+ return -2;
+ }
+ case 8: /* double */
+ switch (fp)
+ {
+ case EF_RISCV_FLOAT_ABI_DOUBLE:
+ return pass_in_fpr_lp64d (locp, size);
+ case EF_RISCV_FLOAT_ABI_SINGLE:
+ case EF_RISCV_FLOAT_ABI_SOFT:
+ return pass_in_gpr_lp64 (locp, size);
+ default:
+ return -2;
+ }
+
+ case 16: /* quad */
return pass_in_gpr_lp64 (locp, size);
default:
@@ -227,12 +246,31 @@ riscv_return_value_location_lp64d (Dwarf_Die *functypedie,
switch (size)
{
case 8: /* float _Complex */
- return pass_in_fpr_lp64f (locp, size);
-
- case 16: /* double _Complex */
- return pass_in_fpr_lp64d (locp, size);
-
- case 32: /* long double _Complex */
+ switch (fp)
+ {
+ case EF_RISCV_FLOAT_ABI_DOUBLE:
+ case EF_RISCV_FLOAT_ABI_SINGLE:
+ return pass_in_fpr_lp64f (locp, size);
+ case EF_RISCV_FLOAT_ABI_SOFT:
+ /* Double the size so the vals are two registers. */
+ return pass_in_gpr_lp64 (locp, size * 2);
+ default:
+ return -2;
+ }
+
+ case 16: /* double _Complex */
+ switch (fp)
+ {
+ case EF_RISCV_FLOAT_ABI_DOUBLE:
+ return pass_in_fpr_lp64d (locp, size);
+ case EF_RISCV_FLOAT_ABI_SINGLE:
+ case EF_RISCV_FLOAT_ABI_SOFT:
+ return pass_in_gpr_lp64 (locp, size);
+ default:
+ return -2;
+ }
+
+ case 32: /* long double _Complex */
return pass_by_ref (locp);
default:
@@ -249,3 +287,27 @@ riscv_return_value_location_lp64d (Dwarf_Die *functypedie,
*locp = NULL;
return 0;
}
+
+int
+riscv_return_value_location_lp64d (Dwarf_Die *functypedie,
+ const Dwarf_Op **locp)
+{
+ return riscv_return_value_location_lp64ifd (EF_RISCV_FLOAT_ABI_DOUBLE,
+ functypedie, locp);
+}
+
+int
+riscv_return_value_location_lp64f (Dwarf_Die *functypedie,
+ const Dwarf_Op **locp)
+{
+ return riscv_return_value_location_lp64ifd (EF_RISCV_FLOAT_ABI_SINGLE,
+ functypedie, locp);
+}
+
+int
+riscv_return_value_location_lp64 (Dwarf_Die *functypedie,
+ const Dwarf_Op **locp)
+{
+ return riscv_return_value_location_lp64ifd (EF_RISCV_FLOAT_ABI_SOFT,
+ functypedie, locp);
+}