Closed rikusalminen closed 11 years ago
@Overv I wrote a better makefile for cross compiling and added instructions for building the toolchain to README.md. The new makefile does not put binary files under bin/, that doesn't work too well with GNU make if you want to take advantage of implicit build rules.
The elf linker script file does not seem to work correctly, it needs a little fine tuning. It crashes qemu with this message:
qemu: fatal: Trying to execute code outside RAM or ROM at 0x000a0000
I already had the elf files working properly in QEMU + gdb remote debugger at one point but I don't know what I did to break it. Maybe the linker script is fragile. I'll see if I can fix the issue later.
Okay, I'll play around with it tomorrow and then merge if it's stable enough.
There's no hurry to get this merged.
On the other hand, it this change shouldn't break anything. edit: The old patch didn't really link the .bin file properly but it still booted ok because the bin file is so small that the multiboot header is close enough to beginning of file.
I will poke around with the debugger/objdump a little bit and see if I can make the elf files work, I think the address space set up by the linker does not quite match what the bootloader and init code expects.
@Overv did you try building a cross compiler toolchain? Did the instructions I wrote work?
I have solved the issue. I can now run MineAssemble on QEMU i368-softmmu with remote debugging using i686-pc-elf-gdb. I also tested the ELF file on real hardware using GRUB.
The problem was that the init code and multiboot header were not placed in the beginning of the elf executable.
The old Makefile had init.o as the first object file in the (hand-written) linker command line. This makes init.o text section the first object in the output binary and that makes it work.
I changed the linker scripts to put src/init.o text section in the beginning of the text section. That puts the multiboot header in the right place (close enough to beginning of executable binary).
The new Makefile works a little better, but it's still not perfect. It uses automatic dependency generation (using gcc -MMD
and nasm -MD
) but it works only after make has been run twice. It should, however, reliably rebuild everything when needed (and only when needed).
The latest patch should be good enough to merge. Test and review, please!
@rikusalminen I managed to install the toolchain. I did have to fix two typos (?) in your script:
- mkdir ~/i686-pc-elf-build/gcc ; cd ~/gcc-pc-elf-build/gcc
+ mkdir ~/i686-pc-elf-build/gcc ; cd ~/i686-pc-elf-build/gcc
- mkdir ~/i686-pc-elf-build/qemu ; cd ~/gcc-pc-elf-build/qemu
+ mkdir ~/i686-pc-elf-build/qemu ; cd ~/i686-pc-elf-build/qemu
The binutils
, gcc
and qemu
projects all compiled successfully, but they each gave some strange errors when running make install
. It doesn't seem like it affected anything however. I'm now going to try your makefile.
Hmm, currently getting this when compiling with your latest makefile:
overv@overv-linux:~/Code/MineAssemble$ make
i686-pc-elf-gcc -std=c99 -MMD -m32 -g -ggdb -O3 -ffast-math -ffreestanding -nostdlib -nostdinc -fno-builtin -nostartfiles -nodefaultlibs -fno-exceptions -fno-stack-protector -static -fno-pic -c -o src/reference.o src/reference.c
/tmp/cc2nyW1b.s: Assembler messages:
/tmp/cc2nyW1b.s:269: Error: invalid instruction suffix for `push'
/tmp/cc2nyW1b.s:271: Error: invalid instruction suffix for `push'
/tmp/cc2nyW1b.s:273: Error: invalid instruction suffix for `push'
/tmp/cc2nyW1b.s:275: Error: invalid instruction suffix for `push'
...
Seems like it's using the assembler in 64-bit mode for some reason.
The latest revision is just a few touches to the toolchain build instructions in the README.
I fixed the copy/paste/typos you mention.
@Overv I don't know what your build problem could be. Do you have the right binutils in your $PATH? Is GCC trying to use a wrong version of as to assemble? It needs to find i686-pc-elf-as to work. "invalid instruction suffix" often means that there's a 64 bit instruction in 32 bit code.
For debugging, here's the assembly output for reference.c from my compiler: http://www.pasteall.org/43406
Generated using this:
i686-pc-elf-gcc -std=c99 -m32 -g -ggdb -O3 -ffast-math -ffreestanding -nostdlib -nostdinc -fno-builtin -nostartfiles -nodefaultlibs -fno-exceptions -fno-stack-protector -static -fno-pic -S -o reference.s src/reference.c
Can you spot a difference?
@rikusalminen Ah, you're right, I currently don't have a i686-pc-elf-as
executable.
@Overv something has gone wrong with your binutils installation then, you'll need to have i686-pc-elf-as and i686-pc-elf-ld in your $PATH. Try running the install again and see if there were any meaningful errors.
@rikusalminen Ah, the binutils building got stuck because I didn't have texinfo installed, it finished building now and I can successfully make and run it (although the QEMU test still runs at 0.3 frames per second)
Good that you can build it.
Running this under QEMU is really slow, but it's the easiest way to attach a debugger to a kernel image.
Improved Makefile using a cross compiler toolchaing and dependency generation.
A linker script for building debuggable ELF files.
Instructions for building a cross compiler and remote debugging with QEMU and GDB.