Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Comments for "https://os.phil-opp.com/freestanding-rust-binary/" #386

Closed
utterances-bot opened this issue Feb 10, 2018 · 56 comments
Closed

Comments

@utterances-bot
Copy link

utterances-bot commented Feb 10, 2018

This is a general purpose comment thread for the “A Freestanding Rust Binary” post.

@phil-opp phil-opp changed the title freestanding-rust-binary/ Comments for "freestanding-rust-binary/" Feb 10, 2018
@sunjay
Copy link

sunjay commented Mar 6, 2018

There is a broken link which isn't actually formatted as a link: [name mangling][mangling]

@phil-opp
Copy link
Owner

phil-opp commented Mar 7, 2018

Thanks! Fixed in 8bd66bf.

@memoryruins
Copy link

Both the first and second editions of these series are invaluable. Thank you for every bit of clearly written information you’ve shared ✨

@phil-opp
Copy link
Owner

@memoryruins Thanks so much!

@CornedBee
Copy link

The Windows subsystem information link is outdated. The page behind it is pretty much unreadable and suggests to link to here instead:

https://docs.microsoft.com/en-us/cpp/build/reference/entry-entry-point-symbol

@phil-opp
Copy link
Owner

@CornedBee Thanks for the hint! Fixed in 6599a69.

@AleVul
Copy link

AleVul commented Apr 8, 2018

In the windows part of the post, the CONSOLE subsystem entry points are used as an example, then immediately the Windows subsystems entry points are referenced, i got a feeling that some explication is missing there.

@phil-opp
Copy link
Owner

phil-opp commented Apr 8, 2018

@AleVul Thanks for reporting! We used to define the Windows subsystem entry points and then switched to console subsystem entry points. Seems like we missed some references. Fixed in 5f12cd8.

Copy link
Contributor

Is the final code sample is supposed to build wihtout errors ? Compilator ask me to import PanicInfo

@phil-opp
Copy link
Owner

@sepiropht Thanks for reporting. Seems like we forgot to add the imports in the latest update. I opened #440 to fix this.

@phil-opp phil-opp changed the title Comments for "freestanding-rust-binary/" Comments for "https://os.phil-opp.com/freestanding-rust-binary/" Jun 27, 2018
Copy link

dodikk commented Jul 3, 2018

@phil-opp , thanks for a great series. Really well written and well explained (so much beginner-friendly).

What do you think about adding the platform annotations for the trampoline functions?

#[cfg(target_os = "windows")]
#[no_mangle]
pub extern "C" fn mainCRTStartup() -> ! {
    main();
}

@phil-opp
Copy link
Owner

phil-opp commented Jul 5, 2018

@dodikk

thanks for a great series. Really well written and well explained (so much beginner-friendly).

Thanks a lot!

What do you think about adding the platform annotations for the trampoline functions?

These functions are just used to get a compiling no_std executable on existing operating systems in the first post. It wouldn't make sense to keep them for the subsequent posts because our OS kernel won't ever run on top of Windows or macOS. Only adding the conditional compilation for the first post would be possible, but I don't think that it's worth it because it makes things more complicated and the functions are removed in the second post anyway.

Copy link

But you have two main() functions, one for Windows and one for MacOS.
It errors on it, am I missing something?

@phil-opp
Copy link
Owner

@AregevDev You should only use one of the three variants, depending on your host OS. So if you're on Windows, only add the Windows-style entry point and not the Linux and macOS entry points.

@andre-richter
Copy link
Contributor

andre-richter commented Aug 17, 2018

@AregevDev An alternative approach to having os-specific entrypoints would be the introduction of a custom linker script. There, you can define the entry-point function via ENTRY().

I think the first edition of the blog talked about it.

One way or the other, you have a little piece of inconvenience. When writing a kernel, though, in the long run you will probably end up with a custom linker script at some point anyways.

Copy link

panic_implementation : this attribute was renamed to panic_handler. See rust-lang/rust#44489 (comment)

Copy link

In addition to the panic_implementation being renamed, using the new name means you don't need the #![feature(panic_implementation)] anymore (or I believe the nightly?).

@phil-opp
Copy link
Owner

phil-opp commented Oct 1, 2018

@jaypatelani @jessejhein Thanks for reporting. I updated the blog in #468.

Copy link

cymno commented Oct 21, 2018

