rust-osdev / cargo-xbuild

Automatically cross-compiles the sysroot crates core, compiler_builtins, and alloc.
Apache License 2.0
260 stars 25 forks source link

Cargo xbuild failed when linking to high address #76

Closed ghost closed 4 years ago

ghost commented 4 years ago

I'm trying to build and link my kernel to higher address but cargo xuild emits alots of errors.

rust-lld: error: core.dn6za2s3-cgu.4:(function core::fmt::num::imp::_$LT$impl$u20$core..fmt..Display$u20$for$u20$usize$GT$::fmt::h5a6ad2655a4131f3: .text._ZN4core3fmt3num3imp54_$LT$impl$u20$core..fmt..Display$u20$for$u20$usize$GT$3fmt17h5a6ad2655a4131f3E+0xFB): relocation R_X86_64_32 out of range: 18446603336221277272 is not in [0, 4294967295]
          rust-lld: error: core.dn6za2s3-cgu.4:(function core::fmt::num::imp::_$LT$impl$u20$core..fmt..Display$u20$for$u20$u32$GT$::fmt::hb74b0354b9128009: .text._ZN4core3fmt3num3imp52_$LT$impl$u20$core..fmt..Display$u20$for$u20$u32$GT$3fmt17hb74b0354b9128009E+0xFB): relocation R_X86_64_32 out of range: 18446603336221277272 is not in [0, 4294967295]
ghost commented 4 years ago

cargo xbuild --version

cargo-xbuild 0.5.31 (eede1a1 2020-05-13)

link.ld:

PHDRS
{
    load PT_LOAD;
}

SECTIONS
{
    . = 0xffff800000000000;

    .text : { *(.text) }
    .data : { *(.data) *(.rodata) }
    .bss : { *(.bss) }

    /DISCARD/ : { *(.eh_frame) *(.comment) }
}

rust-toolchain:

nightly-2020-02-24

.cargo/config:

[build]
rustflags = ["-Clink-arg=--script=link.ld"]
phil-opp commented 4 years ago

I don't think that this error is related to cargo-xbuild, given that it comes directly from the linker.

From a first guess, I think that this might be related to the code model in your target specification. Try setting it to large or kernel. See https://github.com/phil-opp/blog_os/issues/801 for more information.

ghost commented 4 years ago

I tried that too but still error.

x86_64-unknown-none.json:

{
  "llvm-target": "x86_64-unknown-none",
  "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
  "arch": "x86_64",
  "target-endian": "little",
  "target-pointer-width": "64",
  "target-c-int-width": "32",
  "os": "none",
  "executables": true,
  "relocation-models": "static",
  "code-model": "large",
  "linker-flavor": "ld.lld",
  "linker": "rust-lld",
  "panic-strategy": "abort",
  "disable-redzone": true,
  "features": "-mmx,-sse,+soft-float"
}
phil-opp commented 4 years ago

