summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHelge Deller <deller@gmx.de>2023-01-29 22:08:51 +0100
committerDmitry V. Levin <ldv@strace.io>2023-01-29 21:08:51 +0000
commit8e8434397487f533a6e263b1e3f24d1c4289eb09 (patch)
tree5d9c6678506caf729d658450466cc443c946bdd0
parentad8aff80d9562207d07ed8bfb5af4ac32393d035 (diff)
downloadstrace-8e8434397487f533a6e263b1e3f24d1c4289eb09.tar.gz
hppa: Fix display of mask for rt_sigreturn syscall
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@gmx.de>
-rw-r--r--src/linux/hppa/arch_rt_sigframe.c37
-rw-r--r--src/linux/hppa/rt_sigframe.h8
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 */