As of rustc 1.29.2 stable it is still necessary to use the nightly toolchain on Linux (and probably Mac), as the '-Z' option works only in nightly.

Copy link

fcogama commented Oct 27, 2018

Hi, playing around I'm getting the following linker error with Rust nightly build 1.31.0.

rustc 1.31.0-nightly (3e6f30ec3 2018-10-26)

error: linking with `cc` failed: exit code: 1                                                                                                                                                                      
  |                                                                                                                                                                                                                
  = note: "cc" "-Wl,--as-needed" "-Wl,-z,noexecstack" "-m64" "-nostartfiles" "-L" "/home/devop/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "/home/devop/workspace/tactical_os/target/debug/deps/tactical_os-091a9ff38ca58526.1lwzcx53g884pkrj.rcgu.o" "/home/devop/workspace/tactical_os/target/debug/deps/tactical_os-091a9ff38ca58526.1mxek59mmosxp1gr.rcgu.o" "/home/devop/workspace/tactical_os/target/debug/deps/tactical_os-091a9ff38ca58526.3vwhvtx17707okjv.rcgu.o" "/home/devop/workspace/tactical_os/target/debug/deps/tactical_os-091a9ff38ca58526.4k2fyypy62ab6aaa.rcgu.o" "/home/devop/workspace/tactical_os/target/debug/deps/tactical_os-091a9ff38ca58526.pmfm3pkes9s56eu.rcgu.o" "/home/devop/workspace/tactical_os/target/debug/deps/tactical_os-091a9ff38ca58526.u78q3renarfctfb.rcgu.o" "-o" "/home/devop/workspace/tactical_os/target/debug/deps/tactical_os-091a9ff38ca58526" "/home/devop/workspace/tactical_os/target/debug/deps/tactical_os-091a9ff38ca58526.36u6sdy3tifj0l3t.rcgu.o" "-Wl,--gc-sections" "-pie" "-Wl,-zrelro" "-Wl,-znow" "-nodefaultlibs" "-L" "/home/devop/workspace/tactical_os/target/debug/deps" "-L" "/home/devop/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-Wl,--start-group" "-Wl,-Bstatic" "/home/devop/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-749cdbe450dd7140.rlib" "/home/devop/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libpanic_abort-b02d3fe29f436127.rlib" "/home/devop/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc_jemalloc-cf548d84ef70130f.rlib" "/home/devop/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libunwind-1d3e911ab051fda4.rlib" "/home/devop/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc_system-b9cd5a1dfd88584e.rlib" "/home/devop/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liblibc-8f294fb62aa82289.rlib" "/home/devop/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc-b6501604988320ff.rlib" "/home/devop/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-56f5587bc5216ac9.rlib" "-Wl,--end-group" "/home/devop/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler_builtins-e578c298dc2b65d9.rlib" "-Wl,-Bdynamic" "-ldl" "-lrt" "-lpthread" "-lpthread" "-lgcc_s" "-lc" "-lm" "-lrt" "-lpthread" "-lutil" "-lutil"
  = note: /usr/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000000003370                                                                                                                    
          /usr/lib/x86_64-linux-gnu/libpthread_nonshared.a(pthread_atfork.oS): In function `__pthread_atfork':                                                                                                     
          /build/glibc-OTsEL5/glibc-2.27/nptl/pthread_atfork.c:51: undefined reference to `__dso_handle'                                                                                                           
          /usr/lib/x86_64-linux-gnu/libc_nonshared.a(atexit.oS): In function `atexit':                                                                                                                             
          (.text+0x3): undefined reference to `__dso_handle'                                                                                                                                                       
          /usr/bin/ld: /home/devop/workspace/tactical_os/target/debug/deps/tactical_os-091a9ff38ca58526: hidden symbol `__dso_handle' isn't defined                                                                
          /usr/bin/ld: final link failed: Bad value                                                                                                                                                                
          collect2: error: ld returned 1 exit status                                                                                                                                                               
                                                                                                                                                                                                                   
                                                                                                                                                                                                                   
error: aborting due to previous error                                                                                                                                                                              
                                                                                                                                                                                                                   
error: Could not compile `tactical_os`.                                                                                                                                                                            

To learn more, run the command again with --verbose.

@phil-opp
Copy link
Owner

@fcogama I never seen this one before. Are you using Linux? If yes, are you using a #[no_mangle] _start function and compiling with -Z pre-link-arg=-nostartfiles?

@phil-opp
Copy link
Owner

As of rustc 1.29.2 stable it is still necessary to use the nightly toolchain on Linux (and probably Mac), as the '-Z' option works only in nightly.

@cymno Sorry for the late reply! You're absolutely right. I opened #493 to fix this.

Copy link

With current rustc nightly, the errors printed with no panic handler defined no longer references panic_impl but instead says:

> cargo build
error: `#[panic_handler]` function required, but not found
error: language item required, but not found: `eh_personality`

