rust-osdev / bootloader

An experimental pure-Rust x86 bootloader
Apache License 2.0
1.39k stars 212 forks source link

Load kernel at specific address in v0.11 #427

Closed jxors closed 8 months ago

jxors commented 8 months ago

Is there any way to load the kernel at a specific address? With v0.10 I was using link-arg=--image-base=0x00001eecb3620000 to ensure that the kernel was always located at 0x00001eecb3620000, but v0.11 no longer seems to respect the offsets in the ELF file.

I'm guessing it's probably because of this code. I'm happy to write a PR that adds a config option to override the address chosen there.

Freax13 commented 8 months ago

I'm guessing it's probably because of this code. I'm happy to write a PR that adds a config option to override the address chosen there.

The line you mentioned is only active for kernel compiled as position-independent executables. If you want your kernel to be loaded at a specific address you'll have to compile it with -C relocation-model=static.

jxors commented 8 months ago

Thank you for responding! I'm having some trouble compiling with the flag you mentioned.

When I compile with RUSTFLAGS="-Crelocation-model=static -Ccode-model=large -Clink-arg=--image-base=0x00001eecb3620000" cargo build --target x86_64-unknown-none -Z build-std=core,alloc I get the following error:

  = note: rust-lld: error: /[..]/target/x86_64-unknown-none/debug/deps/vmimage_x86_64-bca14057c3e0cdc3.3vq7oiz3rrtsr935.rcgu.o:(function _start: .ltext._start+0x23): relocation R_X86_64_32 out of range: 34001970711948 is not in [0, 4294967295]; references section '.bootloader-config'
          >>> referenced by lib.rs:129 (/[..]/bootloader/api/src/lib.rs:129)

Which I think refers to here

Freax13 commented 8 months ago

This is caused by a bug related to the large code model: AFAICT when the large relocation model is used, all functions and global variables that contain references to other functions and global variables outside what's reachable by the small code model are put in special .ltext, .lrodata and .ldata sections instead the regular .text, .rodata and .data sections. The bootloader_api crate internally uses a special .bootloader-config section to tell the bootloader how to boot the kernel. It seems to me that some part of the compiler is confused by this section. My guess is that the compiler will use 32-bit relocations by default and only use 64-bit relocations when referencing something in a .ltext, .lrodata, or .ldata section. Since .bootloader-config is not one of those, it uses a 32-bit relocation, but this fails because .bootloader-config cannot be referenced with a 32-bit relocation.

Freax13 commented 8 months ago

I opened #428 to work around the compiler bug.

daihuasheng commented 3 months ago

In v0.11 kernel is placed as a workspace member of the whole project. In this case, how could I pass -Crelocation-model=static to the kernel without affecting bootloader?

Freax13 commented 3 months ago

In v0.11 kernel is placed as a workspace member of the whole project. In this case, how could I pass -Crelocation-model=static to the kernel without affecting bootloader?

See this example.