assembly - wrong memory locations when debugging in qemu with gdb -
i'm writing little kernel in assembler. i'm running in qemu , have problems bugs. want debug kernel dbg. assembled so:
$ nasm -g -f elf -o myos.elf myos.asm $ objcopy --only-keep-debug myos.elf myos.sym $ objcopy -o binary myos.elf myos.bin
then run in qemu with:
$ qemu-system-i386 -s -s myos.bin
then connect gdb:
$ gdb (gdb) target remote localhost:1234 remote debugging using localhost:1234 0x0000fff0 in ?? () symbol-file myos.sym reading symbols /home/sven/projekte/myos/myos.sym...done.
i have label named welcome
in kernel points string. while testing tried @ string, gave following result:
(gdb) x/32b welcome 0x1e <welcome>: 0x00 0xf0 0xa5 0xfe 0x00 0xf0 0x87 0xe9 0x26: 0x00 0xf0 0x6e 0xc9 0x00 0xf0 0x6e 0xc9 0x2e: 0x00 0xf0 0x6e 0xc9 0x00 0xf0 0x6e 0xc9 0x36: 0x00 0xf0 0x57 0xef 0x00 0xf0 0x6e
the label defined this:
welcome: db "system started. happy hacking!", 10, 0
so can see, gdb pretending welcome starts null byte definition it's not. kernel uses label correctly, doesn't seem poblem code. examining other parts of memory doesn't match loaded kernel @ all.
does know why memory of virtual machine doesn't match loaded kernel, while machine still behaves corectly?
explanation
qemu-system-i386
loads first byte of x86 boot sector image file @ address0x7c00
@ run time.- your elf files (
myos.elf
,myos.sym
) mistakenly inform gdb code loaded @ address 0. gdb thinkswelcome
@0x1e
while it's @0x7c1e
. - adding
0x7c00
addresses in gdb work clumsy:x/32xb (welcome + 0x7c00)
- a better solution create elf file right addresses.
solution
boot.asm
; 'boot.asm' ; loaded bios [bits 16] global main main: mov di, welcome print_welcome: mov ah, 0x0e mov al, [di] int 0x10 inc di cmp byte [di], 0 jne print_welcome hlt db "xxxxxxxxxxxxxx" ; padding make welcome appear @ 0x1e welcome: db "system started. happy hacking!", 10, 0 ; x86 boot sector padding , signature ; note: intentionally commented out. added linker script ;times 510 - ($ - $$) db 0x00 ;db 0x55, 0xaa
x86-boot.ld
entry(main); sections { . = 0x7c00; .text : at(0x7c00) { _text = .; *(.text); _text_end = .; } .data : { _data = .; *(.bss); *(.bss*); *(.data); *(.rodata*); *(common) _data_end = .; } .sig : at(0x7dfe) { short(0xaa55); } /discard/ : { *(.note*); *(.iplt*); *(.igot*); *(.rel*); *(.comment); /* add unwanted sections spewed out version of gcc , flags here */ } }
build code with:
nasm -g -f elf -f dwarf boot.asm -o boot.o cc -nostdlib -m32 -t x86-boot.ld -wl,--build-id=none boot.o -o boot objcopy -o binary boot boot.good.bin
dump-welcome.gdb
target remote localhost:1234 symbol-file boot monitor system_reset # run until hlt instruction, address obtained through disassembly until *0x7c0f x/32xb welcome monitor quit disconnect quit
sample session:
$ qemu-system-x86_64 -s -s boot.good.bin & $ gdb -q -x dump-welcome.gdb 0x0000fff0 in ?? () main () @ boot.asm:16 16 hlt 0x7c1e : 0x53 0x79 0x73 0x74 0x65 0x6d 0x20 0x73 0x7c26: 0x74 0x61 0x72 0x74 0x65 0x64 0x2e 0x20 0x7c2e: 0x48 0x61 0x70 0x70 0x79 0x20 0x68 0x61 0x7c36: 0x63 0x6b 0x69 0x6e 0x67 0x21 0x0a 0x00
thought process
most of 32 bytes dumped have values ≥ 0x80, i.e. they're not printable ascii characters. raises question: am really dumping right address?
the hex dump of welcome
message should be:
$ python -c 's = "system started. happy hacking!"; print [hex(ord(x)) x in s ]' ['0x53', '0x79', '0x73', '0x74', '0x65', '0x6d', '0x20', '0x73', '0x74', '0x61', '0x72', '0x74', '0x65', '0x64', '0x2e', '0x20', '0x48', '0x61', '0x70', '0x70', '0x79', '0x20', '0x68', '0x61', '0x63', '0x6b', '0x69', '0x6e', '0x67', '0x21']
using gdb search welcome
message in memory have revealed right address well:
(gdb) find 0, 0xffff, 's', 'y', 's', 't' 0x7c1e
further reading
- gnu ld: basic linker script concepts: see discussion on lma vs. vma
- real mode in c gcc : writing bootloader: source of linker script above. shows cool gnu toolchain tricks x86 real mode development.
Comments
Post a Comment