Re: gdbstub initial code, v7

2010-10-15 Thread Oleg Nesterov
On 10/13, Roland McGrath wrote:

  On 09/10, Roland McGrath wrote:
  
ugdb sets please stop flag and does utrace_control(INTERRUPT). 
However,
in unlikely case the tracee can stop before -report_signal() reporting
  
   I don't think this is the right thing to do.  When the intent is 
   explicitly
   to interrupt, there is no reason to stop before the interruption is
   complete, i.e. report_signal.
 
  This means that ugdb_report_quiesce() should never return UTRACE_STOP,
  and that is all.

 I'm not sure about this.

Ignoring the problems below, why?

  But what about multitracing? Suppose that (gdb) interrupt happens
  just before, say, do_report_syscall_entry() and another engine wants
  to stop. If ugdb_report_quiesce() doesn't return UTRACE_STOP, then
  gdb will wait until another debugger resumes the tracee.

 Yes, I do think that's a problem.  We want gdb to report back promptly.
 One possibility is to have report_quiesce notice its argument is
 UTRACE_EVENT(SYSCALL_ENTRY) and roll back to before the syscall.
 That is, it enables SYSCALL_ENTRY and SYSCALL_EXIT reporting, then
 its report_syscall_entry uses UTRACE_SIGNAL_ABORT, report_syscall_exit
 does syscall_set_return_value(-ERESTARTNOHAND, 0) and then returns
 UTRACE_INTERRUPT.  Now, we'll reenter a UTRACE_SIGNAL_REPORT callback
 before the system call, and we can stop there without being in any
 sticky situation.

Well, but this doesn't look friendly to other engines...

And at first glance this looks a bit too hairy. And, this doesn't
cover another case: gdb asks to stop the tracee when it is already
stopped by another engine and sleeps in utrace_resume() path.

So, I think ugdb should be changed so that signal SIG always works
(without reporing this signal) even when the stopped tracee doesn't
have the signal context.

As for $_siginfo (qXfer:siginfo:read::), I do not know what ugdb
should do. Probably it can just report the all-zeroes siginfo or
report si_signo = SIGSTOP.

Oleg.



Re: gdbstub initial code, v7

