The below code is an snippet from the 2nd stage loader program. It is running in Real Mode
and gets called by the bootloader program. The problem is that GDB is showing wrong addresses to variables allocated in stack.
|------|------|------|
|Name |GDB |Actual|
|------|------|------|
|char a|0x7be7|0x7bfb|
|char b|0x7be6|0x7bfa|
|------|------|------|
Source:
__attribute__((noreturn))
void __main()
{
char a = 'A';
char b = 'B';
while(1);
}
Disassembly:
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>
This file gets loaded at physical location 0x8000
by a custom bootloader.
QEMU and 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
I do not really understand what is going on. Could it be the -m16
option?
Compilation
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
Linker Script (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)
}
}
Things I tried:
- Using
-m32
instead of-m16
and.code16gcc
at the top of the C file. - Verified that GCC, GDB works perfectly when compilling a native application.
- Used
--oformat binary
option inld
instead ofobjcopy
PS:
- GCC Version: 8.3.0
- GNU ld Version: 2.31.1
- Linux Debian 10