OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 2:04 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 8 posts ] 
Author Message
 Post subject: gdb code display not same as source code
PostPosted: Sun Aug 23, 2020 4:00 pm 
Offline

Joined: Sun Aug 23, 2020 3:40 pm
Posts: 4
Hello, I am new to OS development and have been following the book recommended on the wiki called "Operating Systems: From 0 to 1", I have been following along and also implementing the code they use in the book on my computer. Everything was doing well with some slight changes needed from the books code, then section 8.5.3 I stumbled into a problem. The gdb debugger was not displaying the correct assembly code. I followed the books code precisely and do not understand why gdb is displaying the wrong assembly. I know now that the opcodes gdb displays at main are the magic numbers of the main program elf header, but why is this happening and how do I get it to display properly? If not possible is there an alternative solution?

bootloader.asm
Code:
;*************************************************
; bootloader.asm
; A Simple Bootloader
;*************************************************
bits 16
start: jmp  boot

;; constants and variable definitions
msg db "Welcome to My Operating System!", 0ah, 0dh, 0h

boot:

    cli ; no interrupts
    cld ; all that we need to init
   
    mov ax, 0x0000

    ;; set buffer
    mov es, ax 
    mov bx, 0x0600

    mov al, 1   ; read one sector
    mov ch, 0   ; track 0
    mov cl, 2       ; sector to read
    mov dh, 0   ; head number
    mov dl, 0   ; drive number
       
    mov ah, 0x02    ; read sectors from disk   
    int 0x13      ; call the BIOS routine
    jmp 0x0000:0x0600   ; jump and execute the sector!
   
    hlt ; halt the system

; We have to be 512 bytes. Clear the rest of the bytes with 0

times 510 - ($-$$) db 0
dw 0xAA55 ; Boot Signature


readelf -h main
Code:
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Intel 80386
  Version:                           0x1
  Entry point address:               0x600
  Start of program headers:          52 (bytes into file)
  Start of section headers:          12888 (bytes into file)
  Flags:                             0x0
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         3
  Size of section headers:           40 (bytes)
  Number of section headers:         12
  Section header string table index: 11


readelf -l main
Code:
Elf file type is EXEC (Executable file)
Entry point 0x600
There are 3 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  PHDR           0x000000 0x00000000 0x00000000 0x00094 0x00094 R   0x4
  LOAD           0x000000 0x00000000 0x00000000 0x00094 0x00094 R   0x4
  LOAD           0x000100 0x00000600 0x00000600 0x00006 0x00006 R E 0x100

Section to Segment mapping:
  Segment Sections...
   00     
   01     
   02     .text


main.c
Code:
void main(){}


objdump -z -M intel -S -D build/os/main
Code:
Disassembly of section .text:

00000600 <main>:
void main(){}
600:   55                      push   ebp
601:   89 e5                   mov    ebp,esp
603:   90                      nop
604:   5d                      pop    ebp
605:   c3                      ret   


when jumping to 0x0000:0x0600 in bootloader to main
this is what gdb displays;
Code:
0x600 <main>    jg     0x647                                               │
│   0x602 <main+2>  dec    esp                                                 │
│   0x603 <main+3>  inc    esi                                                 │
│   0x604 <main+4>  add    DWORD PTR [ecx],eax                                 │


also here is how I compiled everything and started up qemu
Code:
nasm -f elf bootloader.asm -F dwarf -g -o ../build/bootloader/bootloader.o
ld -m elf_i386 -T bootloader.lds ../build/bootloader/bootloader.o -o ../build/bootloader/bootloader.o.elf
objcopy -O binary ../build/bootloader/bootloader.o.elf ../build/bootloader/bootloader.o
gcc -ffreestanding -nostdlib -fno-pic -gdwarf-4 -m16 -ggdb3 -c main.c -o ../build/os/main.o
ld -m elf_i386 -nmagic -T os.lds  ../build/os/main.o -o ../build/os/main
dd if=/dev/zero of=disk.img bs=512 count=2880
2880+0 records in
2880+0 records out
1474560 bytes (1.5 MB, 1.4 MiB) copied, 0.0150958 s, 97.7 MB/s
dd conv=notrunc if=build/bootloader/bootloader.o of=disk.img bs=512 count=1 seek=0
1+0 records in
1+0 records out
512 bytes copied, 0.000127745 s, 4.0 MB/s
dd conv=notrunc if=build/os/main.o of=disk.img bs=512 count=$((8504/512))
seek=1
16+0 records in
16+0 records out
8192 bytes (8.2 kB, 8.0 KiB) copied, 0.000184251 s, 44.5 MB/s
qemu-system-i386 -machine q35 -fda disk.img -gdb tcp::26000 -S


here is the code I used for gdb
Code:
set architecture i8086
target remote localhost:26000
b *0x7c00
set disassembly-flavor intel
layout asm
layout reg
symbol-file build/os/main
b main


Top
 Profile  
 
 Post subject: Re: gdb code display not same as source code
PostPosted: Sun Aug 23, 2020 8:55 pm 
Offline
Member
Member

