tech-toolchain archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Base GDB tracing 32bit applications on amd64 kernel (with 64bit debugger) part 1)



In article <272cb7c0-c171-8b87-393a-0ccdd042b84b%gmx.com@localhost>,
Kamil Rytarowski  <n54%gmx.com@localhost> wrote:
>-=-=-=-=-=-
>-=-=-=-=-=-
>
>On 22.06.2019 16:38, maya%netbsd.org@localhost wrote:
>> The following kernel works with unmodified -current userland.
>> NetBSD 7.99.75
>> 
>> Reverting to the git mirror Dec 1 2018 with this list of commits also
>> works.
>> 
>> 4cab1e757c7197a01b6dc268c0104fa43ab7f0aa
>> 5542798943417f4d1bdb61d0a49a9f8c1c37445c
>> ef20f297e5f1527c1b54d4b2de8280a6cca21c71
>> 80d084c7ddc1104b2bf191ccaa8a5347e71253ef
>> 
>> We don't need any changes to GDB whatsoever. I didn't even rebuild the
>> binary.
>> 
>> It's a really tricky bisect because every few days changes are made to
>> re-break it.
>> 
>
>My patch adds i386 to recognized osabi/bfd, but there is trash in
>registers. Something gets malformed, might it be related to these
>regressions?

Maxv disabled 64 bit ptrace on a 32 bit tracee. The following patch
puts it back, and an unmodified gdb from head now can trace a 32 bit
binary again.

Index: machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/amd64/amd64/machdep.c,v
retrieving revision 1.332
diff -u -p -u -r1.332 machdep.c
--- machdep.c	12 Jun 2019 14:28:38 -0000	1.332
+++ machdep.c	23 Jun 2019 03:40:54 -0000
@@ -2095,40 +2095,46 @@ cpu_setmcontext(struct lwp *l, const mco
 int
 cpu_mcontext_validate(struct lwp *l, const mcontext_t *mcp)
 {
-	struct proc *p __diagused = l->l_proc;
+	struct proc *p = l->l_proc;
 	struct trapframe *tf = l->l_md.md_regs;
 	const __greg_t *gr;
 	uint16_t sel;
+	const bool pk32 = (p->p_flag & PK_32) != 0;
 
-	KASSERT((p->p_flag & PK_32) == 0);
 	gr = mcp->__gregs;
 
 	if (((gr[_REG_RFLAGS] ^ tf->tf_rflags) & PSL_USERSTATIC) != 0)
 		return EINVAL;
+#define VUD(sel) (pk32 ? VALID_USER_DSEL32(sel) : VALID_USER_DSEL(sel))
+#define VUF(sel) (pk32 ? (VALID_USER_DSEL32(sel) || VALID_USER_FSEL32(sel)) \
+    : VALID_USER_DSEL(sel))
+#define VUG(sel) (pk32 ? (VALID_USER_DSEL32(sel) || VALID_USER_GSEL32(sel)) \
+    : VALID_USER_DSEL(sel))
+#define VUC(sel) (pk32 ? VALID_USER_CSEL32(sel) : VALID_USER_CSEL(sel))
 
 	sel = gr[_REG_ES] & 0xffff;
-	if (sel != 0 && !VALID_USER_DSEL(sel))
+	if (sel != 0 && !VUD(sel))
 		return EINVAL;
 
 	sel = gr[_REG_FS] & 0xffff;
-	if (sel != 0 && !VALID_USER_DSEL(sel))
+	if (sel != 0 && !VUF(sel))
 		return EINVAL;
 
 	sel = gr[_REG_GS] & 0xffff;
-	if (sel != 0 && !VALID_USER_DSEL(sel))
+	if (sel != 0 && !VUG(sel))
 		return EINVAL;
 
 	sel = gr[_REG_DS] & 0xffff;
-	if (!VALID_USER_DSEL(sel))
+	if (!VUD(sel))
 		return EINVAL;
 
 #ifndef XENPV
 	sel = gr[_REG_SS] & 0xffff;
-	if (!VALID_USER_DSEL(sel))
+	if (!VUD(sel))
 		return EINVAL;
 
 	sel = gr[_REG_CS] & 0xffff;
-	if (!VALID_USER_CSEL(sel))
+	if (!VUC(sel))
 		return EINVAL;
 #endif
 
Index: process_machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/amd64/amd64/process_machdep.c,v
retrieving revision 1.39
diff -u -p -u -r1.39 process_machdep.c
--- process_machdep.c	11 Feb 2019 14:59:32 -0000	1.39
+++ process_machdep.c	23 Jun 2019 03:40:54 -0000
@@ -100,42 +100,48 @@ process_frame(struct lwp *l)
 }
 
 int