@phil-opp
Copy link
Owner

@kballard Thanks! I updated the code and reworded the section in 298e714.

@guncha
Copy link

guncha commented Jan 24, 2019

This was super useful to get me started. Once I did, I ran into some seemingly arbitrary segfaults. Turns out the libc initialization does something useful after all! It aligns the stack to 16 bytes which is necessary for SSE instructions. So if you find that you're reliably getting SIGSEGV when executing xmmN instructions which can happen when destructuring tuples or passing large stack allocated arguments to a function, this is why.

#[no_mangle]
fn main() {
  // the actual main
}


#[no_mangle]
pub unsafe extern "C" fn _start() {
    // Align the stack to the 16 byte boundary as the stdlib C preamble would
    asm!(
        "
        and $$0xfffffffffffffff0, %rsp;
        call main;
    "
    );
}

@phil-opp
Copy link
Owner

@guncha Yeah, the x86_64 architecture requires that the stack is aligned on each function entry. The bootloader that we add in the next post should do this for our kernel.

Copy link

Adding the compiler flags in a .cargo/config in the root of the project like so:

[build]
rustflags = ["-C", "link-arg=-nostartfiles"]

keeps the build commands consistent accross OSes (cargo build)

@phil-opp
Copy link
Owner

phil-opp commented Apr 8, 2019

@mfournial Sorry for the late reply!

Adding the compiler flags in a .cargo/config in the root of the project like so:

[build]
rustflags = ["-C", "link-arg=-nostartfiles"]

keeps the build commands consistent accross OSes (cargo build)

So we don't need to pass -lSystem on macOS?

@phil-opp
Copy link
Owner

phil-opp commented Apr 8, 2019

@reesmanp I also thought about adding conditional compilation and a .cargo/config to keep the build command simple and platform independent. I decided against it because we no longer need these arguments when we compile for a custom target in the next post. I'll add a short notice to the post.

Copy link
Owner

phil-opp commented Apr 9, 2019

After rereading all the feedback in this thread, I decided to rewrite the section about overwriting the entry point. It now uses a different approach to fixing the linker errors: compile for a bare metal target. The existing section about the linker arguments still exists, but is now optional and hidden by default. I updated the arguments so that now _start is used on all OSs and also explained how to create a .cargo/config file. For more details see the pull request at #577.

Thank you all for your feedback and helping in improving this post!

Copy link

@phil-opp Thank you for all the hard work you've put into this blog. It's an amazing resource.

If anyone has issues completing the Linker Arguments portion on a Mac the following .cargo/config file worked for me (not tested on Linux and Windows yet).

[target.'cfg(target_os = "linux")']
rustflags = [
  "-C", "link-arg=-nostartfiles",
]

[target.'cfg(target_os = "windows")']
rustflags = [
  "-C", "link-arg=/ENTRY:_start",
  "-C", "link-arg=/SUBSYSTEM:console",
]

[target.'cfg(target_os = "macos")']
rustflags = [
  "-C", "link-arg=-lSystem",
  "-C", "link-arg=-e __start",
  "-C", "link-arg=-static",
  "-C", "link-arg=-nostartfiles",
]

The first change I made was separating the link-args into multiple link-arg arguments as it didn't seem to be parsing the spaces correctly. Then I added -lSystem to avoid the clang linker error ld: library not found for -lSystem.

@phil-opp
Copy link
Owner

@cstenger Thanks a lot :).

Interesting. I updated this section quite recently. I don't have a mac myself, so I was only able to test it on CI, where the command cargo rustc -- -C link-args="-e __start -static -nostartfiles" works fine on macOS. Does this command work for you, i.e. does the problem only occur with the cargo/.config file?

Copy link

cstenger commented Apr 15, 2019

