mirror of
https://github.com/libunwind/libunwind.git
synced 2026-01-12 00:04:03 +08:00
arm64: Add test for SVE unwinding from signal handler
The test is skipped if the compiler doesn't support SVE, otherwise it uses some SVE intrinsics across a few functions and then sends a signal to take a backtrace from the sum() function. Without the previous SVE changes, the unwinding fails at sum() and the stack looks like: -> signal_handler() -> kill() -> sum() With the changes the full stack to main can be unwound and the test passes: -> signal_handler() -> kill() -> sum() -> square() -> main() Currently this test will pass on a Graviton 3 instance on AWS and with gcc-10. Co-authored-by: Kent Cheung <Kent.Cheung@arm.com> Signed-off-by: James Clark <james.clark@arm.com> Change-Id: Ibe38e6b0fa26276c545f044ffdd26fbdb2789c38
This commit is contained in:
committed by
Stephen M. Webb
parent
7001a99f30
commit
b8cf600dfc
121
tests/Garm64-test-sve-signal.c
Normal file
121
tests/Garm64-test-sve-signal.c
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Verify that unwinding from a signal handler works when variable width
|
||||
* SVE registers are pushed onto the stack
|
||||
*/
|
||||
|
||||
#if defined(__ARM_FEATURE_SVE) && defined(__ARM_FEATURE_SVE_VECTOR_OPERATORS)
|
||||
|
||||
#include <arm_sve.h>
|
||||
#include <libunwind.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int64_t z[100];
|
||||
|
||||
void signal_handler(int signum)
|
||||
{
|
||||
unw_cursor_t cursor;
|
||||
unw_context_t context;
|
||||
|
||||
const char* expected[] = {
|
||||
"signal_frame",
|
||||
"kill",
|
||||
"sum",
|
||||
"square",
|
||||
"main",
|
||||
};
|
||||
|
||||
unw_getcontext(&context);
|
||||
unw_init_local(&cursor, &context);
|
||||
|
||||
for (unsigned int depth = 0; depth < sizeof(expected) / sizeof(expected[0]); ++depth)
|
||||
{
|
||||
unw_word_t offset, pc;
|
||||
int unw_rc = unw_step(&cursor);
|
||||
if (unw_rc <= 0) {
|
||||
printf("Frame: %d unw_step error: %d\n", depth, unw_rc);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
unw_rc = unw_get_reg(&cursor, UNW_REG_IP, &pc);
|
||||
if (pc == 0 || unw_rc != 0) {
|
||||
printf("Frame: %d unw_get_reg error: %d\n", depth, unw_rc);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
char sym[256];
|
||||
unw_rc = unw_is_signal_frame(&cursor);
|
||||
if (unw_rc > 0)
|
||||
{
|
||||
strcpy(sym, "signal_frame");
|
||||
}
|
||||
else if (unw_rc < 0)
|
||||
{
|
||||
printf("Frame: %d unw_is_signal_frame error: %d\n", depth, unw_rc);
|
||||
exit(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
unw_rc = unw_get_proc_name(&cursor, sym, sizeof(sym), &offset);
|
||||
if (unw_rc)
|
||||
{
|
||||
printf("Frame: %d unw_get_proc_name error: %d\n", depth, unw_rc);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
if (strcmp(sym, expected[depth]) != 0)
|
||||
{
|
||||
printf("Frame: %d expected %s but found %s\n", depth, expected[depth], sym);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
exit(0); /* PASS */
|
||||
}
|
||||
|
||||
int64_t sum(svint64_t z0)
|
||||
{
|
||||
int64_t ret = svaddv_s64(svptrue_b64(), z0);
|
||||
kill (getpid (), SIGUSR1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int64_t square(svint64_t z0)
|
||||
{
|
||||
int64_t res = 0;
|
||||
for (int i = 0; i < 100; ++i)
|
||||
{
|
||||
z0 = svmul_s64_z(svptrue_b64(), z0, z0);
|
||||
res += sum(z0);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
signal(SIGUSR1, signal_handler);
|
||||
for (unsigned int i = 0; i < sizeof(z) / sizeof(z[0]); ++i)
|
||||
z[i] = rand();
|
||||
|
||||
svint64_t z0 = svld1(svptrue_b64(), &z[0]);
|
||||
square(z0);
|
||||
|
||||
/*
|
||||
* Shouldn't get here, exit is called from signal handler
|
||||
*/
|
||||
printf("Signal handler wasn't called\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#else /* !__ARM_FEATURE_SVE */
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return 77; /* SKIP */
|
||||
}
|
||||
#endif
|
||||
5
tests/Larm64-test-sve-signal.c
Normal file
5
tests/Larm64-test-sve-signal.c
Normal file
@@ -0,0 +1,5 @@
|
||||
#define UNW_LOCAL_ONLY
|
||||
#include <libunwind.h>
|
||||
#if !defined(UNW_REMOTE_ONLY)
|
||||
#include "Garm64-test-sve-signal.c"
|
||||
#endif
|
||||
@@ -46,6 +46,11 @@ if ARCH_X86_64
|
||||
endif #ARCH X86_64
|
||||
endif #!ARCH_PPC64
|
||||
endif #!ARCH_IA64
|
||||
|
||||
if ARCH_AARCH64
|
||||
check_PROGRAMS_arch += Garm64-test-sve-signal Larm64-test-sve-signal
|
||||
endif
|
||||
|
||||
check_PROGRAMS_cdep += Gtest-bt Ltest-bt Gtest-exc Ltest-exc \
|
||||
Gtest-init Ltest-init \
|
||||
Gtest-concurrent Ltest-concurrent \
|
||||
@@ -161,6 +166,10 @@ Gx64_test_dwarf_expressions_SOURCES = Gx64-test-dwarf-expressions.c \
|
||||
Lx64_test_dwarf_expressions_SOURCES = Lx64-test-dwarf-expressions.c \
|
||||
x64-test-dwarf-expressions.S
|
||||
|
||||
Garm64_test_sve_signal_SOURCES = Garm64-test-sve-signal.c
|
||||
Larm64_test_sve_signal_SOURCES = Larm64-test-sve-signal.c
|
||||
Garm64_test_sve_signal_CFLAGS = -fno-inline -march=native
|
||||
Larm64_test_sve_signal_CFLAGS = -fno-inline -march=native
|
||||
|
||||
Gtest_init_SOURCES = Gtest-init.cxx
|
||||
Ltest_init_SOURCES = Ltest-init.cxx
|
||||
@@ -261,3 +270,6 @@ ppc64_test_altivec_LDADD = $(LIBUNWIND)
|
||||
|
||||
Gx64_test_dwarf_expressions_LDADD = $(LIBUNWIND) $(LIBUNWIND_local)
|
||||
Lx64_test_dwarf_expressions_LDADD = $(LIBUNWIND_local)
|
||||
|
||||
Garm64_test_sve_signal_LDADD = $(LIBUNWIND) $(LIBUNWIND_local)
|
||||
Larm64_test_sve_signal_LDADD = $(LIBUNWIND_local)
|
||||
|
||||
Reference in New Issue
Block a user