Re: gdbstub initial code, v9
On 09/10, Roland McGrath wrote: Oleg == Oleg Nesterov o...@redhat.com writes: Oleg (gdb) set var 0 You need: set variable var = 0 The variable can be abbreviated. I've always just used: (gdb) set var=0 No, I tried this too, doesn't work. (gdb) set var=0 A syntax error in expression, near `=0'. But, it turns out I choosed a bad name for the variable when I tested the fix in unxex(). (gdb) set xxx=0 This works. (gdb) set var var=0 This works too. I guess, when gdb sees set var it expects the full set variable ... command. Oleg.
Re: gdbstub initial code, v9
Oleg == Oleg Nesterov o...@redhat.com writes: I've always just used: (gdb) set var=0 Oleg No, I tried this too, doesn't work. Oleg (gdb) set var=0 Oleg A syntax error in expression, near `=0'. Yeah, it is ambiguous if the actual variable name conflicts with any gdb set subcommand. I typically just use call or print. Tom
Re: gdbstub initial code, v9
Hi Oleg, kernel-devel-2.6.34.6-54.fc13.x86_64 (real F13) says: ugdb.c:1988: error: implicit declaration of function ‘hex_to_bin’ Jan
Re: gdbstub initial code, v9
On 09/09, Frank Ch. Eigler wrote: Oleg Nesterov o...@redhat.com writes: [...] But, Jan. Implementing the memory writes does not mean breakpoints automatically start to work! It approximately should though. Yes, gdb writes cc, and yes the tracee reports SIGTRAP. But after that continue does nothing except $c, and the tracee naturally gets SIGILL. I expected that, since ugdb doesn't even know the code was changed, gdb should write the original byte back before continue, but this doesn't happen. In normal all-stop mode, Currently ugdb only supports non-stop gdb does normally replace the old instruction, in order to single-step over it with the 's' packet. Yes, probably single-stepping is needed... I am still trying to understand how this works with gdbserver, but I see vCont:s packets. Perhaps you're testing some buggy non-stop aspect that only works with 'Z' breakpoint management packets? No. Just a trivial test-case which printfs in a loop. A fuller packet trace would help explain. Please see below. But the only important part is: $M4005ba,1:cc --- set bp $c --- resume of course, this can't work. Full trace: = qSupported:multiprocess+ = PacketSize=400;QStartNoAckMode+;QNonStop+;multiprocess+;QPassS... = QStartNoAckMode = OK = ! = OK = Hgp0.0 = E01 = QNonStop:1 = OK = qfThreadInfo = E01 = ? = OK = qSymbol:: = = vAttach;95b = OK = qfThreadInfo = mp95b.95b = qsThreadInfo = l = Hgp95b.95b = OK = vCont? = vCont;t = vCont;t:p95b.-1 = OK = %Stop:T00thread:p95b.95b; = vStopped = OK = g = fcfd90ad5329ff7f00... = m600880,8 = 403c6d7d007f = m7f007d6d3c48,8 = 00106d7d007f = m7f007d6d1000,28 = f6e04c7d007fe807600080156d7d007f00... = m7f007d6d1580,28 = 00f0ef29ff7ff6e04c7d007f50f45f29ff7f00c06c7d007f00... = m7f007d4ce0f4,4 = 090a0069 = m7f007d6cc000,28 = 0030167d007f781f6d7d007f400b4b7d007fe8346d7d007f00... = m7f007d6d1f78,4 = 2f6c6962 = m7f007d6d1f7c,4 = 2f6c6962 = m7f007d6d1f80,4 = 632e736f = m7f007d6d1f84,4 = 2e36 = m7f007d6d34e8,28 = 00704b7d007f0002482e6d7d007f00... = m400200,4 = 2f6c6962 = m400204,4 = 2f6c642d = m400208,4 = 6c696e75 = m40020c,4 = 782d7838 = m400210,4 = 362d3634 = m400214,4 = 2e736f2e = m400218,4 = 3200 = m7f007d6d3c40,4 = 0100 = m7f007d6d3c48,8 = 00106d7d007f = m7f007d6d3c50,8 = c04e4c7d007f = Z0,7f007d4c4ec0,1 = = m7f007d4c4ec0,1 = f3 = X7f007d4c4ec0,0: = = M7f007d4c4ec0,1:cc = OK = m600880,8 = 403c6d7d007f = m7f007d6d3c48,8 = 00106d7d007f = m7f007d6d1000,28 = f6e04c7d007fe807600080156d7d007f00... = m7f007d6d1580,28 = 00f0ef29ff7ff6e04c7d007f50f45f29ff7f00c06c7d007f00... = m7f007d4ce0f4,4 = 090a0069 = m7f007d6cc000,28 = 0030167d007f781f6d7d007f400b4b7d007fe8346d7d007f00... = m7f007d6d1f78,4 = 2f6c6962 = m7f007d6d1f7c,4 = 2f6c6962 = m7f007d6d1f80,4 = 632e736f = m7f007d6d1f84,4 = 2e36 = m7f007d6d34e8,28 = 00704b7d007f0002482e6d7d007f00... = m400200,4 = 2f6c6962 = m400204,4 = 2f6c642d = m400208,4 = 6c696e75 = m40020c,4 = 782d7838 = m400210,4 = 362d3634 = m400214,4 = 2e736f2e = m400218,4 = 3200 = m7f007d6d3c40,4 = 0100 = vCont;t:p95b.-1 = OK = m7f007d201f40,1 = 48 = m7f007d201f40,1 = 48 = g = fcfd90ad5329ff7f00... = m7f007d201f40,1 = 48 = m7f007d201f40,1 = 48 = m40056c,12 = 554889e5e8e3fe89c6ba0700bfdc = m40056c,1 = 55 = m40056d,3 = 4889e5 = m40056c,12 = 554889e5e8e3fe89c6ba0700bfdc = m40056c,1 = 55 = m40056d,3 = 4889e5 = m4005ba,1 = e8 = m4005ba,1 = e8 (gdb) b BP.c:13 Breakpoint 1 at 0x4005ba: file BP.c,
Re: gdbstub initial code, v9
On 09/09, Oleg Nesterov wrote: the tracee hits this bp and reports SIGTRAP = vStopped = OK = g = 00064000401f207d007f00... = P10=ba054000 = = G00064000401f207d007f0... = May be this can explain... Probably I need to implement G/P first, otherwise gdb can't change ip. Still, I'd appreciate if someone can explain me what gdb needs/expects to handle breakpoints before I start to read the sources. Oleg.
Re: gdbstub initial code, v9
Hi - On Thu, Sep 09, 2010 at 05:50:47PM +0200, Oleg Nesterov wrote: Probably I need to implement G/P first, otherwise gdb can't change ip. Perhaps. Still, I'd appreciate if someone can explain me what gdb needs/expects to handle breakpoints before I start to read the sources. It'd be simpler if the normal all-stop mode was what you first focused on. That mode works fine with Z/z and with M/m based breakpoint insertion/removal and c/s continue/singlestep. (This stuff was all working in the earlier gdbstub code.) Re. non-stop mode, see http://www.codesourcery.com/publications/non_stop_multi_threaded_debugging_in_gdb.pdf - FChE
Re: gdbstub initial code, v9
On Thu, 09 Sep 2010 18:30:31 +0200, Oleg Nesterov wrote: OOPS! indeed, unhex() confuses lo and hi. It works for 0xcc, though. Cough... could you tell me how can I change the variable done without printing it? (gdb) help set variable Evaluate expression EXP and assign result to variable VAR, using assignment syntax appropriate for the current language (VAR = EXP or VAR := EXP for example). VAR may be a debugger convenience variable (names starting with $), a register (a few standard names starting with $), or an actual variable in the program being debugged. EXP is any valid expression. This may usually be abbreviated to simply set. Regards, Jan
Re: gdbstub initial code, v9
Oleg == Oleg Nesterov o...@redhat.com writes: Oleg (gdb) set var 0 You need: set variable var = 0 The variable can be abbreviated. FWIW, print, set variable, and call are basically aliases. print just happens to print the result of the expression. Tom
gdbstub initial code, v9
Changes: - partly fix the multitracing problems. ugdb still can't work with ptrace, ptrace-utrace.c needs changes. But at least multiple udgb tracers can coexist, more or less. But of course they can confuse each other anyway, no matter what ugdb does. - implement memory writes ($M). - refactor memory reads to avoid the Too late to report the error case. But, Jan. Implementing the memory writes does not mean breakpoints automatically start to work! Yes, gdb writes cc, and yes the tracee reports SIGTRAP. But after that continue does nothing except $c, and the tracee naturally gets SIGILL. I expected that, since ugdb doesn't even know the code was changed, gdb should write the original byte back before continue, but this doesn't happen. Tried to understand how this works with gdbserver, but failed so far. Will continue, but any hint is very much appreciated ;) 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