Notes on GDB

This is a living document containing my notes on GDB usage

gdbinit

The script ~/.gdbinit will always be run when starting gdb. A good default is:

set width 0
set height 0
set print pretty on
set disassembly-flavor intel
set confirm off

These will

  • Disable paging
  • Turn on pretty printing
  • Set the assembly syntax to Intel
  • Remove the confirmation message when exiting

Debugging Levels

If the code has a lot of macros, consider using debug info level of -g3. This allows gdb to expand macros when debugging

Passing Arguments

To pass arguments to a program launched with gdb, use the --args switch with the program name as the first argument:

gdb --args a.out --switch1 --switch2=somesetting

Then in gdb you can see arguments anytime:

(gdb) show args
" --switch1 --switch2=somesetting"

Conditonal Breakpoints

Breakpoints can have conditions. If I want to break some_function(int n), but only when n == 3:

(gdb) break some_function if n == 3

Scripting

Consider the following file gdbscript:

# gdbscript
b 12
b other.c:45
r

When run with gdb -x gdbscript a.out, this will set breakpoints and start the program.

Caveats

Everything in gdb scripting is global. Be careful with function and variable definitions

Commands

Commands will be run on every breakpoint. With the following snippet of C code:

int n = 0;

# starts at line 32
for (int i = 0; i < 10; i++) {
    ++n;
}

The following gdbscript will print every other value of i during iteration:

# gdbscript
set $x = 0
b 32
commands
    set $x = $x + 1
    if $x % 2 == 0
        printf "n: %d\n", n
    end
    c
end
run

Macros

Macros can be defined in gdbscript to be used during a debugging session. Here’s an interesting macro that prints the values of the x86 eflags register (Taken from adacore)

define eflags
    printf "     OF <%d>  DF <%d>  IF <%d>  TF <%d>",\
           (($eflags >> 0xB) & 1), (($eflags >> 0xA) & 1), \
           (($eflags >> 9) & 1), (($eflags >> 8) & 1)
    printf "  SF <%d>  ZF <%d>  AF <%d>  PF <%d>  CF <%d>
",\
           (($eflags >> 7) & 1), (($eflags >> 6) & 1),\
           (($eflags >> 4) & 1), (($eflags >> 2) & 1), ($eflags & 1)
    printf "     ID <%d>  VIP <%d> VIF <%d> AC <%d>",\
           (($eflags >> 0x15) & 1), (($eflags >> 0x14) & 1), \
           (($eflags >> 0x13) & 1), (($eflags >> 0x12) & 1)
    printf "  VM <%d>  RF <%d>  NT <%d>  IOPL <%d>
",\
           (($eflags >> 0x11) & 1), (($eflags >> 0x10) & 1),\
           (($eflags >> 0xE) & 1), (($eflags >> 0xC) & 3)
end

This macro can then be run at any time during a debugging session

(gdb) eflags
    OF <0>  DF <0>  IF <1>  TF <0>  SF <1>  ZF <0>  AF <0>  PF <0>  CF <0>
    ID <1>  VIP <0> VIF <0> AC <0>  VM <0>  RF <0>  NT <0>  IOPL <0>

Hook-stop

The hook stop macro is called every time the program hits a breakpoint. This can be combined with user-defined macros. In this example, we will call the above eflags macro every time we hit a breakpoint:

define hook-stop
  eflags
end

fputs.com

Opinions expressed on this website are mine and are usually wrong


2022-04-04