diff --git a/Cargo.toml b/Cargo.toml index 873b7a3e..35df4cad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -96,7 +96,7 @@ rustflags = [ "-C", "link-args=--image-base 0xFFFF800000000000", "-C", - "relocation-model=static", # pic in higher half not supported yet + "relocation-model=pie", # pic in higher half not supported yet "-C", "code-model=large", ] diff --git a/build.rs b/build.rs index 6259ed71..96255efa 100644 --- a/build.rs +++ b/build.rs @@ -55,6 +55,7 @@ fn build_uefi_bootloader(out_dir: &Path) -> PathBuf { // local build cmd.arg("--path").arg("uefi"); println!("cargo:rerun-if-changed=uefi"); + println!("cargo:rerun-if-changed=common"); } else { cmd.arg("--version").arg(BOOTLOADER_X86_64_UEFI_VERSION); } @@ -135,6 +136,10 @@ fn build_bios_stage_2(out_dir: &Path) -> PathBuf { // local build cmd.arg("--path").arg(&local_path); println!("cargo:rerun-if-changed={}", local_path.display()); + println!( + "cargo:rerun-if-changed={}", + local_path.with_file_name("common").display() + ); } else { cmd.arg("--version") .arg(BOOTLOADER_X86_64_BIOS_STAGE_2_VERSION); diff --git a/common/src/level_4_entries.rs b/common/src/level_4_entries.rs index 2e5e1c4c..338263a5 100644 --- a/common/src/level_4_entries.rs +++ b/common/src/level_4_entries.rs @@ -126,11 +126,11 @@ impl UsedLevel4Entries { pub fn mark_segments<'a>( &mut self, segments: impl Iterator>, - virtual_address_offset: u64, + virtual_address_offset: i128, ) { for segment in segments.filter(|s| s.mem_size() > 0) { self.mark_range_as_used( - segment.virtual_addr() + virtual_address_offset, + u64::try_from(i128::from(segment.virtual_addr()) + virtual_address_offset).unwrap(), segment.mem_size(), ); } @@ -158,7 +158,8 @@ impl UsedLevel4Entries { // Choose the first index. free_entries.next() }; - let idx = idx_opt.expect("no usable level 4 entries found"); + let idx = idx_opt + .unwrap_or_else(|| panic!("no usable level 4 entries found ({num} entries requested)")); // Mark the entries as used. for i in 0..num.into_usize() { diff --git a/common/src/load_kernel.rs b/common/src/load_kernel.rs index c0bb3eb1..56853954 100644 --- a/common/src/load_kernel.rs +++ b/common/src/load_kernel.rs @@ -29,7 +29,7 @@ struct Loader<'a, M, F> { struct Inner<'a, M, F> { kernel_offset: PhysAddr, - virtual_address_offset: u64, + virtual_address_offset: i128, page_table: &'a mut M, frame_allocator: &'a mut F, } @@ -65,18 +65,26 @@ where let load_program_headers = elf_file .program_iter() .filter(|h| matches!(h.get_type(), Ok(Type::Load))); - let size = load_program_headers + let max_addr = load_program_headers .clone() .map(|h| h.virtual_addr() + h.mem_size()) .max() .unwrap_or(0); + let min_addr = load_program_headers + .clone() + .map(|h| h.virtual_addr()) + .min() + .unwrap_or(0); + let size = max_addr - min_addr; let align = load_program_headers.map(|h| h.align()).max().unwrap_or(1); - used_entries.get_free_address(size, align).as_u64() + let offset = used_entries.get_free_address(size, align).as_u64(); + offset as i128 - min_addr as i128 } header::Type::Core => unimplemented!(), header::Type::ProcessorSpecific(_) => unimplemented!(), }; + log::info!("virtual_address_offset: {virtual_address_offset:#x}"); used_entries.mark_segments(elf_file.program_iter(), virtual_address_offset); @@ -141,7 +149,13 @@ where } fn entry_point(&self) -> VirtAddr { - VirtAddr::new(self.elf_file.header.pt2.entry_point() + self.inner.virtual_address_offset) + VirtAddr::new( + u64::try_from( + i128::from(self.elf_file.header.pt2.entry_point()) + + self.inner.virtual_address_offset, + ) + .unwrap(), + ) } } @@ -158,7 +172,10 @@ where let end_frame: PhysFrame = PhysFrame::containing_address(phys_start_addr + segment.file_size() - 1u64); - let virt_start_addr = VirtAddr::new(segment.virtual_addr()) + self.virtual_address_offset; + let virt_start_addr = VirtAddr::new( + u64::try_from(i128::from(segment.virtual_addr()) + self.virtual_address_offset) + .unwrap(), + ); let start_page: Page = Page::containing_address(virt_start_addr); let mut segment_flags = Flags::PRESENT; @@ -198,7 +215,10 @@ where ) -> Result<(), &'static str> { log::info!("Mapping bss section"); - let virt_start_addr = VirtAddr::new(segment.virtual_addr()) + self.virtual_address_offset; + let virt_start_addr = VirtAddr::new( + u64::try_from(i128::from(segment.virtual_addr()) + self.virtual_address_offset) + .unwrap(), + ); let mem_size = segment.mem_size(); let file_size = segment.file_size(); @@ -343,7 +363,10 @@ where fn remove_copied_flags(&mut self, elf_file: &ElfFile) -> Result<(), &'static str> { for program_header in elf_file.program_iter() { if let Type::Load = program_header.get_type()? { - let start = self.virtual_address_offset + program_header.virtual_addr(); + let start = u64::try_from( + self.virtual_address_offset + i128::from(program_header.virtual_addr()), + ) + .unwrap(); let end = start + program_header.mem_size(); let start = VirtAddr::new(start); let end = VirtAddr::new(end); @@ -380,7 +403,10 @@ where fn handle_tls_segment(&mut self, segment: ProgramHeader) -> Result { Ok(TlsTemplate { - start_addr: segment.virtual_addr() + self.virtual_address_offset, + start_addr: u64::try_from( + i128::from(segment.virtual_addr()) + self.virtual_address_offset, + ) + .unwrap(), mem_size: segment.mem_size(), file_size: segment.file_size(), }) @@ -476,11 +502,15 @@ where // R_AMD64_RELATIVE 8 => { check_is_in_load(elf_file, rela.get_offset())?; - let addr = self.virtual_address_offset + rela.get_offset(); - let value = self - .virtual_address_offset - .checked_add(rela.get_addend()) - .unwrap(); + let addr = + u64::try_from(self.virtual_address_offset + i128::from(rela.get_offset())) + .unwrap(); + let value = u64::try_from( + self.virtual_address_offset + .checked_add(i128::from(rela.get_addend())) + .unwrap(), + ) + .unwrap(); let ptr = addr as *mut u64; if ptr as usize % align_of::() != 0 { @@ -511,7 +541,9 @@ where /// need to be writable while applying relocations, but should never be /// written to after relocations have been applied. fn handle_relro_segment(&mut self, program_header: ProgramHeader) { - let start = self.virtual_address_offset + program_header.virtual_addr(); + let start = + u64::try_from(self.virtual_address_offset + i128::from(program_header.virtual_addr())) + .unwrap(); let end = start + program_header.mem_size(); let start = VirtAddr::new(start); let end = VirtAddr::new(end); diff --git a/tests/runner/src/lib.rs b/tests/runner/src/lib.rs index 7f50cd42..87683333 100644 --- a/tests/runner/src/lib.rs +++ b/tests/runner/src/lib.rs @@ -5,8 +5,8 @@ const QEMU_ARGS: &[&str] = &[ "isa-debug-exit,iobase=0xf4,iosize=0x04", "-serial", "stdio", - "-display", - "none", + // "-display", + // "none", "--no-reboot", ];