Try cargo clean before building it to ensure that everything is compiled with the new code model. Also, try removing the "relocation-models": "static" key (I don't think that it applies anyway because it has to be "relocation-model" (singular) as far as I know).

ghost commented 4 years ago

Ah, my bad. i tried with both "relocation-model": "static" (signular) and delete that key, with cargo clean before cargo xbuild --target x86_64-unknown-none, but still no hope :(

Edit: fix typo

phil-opp commented 4 years ago

Hmm, I'm out of ideas then. Unfortunately, I don't have the time to help debugging this at the moment.

ghost commented 4 years ago

I look into the error messages and it seem that all the error is in the core crate itself, which could mean the core crate is not compiled with code-model large in mind. Maybe the target file is not used when building the core crate?

phil-opp commented 4 years ago

We build core and other sysroot libraries for the same target as the kernel, so if your target JSON file sets the code-model to large, it should also apply to core. Still, it might make sense to try compiling with cargo's own -Zbuild-std=core,alloc flag instead of cargo-xbuild, maybe there is something we're doing wrong. See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std for more information about the -Zbuild-std flag.

ghost commented 4 years ago

Could you please explain more? I don't quite know how to cross-compile core crate (that why i use cargo xbuild to do the work for me) and link it with my kernel.

ghost commented 4 years ago

As I run cargo build -Zbuild-std=core,alloc --target x86_64-unknown-none, it finish with error: Could not find specification for target "x86_64-unknown-none", the same for cargo xbuild -Zbuild-std=core,alloc --target x86_64-unknown-none

Edit: I tried again with: cargo build -Zbuild-std=core,alloc --target x86_64-unknown-none.json and cargo xbuild -Zbuild-std=core,alloc --target x86_64-unknown-none.json, this time, it greet me with this error: error: undefined symbol: memcpy

phil-opp commented 4 years ago

it greet me with this error: error: undefined symbol: memcpy

This is expected since -Zbuild-std currently builds the compiler_builtins crate without its mem feature. You can work around that error by adding the rlibc crate as dependency. Note that you also need to specify extern crate rlibc in your main.rs (even on the 2018 edition) to enforce that it is linked.

ghost commented 4 years ago

I tried again and it somehow process, but this time, a new error:

error[E0463]: can't find crate for `std`
  = note: the x86_64-unknown-none-3339195998372785209 target may not be installed

As an alternative method: I cloned rust source (https://github.com/rust-lang/rust/tree/master/src), copy x86_64-unknown-none.json to libcore and liballoc folder. Then I build them with command cargo build --target x86_64-unknown-none.json --release. What should I do next?

phil-opp commented 4 years ago

I tried again and it somehow process, but this time, a new error:

error[E0463]: can't find crate for `std`
  = note: the x86_64-unknown-none-3339195998372785209 target may not be installed

Are you sure that your binary/library is no_std? This error means that your crate or one of your dependencies tries to include the standard library, which is not available on bare metal.

ghost commented 4 years ago

Are you sure that your binary/library is no_std? This error means that your crate or one of your dependencies tries to include the standard library, which is not available on bare metal.

Yes, i'm very sure since i have '#![no_std]' line in my main.rs.

That error only appear when i have extern crate rlib; in my main.rs

Currently, I have extern crate rlib; in my main.rs and rlib = "0.0.1" in my Cargo.toml

ghost commented 4 years ago

By the way, I found my backup and have sysroot folder that build and link everything ok. That sysroot folder i built using cargo-xbuild, with rustc nightly-2020-03-24.

But I can't re-build that sysroot folder anymore, even i'm still using rustc nightly-2020-03-24 and cargo-build, with exactly same code and x86_64-unknown-none.json. It throw out a lots of relocation R_X86_64_32S out of range linking errors.

I can send you that sysroot folder if you want a closer look.

phil-opp commented 4 years ago

Currently, I have extern crate rlib; in my main.rs and rlib = "0.0.1" in my Cargo.toml

You need to include the rlibc crate, not the (empty) rlib crate. The latter is not no_std, so that's likely where the issue is coming from.

ghost commented 4 years ago

Ah, my bad again, sorry about that :(

This time: main.rs extern crate rlibc; Cargo.toml: rlibc = ""

My command: cargo build -Zbuild-std=core,alloc --target x86_64-unknown-none.json

Good news: It's worked! So I think there is some problems with cargo-xbuild

phil-opp commented 4 years ago

Ok, could you try to create a minimal example project that works with -Zbuild-std but not cargo-xbuild? This would make debugging this issue much easier.

ghost commented 4 years ago

Here you are:

main.rs

#![no_std]                                  // don't link the Rust standard library
#![no_main]                                 // disable all Rust-level entry points

use core::panic::PanicInfo;
static TEST: usize = 1;

#[no_mangle]
pub extern "C" fn _start () -> ! {
    let a = &TEST as *const usize as u128;
    let b = a*128;
    loop {}
}

#[panic_handler]
pub fn my_panic_handler (_panic_info: &PanicInfo) -> ! {
    loop {}
}

rust-toolchain: nightly-2020-03-24

x86_64-unknown-none.json

{
  "llvm-target": "x86_64-unknown-none",
  "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
  "arch": "x86_64",
  "target-endian": "little",
  "target-pointer-width": "64",
  "target-c-int-width": "32",
  "os": "none",
  "executables": true,
  "relocation-model": "static",
  "code-model": "large",
  "linker-flavor": "ld.lld",
  "linker": "rust-lld",
  "panic-strategy": "abort",
  "disable-redzone": true,
  "features": "-mmx,-sse,+soft-float"
}

link.ld

PHDRS
{
    load PT_LOAD;
}

SECTIONS
{
    . = 0xffff800000000000;

    .text : { *(.text) }
    .data : { *(.data) *(.rodata) }
    .bss : { *(.bss) }

    /DISCARD/ : { *(.eh_frame) *(.comment) }
}

.cargo/config

rustflags = ["-Clink-arg=--script=link.ld", "-Ccode-model=large", "-Crelocation-model=static"]

build command: cargo xbuild --target x86_64-unknown-none.json

Errors:

rust-lld: error: core.es9ltvmc-cgu.5:(function core::panicking::panic_fmt::he67cfa247b17aacf: .text._ZN4core9panicking9panic_fmt17he67cfa247b17aacfE+0x9): relocation R_X86_64_32S out of range: -140737488355240 is not in [-2147483648, 2147483647]
          rust-lld: error: core.es9ltvmc-cgu.5:(function core::panicking::panic::h9ffef647d76b21f3: .text._ZN4core9panicking5panic17h9ffef647d76b21f3E+0x2F): relocation R_X86_64_32S out of range: -140737488355240 is not in [-2147483648, 2147483647]
          rust-lld: error: core.es9ltvmc-cgu.5:(function core::panicking::panic_fmt::he67cfa247b17aacf: .text._ZN4core9panicking9panic_fmt17he67cfa247b17aacfE+0x12): relocation R_X86_64_32S out of range: -140737488355240 is not in [-2147483648, 2147483647]
ghost commented 4 years ago

For this to build with cargo build, you just add extern crate rlibc; to main.rs and rlibc = "" to Cargo.toml

phil-opp commented 4 years ago

I tried it with both the current nightly, nightly 2020-03-24, and nightly 2020-03-23, and it always seems to work for me. It builds without any error.

ghost commented 4 years ago

It's weird then. Have you build it with config file at [current dir]/.cargo/config? I use that file to force cargo link to high address, the problem only appear when linking to high address.

And you also need link.ld file at current dir too. I posted content of both files above.

vinaychandra commented 4 years ago

FWIW, I am able to run the snippet provided with "code-model": "large". To run with "code-model": "kernel", I had to remove "relocation-model": "static"

ghost commented 4 years ago

By run, do you mean that it compile without error? Do the binary link correctly to address 0xffff800000000000? Do the init code of variable 'a' not stripped? Can you post the binary here?

vinaychandra commented 4 years ago

I was able to link to a high address and run a quick test to verify.

https://github.com/vinaychandra/MoonDustKernel/tree/2cba4c9dbf5097b2f33ba0852bd86e41a44860c2

You can see that I'm actually using code model as kernel. Call make run will build and run qemu.

ghost commented 4 years ago

I see that your kernel can link and run just ok. Now i'm really out of ideal.