Re: gdb has outdated knowledge of signal trampolines

From: Konstantin Belousov <kostikbel_at_gmail.com>
Date: Tue, 26 Nov 2013 10:09:53 +0200
On Mon, Nov 25, 2013 at 07:35:27PM +0200, Konstantin Belousov wrote:
> Could you update your gdb patch to use the KERN_PROC_SIGTRAMP from
> the patch below ? If this works out, I will add initialization of
> sv_szsigcode for ABIs which do not use shared page.

Below is the complete patch.  With it applied, I get
(gdb) bt
#0  sighandler (signo=1, info=0x7fffffffd2b0, context=Unhandled dwarf expression opcode 0xf3
) at siginfo.c:34
#1  <signal handler called>
#2  0x000000080088849a in sigsuspend () from /lib/libc.so.7
#3  0x000000000040093a in main (argc=Unhandled dwarf expression opcode 0xf3
) at siginfo.c:54

diff --git a/contrib/gdb/gdb/amd64fbsd-nat.c b/contrib/gdb/gdb/amd64fbsd-nat.c
index f083734..dacd4a3 100644
--- a/contrib/gdb/gdb/amd64fbsd-nat.c
+++ b/contrib/gdb/gdb/amd64fbsd-nat.c
_at__at_ -29,6 +29,7 _at__at_
 #include <sys/types.h>
 #include <sys/ptrace.h>
 #include <sys/sysctl.h>
+#include <sys/user.h>
 #include <machine/reg.h>
 
 #ifdef HAVE_SYS_PROCFS_H
_at__at_ -212,24 +213,23 _at__at_ Please report this to <bug-gdb_at_gnu.org>.",
 
   SC_RBP_OFFSET = offset;
 
-  /* FreeBSD provides a kern.ps_strings sysctl that we can use to
+  /* FreeBSD provides a kern.proc.sigtramp sysctl that we can use to
      locate the sigtramp.  That way we can still recognize a sigtramp
-     if its location is changed in a new kernel.  Of course this is
-     still based on the assumption that the sigtramp is placed
-     directly under the location where the program arguments and
-     environment can be found.  */
+     if its location is changed in a new kernel. */
   {
-    int mib[2];
-    long ps_strings;
+    int mib[4];
+    struct kinfo_sigtramp kst;
     size_t len;
 
     mib[0] = CTL_KERN;
-    mib[1] = KERN_PS_STRINGS;
-    len = sizeof (ps_strings);
-    if (sysctl (mib, 2, &ps_strings, &len, NULL, 0) == 0)
+    mib[1] = KERN_PROC;
+    mib[2] = KERN_PROC_SIGTRAMP;
+    mib[3] = getpid();
+    len = sizeof (kst);
+    if (sysctl (mib, sizeof(mib) / sizeof(mib[0]), &kst, &len, NULL, 0) == 0)
       {
-	amd64fbsd_sigtramp_start_addr = ps_strings - 32;
-	amd64fbsd_sigtramp_end_addr = ps_strings;
+	amd64fbsd_sigtramp_start_addr = kst.ksigtramp_start;
+	amd64fbsd_sigtramp_end_addr = kst.ksigtramp_end;
       }
   }
 }
diff --git a/sys/amd64/include/pcb.h b/sys/amd64/include/pcb.h
index c106edc..80aff86 100644
--- a/sys/amd64/include/pcb.h
+++ b/sys/amd64/include/pcb.h
_at__at_ -43,6 +43,7 _at__at_
 #include <machine/fpu.h>
 #include <machine/segments.h>
 
