Debugging Running Processes with GDB

This is a continuation of the exploring C articles I started here. This one will focus less on C and more on some obscure commands in GDB.

When compiling a program with gcc or clang, you can pass the -g switch to produce a dsym file along with a debugging version of your program. This allows you to see the original C code when debugging.

To debug a running process, you can use the -p switch:

$ ps
  PID TTY           TIME CMD
  1234 ttys000    0:00.02 -program
$ gdb -p 1234

This will attach to the process, which you can then set breakpoints on and resume it when you are ready.

To get a graphical view of the source, you can use the -tui switch that splits the panel into the source above and the gdb command pallet below.

Once attached, you can use the list command to open up a file to view:

(gdb) list src/file.c:1

The :1 on the end lets GDB know you are looking for a file and not a function. Once viewing your source file, you can use list function_name to navigate to that function.

When your breakpoints are hit, the print function can evalute complex expressions. For example:

(gdb) p strlen(some_text); //outputs the length of the text

Switching gears, to run a program with arguments, use the f command to load the file, and then the r command with any arguments. For example:

$ gdb
(gdb) f program
(gdb) r arg1 arg2

If you have a program that outputs information, you can use tty to have that sent to another window. Open two terminal windows, [1] and [2]. [1] will be where output is placed, [2] will be where we run GDB. In [1], run:

$ tty

In [2], open up GDB and run:

$ gdb
(gdb) tty /dev/some/window
(gdb) r

All program output will now be redirected to terminal [1].

This is not a comprehensive list, but hopefully helps to show that GDB isn't restricted to tediously looking over assembly code.