Debugging Souce Code with Assembly

If we compile C program with -g flag, it tells GCC to include debugging symbols inside the resulting binary (a.out by default). These symbols live in a special section of the ELF file (like .debug_info, .debug_line, .debug_str, etc.) and contain metadata that maps machine instructions back to your original source code.

This allows us to see corresponding source along with assembly while debugging with GDB.

Let’s take this program

// firstprog.c
#include<stdio.h>

int main()
{
	int i;
	for (i=0; i<10; i++) {
		printf("Hello, World!\n");
	}
}
sanketh@sanketh-81de:~/assembly/gdb$ gcc -g firstprog.c
sanketh@sanketh-81de:~/assembly/gdb$ readelf -S a.out | grep debug
  [28] .debug_aranges    PROGBITS         0000000000000000  0000303b
  [29] .debug_info       PROGBITS         0000000000000000  0000306b
  [30] .debug_abbrev     PROGBITS         0000000000000000  00003105
  [31] .debug_line       PROGBITS         0000000000000000  00003159
  [32] .debug_str        PROGBITS         0000000000000000  000031bc
  [33] .debug_line_str   PROGBITS         0000000000000000  00003295

We can see the source code using list command

(-q flag just tells gdb not to print version and some info on startup)

$ gdb -q ./a.out
Reading symbols from ./a.out...
(gdb) list
1	#include<stdio.h>
2
3	int main()
4	{
5		int i;
6		for (i=0; i<10; i++) {
7			printf("Hello, World!\n");
8		}
9	}

You can even control the detail level: • -g1: minimal info (function names, line numbers) • -g2: normal (default) — enough for GDB • -g3: adds macro

We can also

gcc -g -O0 -Wall -o prog prog.c

-0O means no optimizations, which will prevent reordering of instructions. Because optimization (-O2, -O3) can reorder or remove variables, making debugging confusing.

GDB Layouts

GDB has a Text User Interface (TUI) mode that lets you see source code, assembly, and registers in split or full-screen views.

It’s very useful when stepping line-by-line or instruction-by-instruction.

You enter TUI mode using:

(gdb) layout [mode]

Available Layouts

CommandViewDescription
layout srcSource viewShows only C source lines (if compiled with -g)
layout asmAssembly viewShows disassembly around current instruction
layout splitSplit viewShows both source + assembly side by side
layout regsRegisters viewShows CPU registers (RAX, RBP, etc.)
layout nextCycle layoutsSwitch to the next available layout (GDB switches to the next view mode in this order: src → asm → split → regs → src → …)

GDB Navigation & Stepping Commands

1. Source-Level (C) Navigation

These commands work on C source lines when the binary is compiled with -g.

CommandShortMeaningSteps Into?Description
nextnNext line❌ NoExecutes the next C line, skipping over function calls.
stepsStep into✅ YesExecutes the next C line, enters called functions.
finishFinish current functionRuns until the current function returns.
continuecContinue executionRuns until next breakpoint or program exit.
untiluRun until a specific lineContinue until a specific line number or loop ends.

2. Assembly-Level Navigation

These work on individual machine instructions, not source lines.

Ideal for reverse engineering or checking compiler output.

CommandShortMeaningSteps Into?Description
nextiniNext instruction❌ NoExecute one assembly instruction, skip over calls.
stepisiStep instruction✅ YesExecute one instruction, enters called functions.
untiluUntil addressRun until a specified instruction address.

3. Breakpoints & Execution Flow

CommandShortDescription
break <line/function>bSet a breakpoint. Example: b main or b 12.
info breakpointsinfo bList all breakpoints.
delete <num>dRemove a breakpoint.
disable / enableTemporarily turn breakpoints off/on.
runrStart program execution.
continuecResume execution after breakpoint.
finishRun until current function returns.
killStop the program being debugged.
quitqExit GDB.

4. Viewing Context While Navigating

CommandDescription
list or lShow source lines around current location.
layout srcShow C source view (TUI).
layout asmShow disassembly view.
layout splitShow both C and assembly views.
info registersShow CPU registers.
x/i $pcShow current instruction.
disassemble /sShow mixed C and assembly view.