Pub and no_mangle are no longer required for panic_handler (#468)

This commit is contained in:
Philipp Oppermann
2018-10-01 13:11:39 +02:00
committed by GitHub
parent 2dd925d34d
commit 6f48a17ba4
10 changed files with 39 additions and 48 deletions

View File

@@ -143,8 +143,7 @@ use core::panic::PanicInfo;
/// This function is called on panic. /// This function is called on panic.
#[panic_handler] #[panic_handler]
#[no_mangle] fn panic(_info: &PanicInfo) -> ! {
pub fn panic(_info: &PanicInfo) -> ! {
loop {} 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 [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 [“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: 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. /// This function is called on panic.
#[panic_handler] #[panic_handler]
#[no_mangle] fn panic(_info: &PanicInfo) -> ! {
pub fn panic(_info: &PanicInfo) -> ! {
loop {} loop {}
} }
``` ```
@@ -313,8 +297,7 @@ use core::panic::PanicInfo;
/// This function is called on panic. /// This function is called on panic.
#[panic_handler] #[panic_handler]
#[no_mangle] fn panic(_info: &PanicInfo) -> ! {
pub fn panic(_info: &PanicInfo) -> ! {
loop {} loop {}
} }

View File

@@ -206,8 +206,7 @@ use core::panic::PanicInfo;
/// This function is called on panic. /// This function is called on panic.
#[panic_handler] #[panic_handler]
#[no_mangle] fn panic(_info: &PanicInfo) -> ! {
pub fn panic(_info: &PanicInfo) -> ! {
loop {} 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. 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 #### 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 [`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`. 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 > 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 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. 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.

View File

@@ -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. /// This function is called on panic.
#[panic_handler] #[panic_handler]
#[no_mangle] fn panic(info: &PanicInfo) -> ! {
pub fn panic(info: &PanicInfo) -> ! {
println!("{}", info); println!("{}", info);
loop {} loop {}
} }

View File

@@ -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`. error[E0152]: duplicate lang item found: `panic_impl`.
--> src/main.rs:35:1 --> src/main.rs:35:1
| |
35 | / pub fn panic(info: &PanicInfo) -> ! { 35 | / fn panic(info: &PanicInfo) -> ! {
36 | | println!("{}", info); 36 | | println!("{}", info);
37 | | loop {} 37 | | loop {}
38 | | } 38 | | }
@@ -49,8 +49,7 @@ use core::panic::PanicInfo;
#[cfg(not(test))] // only compile when the test flag is not set #[cfg(not(test))] // only compile when the test flag is not set
#[panic_handler] #[panic_handler]
#[no_mangle] fn panic(info: &PanicInfo) -> ! {
pub fn panic(info: &PanicInfo) -> ! {
println!("{}", info); println!("{}", info);
loop {} loop {}
} }

View File

@@ -344,8 +344,7 @@ pub extern "C" fn _start() -> ! {
#[cfg(not(test))] #[cfg(not(test))]
#[panic_handle] #[panic_handle]
#[no_mangle] fn panic(_info: &PanicInfo) -> ! {
pub fn panic(_info: &PanicInfo) -> ! {
loop {} loop {}
} }
``` ```
@@ -424,8 +423,7 @@ pub extern "C" fn _start() -> ! {
/// This function is called on panic. /// This function is called on panic.
#[cfg(not(test))] #[cfg(not(test))]
#[panic_handler] #[panic_handler]
#[no_mangle] fn panic(info: &PanicInfo) -> ! {
pub fn panic(info: &PanicInfo) -> ! {
println!("{}", info); println!("{}", info);
loop {} loop {}
} }
@@ -488,8 +486,7 @@ pub extern "C" fn _start() -> ! {
/// This function is called on panic. /// This function is called on panic.
#[cfg(not(test))] #[cfg(not(test))]
#[panic_handler] #[panic_handler]
#[no_mangle] fn panic(info: &PanicInfo) -> ! {
pub fn panic(info: &PanicInfo) -> ! {
serial_println!("failed"); serial_println!("failed");
serial_println!("{}", info); serial_println!("{}", info);
@@ -546,8 +543,7 @@ pub extern "C" fn _start() -> ! {
#[cfg(not(test))] #[cfg(not(test))]
#[panic_handler] #[panic_handler]
#[no_mangle] fn panic(_info: &PanicInfo) -> ! {
pub fn panic(_info: &PanicInfo) -> ! {
serial_println!("ok"); serial_println!("ok");
unsafe { exit_qemu(); } unsafe { exit_qemu(); }

View File

@@ -25,8 +25,7 @@ pub extern "C" fn _start() -> ! {
/// This function is called on panic. /// This function is called on panic.
#[cfg(not(test))] #[cfg(not(test))]
#[panic_handler] #[panic_handler]
#[no_mangle] fn panic(info: &PanicInfo) -> ! {
pub fn panic(info: &PanicInfo) -> ! {
serial_println!("failed"); serial_println!("failed");
serial_println!("{}", info); serial_println!("{}", info);

View File

@@ -45,8 +45,7 @@ pub extern "C" fn _start() -> ! {
/// This function is called on panic. /// This function is called on panic.
#[cfg(not(test))] #[cfg(not(test))]
#[panic_handler] #[panic_handler]
#[no_mangle] fn panic(info: &PanicInfo) -> ! {
pub fn panic(info: &PanicInfo) -> ! {
serial_println!("failed"); serial_println!("failed");
serial_println!("{}", info); serial_println!("{}", info);

View File

@@ -39,8 +39,7 @@ pub extern "C" fn _start() -> ! {
/// This function is called on panic. /// This function is called on panic.
#[cfg(not(test))] #[cfg(not(test))]
#[panic_handler] #[panic_handler]
#[no_mangle] fn panic(info: &PanicInfo) -> ! {
pub fn panic(info: &PanicInfo) -> ! {
serial_println!("failed"); serial_println!("failed");
serial_println!("{}", info); serial_println!("{}", info);

View File

@@ -16,8 +16,7 @@ pub extern "C" fn _start() -> ! {
#[cfg(not(test))] #[cfg(not(test))]
#[panic_handler] #[panic_handler]
#[no_mangle] fn panic(_info: &PanicInfo) -> ! {
pub fn panic(_info: &PanicInfo) -> ! {
serial_println!("ok"); serial_println!("ok");
unsafe { unsafe {

View File

@@ -35,8 +35,7 @@ pub extern "C" fn _start() -> ! {
/// This function is called on panic. /// This function is called on panic.
#[cfg(not(test))] #[cfg(not(test))]
#[panic_handler] #[panic_handler]
#[no_mangle] fn panic(info: &PanicInfo) -> ! {
pub fn panic(info: &PanicInfo) -> ! {
println!("{}", info); println!("{}", info);
loop {} loop {}
} }