Well, guess I'm going crazy. To ensure it wasn't due to any changes I had in my existing project, I started from scratch today. Everything worked as it should have. When calling rustc directly as well as from a config file, no "-lSystem" or multiple link-arg statements were required. Then I went back to the retrofitted project (where I encountered the issues), and it all worked there too. At this moment I don't know why the behavior doesn't match from the previous evening, if I'm able to reproduce it I'll be sure to document the circumstances. Hopefully my experiences haven't lead anyone astray.

@phil-opp
Copy link
Owner

@cstenger Thanks for the update! Let me know if you can reproduce the failure.

It's not that there's something wrong with -lSystem (it works too), I just want that the instructions on the blog work for everyone.

Copy link

ghost commented Jun 14, 2019

@phil-opp I followed each instruction here but I this happened:

C:\Users\Administrator\LunarOS>xargo +nightly build --target thumbv7em-none-eabihf --release --verbose
+ "rustc" "--print" "sysroot"
WARNING: the sysroot can't be built for the Stable channel. Switch to nightly.
+ "cargo" "+nightly" "build" "--target" "thumbv7em-none-eabihf" "--release" "--verbose"
   Compiling LunarOS v0.1.0 (C:\Users\Administrator\LunarOS)
     Running `rustc --edition=2018 --crate-name LunarOS src\main.rs --color always --crate-type bin --emit=dep-info,link -C opt-level=3 -C panic=abort -C metadata=b20ba269d00b8257 -C extra-filename=-b20ba269d00b8257 --out-dir C:\Users\Administrator\LunarOS\target\thumbv7em-none-eabihf\release\deps --target thumbv7em-none-eabihf -L dependency=C:\Users\Administrator\LunarOS\target\thumbv7em-none-eabihf\release\deps -L dependency=C:\Users\Administrator\LunarOS\target\release\deps`
error[E0463]: can't find crate for `core`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0463`.
error: Could not compile `LunarOS`.

Caused by:
  process didn't exit successfully: `rustc --edition=2018 --crate-name LunarOS src\main.rs --color always --crate-type bin --emit=dep-info,link -C opt-level=3 -C panic=abort -C metadata=b20ba269d00b8257 -C extra-filename=-b20ba269d00b8257 --out-dir C:\Users\Administrator\LunarOS\target\thumbv7em-none-eabihf\release\deps --target thumbv7em-none-eabihf -L dependency=C:\Users\Administrator\LunarOS\target\thumbv7em-none-eabihf\release\deps -L dependency=C:\Users\Administrator\LunarOS\target\release\deps` (exit code: 1)

How can I fix this?

System Info: OS Name Microsoft Windows 10 Home Version 10.0.17134 Build 17134 Other OS Description Not Available OS Manufacturer Microsoft Corporation System Name LAPTOP-FHA479JD System Manufacturer HP System Model OMEN by HP Laptop 15-ce0xx System Type x64-based PC System SKU 1KV79UA#ABA Processor Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz, 2808 Mhz, 4 Core(s), 8 Logical Processor(s) BIOS Version/Date American Megatrends Inc. F.10, 11/1/2017 SMBIOS Version 3.0 Embedded Controller Version 40.24 BIOS Mode UEFI BaseBoard Manufacturer HP BaseBoard Model Not Available BaseBoard Name Base Board Platform Role Mobile Secure Boot State On PCR7 Configuration Binding Possible Windows Directory C:\WINDOWS System Directory C:\WINDOWS\system32 Boot Device \Device\HarddiskVolume1 Locale United States Hardware Abstraction Layer Version = "10.0.17134.765" User Name LAPTOP-FHA479JD\Administrator Time Zone Eastern Daylight Time Installed Physical Memory (RAM) 8.00 GB Total Physical Memory 7.88 GB Available Physical Memory 2.66 GB Total Virtual Memory 12.9 GB Available Virtual Memory 5.42 GB Page File Space 5.00 GB Page File C:\pagefile.sys Kernel DMA Protection Off Virtualization-based security Not enabled Device Encryption Support Reasons for failed automatic device encryption: Hardware Security Test Interface failed and device is not InstantGo, Un-allowed DMA capable bus/device(s) detected Hyper-V - VM Monitor Mode Extensions Yes Hyper-V - Second Level Address Translation Extensions Yes Hyper-V - Virtualization Enabled in Firmware Yes Hyper-V - Data Execution Protection Yes

Edit(phil-opp): Cleaned up formatting.

Copy link

ghost commented Jun 14, 2019

but this happened*

