在 QEMU 上调试 GRUB2 EFI 映像 运行
Debug GRUB2 EFI image running on QEMU
我想达到的目标
我想定制一个 GRUB EFI 映像,并在 QEMU 上 运行 调试它。
所以我尝试在自定义之前调试普通 GRUB 映像。
到目前为止我做了什么
我从 http://git.savannah.gnu.org 下载 GRUB2 并编译它:
./autogen.sh
./configure --prefix=`pwd`/local --with-platform=efi --target=i386 CFLAGS=-g
make
make install
然后,生成了一个简单的 EFI 图像:
./local/bin/grub-mkstandalone -O i386-efi -o bootIA32.efi
并将其放入磁盘映像文件中:
qemu-img create -f raw hda.img 1G
mkfs.fat hda.img
sudo mount -o uid=$UID hda.img /mnt
mkdir -p /mnt/efi/boot/
mv bootIA32.efi /mnt/efi/boot/
sudo umount /mnt
为了启动它,我编译了一个 IA32 OVMF.fd 来与 QEMU 一起使用:
qemu-system-i386 -bios $UDK_PATH/Build/OvmfIa32/RELEASE_GCC48/FV/OVMF.fd \
-hda hda.img
它正确启动,给我一个 grub shell。
我卡在哪里
现在,我想调试 GRUB。所以我用附加参数调用了 QEMU:
qemu-system-i386 -bios $UDK_PATH/Build/OvmfIa32/RELEASE_GCC48/FV/OVMF.fd \
-hda hda.img \
-s -S
并将 gdb 附加到 QEMU:
cd grub-core/
gdb -x gdb_grub
但是,似乎缺少调试符号:
GNU gdb (Debian 7.7.1+dfsg-5) 7.7.1
(...)
For help, type "help".
Type "apropos word" to search for commands related to "word".
0x0000fff0 in grub_disk_cache_table ()
Breakpoint 1 at 0x49b1: file kern/dl.c, line 53.
(gdb) n
Single stepping until exit from function grub_disk_cache_table,
which has no line number information.
0xffffff75 in ?? ()
(gdb)
我做错了什么?
添加符号后
@unixsmurf 当我使用 symbol-file
命令时,它似乎正在加载调试符号。事实上,gdb 说
(gdb) symbol-file ../local/lib/grub/i386-efi/kernel.exec
Reading symbols from ../local/lib/grub/i386-efi/kernel.exec...done.
但是,我仍然无法执行 next
命令,returns
(gdb) n
Single stepping until exit from function grub_disk_cache_table,
which has no line number information.
0xffffff75 in ?? ()
例如,我想在 grub_core/kern/main.c:grub_main
函数中设置一个断点,然后 运行 逐步执行。
但是虽然设置了断点,但是当我continue
执行时,GRUB到达shell并没有在断点处停止:
(gdb) b main.c:grub_main
Note: breakpoint 2 also set at pc 0x6082.
Breakpoint 3 at 0x6082: file kern/main.c, line 266.
(gdb) c
Continuing.
您的 bootIA32.efi
图片中没有调试符号。
gdb_grub
脚本尝试执行此操作,但由于它是为 BIOS(而非 UEFI)设计的,并且似乎基本上是偶然包含和生成的,因此它不再真正起作用 - 因为 GRUB 的 EFI 版本是动态到 运行 时间决定的地址。
现在,通过一些技巧(以及使用 -D DEBUG_ON_SERIAL_PORT
构建的 OVMF_CODE.fd
),只要我在输入之前不 运行 任何其他命令,我就可以看到GRUB,我总是看到:
Loading driver at 0x0003DDE9000 EntryPoint=0x0003DDE9400
所以对 gdb_grub
进行了一次可怕的破解,在接近尾声的地方更改了行:
file kernel.exec
至
add-symbol-file kernel.exec 0x0003DDE9400
我最终遇到的情况不是
add symbol table from file "kernel.exec" at
.text_addr = 0x3dde9400
0x0000fff0 in ?? ()
Breakpoint 1 at 0x3ddedddb: file kern/dl.c, line 53.
(gdb)
到此为止。如果我继续,模块符号加载现在按预期的脚本工作:
(gdb) cont
Continuing.
add symbol table from file "memdisk.module" at
.text_addr = 0x3bf75cb0
.rodata.str1.1_addr = 0x3bf75e77
.data_addr = 0x3bf75ee0
.module_license_addr = 0x3bf75f00
.bss_addr = 0x3bf75f10
add symbol table from file "archelp.module" at
.text_addr = 0x3b885ef0
.rodata.str1.1_addr = 0x3b8864d6
.module_license_addr = 0x3b88653c
不完全适合生产,但可行。
接受的答案对我来说就像魔法。
顺便说一句,我使用以下 lower-level 可执行文件来构建 EFI,与完整的 debian qemu 映像相同(该命令创建一个较小的 EFI,并且可以来自任何目录 运行。)
MODULES="search iso9660 configfile normal memdisk tar part_msdos part_gpt fat"
$GRUB_PATH/grub-mkimage -O x86_64-efi -d $GRUB_PATH/grub-core -p "" -o ./grub.efi $MODULES
我仍然必须在与 kernel.exec 相同的源目录中启动 gdb 会话,因为源文件路径是相对于该目录的。
我想达到的目标
我想定制一个 GRUB EFI 映像,并在 QEMU 上 运行 调试它。
所以我尝试在自定义之前调试普通 GRUB 映像。
到目前为止我做了什么
我从 http://git.savannah.gnu.org 下载 GRUB2 并编译它:
./autogen.sh
./configure --prefix=`pwd`/local --with-platform=efi --target=i386 CFLAGS=-g
make
make install
然后,生成了一个简单的 EFI 图像:
./local/bin/grub-mkstandalone -O i386-efi -o bootIA32.efi
并将其放入磁盘映像文件中:
qemu-img create -f raw hda.img 1G
mkfs.fat hda.img
sudo mount -o uid=$UID hda.img /mnt
mkdir -p /mnt/efi/boot/
mv bootIA32.efi /mnt/efi/boot/
sudo umount /mnt
为了启动它,我编译了一个 IA32 OVMF.fd 来与 QEMU 一起使用:
qemu-system-i386 -bios $UDK_PATH/Build/OvmfIa32/RELEASE_GCC48/FV/OVMF.fd \
-hda hda.img
它正确启动,给我一个 grub shell。
我卡在哪里
现在,我想调试 GRUB。所以我用附加参数调用了 QEMU:
qemu-system-i386 -bios $UDK_PATH/Build/OvmfIa32/RELEASE_GCC48/FV/OVMF.fd \
-hda hda.img \
-s -S
并将 gdb 附加到 QEMU:
cd grub-core/
gdb -x gdb_grub
但是,似乎缺少调试符号:
GNU gdb (Debian 7.7.1+dfsg-5) 7.7.1
(...)
For help, type "help".
Type "apropos word" to search for commands related to "word".
0x0000fff0 in grub_disk_cache_table ()
Breakpoint 1 at 0x49b1: file kern/dl.c, line 53.
(gdb) n
Single stepping until exit from function grub_disk_cache_table,
which has no line number information.
0xffffff75 in ?? ()
(gdb)
我做错了什么?
添加符号后
@unixsmurf 当我使用 symbol-file
命令时,它似乎正在加载调试符号。事实上,gdb 说
(gdb) symbol-file ../local/lib/grub/i386-efi/kernel.exec
Reading symbols from ../local/lib/grub/i386-efi/kernel.exec...done.
但是,我仍然无法执行 next
命令,returns
(gdb) n
Single stepping until exit from function grub_disk_cache_table,
which has no line number information.
0xffffff75 in ?? ()
例如,我想在 grub_core/kern/main.c:grub_main
函数中设置一个断点,然后 运行 逐步执行。
但是虽然设置了断点,但是当我continue
执行时,GRUB到达shell并没有在断点处停止:
(gdb) b main.c:grub_main
Note: breakpoint 2 also set at pc 0x6082.
Breakpoint 3 at 0x6082: file kern/main.c, line 266.
(gdb) c
Continuing.
您的 bootIA32.efi
图片中没有调试符号。
gdb_grub
脚本尝试执行此操作,但由于它是为 BIOS(而非 UEFI)设计的,并且似乎基本上是偶然包含和生成的,因此它不再真正起作用 - 因为 GRUB 的 EFI 版本是动态到 运行 时间决定的地址。
现在,通过一些技巧(以及使用 -D DEBUG_ON_SERIAL_PORT
构建的 OVMF_CODE.fd
),只要我在输入之前不 运行 任何其他命令,我就可以看到GRUB,我总是看到:
Loading driver at 0x0003DDE9000 EntryPoint=0x0003DDE9400
所以对 gdb_grub
进行了一次可怕的破解,在接近尾声的地方更改了行:
file kernel.exec
至
add-symbol-file kernel.exec 0x0003DDE9400
我最终遇到的情况不是
add symbol table from file "kernel.exec" at
.text_addr = 0x3dde9400
0x0000fff0 in ?? ()
Breakpoint 1 at 0x3ddedddb: file kern/dl.c, line 53.
(gdb)
到此为止。如果我继续,模块符号加载现在按预期的脚本工作:
(gdb) cont
Continuing.
add symbol table from file "memdisk.module" at
.text_addr = 0x3bf75cb0
.rodata.str1.1_addr = 0x3bf75e77
.data_addr = 0x3bf75ee0
.module_license_addr = 0x3bf75f00
.bss_addr = 0x3bf75f10
add symbol table from file "archelp.module" at
.text_addr = 0x3b885ef0
.rodata.str1.1_addr = 0x3b8864d6
.module_license_addr = 0x3b88653c
不完全适合生产,但可行。
接受的答案对我来说就像魔法。
顺便说一句,我使用以下 lower-level 可执行文件来构建 EFI,与完整的 debian qemu 映像相同(该命令创建一个较小的 EFI,并且可以来自任何目录 运行。)
MODULES="search iso9660 configfile normal memdisk tar part_msdos part_gpt fat"
$GRUB_PATH/grub-mkimage -O x86_64-efi -d $GRUB_PATH/grub-core -p "" -o ./grub.efi $MODULES
我仍然必须在与 kernel.exec 相同的源目录中启动 gdb 会话,因为源文件路径是相对于该目录的。