Operator On The Wire
← Back to Knowledge Base
OOTW / Chapter I - Foundation / 06. Programming & Debugging / 09. Debugging

Debugging

Writing software is only half of the equation. At some point, every developer, reverse engineer and security researcher must answer the question:

What is the program actually doing right now?

Debugging is the process of observing a program while it executes. Instead of merely reading source code, a debugger allows us to pause execution, inspect memory, examine variables and follow the exact path taken by the CPU.

A debugger is one of the most powerful tools available to an operator because it transforms software from a static object into something that can be observed and understood in real time.

Common uses include:

  • Understanding how software works
  • Troubleshooting bugs
  • Reverse engineering applications
  • Analyzing malware
  • Studying operating system internals
  • Investigating security vulnerabilities

Throughout this course we will primarily use debuggers to understand behavior rather than to develop software.


Core Debugging Concepts

Although different debuggers have different interfaces, most of them provide the same fundamental capabilities.

Breakpoints

A breakpoint instructs the debugger to pause execution at a specific location.

For example:

int age = 28;

printf("%d", age);

A breakpoint placed on the printf() line would allow us to inspect the program state immediately before that instruction executes.

Step Into

Executes the next instruction and enters any function that is called.

Main()
 └── CalculateAge()

Using Step Into would move execution into CalculateAge().

Step Over

Executes the current line without entering called functions.

Main()
 └── CalculateAge()

Using Step Over would execute the function and return immediately to the next line in Main().

Continue

Resumes normal execution until another breakpoint is encountered.

Inspecting Variables

Most debuggers allow us to observe the current values of variables while execution is paused.

int age = 28;

The debugger may show:

age = 28

This allows us to verify assumptions about how the program behaves.


Debugging at the Machine Level

While source code is useful, the CPU ultimately executes machine instructions.

Modern debuggers allow us to observe these instructions directly.

For example:

mov eax, 5
add eax, 3

A debugger might show:

eax = 5

After stepping one instruction:

eax = 8

In addition to variables, debuggers commonly expose:

  • CPU registers
  • Memory contents
  • Function calls
  • Return addresses
  • Loaded modules
  • Threads

Conceptually:

Source Code
    │
    ▼
Assembly Instructions
    │
    ▼
CPU Registers
    │
    ▼
Memory

This visibility is what makes debugging such a powerful skill. Whether analyzing malware, reversing software or investigating vulnerabilities, the debugger provides direct insight into what the program is actually doing rather than what we think it is doing.