2010-09-10 Thread Roland McGrath
 But I meant another case, when the stopped tracee doesn't have siginfo.
 Currently ugdb just sends this signal to tracee, and then it will be
 reported to gdb. Not sure if this is right or not, I can change this.
 (or perhap this doesn't matter, I dunno).

What do you mean by doesn't have siginfo?  You mean non-signal stops?
What non-signal stops does ugdb report?


Thanks,
Roland



Re: gdbstub initial code, v7

2010-09-10 Thread Oleg Nesterov
On 09/10, Roland McGrath wrote:

  But I meant another case, when the stopped tracee doesn't have siginfo.
  Currently ugdb just sends this signal to tracee, and then it will be
  reported to gdb. Not sure if this is right or not, I can change this.
  (or perhap this doesn't matter, I dunno).

 What do you mean by doesn't have siginfo?  You mean non-signal stops?

Yes.

 What non-signal stops does ugdb report?

(gdb) interrupt

ugdb sets please stop flag and does utrace_control(INTERRUPT). However,
in unlikely case the tracee can stop before -report_signal() reporting
loop (especially in multitracing case). Or it can be already stopped
(note: this needs a separate discussion, currently ugdb intentionally
doesn't handle this case).

And. With the current implementation, even if the tracee stops after
ugdb_report_signal() was called, it doesn't setup -t_siginfo.

IOW. If the tracee actually recieves a signal, then

- qXfer:siginfo:read works

- signal SIG works as expected (delivered to tracee)

Otherwise

- qXfer:siginfo:read reports E01

- signal XX means TXX report.

Once again, this can be changed (fixed?), but I am not sure this
should be changed.

Oleg.



Re: gdbstub initial code, v7

2010-09-10 Thread Roland McGrath
 ugdb sets please stop flag and does utrace_control(INTERRUPT). However,
 in unlikely case the tracee can stop before -report_signal() reporting

I don't think this is the right thing to do.  When the intent is explicitly
to interrupt, there is no reason to stop before the interruption is
complete, i.e. report_signal.  If you only stop there, then you can always
process a signal injection with complete flexibility.  The gdb model and
the remote protocol doesn't currently have any concept of requesting a stop
that is not an interruption.


Thanks,
Roland



Re: gdbstub initial code, v7

2010-09-10 Thread Oleg Nesterov
On 09/10, Roland McGrath wrote:

  ugdb sets please stop flag and does utrace_control(INTERRUPT). However,
  in unlikely case the tracee can stop before -report_signal() reporting

 I don't think this is the right thing to do.  When the intent is explicitly
 to interrupt, there is no reason to stop before the interruption is
 complete, i.e. report_signal.

This means that ugdb_report_quiesce() should never return UTRACE_STOP,
and that is all.

But what about multitracing? Suppose that (gdb) interrupt happens
just before, say, do_report_syscall_entry() and another engine wants
to stop. If ugdb_report_quiesce() doesn't return UTRACE_STOP, then
gdb will wait until another debugger resumes the tracee.

What do you think?

 If you only stop there, then you can always
 process a signal injection with complete flexibility.

Yes, sure (again, currently ugdb does not injection a signal even
if the tracee was stopped in report_signal, but of course we can
change this).

Oleg.



Re: gdbstub initial code, v7

2010-09-03 Thread Jan Kratochvil
On Thu, 02 Sep 2010 22:06:32 +0200, Oleg Nesterov wrote:
 I assume that qXfer:siginfo:read always mean Hg thread.

It seems so.

 It is not clear to me what should ugdb report if there is no a valid
 siginfo.  linux_xfer_siginfo() return E01, but gdbserver uses SIGSTOP to
 stop the tracee,

I find error more appropriate in such case.

 Likewise, it is not clear what should ugdb do if gdb sends
 $CSIG in this case.

Currently GDB does not do anything special, that is if there is siginfo for
signal SIGUSR1 but one does $C0B (SIGSEGV) does ptrace reset the siginfo or is
left the SIGUSR1 siginfo for SIGSEGV?

 But this all is minor, I think.

As this is being discussed for GDB I would find enough to just make $_siginfo
accessible without these details.


Thanks,
Jan



Re: gdbstub initial code, v7

2010-09-03 Thread Frank Ch. Eigler
Oleg Nesterov o...@redhat.com writes:

 [...]  To the point, I had to add printk's to utrace.c to understand
 what is wrong. Hopefully tomorrow.

You might wish to try out systemtap for such purposes.  It's easy to
insert printk-like tracing at almost any point; monitor variables for
changes, pretty-print structs, etc.  No recompilation/reboot.

- FChE



Re: gdbstub initial code, v7

2010-09-03 Thread Roland McGrath
 Currently GDB does not do anything special, that is if there is siginfo for
 signal SIGUSR1 but one does $C0B (SIGSEGV) does ptrace reset the siginfo or is
 left the SIGUSR1 siginfo for SIGSEGV?

The kernel considers this sloppy behavior on the debugger's part.  If
you inject a different signal, we expect you should PTRACE_SETSIGINFO
to something appropriate, or else that you really didn't care about
the bits being accurate.  If the resumption signal does not match the
siginfo_t.si_signo, then the kernel resets the siginfo as if the
debugger had just used kill with the new signal (i.e. si_pid, si_uid
point to the ptracer).


Thanks,
Roland



Re: gdbstub initial code, v7

2010-09-03 Thread Jan Kratochvil
On Fri, 03 Sep 2010 21:59:06 +0200, Roland McGrath wrote:
  Currently GDB does not do anything special, that is if there is siginfo for
  signal SIGUSR1 but one does $C0B (SIGSEGV) does ptrace reset the siginfo or 
  is
  left the SIGUSR1 siginfo for SIGSEGV?
 
 The kernel considers this sloppy behavior on the debugger's part.  If
 you inject a different signal, we expect you should PTRACE_SETSIGINFO
 to something appropriate, or else that you really didn't care about
 the bits being accurate.  If the resumption signal does not match the
 siginfo_t.si_signo, then the kernel resets the siginfo as if the
 debugger had just used kill with the new signal (i.e. si_pid, si_uid
 point to the ptracer).

OK, that seems to me as the best choice.  Sorry I did not test/read it.


Thanks,
Jan



Re: gdbstub initial code, v7

2010-09-02 Thread Oleg Nesterov
Sorry for the delay, I was distracted. Trying to switch back to ugdb.

On 08/31, Jan Kratochvil wrote:

  ugdb should support qXfer:siginfo, currently accessible only via $_siginfo
  print/set, though.

 Still sure this feature should be also implemented one day.

Yes sure. This should be simple, although I didn't expect qXfer
needs remote_escape_output() and x86_siginfo_fixup(). I assume
that qXfer:siginfo:read always mean Hg thread. It is not clear
to me what should ugdb report if there is no a valid siginfo.
linux_xfer_siginfo() return E01, but gdbserver uses SIGSTOP to
stop the tracee, so it always has something to report. But ugdb
stop the tracee somewhere else, not in get_signal_to_deliver()
path.

Likewise, it is not clear what should ugdb do if gdb sends
$CSIG in this case. But this all is minor, I think.

I was going to send v8 which implements qXfer:siginfo:read and
continue with signal, but (oh, as always) hit the unexpected
problems. To the point, I had to add printk's to utrace.c to
understand what is wrong. Hopefully tomorrow.

Oleg.



Re: gdbstub initial code, v7

2010-08-31 Thread Jan Kratochvil
On Mon, 30 Aug 2010 21:20:40 +0200, Jan Kratochvil wrote:
 On Mon, 30 Aug 2010 20:58:50 +0200, Oleg Nesterov wrote:
  - report signals. A bit more code changes than I expected.
 
 BTW not sure if it is already the right time for it but to keep ugdb on-par
 with my linux-nat's re-post today (still not accepted in FSF GDB)

That's not true, this functionality needs no gdb/remote.c changes and its
correctnes relies just on ugdb (and it is probably not a problem for ugdb).


 ugdb should support qXfer:siginfo, currently accessible only via $_siginfo
 print/set, though.

Still sure this feature should be also implemented one day.


Thanks,
Jan



gdbstub initial code, v7

2010-08-30 Thread Oleg Nesterov
Changes:

- report signals. A bit more code changes than I expected.

- implement QPassSignals, trivial.

Note: $CSIG is not supported yet, and I am not sure I understand
how it should work. Next time...

#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;

struct ugdb *t_ugdb;
struct ugdb_process *t_process;

struct list_headt_threads;
struct list_headt_stopped;

struct pid  *t_spid;

struct utrace_engine*t_engine;
};

static inline bool thread_alive(struct ugdb_thread *thread)
{
WARN_ON((thread-t_tid != 0) != process_alive(thread-t_process));

return thread-t_tid != 0;
}

static inline void mark_thread_dead(struct ugdb_thread *thread)
{
mark_process_dead(thread-t_process);
thread-t_tid = 0;
}

/*
 * The thread should be alive, and it can't pass ugdb_report_death()
 * if the caller holds ugdb-u_mutex. However 

Re: gdbstub initial code, v7

2010-08-30 Thread Jan Kratochvil
On Mon, 30 Aug 2010 20:58:50 +0200, Oleg Nesterov wrote:
   - report signals. A bit more code changes than I expected.

BTW not sure if it is already the right time for it but to keep ugdb on-par
with my linux-nat's re-post today (still not accepted in FSF GDB)
[0/9]#2 Fix lost siginfo_t
http://sourceware.org/ml/gdb-patches/2010-08/msg00480.html

ugdb should support qXfer:siginfo, currently accessible only via $_siginfo
print/set, though.


Thanks,
Jan