Re: gdbstub initial code, v11

2010-09-23 Thread Roland McGrath
  The ones I'm talking about are Z2/Z3 for (data) watchpoints.
 
 Ah, OK, thanks. I'll try to understand how this works.

In theory these will map to uses of the hw_breakpoint interface.


Thanks,
Roland



Re: gdbstub initial code, v11

2010-09-23 Thread Roland McGrath
 I think it would be good to implement a feature that shows how this
 approach is an improvement over the current state of gdb+ptrace or
 gdb+gdbserver.
 
 Exactly what feature this should be... I don't know :-)
 I would imagine something performance-related.

My vague notion was that we'd get it working well enough to have basic
parity with native or gdbserver on some realish test cases, and then just
look at the protocol interaction log to see cases where we could reduce
round-trips between gdb and the stub.  Some of those are bound to entail
protocol extensions and gdb changes to exploit them.  Off hand, the Z cases
might be the only things that won't need that.


Thanks,
Roland



Re: gdbstub initial code, v11

2010-09-23 Thread Frank Ch. Eigler
Hi -

On Thu, Sep 23, 2010 at 02:21:38PM -0700, Roland McGrath wrote:
   The ones I'm talking about are Z2/Z3 for (data) watchpoints.
  Ah, OK, thanks. I'll try to understand how this works.
 
 In theory these will map to uses of the hw_breakpoint interface.

Not quite.  The hw_breakpoint widget is only useful for the first few
active watchpoints.  The rest, which gdb calls software watchpoints,
can be implemented in ugdb by local singlestep + polling, without
gdb's live involvement.

- FChE



Re: gdbstub initial code, v11

2010-09-22 Thread Tom Tromey
Oleg But what about features? What should I do next? all-stop,
Oleg thread-specific breakpoints (currently I have no idea what
Oleg this means), or what?

I think it would be good to implement a feature that shows how this
approach is an improvement over the current state of gdb+ptrace or
gdb+gdbserver.

Exactly what feature this should be... I don't know :-)
I would imagine something performance-related.

There was previously some discussion about some watchpoint-related
thing, I forget the details of that.

I don't think thread-specific breakpoints are exposed outside of gdb
yet.  If that is true, then implementing that would mean adding remote
protocol features and also other stuff inside gdb.  So, I would suggest
not tackling this yet.

Tom



Re: gdbstub initial code, v11

2010-09-22 Thread Jan Kratochvil
On Wed, 22 Sep 2010 21:09:12 +0200, Tom Tromey wrote:
 I think it would be good to implement a feature that shows how this
 approach is an improvement over the current state of gdb+ptrace or
 gdb+gdbserver.
 
 Exactly what feature this should be... I don't know :-)
 I would imagine something performance-related.

I would bet on a massive threads creating/deleting testcase signalling tasks
around, together with watchpoints.  There are races in the linux-nat code and
IIRC even gdbserver code.

OTOH if one tries hard one can probably manage one day to fix all the corner
cases in the ptrace based linux-nat and gdbserver.


Regards,
Jan



Re: gdbstub initial code, v11

2010-09-22 Thread Oleg Nesterov
On 09/22, Frank Ch. Eigler wrote:

 oleg wrote:

  [...]  Honestly, I don't really know how do the right thing here.
  Anyway, most probably this code will be changed. Like ptrace, ugdb
  uses -report_syscall_exit() to synthesize a trap. Unlike ptrace,
  ugdb_report_signal() doesn't send SIGTRAP to itself but reports
  SIGTRAP using siginfo_t we have. In any case, whatever we do,
  multiple tracers can confuse each other.

 (It seems to me that a pure gdb report, without a synthetic
 self-injected SIGTRAP, should be fine.)

What do you mean?

  Next: fully implement g/G/p/P, currently I am a bit confused...
  But what about features? [...]

 You could dig out the old fishing plan.  One demonstrated
 improvement was from simulating (software) watchpoints within the
 gdb stub, instead of having gdb fall back to issing countless
 single-steps with memory-fetch inquiries in between.

When I do 'watch', gdb sends '$Z2'. I am a bit confused, iirc it
was decided I shouldn't play with Z packets now. But I won't
argue.

Oleg.



Re: gdbstub initial code, v11

2010-09-22 Thread Frank Ch. Eigler
Hi -

On Thu, Sep 23, 2010 at 01:14:51AM +0200, Oleg Nesterov wrote:
  (It seems to me that a pure gdb report, without a synthetic
  self-injected SIGTRAP, should be fine.)
 
 What do you mean?

