Restarting the application in remote debugging

I have ported lldb for remotely debugging our target. The lldb is connected to the target simulator using the gdb remote protocol.

$lldb --arch vliw app.elf
(lldb)process connect --plugin gdb-remote connect://localhost:51000

The above command connects the lldb with the target simulator waiting at port ‘51000’. And the debug commands work properly.

But once the execution of the application completes, I am facing the problem in restarting the application for debugging again.

For restarting the application being debugged, I think lldb should send the ‘R’ packet. When would lldb send the ‘R’ packet?

Currently the target simulator sends the SIGTERM signal (T0fthread:0001) after completing the program execution. And on receiving this signal, lldb doesn’t doesn’t display the message “Program exited normally”.

Also when I gave the ‘continue’ command to restart the application debugging again, lldb sends the ‘C0f’ packet.

Thanks,
Chandra Kumar R.

I have ported lldb for remotely debugging our target. The lldb is connected to the target simulator using the gdb remote protocol.

$lldb --arch vliw app.elf
(lldb)process connect --plugin gdb-remote connect://localhost:51000

The above command connects the lldb with the target simulator waiting at port '51000'. And the debug commands work properly.

But once the execution of the application completes, I am facing the problem in restarting the application for debugging again.

For restarting the application being debugged, I think lldb should send the 'R' packet. When would lldb send the 'R' packet?

Currently the target simulator sends the SIGTERM signal (T0fthread:0001) after completing the program execution. And on receiving this signal, lldb doesn't doesn't display the message "Program exited normally”.

The “T0F” means we stopped with a signal. Send a “WXX” packet to indicate the program exited.

Also when I gave the 'continue' command to restart the application debugging again, lldb sends the 'C0f' packet.

Yes, you indicated you stopped with a signal. We often catch signals before they get passed onto the signal handlers and we can decide to not pass on the signal. See “help process handle” for more information, but again, if your process exits with a signal, send a “WXX” packet where XX is the hex exit status of the program.

Greg

Send a “WXX” packet to indicate the program exited.

Thank you. Sending the “WXX”” packet to indicate the program exited worked. I received the following message at the lldb prompt.

Process 1 exited with status = 0

And now to restart the application I gave the ‘run’ command for which I received the error “‘A’ packet returned an error: -1”. When I checked the simulator for this I found that the simulator didn’t receive the ‘A’ packet.

When debugged the lldb, I found that the problem is with the platform that has been chosen for my target. I had made platform “gdb-server” as my default platform explicitly by modifying the “PlatformRemoteGDBServer::Initialize ()” method.

$ lldb --arch vliw workplace/app.elf
Current executable set to ‘workplace/app.elf’ (vliw).
(lldb) target list
Current targets:

  • target #0: /home/chandra/app01/workplace/app.elf ( arch=vliw-unknown-unknown, platform=remote-gdb-server )

Since I was connecting the target simulator using the Process plugin ‘gdb-remote’, the platform “gdb-server” didn’t come into picture of connecting the simulator.

(lldb) process connect --plugin gdb-remote connect://localhost:51000

The connection and the debugging happened through the ‘gdb-remote’ Process plugin. And the problem comes when I restart the program after it terminates with an exit status. I.e. When I give the ‘run’ command to restart the program, the platform “gdb-server” sends the argument packet ‘A’ for program launching. But there is no connection associated with the platform “gdb-server”. Hence lldb gives the following error:

error: ‘A’ packet returned an error: -1

With my existing porting of lldb I am able to connect the simulator and successfully debug a program once. But I am not able to do the following:

  1. Restart the program for debugging with disconnecting the connection.
  2. Send launch command to the simulator from lldb.

Can’t I support the above two features from the ‘gdb-remote’ Process plugin? Can you please suggest the way of supporting the above two features?

Thanks,
Chandra Kumar R.

> Send a “WXX” packet to indicate the program exited.

Thank you. Sending the "WXX"” packet to indicate the program exited worked. I received the following message at the lldb prompt.

Process 1 exited with status = 0

