[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