Learn how debuggers work by building your own one - Sayani Bhattacharjee

Learn how to build a basic debugger from scratch by creating a target program, setting breakpoints, and controlling a child process using ptrace, and explore the internal implementation of step in and step out instructions.

Key takeaways
  • A debugger can be built from scratch by creating a target program, inserting a breakpoint, and controlling a child process using ptrace.
  • ptrace can be used to get the current program counter (PC), set breakpoints, and read registers.
  • To step through a program, insert breakpoints at specific lines and use ptrace to control the child process.
  • A step in instruction is different from a step in on the source code, and both are implemented using breakpoints.
  • A step over instruction can be implemented by inserting a breakpoint at the next line of the source code.
  • A step out instruction can be implemented by inserting a breakpoint at the return address of a function call.
  • The DWARF file can be used to parse function calls and get the program counter.
  • To read variables, the compiler’s symbol table and the DWARF file can be used.
  • The ptrace system call can be used to read and write memory.
  • A debugger can be built using a UI layer, a symbolic layer, and a target layer.
  • Delve, a debugger for Go, provides a UI for debugging and supports commands such as step in, step out, and step over.
  • The internal implementation of step in and step out instructions in Delve involves setting breakpoints at specific lines of code.