-process_read_regs(struct lwp *l, struct reg *regs)
+process_read_regs(struct lwp *l, struct reg *regp)
 {
 	struct trapframe *tf = process_frame(l);
-	struct proc *p = l->l_proc;
+	long *regs = regp->regs;
+	const bool pk32 = (l->l_proc->p_flag & PK_32) != 0;
 
-	if (p->p_flag & PK_32) {
-		return EINVAL;
-	}
-
-	regs->regs[_REG_RDI] = tf->tf_rdi;
-	regs->regs[_REG_RSI] = tf->tf_rsi;
-	regs->regs[_REG_RDX] = tf->tf_rdx;
-	regs->regs[_REG_R10] = tf->tf_r10;
-	regs->regs[_REG_R8]  = tf->tf_r8;
-	regs->regs[_REG_R9]  = tf->tf_r9;
+	regs[_REG_RDI] = tf->tf_rdi;
+	regs[_REG_RSI] = tf->tf_rsi;
+	regs[_REG_RDX] = tf->tf_rdx;
+	regs[_REG_R10] = tf->tf_r10;
+	regs[_REG_R8]  = tf->tf_r8;
+	regs[_REG_R9]  = tf->tf_r9;
 	/* argX not touched */
-	regs->regs[_REG_RCX] = tf->tf_rcx;
-	regs->regs[_REG_R11] = tf->tf_r11;
-	regs->regs[_REG_R12] = tf->tf_r12;
-	regs->regs[_REG_R13] = tf->tf_r13;
-	regs->regs[_REG_R14] = tf->tf_r14;
-	regs->regs[_REG_R15] = tf->tf_r15;
-	regs->regs[_REG_RBP] = tf->tf_rbp;
-	regs->regs[_REG_RBX] = tf->tf_rbx;
-	regs->regs[_REG_RAX] = tf->tf_rax;
-	regs->regs[_REG_GS]  = 0;
-	regs->regs[_REG_FS]  = 0;
-	regs->regs[_REG_ES]  = GSEL(GUDATA_SEL, SEL_UPL);
-	regs->regs[_REG_DS]  = GSEL(GUDATA_SEL, SEL_UPL);
-	regs->regs[_REG_TRAPNO] = tf->tf_trapno;
-	regs->regs[_REG_ERR] = tf->tf_err;
-	regs->regs[_REG_RIP] = tf->tf_rip;
-	regs->regs[_REG_CS]  = LSEL(LUCODE_SEL, SEL_UPL);
-	regs->regs[_REG_RFLAGS] = tf->tf_rflags;
-	regs->regs[_REG_RSP] = tf->tf_rsp;
-	regs->regs[_REG_SS]  = LSEL(LUDATA_SEL, SEL_UPL);
+	regs[_REG_RCX] = tf->tf_rcx;
+	regs[_REG_R11] = tf->tf_r11;
+	regs[_REG_R12] = tf->tf_r12;
+	regs[_REG_R13] = tf->tf_r13;
+	regs[_REG_R14] = tf->tf_r14;
+	regs[_REG_R15] = tf->tf_r15;
+	regs[_REG_RBP] = tf->tf_rbp;
+	regs[_REG_RBX] = tf->tf_rbx;
+	regs[_REG_RAX] = tf->tf_rax;
+	if (pk32) {
+		regs[_REG_GS] = tf->tf_gs & 0xffff;
+		regs[_REG_FS] = tf->tf_fs & 0xffff;
+		regs[_REG_ES] = tf->tf_es & 0xffff;
+		regs[_REG_DS] = tf->tf_ds & 0xffff;
+		regs[_REG_CS] = tf->tf_cs & 0xffff;
+		regs[_REG_SS] = tf->tf_ss & 0xffff;
+	} else {
+		regs[_REG_GS] = 0;
+		regs[_REG_FS] = 0;
+		regs[_REG_ES] = GSEL(GUDATA_SEL, SEL_UPL);
+		regs[_REG_DS] = GSEL(GUDATA_SEL, SEL_UPL);
+		regs[_REG_CS] = LSEL(LUCODE_SEL, SEL_UPL);
+		regs[_REG_SS] = LSEL(LUDATA_SEL, SEL_UPL);
+	}
+	regs[_REG_TRAPNO] = tf->tf_trapno;
+	regs[_REG_ERR] = tf->tf_err;
+	regs[_REG_RIP] = tf->tf_rip;
+	regs[_REG_RFLAGS] = tf->tf_rflags;
+	regs[_REG_RSP] = tf->tf_rsp;
 
 	return 0;
 }
