GDB (GNU Debugger) is a powerful tool used for debugging programs written in languages like C and C++. It allows developers to examine and manipulate the execution of a program, helping to identify and fix bugs, inspect variable values, trace function calls, and control program flow. GDB is a crucial tool for anyone working with assembly, C, or C++ in low-level programming and computer organization.
In the context of Computer Organization and Assembly Language (COAL), GDB is essential for debugging assembly programs, especially when you need to inspect the contents of registers, step through assembly instructions, or track down issues with memory management.
GDB lets you:
To start debugging a program with GDB, you need to first compile your program with debugging information enabled. This can be done by using the -g flag with the compiler (e.g., GCC for C programs). This flag includes debugging symbols that help GDB understand the structure of your program.
For example, to compile a C program:
gcc -g program.c -o program
Then, you can start GDB with the following command:
gdb ./program
This launches GDB and loads your program, allowing you to interact with it via GDB commands.
Once you're inside GDB, there are several useful commands for interacting with your program. Let’s look at some of the most commonly used commands.
run command:
(gdb) run
This will start executing your program from the beginning. If your program takes arguments, you can pass them after the run command:
(gdb) run arg1 arg2
(gdb) break function_name
(gdb) break filename.c:line_number
For example:
(gdb) break main.c:25
(gdb) info breakpoints
(gdb) step
(gdb) next
To examine the value of a variable:
(gdb) print variable_name
For example:
(gdb) print x
To examine a register (important for assembly language programs):
(gdb) info registers
This command will display the contents of all registers (e.g., eax, ebx, etc.).
If you want to print a specific register:
(gdb) print $eax
You can examine memory directly in GDB using the x command. For example, to examine 4 bytes of memory at a specific address:
(gdb) x/4xb 0xaddress
x tells GDB to examine memory.4 means you want to inspect 4 units.x means examining the memory as bytes (you can use other formats like h for halfwords, w for words).0xaddress is the memory address you want to examine.You can modify the value of a variable during debugging using the set command. For example, to set the variable x to 10:
(gdb) set variable x = 10
If you want to change the value of a register, use:
(gdb) set $eax = 42
Once you have hit a breakpoint and inspected or modified values, you can continue the execution of the program with:
(gdb) continue
To exit GDB when you are done debugging, use:
(gdb) quit
When debugging assembly programs, you can disassemble your code in GDB to view the corresponding assembly instructions. To disassemble the current function:
(gdb) disassemble
To disassemble a specific function:
(gdb) disassemble function_name
If your program crashes or you want to trace the call stack to see how you arrived at a particular point in the program, use the backtrace or bt command:
(gdb) backtrace
This will show the sequence of function calls that led to the current location, which is especially helpful in debugging segmentation faults or crashes.
Watchpoints are like breakpoints, but they pause the program whenever a specific variable changes. To set a watchpoint:
(gdb) watch variable_name
For example:
(gdb) watch x
This will stop the program whenever the variable x is modified.
When debugging assembly programs, GDB is especially powerful because it allows you to step through assembly instructions and inspect the contents of registers.
disassemble to view the assembly instructions.info registers to check the contents of registers like eax, ebx, etc.stepi or nexti to step through the program one instruction at a time. This is very useful when debugging assembly-level code to identify where things go wrong.
(gdb) stepi ; Step by one instruction
(gdb) nexti ; Step over one instruction
When working with Assembly Language, GDB can be incredibly useful to inspect how your Assembly instructions are executing, check the values in registers, and monitor how memory is being accessed.
Let's say you have a simple Assembly program in x86 architecture that adds two numbers:
section .data
num1 db 10
num2 db 20
section .text
global _start
_start:
; Load values into registers
MOV AL, [num1] ; Load num1 into AL
ADD AL, [num2] ; Add num2 to AL
MOV [num1], AL ; Store the result back into num1
; Exit the program
MOV EAX, 1 ; SYS_exit system call
MOV EBX, 0 ; Exit status
INT 0x80 ; Invoke system call
Assemble the Code:
Assemble the program and create an executable.
nasm -f elf32 my_program.asm -o my_program.o
ld -m elf_i386 -s -o my_program my_program.o
Start GDB: Open the program with GDB.
gdb ./my_program
Set Breakpoints:
Set a breakpoint at the entry point, or at specific lines in the code (e.g., before the ADD instruction).
(gdb) break _start
Run the Program: Start running the program inside GDB.
(gdb) run
Inspect Registers: Once the breakpoint is hit, you can inspect the CPU registers to see the state of the program.
(gdb) info registers
This will show you the values of all the registers, including EAX, which stores the result of the addition.
Step Through the Code: Use the next or step commands to execute the instructions one by one and observe the behavior.
(gdb) step
Print Variable Values:
You can also print values stored in memory (such as the result in num1).
(gdb) print $al # Print the value in the AL register
(gdb) print num1 # Print the value at the memory address of num1
Continue Execution: If you're satisfied with the current state, you can resume execution.
(gdb) continue
Exit GDB: Once you've finished debugging, you can exit GDB.
(gdb) quit
GDB is an invaluable tool for debugging assembly language programs, C programs, and other low-level code. By using GDB, you can inspect and modify registers, step through assembly instructions, examine memory, set breakpoints, and even modify variables during execution. Whether you're debugging simple logic errors or complex memory issues, GDB offers the necessary functionality to analyze and fix bugs in your code efficiently.
Open this section to load past papers