summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Clark <james.clark@arm.com>2022-05-03 14:09:22 +0100
committerStephen M. Webb <stephen.webb@bregmasoft.ca>2022-11-07 20:00:42 -0500
commit267e97fe2d60831542d8ca18f807374170883984 (patch)
tree08d239f7b62d03701f53d47ceb377703823756e0
parentc30489a9ac85f9c3c315c85b05bcd45cd2779044 (diff)
downloadlibunwind-267e97fe2d60831542d8ca18f807374170883984.tar.gz
arm64: Add VG (Vector Granule) pseudo register
This allows remote only unwinding though an SVE function that pushes SVE registers onto the stack[1]. The remote unwinder is responsible for providing the value of the VG register at the time the sample was taken. [1]: https://github.com/ARM-software/abi-aa/blob/main/aadwarf64/aadwarf64.rst Signed-off-by: James Clark <james.clark@arm.com> Change-Id: I8a203b73b17cd4a07afc1fdc55ad11765d73e173
-rw-r--r--include/libunwind-aarch64.h3
-rw-r--r--src/aarch64/Ginit.c9
-rw-r--r--src/aarch64/Gregs.c1
-rw-r--r--src/aarch64/Gstep.c1
-rw-r--r--src/aarch64/init.h7
5 files changed, 18 insertions, 3 deletions
diff --git a/include/libunwind-aarch64.h b/include/libunwind-aarch64.h
index f71835ad..63be0530 100644
--- a/include/libunwind-aarch64.h
+++ b/include/libunwind-aarch64.h
@@ -122,6 +122,9 @@ typedef enum
/* Pseudo-register */
UNW_AARCH64_RA_SIGN_STATE = 34,
+ /* SVE Vector Granule pseudo register */
+ UNW_AARCH64_VG = 46,
+
/* 128-bit FP/Advanced SIMD registers. */
UNW_AARCH64_V0 = 64,
UNW_AARCH64_V1,
diff --git a/src/aarch64/Ginit.c b/src/aarch64/Ginit.c
index 34e5c39a..57f48467 100644
--- a/src/aarch64/Ginit.c
+++ b/src/aarch64/Ginit.c
@@ -46,6 +46,15 @@ unw_addr_space_t unw_local_addr_space = &local_addr_space;
static inline void *
uc_addr (unw_tdep_context_t *uc, int reg)
{
+ if (reg == UNW_AARCH64_VG)
+ {
+ /*
+ * Support for saving the vector length in the context needs to be
+ * added to get_context() for this path to work.
+ */
+ Debug(1, "Accessing VG register from context is not supported\n");
+ return NULL;
+ }
#ifdef __FreeBSD__
if (reg >= UNW_AARCH64_X0 && reg < UNW_AARCH64_X30)
return &uc->uc_mcontext.mc_gpregs.gp_x[reg];
diff --git a/src/aarch64/Gregs.c b/src/aarch64/Gregs.c
index 5ae47254..e6328c0a 100644
--- a/src/aarch64/Gregs.c
+++ b/src/aarch64/Gregs.c
@@ -86,6 +86,7 @@ tdep_access_reg (struct cursor *c, unw_regnum_t reg, unw_word_t *valp,
case UNW_AARCH64_X29:
case UNW_AARCH64_PC:
case UNW_AARCH64_PSTATE:
+ case UNW_AARCH64_VG:
loc = c->dwarf.loc[reg];
break;
case UNW_AARCH64_RA_SIGN_STATE:
diff --git a/src/aarch64/Gstep.c b/src/aarch64/Gstep.c
index d682a53c..560430eb 100644
--- a/src/aarch64/Gstep.c
+++ b/src/aarch64/Gstep.c
@@ -122,6 +122,7 @@ aarch64_handle_signal_frame (unw_cursor_t *cursor)
c->dwarf.loc[UNW_AARCH64_SP] = DWARF_MEM_LOC (c->dwarf, sc_addr + LINUX_SC_SP_OFF);
c->dwarf.loc[UNW_AARCH64_PC] = DWARF_MEM_LOC (c->dwarf, sc_addr + LINUX_SC_PC_OFF);
c->dwarf.loc[UNW_AARCH64_PSTATE] = DWARF_MEM_LOC (c->dwarf, sc_addr + LINUX_SC_PSTATE_OFF);
+ c->dwarf.loc[UNW_AARCH64_VG] = DWARF_NULL_LOC;
/* Set SP/CFA and PC/IP. */
dwarf_get (&c->dwarf, c->dwarf.loc[UNW_AARCH64_SP], &c->dwarf.cfa);
diff --git a/src/aarch64/init.h b/src/aarch64/init.h
index 5dab60bb..e7613296 100644
--- a/src/aarch64/init.h
+++ b/src/aarch64/init.h
@@ -30,6 +30,9 @@ common_init (struct cursor *c, unsigned use_prev_instr)
{
int ret, i;
+ for (i = UNW_AARCH64_PSTATE + 1; i < UNW_AARCH64_V0; ++i)
+ c->dwarf.loc[i] = DWARF_NULL_LOC;
+
c->dwarf.loc[UNW_AARCH64_X0] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X0);
c->dwarf.loc[UNW_AARCH64_X1] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X1);
c->dwarf.loc[UNW_AARCH64_X2] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_X2);
@@ -65,6 +68,7 @@ common_init (struct cursor *c, unsigned use_prev_instr)
c->dwarf.loc[UNW_AARCH64_PC] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_PC);
c->dwarf.loc[UNW_AARCH64_PSTATE] = DWARF_REG_LOC (&c->dwarf,
UNW_AARCH64_PSTATE);
+ c->dwarf.loc[UNW_AARCH64_VG] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_VG);
c->dwarf.loc[UNW_AARCH64_V0] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V0);
c->dwarf.loc[UNW_AARCH64_V1] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V1);
c->dwarf.loc[UNW_AARCH64_V2] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V2);
@@ -98,9 +102,6 @@ common_init (struct cursor *c, unsigned use_prev_instr)
c->dwarf.loc[UNW_AARCH64_V30] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V30);
c->dwarf.loc[UNW_AARCH64_V31] = DWARF_REG_LOC (&c->dwarf, UNW_AARCH64_V31);
- for (i = UNW_AARCH64_PSTATE + 1; i < UNW_AARCH64_V0; ++i)
- c->dwarf.loc[i] = DWARF_NULL_LOC;
-
ret = dwarf_get (&c->dwarf, c->dwarf.loc[UNW_AARCH64_PC], &c->dwarf.ip);
if (ret < 0)
return ret;