Joined: Sun Aug 23, 2020 4:35 pm
Posts: 148
The main problem is that your "main" file is in the ELF format. Computers only read binary format.

Here's the way I got your code working:
Since you didn't provide os.lds or bootloader.lds, I did it a different way.
Code:
nasm -fbin bootloader.asm -o bootloader.o
gcc -ffreestanding -nostdlib -nostartfiles -fno-pic -fcf-protection=none -gdwar>
ld --oformat binary -T os.lds main.o -o os.bin
ld -T os.lds main.o -o os.sym
dd if=/dev/zero of=disk.img bs=512 count=2880
dd conv=notrunc if=bootloader.o of=disk.img bs=512 count=1 seek=0
dd conv=notrunc if=os.bin of=disk.img bs=512 seek=1
qemu-system-i386 -machine q35 -fda disk.img -gdb tcp::26000 -S

using the following linker file (os.lds):
Code:
OUTPUT_ARCH(i8086)
ENTRY (main)

SECTIONS
{
   . = 0x600;
   .text : { *(.text) }
   .data : { *(.data) }
   .rodata : { *(.rodata) }
}


This compiles a bootable floppy. There is os.bin, which is the binary output that the computer should read and os.sym, which is the ELF output that your debugger should read.

However, the code you provided (bootloader.asm) does NOT work for two reasons:
- You haven't set up a stack of any sort, so right now it is undefined
- You used jmp instead of call, so when the main function tries to return, it will look in the undefined stack and find a random number (with QEMU it jumped to 0xf000d002, but it can vary by platform). I believe your intention was for the main function to return and execute the hlt instruction.

However, if you are worried whether gdb disassembles it,
Code:
set architecture i8086
target remote localhost:26000
b *0x7C00
set disassembly-flavor intel
layout asm
layout reg
symbol-file os.sym
b main

--------

B+>0x600 <main>    push   %bp                                                 │
│   0x602 <main+2>  mov    %sp,%bp                                             │
│   0x605 <main+5>  nop                                                        │
│   0x606 <main+6>  pop    %bp                                                 │
│   0x608 <main+8>  retw                                                       │
│   0x60a               add    %al,(%eax)


I don't know how you want your build mechanism to go, but that is up to you.
Good luck with your OS!

_________________
My OS: TritiumOS
https://github.com/foliagecanine/tritium-os
void warranty(laptop_t laptop) { if (laptop.broken) return laptop; }
I don't get it: Why's the warranty void?


Top
 Profile  
 
 Post subject: Re: gdb code display not same as source code
PostPosted: Sun Aug 23, 2020 11:31 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5100
I think you should read section 8.5.1 again.


Top
 Profile  
 
 Post subject: Re: gdb code display not same as source code
PostPosted: Mon Aug 24, 2020 9:18 am 
Offline
Member
Member

Joined: Sun Aug 23, 2020 4:35 pm
Posts: 148
Oops. I didn't notice that you were following a book #-o .

Octocontrabass is right though; on section 8.5 it tells you how to fix the linker script to load the "text" (code) section at 0x600.

However, do note that (as far as I can tell) that book is far from finished and won't get you too far.
There's also the two bugs I've mentioned in the previous post (no stack set up and jmp instead of call).

Good luck!

edit: spelling

_________________
My OS: TritiumOS
https://github.com/foliagecanine/tritium-os
void warranty(laptop_t laptop) { if (laptop.broken) return laptop; }
I don't get it: Why's the warranty void?


Top
 Profile  
 
 Post subject: Re: gdb code display not same as source code
PostPosted: Mon Aug 24, 2020 8:48 pm 
Offline

Joined: Sun Aug 23, 2020 3:40 pm
Posts: 4
Sorry for the late reply,
fpr this step; gcc -ffreestanding -nostdlib -nostartfiles -fno-pic -fcf-protection=none -gdwar>
did you mean this; gcc -ffreestanding -nostdlib -nostartfiles -fno-pic -fcf-protection=none -gdwarf -c main.c, or was it supposed to be like that?
also sorry for leaving out the linker scripts I used;

os.lds;
Code:
ENTRY(main);

PHDRS
{
  headers PT_PHDR FILEHDR PHDRS;
  headers2 PT_LOAD FILEHDR PHDRS;
  code PT_LOAD;
}

SECTIONS
{
  .text 0x600: ALIGN(0x100)  { *(.text)  } :code
  .data :  { *(.data)  }
  .bss :  { *(.bss) }
  /DISCARD/ : { *(.eh_frame) }
}


bootloader.lds
Code:
OUTPUT(bootloader);

PHDRS
{
  headers PT_NULL;
  text PT_LOAD FILEHDR PHDRS ;
  data PT_LOAD ;
}


SECTIONS
{
  . = SIZEOF_HEADERS;
  .text 0x7c00:  {  *(.text)  } :text
  .data :  {  *(.data)  } :data
}


Thanks for the help so far.


Top
 Profile  
 
 Post subject: Re: gdb code display not same as source code
