Ptrace problem on amd64? (Was: Re: Warcraft III can't find cdrom)
Mike Hearn
mike at navi.cx
Wed Mar 2 06:52:38 CST 2005
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?
I'm not sure, probably lkml would be best but I'm not subscribed to
that. I'll CC wine-devel and maybe somebody there can help.
I'd recommend pinging Linus and asking about whether the ptrace
regressions still affect x86-64.
thanks -mike
> 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
More information about the wine-devel
mailing list