mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-09 05:16:47 +00:00
support dynamic linking
This commit is contained in:
parent
567ac612e5
commit
d19dc09563
121
src/Cargo.lock
generated
121
src/Cargo.lock
generated
@ -24,6 +24,23 @@ dependencies = [
|
|||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "align_ext"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aml"
|
||||||
|
version = "0.16.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5dcf92e2afd8d6607e435cdc1d8ea76260fa467f6cf821f6af40e88dca15d183"
|
||||||
|
dependencies = [
|
||||||
|
"bit_field",
|
||||||
|
"bitvec",
|
||||||
|
"byteorder",
|
||||||
|
"log",
|
||||||
|
"spinning_top",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.32"
|
version = "1.0.32"
|
||||||
@ -60,6 +77,18 @@ version = "1.3.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitvec"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c"
|
||||||
|
dependencies = [
|
||||||
|
"funty",
|
||||||
|
"radium",
|
||||||
|
"tap",
|
||||||
|
"wyz",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "buddy_system_allocator"
|
name = "buddy_system_allocator"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
@ -69,6 +98,12 @@ dependencies = [
|
|||||||
"spin 0.9.4",
|
"spin 0.9.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "byteorder"
|
||||||
|
version = "1.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
@ -131,6 +166,12 @@ version = "0.2.7"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e63201c624b8c8883921b1a1accc8916c4fa9dbfb15d122b26e4dde945b86bbf"
|
checksum = "e63201c624b8c8883921b1a1accc8916c4fa9dbfb15d122b26e4dde945b86bbf"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "funty"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ghost"
|
name = "ghost"
|
||||||
version = "0.1.7"
|
version = "0.1.7"
|
||||||
@ -179,7 +220,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "inventory"
|
name = "inventory"
|
||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
source = "git+https://github.com/sdww0/inventory#6356dc79fb15ae4e72ddb6fe826a3ea76d9046a5"
|
source = "git+https://github.com/sdww0/inventory?rev=6356dc7#6356dc79fb15ae4e72ddb6fe826a3ea76d9046a5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ctor",
|
"ctor",
|
||||||
"ghost",
|
"ghost",
|
||||||
@ -200,7 +241,9 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"component",
|
"component",
|
||||||
"jinux-frame",
|
"jinux-frame",
|
||||||
|
"jinux-framebuffer",
|
||||||
"jinux-std",
|
"jinux-std",
|
||||||
|
"jinux-time",
|
||||||
"limine",
|
"limine",
|
||||||
"x86_64",
|
"x86_64",
|
||||||
]
|
]
|
||||||
@ -217,7 +260,6 @@ dependencies = [
|
|||||||
"jinux-virtio",
|
"jinux-virtio",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"log",
|
"log",
|
||||||
"pod",
|
|
||||||
"spin 0.9.4",
|
"spin 0.9.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -234,9 +276,11 @@ name = "jinux-frame"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"acpi",
|
"acpi",
|
||||||
|
"align_ext",
|
||||||
|
"aml",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"buddy_system_allocator",
|
"buddy_system_allocator",
|
||||||
"font8x8",
|
"cfg-if",
|
||||||
"intrusive-collections",
|
"intrusive-collections",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"limine",
|
"limine",
|
||||||
@ -244,12 +288,22 @@ dependencies = [
|
|||||||
"pod",
|
"pod",
|
||||||
"spin 0.9.4",
|
"spin 0.9.4",
|
||||||
"trapframe",
|
"trapframe",
|
||||||
"uart_16550",
|
|
||||||
"volatile",
|
"volatile",
|
||||||
"x86",
|
"x86",
|
||||||
"x86_64",
|
"x86_64",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jinux-framebuffer"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"component",
|
||||||
|
"font8x8",
|
||||||
|
"jinux-frame",
|
||||||
|
"log",
|
||||||
|
"spin 0.9.4",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jinux-input"
|
name = "jinux-input"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@ -262,7 +316,6 @@ dependencies = [
|
|||||||
"jinux-virtio",
|
"jinux-virtio",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"log",
|
"log",
|
||||||
"pod",
|
|
||||||
"spin 0.9.4",
|
"spin 0.9.4",
|
||||||
"virtio-input-decoder",
|
"virtio-input-decoder",
|
||||||
]
|
]
|
||||||
@ -294,6 +347,7 @@ dependencies = [
|
|||||||
name = "jinux-std"
|
name = "jinux-std"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"align_ext",
|
||||||
"ascii",
|
"ascii",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"controlled",
|
"controlled",
|
||||||
@ -303,6 +357,7 @@ dependencies = [
|
|||||||
"jinux-frame",
|
"jinux-frame",
|
||||||
"jinux-input",
|
"jinux-input",
|
||||||
"jinux-rights-proc",
|
"jinux-rights-proc",
|
||||||
|
"jinux-time",
|
||||||
"jinux-util",
|
"jinux-util",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"log",
|
"log",
|
||||||
@ -318,6 +373,16 @@ dependencies = [
|
|||||||
"xmas-elf",
|
"xmas-elf",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jinux-time"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"component",
|
||||||
|
"jinux-frame",
|
||||||
|
"log",
|
||||||
|
"spin 0.9.4",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jinux-util"
|
name = "jinux-util"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@ -422,6 +487,7 @@ checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "pod"
|
name = "pod"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
source = "git+https://github.com/jinzhao-dev/pod?rev=7fa2ed2#7fa2ed2bb8344856f98f0d533ecb1bab238f79ba"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"pod-derive",
|
"pod-derive",
|
||||||
]
|
]
|
||||||
@ -429,6 +495,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "pod-derive"
|
name = "pod-derive"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
source = "git+https://github.com/jinzhao-dev/pod?rev=7fa2ed2#7fa2ed2bb8344856f98f0d533ecb1bab238f79ba"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -453,6 +520,12 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "radium"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "raw-cpuid"
|
name = "raw-cpuid"
|
||||||
version = "10.7.0"
|
version = "10.7.0"
|
||||||
@ -529,6 +602,15 @@ dependencies = [
|
|||||||
"lock_api",
|
"lock_api",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spinning_top"
|
||||||
|
version = "0.2.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b9eb1a2f4c41445a3a0ff9abc5221c5fcd28e1f13cd7c0397706f9ac938ddb0"
|
||||||
|
dependencies = [
|
||||||
|
"lock_api",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.109"
|
version = "1.0.109"
|
||||||
@ -540,6 +622,12 @@ dependencies = [
|
|||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tap"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.37"
|
version = "1.0.37"
|
||||||
@ -613,9 +701,10 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "trapframe"
|
name = "trapframe"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
source = "git+https://github.com/sdww0/trapframe-rs?rev=13e1065#13e106595d3cde9988e101e6b51e8fb9da38053d"
|
source = "git+https://github.com/sdww0/trapframe-rs?rev=4234db5#4234db5ceb667a46c3a7b68b63a5e9ef25993ef9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
|
"pod",
|
||||||
"raw-cpuid",
|
"raw-cpuid",
|
||||||
"x86_64",
|
"x86_64",
|
||||||
]
|
]
|
||||||
@ -634,17 +723,6 @@ dependencies = [
|
|||||||
name = "typeflags-util"
|
name = "typeflags-util"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "uart_16550"
|
|
||||||
version = "0.2.18"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b074eb9300ad949edd74c529c0e8d451625af71bb948e6b65fe69f72dc1363d9"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags",
|
|
||||||
"rustversion",
|
|
||||||
"x86_64",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.5"
|
version = "1.0.5"
|
||||||
@ -720,6 +798,15 @@ dependencies = [
|
|||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wyz"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed"
|
||||||
|
dependencies = [
|
||||||
|
"tap",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "x86"
|
name = "x86"
|
||||||
version = "0.52.0"
|
version = "0.52.0"
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:da31082cbaabc14fb9f6b62933844d61a73942dd23a28ac920d86c163126b530
|
oid sha256:64b67cf4ad247d668833888447ec7f12d37f5f816abd549d5c2c08fecfa4dd09
|
||||||
size 16696
|
size 16696
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
printf("hello world from hello_c!\n");
|
printf("hello world from hello_pie!\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
@ -9,6 +9,7 @@
|
|||||||
#![feature(btree_drain_filter)]
|
#![feature(btree_drain_filter)]
|
||||||
#![feature(const_option)]
|
#![feature(const_option)]
|
||||||
#![feature(extend_one)]
|
#![feature(extend_one)]
|
||||||
|
#![feature(let_chains)]
|
||||||
// FIXME: This feature is used to support vm capbility now as a work around.
|
// FIXME: This feature is used to support vm capbility now as a work around.
|
||||||
// Since this is an incomplete feature, use this feature is unsafe.
|
// Since this is an incomplete feature, use this feature is unsafe.
|
||||||
// We should find a proper method to replace this feature with min_specialization, which is a sound feature.
|
// We should find a proper method to replace this feature with min_specialization, which is a sound feature.
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/// A wrapper of xmas_elf's elf parsing
|
/// A wrapper of xmas_elf's elf parsing
|
||||||
use xmas_elf::{
|
use xmas_elf::{
|
||||||
header::{self, Header, HeaderPt1, HeaderPt2, HeaderPt2_, Machine_, Type_},
|
header::{self, Header, HeaderPt1, HeaderPt2, HeaderPt2_, Machine_, Type_},
|
||||||
program::ProgramHeader64,
|
program::{self, ProgramHeader64},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
@ -86,6 +86,34 @@ impl Elf {
|
|||||||
pub fn is_shared_object(&self) -> bool {
|
pub fn is_shared_object(&self) -> bool {
|
||||||
self.elf_header.pt2.type_.as_type() == header::Type::SharedObject
|
self.elf_header.pt2.type_.as_type() == header::Type::SharedObject
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// read the ldso path from the elf interpret section
|
||||||
|
pub fn ldso_path(&self, file_header_buf: &[u8]) -> Result<String> {
|
||||||
|
for program_header in &self.program_headers {
|
||||||
|
let type_ = program_header.get_type().map_err(|_| {
|
||||||
|
Error::with_message(Errno::ENOEXEC, "parse program header type fails")
|
||||||
|
})?;
|
||||||
|
if type_ == program::Type::Interp {
|
||||||
|
let file_size = program_header.file_size as usize;
|
||||||
|
let file_offset = program_header.offset as usize;
|
||||||
|
debug_assert!(file_offset + file_size <= file_header_buf.len());
|
||||||
|
let ldso = CStr::from_bytes_with_nul(
|
||||||
|
&file_header_buf[file_offset..file_offset + file_size],
|
||||||
|
)?;
|
||||||
|
return Ok(ldso.to_string_lossy().to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return_errno_with_message!(
|
||||||
|
Errno::ENOEXEC,
|
||||||
|
"cannot find interpreter section in dyn-link program"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// An offset to be subtracted from ELF vaddr for PIE
|
||||||
|
pub fn base_load_address_offset(&self) -> u64 {
|
||||||
|
let phdr = self.program_headers.iter().nth(0).unwrap();
|
||||||
|
phdr.virtual_addr - phdr.offset
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ElfHeader {
|
pub struct ElfHeader {
|
||||||
|
@ -15,6 +15,7 @@ use jinux_frame::vm::{VmIo, VmPerm};
|
|||||||
|
|
||||||
use super::aux_vec::{AuxKey, AuxVec};
|
use super::aux_vec::{AuxKey, AuxVec};
|
||||||
use super::elf_file::Elf;
|
use super::elf_file::Elf;
|
||||||
|
use super::load_elf::LdsoLoadInfo;
|
||||||
|
|
||||||
pub const INIT_STACK_BASE: Vaddr = 0x0000_0000_2000_0000;
|
pub const INIT_STACK_BASE: Vaddr = 0x0000_0000_2000_0000;
|
||||||
pub const INIT_STACK_SIZE: usize = 0x1000 * 16; // 64KB
|
pub const INIT_STACK_SIZE: usize = 0x1000 * 16; // 64KB
|
||||||
@ -109,9 +110,15 @@ impl InitStack {
|
|||||||
self.init_stack_top - self.init_stack_size
|
self.init_stack_top - self.init_stack_size
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init(&mut self, root_vmar: &Vmar<Full>, elf: &Elf, aux_vec: &mut AuxVec) -> Result<()> {
|
pub fn init(
|
||||||
|
&mut self,
|
||||||
|
root_vmar: &Vmar<Full>,
|
||||||
|
elf: &Elf,
|
||||||
|
ldso_load_info: &Option<LdsoLoadInfo>,
|
||||||
|
aux_vec: &mut AuxVec,
|
||||||
|
) -> Result<()> {
|
||||||
self.map_and_zeroed(root_vmar)?;
|
self.map_and_zeroed(root_vmar)?;
|
||||||
self.write_stack_content(root_vmar, elf, aux_vec)?;
|
self.write_stack_content(root_vmar, elf, ldso_load_info, aux_vec)?;
|
||||||
self.debug_print_stack_content(root_vmar);
|
self.debug_print_stack_content(root_vmar);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -155,6 +162,7 @@ impl InitStack {
|
|||||||
&mut self,
|
&mut self,
|
||||||
root_vmar: &Vmar<Full>,
|
root_vmar: &Vmar<Full>,
|
||||||
elf: &Elf,
|
elf: &Elf,
|
||||||
|
ldso_load_info: &Option<LdsoLoadInfo>,
|
||||||
aux_vec: &mut AuxVec,
|
aux_vec: &mut AuxVec,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
// write a zero page. When a user program tries to read a cstring(like argv) from init stack,
|
// write a zero page. When a user program tries to read a cstring(like argv) from init stack,
|
||||||
@ -173,6 +181,10 @@ impl InitStack {
|
|||||||
let random_value = generate_random_for_aux_vec();
|
let random_value = generate_random_for_aux_vec();
|
||||||
let random_value_pointer = self.write_bytes(&random_value, root_vmar)?;
|
let random_value_pointer = self.write_bytes(&random_value, root_vmar)?;
|
||||||
aux_vec.set(AuxKey::AT_RANDOM, random_value_pointer)?;
|
aux_vec.set(AuxKey::AT_RANDOM, random_value_pointer)?;
|
||||||
|
if let Some(ldso_load_info) = ldso_load_info {
|
||||||
|
let ldso_base = ldso_load_info.base_addr();
|
||||||
|
aux_vec.set(AuxKey::AT_BASE, ldso_base as u64)?;
|
||||||
|
}
|
||||||
self.adjust_stack_alignment(root_vmar, &envp_pointers, &argv_pointers, &aux_vec)?;
|
self.adjust_stack_alignment(root_vmar, &envp_pointers, &argv_pointers, &aux_vec)?;
|
||||||
self.write_aux_vec(root_vmar, aux_vec)?;
|
self.write_aux_vec(root_vmar, aux_vec)?;
|
||||||
self.write_envp_pointers(root_vmar, envp_pointers)?;
|
self.write_envp_pointers(root_vmar, envp_pointers)?;
|
||||||
@ -331,6 +343,13 @@ pub fn init_aux_vec(elf: &Elf, elf_map_addr: Option<Vaddr>) -> Result<AuxVec> {
|
|||||||
aux_vec.set(AuxKey::AT_PHDR, ph_addr as u64)?;
|
aux_vec.set(AuxKey::AT_PHDR, ph_addr as u64)?;
|
||||||
aux_vec.set(AuxKey::AT_PHNUM, elf.ph_count() as u64)?;
|
aux_vec.set(AuxKey::AT_PHNUM, elf.ph_count() as u64)?;
|
||||||
aux_vec.set(AuxKey::AT_PHENT, elf.ph_ent() as u64)?;
|
aux_vec.set(AuxKey::AT_PHENT, elf.ph_ent() as u64)?;
|
||||||
|
let elf_entry = if elf.is_shared_object() {
|
||||||
|
let base_load_offset = elf.base_load_address_offset();
|
||||||
|
elf.entry_point() + elf_map_addr.unwrap() - base_load_offset as usize
|
||||||
|
} else {
|
||||||
|
elf.entry_point()
|
||||||
|
};
|
||||||
|
aux_vec.set(AuxKey::AT_ENTRY, elf_entry as u64)?;
|
||||||
Ok(aux_vec)
|
Ok(aux_vec)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
//! When create a process from elf file, we will use the elf_load_info to construct the VmSpace
|
//! When create a process from elf file, we will use the elf_load_info to construct the VmSpace
|
||||||
|
|
||||||
use crate::fs::file_handle::FileHandle;
|
use crate::fs::file_handle::FileHandle;
|
||||||
|
use crate::fs::fs_resolver::{FsPath, FsResolver, AT_FDCWD};
|
||||||
|
use crate::fs::utils::AccessMode;
|
||||||
use crate::process::program_loader::elf::init_stack::{init_aux_vec, InitStack};
|
use crate::process::program_loader::elf::init_stack::{init_aux_vec, InitStack};
|
||||||
use crate::vm::perms::VmPerms;
|
use crate::vm::perms::VmPerms;
|
||||||
use crate::vm::vmo::VmoRightsOp;
|
use crate::vm::vmo::VmoRightsOp;
|
||||||
@ -28,24 +30,87 @@ pub fn load_elf_to_root_vmar(
|
|||||||
root_vmar: &Vmar<Full>,
|
root_vmar: &Vmar<Full>,
|
||||||
file_header: &[u8],
|
file_header: &[u8],
|
||||||
elf_file: Arc<FileHandle>,
|
elf_file: Arc<FileHandle>,
|
||||||
|
fs_resolver: &FsResolver,
|
||||||
argv: Vec<CString>,
|
argv: Vec<CString>,
|
||||||
envp: Vec<CString>,
|
envp: Vec<CString>,
|
||||||
) -> Result<ElfLoadInfo> {
|
) -> Result<ElfLoadInfo> {
|
||||||
let elf = Elf::parse_elf(file_header)?;
|
let elf = Elf::parse_elf(file_header)?;
|
||||||
|
let ldso_load_info = if let Ok(ldso_load_info) =
|
||||||
|
load_ldso_for_shared_object(root_vmar, &elf, file_header, fs_resolver)
|
||||||
|
{
|
||||||
|
Some(ldso_load_info)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
let map_addr = map_segment_vmos(&elf, root_vmar, elf_file)?;
|
let map_addr = map_segment_vmos(&elf, root_vmar, elf_file)?;
|
||||||
let mut aux_vec = init_aux_vec(&elf, map_addr)?;
|
let mut aux_vec = init_aux_vec(&elf, map_addr)?;
|
||||||
let mut init_stack = InitStack::new_default_config(argv, envp);
|
let mut init_stack = InitStack::new_default_config(argv, envp);
|
||||||
init_stack.init(root_vmar, &elf, &mut aux_vec)?;
|
init_stack.init(root_vmar, &elf, &ldso_load_info, &mut aux_vec)?;
|
||||||
let entry_point = if elf.is_shared_object() {
|
let entry_point = if let Some(ldso_load_info) = ldso_load_info {
|
||||||
elf.entry_point() + map_addr.unwrap()
|
// Normal shared object
|
||||||
|
ldso_load_info.entry_point()
|
||||||
} else {
|
} else {
|
||||||
elf.entry_point()
|
if elf.is_shared_object() {
|
||||||
|
// ldso itself
|
||||||
|
elf.entry_point() + map_addr.unwrap()
|
||||||
|
} else {
|
||||||
|
// statically linked executable
|
||||||
|
elf.entry_point()
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let elf_load_info = ElfLoadInfo::new(entry_point, init_stack.user_stack_top());
|
let elf_load_info = ElfLoadInfo::new(entry_point, init_stack.user_stack_top());
|
||||||
debug!("load elf succeeds.");
|
debug!("load elf succeeds.");
|
||||||
Ok(elf_load_info)
|
Ok(elf_load_info)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn load_ldso_for_shared_object(
|
||||||
|
root_vmar: &Vmar<Full>,
|
||||||
|
elf: &Elf,
|
||||||
|
file_header: &[u8],
|
||||||
|
fs_resolver: &FsResolver,
|
||||||
|
) -> Result<LdsoLoadInfo> {
|
||||||
|
if let Ok(ldso_path) = elf.ldso_path(file_header) && elf.is_shared_object(){
|
||||||
|
trace!("ldso_path = {:?}", ldso_path);
|
||||||
|
let fs_path = FsPath::new(AT_FDCWD, &ldso_path)?;
|
||||||
|
let ldso_file = fs_resolver.open(&fs_path, AccessMode::O_RDONLY as u32, 0)?;
|
||||||
|
let mut buf = Box::new([0u8; PAGE_SIZE]);
|
||||||
|
let ldso_header = ldso_file.read(&mut *buf)?;
|
||||||
|
let ldso_elf = Elf::parse_elf(&*buf)?;
|
||||||
|
let ldso_file = Arc::new(FileHandle::new_inode_handle(ldso_file));
|
||||||
|
let map_addr = map_segment_vmos(&ldso_elf, root_vmar, ldso_file)?.unwrap();
|
||||||
|
return Ok(LdsoLoadInfo::new(ldso_elf.entry_point() + map_addr, map_addr));
|
||||||
|
}
|
||||||
|
// There are three reasons that an executable may lack ldso_path,
|
||||||
|
// 1. this is a statically linked executable,
|
||||||
|
// 2. the shared object is invalid,
|
||||||
|
// 3. the shared object is ldso itself,
|
||||||
|
// we don't try to distinguish these cases and just let it go.
|
||||||
|
return_errno_with_message!(Errno::ENOEXEC, "cannot find ldso for shared object");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct LdsoLoadInfo {
|
||||||
|
entry_point: Vaddr,
|
||||||
|
base_addr: Vaddr,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LdsoLoadInfo {
|
||||||
|
pub fn new(entry_point: Vaddr, base_addr: Vaddr) -> Self {
|
||||||
|
Self {
|
||||||
|
entry_point,
|
||||||
|
base_addr,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn entry_point(&self) -> Vaddr {
|
||||||
|
self.entry_point
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn base_addr(&self) -> Vaddr {
|
||||||
|
self.base_addr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct ElfLoadInfo {
|
pub struct ElfLoadInfo {
|
||||||
entry_point: Vaddr,
|
entry_point: Vaddr,
|
||||||
user_stack_top: Vaddr,
|
user_stack_top: Vaddr,
|
||||||
@ -74,8 +139,13 @@ pub fn map_segment_vmos(
|
|||||||
root_vmar: &Vmar<Full>,
|
root_vmar: &Vmar<Full>,
|
||||||
elf_file: Arc<FileHandle>,
|
elf_file: Arc<FileHandle>,
|
||||||
) -> Result<Option<Vaddr>> {
|
) -> Result<Option<Vaddr>> {
|
||||||
let is_shared_object = elf.is_shared_object();
|
// all segments of the shared object must be mapped to a continuous vm range
|
||||||
let mut file_map_addr = None;
|
// to ensure the relative offset of each segment not changed.
|
||||||
|
let file_map_addr = if elf.is_shared_object() {
|
||||||
|
Some(hint_elf_map_addr(elf, root_vmar)?)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
for program_header in &elf.program_headers {
|
for program_header in &elf.program_headers {
|
||||||
let type_ = program_header
|
let type_ = program_header
|
||||||
.get_type()
|
.get_type()
|
||||||
@ -87,43 +157,49 @@ pub fn map_segment_vmos(
|
|||||||
vmo,
|
vmo,
|
||||||
root_vmar,
|
root_vmar,
|
||||||
elf_file.clone(),
|
elf_file.clone(),
|
||||||
&mut file_map_addr,
|
&file_map_addr,
|
||||||
is_shared_object,
|
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(file_map_addr)
|
Ok(file_map_addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn hint_elf_map_addr(elf: &Elf, root_vmar: &Vmar<Full>) -> Result<Vaddr> {
|
||||||
|
let mut size = 0;
|
||||||
|
for program_header in &elf.program_headers {
|
||||||
|
let ph_size = program_header.virtual_addr + program_header.mem_size;
|
||||||
|
if ph_size > size {
|
||||||
|
size = ph_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
root_vmar.hint_map_addr(size as usize)
|
||||||
|
}
|
||||||
|
|
||||||
/// map the segment vmo to root_vmar
|
/// map the segment vmo to root_vmar
|
||||||
fn map_segment_vmo(
|
fn map_segment_vmo(
|
||||||
program_header: &ProgramHeader64,
|
program_header: &ProgramHeader64,
|
||||||
vmo: Vmo,
|
vmo: Vmo,
|
||||||
root_vmar: &Vmar<Full>,
|
root_vmar: &Vmar<Full>,
|
||||||
elf_file: Arc<FileHandle>,
|
elf_file: Arc<FileHandle>,
|
||||||
file_map_addr: &mut Option<Vaddr>,
|
file_map_addr: &Option<Vaddr>,
|
||||||
is_shared_object: bool,
|
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let perms = VmPerms::from(parse_segment_perm(program_header.flags)?);
|
let perms = VmPerms::from(parse_segment_perm(program_header.flags)?);
|
||||||
|
// let perms = VmPerms::READ | VmPerms::WRITE | VmPerms::EXEC;
|
||||||
let offset = (program_header.virtual_addr as Vaddr).align_down(PAGE_SIZE);
|
let offset = (program_header.virtual_addr as Vaddr).align_down(PAGE_SIZE);
|
||||||
debug!(
|
trace!(
|
||||||
"map segment vmo: offset = 0x{:x}, virtual_addr = 0x{:x}",
|
"map segment vmo: virtual addr = 0x{:x}, size = 0x{:x}, perms = {:?}",
|
||||||
offset, program_header.virtual_addr
|
program_header.virtual_addr,
|
||||||
|
program_header.file_size,
|
||||||
|
perms
|
||||||
);
|
);
|
||||||
let mut vm_map_options = root_vmar.new_map(vmo, perms)?;
|
let mut vm_map_options = root_vmar.new_map(vmo, perms)?;
|
||||||
// offset = 0 means the vmo can be put at any address
|
if let Some(file_map_addr) = *file_map_addr {
|
||||||
if is_shared_object {
|
let offset = file_map_addr + offset;
|
||||||
if let Some(file_init_addr) = *file_map_addr {
|
vm_map_options = vm_map_options.offset(offset);
|
||||||
let offset = file_init_addr + offset;
|
|
||||||
vm_map_options = vm_map_options.offset(offset);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
vm_map_options = vm_map_options.offset(offset);
|
vm_map_options = vm_map_options.offset(offset);
|
||||||
}
|
}
|
||||||
let map_addr = vm_map_options.build()?;
|
let map_addr = vm_map_options.build()?;
|
||||||
if is_shared_object && *file_map_addr == None {
|
|
||||||
*file_map_addr = Some(map_addr);
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,11 +38,11 @@ pub fn load_program_to_root_vmar(
|
|||||||
let file = fs_resolver.open(&fs_path, AccessMode::O_RDONLY as u32, 0)?;
|
let file = fs_resolver.open(&fs_path, AccessMode::O_RDONLY as u32, 0)?;
|
||||||
let file_header = {
|
let file_header = {
|
||||||
// read the first page of file header
|
// read the first page of file header
|
||||||
let mut file_header_buffer = [0u8; PAGE_SIZE];
|
let mut file_header_buffer = Box::new([0u8; PAGE_SIZE]);
|
||||||
file.read(&mut file_header_buffer)?;
|
file.read(&mut *file_header_buffer)?;
|
||||||
file_header_buffer
|
file_header_buffer
|
||||||
};
|
};
|
||||||
if let Some(mut new_argv) = parse_shebang_line(&file_header)? {
|
if let Some(mut new_argv) = parse_shebang_line(&*file_header)? {
|
||||||
if recursion_limit == 0 {
|
if recursion_limit == 0 {
|
||||||
return_errno_with_message!(Errno::EINVAL, "the recursieve limit is reached");
|
return_errno_with_message!(Errno::EINVAL, "the recursieve limit is reached");
|
||||||
}
|
}
|
||||||
@ -60,5 +60,5 @@ pub fn load_program_to_root_vmar(
|
|||||||
|
|
||||||
let elf_file = Arc::new(FileHandle::new_inode_handle(file));
|
let elf_file = Arc::new(FileHandle::new_inode_handle(file));
|
||||||
debug!("load executable, path = {}", executable_path);
|
debug!("load executable, path = {}", executable_path);
|
||||||
load_elf_to_root_vmar(root_vmar, &file_header, elf_file, argv, envp)
|
load_elf_to_root_vmar(root_vmar, &*file_header, elf_file, fs_resolver, argv, envp)
|
||||||
}
|
}
|
||||||
|
@ -21,20 +21,20 @@ pub fn handle_exception(context: &mut UserContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn handle_page_fault(trap_info: &TrapInformation) {
|
fn handle_page_fault(trap_info: &TrapInformation) {
|
||||||
const PAGE_NOT_PRESENT_ERROR_MASK: usize = 0x1 << 0;
|
const PAGE_NOT_PRESENT_ERROR_MASK: u64 = 0x1 << 0;
|
||||||
const WRITE_ACCESS_MASK: usize = 0x1 << 1;
|
const WRITE_ACCESS_MASK: u64 = 0x1 << 1;
|
||||||
|
let page_fault_addr = trap_info.cr2 as Vaddr;
|
||||||
|
trace!(
|
||||||
|
"page fault error code: 0x{:x}, Page fault address: 0x{:x}",
|
||||||
|
trap_info.err,
|
||||||
|
page_fault_addr
|
||||||
|
);
|
||||||
let not_present = trap_info.err & PAGE_NOT_PRESENT_ERROR_MASK == 0;
|
let not_present = trap_info.err & PAGE_NOT_PRESENT_ERROR_MASK == 0;
|
||||||
let write = trap_info.err & WRITE_ACCESS_MASK != 0;
|
let write = trap_info.err & WRITE_ACCESS_MASK != 0;
|
||||||
if not_present || write {
|
if not_present || write {
|
||||||
// If page is not present or due to write access, we should ask the vmar try to commit this page
|
// If page is not present or due to write access, we should ask the vmar try to commit this page
|
||||||
let current = current!();
|
let current = current!();
|
||||||
let root_vmar = current.root_vmar();
|
let root_vmar = current.root_vmar();
|
||||||
let page_fault_addr = trap_info.cr2 as Vaddr;
|
|
||||||
trace!(
|
|
||||||
"Page fault address: 0x{:x}, write access: {}",
|
|
||||||
page_fault_addr,
|
|
||||||
write
|
|
||||||
);
|
|
||||||
if let Err(e) = root_vmar.handle_page_fault(page_fault_addr, not_present, write) {
|
if let Err(e) = root_vmar.handle_page_fault(page_fault_addr, not_present, write) {
|
||||||
error!(
|
error!(
|
||||||
"page fault handler failed: addr: 0x{:x}, err: {:?}",
|
"page fault handler failed: addr: 0x{:x}, err: {:?}",
|
||||||
|
@ -144,6 +144,12 @@ impl Vmar<Rights> {
|
|||||||
self.check_rights(Rights::DUP)?;
|
self.check_rights(Rights::DUP)?;
|
||||||
Ok(Vmar(self.0.clone(), self.1.clone()))
|
Ok(Vmar(self.0.clone(), self.1.clone()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Given a map size, returns the possible map address without doing actual allocation.
|
||||||
|
pub fn hint_map_addr(&self, map_size: usize) -> Result<Vaddr> {
|
||||||
|
self.check_rights(Rights::READ)?;
|
||||||
|
self.0.hint_map_addr(map_size)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VmIo for Vmar<Rights> {
|
impl VmIo for Vmar<Rights> {
|
||||||
|
@ -265,7 +265,7 @@ impl Vmar_ {
|
|||||||
inner.free_regions.append(&mut free_regions);
|
inner.free_regions.append(&mut free_regions);
|
||||||
|
|
||||||
for (_, vm_mapping) in &inner.vm_mappings {
|
for (_, vm_mapping) in &inner.vm_mappings {
|
||||||
vm_mapping.unmap(vm_mapping.range(), true)?;
|
vm_mapping.unmap(&vm_mapping.range(), true)?;
|
||||||
let free_region = FreeRegion::new(vm_mapping.range());
|
let free_region = FreeRegion::new(vm_mapping.range());
|
||||||
free_regions.insert(free_region.start(), free_region);
|
free_regions.insert(free_region.start(), free_region);
|
||||||
}
|
}
|
||||||
@ -515,6 +515,8 @@ impl Vmar_ {
|
|||||||
for (child_vmo_base, child_vmo) in &inner.vm_mappings {
|
for (child_vmo_base, child_vmo) in &inner.vm_mappings {
|
||||||
let child_vmo_range = *child_vmo_base..*child_vmo_base + child_vmo.map_size();
|
let child_vmo_range = *child_vmo_base..*child_vmo_base + child_vmo.map_size();
|
||||||
if is_intersected(&vmo_range, &child_vmo_range) {
|
if is_intersected(&vmo_range, &child_vmo_range) {
|
||||||
|
debug!("vmo_range = {:x?}", vmo_range);
|
||||||
|
debug!("child_vmo_range = {:x?}", child_vmo_range);
|
||||||
return_errno_with_message!(
|
return_errno_with_message!(
|
||||||
Errno::EACCES,
|
Errno::EACCES,
|
||||||
"vmo range overlapped with another vmo"
|
"vmo range overlapped with another vmo"
|
||||||
@ -593,6 +595,16 @@ impl Vmar_ {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn hint_map_addr(&self, size: usize) -> Result<Vaddr> {
|
||||||
|
let inner = self.inner.lock();
|
||||||
|
for (free_region_base, free_region) in &inner.free_regions {
|
||||||
|
if free_region.size() >= size {
|
||||||
|
return Ok(*free_region_base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return_errno_with_message!(Errno::ENOMEM, "cannot find a suitale free region");
|
||||||
|
}
|
||||||
|
|
||||||
fn trim_existing_mappings(&self, trim_range: Range<usize>) -> Result<()> {
|
fn trim_existing_mappings(&self, trim_range: Range<usize>) -> Result<()> {
|
||||||
let mut inner = self.inner.lock();
|
let mut inner = self.inner.lock();
|
||||||
let mut mappings_to_remove = BTreeSet::new();
|
let mut mappings_to_remove = BTreeSet::new();
|
||||||
|
@ -5,7 +5,7 @@ use jinux_frame::vm::VmIo;
|
|||||||
use jinux_rights_proc::require;
|
use jinux_rights_proc::require;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
rights::{Dup, Rights, TRights},
|
rights::{Dup, Read, Rights, TRights},
|
||||||
vm::{page_fault_handler::PageFaultHandler, vmo::Vmo},
|
vm::{page_fault_handler::PageFaultHandler, vmo::Vmo},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -148,6 +148,12 @@ impl<R: TRights> Vmar<R> {
|
|||||||
Ok(Vmar(self.0.clone(), self.1))
|
Ok(Vmar(self.0.clone(), self.1))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Given a map size, returns the possible map address without doing actual allocation.
|
||||||
|
#[require(R > Read)]
|
||||||
|
pub fn hint_map_addr(&self, map_size: usize) -> Result<Vaddr> {
|
||||||
|
self.0.hint_map_addr(map_size)
|
||||||
|
}
|
||||||
|
|
||||||
/// Strict the access rights.
|
/// Strict the access rights.
|
||||||
#[require(R > R1)]
|
#[require(R > R1)]
|
||||||
pub fn restrict<R1: TRights>(self) -> Vmar<R1> {
|
pub fn restrict<R1: TRights>(self) -> Vmar<R1> {
|
||||||
|
@ -79,8 +79,8 @@ impl VmMapping {
|
|||||||
align,
|
align,
|
||||||
can_overwrite,
|
can_overwrite,
|
||||||
)?;
|
)?;
|
||||||
debug!(
|
trace!(
|
||||||
"build mapping, map_to_addr = 0x{:x}- 0x{:x}",
|
"build mapping, map_range = 0x{:x}- 0x{:x}",
|
||||||
map_to_addr,
|
map_to_addr,
|
||||||
map_to_addr + size
|
map_to_addr + size
|
||||||
);
|
);
|
||||||
@ -188,14 +188,14 @@ impl VmMapping {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Unmap pages in the range
|
/// Unmap pages in the range
|
||||||
pub fn unmap(&self, range: Range<usize>, destroy: bool) -> Result<()> {
|
pub fn unmap(&self, range: &Range<usize>, destroy: bool) -> Result<()> {
|
||||||
let map_to_addr = self.map_to_addr();
|
let map_to_addr = self.map_to_addr();
|
||||||
let vmo_map_range = (range.start - map_to_addr)..(range.end - map_to_addr);
|
let vmo_map_range = (range.start - map_to_addr)..(range.end - map_to_addr);
|
||||||
let page_idx_range = get_page_idx_range(&vmo_map_range);
|
let page_idx_range = get_page_idx_range(&vmo_map_range);
|
||||||
for page_idx in page_idx_range {
|
for page_idx in page_idx_range {
|
||||||
self.unmap_one_page(page_idx)?;
|
self.unmap_one_page(page_idx)?;
|
||||||
}
|
}
|
||||||
if destroy && range == self.range() {
|
if destroy && *range == self.range() {
|
||||||
self.inner.lock().is_destroyed = false;
|
self.inner.lock().is_destroyed = false;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -204,7 +204,7 @@ impl VmMapping {
|
|||||||
pub fn unmap_and_decommit(&self, range: Range<usize>) -> Result<()> {
|
pub fn unmap_and_decommit(&self, range: Range<usize>) -> Result<()> {
|
||||||
let map_to_addr = self.map_to_addr();
|
let map_to_addr = self.map_to_addr();
|
||||||
let vmo_range = (range.start - map_to_addr)..(range.end - map_to_addr);
|
let vmo_range = (range.start - map_to_addr)..(range.end - map_to_addr);
|
||||||
self.unmap(range, false)?;
|
self.unmap(&range, false)?;
|
||||||
self.vmo.decommit(vmo_range)?;
|
self.vmo.decommit(vmo_range)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -267,6 +267,7 @@ impl VmMapping {
|
|||||||
let VmMapping { inner, parent, vmo } = self;
|
let VmMapping { inner, parent, vmo } = self;
|
||||||
let parent_vmo = vmo.dup().unwrap();
|
let parent_vmo = vmo.dup().unwrap();
|
||||||
let vmo_size = parent_vmo.size();
|
let vmo_size = parent_vmo.size();
|
||||||
|
debug!("fork vmo in forkmapping, parent size = 0x{:x}", vmo_size);
|
||||||
let child_vmo = VmoChildOptions::new_cow(parent_vmo, 0..vmo_size).alloc()?;
|
let child_vmo = VmoChildOptions::new_cow(parent_vmo, 0..vmo_size).alloc()?;
|
||||||
let parent_vmar = new_parent.upgrade().unwrap();
|
let parent_vmar = new_parent.upgrade().unwrap();
|
||||||
let vm_space = parent_vmar.vm_space();
|
let vm_space = parent_vmar.vm_space();
|
||||||
@ -335,6 +336,11 @@ impl VmMapping {
|
|||||||
if !is_intersected(&range, &trim_range) {
|
if !is_intersected(&range, &trim_range) {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
if trim_range.start == map_to_addr && trim_range.end == map_to_addr + map_size {
|
||||||
|
// fast path: the whole mapping was trimed
|
||||||
|
self.unmap(trim_range, true)?;
|
||||||
|
mappings_to_remove.insert(map_to_addr);
|
||||||
|
}
|
||||||
let vm_mapping_left = range.start;
|
let vm_mapping_left = range.start;
|
||||||
let vm_mapping_right = range.end;
|
let vm_mapping_right = range.end;
|
||||||
|
|
||||||
|
@ -465,6 +465,7 @@ fn alloc_child_vmo_(
|
|||||||
}
|
}
|
||||||
let parent_vmo_size = parent_vmo_.size();
|
let parent_vmo_size = parent_vmo_.size();
|
||||||
let parent_vmo_inner = parent_vmo_.inner.lock();
|
let parent_vmo_inner = parent_vmo_.inner.lock();
|
||||||
|
|
||||||
match child_type {
|
match child_type {
|
||||||
ChildType::Slice => {
|
ChildType::Slice => {
|
||||||
// A slice child should be inside parent vmo's range
|
// A slice child should be inside parent vmo's range
|
||||||
@ -478,8 +479,8 @@ fn alloc_child_vmo_(
|
|||||||
}
|
}
|
||||||
ChildType::Cow => {
|
ChildType::Cow => {
|
||||||
// A copy on Write child should intersect with parent vmo
|
// A copy on Write child should intersect with parent vmo
|
||||||
debug_assert!(range.start < parent_vmo_inner.size);
|
debug_assert!(range.start <= parent_vmo_inner.size);
|
||||||
if range.start >= parent_vmo_inner.size {
|
if range.start > parent_vmo_inner.size {
|
||||||
return_errno_with_message!(Errno::EINVAL, "COW vmo should overlap with its parent");
|
return_errno_with_message!(Errno::EINVAL, "COW vmo should overlap with its parent");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user