Make stripping ELF optional for QEMU direct boot

This commit is contained in:
Zhang Junyang 2024-05-17 15:26:14 +00:00 committed by Tate, Hongliang Tian
parent 32b1fb3723
commit f420286920
7 changed files with 57 additions and 27 deletions

View File

@ -27,6 +27,7 @@ args = "$(./tools/qemu_args.sh test)"
[scheme."microvm"] [scheme."microvm"]
boot.method = "qemu-direct" boot.method = "qemu-direct"
build.strip_elf = true
qemu.args = "$(./tools/qemu_args.sh microvm)" qemu.args = "$(./tools/qemu_args.sh microvm)"
[scheme."iommu"] [scheme."iommu"]

View File

@ -54,6 +54,8 @@ To display the GRUB menu if booting with GRUB
Path of QEMU Path of QEMU
- `--qemu-args <ARGS>`: - `--qemu-args <ARGS>`:
Extra arguments for running QEMU Extra arguments for running QEMU
- `--strip-elf`:
Whether to strip the built kernel ELF using `rust-strip`
## Examples ## Examples

View File

@ -43,6 +43,7 @@ supported_archs = ["x86_64"]# List of strings, that the arch the schema can appl
[build] [build]
features = [] # List of strings, the same as Cargo features = [] # List of strings, the same as Cargo
profile = "dev" # String, the same as Cargo profile = "dev" # String, the same as Cargo
strip_elf = false # Whether to strip the built kernel ELF using `rust-strip`
[boot] [boot]
method = "qemu-direct" # "grub-rescue-iso"/"qemu-direct"/"grub-qcow2" method = "qemu-direct" # "grub-rescue-iso"/"qemu-direct"/"grub-qcow2"
kcmd_args = [] # <1> kcmd_args = [] # <1>

View File

@ -264,6 +264,12 @@ pub struct CommonArgs {
global = true global = true
)] )]
pub linux_x86_legacy_boot: bool, pub linux_x86_legacy_boot: bool,
#[arg(
long = "strip-elf",
help = "Strip the built kernel ELF file for a smaller size",
global = true
)]
pub strip_elf: bool,
#[arg( #[arg(
long = "target-arch", long = "target-arch",
value_name = "ARCH", value_name = "ARCH",

View File

@ -68,8 +68,8 @@ pub fn make_install_bzimage(
) )
} }
pub fn strip_elf_for_qemu(install_dir: impl AsRef<Path>, elf: &AsterBin) -> AsterBin { pub fn make_elf_for_qemu(install_dir: impl AsRef<Path>, elf: &AsterBin, strip: bool) -> AsterBin {
let stripped_elf_path = { let result_elf_path = {
let elf_name = elf let elf_name = elf
.path() .path()
.file_name() .file_name()
@ -77,29 +77,34 @@ pub fn strip_elf_for_qemu(install_dir: impl AsRef<Path>, elf: &AsterBin) -> Aste
.to_str() .to_str()
.unwrap() .unwrap()
.to_string(); .to_string();
install_dir.as_ref().join(elf_name + ".stripped.elf") install_dir.as_ref().join(elf_name + ".qemu_elf")
}; };
// We use rust-strip to reduce the kernel image size. if strip {
let status = Command::new("rust-strip") // We use rust-strip to reduce the kernel image size.
.arg(elf.path()) let status = Command::new("rust-strip")
.arg("-o") .arg(elf.path())
.arg(stripped_elf_path.as_os_str()) .arg("-o")
.status(); .arg(result_elf_path.as_os_str())
.status();
match status { match status {
Ok(status) => { Ok(status) => {
if !status.success() { if !status.success() {
panic!("Failed to strip kernel elf."); panic!("Failed to strip kernel elf.");
}
} }
Err(err) => match err.kind() {
std::io::ErrorKind::NotFound => panic!(
"`rust-strip` command not found. Please
try `cargo install cargo-binutils` and then rerun."
),
_ => panic!("Strip kernel elf failed, err:{:#?}", err),
},
} }
Err(err) => match err.kind() { } else {
std::io::ErrorKind::NotFound => panic!( // Copy the ELF file.
"`rust-strip` command not found. Please std::fs::copy(elf.path(), &result_elf_path).unwrap();
try `cargo install cargo-binutils` and then rerun."
),
_ => panic!("Strip kernel elf failed, err:{:#?}", err),
},
} }
// Because QEMU denies a x86_64 multiboot ELF file (GRUB2 accept it, btw), // Because QEMU denies a x86_64 multiboot ELF file (GRUB2 accept it, btw),
@ -110,7 +115,7 @@ pub fn strip_elf_for_qemu(install_dir: impl AsRef<Path>, elf: &AsterBin) -> Aste
let mut file = OpenOptions::new() let mut file = OpenOptions::new()
.read(true) .read(true)
.write(true) .write(true)
.open(&stripped_elf_path) .open(&result_elf_path)
.unwrap(); .unwrap();
let bytes: [u8; 2] = [0x03, 0x00]; let bytes: [u8; 2] = [0x03, 0x00];
@ -120,7 +125,7 @@ pub fn strip_elf_for_qemu(install_dir: impl AsRef<Path>, elf: &AsterBin) -> Aste
file.flush().unwrap(); file.flush().unwrap();
AsterBin::new( AsterBin::new(
&stripped_elf_path, &result_elf_path,
AsterBinType::Elf(AsterElfMeta { AsterBinType::Elf(AsterElfMeta {
has_linux_header: false, has_linux_header: false,
has_pvh_header: false, has_pvh_header: false,
@ -128,7 +133,7 @@ pub fn strip_elf_for_qemu(install_dir: impl AsRef<Path>, elf: &AsterBin) -> Aste
has_multiboot2_header: true, has_multiboot2_header: true,
}), }),
elf.version().clone(), elf.version().clone(),
true, strip,
) )
} }

