gdb – Assembly Language Debugging 101

This article introduces the basic commands required to debug assembly language in gdb.

Note: If you would like to understand an assembly language listing, jump to this article first.

Disassemble

The disassemble command provides the assembly language listing of a program and works even when a program is not running. The command works for a function name / an address / an address range.

disassemble function_name disassembles the function called function_name.

disassemble main

Dump of assembler code for function main:
0x00401180 <main+0>:    lea    0x4(%esp),%ecx
0x00401184 <main+4>:    and    $0xfffffff0,%esp
0x00401187 <main+7>:    pushl  -0x4(%ecx)
0x0040118a <main+10>:   push   %ebp
0x0040118b <main+11>:   mov    %esp,%ebp
0x0040118d <main+13>:   push   %esi
0x0040118e <main+14>:   push   %ebx
------8<---------<snip>---------8<---------------

The disassemble command can also be used for a specific address.

disassemble 0x0040120f

At times the disassembly listing of a function can get very long and to limit it, an address range can be provided as shown below.

disassemble <from_address1> <to_address2>

disassemble main main+20

disassemble 0x004011ce 0x004011f7

Developers who have debugged in assembly on various debuggers on the Windows platform may prefer the Intel instruction set instead instead of the At&T set which is the default in gdb.  The listing can be changed to use the Intel instruction set instead by setting the disassembly-flavor.

set disassembly-flavor intel

disassemble

Dump of assembler code for function main:
0x00401180 <main+0>:    lea    ecx,[esp+0x4]
0x00401184 <main+4>:    and    esp,0xfffffff0
0x00401187 <main+7>:    push   DWORD PTR [ecx-0x4]
0x0040118a <main+10>:   push   ebp
0x0040118b <main+11>:   mov    ebp,esp
0x0040118d <main+13>:   push   esi
0x0040118e <main+14>:   push   ebx
-----8<---------<snip>---------8<--------------

Controlling The Flow Of Program Execution

An instruction breakpoint can be set at a particular address using the breakpoint command.

breakpoint *0x0040118d

Take note of the asterix just before the address above.

To step into the assembly language one instruction at a time use the command:

stepi

Note that this will step into function calls that the program encounters.

To step over a function call, one can use the command:

nexti

To return from a function call that one is current stepping through, use the command:

finish

Gathering Information

To know about the values of the registers of the program being debugged use the following command:

info registers

$pc holds the program counter and it can also be used to find the instruction that will be executed next.

x/i $pc

0x40124e <main+206>:    mov    eax,ebx

Similar to regular debugging, the backtrace command prints the callstack.

bt

To get a list of the shared libraries that are loaded for the current program being debugged the following command is handy to use:

info sharedlibrary

From        To          Syms Read   Shared Object Library
0x779e1000  0x77b1bc3c  Yes         /cygdrive/c/Windows/system32/ntdll.dll
0x77901000  0x779d30c0  Yes         /cygdrive/c/Windows/system32/kernel32.dll
0x75c41000  0x75c895d0  Yes         /cygdrive/c/Windows/system32/KernelBase.dll
0x61001000  0x61450000  Yes         /usr/bin/cygwin1.dll
-----8<---------<snip>---------8<--------------

 

Note: A handy tip on using the display command during assembly language debugging with gdb was shared in a previous blog entry here.