And now to restart the application I gave the 'run' command for which I received the error "'A' packet returned an error: -1". When I checked the simulator for this I found that the simulator didn't receive the 'A' packet.

When debugged the lldb, I found that the problem is with the platform that has been chosen for my target. I had made platform "gdb-server" as my default platform explicitly by modifying the "PlatformRemoteGDBServer::Initialize ()" method.

$ lldb --arch vliw workplace/app.elf
Current executable set to 'workplace/app.elf' (vliw).
(lldb) target list
Current targets:
* target #0: /home/chandra/app01/workplace/app.elf ( arch=vliw-unknown-unknown, platform=remote-gdb-server )

Since I was connecting the target simulator using the Process plugin 'gdb-remote', the platform "gdb-server" didn't come into picture of connecting the simulator.

(lldb) process connect --plugin gdb-remote connect://localhost:51000

The connection and the debugging happened through the 'gdb-remote' Process plugin. And the problem comes when I restart the program after it terminates with an exit status. I.e. When I give the 'run' command to restart the program, the platform "gdb-server" sends the argument packet 'A' for program launching. But there is no connection associated with the platform "gdb-server". Hence lldb gives the following error:

error: 'A' packet returned an error: -1

With my existing porting of lldb I am able to connect the simulator and successfully debug a program once. But I am not able to do the following:

1. Restart the program for debugging with disconnecting the connection.

LLDB doesn't currently support the restart packet ("RXX"). Feel free to add support for it.

2. Send launch command to the simulator from lldb.

The launch command will send the "A" packet which sends the program and arguments. I believe that LLDB will disconnect from the remote server when the process exits, though it doesn't need to.

Can't I support the above two features from the 'gdb-remote' Process plugin? Can you please suggest the way of supporting the above two features?

Currently the "restart" support uses lldb_private::Process primitives like Process::Kill() to kill the current program, then it will just call "Process::Launch()" again. We could modify lldb_private::Process with a few new calls:

bool
Process::SupportsRestart();

Error
Process::Restart();

We would need to query if the current process supports restarting so if you run the "process launch" command and the current process is alive, we would then need to try and restart.

So yes, this is possible, but we don't have any support for restart except for using the current Process primitives.

Greg

We would need to query if the current process supports restarting so if
you run the “process launch” command and the current process is alive,
we would then need to try and restart.

I am working on the support for restarting in remote debugging. When the “process launch” command is run and if the process is alive I am sending the ‘R’ packet. I have attached the file that contains the implementation of Process::Restart() and ProcessGDBRemote::DoRestart(). I wrote these two methods by referring the methods Process::Destroy() and ProcessGDBRemote::DoDestroy().

Now when I run “process launch” command when the process is alive (i.e. at a breakpoint), the ‘R’ packet is sent to the target and also the process launch packets ‘A’ are sent. But I get the error “error: initial process state wasn’t stopped: exited” and the previous breakpoint status message is printed on the console as shown below.

$ lldb --arch vliw-unknown-unknown workplace/app.elf
Current executable set to ‘workplace/app.elf’ (vliw).
(lldb)process connect --plugin gdb-remote connect://localhost:51000
Process 0 connected
(lldb)b main.c:31
breakpoint set --file ‘main.c’ --line 31
Breakpoint created: 1: file =‘main.c’, line = 31, locations = 1
(lldb)run
Process 1 launched: ‘/home/chandra/app01/workplace/app.elf’ (vliw)
Process 1 stopped

  • thread #1: tid = 0x0001, 0x20016440 app.elfmain + 304 at main.c:31, stop reason = breakpoint 1.1 frame #0: 0x20016440 app.elfmain + 304 at main.c:31
    28 for (i=0; i<N; i++)
    29 {
    30 result += i*10;
    → 31 A[i] = result;
    32 }
    33
    (lldb) run
    There is a running process, kill it and restart?: [Y/n]
    Y
    Process 1 launched: ‘/home/chandra/app01/workplace/app.elf’ (vliw)
    error: initial process state wasn’t stopped: exited
    Process 1 stopped
  • thread #1: tid = 0x0001, 0x20016440 app.elfmain + 304 at main.c:31, stop reason = signal SIGSTOP frame #0: 0x20016440 app.elfmain + 304 at main.c:31
    28 for (i=0; i<N; i++)
    29 {
    30 result += i*10;
    → 31 A[i] = result;
    32 }
    33
    (lldb)

