From 6f48a17ba425ae341bd04671c36778e2a6d6f4b8 Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Mon, 1 Oct 2018 13:11:39 +0200 Subject: [PATCH] Pub and no_mangle are no longer required for panic_handler (#468) --- .../01-freestanding-rust-binary/index.md | 23 ++------------- .../posts/02-minimal-rust-kernel/index.md | 29 +++++++++++++++---- .../posts/03-vga-text-buffer/index.md | 3 +- .../posts/04-unit-testing/index.md | 5 ++-- .../posts/05-integration-tests/index.md | 12 +++----- src/bin/test-basic-boot.rs | 3 +- src/bin/test-exception-breakpoint.rs | 3 +- ...t-exception-double-fault-stack-overflow.rs | 3 +- src/bin/test-panic.rs | 3 +- src/main.rs | 3 +- 10 files changed, 39 insertions(+), 48 deletions(-) diff --git a/blog/content/second-edition/posts/01-freestanding-rust-binary/index.md b/blog/content/second-edition/posts/01-freestanding-rust-binary/index.md index 35a6992c..ce4eb86e 100644 --- a/blog/content/second-edition/posts/01-freestanding-rust-binary/index.md +++ b/blog/content/second-edition/posts/01-freestanding-rust-binary/index.md @@ -143,8 +143,7 @@ use core::panic::PanicInfo; /// This function is called on panic. #[panic_handler] -#[no_mangle] -pub fn panic(_info: &PanicInfo) -> ! { +fn panic(_info: &PanicInfo) -> ! { loop {} } ``` @@ -155,20 +154,6 @@ The [`PanicInfo` parameter][PanicInfo] contains the file and line where the pani [diverging function]: https://doc.rust-lang.org/book/first-edition/functions.html#diverging-functions [“never” type]: https://doc.rust-lang.org/nightly/std/primitive.never.html -When we try `cargo build` now, we get an error that “#[panic_handler] is an unstable feature”. - -#### Enabling Unstable Features - -The `panic_handler` attribute was recently added and is thus still unstable and protected by a so-called _feature gate_. A feature gate is a special attribute that you have to specify at the top of your `main.rs` in order to use the corresponding feature. By doing this you basically say: “I know that this feature is unstable and that it might stop working without any warnings. I want to use it anyway.” - -Feature gates are not available in the stable or beta Rust compilers, only [nightly Rust] makes it possible to opt-in. This means that you have to use a nightly compiler for OS development for the near future (until all unstable features that we need are added are stabilized). - -[nightly Rust]: https://doc.rust-lang.org/book/first-edition/release-channels.html - -To manage Rust installations I highly recommend [rustup]. It allows you to install nightly, beta, and stable compilers side-by-side and makes it easy to update them. To use a nightly compiler for the current directory, you can run `rustup override add nightly`. Alternatively, you can add a file called `rust-toolchain` with the content `nightly` to the project's root directory. - -[rustup]: https://www.rustup.rs/ - Now we fixed both language item errors. However, if we try to compile it now, another language item is required: ``` @@ -199,8 +184,7 @@ use core::panic::PanicInfo; /// This function is called on panic. #[panic_handler] -#[no_mangle] -pub fn panic(_info: &PanicInfo) -> ! { +fn panic(_info: &PanicInfo) -> ! { loop {} } ``` @@ -313,8 +297,7 @@ use core::panic::PanicInfo; /// This function is called on panic. #[panic_handler] -#[no_mangle] -pub fn panic(_info: &PanicInfo) -> ! { +fn panic(_info: &PanicInfo) -> ! { loop {} } diff --git a/blog/content/second-edition/posts/02-minimal-rust-kernel/index.md b/blog/content/second-edition/posts/02-minimal-rust-kernel/index.md index 1c43c698..b61e1e39 100644 --- a/blog/content/second-edition/posts/02-minimal-rust-kernel/index.md +++ b/blog/content/second-edition/posts/02-minimal-rust-kernel/index.md @@ -206,8 +206,7 @@ use core::panic::PanicInfo; /// This function is called on panic. #[panic_handler] -#[no_mangle] -pub fn panic(_info: &PanicInfo) -> ! { +fn panic(_info: &PanicInfo) -> ! { loop {} } @@ -238,7 +237,7 @@ It fails! The error tells us that the Rust compiler no longer finds the `core` o The problem is that the core library is distributed together with the Rust compiler as a _precompiled_ library. So it is only valid for supported host triples (e.g., `x86_64-unknown-linux-gnu`) but not for our custom target. If we want to compile code for other targets, we need to recompile `core` for these targets first. #### Cargo xbuild -That's where [`cargo xbuild`] comes in. It is a wrapper for `cargo build` that automatically cross-compiles the built-in libraries. We can install it by executing: +That's where [`cargo xbuild`] comes in. It is a wrapper for `cargo build` that automatically cross-compiles `core` and other built-in libraries. We can install it by executing: [`cargo xbuild`]: https://github.com/rust-osdev/cargo-xbuild @@ -248,7 +247,27 @@ cargo install cargo-xbuild The command depends on the rust source code, which we can install with `rustup component add rust-src`. -We now can rerun the above command with `xbuild` instead of `build`: +Now we can rerun the above command with `xbuild` instead of `build`: + +``` +> cargo xbuild --target x86_64-blog_os.json +``` + +Depending on your version of the Rust compiler you might get the following error: + +``` +error: The sysroot can't be built for the Stable channel. Switch to nightly. +``` + +To understand this error, you need to know that the Rust compiler has three release channels: _stable_, _beta_, and _nightly_. The Rust Book explains the difference between these channels really well, so take a minute and [check it out](https://doc.rust-lang.org/book/second-edition/appendix-07-nightly-rust.html#choo-choo-release-channels-and-riding-the-trains). + +Some experimental features are only available on the nightly channel. Since Rust uses many of these features for the internal implementation of `core` and other built-in libraries, we need to use a nightly compiler when invoking `cargo xbuild` (since it rebuilds these libraries). + +To manage Rust installations I highly recommend [rustup]. It allows you to install nightly, beta, and stable compilers side-by-side and makes it easy to update them. With rustup you can use a nightly compiler for the current directory by running `rustup override add nightly`. Alternatively, you can add a file called `rust-toolchain` with the content `nightly` to the project's root directory. + +[rustup]: https://www.rustup.rs/ + +With a nightly compiler the build finally succeeds: ``` > cargo xbuild --target x86_64-blog_os.json @@ -260,7 +279,7 @@ We now can rerun the above command with `xbuild` instead of `build`: Finished dev [unoptimized + debuginfo] target(s) in 0.29 secs ``` -It worked! We see that `cargo xbuild` cross-compiled the `core`, `compiler_builtin`, and `alloc` libraries for our new custom target and then continued to compile our `blog_os` crate. +We see that `cargo xbuild` cross-compiled the `core`, `compiler_builtin`, and `alloc` libraries for our new custom target and then continued to compile our `blog_os` crate. Now we are able to build our kernel for a bare metal target. However, our `_start` entry point, which will be called by the boot loader, is still empty. So let's output something to screen from it. diff --git a/blog/content/second-edition/posts/03-vga-text-buffer/index.md b/blog/content/second-edition/posts/03-vga-text-buffer/index.md index c0bd5ddf..0c4e9bed 100644 --- a/blog/content/second-edition/posts/03-vga-text-buffer/index.md +++ b/blog/content/second-edition/posts/03-vga-text-buffer/index.md @@ -628,8 +628,7 @@ Now that we have a `println` macro, we can use it in our panic function to print /// This function is called on panic. #[panic_handler] -#[no_mangle] -pub fn panic(info: &PanicInfo) -> ! { +fn panic(info: &PanicInfo) -> ! { println!("{}", info); loop {} } diff --git a/blog/content/second-edition/posts/04-unit-testing/index.md b/blog/content/second-edition/posts/04-unit-testing/index.md index 14f34959..7d6f80cc 100644 --- a/blog/content/second-edition/posts/04-unit-testing/index.md +++ b/blog/content/second-edition/posts/04-unit-testing/index.md @@ -28,7 +28,7 @@ Unfortunately it's a bit more complicated for `no_std` applications such as our error[E0152]: duplicate lang item found: `panic_impl`. --> src/main.rs:35:1 | -35 | / pub fn panic(info: &PanicInfo) -> ! { +35 | / fn panic(info: &PanicInfo) -> ! { 36 | | println!("{}", info); 37 | | loop {} 38 | | } @@ -49,8 +49,7 @@ use core::panic::PanicInfo; #[cfg(not(test))] // only compile when the test flag is not set #[panic_handler] -#[no_mangle] -pub fn panic(info: &PanicInfo) -> ! { +fn panic(info: &PanicInfo) -> ! { println!("{}", info); loop {} } diff --git a/blog/content/second-edition/posts/05-integration-tests/index.md b/blog/content/second-edition/posts/05-integration-tests/index.md index 87955717..083d6c9a 100644 --- a/blog/content/second-edition/posts/05-integration-tests/index.md +++ b/blog/content/second-edition/posts/05-integration-tests/index.md @@ -344,8 +344,7 @@ pub extern "C" fn _start() -> ! { #[cfg(not(test))] #[panic_handle] -#[no_mangle] -pub fn panic(_info: &PanicInfo) -> ! { +fn panic(_info: &PanicInfo) -> ! { loop {} } ``` @@ -424,8 +423,7 @@ pub extern "C" fn _start() -> ! { /// This function is called on panic. #[cfg(not(test))] #[panic_handler] -#[no_mangle] -pub fn panic(info: &PanicInfo) -> ! { +fn panic(info: &PanicInfo) -> ! { println!("{}", info); loop {} } @@ -488,8 +486,7 @@ pub extern "C" fn _start() -> ! { /// This function is called on panic. #[cfg(not(test))] #[panic_handler] -#[no_mangle] -pub fn panic(info: &PanicInfo) -> ! { +fn panic(info: &PanicInfo) -> ! { serial_println!("failed"); serial_println!("{}", info); @@ -546,8 +543,7 @@ pub extern "C" fn _start() -> ! { #[cfg(not(test))] #[panic_handler] -#[no_mangle] -pub fn panic(_info: &PanicInfo) -> ! { +fn panic(_info: &PanicInfo) -> ! { serial_println!("ok"); unsafe { exit_qemu(); } diff --git a/src/bin/test-basic-boot.rs b/src/bin/test-basic-boot.rs index 223ca6a4..9b891aad 100644 --- a/src/bin/test-basic-boot.rs +++ b/src/bin/test-basic-boot.rs @@ -25,8 +25,7 @@ pub extern "C" fn _start() -> ! { /// This function is called on panic. #[cfg(not(test))] #[panic_handler] -#[no_mangle] -pub fn panic(info: &PanicInfo) -> ! { +fn panic(info: &PanicInfo) -> ! { serial_println!("failed"); serial_println!("{}", info); diff --git a/src/bin/test-exception-breakpoint.rs b/src/bin/test-exception-breakpoint.rs index 9e3ae7ec..e6150acf 100644 --- a/src/bin/test-exception-breakpoint.rs +++ b/src/bin/test-exception-breakpoint.rs @@ -45,8 +45,7 @@ pub extern "C" fn _start() -> ! { /// This function is called on panic. #[cfg(not(test))] #[panic_handler] -#[no_mangle] -pub fn panic(info: &PanicInfo) -> ! { +fn panic(info: &PanicInfo) -> ! { serial_println!("failed"); serial_println!("{}", info); diff --git a/src/bin/test-exception-double-fault-stack-overflow.rs b/src/bin/test-exception-double-fault-stack-overflow.rs index 5ed15e41..876e4486 100644 --- a/src/bin/test-exception-double-fault-stack-overflow.rs +++ b/src/bin/test-exception-double-fault-stack-overflow.rs @@ -39,8 +39,7 @@ pub extern "C" fn _start() -> ! { /// This function is called on panic. #[cfg(not(test))] #[panic_handler] -#[no_mangle] -pub fn panic(info: &PanicInfo) -> ! { +fn panic(info: &PanicInfo) -> ! { serial_println!("failed"); serial_println!("{}", info); diff --git a/src/bin/test-panic.rs b/src/bin/test-panic.rs index 15075755..64131b86 100644 --- a/src/bin/test-panic.rs +++ b/src/bin/test-panic.rs @@ -16,8 +16,7 @@ pub extern "C" fn _start() -> ! { #[cfg(not(test))] #[panic_handler] -#[no_mangle] -pub fn panic(_info: &PanicInfo) -> ! { +fn panic(_info: &PanicInfo) -> ! { serial_println!("ok"); unsafe { diff --git a/src/main.rs b/src/main.rs index 52059a2a..bb7e1a92 100644 --- a/src/main.rs +++ b/src/main.rs @@ -35,8 +35,7 @@ pub extern "C" fn _start() -> ! { /// This function is called on panic. #[cfg(not(test))] #[panic_handler] -#[no_mangle] -pub fn panic(info: &PanicInfo) -> ! { +fn panic(info: &PanicInfo) -> ! { println!("{}", info); loop {} }