[Wine]Ptrace problem on amd64? (Was: Re: Warcraft III can't find cdrom)

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

 



Hi,

On Fri, 2005-02-18 at 23:44 +0000, Mike Hearn wrote:
> On Fri, 2005-02-18 at 23:34 +0100, T.J. Zeeman wrote:
> > Warcraft still complains about the CD-rom being MIA though :( I'll see
> > if I can dig up a few hints from the log this weekend.
> 
> Make sure your kernel hsa the ptrace regression fixes in.

I guess you meant the problems refered to in WWN250
(http://www.winehq.com/?issue=250). I checked and the patch there is
only for i386. I ported those to the x86_64 files (see attachments) and
tried again to no avail.

I also tried the test app as posted by Linus Torvalds here:
http://www.winehq.com/hypermail/wine-devel/2004/11/0551.html
When trying that on amd64 with the ptrace patches it does not even want
to compile (not completely surprising). In the chroot it segfaults.
A strace showed the following:

x5556c000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or
directory)
open("/etc/ld.so.preload", O_RDONLY)    = -1 ENOENT (No such file or
directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=32850, ...}) = 0
old_mmap(NULL, 32850, PROT_READ, MAP_PRIVATE, 3, 0) = 0x5556d000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or
directory)
open("/lib/tls/libc.so.6", O_RDONLY)    = 3
read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\360Y\1"...,
512) = 512
fstat64(3, {st_mode=S_IFREG|0644, st_size=1253924, ...}) = 0
old_mmap(NULL, 1260140, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) =
0x55576000
old_mmap(0x5569f000, 32768, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED,
3, 0x129000) = 0x5569f000
old_mmap(0x556a7000, 10860, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|
MAP_ANONYMOUS, -1, 0) = 0x556a7000
close(3)                                = 0
old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS,
-1, 0) = 0x556aa000
set_thread_area({entry_number:-1 -> 11, base_addr:0x556aa2a0,
limit:1048575, seg_32bit:1, contents:0, read_exec_only:0,
limit_in_pages:1, seg_not_present:0, useable:1}) = 0
munmap(0x5556d000, 32850)               = 0
rt_sigaction(SIGTRAP, {0x8048438, [TRAP], SA_RESTART}, {SIG_DFL}, 8) = 0
mprotect(0x8048000, 4096, PROT_READ|PROT_WRITE) = 0
--- SIGSEGV (Segmentation fault) @ 0 (0) ---
+++ killed by SIGSEGV +++


I haven't been this deep into low level code in a long time (and that
was 8086 asm simulated on a sparc), but I thought this would work and
not segfault. Anybody around here that can comment on that? Or should I
take this to another forum to further investigate? If so, where would
you suggest I take it?

regards,
Thomas


--- /usr/src/kernel-source-2.6.10/arch/x86_64/kernel/ptrace.c	2004-12-24 22:34:30.000000000 +0100
+++ ptrace.c	2005-03-01 20:32:29.713639136 +0100
@@ -79,6 +79,28 @@
 	return 0;
 }
 
