Using Gdb to Single-Step Assembly Code Outside Specified Executable Causes Error "Cannot Find Bounds of Current Function"

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

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

gdb Cannot find bounds of current function

But when I debug my program using gdb, it shows:

(gdb) n

0x6a7706f8 in ?? () from C:\Windows\System32\DriverStore...

This is happening because you are stopped inside atioglxx.dll, which has no debugging info (or even symbol table).

When debugging, you need to be aware of your current context (e.g. which function am I stopped in).

When you are in your own code, and assuming you compiled it with debug info, you can do next, step, info locals, etc. But when you are in somebody else's code (e.g. in system-provided DLL), these commands will not work (are not expected to work).

Debugging with Bochs + GDB: cannot find bounds of current function?

Well, I got debugging working, but I had to switch emulators. I was able to get GDB working with Qemu, even though I also had problems doing that. To get GDB to connect to the Qemu gdbserver, I had to pass the following option to Qemu: "-gdb tcp::1234,ipv4". Took me forever to figure that out... Debugging works perfectly now!

CR0 contains PE/PG flags right upon the Linux Kernel startup

"All Intel 64 and IA-32 processors enter real-address mode following a power-up or reset", and then the firmware starts (using one CPU), then it starts all the other CPUs, and all the CPUs get switched to protected mode or long mode (along with initializing a lot of stuff - memory, MTRRs, ACPI tables, ...); and all the CPUs except one are put back to sleep.

Eventually; if the firmware is BIOS it switches the CPU back to real mode and starts a boot loader; and if the firmware is UEFI it leaves the CPU in long mode and starts a boot loader. Either way GRUB is started.

If the firmware was BIOS then GRUB switches the CPU to protected mode (and then switches it from protected mode to real mode and back to protected mode each time it wants to use BIOS functions); does a bunch of stuff; figures out it's loading a 64-bit Linux kernel and switches to long mode. If the firmware is UEFI it just stays in long mode the whole time. Note that GRUB's code is mostly 32-bit code; and both protected mode and long mode allow you to run 32-bit code; so most of GRUB's code works for both protected mode and long mode.

Even later; after a huge amount of stuff has been done by firmware and GRUB, and possibly after the CPU's mode has been changed a few thousand times; GRUB passes control to Linux.

Now... Linux has several different entry points, where the boot loader uses whichever entry point suits it the most. This changes occasionally - e.g. very old versions of Linux has a floppy disk boot loader built into it (they got rid of a bit later), and modern versions of Linux can have a UEFI boot loader built into it. There's also a real mode entry point and a protected mode entry point (which are older) and a 64-bit entry point (which is newer). Of these GRUB probably just uses the 32-bit entry point if the firmware was BIOS, and the 64-bit entry point if the firmware was UEFI.

Most of these entry points (excluding the UEFI boot loader entry point) work as a chain - e.g. if the real mode entry point is used it switches to protect mode and jumps to the 32-bit entry point; and if the 32-bit entry point is used it sets up paging and long mode and jumps to the 64-bit entry point.

Your breakpoint is at/near the 64-bit entry point; so regardless of which entry point the boot loader used (the 32-bit one or the 64-bit one) you start looking at 64-bit code. 64-bit code requires long mode, and long mode requires paging; so PG and PE must be set.

Of course (for the 64-bit entry point) paging is likely configured so that all physical addresses are mapped to the identical virtual addresses, so even though paging is enabled it doesn't actually do anything. Kernel's 64-bit startup code would change the way paging is configured (map kernel into kernel space, etc).



Related Topics



Leave a reply



Submit