Message ID | 1517222676-467-1-git-send-email-omair.javaid@linaro.org |
---|---|
State | New |
Headers | show |
Series | Fix for GDB failing to interrupt after run when no PID issued by stub | expand |
Omair Javaid <omair.javaid@linaro.org> writes: > Here are the steps to reproduce: > 1) arm-none-eabi-gdb file-to-debug.elf > 2) target remote :3333 "target extended-remote :3333". > At this stage gdb would have connected and halted successfully. > 3) run > Issue ctrl + C to interrupt running program and GDB wont be able to stop. Could you show the log of "set debug remote 1", especially after "ctrl-c" is typed. I want to understand what is going on over these packets between GDB and stub, and reproduce it on GDBserver by disabling some packets. This is what I get, (gdb) c Continuing. Sending packet: $Z0,7ffff7dea940,1#e0...Packet received: OK Sending packet: $QPassSignals:#f3...Packet received: OK Sending packet: $Hc0#db...Packet received: OK Sending packet: $s#73...Packet received: T0506:c0dcffffff7f0000;07:c0dcffffff7f0000;10:7f05400000000000; Sending packet: $Z0,40057a,1#74...Packet received: OK Sending packet: $QPassSignals:e;10;14;17;1a;1b;1c;21;24;25;2c;4c;97;#0a...Packet received: OK Sending packet: $Hcpa410.0#6f...Packet received: E01 Sending packet: $c#63...^Cremote_pass_ctrlc called remote_interrupt called Packet received: T0206:ffffffff00000000;07:d8daffffff7f0000;10:e05dadf7ff7f0000; Sending packet: $qL1200000000000000000#50...Packet received: Program received signal SIGINT, Interrupt. Sending packet: $z0,40057a,1#94...Packet received: OK In the stop reply from my gdbserver, there is no "thread id" either. My stop reply has expedite registers while OpenOCD doesn't. I don't think this matters here. -- Yao (齐尧)
On 31 January 2018 at 21:41, Yao Qi <qiyaoltc@gmail.com> wrote: > Omair Javaid <omair.javaid@linaro.org> writes: > > > Here are the steps to reproduce: > > 1) arm-none-eabi-gdb file-to-debug.elf > > 2) target remote :3333 > > "target extended-remote :3333". > > > At this stage gdb would have connected and halted successfully. > > 3) run > > Issue ctrl + C to interrupt running program and GDB wont be able to stop. > > Could you show the log of "set debug remote 1", especially after > "ctrl-c" is typed. I want to understand what is going on over these > packets between GDB and stub, and reproduce it on GDBserver by disabling > some packets. This is what I get, > Heres the gdb log with run (no other command b/w connection and run): https://paste.ubuntu.com/26496015/ Heres the gdb log with continue + run (after we issue a continue/interrupt cycle where inferior PID is set and inferior->control.stop_soon = NO_STOP_QUIETLY;) https://paste.ubuntu.com/26496048/ > > (gdb) c > Continuing. > Sending packet: $Z0,7ffff7dea940,1#e0...Packet received: OK > Sending packet: $QPassSignals:#f3...Packet received: OK > Sending packet: $Hc0#db...Packet received: OK > Sending packet: $s#73...Packet received: T0506:c0dcffffff7f0000;07: > c0dcffffff7f0000;10:7f05400000000000; > Sending packet: $Z0,40057a,1#74...Packet received: OK > Sending packet: $QPassSignals:e;10;14;17;1a;1b;1c;21;24;25;2c;4c;97;#0a...Packet > received: OK > Sending packet: $Hcpa410.0#6f...Packet received: E01 > Sending packet: $c#63...^Cremote_pass_ctrlc called > remote_interrupt called > Packet received: T0206:ffffffff00000000;07:d8daffffff7f0000;10: > e05dadf7ff7f0000; > Sending packet: $qL1200000000000000000#50...Packet received: > > Program received signal SIGINT, Interrupt. > Sending packet: $z0,40057a,1#94...Packet received: OK > > In the stop reply from my gdbserver, there is no "thread id" either. My > stop reply has expedite registers while OpenOCD doesn't. I don't think > this matters here. > The situation with OpenOCD happens because we ran and set inferior pid to null hoping to update it. Later in extended_remote_create_inferior called buy run command thread pid gets assigned but we are checking inferior->control.stop_soon just before we update the pid and thus it remains to STOP_QUIETLY for lifetime of the inferior as this flag is only altered by attach command handlers or during call of clear_proceed_status > > -- > Yao (齐尧) >
Omair Javaid <omair.javaid@linaro.org> writes: > Heres the gdb log with run (no other command b/w connection and run): > https://paste.ubuntu.com/26496015/ > One thing suspicious to me is an empty reply to qXfer:threads:read w $qXfer:threads:read::0,fff#03 r $l<?xml version="1.0"?>\n<threads>\n</threads>\n#02 OpenOCD claims support "qXfer:threads:read+;", but such reply above may confuse GDB. In OpenOCD source, I find OpenOCD supports qXfer:threads unconditionally, but I think it should be changed to support it when "target->rtos != NULL". This may don't matter. > Heres the gdb log with continue + run (after we issue a > continue/interrupt cycle where inferior PID is set and > inferior->control.stop_soon = NO_STOP_QUIETLY;) > https://paste.ubuntu.com/26496048/ > > > The situation with OpenOCD happens because we ran and set inferior pid > to null hoping to update it. Later in extended_remote_create_inferior > called buy run command thread pid gets assigned but we are checking > inferior->control.stop_soon just before we update the pid and thus it > remains to STOP_QUIETLY for lifetime of the inferior as this flag is > only altered by attach command handlers or during call of > clear_proceed_status I still don't understand why inferior->control.stop_soon remains "STOP_QUIETLY", inferior::control::stop_soon is initialized to NO_STOP_QUIETLY. I even don't see where it is changed to STOP_QUIETLY. I can understand that GDB check inferior_ptid (try to set inferior->control.stop_soon) first [1], and then update inferior_ptid later [2], if (!have_inferiors ()) { /* Clean up from the last time we ran, before we mark the target running again. This will mark breakpoints uninserted, and get_offsets may insert breakpoints. */ init_thread_list (); init_wait_for_inferior (); <-- [1] } /* vRun's success return is a stop reply. */ stop_reply = run_worked ? rs->buf : NULL; add_current_inferior_and_thread (stop_reply); <-- [2] However, current_inferior_ isn't changed at all, and current_inferior_->control.stop_soon is not changed either (NO_STOP_QUIETLY). Could you show me where inf->control.stop_soon is changed from NO_STOP_QUIETLY? -- Yao (齐尧)
On 1 February 2018 at 17:48, Yao Qi <qiyaoltc@gmail.com> wrote: > Omair Javaid <omair.javaid@linaro.org> writes: > > > Heres the gdb log with run (no other command b/w connection and run): > > https://paste.ubuntu.com/26496015/ > > > > One thing suspicious to me is an empty reply to qXfer:threads:read > > w $qXfer:threads:read::0,fff#03 > r $l<?xml version="1.0"?>\n<threads>\n</threads>\n#02 > > OpenOCD claims support "qXfer:threads:read+;", but such reply above may > confuse GDB. In OpenOCD source, I find OpenOCD supports qXfer:threads > unconditionally, but I think it should be changed to support it when > "target->rtos != NULL". This may don't matter. > > > Heres the gdb log with continue + run (after we issue a > > continue/interrupt cycle where inferior PID is set and > > inferior->control.stop_soon = NO_STOP_QUIETLY;) > > https://paste.ubuntu.com/26496048/ > > > > > > > The situation with OpenOCD happens because we ran and set inferior pid > > to null hoping to update it. Later in extended_remote_create_inferior > > called buy run command thread pid gets assigned but we are checking > > inferior->control.stop_soon just before we update the pid and thus it > > remains to STOP_QUIETLY for lifetime of the inferior as this flag is > > only altered by attach command handlers or during call of > > clear_proceed_status > > I still don't understand why inferior->control.stop_soon remains > "STOP_QUIETLY", inferior::control::stop_soon is initialized to > NO_STOP_QUIETLY. I even don't see where it is changed to STOP_QUIETLY. > > I can understand that GDB check inferior_ptid (try to set > inferior->control.stop_soon) first [1], and then update inferior_ptid > later [2], > > if (!have_inferiors ()) > { > /* Clean up from the last time we ran, before we mark the target > running again. This will mark breakpoints uninserted, and > get_offsets may insert breakpoints. */ > init_thread_list (); > init_wait_for_inferior (); <-- [1] > } > > /* vRun's success return is a stop reply. */ > stop_reply = run_worked ? rs->buf : NULL; > add_current_inferior_and_thread (stop_reply); <-- [2] > > However, current_inferior_ isn't changed at all, and > current_inferior_->control.stop_soon is not changed either > (NO_STOP_QUIETLY). Could you show me where inf->control.stop_soon is > changed from NO_STOP_QUIETLY? > > Here is the sequence of change to inf->control.stop_soon gdb) tar ext :3333 infrun.c clear_proceed_status () line: 2903 (inferior->control.stop_soon = NO_STOP_QUIETLY;) infrun.c start_remote () line:3223 (inferior->control.stop_soon = STOP_QUIETLY_REMOTE;) gdb) run infcmd.c:575 calls run_command_1 call () which sets PID to null Further more if we do a continue after connection a call to clear_proceed_status with a valid PID will set inferior->control.stop_soon = NO_STOP_QUIETLY; -- > Yao (齐尧) >
Omair Javaid <omair.javaid@linaro.org> writes: > Here is the sequence of change to inf->control.stop_soon > > gdb) tar ext :3333 > > infrun.c clear_proceed_status () line: 2903 > (inferior->control.stop_soon = NO_STOP_QUIETLY;) > > infrun.c start_remote () line:3223 (inferior->control.stop_soon = > STOP_QUIETLY_REMOTE;) > > gdb) run > > infcmd.c:575 calls run_command_1 call () which sets PID to null > > Further more if we do a continue after connection a call to > clear_proceed_status with a valid PID will set > inferior->control.stop_soon = NO_STOP_QUIETLY; Hi Omair, I manged to reproduce it with GDBserver, 1.exe is a simple program calls sleep, $ ./gdbserver/gdbserver --multi :1234 ./1.exe $ ./gdb ./1.exe (gdb) target extended-remote :1234 Remote debugging using :1234 ... 0x00007ffff7ddb2d0 in ?? () from target:/lib64/ld-linux-x86-64.so.2 (gdb) r The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /scratch/yao/gdb/build-git/x86_64/gdb/1.exe Reading /lib64/ld-linux-x86-64.so.2 from remote target... Reading /lib64/ld-linux-x86-64.so.2 from remote target... Reading /lib64/ld-2.19.so from remote target... Reading /lib64/.debug/ld-2.19.so from remote target... Reading /lib/x86_64-linux-gnu/libc.so.6 from remote target... Reading /lib/x86_64-linux-gnu/libc-2.19.so from remote target... Reading /lib/x86_64-linux-gnu/.debug/libc-2.19.so from remote target... ^C This is consistent to the bug reported https://bugs.launchpad.net/gcc-arm-embedded/+bug/1594341 I set watchpoint on inferior->control.stop_soon and inferior_ptid, so I find that inferior_ptid is reset in generic_mourn_inferior, (gdb) r The program being debugged has been started already. Start it from the beginning? (y or n) y Hardware watchpoint 3: inferior_ptid Old value = {m_pid = 643, m_lwp = 643, m_tid = 0} New value = {m_pid = 0, m_lwp = 643, m_tid = 0} 0x0000000000c83ef6 in generic_mourn_inferior () at /home/yao/SourceCode/gnu/gdb/git/gdb/target.c:3299 3299 inferior_ptid = null_ptid; top?bt 10 #0 0x0000000000c83ef6 in generic_mourn_inferior () at /home/yao/SourceCode/gnu/gdb/git/gdb/target.c:3299 #1 0x0000000000b9d1f2 in remote_mourn (target=0x1839d40 <extended_remote_ops>) at /home/yao/SourceCode/gnu/gdb/git/gdb/remote.c:9431 #2 0x0000000000c621f4 in delegate_mourn_inferior (self=0x1839d40 <extended_remote_ops>) at /home/yao/SourceCode/gnu/gdb/git/gdb/target-delegates.c:1382 #3 0x0000000000c809b6 in target_mourn_inferior (ptid=...) at /home/yao/SourceCode/gnu/gdb/git/gdb/target.c:2397 #4 0x0000000000b9cd45 in remote_kill (ops=0x1839d40 <extended_remote_ops>) at /home/yao/SourceCode/gnu/gdb/git/gdb/remote.c:9302 #5 0x0000000000c5fd4e in delegate_kill (self=0x1839d40 <extended_remote_ops>) at /home/yao/SourceCode/gnu/gdb/git/gdb/target-delegates.c:1015 #6 0x0000000000c7a905 in target_kill () at /home/yao/SourceCode/gnu/gdb/git/gdb/target.c:423 #7 0x0000000000a21025 in kill_if_already_running (from_tty=1) at /home/yao/SourceCode/gnu/gdb/git/gdb/infcmd.c:522 #8 0x0000000000a211cd in run_command_1 (args=0x0, from_tty=1, run_how=RUN_NORMAL) at /home/yao/SourceCode/gnu/gdb/git/gdb/infcmd.c:575 #9 0x0000000000a2183f in run_command (args=0x0, from_tty=1) at /home/yao/SourceCode/gnu/gdb/git/gdb/infcmd.c:688 however, this leads me thinking that why don't we reset inferior too? Note that generic_mourn_inferior calls exit_inferior_1, where various fields of inferior are "reset". The patch below fixes the problem with gdbserver, does it work with you on OpenOCD? -- Yao (齐尧) From 854cca001e56dd40f3e5e5118d1e25ffa06a643b Mon Sep 17 00:00:00 2001 From: Yao Qi <yao.qi@linaro.org> Date: Tue, 6 Feb 2018 14:45:08 +0000 Subject: [PATCH] Reset inferior::control on inferior exit When we kill an inferior, the inferior is not deleted. What is more, it is reused when the new process is created, so we need to reset inferior's state when it exits. gdb: 2018-02-06 Yao Qi <yao.qi@linaro.org> * inferior.c (exit_inferior_1): Reset inf->control. diff --git a/gdb/inferior.c b/gdb/inferior.c index 38b7369..880f25d 100644 --- a/gdb/inferior.c +++ b/gdb/inferior.c @@ -224,6 +224,8 @@ exit_inferior_1 (struct inferior *inftoex, int silent) } inf->pending_detach = 0; + /* Reset it. */ + inf->control = {NO_STOP_QUIETLY}; } void
On 6 February 2018 at 19:47, Yao Qi <qiyaoltc@gmail.com> wrote: > Omair Javaid <omair.javaid@linaro.org> writes: > > > Here is the sequence of change to inf->control.stop_soon > > > > gdb) tar ext :3333 > > > > infrun.c clear_proceed_status () line: 2903 > > (inferior->control.stop_soon = NO_STOP_QUIETLY;) > > > > infrun.c start_remote () line:3223 (inferior->control.stop_soon = > > STOP_QUIETLY_REMOTE;) > > > > gdb) run > > > > infcmd.c:575 calls run_command_1 call () which sets PID to null > > > > Further more if we do a continue after connection a call to > > clear_proceed_status with a valid PID will set > > inferior->control.stop_soon = NO_STOP_QUIETLY; > > Hi Omair, > I manged to reproduce it with GDBserver, 1.exe is a simple program calls > sleep, > > $ ./gdbserver/gdbserver --multi :1234 ./1.exe > $ ./gdb ./1.exe > (gdb) target extended-remote :1234 > Remote debugging using :1234 > ... > 0x00007ffff7ddb2d0 in ?? () from target:/lib64/ld-linux-x86-64.so.2 > (gdb) r > The program being debugged has been started already. > Start it from the beginning? (y or n) y > Starting program: /scratch/yao/gdb/build-git/x86_64/gdb/1.exe > Reading /lib64/ld-linux-x86-64.so.2 from remote target... > Reading /lib64/ld-linux-x86-64.so.2 from remote target... > Reading /lib64/ld-2.19.so from remote target... > Reading /lib64/.debug/ld-2.19.so from remote target... > Reading /lib/x86_64-linux-gnu/libc.so.6 from remote target... > Reading /lib/x86_64-linux-gnu/libc-2.19.so from remote target... > Reading /lib/x86_64-linux-gnu/.debug/libc-2.19.so from remote target... > ^C > > This is consistent to the bug reported > https://bugs.launchpad.net/gcc-arm-embedded/+bug/1594341 > > I set watchpoint on inferior->control.stop_soon and inferior_ptid, so I > find that inferior_ptid is reset in generic_mourn_inferior, > > (gdb) r > The program being debugged has been started already. > Start it from the beginning? (y or n) y > Hardware watchpoint 3: inferior_ptid > > Old value = {m_pid = 643, m_lwp = 643, m_tid = 0} > New value = {m_pid = 0, m_lwp = 643, m_tid = 0} > 0x0000000000c83ef6 in generic_mourn_inferior () at > /home/yao/SourceCode/gnu/gdb/git/gdb/target.c:3299 > 3299 inferior_ptid = null_ptid; > top?bt 10 > #0 0x0000000000c83ef6 in generic_mourn_inferior () at > /home/yao/SourceCode/gnu/gdb/git/gdb/target.c:3299 > #1 0x0000000000b9d1f2 in remote_mourn (target=0x1839d40 > <extended_remote_ops>) at /home/yao/SourceCode/gnu/gdb/ > git/gdb/remote.c:9431 > #2 0x0000000000c621f4 in delegate_mourn_inferior (self=0x1839d40 > <extended_remote_ops>) at /home/yao/SourceCode/gnu/gdb/ > git/gdb/target-delegates.c:1382 > #3 0x0000000000c809b6 in target_mourn_inferior (ptid=...) at > /home/yao/SourceCode/gnu/gdb/git/gdb/target.c:2397 > #4 0x0000000000b9cd45 in remote_kill (ops=0x1839d40 > <extended_remote_ops>) at /home/yao/SourceCode/gnu/gdb/ > git/gdb/remote.c:9302 > #5 0x0000000000c5fd4e in delegate_kill (self=0x1839d40 > <extended_remote_ops>) at /home/yao/SourceCode/gnu/gdb/ > git/gdb/target-delegates.c:1015 > #6 0x0000000000c7a905 in target_kill () at /home/yao/SourceCode/gnu/gdb/ > git/gdb/target.c:423 > #7 0x0000000000a21025 in kill_if_already_running (from_tty=1) at > /home/yao/SourceCode/gnu/gdb/git/gdb/infcmd.c:522 > #8 0x0000000000a211cd in run_command_1 (args=0x0, from_tty=1, > run_how=RUN_NORMAL) at /home/yao/SourceCode/gnu/gdb/git/gdb/infcmd.c:575 > #9 0x0000000000a2183f in run_command (args=0x0, from_tty=1) at > /home/yao/SourceCode/gnu/gdb/git/gdb/infcmd.c:688 > > however, this leads me thinking that why don't we reset inferior too? > Note that generic_mourn_inferior calls exit_inferior_1, where various > fields of inferior are "reset". The patch below fixes the problem with > gdbserver, does it work with you on OpenOCD? > > -- > Yao (齐尧) > From 854cca001e56dd40f3e5e5118d1e25ffa06a643b Mon Sep 17 00:00:00 2001 > From: Yao Qi <yao.qi@linaro.org> > Date: Tue, 6 Feb 2018 14:45:08 +0000 > Subject: [PATCH] Reset inferior::control on inferior exit > > When we kill an inferior, the inferior is not deleted. What is more, it > is reused when the new process is created, so we need to reset inferior's > state when it exits. > Hi Yao, Your patch fixes the issue with openOCD stub. I was a little reluctant to make a generic change with regards to reseting inferior control structure. If there isnt a need to preserve inferior control structure in any case then your change is the right solution. gdb: > > 2018-02-06 Yao Qi <yao.qi@linaro.org> > > * inferior.c (exit_inferior_1): Reset inf->control. > > diff --git a/gdb/inferior.c b/gdb/inferior.c > index 38b7369..880f25d 100644 > --- a/gdb/inferior.c > +++ b/gdb/inferior.c > @@ -224,6 +224,8 @@ exit_inferior_1 (struct inferior *inftoex, int silent) > } > > inf->pending_detach = 0; > + /* Reset it. */ > + inf->control = {NO_STOP_QUIETLY}; > } > > void >
On Thu, Feb 8, 2018 at 10:08 AM, Omair Javaid <omair.javaid@linaro.org> wrote: > Hi Yao, > > Your patch fixes the issue with openOCD stub. I was a little reluctant to > make a generic change with regards to reseting inferior control structure. > > If there isnt a need to preserve inferior control structure in any case then > your change is the right solution. > I opened PR 22849 for this issue. Pushed patch to both master and 8.1 branch. -- Yao (齐尧)
diff --git a/gdb/remote.c b/gdb/remote.c index 5ac84df..3387e1c 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -9688,13 +9688,16 @@ Remote replied unexpectedly while setting startup-with-shell: %s"), running again. This will mark breakpoints uninserted, and get_offsets may insert breakpoints. */ init_thread_list (); - init_wait_for_inferior (); } /* vRun's success return is a stop reply. */ stop_reply = run_worked ? rs->buf : NULL; add_current_inferior_and_thread (stop_reply); + /* We have called add_current_inferior_and_thread above, + call init_wait_for_inferior before new inferior begins. */ + init_wait_for_inferior (); + /* Get updated offsets, if the stub uses qOffsets. */ get_offsets (); }