PostPosted: Mon Aug 24, 2020 9:36 pm 
Offline
Member
Member

Joined: Sun Aug 23, 2020 4:35 pm
Posts: 148
programmern00b wrote:
fpr this step; gcc -ffreestanding -nostdlib -nostartfiles -fno-pic -fcf-protection=none -gdwar>
did you mean this; gcc -ffreestanding -nostdlib -nostartfiles -fno-pic -fcf-protection=none -gdwarf -c main.c, or was it supposed to be like that?

Sorry, nano cut out that last bit
Code:
gcc -ffreestanding -nostdlib -nostartfiles -fno-pic -fcf-protection=none -gdwarf-4 -m16 -ggdb3 -c main.c -o main.o

Since you're using a platform specific compiler, this disables GCC start files and disables fcf protections (they're meant for programs running on an OS, otherwise you'd have endbr32's everywhere)

----------------------------------------------------


The way the book says to do it is

os.lds:
Code:
ENTRY(main);
PHDRS
{
    headers PT_PHDR FILEHDR PHDRS;
    code PT_LOAD;
}

SECTIONS
{
    .text 0x600: ALIGN(0x100) { *(.text) } :code
    .data : { *(.data) }
    .bss : { *(.bss) }
    /DISCARD/ : { *(.eh_frame) }
}


and in your build process add -nmagic:
Code:
ld -m elf_i386 -nmagic -T os.lds main.o -o main


The way I did it (is probably not the best, but) literally strips out all of the ELF headers and data.
It produces two files, one binary and one with the symbols; the PC (or emulator) uses the binary file while gdb uses the symbol file.

----------------------------------------------------

Just a few tips:
- If you're running a Linux or BSD distro (in a virtual machine, or on real hardware) with a graphical envorionment, there's a software called DDD (Data Display Debugger). It has a horrible UI, but it's one of the easiest ways (for me at least) to see everything I'm debugging. It uses gdb for everything, but makes it much faster and easier to see and debug things.
- If you run QEMU with
Code:
qemu-system-i386 <flags here> -s
it will be the same as
Code:
qemu-system-i386 <flags here> -gdb tcp::1234

- The book you're using ends very soon. At this point, you'll either want to continue to create a Real Mode OS/bootloader or create a Protected Mode (or even Long Mode) OS. If you choose protected mode (like I did, although I did make a little tiny bootloader once), I'd recommend looking at the Bare Bones page.
- You could have probably put this thread in OS Development rather than General Programming, but I don't think it matters too much

----------------------------------------------------

(as a bonus, here's how I'd make bootloader.asm)
Code:
;*************************************************
; bootloader.asm
; A Simple Bootloader
;*************************************************
bits 16
start: jmp  boot

;; constants and variable definitions
msg db "Welcome to My Operating System!", 0ah, 0dh, 0h

boot:

    cli ; no interrupts
    cld ; all that we need to init
   
    xor ax,ax ; This is the same thing as doing "mov ax,0"
    mov ss,ax ; Set stack segment to 0
    mov sp,0xFFFF ; Set stack to start at 0xFFFF and grow down

    ;; set buffer
    mov es, ax
    mov bx, 0x0600

    mov al, 1   ; read one sector
    mov ch, 0   ; track 0
    mov cl, 2       ; sector to read
    mov dh, 0   ; head number
    mov dl, 0   ; drive number
       
    mov ah, 0x02    ; read sectors from disk   
    int 0x13      ; call the BIOS routine
    call 0x0000:0x0600   ; execute the sector, but provide a way for main to return
   
    hlt ; halt the system

; We have to be 512 bytes. Clear the rest of the bytes with 0

times 510 - ($-$$) db 0
dw 0xAA55 ; Boot Signature

_________________
My OS: TritiumOS
https://github.com/foliagecanine/tritium-os
void warranty(laptop_t laptop) { if (laptop.broken) return laptop; }
I don't get it: Why's the warranty void?


Top
 Profile  
 
 Post subject: Re: gdb code display not same as source code
PostPosted: Mon Aug 24, 2020 9:41 pm 
Offline

Joined: Sun Aug 23, 2020 3:40 pm
Posts: 4
Okay GDB displays the correct code now, all that needed to change was I needed a binary file and symbol file for the kernel code if i'm not mistaken?
Thanks for all the help again!


Top
 Profile  
 
 Post subject: Re: gdb code display not same as source code
PostPosted: Mon Aug 24, 2020 10:02 pm 
Offline

Joined: Sun Aug 23, 2020 3:40 pm
Posts: 4
Quote:
If you're running a Linux or BSD distro (in a virtual machine, or on real hardware) with a graphical envorionment, there's a software called DDD (Data Display Debugger).

Yes, I think I have stumbled upon this before to debug assembly code, I'll look more into it.

Also thanks for the tips on implementing a stack in my OS, remember to implement one in my future projects.

And thanks for giving me some directions on how to move forward, OS development seems like a big topic with lots of paths so thanks for the advice!


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 8 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: No registered users and 33 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group