Debugging remotely with gdbserver
This year has been an awkward one. All COVID-19 situation has been changing a lot the way we work. Suddenly everyone needs to start to work remotely and learn new tools to do so. I had been learning a lot of terminal tools and using a minimal graphical interface as much as possible in my daily activities, just for fun. So this transition to remote work was, basically, in my environment, with an ssh connection in the middle. One of the tools that I’ve started to use more often was gdbserver.
In this guide, I am going to give you a quite basic tutorial on how to use gdbserver to debug your Linux application.
What is the gdbserver
“Remote debugging” is the process of debugging an application running on a different machine. The developer’s system is called the host machine, and the machine running the application is the target.
The gdbserver is a tool to work with the gdb (GNU Debugger tool) remotely. It provides probes and all the necessary tools to debug an application and connect it with external gdb, and by external, I mean in any machine.
So gdbserver only joins with the application and wait for gdb to connect.
The gdbserver receives the commands from a serial line or a network socket. Here I’m going to show how to use it through the network. Notice: You must compile your application with debug symbols (-g option on compile) to get some useful information, as we did in the [previous post]:(2019-11-16-core_dump.md).
(target machine)$ gdbserver localhost:1234 app_exec
Connect with gdb
On the gdb, you need the same binary running on the gdbserver and the source code. On the code folder, run the gdb passing the binary as a parameter.
(host machine)$ gdb app_exec
If your application has a lot of shared libraries, take a look at the sysroot command to load them.
Now you need to connect the gdb to your server. For this, use the command remote.
(inside gdb-host)$ target remote 192.168.1.10:1234
With the command above, you set your target as remote passing the IP and port address to it.
Commands to control the flow of your application
After you connect the gbd to gbdserver, you should be able to control your application. For these, you can use all the features that you are used to, e.g., as program breakpoint, data breakpoints, step, run, backtrace.
help: list command classes
Basic program flow
- run: run the program with current arguments
- cont: continue the program
- step: single step at the program; step into functions
- next: step by step over functions
- finish: finish current function’s execution
- kill: kill current executing program
- quit: quit gdb
- info breakpoints: show breakpoints
- delete 1: delete a breakpoint by its number
- delete: delete all breakpoints
- tbreak <function|line>: set a temporary breakpoint
- break <function>: set a breakpoint on a function. Ex.: “break main”
- break <number>: set a breakpoint on a line number . Ex.: “break 124”
- break <file>:<line>: set breakpoint at file and line
- watch expression: set software watchpoint on variable
- info watchpoints: show current watchpoints
- bt: print stack backtrace
- frame: show current execution position (frame)
- frame <number>: go to the frame number
- up: move up stack trace (towards main)
- down: move down stack trace (away from main)
- info locals: print automatic variables in frame
- info args: print function parameters
- print expression: print expression, added to value history
- ptype name: print type definition
- set variable = expression: assign value