I was trying to run gdbserver in a UML instance and got "Couldn't
write debug register" after setting a breakpoint and continuing after
attaching from a remote gdb on the host. This is on an AMD x86_64
machine. The error message was resulting from getting EIO error  when
making a PTRACE_POKEUSER call. I debugged the ptrace call handling on
the kernel side and found that the poke_user() and peek_user() calls
in arch/um/sys-x86_64/ptrace.c assume that long is 4 bytes instead of
8. With the patch below, I found that gdbserver works fine.

Thanks,
Barry

*** linux-2.6.32/arch/um/sys-x86_64/ptrace.c    Wed Dec  2 19:51:21 2009
--- ../linux-2.6.32/arch/um/sys-x86_64/ptrace.c Wed Dec  9 10:54:36 2009
*************** int poke_user(struct task_struct *child,
*** 67,77 ****
        if (addr < MAX_REG_OFFSET)
                return putreg(child, addr, data);
        else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
                (addr <= offsetof(struct user, u_debugreg[7]))) {
                addr -= offsetof(struct user, u_debugreg[0]);
!               addr = addr >> 2;
                if ((addr == 4) || (addr == 5))
                        return -EIO;
                child->thread.arch.debugregs[addr] = data;
                return 0;
        }
--- 67,77 ----
        if (addr < MAX_REG_OFFSET)
                return putreg(child, addr, data);
        else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
                (addr <= offsetof(struct user, u_debugreg[7]))) {
                addr -= offsetof(struct user, u_debugreg[0]);
!                 addr = addr >> 3;  // long is 8 bytes on x86_64
                if ((addr == 4) || (addr == 5))
                        return -EIO;
                child->thread.arch.debugregs[addr] = data;
                return 0;
        }
*************** int peek_user(struct task_struct *child,
*** 112,122 ****
        if (addr < MAX_REG_OFFSET)
                tmp = getreg(child, addr);
        else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
                (addr <= offsetof(struct user, u_debugreg[7]))) {
                addr -= offsetof(struct user, u_debugreg[0]);
!               addr = addr >> 2;
                tmp = child->thread.arch.debugregs[addr];
        }
        return put_user(tmp, (unsigned long *) data);
  }

--- 112,122 ----
        if (addr < MAX_REG_OFFSET)
                tmp = getreg(child, addr);
        else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
                (addr <= offsetof(struct user, u_debugreg[7]))) {
                addr -= offsetof(struct user, u_debugreg[0]);
!                 addr = addr >> 3;  // long is 8 bytes on x86_64
                tmp = child->thread.arch.debugregs[addr];
        }
        return put_user(tmp, (unsigned long *) data);
  }

------------------------------------------------------------------------------
Return on Information:
Google Enterprise Search pays you back
Get the facts.
http://p.sf.net/sfu/google-dev2dev
_______________________________________________
User-mode-linux-devel mailing list
User-mode-linux-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel

Reply via email to