@@ -143,11 +149,6 @@ process_read_regs(struct lwp *l, struct 
 int
 process_read_fpregs(struct lwp *l, struct fpreg *regs, size_t *sz)
 {
-	struct proc *p = l->l_proc;
-
-	if (p->p_flag & PK_32) {
-		return EINVAL;
-	}
 
 	process_read_fpregs_xmm(l, &regs->fxstate);
 
@@ -157,11 +158,6 @@ process_read_fpregs(struct lwp *l, struc
 int
 process_read_dbregs(struct lwp *l, struct dbreg *regs, size_t *sz)
 {
-	struct proc *p = l->l_proc;
-
-	if (p->p_flag & PK_32) {
-		return EINVAL;
-	}
 
 	x86_dbregs_read(l, regs);
 
@@ -172,13 +168,9 @@ int
 process_write_regs(struct lwp *l, const struct reg *regp)
 {
 	struct trapframe *tf = process_frame(l);
-	struct proc *p = l->l_proc;
 	int error;
 	const long *regs = regp->regs;
-
-	if (p->p_flag & PK_32) {
-		return EINVAL;
-	}
+	const bool pk32 = (l->l_proc->p_flag & PK_32) != 0;
 
 	/*
 	 * Check for security violations. Note that struct regs is compatible
@@ -204,16 +196,25 @@ process_write_regs(struct lwp *l, const 
 	tf->tf_rbp  = regs[_REG_RBP];
 	tf->tf_rbx  = regs[_REG_RBX];
 	tf->tf_rax  = regs[_REG_RAX];
-	tf->tf_gs   = 0;
-	tf->tf_fs   = 0;
-	tf->tf_es   = GSEL(GUDATA_SEL, SEL_UPL);
-	tf->tf_ds   = GSEL(GUDATA_SEL, SEL_UPL);
+	if (pk32) {
+		tf->tf_gs = regs[_REG_GS] & 0xffff;
+		tf->tf_fs = regs[_REG_FS] & 0xffff;
+		tf->tf_es = regs[_REG_ES] & 0xffff;
+		tf->tf_ds = regs[_REG_DS] & 0xffff;
+		tf->tf_cs = regs[_REG_CS] & 0xffff;
+		tf->tf_ss = regs[_REG_SS] & 0xffff;
+	} else {
+		tf->tf_gs = 0;
+		tf->tf_fs = 0;
+		tf->tf_es = GSEL(GUDATA_SEL, SEL_UPL);
+		tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL);
+		tf->tf_cs = LSEL(LUCODE_SEL, SEL_UPL);
+		tf->tf_ss = LSEL(LUDATA_SEL, SEL_UPL);
+	}
 	/* trapno, err not touched */
 	tf->tf_rip  = regs[_REG_RIP];
-	tf->tf_cs   = LSEL(LUCODE_SEL, SEL_UPL);
 	tf->tf_rflags = regs[_REG_RFLAGS];
 	tf->tf_rsp  = regs[_REG_RSP];
-	tf->tf_ss   = LSEL(LUDATA_SEL, SEL_UPL);
 
 #ifdef XENPV
 	/* see comment in cpu_setmcontext */
@@ -227,11 +228,6 @@ process_write_regs(struct lwp *l, const 
 int
 process_write_fpregs(struct lwp *l, const struct fpreg *regs, size_t sz)
 {
-	struct proc *p = l->l_proc;
-
-	if (p->p_flag & PK_32) {
-		return EINVAL;
-	}
 
 	process_write_fpregs_xmm(l, &regs->fxstate);
 	return 0;
@@ -240,13 +236,8 @@ process_write_fpregs(struct lwp *l, cons
 int
 process_write_dbregs(struct lwp *l, const struct dbreg *regs, size_t sz)
 {
-	struct proc *p = l->l_proc;
 	int error;
 
-	if (p->p_flag & PK_32) {
-		return EINVAL;
-	}
-
 	/*
 	 * Check for security violations.
 	 */
@@ -276,11 +267,6 @@ int
 process_set_pc(struct lwp *l, void *addr)
 {
 	struct trapframe *tf = process_frame(l);
-	struct proc *p = l->l_proc;
-
-	if (p->p_flag & PK_32) {
-		return EINVAL;
-	}
 
 	if ((uint64_t)addr >= VM_MAXUSER_ADDRESS)
 		return EINVAL;



Home | Main Index | Thread Index | Old Index