问题描述
下面的代码是第二阶段加载程序的摘录。它在Real Mode
中运行,并由引导加载程序调用。问题在于GDB向堆栈中分配的变量显示了错误的地址。
|------|------|------|
|Name |GDB |Actual|
|------|------|------|
|char a|0x7be7|0x7bfb|
|char b|0x7be6|0x7bfa|
|------|------|------|
来源:
__attribute__((noreturn))
void __main()
{
char a = 'A';
char b = 'B';
while(1);
}
反汇编:
00008000 <__main>:
8000: 66 55 push ebp
8002: 66 89 e5 mov ebp,esp
8005: 66 83 ec 10 sub esp,0x10
8009: 67 c6 45 ff 41 mov BYTE PTR [ebp-0x1],0x41 <--- char a
800e: 67 c6 45 fe 42 mov BYTE PTR [ebp-0x2],0x42 <--- char b
8013: eb fe jmp 8013 <__main+0x13>
此文件由自定义引导程序加载到物理位置0x8000
。
QEMU和GDB
> qemu-system-i386 -fda build/boot.flp -s -S
> gdb loader.sym
target remote localhost:1234
set architecture i386
b __main
c
s
s
p &a
0x7be7 "" <-- Not EBP - 1
p &b
0x7be6 "" <-- Not EBP - 2
info reg
eax 0x0 0
ecx 0x0 0
edx 0x7de3 32227
ebx 0x8000 32768
esp 0x7bec 0x7bec
ebp 0x7bfc 0x7bfc <-- char a is at 0x7bfb and char b is at 0x7bfa
esi 0x0 0
edi 0x0 0
eip 0x8013 0x8013 <__main+19>
eflags 0x202 [ IF ]
cs 0x0 0
ss 0x0 0
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
我不太了解发生了什么。可能是-m16
选项吗?
编译
gcc -std=c99 \
-nostartfiles \
-c \
-g \
-ffreestanding \
-fno-pie \
-fno-stack-protector \
-m16 \
-march=i386 \
-Wpedantic \
-Wextra \
-Wall \
-O0 bootloader/x86/phase2/loader.c -o $TEMPDIR/loader.o || exit
ld -m elf_i386 --nmagic --script=build/loader.ld $TEMPDIR/loader.o -o $TEMPDIR/loader.lo || exit
objcopy --only-keep-debug $TEMPDIR/loader.lo $SYMDIR/loader.sym||exit
objcopy -O binary $TEMPDIR/loader.lo $OBJDIR/LOADER.flt||exit
链接器脚本(build / loader.ld)
ENTRY (__main)
SECTIONS
{
. = 0x8000; /* Loader is loaded at 0x0000:0x8000 */
.text :AT(0x0)
{
*.o (.text);
}
.data :
{
*.o (.data);
*.o (.bss);
*.o (.rodata);
}
/DISCARD/ :
{
*(.eh_frame)
}
}
我尝试过的事情:
- 在C文件顶部使用
-m32
代替-m16
和.code16gcc
。 - 验证了GCC,GDB在编译本机应用程序时完美运行。
- 在
--oformat binary
中使用了ld
选项,而不是objcopy
PS:
- GCC版本:8.3.0
- GNU ld版本:2.31.1
- Linux Debian 10
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)