@phil-opp
Copy link
Owner

@LiamTheProgrammer Is there a reason why you're using xargo instead of cargo-xbuild?

The problem seems to be that xargo does not use the +nightly argument when using the sysroot. As a result, it tries to build the sysroot with the default stable Rust compiler, which results in this warning:

WARNING: the sysroot can't be built for the Stable channel. Switch to nightly.

To fix this, you can either add a nightly override for the LunarOS directory using rustup override add nightly or create a rust-toolchain file with the content "nightly` in that folder.

Copy link

I am doing translation.And I have some doubts.
Can I think of the normal entry point chain as the normal entry point

@bjorn3
Copy link
Contributor

bjorn3 commented Dec 22, 2019

@thebegining Normally there is a #[lang = "start"] function defined in libstd which gets main as argument. This function first performs some initialization like setting up a stack guard and storing the arguments of the process at a specific location. It then calls main. By using #![no_main] there doesn't need to be a #[lang = "start"] function, instead you have to define the entrypoint of the executable yourself.

@Fibration
Copy link

@phil-opp Thanks for the tutorial. I have been enjoying following it so far. I am stuck at cargo xbuild and have checked against your files in the post-02 branch to make sure that everything is identical.

I am receiving the following error at the end of cargo xbuild:

error: cannot produce bin for `os v0.1.0` as the target `x86_64-os` does not support these crate types

Cargo now uses a more informative error message. Issue here. I assume that xbuild is still using an older version of cargo.

I could not get any further than that. Any insight you have would be great.

@phil-opp
Copy link
Owner

phil-opp commented Jan 5, 2020

@Fibration

Cargo now uses a more informative error message. Issue here. I assume that xbuild is still using an older version of cargo.

cargo-xbuild just calls out to the cargo you have installed. Maybe you did not add a nightly override for your directory (either though rustup override add or a rust-toolchain file) so that the default cargo is a stable version instead of a more recent nightly version?

Either way, the old error message contains the same number of information, it just uses a different formulation. The error indicates that your target does not support the bin crate type, which likely means that you don't have the "executables": true line in your target JSON:

"executables": true,

Note that needs to be executables (plural), not executable. Unfortunately, cargo just ignores invalid target configuration keys instead of throwing an error for them.

I hope this solves your issue!

@Lokathor
Copy link

Infinite loop with no side effect is UB because of LLVM problems.

there is a -Z flag to fix this, rust-lang/rust#59546

Or you can just volatile read a local variable over and over (or any other side effect of of choice).

Copy link

Thank you.

@phil-opp
Copy link
Owner

@Lokathor Thanks for your comment! I'm aware of that issue. Everytime I look at it it seems like it is close to being solved, so I always thinks that it's not worth it to mention it on the blog. However, since the issue now persists for multiple years, you're probably right that we should fix it on the blog too. I opened #793 to track this.

@phil-opp
Copy link
Owner

@jerryajay You're welcome!

Copy link
Contributor

briankung commented Sep 17, 2020

Our freestanding executable does not have access to the Rust runtime and crt0, so we need to define our own entry point. Implementing the start language item wouldn't help, since it would still require crt0. Instead, we need to overwrite the crt0 entry point directly...The reason for naming the function _start is that this is the default entry point name for most systems.

What system or systems are responsible for calling the _start entrypoint?

@Lokathor
Copy link

since this booted to, i presume the linker is configured by default to arrange the binary for the _start to be at the initial address that the bootloader jumps to.

@briankung
Copy link
Contributor

Thank you!

Copy link

dy9-spec commented Dec 9, 2020

Thanks for the work & sponsor the blog already!

@phil-opp
Copy link
Owner

@dy9-spec Thanks a lot for your support!

Copy link

shouze commented Feb 9, 2021

Nice!

Copy link

cargo build
error: #[panic_handler] function required, but not found
error: language item required, but not found: eh_personality

I just pass the build without the errors...

@bjorn3
Copy link
Contributor

bjorn3 commented Mar 29, 2021

Do you have -Cpanic=abort somewhere in your env or you have panic=abort in a global .cargo/config.toml? What does cargo build -v show after you made a small change to your code to force a rebuild?

Copy link

Rdna123 commented May 6, 2021

What nightly version is this.

Repository owner locked and limited conversation to collaborators Jun 12, 2021

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
None yet
Projects
None yet
Development

No branches or pull requests