Using gdb to single-step assembly code outside specified executable causes error "cannot find bounds of current function"

LinuxAssemblyGdbX86Linux Kernel

Linux Problem Overview


I'm outside gdb's target executable and I don't even have a stack that corresponds to that target. I want to single-step anyway, so that I can verify what's going on in my assembly code, because I'm not an expert at x86 assembly. Unfortunately, gdb refuses to do this simple assembly-level debugging. It allows me to set and stop on appropriate breakpoint, but as soon as I try to single-step onwards, gdb reports the error "Cannot find bounds of current function" and the EIP doesn't change.

Additional details:

The machine code was generated by gcc asm statements and I copied it to the kernel memory location where it's executing, from the output of objdump -d. I wouldn't mind a simple way to use a loader to load my object code to a relocated address, but bear in mind the loading has to be done in a kernel module.

I suppose another alternative would be to produce a fake kernel module or debug info file to give to gdb, to cause it to believe this area is within the program code. gdb works fine on the kernel executable itself.

(For those who really want to know, I'm inserting code at runtime into Linux kernel data space inside a VMware VM and debugging it from gdb remote debugging the kernel via VMware Workstation's built-in gdb stub. Note I'm not writing kernel exploits; I'm a security graduate student writing a prototype.)

(I can set a breakpoint on each instruction inside my assembly. This works but would get quite laborious after a while, since the size of x86 assembly instructions varies and the location of the assembly will change every time I reboot.)

Linux Solutions


Solution 1 - Linux

Instead of gdb, run gdbtui. Or run gdb with the -tui switch. Or press C-x C-a after entering gdb. Now you're in GDB's TUI mode.

Enter layout asm to make the upper window display assembly -- this will automatically follow your instruction pointer, although you can also change frames or scroll around while debugging. Press C-x s to enter SingleKey mode, where run continue up down finish etc. are abbreviated to a single key, allowing you to walk through your program very quickly.

+---------------------------------------------------------------------------+
B+>|0x402670 <main>         push   %r15                                        |
|0x402672 <main+2>       mov    %edi,%r15d                                  |
|0x402675 <main+5>       push   %r14                                        |
|0x402677 <main+7>       push   %r13                                        |
|0x402679 <main+9>       mov    %rsi,%r13                                   |
|0x40267c <main+12>      push   %r12                                        |
|0x40267e <main+14>      push   %rbp                                        |
|0x40267f <main+15>      push   %rbx                                        |
|0x402680 <main+16>      sub    $0x438,%rsp                                 |
|0x402687 <main+23>      mov    (%rsi),%rdi                                 |
|0x40268a <main+26>      movq   $0x402a10,0x400(%rsp)                       |
|0x402696 <main+38>      movq   $0x0,0x408(%rsp)                            |
|0x4026a2 <main+50>      movq   $0x402510,0x410(%rsp)                       |
+---------------------------------------------------------------------------+
child process 21518 In: main                            Line: ??   PC: 0x402670
(gdb) file /opt/j64-602/bin/jconsole
Reading symbols from /opt/j64-602/bin/jconsole...done.
(no debugging symbols found)...done.
(gdb) layout asm
(gdb) start
(gdb)

Solution 2 - Linux

You can use stepi or nexti (which can be abbreviated to si or ni) to step through your machine code.

Solution 3 - Linux

The most useful thing you can do here is display/i $pc, before using stepi as already suggested in R Samuel Klatchko's answer. This tells gdb to disassemble the current instruction just before printing the prompt each time; then you can just keep hitting Enter to repeat the stepi command.

(See my answer to another question for more detail - the context of that question was different, but the principle is the same.)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPaulView Question on Stackoverflow
Solution 1 - LinuxephemientView Answer on Stackoverflow
Solution 2 - LinuxR Samuel KlatchkoView Answer on Stackoverflow
Solution 3 - LinuxMatthew SlatteryView Answer on Stackoverflow