I needed to debug a program asynchronously, because it stalled, and Ctrl+C killed gdb, rather than interrupting the program (this is on MinGW/MSYS).
Someone hinted that gdb wouldn't work on Windows in async mode, and indeed it didn't (with the Asynchronous execution not supported on this target. message), but that gdbserver would.
So I try:
$ gdbserver localhost:60000 ./a_.exe 0
Process ./a_.exe created; pid = 53644
Listening on port 60000
(Supplying the 0 as the argument, according to how the manpage says it's done.)
Then in another terminal:
$ gdb ./a_.exe
(gdb) target remote localhost:60000
Remote debugging using localhost:60000
0x76fa878f in ntdll!DbgBreakPoint () from C:\Windows\system32\ntdll.dll
(gdb) continue
Continuing.
[Inferior 1 (Remote target) exited with code 01]
While the original now looks like:
$ gdbserver localhost:60000 ./a_.exe 0
Process ./a_.exe created; pid = 53484
Listening on port 60000
Remote debugging from host 127.0.0.1
Expecting 1 argument: test case number to run.
Child exited with status 1
GDBserver exiting
That is, my program thought that it got no arguments.
Is the manpage wrong?
Yes! "Misleading" is a more fitting term. (Misleading, at least as it applies to this version of gdbserver on this platform.)
The first argument is literally the first argument (argv) given to the inferior. Normally this is the name of the executable. So, the following worked:
$ gdbserver localhost:60000 ./a_.exe whatever 0
That is, the manpage should have said, to be consistent:
target> gdbserver host:2345 emacs emacs foo.txt
I am not able to help you out with gdbserver,
but if you are just looking for a way to interrupt a program running in mingw/msys gdb(Similar to Ctrl+C on linux)
take a look at at Debugbreak
Related
Ubuntu 16.04.4 LTS, GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
I am trying to call a function in a compiled C program and get the following:
"(gdb) call getVarName(someParam)
You can't do that without a process to debug."
There are no other codes or messages.
I can run the program from the shell prompt
jef#ubuntu$ ./program.
I can run the program within gdb after designating the file. Permissions are 777 (just to cover all bases).
Based on research, I set the SHELL with "export SHELL=/bin/bash"
and
set kernal.yama.ptrace_scope = 0 in /etc/sysctl.d/10-ptrace.conf
I still get the same behavior.
I still get the same behavior.
Naturally.
The error you are getting means: you can't do this, unless you are debugging a live process.
This will work:
(gdb) break main
(gdb) run
... GDB is now stopped, *and* you have a live process.
... you *can* call getVarName(...) now
(gdb) call getVarName(...)
(gdb) continue # causes the process to run to end and exit
[Inferior 1 (process 195969) exited normally]
(gdb) # Now you no longer have a live process, so you *again* can't
# call functions in it.
Why is gdb showing that the program exited during its startup, so before to stop at the first breakpoint in the main function ?
Some steps:
$ gdb --cd $programhome -tui -tty $reservedtty --args myprogram
b main
r
gdb shows:
Starting program: myprogram
During startup program exited with code 1.
I already tried to break at exit() function, without success.
Why is gdb exiting before to stop at the first breakpoint in the main function
GDB is not exiting. Your program does.
It does exit before reaching main.
This can happen for a few reasons, such as:
Corrupt binary -- the kernel rejects it in execve system call for some reason and not a single instruction of the program actually runs.
The dynamic linker rejects it (e.g. because some required library or symbol is missing)
Your shell refuses to execute the program (bad ~/.bashrc, bad $PATH, etc).
You can narrow down the actual cause by running the program outside GDB (does it run?), running without ~/.bashrc, using (gdb) catch syscall exit_group (on Linux), etc.
There was a permission issue accessing the secondary terminal port.
The gdb is being started with the parameter -tty which switches the input/output to another tty port (in that case pseudo: pts).
When the two terminals are opened by different users, that problem occurs, even if after the first logon you change the user with su command, the first user logged needed to be the same among the two ttys.
If I start a normal 'gdb' session, then I can reach STDIN and see STDOUT directly in the terminal:
$ gdb wc
GNU gdb (Gentoo 7.10.1 vanilla) 7.10.1
...
gdb> run
Starting program: /usr/bin/wc
asdf
1 1 5
[Inferior 1 (process 28131) exited normally]
gdb> quit
$
Can I do the same with a gdbserver???
Here is what I have tried (gdbserver):
$ gdbserver /dev/ttyS0 wc
Process wc created; pid = 28156
Listening on port 2345
and client:
$ gdb
GNU gdb (Gentoo 7.10.1 vanilla) 7.10.1
...
gdb> c
Continuing.
Program received signal SIGINT, Interrupt.
0x00007ffff7ddbc40 in _start () from target:/lib64/ld-linux-x86-64.so.2
gdb>
But, it seems like STDIN/STDOUT is not being connected when using the gdbserver.
How can I run remote debugging over the serial line, and also access STDIN/STDOUT of the application that I'm debugging over the same serial line??
How can I run remote debugging over the serial line, and also access STDIN/STDOUT of the application that I'm debugging over the same serial line??
You'll need to use screen or tmux to multiplex gdb<->gdbserver and keyboard->application traffic over a single serial line.
I am remote debugging a Stellaris Launchpad. I use OpenOCD to connect to the stellaris and then connect GDB to the server provided by openOCD. I use Open On-Chip Debugger 0.10.0-dev-00002-g79fdeb3 (2015-07-09-23:28). GDB is the one from arm-gcc-none-eabi, the 4_9-2015q1 release.
I invoke openOCD like this:
/usr/local/bin/openocd --file \
/usr/local/share/openocd/scripts/board/ek-lm4f120xl.cfg \
>> openocdLog.txt 2>&1 &
And then GDB like this:
arm-none-eabi-gdb proj//debug/exec -x gdb//gdb.script
gdb/gdb.script contains:
set remotetimeout 10000
target extended-remote :3333
monitor reset halt
load
monitor reset init
The problem is that whenever I hit control+c GDB disconnects. Normally this would halt the remote, but GDB just disconnects:
(gdb) cont
Continuing.
^CError detected on fd 6
Remote communication error. Target disconnected.: Interrupted system call.
(gdb)
OpenOCD has the following things to say, this one while GDB is launching:
Warn : keep_alive() was not invoked in the 1000ms timelimit. GDB alive packet not sent! (1258). Workaround: increase "set remotetimeout" in GDB
Which is weird, considering the gdb/gdb.script file forces remotetimeout to an insanly large number.
And when pressing control+c openOCD says:
Debug: 2602 5089 hla_interface.c:119 hl_interface_quit(): hl_interface_quit
So, how do I resolve this? How can I make GDB halt the remote instead of disconnecting when pressing control+c?
The problem was OpenOCD being too bleeding edge. I had issues with 0.6.1, but version 0.7.0 of OpenOCD works great.
In Linux, GDB doesn't allow set new-console on and in stead uses something called tty. With
set inferior-tty /dev/pts/[number of an active console],
in a .gdbinit file (requires editing the number every time) it redirects std::cout, but std::cin isn't working properly. It just interprets my input as if I'm sending a bash command and reports an error, and my program continues to wait for input. I can no longer type in the console after that, so I assume std::cin is being redirected, but doesn't work properly.
I tried looking up how to launch a terminal from the application itself. I could only find this answer, which also mentions a bug that it doesn't redirect input.
Is there any way to fix this issue and redirect std::cin (and std::cout) to a Linux terminal properly when debugging?
Background info: What I'm trying to do should be simple. Print a > in front of user input before using std::cin. I have simple code in place that prints the >, flushes cout and then calls getline(). It works when just running the program normally. But sadly, GDB refuses to flush the stream when there isn't a newline, so it doesn't print the >, ignores the first character of the user input and then does prints the >, immediately followed by the error message that my program sends because of the mutilated input string.
In Windows, I've solved it by making a .gdbinit file with set new-console on. This causes GDB to use a Windows console in stead of its own and that works as intended.
If you need to start the debugging after the program has a chance to pause, just run the program in a terminal, and then gdb - your-program-pid in another terminal. Otherwise there's a sequence of steps which is faster to do than to describe.
Start two terminal windows.
In one terminal, figure out the PID of the shell. ps should tell you.
In the other terminal, use these commands
$ gdb - pid-of-the-other-shell
(gdb) br main
(gdb) c
Now you have gdb attached to your shell in another terminal. Not very useful.
In the first terminal, type at the shell prompt
$ exec your-program
Now you have one terminal running gdb and another terminal running your program under gdb, stopped at main. Bear in mind that when the program exits, its terminal window will close. If you don't want this, start a second level shell in the first terminal and attach gdb to it.
You can also use set inferior-tty command, but you must make sure the other tty exists and no other program attempts to read from it. The easiest way is to run a shell in another terminal and give it a while true; do sleep 1000; done command. Note that you may get warning: GDB: Failed to set controlling terminal: Operation not permitted messages. They are harmless.
You can use gdb's multiprocess debugging feature and a terminal emulator like xterm to do this. (gnome-terminal won't work so well as explained later)
prompt.c
#include <stdio.h>
int main()
{
enum {
N = 100,
};
char name[N];
printf("> ");
scanf("%s", name);
printf("Hi, %s\n", name);
return 0;
}
xterm.gdb
set detach-on-fork off
set target-async on
set pagination off
set non-stop on
file /usr/bin/xterm
# -ut tells xterm not to write a utmp log record
# which involves root privileges
set args -ut -e ./prompt
catch exec
run
Sample Session
$ gdb -q -x xterm.gdb
Catchpoint 1 (exec)
<...>
[New process 7073]
<...>
Thread 0x7ffff7fb2780 (LWP 7073) is executing new program: /home/scottt/Dropbox/stackoverflow/gdb-stdin-new-terminal/prompt
Reading symbols from /home/scottt/Dropbox/stackoverflow/gdb-stdin-new-terminal/prompt...done.
Catchpoint 1 (exec'd /home/scottt/Dropbox/stackoverflow/gdb-stdin-new-terminal/prompt), 0x0000003d832011f0 in _start () from /lib64/ld-linux-x86-64.so.2
(gdb) inferior 2
[Switching to inferior 2 [process 7073] (/home/scottt/Dropbox/stackoverflow/gdb-stdin-new-terminal/prompt)]
[Switching to thread 2 (Thread 0x7ffff7fb2780 (LWP 7073))]
#0 0x0000003d832011f0 in _start () from /lib64/ld-linux-x86-64.so.2
(gdb) break prompt.c:11
Breakpoint 2 at 0x4004b4: file prompt.c, line 11.
(gdb) continue &
Continuing.
(gdb)
Breakpoint 2, main () at prompt.c:11
11 printf("> ");
next
12 scanf("%s", name);
(gdb) next
13 printf("Hi, %s\n", name);
A new xterm window will appear after executing gdb -q -x xterm.gdb and you can interact with prompt inside it without interfering with GDB.
Related GDB commands:
inferior 2 switches the process GDB's debugging much like the thread command switches threads. (GDB: Debugging Multiple Inferiors and Programs)
continue & means to continue executing in the background. (GDB: Background Execution)
I used xterm because gnome-terminal uses dbus-launch to ask another process to launch the new terminal outside of the parent-child process relationship that GDB relies on.