gdbstub initial code
Hello. Please see the attachment. Don't take this code seriously, this is the early prototype and everything should be rewritten. It barely uses utrace, only to stop the target. (gdb) file /path/to/binary (gdb) target extended-remote /proc/ugdb (gdb) attach PID (gdb) disassemble _start (gdb) bt (gdb) info registers (gdb) info threads (gdb) detach This seems to work, but I had to export access_process_vm(). Currently it only attaches to the single thread. vCont or ^C doesn't work. I still can't understand what utrace_xxx_pid() buys us, and I still think that utrace_prepare_examine() can't protect the task even for regset calls. Oleg. #include linux/module.h #include linux/proc_fs.h #include linux/utrace.h #include linux/regset.h #include linux/mm.h #include asm/uaccess.h #define static #define PACKET_SIZE 1024 #define BUFFER_SIZE 1024 struct cbuf { char*w_ptr; char*r_ptr; charbuf[BUFFER_SIZE]; }; static inline void cb_init(struct cbuf *cb) { cb-w_ptr = cb-r_ptr = cb-buf; } static int cb_rsz(struct cbuf *cb) { int rsz = cb-w_ptr - cb-r_ptr; if (rsz 0) rsz += BUFFER_SIZE; return rsz; } static int cb_wsz(struct cbuf *cb) { int wsz = cb-r_ptr - cb-w_ptr - 1; if (wsz 0) wsz += BUFFER_SIZE; return wsz; } static int cb_l_wsz(struct cbuf *cb) { char *lim = cb-r_ptr - 1; if (cb-w_ptr = cb-r_ptr) { lim = cb-buf + BUFFER_SIZE; if (cb-r_ptr == cb-buf) lim--; } return lim - cb-w_ptr; } static void __cb_padd(struct cbuf *cb, char **pptr, int cnt) { char *p = *pptr + cnt; if (p = cb-buf + BUFFER_SIZE) p -= BUFFER_SIZE; *pptr = p; } #define cb_pinc(cb, pptr) __cb_padd((cb), (pptr), 1) #define cb_padd(cb, pptr, cnt) __cb_padd((cb), (pptr), (cnt)) static inline void put_hex(unsigned char val, char to[2]) { static char hex[] = 0123456789abcdef; to[0] = hex[(val 0xf0) 4]; to[1] = hex[(val 0x0f) 0]; } static int cb_copy_to_user(struct cbuf *cb, unsigned char *pcsum, char __user *uptr, int size) { unsigned char csum = *pcsum; char *kptr = cb-r_ptr; int total, copied = 0; if (!access_ok(VERIFY_WRITE, uptr, size)) goto efault; for (total = cb_rsz(cb); total; --total) { unsigned char c = *kptr; int sz = (c == '#') ? 3 : 1; char csh[2]; size -= sz; if (size 0) break; if (__put_user(c, uptr)) goto efault; switch (c) { case '#': put_hex(csum, csh); if (__copy_to_user(uptr + 1, csh, sizeof csh)) goto efault; case '$': case '%': csum = 0; break; default: csum += (unsigned char)c; } cb_pinc(cb, kptr); copied += sz; uptr += sz; } ret: *pcsum = csum; cb-r_ptr = kptr; return copied ?: -EPIPE; efault: copied = copied ?: -EFAULT; goto ret; } static int cb_copy_from(struct cbuf *cb, const char *data, int size) { int flat, i; if (size cb_wsz(cb)) return -EOVERFLOW; for (i = 0; size i 2; ++i) { flat = cb_l_wsz(cb); if (flat size) flat = size; memcpy(cb-w_ptr, data, flat); cb_padd(cb, cb-w_ptr, flat); data += flat; size -= flat; } BUG_ON(size); return 0; } static int __attribute__ ((format(printf, 2, 3))) cb_printf(struct cbuf *cb, const char *fmt, ...) { char sbuf[64]; va_list args; int size; va_start(args, fmt); size = vsnprintf(sbuf, sizeof(sbuf), fmt, args); va_end(args); if (size = sizeof(sbuf)) return -EINVAL; return cb_copy_from(cb, sbuf, size); } static void cb_hexcopy_from(struct cbuf *cb, const char *data, int size) { if (WARN_ON(2 * size cb_wsz(cb))) return; while (size--) { char byte[2]; put_hex(*data++, byte); *cb-w_ptr = byte[0]; cb_pinc(cb, cb-w_ptr); *cb-w_ptr = byte[1]; cb_pinc(cb, cb-w_ptr); } } #define cb_puthex(cb, val) \ cb_hexcopy_from((cb), (val), sizeof(val)) static void cb_putc(struct cbuf *cb, char c) { if
Re: gdbstub initial code
Hi Oleg, Hello. Please see the attachment. Don't take this code seriously, this is the early prototype and everything should be rewritten. It barely uses utrace, only to stop the target. (gdb) file /path/to/binary (gdb) target extended-remote /proc/ugdb (gdb) attach PID (gdb) disassemble _start (gdb) bt (gdb) info registers (gdb) info threads (gdb) detach This seems to work, but I had to export access_process_vm(). Currently it only attaches to the single thread. vCont or ^C doesn't work. I still can't understand what utrace_xxx_pid() buys us, and I still think that utrace_prepare_examine() can't protect the task even for regset calls. When I had posted a prototype of a gdbstub which Frank and I had worked on. http://lkml.org/lkml/2009/11/30/173, Peter and Ingo showed a preference for a combined gdbstub in kernel, i.e kgdb and the newer stub should use only one stub in kernel. Do we have plans to handle that? -- Thanks and Regards Srikar
Re: gdbstub initial code
On Mon, Jul 12, 2010 at 08:37:29PM +0200, Oleg Nesterov wrote: Hello. Please see the attachment. Don't take this code seriously, this is the early prototype and everything should be rewritten. It barely uses utrace, only to stop the target. (gdb) file /path/to/binary (gdb) target extended-remote /proc/ugdb (gdb) attach PID (gdb) disassemble _start (gdb) bt (gdb) info registers (gdb) info threads (gdb) detach This seems to work, but I had to export access_process_vm(). Currently it only attaches to the single thread. vCont or ^C doesn't work. I still can't understand what utrace_xxx_pid() buys us, and I still think that utrace_prepare_examine() can't protect the task even for regset calls. IMHO, if this is the start of another stab at getting utrace in the upstream kernel, you may want to consider Linus' problem statement for utrace -- infrastructure that will allow strace and gdb on the same thread at the same time. OTOH, the Tom Tromey alluded on lkml that if kernel provides infrastructure that allows for breakpoint assistance and 'displaced' stepping, with a suitable user interface, preferably a ptrace variant that is fd based, they'll migrate gdb to using the interface. (The bp assistance and displaced stepping can be provided with extensions to the current uprobes set under review). In any case, its good to see a restart of this effort. Though there has been support for gdbstub in the past, an overwhelming majority of people would like to see a 'user interface', be it ptrace2 or PTRACE_ATTACH2 or whatever it needs to be called. Given these requirements, and given that the 'new' uprobes is close to -tip, would it be more useful to pursue an alternate syscall approach rather than gdbstub? Ananth
Re: gdbstub initial code
Hello. Please see the attachment. Don't take this code seriously, this is the early prototype and everything should be rewritten. It barely uses utrace, only to stop the target. (gdb) file /path/to/binary (gdb) target extended-remote /proc/ugdb (gdb) attach PID (gdb) disassemble _start What is the reasoning for selecting /proc/ugdb instead of something like /proc/pid/ugdb? We had a discussion sometime back in utrace_devel https://www.redhat.com/archives/utrace-devel/2008-June/msg00070.html where we thought having /proc/utrace was a bad choice. -- Thanks and Regards Srikar
Re: gdbstub initial code
Please see the attachment. Don't take this code seriously, this is the early prototype and everything should be rewritten. It barely uses utrace, only to stop the target. You've got to start somewhere! Thanks, Oleg. It's great to see this get underway. This seems to work, but I had to export access_process_vm(). Yeah, that's a known issue. We can discuss how to either work around or change it at some point, but it's just a distraction at the moment. I still can't understand what utrace_xxx_pid() buys us, and I still think that utrace_prepare_examine() can't protect the task even for regset calls. Please start a separate thread here about each of those issues. The first one is fairly simple, but what that means in practice depends on the resolution of the second question, which is a more complex subject. Thanks, Roland
Re: gdbstub initial code
When I had posted a prototype of a gdbstub which Frank and I had worked on. http://lkml.org/lkml/2009/11/30/173, Peter and Ingo showed a preference for a combined gdbstub in kernel, i.e kgdb and the newer stub should use only one stub in kernel. Do we have plans to handle that? Their actual idea there largely represents a misunderstanding of the problem space. But regardless, it's a distraction from the prototype work that Oleg is doing now. The actual possibilities for code sharing between kgdb and something at all like what we're doing now are quite small. It's just not a problem at all to get prototyping progress done with a new implementation of the fairly trivial gdb remote protocol decoder, and contemplate consolidation later on. Thanks, Roland