gdbstub initial code

2010-07-12 Thread Oleg Nesterov
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

2010-07-12 Thread Srikar Dronamraju
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

2010-07-12 Thread Ananth N Mavinakayanahalli
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

2010-07-12 Thread Srikar Dronamraju
 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

2010-07-12 Thread Roland McGrath
 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

2010-07-12 Thread Roland McGrath
 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