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"]
boot.method = "qemu-direct"
build.strip_elf = true
qemu.args = "$(./tools/qemu_args.sh microvm)"
[scheme."iommu"]

View File

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

View File

@ -43,6 +43,7 @@ supported_archs = ["x86_64"]# List of strings, that the arch the schema can appl
[build]
features = [] # List of strings, 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]
method = "qemu-direct" # "grub-rescue-iso"/"qemu-direct"/"grub-qcow2"
kcmd_args = [] # <1>

View File

@ -264,6 +264,12 @@ pub struct CommonArgs {
global = true
)]
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(
long = "target-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 {
let stripped_elf_path = {
pub fn make_elf_for_qemu(install_dir: impl AsRef<Path>, elf: &AsterBin, strip: bool) -> AsterBin {
let result_elf_path = {
let elf_name = elf
.path()
.file_name()
@ -77,14 +77,15 @@ pub fn strip_elf_for_qemu(install_dir: impl AsRef<Path>, elf: &AsterBin) -> Aste
.to_str()
.unwrap()
.to_string();
install_dir.as_ref().join(elf_name + ".stripped.elf")
install_dir.as_ref().join(elf_name + ".qemu_elf")
};
if strip {
// We use rust-strip to reduce the kernel image size.
let status = Command::new("rust-strip")
.arg(elf.path())
.arg("-o")
.arg(stripped_elf_path.as_os_str())
.arg(result_elf_path.as_os_str())
.status();
match status {
@ -101,6 +102,10 @@ pub fn strip_elf_for_qemu(install_dir: impl AsRef<Path>, elf: &AsterBin) -> Aste
_ => panic!("Strip kernel elf failed, err:{:#?}", err),
},
}
} else {
// Copy the ELF file.
std::fs::copy(elf.path(), &result_elf_path).unwrap();
}
// Because QEMU denies a x86_64 multiboot ELF file (GRUB2 accept it, btw),
// modify `em_machine` to pretend to be an x86 (32-bit) ELF image,
@ -110,7 +115,7 @@ pub fn strip_elf_for_qemu(install_dir: impl AsRef<Path>, elf: &AsterBin) -> Aste
let mut file = OpenOptions::new()
.read(true)
.write(true)
.open(&stripped_elf_path)
.open(&result_elf_path)
.unwrap();
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();
AsterBin::new(
&stripped_elf_path,
&result_elf_path,
AsterBinType::Elf(AsterElfMeta {
has_linux_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,
}),
elf.version().clone(),
true,
strip,
)
}

View File

@ -10,7 +10,7 @@ use std::{
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 crate::{
@ -169,10 +169,11 @@ pub fn do_build(
action,
);
bundle.consume_vm_image(bootdev_image);
bundle.consume_aster_bin(aster_elf);
}
BootMethod::QemuDirect => {
let stripped_elf = strip_elf_for_qemu(&osdk_output_directory, &aster_elf);
bundle.consume_aster_bin(stripped_elf);
let qemu_elf = make_elf_for_qemu(&osdk_output_directory, &aster_elf, build.strip_elf);
bundle.consume_aster_bin(qemu_elf);
}
BootMethod::GrubQcow2 => {
todo!()

View File

@ -13,6 +13,7 @@ pub enum ActionChoice {
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct BuildScheme {
pub profile: Option<String>,
#[serde(default)]
pub features: Vec<String>,
#[serde(default)]
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)
#[serde(default)]
pub linux_x86_legacy_boot: bool,
#[serde(default)]
pub strip_elf: bool,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Build {
pub profile: String,
#[serde(default)]
pub features: Vec<String>,
#[serde(default)]
pub no_default_features: bool,
@ -32,6 +36,8 @@ pub struct Build {
pub override_configs: Vec<String>,
#[serde(default)]
pub linux_x86_legacy_boot: bool,
#[serde(default)]
pub strip_elf: bool,
}
impl Default for Build {
@ -42,6 +48,7 @@ impl Default for Build {
no_default_features: false,
override_configs: Vec::new(),
linux_x86_legacy_boot: false,
strip_elf: false,
}
}
}
@ -61,6 +68,9 @@ impl Build {
if common_args.linux_x86_legacy_boot {
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
};
// no_default_features is not inherited
// `no_default_features` is not inherited
if parent.linux_x86_legacy_boot {
self.linux_x86_legacy_boot = true;
}
if parent.strip_elf {
self.strip_elf = true;
}
}
pub fn finalize(self) -> Build {
@ -87,6 +100,7 @@ impl BuildScheme {
no_default_features: self.no_default_features,
override_configs: Vec::new(),
linux_x86_legacy_boot: self.linux_x86_legacy_boot,
strip_elf: self.strip_elf,
}
}
}