Skip to content

Commit f770e97

Browse files
bors[bot]phil-opp
andcommitted
Merge #55
55: Version 0.6.0 r=phil-opp a=phil-opp The main change of this PR is to remove the `#[cfg(not(test))]` attribute from the `entry_point` macro. This makes it possible to use the macro together with custom test frameworks and `cargo xtest`. Since this is a breaking change, this PR bumps the version to 0.6.0. This PR also adds two additional checks to the build script: - check that the kernel exists early to provide a better error message - check that the kernel has a non-empty text section - an empty text section can occur if no entry point is set - this turns a runtime error (bootloader panics when loading the kernel) into a compile time error Co-authored-by: Philipp Oppermann <[email protected]>
2 parents 1affb83 + e5cc7fb commit f770e97

File tree

5 files changed

+48
-7
lines changed

5 files changed

+48
-7
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ cargo-features = ["publish-lockfile"]
22

33
[package]
44
name = "bootloader"
5-
version = "0.5.3"
5+
version = "0.6.0"
66
authors = ["Philipp Oppermann <[email protected]>"]
77
license = "MIT/Apache-2.0"
88
description = "An experimental pure-Rust x86 bootloader."

Changelog.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
# 0.6.0
2+
3+
## Breaking
4+
5+
- Don't set the `#[cfg(not(test))]` attribute for the entry point function in the `entry_point` macro
6+
- With custom test frameworks, it's possible to use the normal entry point also in test environments
7+
- To get the old behavior, you can add the `#[cfg(not(test))]` attribute to the `entry_point` invocation
8+
9+
## Other
10+
11+
- Additional assertions for the passed `KERNEL` executable
12+
- check that the executable exists (for better error messages)
13+
- check that the executable has a non-empty text section (an empty text section occurs when no entry point is set)
14+
115
# 0.5.3
216

317
- Mention minimal required bootimage version in error message when `KERNEL` environment variable is not set.

build.rs

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ fn main() {
2727
}
2828
});
2929

30+
// check that the kernel file exists
31+
assert!(
32+
kernel.exists(),
33+
format!("KERNEL does not exist: {}", kernel.display())
34+
);
35+
3036
let kernel_file_name = kernel
3137
.file_name()
3238
.expect("KERNEL has no valid file name")
@@ -36,6 +42,7 @@ fn main() {
3642
let kernel_out_path = out_dir.join(format!("kernel_bin-{}.o", kernel_file_name));
3743
let kernel_archive_path = out_dir.join(format!("libkernel_bin-{}.a", kernel_file_name));
3844

45+
// get access to llvm tools shipped in the llvm-tools-preview rustup component
3946
let llvm_tools = match llvm_tools::LlvmTools::new() {
4047
Ok(tools) => tools,
4148
Err(llvm_tools::Error::NotFound) => {
@@ -49,10 +56,28 @@ fn main() {
4956
process::exit(1);
5057
}
5158
};
59+
60+
// check that kernel executable has code in it
61+
let llvm_size = llvm_tools
62+
.tool(&llvm_tools::exe("llvm-size"))
63+
.expect("llvm-size not found in llvm-tools");
64+
let mut cmd = Command::new(llvm_size);
65+
cmd.arg(&kernel);
66+
let output = cmd.output().expect("failed to run llvm-size");
67+
let output_str = String::from_utf8_lossy(&output.stdout);
68+
let second_line_opt = output_str.lines().skip(1).next();
69+
let second_line = second_line_opt.expect("unexpected llvm-size line output");
70+
let text_size_opt = second_line.split_ascii_whitespace().next();
71+
let text_size = text_size_opt.expect("unexpected llvm-size output");
72+
if text_size == "0" {
73+
panic!("Kernel executable has an empty text section. Perhaps the entry point was set incorrectly?\n\n\
74+
Kernel executable at `{}`\n", kernel.display());
75+
}
76+
77+
// wrap the kernel executable as binary in a new ELF file
5278
let objcopy = llvm_tools
5379
.tool(&llvm_tools::exe("llvm-objcopy"))
5480
.expect("llvm-objcopy not found in llvm-tools");
55-
5681
let mut cmd = Command::new(objcopy);
5782
cmd.arg("-I").arg("binary");
5883
cmd.arg("-O").arg("elf64-x86-64");
@@ -79,6 +104,7 @@ fn main() {
79104
process::exit(1);
80105
}
81106

107+
// create an archive for linking
82108
let ar = llvm_tools
83109
.tool(&llvm_tools::exe("llvm-ar"))
84110
.unwrap_or_else(|| {
@@ -97,12 +123,14 @@ fn main() {
97123
process::exit(1);
98124
}
99125

100-
println!("cargo:rerun-if-env-changed=KERNEL");
101-
println!("cargo:rerun-if-changed={}", kernel.display());
102-
println!("cargo:rerun-if-changed=build.rs");
126+
// pass link arguments to rustc
103127
println!("cargo:rustc-link-search=native={}", out_dir.display());
104128
println!(
105129
"cargo:rustc-link-lib=static=kernel_bin-{}",
106130
kernel_file_name
107131
);
132+
133+
println!("cargo:rerun-if-env-changed=KERNEL");
134+
println!("cargo:rerun-if-changed={}", kernel.display());
135+
println!("cargo:rerun-if-changed=build.rs");
108136
}

src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ pub mod bootinfo;
2222
#[macro_export]
2323
macro_rules! entry_point {
2424
($path:path) => {
25-
#[cfg(not(test))]
2625
#[export_name = "_start"]
2726
pub extern "C" fn __impl_start(boot_info: &'static $crate::bootinfo::BootInfo) -> ! {
2827
// validate the signature of the program entry point

0 commit comments

Comments
 (0)