+#ifdef __amd64__
 struct pcb {
 	register_t	pcb_r15;
 	register_t	pcb_r14;
_at__at_ -105,6 +106,7 _at__at_ struct pcb {
 
 	uint64_t	pcb_pad[3];
 };
+#endif
 
 #ifdef _KERNEL
 struct trapframe;
diff --git a/sys/amd64/include/segments.h b/sys/amd64/include/segments.h
index d9f4280..6bcadc7 100644
--- a/sys/amd64/include/segments.h
+++ b/sys/amd64/include/segments.h
_at__at_ -82,8 +82,8 _at__at_ struct	soft_segment_descriptor {
  * region descriptors, used to load gdt/idt tables before segments yet exist.
  */
 struct region_descriptor {
-	unsigned long rd_limit:16;		/* segment extent */
-	unsigned long rd_base:64 __packed;	/* base address  */
+	uint64_t rd_limit:16;		/* segment extent */
+	uint64_t rd_base:64 __packed;	/* base address  */
 } __packed;
 
 #ifdef _KERNEL
diff --git a/sys/compat/freebsd32/freebsd32.h b/sys/compat/freebsd32/freebsd32.h
index 8376e95..94f886e 100644
--- a/sys/compat/freebsd32/freebsd32.h
+++ b/sys/compat/freebsd32/freebsd32.h
_at__at_ -362,6 +362,12 _at__at_ struct kinfo_proc32 {
 	int	ki_tdflags;
 };
 
+struct kinfo_sigtramp32 {
+	uint32_t ksigtramp_start;
+	uint32_t ksigtramp_end;
+	uint32_t ksigtramp_spare[4];
+};
+
 struct kld32_file_stat_1 {
 	int	version;	/* set to sizeof(struct kld_file_stat_1) */
 	char	name[MAXPATHLEN];
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
index 9968e76..2e6bc32 100644
--- a/sys/kern/kern_proc.c
+++ b/sys/kern/kern_proc.c
_at__at_ -2632,6 +2632,60 _at__at_ errout:
 	return (error);
 }
 
+static int
+sysctl_kern_proc_sigtramp(SYSCTL_HANDLER_ARGS)
+{
+	int *name = (int *)arg1;
+	u_int namelen = arg2;
+	struct proc *p;
+	struct kinfo_sigtramp kst;
+	const struct sysentvec *sv;
+	int error;
+#ifdef COMPAT_FREEBSD32
+	struct kinfo_sigtramp32 kst32;
+#endif
+
+	if (namelen != 1)
+		return (EINVAL);
+
+	error = pget((pid_t)name[0], PGET_CANDEBUG, &p);
+	if (error != 0)
+		return (error);
+	sv = p->p_sysent;
+#ifdef COMPAT_FREEBSD32
+	if ((req->flags & SCTL_MASK32) != 0) {
+		bzero(&kst32, sizeof(kst32));
+		if (SV_PROC_FLAG(p, SV_ILP32)) {
+			if (sv->sv_sigcode_base != 0) {
+				kst32.ksigtramp_start = sv->sv_sigcode_base;
+				kst32.ksigtramp_end = sv->sv_sigcode_base +
+				    *sv->sv_szsigcode;
+			} else {
+				kst32.ksigtramp_start = sv->sv_psstrings -
+				    *sv->sv_szsigcode;
+				kst32.ksigtramp_end = sv->sv_psstrings;
+			}
+		}
+		PROC_UNLOCK(p);
+		error = SYSCTL_OUT(req, &kst32, sizeof(kst32));
+		return (error);
+	}
+#endif
+	bzero(&kst, sizeof(kst));
+	if (sv->sv_sigcode_base != 0) {
+		kst.ksigtramp_start = (char *)sv->sv_sigcode_base;
+		kst.ksigtramp_end = (char *)sv->sv_sigcode_base +
+		    *sv->sv_szsigcode;
+	} else {
+		kst.ksigtramp_start = (char *)sv->sv_psstrings -
+		    *sv->sv_szsigcode;
+		kst.ksigtramp_end = (char *)sv->sv_psstrings;
+	}
+	PROC_UNLOCK(p);
+	error = SYSCTL_OUT(req, &kst, sizeof(kst));
+	return (error);
+}
+
 SYSCTL_NODE(_kern, KERN_PROC, proc, CTLFLAG_RD,  0, "Process table");
 
 SYSCTL_PROC(_kern_proc, KERN_PROC_ALL, all, CTLFLAG_RD|CTLTYPE_STRUCT|
_at__at_ -2740,3 +2794,7 _at__at_ static SYSCTL_NODE(_kern_proc, KERN_PROC_UMASK, umask, CTLFLAG_RD |
 static SYSCTL_NODE(_kern_proc, KERN_PROC_OSREL, osrel, CTLFLAG_RW |
 	CTLFLAG_ANYBODY | CTLFLAG_MPSAFE, sysctl_kern_proc_osrel,
 	"Process binary osreldate");
+
+static SYSCTL_NODE(_kern_proc, KERN_PROC_SIGTRAMP, sigtramp, CTLFLAG_RD |
+	CTLFLAG_MPSAFE, sysctl_kern_proc_sigtramp,
+	"Process signal trampoline location");
diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h
index 64292ba..8e70a12 100644
--- a/sys/sys/sysctl.h
+++ b/sys/sys/sysctl.h
_at__at_ -530,6 +530,7 _at__at_ SYSCTL_ALLOWED_TYPES(UINT64, uint64_t *a; unsigned long long *b; );
 #define	KERN_PROC_PS_STRINGS	38	/* get ps_strings location */
 #define	KERN_PROC_UMASK		39	/* process umask */
 #define	KERN_PROC_OSREL		40	/* osreldate for process binary */
+#define	KERN_PROC_SIGTRAMP	41	/* signal trampoline location */
 
 /*
  * KERN_IPC identifiers
diff --git a/sys/sys/user.h b/sys/sys/user.h
index d2e2b6e..e926fe8 100644
--- a/sys/sys/user.h
+++ b/sys/sys/user.h
_at__at_ -498,6 +498,12 _at__at_ struct kinfo_kstack {
 	int	 _kkst_ispare[16];		/* Space for more stuff. */
 };
 
+struct kinfo_sigtramp {
+	void	*ksigtramp_start;
+	void	*ksigtramp_end;
+	void	*ksigtramp_spare[4];
+};
+
 #ifdef _KERNEL
 /* Flags for kern_proc_out function. */
 #define KERN_PROC_NOTHREADS	0x1

Received on Tue Nov 26 2013 - 07:10:04 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:40:44 UTC