(Never mind, I'm probably just confused about what you were asking.)


   Next: fully implement g/G/p/P, currently I am a bit confused...
   But what about features? [...]
 
  You could dig out the old fishing plan.  One demonstrated
  improvement was from simulating (software) watchpoints within the
  gdb stub, instead of having gdb fall back to issing countless
  single-steps with memory-fetch inquiries in between.
 
 When I do 'watch', gdb sends '$Z2'. I am a bit confused, iirc it
 was decided I shouldn't play with Z packets now. But I won't
 argue.

There are Z packets and then there are Z packets.  The ones Roland
told you not to worry about are Z0/Z1 related to (code) breakpoints,
which should be implemented via uprobes at some point.

The ones I'm talking about are Z2/Z3 for (data) watchpoints.

- FChE



gdbstub initial code, v11

2010-09-21 Thread Oleg Nesterov
Changes: syscall stepping + minor cleanups.

Seems to work, more or less, but surely there are some bugs.

Honestly, I don't really know how do the right thing here.
Anyway, most probably this code will be changed. Like ptrace,
ugdb uses -report_syscall_exit() to synthesize a trap. Unlike
ptrace, ugdb_report_signal() doesn't send SIGTRAP to itself
but reports SIGTRAP using siginfo_t we have. In any case,
whatever we do, multiple tracers can confuse each other.

Next: fully implement g/G/p/P, currently I am a bit confused...

But what about features? What should I do next? all-stop,
thread-specific breakpoints (currently I have no idea what
this means), or what?

Oleg.

#include linux/module.h
#include linux/proc_fs.h
#include linux/utrace.h
#include linux/poll.h
#include linux/mm.h
#include linux/regset.h
#include asm/uaccess.h

static int o_remote_debug;
module_param_named(echo, o_remote_debug, bool, 0);

#define BUFFER_SIZE 1024
#define PACKET_SIZE 1024

struct pbuf {
char*cur, *pkt;
charbuf[BUFFER_SIZE];
};

static inline void pb_init(struct pbuf *pb)
{
pb-cur = pb-buf;
pb-pkt = NULL;
}

enum {
U_STOP_IDLE = 0,
U_STOP_PENDING,
U_STOP_SENT,
};

struct ugdb {
struct list_headu_processes;
struct list_headu_stopped;

int u_stop_state;

struct mutexu_mutex;
spinlock_t  u_slock;

struct ugdb_thread
*u_cur_tinfo,
*u_cur_hg,
*u_cur_hc;

wait_queue_head_t   u_wait;

int u_err;

struct pbuf u_pbuf;
charu_cbuf[PACKET_SIZE];
int u_clen;

sigset_tu_sig_ign;

unsigned int
u_no_ack:1,
u_allstop:1;
};

static inline void ugdb_ck_stopped(struct ugdb *ugdb)
{
spin_lock(ugdb-u_slock);
WARN_ON(!list_empty(ugdb-u_stopped) 
ugdb-u_stop_state == U_STOP_IDLE);
WARN_ON(list_empty(ugdb-u_stopped) 
ugdb-u_stop_state == U_STOP_PENDING);
spin_unlock(ugdb-u_slock);
}

static struct ugdb *ugdb_create(void)
{
struct ugdb *ugdb;
int err;

err = -ENODEV;
// XXX: ugly. proc_reg_open() should take care.
if (!try_module_get(THIS_MODULE))
goto out;

err = -ENOMEM;
ugdb = kzalloc(sizeof(*ugdb), GFP_KERNEL);
if (!ugdb)
goto put_module;

INIT_LIST_HEAD(ugdb-u_processes);
INIT_LIST_HEAD(ugdb-u_stopped);

mutex_init(ugdb-u_mutex);
spin_lock_init(ugdb-u_slock);

init_waitqueue_head(ugdb-u_wait);

pb_init(ugdb-u_pbuf);

return ugdb;

put_module:
module_put(THIS_MODULE);
out:
return ERR_PTR(err);
}

#define P_DETACHING (1  1)
#define P_ZOMBIE(1  2)

struct ugdb_process {
int p_pid;
int p_state;

struct list_headp_threads;

struct ugdb *p_ugdb;
struct list_headp_processes;
};

static inline bool process_alive(struct ugdb_process *process)
{
return !(process-p_state  P_ZOMBIE);
}

static inline void mark_process_dead(struct ugdb_process *process)
{
process-p_state |= P_ZOMBIE;
}

static struct ugdb_process *ugdb_create_process(struct ugdb *ugdb, int pid_nr)
{
struct ugdb_process *process;

process = kzalloc(sizeof(*process), GFP_KERNEL);
if (!process)
return NULL;

process-p_pid = pid_nr;
process-p_ugdb = ugdb;
INIT_LIST_HEAD(process-p_threads);
list_add_tail(process-p_processes, ugdb-u_processes);

return process;
}

#define T_STOP_RUN  0
#define T_STOP_REQ  (1  0)/* requested by gdb */
#define T_STOP_ALL  (1  1)/* vCont;c:pX.-1, for report_clone */
#define T_STOP_ACK  (1  2)/* visible to vStopped */
#define T_STOP_STOPPED  (1  3)/* reported as stopped to gdb */
/* TASK_TRACED + deactivated ? */

#define T_EV_NONE   0
#define T_EV_EXIT   (1  24)
#define T_EV_SIGN   (2  24)

#define T_EV_TYPE(event)((0xff  24)  (event))
#define T_EV_DATA(event)(~(0xff  24)  (event))

struct ugdb_thread {
int t_tid;
int t_stop_state;
int t_stop_event;
boolt_step; // XXX: move me into 
t_stop_event

siginfo_t   *t_siginfo;

struct ugdb *t_ugdb;
struct ugdb_process *t_process;

struct