My linking command (in my Makefile):
Code: Select all
ld -Ttext 0x1000 -m elf_i386 -o kernel/kernel.bin $^ --oformat binary
Code: Select all
ld -Ttext 0x1000 -m elf_i386 -o kernel/kernel.bin $^ --oformat binary
No, I use an entry assembly script that calls my 'start' c function, so thats not it.alexfru wrote:What about the order in which your C files end up in the binary? May that be screwing up the entry point?
1) I've heard about that, but never found how to use it. Please elaborate on how I could do that.goku420 wrote: - Why run ld manually? Linking with gcc or g++ will call the linker under the hood
- Why specify text manually? You might as well use a linker script.
Also 0x1000 is unusual. The most common place to load the kernel is at the 1MB mark as that's safe enough to avoid anything that's loaded below it.
Please elaborate, it sounds useful in the future.iansjack wrote:Run it under a debugger.
Good insight, but I can't figure out how I would go about loading the kernel somewhere high, like 1M, seeing as I am using a 16 bit bootloader and 16 bit disk read function.mallard wrote:A guess; since you're loading your kernel at a "low" address, you have (approximately; there are complications) 636KB (since you're loading at the 4KB mark) of memory before you hit the legacy ROM/MMIO area (the 384KB just below the 1MB boundary).
When you link this extra file into your kernel, it increases the size of the file so it no longer fits into that small RAM space, so your loader attempts to overwrite ROM, write to non-existent memory, etc. and the system resets in response.
If your kernel is small enough to fit in low memory, you can load it all in real mode and then copy it above 1M after you switch to protected mode.BluCode wrote:Good insight, but I can't figure out how I would go about loading the kernel somewhere high, like 1M, seeing as I am using a 16 bit bootloader and 16 bit disk read function.
Produce an elf file as well as a binary file, and use that as the file you "load" to provide symbols. Or, without symbols, you can still use gdb to debug at the assembler level.BluCode wrote:Yes, I am using qemu. I tried to use gdb but I couldn't figure out how to get a symbol file from my kernel.bin. It would be really advantageous to get that working though.
An observation. If you want a symbol file don't use GCC/LD to output as binary. Output as ELF (with the symbols) and then use Objcopy to convert the ELF to binary.BluCode wrote:Yes, I am using qemu. I tried to use gdb but I couldn't figure out how to get a symbol file from my kernel.bin. It would be really advantageous to get that working though.
Code: Select all
ld -Ttext 0x1000 -m elf_i386 -o kernel/kernel.elf <list of objects>
objcopy -O binary kernel.elf kernel.bin
Don't forget you need a cross compiler: http://wiki.osdev.org/GCC_Cross-CompilerMichaelPetch wrote: ld -Ttext 0x1000 -m elf_i386 -o kernel/kernel.elf <list of objects>
objcopy -O binary kernel.elf kernel.bin
All good ideas, I'll look into them in the future.Octocontrabass wrote: If your kernel is small enough to fit in low memory, you can load it all in real mode and then copy it above 1M after you switch to protected mode.
It's also possible to load part of the kernel in real mode, switch to protected mode to copy that part above 1M, then switch back to real mode and repeat until the entire kernel is loaded.
My favorite option is to install a GPF handler that switches to unreal mode for transparent 32-bit addressing, although you probably don't need something that complicated.
iansjack wrote:Produce an elf file as well as a binary file, and use that as the file you "load" to provide symbols. Or, without symbols, you can still use gdb to debug at the assembler level.
Using these two replies and the wiki article on debugging with QEMU I got it working, thanks!MichaelPetch wrote: An observation. If you want a symbol file don't use GCC/LD to output as binary. Output as ELF (with the symbols) and then use Objcopy to convert the ELF to binary.this would generate an intermediate ELF file called `kernel.elf` that is then converted into `kernel.bin`.Code: Select all
ld -Ttext 0x1000 -m elf_i386 -o kernel/kernel.elf <list of objects> objcopy -O binary kernel.elf kernel.bin
I'll probably move there soon, and I'll let you know if and when I do.MichaelPetch wrote:If you had a project available (github etc) we could have a look.
Good point, but since this is mainly to learn about all of whats going on under the hood I'm doing both, please and thank you.LtG wrote:Didn't see it mentioned yet, but you should think if you want to do osdev or write a bootloader, the two are almost completely different, in design and goals.
If you don't care about bootloaders then use GRUB or some other existing one, and it's their responsibility to load your binary, if you want to do a bootloader then do that, but it doesn't really have much to do with osdev, except it's job is to load some OS.