mirror of
https://github.com/phil-opp/blog_os.git
synced 2025-12-16 22:37:49 +00:00
Pub and no_mangle are no longer required for panic_handler (#468)
This commit is contained in:
committed by
GitHub
parent
2dd925d34d
commit
6f48a17ba4
@@ -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 {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|
||||||
|
|||||||
@@ -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 {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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(); }
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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 {}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user