GDB showing wrong address to local variables

Viewed 203

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:

  1. Using -m32 instead of -m16 and .code16gcc at the top of the C file.
  2. Verified that GCC, GDB works perfectly when compilling a native application.
  3. Used --oformat binary option in ld instead of objcopy

PS:

  • GCC Version: 8.3.0
  • GNU ld Version: 2.31.1
  • Linux Debian 10
0 Answers
Related