This repository provides a comprehensive reference for using GCC (GNU Compiler Collection) and GDB (GNU Debugger) for compiling and debugging C programs.
- Compile a C program:
gcc main.c -o program
- Enable debugging information:
gcc -g main.c -o program
- Enable warnings during compilation:
gcc -Wall main.c -o program
- Treat warnings as errors:
gcc -Werror main.c -o program
-
Start GDB with a Text User Interface (TUI):
shortcut in GDB terminal: ctrl+x+a
gdb --tui
-
View source code:
list
-
View the type of a variable:
whatis <variable>
-
View members of a struct variable:
ptype <variable>
-
Dereference a pointer:
* <pointer_name>
-
Set a temporary breakpoint:
tbreak
-
List all breakpoints:
info breakpoints
-
Delete a breakpoint:
delete <breakpoint_num>
-
Redirect GDB output:
tty <path>
-
Set a conditional breakpoint:
b <file_name>:<line_number> if <condition>
-
Jump directly to execution:
advance <function_name or filename:line_num>
-
Execute until a specific line:
until <function_name or filename:line_num>
-
Watch a variable for changes:
watch <variable_name>
-
Enable/disable a breakpoint:
enable <breakpoint_num> disable <breakpoint_num>
-
Save breakpoints to a file:
save breakpoints <file_name.txt>
-
Load breakpoints from a file:
source <file_name.txt>
-
Display changes in a variable:
display <variable_name>
-
View list of displayed variables:
info display
-
Remove a variable from display list:
undisplay <display_num>
- Backtrace to see the call stack:
bt
- Finish the current stack frame:
finish
- Navigate up/down in the call stack:
up down
-
Segmentation fault: Occurs when a program accesses memory it does not own.
-
Stack overflow: Happens when there is excessive memory usage in the call stack.
Get help for a specific command: ```bash help
-
Delta debugging: Use multiple breakpoints to isolate errors.
-
Calling functions within GDB:
call <function_name(arg...)>
-
Attaching GDB to a running process:
#Get process ID: ps aux | grep <name> #Attach to a process: gdb -p <process_id> #Detach from a process: detach
-
Handling core dumps:
#Set unlimited core dump size: sudo ulimit -c unlimited #Check core dump size: ulimit -c #Install necessary packages sudo apt install systemd-coredump #View core dump files coredumpctl dump coredumpctl gdb
- Set commands to execute automatically at breakpoints:
commands <breakpoint_num> print <variable> bt end
-
Create a script for GDB commands:
File name: .gdbinit Add commands inside the file.
-
Set a variable value:
set var <variable_name> = <value>
-
Reverse Debugging:
target record-full reverse-next
-
Debugging multithreaded programs:
- View Threads:
info threads
- Switch to a specific thread:
thread <thread_num>
- View Threads:
- Finish executing the current function:
finish
- Prints the value in hexadecimal:
print/x n
- Directly examing memory: the x command:
x &i
- Read watchpoint for a variable:
rwatch <varaiable>
- Read and write watchpoint for a variable:
awatch <varaiable>
- Set logging into file:
set logging on
Note GDB saves all output from this point in a text file called gdb.txt that resides in the directory in which you are running GDB
A “core dump” is a snapshot of memory at the instant the program crashed, typically saved in a file called “core”.
The core contains the memory contents of the process at the point of the seg-fault including its code segment, data segment, stack segment and heap segment
--> Core dumps allow a user to save a crash for later or off-site analysis, or comparison with other crashes.
--> For embedded computers, it may be impractical to support debugging on the computer itself, so analysis of a dump may take place on a different computer.
Every process has various limits associated with it.
```bash
$ man setrlimit
Bash offers a built-in ulimit through which we can edit these.
Core-file max-size (ulimit -c/RLIMIT_CORE) controls the maximum core file size that can be generated when the process snaps.
```bash
$ ulimit -c unlimited
The core is dumped in the current working directory of the process.
Core files can be examined with gdb, the GNU debugger.
It can read the crash informations, and display (among other things) the backtrace that leads to the crash.
```bash
$ gdb /path/to/binary /path/to/core/file
After gdb finished to read the input and shows its prompt, execute:
```bash
(gdb) backtrace
or
```bash
(gdb) bt
GDB will then output the backtrace.
One possibility is with gdb, if available. This will let the program running:
```bash
(gdb) attach <pid>
(gdb) generate-core-file <optional-filename>
(gdb) detach
Another possibility is to signal the process. This will terminate it, assuming the signal is not caught by a custom signal handler:
```bash
kill -s SIGABRT <pid>
```bash
{
/*
* Alternative:
* char *p = NULL; *p = 0;
*/
abort();
}
Strace is a debugging tool that monitors the system calls made by a program and the signals it receives
```bash
strace <program/command>
```bash
strace -c <program/command>
```bash
strace -e trace='<system_call>' <program/command>
```bash
strace -p <PID>
ltrace is a command-line utility used to trace library calls made by a program. It shows calls to functions in shared libraries, such as libc, along with their arguments and return values. It is particularly useful for debugging issues related to dynamic linking or library usage.
```bash
ltrace <program>