On debugging the code, I found - lldb sends the ‘R’ packets, lldb updates the process state for ‘R’ packet response, lldb sends the arguments packet for launching, lldb waits for the process to stop and lldb gets the process state as “eStateExited”.

Below is the communication between lldb and simulator.

(lldb) run
There is a running process, kill it and restart?: [Y/n]
Y
< 17> send packet: $z0,20016440,0#c3
< 1> read packet: +
< 6> read packet: $OK#9a
< 1> send packet: +
< 5> send packet: $R#52
< 1> read packet: +
< 7> read packet: $W00#b7
< 1> send packet: +
< 36> send packet: $QSetSTDIN:2f6465762f7074732f3135#4b
< 1> read packet: +
< 6> read packet: $OK#9a
< 1> send packet: +
< 37> send packet: $QSetSTDOUT:2f6465762f7074732f3135#ac
< 1> read packet: +
< 6> read packet: $OK#9a
< 1> send packet: +
< 37> send packet: $QSetSTDERR:2f6465762f7074732f3135#9d
< 1> read packet: +
< 6> read packet: $OK#9a
< 1> send packet: +
< 21> send packet: $QSetDisableASLR:1#ce
< 1> read packet: +
< 6> read packet: $OK#9a
< 1> send packet: +
< 19> send packet: $QLaunchArch:vliw#9f
< 1> read packet: +
< 6> read packet: $OK#9a
< 1> send packet: +
< 251> send packet: $A240,0,2f686f6d652f6368616e6472612f61707030312f776f726b706c6163652f6170702e656c66#75
< 1> read packet: +
< 6> read packet: $OK#9a
< 1> send packet: +
< 18> send packet: $qLaunchSuccess#a5
< 1> read packet: +
< 6> read packet: $OK#9a
< 1> send packet: +
< 6> send packet: $qC#b4
< 1> read packet: +
< 7> read packet: $QC1#c5
< 1> send packet: +
< 5> send packet: $?#3f
< 1> read packet: +
< 19> read packet: $T11thread:0001;#64
< 1> send packet: +
< 16> send packet: $qfThreadInfo#bb
< 1> read packet: +
< 6> read packet: $m1#9e
< 1> send packet: +
< 16> send packet: $qsThreadInfo#c8
< 1> read packet: +
< 5> read packet: $l#6c
< 1> send packet: +
Process 1 launched: ‘/home/chandra/app01/workplace/app.elf’ (vliw)
error: initial process state wasn’t stopped: exited
Process 1 stopped

  • thread #1: tid = 0x0001, 0x20016440 app.elfmain + 304 at main.c:31, stop reason = signal SIGSTOP frame #0: 0x20016440 app.elfmain + 304 at main.c:31
    28 for (i=0; i<N; i++)
    29 {
    30 result += i*10;
    → 31 A[i] = result;
    32 }
    33
    (lldb)

I doubt my ‘restart’ implementation done with inadequate understanding. It would be very helpful if someone guides me in correcting the ‘restart’ implementation attached with this mail.

Thank you,
Chandra Kumar R.

ProcessRestart.cpp (2.85 KB)

When we re-run, we always currently replace the current Process with a new lldb_private::Process instance. Currently the process state is sticky when it gets set to eStateExited. Why? Because when debugging through GDB server, we sometimes lose connection to the debugserver and it causes us to set the process state to exited with a reason of "debugserver lost connection". If the process was in the middle of doing a step or run, it might try to set the state to stepping, running, or stopped. So we currently stop any Process::SetState(...) calls from succeeding if the state is already exited. You will need to work around this when doing restart. Watch for the state getting set to exited to see who is doing this and make sure that during restart this doesn't happen.

Greg