View File

@ -10,7 +10,7 @@ use std::{
time::{Duration, SystemTime}, time::{Duration, SystemTime},
}; };
use bin::strip_elf_for_qemu; use bin::make_elf_for_qemu;
use super::util::{cargo, profile_name_adapter, COMMON_CARGO_ARGS, DEFAULT_TARGET_RELPATH}; use super::util::{cargo, profile_name_adapter, COMMON_CARGO_ARGS, DEFAULT_TARGET_RELPATH};
use crate::{ use crate::{
@ -169,10 +169,11 @@ pub fn do_build(
action, action,
); );
bundle.consume_vm_image(bootdev_image); bundle.consume_vm_image(bootdev_image);
bundle.consume_aster_bin(aster_elf);
} }
BootMethod::QemuDirect => { BootMethod::QemuDirect => {
let stripped_elf = strip_elf_for_qemu(&osdk_output_directory, &aster_elf); let qemu_elf = make_elf_for_qemu(&osdk_output_directory, &aster_elf, build.strip_elf);
bundle.consume_aster_bin(stripped_elf); bundle.consume_aster_bin(qemu_elf);
} }
BootMethod::GrubQcow2 => { BootMethod::GrubQcow2 => {
todo!() todo!()

View File

@ -13,6 +13,7 @@ pub enum ActionChoice {
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct BuildScheme { pub struct BuildScheme {
pub profile: Option<String>, pub profile: Option<String>,
#[serde(default)]
pub features: Vec<String>, pub features: Vec<String>,
#[serde(default)] #[serde(default)]
pub no_default_features: bool, pub no_default_features: bool,
@ -20,11 +21,14 @@ pub struct BuildScheme {
/// [Linux legacy x86 32-bit boot protocol](https://www.kernel.org/doc/html/v5.6/x86/boot.html) /// [Linux legacy x86 32-bit boot protocol](https://www.kernel.org/doc/html/v5.6/x86/boot.html)
#[serde(default)] #[serde(default)]
pub linux_x86_legacy_boot: bool, pub linux_x86_legacy_boot: bool,
#[serde(default)]
pub strip_elf: bool,
} }
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Build { pub struct Build {
pub profile: String, pub profile: String,
#[serde(default)]
pub features: Vec<String>, pub features: Vec<String>,
#[serde(default)] #[serde(default)]
pub no_default_features: bool, pub no_default_features: bool,
@ -32,6 +36,8 @@ pub struct Build {
pub override_configs: Vec<String>, pub override_configs: Vec<String>,
#[serde(default)] #[serde(default)]
pub linux_x86_legacy_boot: bool, pub linux_x86_legacy_boot: bool,
#[serde(default)]
pub strip_elf: bool,
} }
impl Default for Build { impl Default for Build {
@ -42,6 +48,7 @@ impl Default for Build {
no_default_features: false, no_default_features: false,
override_configs: Vec::new(), override_configs: Vec::new(),
linux_x86_legacy_boot: false, linux_x86_legacy_boot: false,
strip_elf: false,
} }
} }
} }
@ -61,6 +68,9 @@ impl Build {
if common_args.linux_x86_legacy_boot { if common_args.linux_x86_legacy_boot {
self.linux_x86_legacy_boot = true; self.linux_x86_legacy_boot = true;
} }
if common_args.strip_elf {
self.strip_elf = true;
}
} }
} }
@ -74,10 +84,13 @@ impl BuildScheme {
features.extend(self.features.clone()); features.extend(self.features.clone());
features features
}; };
// no_default_features is not inherited // `no_default_features` is not inherited
if parent.linux_x86_legacy_boot { if parent.linux_x86_legacy_boot {
self.linux_x86_legacy_boot = true; self.linux_x86_legacy_boot = true;
} }
if parent.strip_elf {
self.strip_elf = true;
}
} }
pub fn finalize(self) -> Build { pub fn finalize(self) -> Build {
@ -87,6 +100,7 @@ impl BuildScheme {
no_default_features: self.no_default_features, no_default_features: self.no_default_features,
override_configs: Vec::new(), override_configs: Vec::new(),
linux_x86_legacy_boot: self.linux_x86_legacy_boot, linux_x86_legacy_boot: self.linux_x86_legacy_boot,
strip_elf: self.strip_elf,
} }
} }
} }