+static void set_singlestep(struct task_struct *child)
+{
+	long eflags;
+
+	set_tsk_thread_flag(child, TIF_SINGLESTEP);
+	eflags = get_stack_long(child, EFL_OFFSET);
+	put_stack_long(child, EFL_OFFSET, eflags | TRAP_FLAG);
+	child->ptrace |= PT_DTRACE;
+}
+
+static void clear_singlestep(struct task_struct *child)
+{
+	if (child->ptrace & PT_DTRACE) {
+		long eflags;
+
+		clear_tsk_thread_flag(child, TIF_SINGLESTEP);
+		eflags = get_stack_long(child, EFL_OFFSET);
+		put_stack_long(child, EFL_OFFSET, eflags & ~TRAP_FLAG);
+		child->ptrace &= ~PT_DTRACE;
+	}
+}
+
 /*
  * Called by kernel/ptrace.c when detaching..
  *
@@ -86,11 +108,12 @@
  */
 void ptrace_disable(struct task_struct *child)
 { 
-	long tmp;
+/*	long tmp;
 
 	clear_tsk_thread_flag(child, TIF_SINGLESTEP);
 	tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
-	put_stack_long(child, EFL_OFFSET, tmp);
+	put_stack_long(child, EFL_OFFSET, tmp); */
+	clear_singlestep(child);
 }
 
 static int putreg(struct task_struct *child,
@@ -338,8 +361,6 @@
 		break;
 	case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
 	case PTRACE_CONT: { /* restart after signal. */
-		long tmp;
-
 		ret = -EIO;
 		if ((unsigned long) data > _NSIG)
 			break;
@@ -347,12 +368,9 @@
 			set_tsk_thread_flag(child,TIF_SYSCALL_TRACE);
 		else
 			clear_tsk_thread_flag(child,TIF_SYSCALL_TRACE);
-		clear_tsk_thread_flag(child, TIF_SINGLESTEP);
 		child->exit_code = data;
 	/* make sure the single step bit is not set. */
-		tmp = get_stack_long(child, EFL_OFFSET);
-		tmp &= ~TRAP_FLAG;
-		put_stack_long(child, EFL_OFFSET,tmp);
+		clear_singlestep(child);
 		wake_up_process(child);
 		ret = 0;
 		break;
@@ -394,34 +412,23 @@
  * exit.
  */
 	case PTRACE_KILL: {
-		long tmp;
-
 		ret = 0;
 		if (child->exit_state == EXIT_ZOMBIE)	/* already dead */
 			break;
 		clear_tsk_thread_flag(child, TIF_SINGLESTEP);
 		child->exit_code = SIGKILL;
 		/* make sure the single step bit is not set. */
-		tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
-		put_stack_long(child, EFL_OFFSET, tmp);
+		clear_singlestep(child);
 		wake_up_process(child);
 		break;
 	}
 
 	case PTRACE_SINGLESTEP: {  /* set the trap flag. */
-		long tmp;
-
 		ret = -EIO;
 		if ((unsigned long) data > _NSIG)
 			break;
 		clear_tsk_thread_flag(child,TIF_SYSCALL_TRACE);
-		if ((child->ptrace & PT_DTRACE) == 0) {
-			/* Spurious delayed TF traps may occur */
-			child->ptrace |= PT_DTRACE;
-		}
-		tmp = get_stack_long(child, EFL_OFFSET) | TRAP_FLAG;
-		put_stack_long(child, EFL_OFFSET, tmp);
-		set_tsk_thread_flag(child, TIF_SINGLESTEP);
+		set_singlestep(child);
 		child->exit_code = data;
 		/* give it a chance to run. */
 		wake_up_process(child);
--- /usr/src/kernel-source-2.6.10/arch/x86_64/kernel/signal.c	2004-12-24 22:35:23.000000000 +0100
+++ signal.c	2005-03-01 20:33:11.425298000 +0100
@@ -205,8 +205,14 @@
 	err |= __put_user(me->thread.trap_no, &sc->trapno);
 	err |= __put_user(me->thread.error_code, &sc->err);
 	err |= __put_user(regs->rip, &sc->rip);
+
+	/*
+	 * Iff TF was set because the program is being single-stepped by a
+	 * debugger, don't save that information on the signal stack.. We
+	 * don't want debugging to change state.
+	 */
 	eflags = regs->eflags;
-	if (current->ptrace & PT_PTRACED) {
+	if (current->ptrace & PT_DTRACE) {
 		eflags &= ~TF_MASK;
 	}
 	err |= __put_user(eflags, &sc->eflags);
@@ -324,12 +330,16 @@
 	regs->rsp = (unsigned long)frame;
 
 	set_fs(USER_DS);
+	/*
+	 * Clear TF when entering the signal handler, but
+	 * notify any tracer that was single-stepping it.
+	 * The tracer may want to single-step inside the
+	 * handler too.
+	 */
 	if (regs->eflags & TF_MASK) {
-		if ((current->ptrace & (PT_PTRACED | PT_DTRACE)) == (PT_PTRACED | PT_DTRACE)) {
+		regs->eflags &= ~TF_MASK;
+		if (current->ptrace & PT_DTRACE) 
 			ptrace_notify(SIGTRAP);
-		} else {
-			regs->eflags &= ~TF_MASK;
-		}
 	}
 
 #ifdef DEBUG_SIG

[Index of Archives]     [Gimp for Windows]     [Red Hat]     [Samba]     [Yosemite Camping]     [Graphics Cards]     [Wine Home]

  Powered by Linux