diff --git a/components/someboot/build.rs b/components/someboot/build.rs index da96646736..564c26c563 100644 --- a/components/someboot/build.rs +++ b/components/someboot/build.rs @@ -1,5 +1,10 @@ use std::{fs, io::Write, path::PathBuf}; +#[path = "build_support/linker.rs"] +mod linker; + +use linker::{LinkerArch, LinkerConfig, render_linker_script, source_paths}; + fn main() { println!("cargo::rustc-check-cfg=cfg(efi)"); println!("cargo::rustc-check-cfg=cfg(page_size_4k)"); @@ -78,6 +83,10 @@ impl Build { const LD_NAME: &'static str = "someboot.x"; fn prepare(&mut self) { + for path in source_paths() { + println!("cargo:rerun-if-changed={path}"); + } + match self.arch { Arch::Loongarch64 => self.prepare_loongarch64(), Arch::Arch64 => self.prepare_aarch64(), @@ -91,8 +100,6 @@ impl Build { fn prepare_aarch64(&mut self) { println!("cargo::rustc-check-cfg=cfg(hard_float)"); - let ld_src = "src/arch/aarch64/link.ld"; - if self.hv { self.uspace = false; self.kernel_vaddr = 0xffff_8000_0000; @@ -101,60 +108,29 @@ impl Build { self.kernel_vaddr = 0xffff_ffff_8000_0000; } - let kernel_vaddr = self.kernel_vaddr as usize; - - let ld = include_str!("src/arch/aarch64/link.ld") - .replace("${kernel_load_vaddr}", &format!("{kernel_vaddr:#x}")); - - println!("cargo:rerun-if-changed={ld_src}"); if std::env::var("CARGO_FEATURE_EFI").is_ok() { println!("cargo:rustc-cfg=efi"); } - let ld_dst = self.out_dir.join(Self::LD_NAME); - - fs::write(ld_dst, ld).unwrap(); + self.write_linker_script(LinkerArch::Aarch64); } fn prepare_loongarch64(&mut self) { - let ld_src = "src/arch/loongarch64/link.ld"; - self.kernel_vaddr = 0xffff_ffff_8000_0000; - let kernel_load_vaddr = self.kernel_vaddr as usize; - let kernel_load_paddr = self.kernel_paddr as usize; - - let ld = include_str!("src/arch/loongarch64/link.ld") - .replace("${kernel_load_vaddr}", &format!("{kernel_load_vaddr:#x}")) - .replace("${kernel_load_paddr}", &format!("{kernel_load_paddr:#x}")); - - println!("cargo:rerun-if-changed={ld_src}"); println!("cargo:rustc-cfg=efi"); - let ld_dst = self.out_dir.join(Self::LD_NAME); - - fs::write(ld_dst, ld).unwrap(); + self.write_linker_script(LinkerArch::Loongarch64); } fn prepare_x86_64(&mut self) { - let ld_src = "src/arch/x86_64/link.ld"; - self.kernel_vaddr = 0xffff_ffff_8000_0000; - let kernel_load_vaddr = self.kernel_vaddr as usize; - - let ld = include_str!("src/arch/x86_64/link.ld") - .replace("${kernel_load_vaddr}", &format!("{kernel_load_vaddr:#x}")); - - println!("cargo:rerun-if-changed={ld_src}"); println!("cargo:rustc-cfg=efi"); - let ld_dst = self.out_dir.join(Self::LD_NAME); - fs::write(ld_dst, ld).unwrap(); + self.write_linker_script(LinkerArch::X86_64); } fn prepare_riscv64(&mut self) { - let ld_src = "src/arch/riscv64/link.ld"; - self.kernel_paddr = env_u64("SOMEBOOT_RISCV64_KERNEL_LOAD_PADDR").unwrap_or(0x8020_0000); if self.uspace || self.hv { self.kernel_vaddr = 0xffff_ffff_8000_0000; @@ -162,12 +138,17 @@ impl Build { self.kernel_vaddr = self.kernel_paddr; } - let kernel_load_vaddr = self.kernel_vaddr as usize; - let ld = include_str!("src/arch/riscv64/link.ld") - .replace("${kernel_load_vaddr}", &format!("{kernel_load_vaddr:#x}")); - - println!("cargo:rerun-if-changed={ld_src}"); + self.write_linker_script(LinkerArch::Riscv64); + } + fn write_linker_script(&self, arch: LinkerArch) { + let ld = render_linker_script( + arch, + LinkerConfig { + kernel_load_vaddr: self.kernel_vaddr, + kernel_load_paddr: self.kernel_paddr, + }, + ); let ld_dst = self.out_dir.join(Self::LD_NAME); fs::write(ld_dst, ld).unwrap(); } diff --git a/components/someboot/build_support/linker.rs b/components/someboot/build_support/linker.rs new file mode 100644 index 0000000000..7f026704d6 --- /dev/null +++ b/components/someboot/build_support/linker.rs @@ -0,0 +1,224 @@ +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum LinkerArch { + Aarch64, + Loongarch64, + X86_64, + Riscv64, +} + +#[derive(Debug, Clone, Copy)] +pub struct LinkerConfig { + pub kernel_load_vaddr: u64, + pub kernel_load_paddr: u64, +} + +struct LinkerTemplate { + path: &'static str, + content: &'static str, + replacements: &'static [(&'static str, &'static str)], +} + +const DEFAULTS_PATH: &str = "src/ld/defaults.ld"; +const TEXT_PATH: &str = "src/ld/text.ld"; +const RODATA_PATH: &str = "src/ld/rodata.ld"; +const DATA_PATH: &str = "src/ld/data.ld"; +const RELA_DYN_PATH: &str = "src/ld/rela-dyn.ld"; +const BSS_PATH: &str = "src/ld/bss.ld"; +const DEBUG_PATH: &str = "src/ld/debug.ld"; +const DISCARD_EXIT_PATH: &str = "src/ld/discard-exit.ld"; +const DISCARD_DYNAMIC_PATH: &str = "src/ld/discard-dynamic.ld"; + +const FRAGMENTS: &[(&str, &str, &str)] = &[ + ( + DEFAULTS_PATH, + "${ld_defaults}", + include_str!("../src/ld/defaults.ld"), + ), + (TEXT_PATH, "${ld_text}", include_str!("../src/ld/text.ld")), + ( + RODATA_PATH, + "${ld_rodata}", + include_str!("../src/ld/rodata.ld"), + ), + (DATA_PATH, "${ld_data}", include_str!("../src/ld/data.ld")), + ( + RELA_DYN_PATH, + "${ld_rela_dyn}", + include_str!("../src/ld/rela-dyn.ld"), + ), + (BSS_PATH, "${ld_bss}", include_str!("../src/ld/bss.ld")), + ( + DEBUG_PATH, + "${ld_debug}", + include_str!("../src/ld/debug.ld"), + ), + ( + DISCARD_EXIT_PATH, + "${ld_discard_exit}", + include_str!("../src/ld/discard-exit.ld"), + ), + ( + DISCARD_DYNAMIC_PATH, + "${ld_discard_dynamic}", + include_str!("../src/ld/discard-dynamic.ld"), + ), +]; + +const AARCH64_REPLACEMENTS: &[(&str, &str)] = &[ + ("${text_output}", ""), + ("${rodata_extra}", ""), + ( + "${data_extra}", + r#" *(.got .got.*) + *(.got.plt .got.plt.*) + *(.igot .igot.*)"#, + ), + ("${percpu_align}", "64"), + ("${tdata_align}", ""), + ("${tdata_output}", ":text :tls"), + ("${post_tdata_sections}", ""), + ("${edata_align}", ". = ALIGN(8);"), + ("${bss_start_before_tbss}", "__bss_start = .;"), + ("${bss_start_after_tbss}", ""), + ("${tbss_align}", ""), + ("${tbss_output}", ":text :tls"), + ("${pre_sbss_align}", ". = ALIGN(8);"), + ("${sbss_extra}", ""), + ("${bss_output}", ":text"), + ("${cpu_stack_align}", ". = ALIGN(PAGE_SIZE);"), + ("${discard_options}", "*(.options)"), + ("${discard_dynamic_extra}", "*(.eh_frame .eh_frame_hdr)"), +]; + +const LOONGARCH64_REPLACEMENTS: &[(&str, &str)] = &[ + ("${text_output}", ":text = 0"), + ("${rodata_extra}", ""), + ("${data_extra}", ""), + ("${percpu_align}", "PAGE_SIZE"), + ("${tdata_align}", ""), + ("${tdata_output}", ":text :tls"), + ("${post_tdata_sections}", ""), + ("${edata_align}", ". = ALIGN(8);"), + ("${bss_start_before_tbss}", "__bss_start = .;"), + ("${bss_start_after_tbss}", ""), + ("${tbss_align}", ""), + ("${tbss_output}", ":text :tls"), + ("${pre_sbss_align}", ". = ALIGN(8);"), + ("${sbss_extra}", ""), + ("${bss_output}", ""), + ("${cpu_stack_align}", ". = ALIGN(PAGE_SIZE);"), + ("${discard_options}", "*(.options)"), + ("${discard_dynamic_extra}", "*(.eh_frame)"), +]; + +const X86_64_REPLACEMENTS: &[(&str, &str)] = &[ + ("${text_output}", ":text = 0"), + ("${rodata_extra}", ""), + ("${data_extra}", "*(.got .got.*)"), + ("${percpu_align}", "PAGE_SIZE"), + ("${tdata_align}", "ALIGN(16)"), + ("${tdata_output}", ":text :tls"), + ("${post_tdata_sections}", ""), + ("${edata_align}", ""), + ("${bss_start_before_tbss}", "__bss_start = .;"), + ("${bss_start_after_tbss}", ""), + ("${tbss_align}", "ALIGN(16)"), + ("${tbss_output}", ":text :tls"), + ("${pre_sbss_align}", ""), + ("${sbss_extra}", ""), + ("${bss_output}", ":text"), + ("${cpu_stack_align}", ". = ALIGN(PAGE_SIZE);"), + ("${discard_options}", ""), + ("${discard_dynamic_extra}", "*(.eh_frame)"), +]; + +const RISCV64_REPLACEMENTS: &[(&str, &str)] = &[ + ("${text_output}", ""), + ("${rodata_extra}", "*(.srodata .srodata.*)"), + ("${data_extra}", ""), + ("${percpu_align}", "PAGE_SIZE"), + ("${tdata_align}", ""), + ("${tdata_output}", ""), + ( + "${post_tdata_sections}", + r#" + .dynamic : ALIGN(8) { + *(.dynamic) + } + .got : ALIGN(8) { + *(.got .got.*) + }"#, + ), + ("${edata_align}", ""), + ("${bss_start_before_tbss}", ""), + ("${bss_start_after_tbss}", "__bss_start = .;"), + ("${tbss_align}", ""), + ("${tbss_output}", ""), + ("${pre_sbss_align}", ""), + ("${sbss_extra}", "*(.sbss.*)"), + ("${bss_output}", ""), + ("${cpu_stack_align}", ""), + ("${discard_options}", ""), + ("${discard_dynamic_extra}", ""), +]; + +pub fn render_linker_script(arch: LinkerArch, config: LinkerConfig) -> String { + let template = arch.template(); + let mut script = template.content.to_string(); + + for (_, token, fragment) in FRAGMENTS { + script = script.replace(token, fragment.trim_end()); + } + for (token, value) in template.replacements { + script = script.replace(token, value); + } + + script + .replace( + "${kernel_load_vaddr}", + &format!("{:#x}", config.kernel_load_vaddr as usize), + ) + .replace( + "${kernel_load_paddr}", + &format!("{:#x}", config.kernel_load_paddr as usize), + ) +} + +pub fn source_paths() -> Vec<&'static str> { + let mut paths = vec![ + "build_support/linker.rs", + LinkerArch::Aarch64.template().path, + LinkerArch::Loongarch64.template().path, + LinkerArch::X86_64.template().path, + LinkerArch::Riscv64.template().path, + ]; + paths.extend(FRAGMENTS.iter().map(|(path, ..)| *path)); + paths +} + +impl LinkerArch { + fn template(self) -> LinkerTemplate { + match self { + LinkerArch::Aarch64 => LinkerTemplate { + path: "src/arch/aarch64/link.ld", + content: include_str!("../src/arch/aarch64/link.ld"), + replacements: AARCH64_REPLACEMENTS, + }, + LinkerArch::Loongarch64 => LinkerTemplate { + path: "src/arch/loongarch64/link.ld", + content: include_str!("../src/arch/loongarch64/link.ld"), + replacements: LOONGARCH64_REPLACEMENTS, + }, + LinkerArch::X86_64 => LinkerTemplate { + path: "src/arch/x86_64/link.ld", + content: include_str!("../src/arch/x86_64/link.ld"), + replacements: X86_64_REPLACEMENTS, + }, + LinkerArch::Riscv64 => LinkerTemplate { + path: "src/arch/riscv64/link.ld", + content: include_str!("../src/arch/riscv64/link.ld"), + replacements: RISCV64_REPLACEMENTS, + }, + } + } +} diff --git a/components/someboot/src/arch/aarch64/link.ld b/components/someboot/src/arch/aarch64/link.ld index 93c2ef1feb..a7e2d3934b 100644 --- a/components/someboot/src/arch/aarch64/link.ld +++ b/components/someboot/src/arch/aarch64/link.ld @@ -4,9 +4,7 @@ */ PECOFF_FILE_ALIGN = 0x200; -PROVIDE(PAGE_SIZE = 0x1000); -/* Provide default stack size if not defined */ -PROVIDE(STACK_SIZE = 0x40000); +${ld_defaults} VM_LOAD_ADDRESS = ${kernel_load_vaddr}; OUTPUT_ARCH(aarch64) @@ -20,47 +18,13 @@ PHDRS { SECTIONS { . = VM_LOAD_ADDRESS; - .head.text : { - KEEP(*(.head.text)) - } - . = ALIGN(PAGE_SIZE); - _stext = .; - .text : { - *(.text .text.*) - *(.init.text) - *(.fixup) - *(.gnu.warning) - } - . = ALIGN(PAGE_SIZE); - _etext = .; - _srodata = .; - .rodata : { - *(.rodata) - *(.rodata.*) - *(.data.rel.ro*) - } - . = ALIGN(PAGE_SIZE); - _erodata = .; - _sdata = .; - - .data : ALIGN(16) { - *(.data .data.*) - *(.init.data) - *(.sdata .sdata.*) - *(.got .got.*) - *(.got.plt .got.plt.*) - *(.igot .igot.*) - - . = ALIGN(64); - __percpu_start = .; - *(.percpu_data .percpu_data.* .percpu .percpu.*) - __percpu_end = .; - } - .rela.dyn : ALIGN(8) { - __rela_dyn_begin = .; - *(.rela .rela*) - __rela_dyn_end = .; + .head.text : { + KEEP(*(.head.text)) } +${ld_text} +${ld_rodata} +${ld_data} +${ld_rela_dyn} .init_array : ALIGN(8) { __init_array_start = .; @@ -68,55 +32,10 @@ SECTIONS KEEP(*(.init_array)) __init_array_end = .; } - - .sdata : ALIGN(8) { - *(.sdata) - . = ALIGN(PAGE_SIZE); - } - - .tdata : { - _stdata = .; - *(.tdata .tdata.*) - _etdata = .; - } :text :tls - . = ALIGN(8); - _edata = .; - __kernel_load_end = .; - __bss_start = .; +${ld_bss} - .tbss : { - _stbss = .; - *(.tbss .tbss.*) - *(.init.bss) - *(.tcommon) - _etbss = .; - } :text :tls - - . = ALIGN(8); - .sbss : { - *(.dynsbss) *(.sbss) *(.scommon) - } :text - .bss : { - *(.dynbss) - *(.bss .bss.*) - *(COMMON) - - /* CPU stacks */ - . = ALIGN(PAGE_SIZE); - __cpu0_stack = .; - . += STACK_SIZE; - __cpu0_stack_top = .; - - } :text - . = ALIGN(PAGE_SIZE); - __bss_stop = .; - _end = .; - __kernel_code_end = .; - - .stab 0 : { *(.stab) } .stabstr 0 : { *(.stabstr) } .stab.excl 0 : { *(.stab.excl) } .stab.exclstr 0 : { *(.stab.exclstr) } .stab.index 0 : { *(.stab.index) } .stab.indexstr 0 : { *(.stab.indexstr) } - .debug 0 : { *(.debug) } .line 0 : { *(.line) } .debug_srcinfo 0 : { *(.debug_srcinfo) } .debug_sfnames 0 : { *(.debug_sfnames) } .debug_aranges 0 : { *(.debug_aranges) } .debug_pubnames 0 : { *(.debug_pubnames) } .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } .debug_abbrev 0 : { *(.debug_abbrev) } .debug_line 0 : { *(.debug_line) } .debug_frame 0 : { *(.debug_frame) } .debug_str 0 : { *(.debug_str) } .debug_loc 0 : { *(.debug_loc) } .debug_macinfo 0 : { *(.debug_macinfo) } .debug_pubtypes 0 : { *(.debug_pubtypes) } .debug_ranges 0 : { *(.debug_ranges) } .debug_weaknames 0 : { *(.debug_weaknames) } .debug_funcnames 0 : { *(.debug_funcnames) } .debug_typenames 0 : { *(.debug_typenames) } .debug_varnames 0 : { *(.debug_varnames) } .debug_gnu_pubnames 0 : { *(.debug_gnu_pubnames) } .debug_gnu_pubtypes 0 : { *(.debug_gnu_pubtypes) } .debug_types 0 : { *(.debug_types) } .debug_addr 0 : { *(.debug_addr) } .debug_line_str 0 : { *(.debug_line_str) } .debug_loclists 0 : { *(.debug_loclists) } .debug_macro 0 : { *(.debug_macro) } .debug_names 0 : { *(.debug_names) } .debug_rnglists 0 : { *(.debug_rnglists) } .debug_str_offsets 0 : { *(.debug_str_offsets) } - .comment 0 : { *(.comment) } .symtab 0 : { *(.symtab) } .strtab 0 : { *(.strtab) } .shstrtab 0 : { *(.shstrtab) } +${ld_debug} _kernel_entry = ABSOLUTE(kernel_entry & 0xffffffffffff); _kernel_asize = ABSOLUTE(_end - _head); _kernel_fsize = ABSOLUTE(_edata - _head); @@ -130,23 +49,6 @@ SECTIONS *(.gptab.bss) *(.gptab.sbss) } - /DISCARD/ : { - *(.exit.text) - *(.text.exit) - *(.exit.data .exit.data.*) - *(.fini_array .fini_array.*) - *(.dtors .dtors.*) - *(.exitcall.exit) - *(.discard) - *(.discard.*) - *(.export_symbol) - *(.no_trim_symbol) - *(.modinfo) - *(.gnu.version*) } - /DISCARD/ : { - *(.dynamic .dynsym .dynstr .hash .gnu.hash) - *(.gnu.attributes) - *(.options) - *(.eh_frame .eh_frame_hdr) - } +${ld_discard_exit} +${ld_discard_dynamic} } diff --git a/components/someboot/src/arch/loongarch64/link.ld b/components/someboot/src/arch/loongarch64/link.ld index cbccc1d7ec..f94ef1bf46 100644 --- a/components/someboot/src/arch/loongarch64/link.ld +++ b/components/someboot/src/arch/loongarch64/link.ld @@ -6,9 +6,7 @@ PECOFF_FILE_ALIGN = 0x200; VM_LOAD_ADDRESS = ${kernel_load_vaddr}; KERNEL_LOAD_ADDRESS = ${kernel_load_paddr}; -PROVIDE(PAGE_SIZE = 0x1000); -/* Provide default stack size if not defined */ -PROVIDE(STACK_SIZE = 0x40000); +${ld_defaults} OUTPUT_ARCH(loongarch) ENTRY(kernel_entry) @@ -21,17 +19,10 @@ PHDRS { SECTIONS { . = VM_LOAD_ADDRESS; - .head.text : { - KEEP(*(.head.text)) + .head.text : { + KEEP(*(.head.text)) } - . = ALIGN(PAGE_SIZE); - _stext = .; - .text : { - *(.text .text.*) - *(.init.text) - *(.fixup) - *(.gnu.warning) - } :text = 0 +${ld_text} /* Exception vector table - must be 64KB aligned */ /* VECSIZE = 0x200 (512 bytes), 128 vectors = 64KB total */ @@ -49,39 +40,15 @@ SECTIONS KEEP(*(.vectors.*)) } :text - . = ALIGN(PAGE_SIZE); - _etext = .; - _srodata = .; - .rodata : { - *(.rodata) - *(.rodata.*) - *(.data.rel.ro*) - } - . = ALIGN(PAGE_SIZE); - _erodata = .; - _sdata = .; - - .data : ALIGN(16) { - *(.data .data.*) - *(.init.data) - *(.sdata .sdata.*) - - . = ALIGN(PAGE_SIZE); - __percpu_start = .; - *(.percpu_data .percpu_data.* .percpu .percpu.*) - __percpu_end = .; - } - .rela.dyn : ALIGN(8) { - __rela_dyn_begin = .; - *(.rela .rela*) - __rela_dyn_end = .; - } +${ld_rodata} +${ld_data} +${ld_rela_dyn} .relr.dyn : ALIGN(8) { __relr_dyn_begin = .; *(.relr.dyn) __relr_dyn_end = .; } - .data.rel : ALIGN(8) { + .data.rel : ALIGN(8) { *(.data.rel*) } .la_abs : ALIGN(8) { @@ -89,53 +56,9 @@ SECTIONS *(.la_abs) __la_abs_end = .; } - .sdata : ALIGN(8) { - *(.sdata) - . = ALIGN(PAGE_SIZE); - } - .tdata : { - _stdata = .; - *(.tdata .tdata.*) - _etdata = .; - } :text :tls - - . = ALIGN(8); - _edata = .; - __kernel_load_end = .; - __bss_start = .; +${ld_bss} - .tbss : { - _stbss = .; - *(.tbss .tbss.*) - *(.init.bss) - *(.tcommon) - _etbss = .; - } :text :tls - - . = ALIGN(8); - .sbss : { - *(.dynsbss) *(.sbss) *(.scommon) - } - .bss : { - *(.dynbss) - *(.bss .bss.*) - *(COMMON) - - /* CPU stacks */ - . = ALIGN(PAGE_SIZE); - __cpu0_stack = .; - . += STACK_SIZE; - __cpu0_stack_top = .; - - } - . = ALIGN(PAGE_SIZE); - __bss_stop = .; - _end = .; - __kernel_code_end = .; - - .stab 0 : { *(.stab) } .stabstr 0 : { *(.stabstr) } .stab.excl 0 : { *(.stab.excl) } .stab.exclstr 0 : { *(.stab.exclstr) } .stab.index 0 : { *(.stab.index) } .stab.indexstr 0 : { *(.stab.indexstr) } - .debug 0 : { *(.debug) } .line 0 : { *(.line) } .debug_srcinfo 0 : { *(.debug_srcinfo) } .debug_sfnames 0 : { *(.debug_sfnames) } .debug_aranges 0 : { *(.debug_aranges) } .debug_pubnames 0 : { *(.debug_pubnames) } .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } .debug_abbrev 0 : { *(.debug_abbrev) } .debug_line 0 : { *(.debug_line) } .debug_frame 0 : { *(.debug_frame) } .debug_str 0 : { *(.debug_str) } .debug_loc 0 : { *(.debug_loc) } .debug_macinfo 0 : { *(.debug_macinfo) } .debug_pubtypes 0 : { *(.debug_pubtypes) } .debug_ranges 0 : { *(.debug_ranges) } .debug_weaknames 0 : { *(.debug_weaknames) } .debug_funcnames 0 : { *(.debug_funcnames) } .debug_typenames 0 : { *(.debug_typenames) } .debug_varnames 0 : { *(.debug_varnames) } .debug_gnu_pubnames 0 : { *(.debug_gnu_pubnames) } .debug_gnu_pubtypes 0 : { *(.debug_gnu_pubtypes) } .debug_types 0 : { *(.debug_types) } .debug_addr 0 : { *(.debug_addr) } .debug_line_str 0 : { *(.debug_line_str) } .debug_loclists 0 : { *(.debug_loclists) } .debug_macro 0 : { *(.debug_macro) } .debug_names 0 : { *(.debug_names) } .debug_rnglists 0 : { *(.debug_rnglists) } .debug_str_offsets 0 : { *(.debug_str_offsets) } - .comment 0 : { *(.comment) } .symtab 0 : { *(.symtab) } .strtab 0 : { *(.strtab) } .shstrtab 0 : { *(.shstrtab) } +${ld_debug} _kernel_entry = ABSOLUTE(KERNEL_LOAD_ADDRESS + (kernel_entry - _head)); _kernel_asize = ABSOLUTE(_end - _head); _kernel_fsize = ABSOLUTE(_edata - _head); @@ -149,23 +72,6 @@ SECTIONS *(.gptab.bss) *(.gptab.sbss) } - /DISCARD/ : { - *(.exit.text) - *(.text.exit) - *(.exit.data .exit.data.*) - *(.fini_array .fini_array.*) - *(.dtors .dtors.*) - *(.exitcall.exit) - *(.discard) - *(.discard.*) - *(.export_symbol) - *(.no_trim_symbol) - *(.modinfo) - *(.gnu.version*) } - /DISCARD/ : { - *(.dynamic .dynsym .dynstr .hash .gnu.hash) - *(.gnu.attributes) - *(.options) - *(.eh_frame) - } +${ld_discard_exit} +${ld_discard_dynamic} } diff --git a/components/someboot/src/arch/riscv64/link.ld b/components/someboot/src/arch/riscv64/link.ld index 611294e46e..73f572f492 100644 --- a/components/someboot/src/arch/riscv64/link.ld +++ b/components/someboot/src/arch/riscv64/link.ld @@ -1,5 +1,4 @@ -PROVIDE(PAGE_SIZE = 0x1000); -PROVIDE(STACK_SIZE = 0x40000); +${ld_defaults} VM_LOAD_ADDRESS = ${kernel_load_vaddr}; OUTPUT_ARCH(riscv) @@ -12,41 +11,10 @@ SECTIONS KEEP(*(.head.text)) KEEP(*(.text._head)) } - . = ALIGN(PAGE_SIZE); - _stext = .; - .text : { - *(.text .text.*) - *(.init.text) - *(.fixup) - *(.gnu.warning) - } - . = ALIGN(PAGE_SIZE); - _etext = .; - _srodata = .; - .rodata : { - *(.rodata) - *(.rodata.*) - *(.srodata .srodata.*) - *(.data.rel.ro*) - } - . = ALIGN(PAGE_SIZE); - _erodata = .; - _sdata = .; - .data : ALIGN(16) { - *(.data .data.*) - *(.init.data) - *(.sdata .sdata.*) - - . = ALIGN(PAGE_SIZE); - __percpu_start = .; - *(.percpu_data .percpu_data.* .percpu .percpu.*) - __percpu_end = .; - } - .rela.dyn : ALIGN(8) { - __rela_dyn_begin = .; - *(.rela .rela*) - __rela_dyn_end = .; - } +${ld_text} +${ld_rodata} +${ld_data} +${ld_rela_dyn} .dynsym : ALIGN(8) { *(.dynsym) } @@ -62,54 +30,7 @@ SECTIONS .eh_frame_hdr : ALIGN(4) { *(.eh_frame_hdr) } - .sdata : ALIGN(8) { - *(.sdata) - . = ALIGN(PAGE_SIZE); - } - - .tdata : { - _stdata = .; - *(.tdata .tdata.*) - _etdata = .; - } - - .dynamic : ALIGN(8) { - *(.dynamic) - } - .got : ALIGN(8) { - *(.got .got.*) - } - _edata = .; - __kernel_load_end = .; - - .tbss : { - _stbss = .; - *(.tbss .tbss.*) - *(.init.bss) - *(.tcommon) - _etbss = .; - } - - __bss_start = .; - - .sbss : { - *(.dynsbss) - *(.sbss .sbss.*) - *(.scommon) - } - .bss : { - *(.dynbss) - *(.bss .bss.*) - *(COMMON) - - __cpu0_stack = .; - . += STACK_SIZE; - __cpu0_stack_top = .; - } - . = ALIGN(PAGE_SIZE); - __bss_stop = .; - _end = .; - __kernel_code_end = .; +${ld_bss} /DISCARD/ : { *(.eh_frame) diff --git a/components/someboot/src/arch/x86_64/link.ld b/components/someboot/src/arch/x86_64/link.ld index fdfb00558c..2e87643539 100644 --- a/components/someboot/src/arch/x86_64/link.ld +++ b/components/someboot/src/arch/x86_64/link.ld @@ -1,7 +1,6 @@ PECOFF_FILE_ALIGN = 0x200; -PROVIDE(PAGE_SIZE = 0x1000); -PROVIDE(STACK_SIZE = 0x40000); +${ld_defaults} VM_LOAD_ADDRESS = ${kernel_load_vaddr}; OUTPUT_ARCH(i386:x86-64) @@ -18,85 +17,13 @@ SECTIONS .head.text : { KEEP(*(.head.text)) } - . = ALIGN(PAGE_SIZE); - _stext = .; - .text : { - *(.text .text.*) - *(.init.text) - *(.fixup) - *(.gnu.warning) - } :text = 0 - . = ALIGN(PAGE_SIZE); - _etext = .; - _srodata = .; - .rodata : { - *(.rodata) - *(.rodata.*) - *(.data.rel.ro*) - } - . = ALIGN(PAGE_SIZE); - _erodata = .; - _sdata = .; - - .data : ALIGN(16) { - *(.data .data.*) - *(.init.data) - *(.sdata .sdata.*) - *(.got .got.*) - - . = ALIGN(PAGE_SIZE); - __percpu_start = .; - *(.percpu_data .percpu_data.* .percpu .percpu.*) - __percpu_end = .; - } - .rela.dyn : ALIGN(8) { - __rela_dyn_begin = .; - *(.rela .rela*) - __rela_dyn_end = .; - } - .sdata : ALIGN(8) { - *(.sdata) - . = ALIGN(PAGE_SIZE); - } - .tdata : ALIGN(16) { - _stdata = .; - *(.tdata .tdata.*) - _etdata = .; - } :text :tls +${ld_text} +${ld_rodata} +${ld_data} +${ld_rela_dyn} +${ld_bss} - _edata = .; - __kernel_load_end = .; - __bss_start = .; - - .tbss : ALIGN(16) { - _stbss = .; - *(.tbss .tbss.*) - *(.init.bss) - *(.tcommon) - _etbss = .; - } :text :tls - - .sbss : { - *(.dynsbss) *(.sbss) *(.scommon) - } :text - .bss : { - *(.dynbss) - *(.bss .bss.*) - *(COMMON) - - . = ALIGN(PAGE_SIZE); - __cpu0_stack = .; - . += STACK_SIZE; - __cpu0_stack_top = .; - } :text - . = ALIGN(PAGE_SIZE); - __bss_stop = .; - _end = .; - __kernel_code_end = .; - - .stab 0 : { *(.stab) } .stabstr 0 : { *(.stabstr) } .stab.excl 0 : { *(.stab.excl) } .stab.exclstr 0 : { *(.stab.exclstr) } .stab.index 0 : { *(.stab.index) } .stab.indexstr 0 : { *(.stab.indexstr) } - .debug 0 : { *(.debug) } .line 0 : { *(.line) } .debug_srcinfo 0 : { *(.debug_srcinfo) } .debug_sfnames 0 : { *(.debug_sfnames) } .debug_aranges 0 : { *(.debug_aranges) } .debug_pubnames 0 : { *(.debug_pubnames) } .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } .debug_abbrev 0 : { *(.debug_abbrev) } .debug_line 0 : { *(.debug_line) } .debug_frame 0 : { *(.debug_frame) } .debug_str 0 : { *(.debug_str) } .debug_loc 0 : { *(.debug_loc) } .debug_macinfo 0 : { *(.debug_macinfo) } .debug_pubtypes 0 : { *(.debug_pubtypes) } .debug_ranges 0 : { *(.debug_ranges) } .debug_weaknames 0 : { *(.debug_weaknames) } .debug_funcnames 0 : { *(.debug_funcnames) } .debug_typenames 0 : { *(.debug_typenames) } .debug_varnames 0 : { *(.debug_varnames) } .debug_gnu_pubnames 0 : { *(.debug_gnu_pubnames) } .debug_gnu_pubtypes 0 : { *(.debug_gnu_pubtypes) } .debug_types 0 : { *(.debug_types) } .debug_addr 0 : { *(.debug_addr) } .debug_line_str 0 : { *(.debug_line_str) } .debug_loclists 0 : { *(.debug_loclists) } .debug_macro 0 : { *(.debug_macro) } .debug_names 0 : { *(.debug_names) } .debug_rnglists 0 : { *(.debug_rnglists) } .debug_str_offsets 0 : { *(.debug_str_offsets) } - .comment 0 : { *(.comment) } .symtab 0 : { *(.symtab) } .strtab 0 : { *(.strtab) } .shstrtab 0 : { *(.shstrtab) } +${ld_debug} _kernel_entry = ABSOLUTE(kernel_entry); _kernel_asize = ABSOLUTE(_end - _head); _kernel_fsize = ABSOLUTE(_edata - _head); @@ -106,23 +33,6 @@ SECTIONS _kernel_bss_size = ABSOLUTE(_kernel_vsize - _kernel_rsize); _kernel_text_offset = ABSOLUTE(_stext - _head); _kernel_image_size = ABSOLUTE(_end - _head); - /DISCARD/ : { - *(.exit.text) - *(.text.exit) - *(.exit.data .exit.data.*) - *(.fini_array .fini_array.*) - *(.dtors .dtors.*) - *(.exitcall.exit) - *(.discard) - *(.discard.*) - *(.export_symbol) - *(.no_trim_symbol) - *(.modinfo) - *(.gnu.version*) - } - /DISCARD/ : { - *(.dynamic .dynsym .dynstr .hash .gnu.hash) - *(.gnu.attributes) - *(.eh_frame) - } +${ld_discard_exit} +${ld_discard_dynamic} } diff --git a/components/someboot/src/ld/bss.ld b/components/someboot/src/ld/bss.ld new file mode 100644 index 0000000000..47dfb94acb --- /dev/null +++ b/components/someboot/src/ld/bss.ld @@ -0,0 +1,47 @@ + .sdata : ALIGN(8) { + *(.sdata) + . = ALIGN(PAGE_SIZE); + } + + .tdata : ${tdata_align} { + _stdata = .; + *(.tdata .tdata.*) + _etdata = .; + } ${tdata_output} + ${post_tdata_sections} + ${edata_align} + _edata = .; + __kernel_load_end = .; + ${bss_start_before_tbss} + + .tbss : ${tbss_align} { + _stbss = .; + *(.tbss .tbss.*) + *(.init.bss) + *(.tcommon) + _etbss = .; + } ${tbss_output} + + ${bss_start_after_tbss} + ${pre_sbss_align} + .sbss : { + *(.dynsbss) + *(.sbss) + ${sbss_extra} + *(.scommon) + } ${bss_output} + .bss : { + *(.dynbss) + *(.bss .bss.*) + *(COMMON) + + /* CPU stacks */ + ${cpu_stack_align} + __cpu0_stack = .; + . += STACK_SIZE; + __cpu0_stack_top = .; + } ${bss_output} + . = ALIGN(PAGE_SIZE); + __bss_stop = .; + _end = .; + __kernel_code_end = .; diff --git a/components/someboot/src/ld/data.ld b/components/someboot/src/ld/data.ld new file mode 100644 index 0000000000..150ca50450 --- /dev/null +++ b/components/someboot/src/ld/data.ld @@ -0,0 +1,11 @@ + .data : ALIGN(16) { + *(.data .data.*) + *(.init.data) + *(.sdata .sdata.*) + ${data_extra} + + . = ALIGN(${percpu_align}); + __percpu_start = .; + *(.percpu_data .percpu_data.* .percpu .percpu.*) + __percpu_end = .; + } diff --git a/components/someboot/src/ld/debug.ld b/components/someboot/src/ld/debug.ld new file mode 100644 index 0000000000..50eccad99c --- /dev/null +++ b/components/someboot/src/ld/debug.ld @@ -0,0 +1,3 @@ + .stab 0 : { *(.stab) } .stabstr 0 : { *(.stabstr) } .stab.excl 0 : { *(.stab.excl) } .stab.exclstr 0 : { *(.stab.exclstr) } .stab.index 0 : { *(.stab.index) } .stab.indexstr 0 : { *(.stab.indexstr) } + .debug 0 : { *(.debug) } .line 0 : { *(.line) } .debug_srcinfo 0 : { *(.debug_srcinfo) } .debug_sfnames 0 : { *(.debug_sfnames) } .debug_aranges 0 : { *(.debug_aranges) } .debug_pubnames 0 : { *(.debug_pubnames) } .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } .debug_abbrev 0 : { *(.debug_abbrev) } .debug_line 0 : { *(.debug_line) } .debug_frame 0 : { *(.debug_frame) } .debug_str 0 : { *(.debug_str) } .debug_loc 0 : { *(.debug_loc) } .debug_macinfo 0 : { *(.debug_macinfo) } .debug_pubtypes 0 : { *(.debug_pubtypes) } .debug_ranges 0 : { *(.debug_ranges) } .debug_weaknames 0 : { *(.debug_weaknames) } .debug_funcnames 0 : { *(.debug_funcnames) } .debug_typenames 0 : { *(.debug_typenames) } .debug_varnames 0 : { *(.debug_varnames) } .debug_gnu_pubnames 0 : { *(.debug_gnu_pubnames) } .debug_gnu_pubtypes 0 : { *(.debug_gnu_pubtypes) } .debug_types 0 : { *(.debug_types) } .debug_addr 0 : { *(.debug_addr) } .debug_line_str 0 : { *(.debug_line_str) } .debug_loclists 0 : { *(.debug_loclists) } .debug_macro 0 : { *(.debug_macro) } .debug_names 0 : { *(.debug_names) } .debug_rnglists 0 : { *(.debug_rnglists) } .debug_str_offsets 0 : { *(.debug_str_offsets) } + .comment 0 : { *(.comment) } .symtab 0 : { *(.symtab) } .strtab 0 : { *(.strtab) } .shstrtab 0 : { *(.shstrtab) } diff --git a/components/someboot/src/ld/defaults.ld b/components/someboot/src/ld/defaults.ld new file mode 100644 index 0000000000..0826f4b5d8 --- /dev/null +++ b/components/someboot/src/ld/defaults.ld @@ -0,0 +1,3 @@ +PROVIDE(PAGE_SIZE = 0x1000); +/* Provide default stack size if not defined */ +PROVIDE(STACK_SIZE = 0x40000); diff --git a/components/someboot/src/ld/discard-dynamic.ld b/components/someboot/src/ld/discard-dynamic.ld new file mode 100644 index 0000000000..0beb3fb0c9 --- /dev/null +++ b/components/someboot/src/ld/discard-dynamic.ld @@ -0,0 +1,6 @@ + /DISCARD/ : { + *(.dynamic .dynsym .dynstr .hash .gnu.hash) + *(.gnu.attributes) + ${discard_options} + ${discard_dynamic_extra} + } diff --git a/components/someboot/src/ld/discard-exit.ld b/components/someboot/src/ld/discard-exit.ld new file mode 100644 index 0000000000..73f948fe3e --- /dev/null +++ b/components/someboot/src/ld/discard-exit.ld @@ -0,0 +1,14 @@ + /DISCARD/ : { + *(.exit.text) + *(.text.exit) + *(.exit.data .exit.data.*) + *(.fini_array .fini_array.*) + *(.dtors .dtors.*) + *(.exitcall.exit) + *(.discard) + *(.discard.*) + *(.export_symbol) + *(.no_trim_symbol) + *(.modinfo) + *(.gnu.version*) + } diff --git a/components/someboot/src/ld/rela-dyn.ld b/components/someboot/src/ld/rela-dyn.ld new file mode 100644 index 0000000000..878f210d32 --- /dev/null +++ b/components/someboot/src/ld/rela-dyn.ld @@ -0,0 +1,5 @@ + .rela.dyn : ALIGN(8) { + __rela_dyn_begin = .; + *(.rela .rela*) + __rela_dyn_end = .; + } diff --git a/components/someboot/src/ld/rodata.ld b/components/someboot/src/ld/rodata.ld new file mode 100644 index 0000000000..ec000e91e0 --- /dev/null +++ b/components/someboot/src/ld/rodata.ld @@ -0,0 +1,12 @@ + . = ALIGN(PAGE_SIZE); + _etext = .; + _srodata = .; + .rodata : { + *(.rodata) + *(.rodata.*) + ${rodata_extra} + *(.data.rel.ro*) + } + . = ALIGN(PAGE_SIZE); + _erodata = .; + _sdata = .; diff --git a/components/someboot/src/ld/text.ld b/components/someboot/src/ld/text.ld new file mode 100644 index 0000000000..bffec5c157 --- /dev/null +++ b/components/someboot/src/ld/text.ld @@ -0,0 +1,8 @@ + . = ALIGN(PAGE_SIZE); + _stext = .; + .text : { + *(.text .text.*) + *(.init.text) + *(.fixup) + *(.gnu.warning) + } ${text_output} diff --git a/components/someboot/tests/linker_templates.rs b/components/someboot/tests/linker_templates.rs new file mode 100644 index 0000000000..39415ee338 --- /dev/null +++ b/components/someboot/tests/linker_templates.rs @@ -0,0 +1,80 @@ +#[path = "../build_support/linker.rs"] +mod linker; + +use linker::{LinkerArch, LinkerConfig, render_linker_script, source_paths}; + +const CONFIG: LinkerConfig = LinkerConfig { + kernel_load_vaddr: 0xffff_ffff_8000_0000, + kernel_load_paddr: 0x20_0000, +}; + +fn assert_common_contract(script: &str) { + assert!( + script.find(".head.text").unwrap() < script.find("_stext = .;").unwrap(), + ".head.text must stay before the main text section" + ); + assert!(script.contains("__kernel_load_end = .;")); + assert!(script.contains("__bss_start")); + assert!(script.contains("__bss_stop = .;")); + assert!(script.contains("__cpu0_stack_top = .;")); + assert!(script.contains("__kernel_code_end = .;")); + assert!( + !script.contains("${"), + "all template tokens must be rendered" + ); +} + +#[test] +fn renders_common_symbols_for_all_arches() { + for arch in [ + LinkerArch::Aarch64, + LinkerArch::Loongarch64, + LinkerArch::X86_64, + LinkerArch::Riscv64, + ] { + let script = render_linker_script(arch, CONFIG); + assert_common_contract(&script); + } +} + +#[test] +fn preserves_arch_specific_linker_contracts() { + let aarch64 = render_linker_script(LinkerArch::Aarch64, CONFIG); + assert!(aarch64.contains("OUTPUT_ARCH(aarch64)")); + assert!(aarch64.contains("_kernel_entry = ABSOLUTE(kernel_entry & 0xffffffffffff);")); + assert!(aarch64.contains("KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*)))")); + + let loongarch64 = render_linker_script(LinkerArch::Loongarch64, CONFIG); + assert!(loongarch64.contains("OUTPUT_ARCH(loongarch)")); + assert!(loongarch64.contains("ENTRY(kernel_entry)")); + assert!(loongarch64.contains(". = ALIGN(0x10000);")); + assert!( + loongarch64 + .contains("_kernel_entry = ABSOLUTE(KERNEL_LOAD_ADDRESS + (kernel_entry - _head));") + ); + + let x86_64 = render_linker_script(LinkerArch::X86_64, CONFIG); + assert!(x86_64.contains("OUTPUT_ARCH(i386:x86-64)")); + assert!(x86_64.contains("_kernel_image_size = ABSOLUTE(_end - _head);")); + assert!(!x86_64.contains("*(.options)")); + + let riscv64 = render_linker_script(LinkerArch::Riscv64, CONFIG); + assert!(riscv64.contains("OUTPUT_ARCH(riscv)")); + assert!(riscv64.contains("KEEP(*(.text._head))")); + assert!(riscv64.contains(".dynamic : ALIGN(8)")); + assert!(!riscv64.contains("*(.dynamic .dynsym .dynstr .hash .gnu.hash)")); +} + +#[test] +fn tracks_arch_templates_and_shared_fragments_for_cargo_reruns() { + let paths = source_paths(); + + assert!(paths.contains(&"build_support/linker.rs")); + assert!(paths.contains(&"src/arch/aarch64/link.ld")); + assert!(paths.contains(&"src/arch/loongarch64/link.ld")); + assert!(paths.contains(&"src/arch/riscv64/link.ld")); + assert!(paths.contains(&"src/arch/x86_64/link.ld")); + assert!(paths.contains(&"src/ld/text.ld")); + assert!(paths.contains(&"src/ld/bss.ld")); + assert!(paths.contains(&"src/ld/discard-exit.ld")); +} diff --git a/scripts/axbuild/src/test/host_http.rs b/scripts/axbuild/src/test/host_http.rs index dbec380a9f..feef992e30 100644 --- a/scripts/axbuild/src/test/host_http.rs +++ b/scripts/axbuild/src/test/host_http.rs @@ -7,13 +7,16 @@ use std::{ mpsc, }, thread, - time::Duration, + time::{Duration, Instant}, }; use anyhow::{Context, bail}; use crate::test::case::HostHttpServerConfig; +const BIND_RETRY_TIMEOUT: Duration = Duration::from_secs(180); +const BIND_RETRY_INTERVAL: Duration = Duration::from_millis(50); + pub(crate) struct HostHttpServerGuard { stop: Arc, thread: Option>, @@ -22,9 +25,7 @@ pub(crate) struct HostHttpServerGuard { impl HostHttpServerGuard { pub(crate) fn start(config: &HostHttpServerConfig, case_name: &str) -> anyhow::Result { let addr = format!("{}:{}", config.bind, config.port); - let listener = TcpListener::bind(&addr).with_context(|| { - format!("failed to bind host HTTP server `{addr}` for `{case_name}`") - })?; + let listener = bind_listener(&addr, case_name)?; listener .set_nonblocking(true) .with_context(|| format!("failed to configure host HTTP server `{addr}`"))?; @@ -71,6 +72,38 @@ impl HostHttpServerGuard { } } +fn bind_listener(addr: &str, case_name: &str) -> anyhow::Result { + let started = Instant::now(); + let mut reported_wait = false; + + loop { + match TcpListener::bind(addr) { + Ok(listener) => return Ok(listener), + Err(err) + if err.kind() == std::io::ErrorKind::AddrInUse + && started.elapsed() < BIND_RETRY_TIMEOUT => + { + if !reported_wait { + println!( + " host http server: waiting for {addr} to become available for \ + {case_name}" + ); + reported_wait = true; + } + thread::sleep(BIND_RETRY_INTERVAL); + } + Err(err) => { + return Err(err).with_context(|| { + format!( + "failed to bind host HTTP server `{addr}` for `{case_name}` after waiting \ + up to {BIND_RETRY_TIMEOUT:?}" + ) + }); + } + } + } +} + #[derive(Debug, Clone)] enum HostHttpBody { Static(Vec), @@ -123,7 +156,12 @@ impl Drop for HostHttpServerGuard { #[cfg(test)] mod tests { - use std::net::{TcpListener, TcpStream}; + use std::{ + net::{TcpListener, TcpStream}, + sync::mpsc, + thread, + time::Duration, + }; use super::*; @@ -156,6 +194,43 @@ mod tests { assert_eq!(&response[body_offset..], b"XXXXXXX"); } + #[test] + #[cfg(unix)] + fn same_host_http_port_waits_for_active_guard() { + let port = free_local_port(); + let config = HostHttpServerConfig { + bind: "127.0.0.1".to_string(), + port, + body: "first".to_string(), + body_size: None, + body_byte: b'A', + }; + + let first_guard = HostHttpServerGuard::start(&config, "first").unwrap(); + let second_config = config.clone(); + let (tx, rx) = mpsc::channel(); + let second_thread = thread::spawn(move || { + let result = HostHttpServerGuard::start(&second_config, "second").map(|_guard| ()); + tx.send(result.map_err(|err| err.to_string())).unwrap(); + }); + + match rx.recv_timeout(Duration::from_millis(100)) { + Err(mpsc::RecvTimeoutError::Timeout) => {} + Err(err) => panic!("second host HTTP guard channel failed: {err}"), + Ok(result) => { + panic!("second host HTTP guard did not wait for the first guard: {result:?}") + } + } + + drop(first_guard); + + let result = rx + .recv_timeout(Duration::from_secs(2)) + .expect("second host HTTP guard did not start after the first guard dropped"); + assert!(result.is_ok(), "{result:?}"); + second_thread.join().unwrap(); + } + fn free_local_port() -> u16 { TcpListener::bind("127.0.0.1:0") .unwrap()