[PATCH 3/5] hppa: Fix display of mask for rt_sigreturn syscall
Helge Deller
deller at gmx.de
Sun Jan 29 21:08:51 UTC 2023
Fix FUNC_GET_RT_SIGFRAME_ADDR to return correct address to the
sigframe so that the mask can be shown for the rt_sigreturn syscall.
This patch cleans up and simplifies the address calculation when
running on Linux kernels < 5.18, where the signal trampoline code
was stored in the executable stack.
With kernel 5.18 we added a VDSO with the trampoline code, could drop
the neccessarity of an executable stack and provided the offset to the
ucontext of the rt_sigframe struct for gdb and to simplify the
calculation sigframe address.
With this patch the rt_sigreturn.gen.test passes for 5.16 and 6.1
kernels on hppa.
Signed-off-by: Helge Deller <deller at gmx.de>
---
src/linux/hppa/arch_rt_sigframe.c | 37 +++++++++++++++++++++++++------
src/linux/hppa/rt_sigframe.h | 8 ++++++-
2 files changed, 37 insertions(+), 8 deletions(-)
diff --git a/src/linux/hppa/arch_rt_sigframe.c b/src/linux/hppa/arch_rt_sigframe.c
index 99249a3e5..879a7d3f6 100644
--- a/src/linux/hppa/arch_rt_sigframe.c
+++ b/src/linux/hppa/arch_rt_sigframe.c
@@ -7,15 +7,38 @@
#include "rt_sigframe.h"
-#define SIGFRAME (sizeof(long) * 16)
-#define FUNCTIONCALLFRAME (sizeof(long) * 12)
-#define RT_SIGFRAME_SIZE \
- (((sizeof(struct_rt_sigframe) + FUNCTIONCALLFRAME)) & -SIGFRAME)
+/* see further comments in GDB: gdb/hppa-linux-tdep.c */
+
+#define SIGFRAME 64
FUNC_GET_RT_SIGFRAME_ADDR
{
- unsigned long addr;
+ unsigned long sp, ip;
+
+ if (!get_instruction_pointer(tcp, &ip) ||
+ !get_stack_pointer(tcp, &sp))
+ return 0;
+
+ sp &= -1UL;
+ /* check if ip is part of stack, running in tramp[] of rt_sigframe */
+ if ((sp - ip) < 1024) {
+ /* on executable stack: We execute in tramp[], so align down. */
+ return (ip & -SIGFRAME)
+ /* compensate for size difference old and new frame */
+ + sizeof(struct_rt_sigframe_old)
+ - sizeof(struct_rt_sigframe);
+ } else {
+ /* running in VDSO on kernel >= 5.18 */
+ static kernel_ulong_t context_offset;
+
+ /* read sigframe offset from kernel VDSO header */
+ if (!context_offset)
+ context_offset = ptrace(PTRACE_PEEKTEXT, (pid_t) tcp->pid,
+ (void *)(ip & -SIGFRAME), 0);
+ if (context_offset == (kernel_ulong_t) -1)
+ return 0;
- return get_stack_pointer(tcp, &addr)
- ? (addr & ~1UL) - RT_SIGFRAME_SIZE : 0;
+ /* context_offset is a negative value */
+ return sp + context_offset - offsetof(struct_rt_sigframe, uc.uc_mcontext);
+ }
}
diff --git a/src/linux/hppa/rt_sigframe.h b/src/linux/hppa/rt_sigframe.h
index 17bff7cd6..3b8348b04 100644
--- a/src/linux/hppa/rt_sigframe.h
+++ b/src/linux/hppa/rt_sigframe.h
@@ -14,6 +14,12 @@ typedef struct {
unsigned int tramp[9];
siginfo_t info;
ucontext_t uc;
-} struct_rt_sigframe;
+} struct_rt_sigframe_old; /* when executed on stack */
+
+typedef struct {
+ unsigned int tramp[2]; /* holds original return address */
+ siginfo_t info;
+ ucontext_t uc;
+} struct_rt_sigframe; /* when VDSO is used */
#endif /* !STRACE_RT_SIGFRAME_H */
--
2.38.1
More information about the Strace-devel
mailing list