mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-16 08:46:48 +00:00
add safe wrapper to read union fields
This commit is contained in:
parent
41b79cf823
commit
8ebaaa283a
1
src/Cargo.lock
generated
1
src/Cargo.lock
generated
@ -144,6 +144,7 @@ dependencies = [
|
|||||||
"jinux-frame",
|
"jinux-frame",
|
||||||
"jinux-pci",
|
"jinux-pci",
|
||||||
"jinux-rights-proc",
|
"jinux-rights-proc",
|
||||||
|
"jinux-util",
|
||||||
"jinux-virtio",
|
"jinux-virtio",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"pod",
|
"pod",
|
||||||
|
@ -176,9 +176,7 @@ pub(crate) fn init() {
|
|||||||
// set gate type to 1110: 64 bit Interrupt Gate, Present bit to 1, DPL to Ring 0
|
// set gate type to 1110: 64 bit Interrupt Gate, Present bit to 1, DPL to Ring 0
|
||||||
let p_low = (((p >> 16) & 0xFFFF) << 48) | (p & 0xFFFF);
|
let p_low = (((p >> 16) & 0xFFFF) << 48) | (p & 0xFFFF);
|
||||||
let trap_entry_option: usize = 0b1000_1110_0000_0000;
|
let trap_entry_option: usize = 0b1000_1110_0000_0000;
|
||||||
let low = (trap_entry_option << 32)
|
let low = (trap_entry_option << 32) | ((kcs.0 as usize) << 16) | p_low;
|
||||||
| ((kcs.0 as usize) << 16)
|
|
||||||
| p_low;
|
|
||||||
let high = p >> 32;
|
let high = p >> 32;
|
||||||
unsafe {
|
unsafe {
|
||||||
IDT.entries[i] = [low, high];
|
IDT.entries[i] = [low, high];
|
||||||
|
@ -33,3 +33,34 @@ macro_rules! offset_of {
|
|||||||
field_offset
|
field_offset
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the offset of a field within an object as a pointer.
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// #[repr(C)]
|
||||||
|
/// pub struct Foo {
|
||||||
|
/// first: u8,
|
||||||
|
/// second: u32,
|
||||||
|
/// }
|
||||||
|
/// let foo = &Foo {first: 0, second: 0};
|
||||||
|
/// assert!(value_offset!(foo) == (0 as *const Foo));
|
||||||
|
/// assert!(value_offset!(foo.first) == (0 as *const u8));
|
||||||
|
/// assert!(value_offset!(foo.second) == (4 as *const u32));
|
||||||
|
/// ```
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! value_offset {
|
||||||
|
($container:ident) => ({
|
||||||
|
let container_addr = &*$container as *const _;
|
||||||
|
let offset = 0 as *const _;
|
||||||
|
let _: bool = offset == container_addr;
|
||||||
|
offset
|
||||||
|
});
|
||||||
|
($container:ident.$($field:ident).*) => ({
|
||||||
|
let container_addr = &*$container as *const _;
|
||||||
|
// SAFETY: This is safe since we never access the field
|
||||||
|
let field_addr = unsafe {&($container.$($field).*)} as *const _;
|
||||||
|
let field_offset = (field_addr as usize- container_addr as usize) as *const _;
|
||||||
|
let _: bool = field_offset == field_addr;
|
||||||
|
field_offset
|
||||||
|
});
|
||||||
|
}
|
||||||
|
@ -81,10 +81,7 @@ impl VmSpace {
|
|||||||
let page_size = (range.end - range.start) / PAGE_SIZE;
|
let page_size = (range.end - range.start) / PAGE_SIZE;
|
||||||
let mut inner = self.memory_set.lock();
|
let mut inner = self.memory_set.lock();
|
||||||
for i in 0..page_size {
|
for i in 0..page_size {
|
||||||
let res = inner.unmap(start_va);
|
inner.unmap(start_va)?;
|
||||||
if res.is_err() {
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
start_va += PAGE_SIZE;
|
start_va += PAGE_SIZE;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -224,6 +221,6 @@ impl TryFrom<u64> for VmPerm {
|
|||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn try_from(value: u64) -> Result<Self> {
|
fn try_from(value: u64) -> Result<Self> {
|
||||||
VmPerm::from_bits(value as u8).ok_or_else(|| Error::InvalidVmpermBits)
|
VmPerm::from_bits(value as u8).ok_or(Error::InvalidVmpermBits)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,10 @@
|
|||||||
|
|
||||||
use proc_macro2::{Ident, TokenStream};
|
use proc_macro2::{Ident, TokenStream};
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use syn::{parse_macro_input, Attribute, Data, DataStruct, DeriveInput, Fields, Generics};
|
use syn::{
|
||||||
|
parse_macro_input, Attribute, Data, DataEnum, DataStruct, DataUnion, DeriveInput, Fields,
|
||||||
|
Generics,
|
||||||
|
};
|
||||||
|
|
||||||
#[proc_macro_derive(Pod)]
|
#[proc_macro_derive(Pod)]
|
||||||
pub fn derive_pod(input_token: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
pub fn derive_pod(input_token: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
@ -15,8 +18,8 @@ pub fn derive_pod(input_token: proc_macro::TokenStream) -> proc_macro::TokenStre
|
|||||||
expand_derive_pod(input).into()
|
expand_derive_pod(input).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
const ALLOWED_REPRS: [&'static str; 13] = [
|
const ALLOWED_REPRS: [&'static str; 11] = [
|
||||||
"C", "u8", "i8", "u16", "i16", "u32", "i32", "u64", "i64", "usize", "isize", "u128", "i128",
|
"C", "u8", "i8", "u16", "i16", "u32", "i32", "u64", "i64", "usize", "isize",
|
||||||
];
|
];
|
||||||
|
|
||||||
fn expand_derive_pod(input: DeriveInput) -> TokenStream {
|
fn expand_derive_pod(input: DeriveInput) -> TokenStream {
|
||||||
@ -25,7 +28,8 @@ fn expand_derive_pod(input: DeriveInput) -> TokenStream {
|
|||||||
let generics = input.generics;
|
let generics = input.generics;
|
||||||
match input.data {
|
match input.data {
|
||||||
Data::Struct(data_struct) => impl_pod_for_struct(data_struct, generics, ident, attrs),
|
Data::Struct(data_struct) => impl_pod_for_struct(data_struct, generics, ident, attrs),
|
||||||
Data::Enum(..) | Data::Union(..) => impl_pod_for_enum_or_union(attrs, generics, ident),
|
Data::Union(data_union) => impl_pod_for_union(data_union, generics, ident, attrs),
|
||||||
|
Data::Enum(data_enum) => impl_pod_for_enum(data_enum, attrs, generics, ident),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +76,45 @@ fn impl_pod_for_struct(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn impl_pod_for_enum_or_union(
|
fn impl_pod_for_union(
|
||||||
|
data_union: DataUnion,
|
||||||
|
generics: Generics,
|
||||||
|
ident: Ident,
|
||||||
|
attrs: Vec<Attribute>,
|
||||||
|
) -> TokenStream {
|
||||||
|
if !has_valid_repr(attrs) {
|
||||||
|
panic!("{} has invalid repr to implement Pod", ident.to_string());
|
||||||
|
}
|
||||||
|
let fields = data_union.fields.named;
|
||||||
|
// deal with generics
|
||||||
|
let (impl_generics, type_generics, where_clause) = generics.split_for_impl();
|
||||||
|
|
||||||
|
let pod_where_predicates = fields
|
||||||
|
.into_iter()
|
||||||
|
.map(|field| {
|
||||||
|
let field_ty = field.ty;
|
||||||
|
quote! {
|
||||||
|
#field_ty: ::pod::Pod
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
// if where_clause is none, we should add a `where` word manually.
|
||||||
|
if where_clause.is_none() {
|
||||||
|
quote! {
|
||||||
|
#[automatically_derived]
|
||||||
|
unsafe impl #impl_generics ::pod::Pod #type_generics for #ident where #(#pod_where_predicates),* {}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote! {
|
||||||
|
#[automatically_derived]
|
||||||
|
unsafe impl #impl_generics ::pod::Pod #type_generics for #ident #where_clause, #(#pod_where_predicates),* {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn impl_pod_for_enum(
|
||||||
|
data_enum: DataEnum,
|
||||||
attrs: Vec<Attribute>,
|
attrs: Vec<Attribute>,
|
||||||
generics: Generics,
|
generics: Generics,
|
||||||
ident: Ident,
|
ident: Ident,
|
||||||
@ -84,6 +126,13 @@ fn impl_pod_for_enum_or_union(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check variant
|
||||||
|
for variant in data_enum.variants {
|
||||||
|
if None == variant.discriminant {
|
||||||
|
panic!("Enum can only have fields like Variant=1");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// deal with generics
|
// deal with generics
|
||||||
let (impl_generics, type_generics, where_clause) = generics.split_for_impl();
|
let (impl_generics, type_generics, where_clause) = generics.split_for_impl();
|
||||||
quote! {
|
quote! {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
use core::{fmt::Debug, mem::MaybeUninit};
|
use core::mem::MaybeUninit;
|
||||||
|
|
||||||
/// A marker trait for plain old data (POD).
|
/// A marker trait for plain old data (POD).
|
||||||
///
|
///
|
||||||
@ -16,7 +16,7 @@ use core::{fmt::Debug, mem::MaybeUninit};
|
|||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// Marking a non-POD type as POD may cause undefined behaviors.
|
/// Marking a non-POD type as POD may cause undefined behaviors.
|
||||||
pub unsafe trait Pod: Copy + Sized + Debug {
|
pub unsafe trait Pod: Copy + Sized {
|
||||||
/// Creates a new instance of Pod type that is filled with zeroes.
|
/// Creates a new instance of Pod type that is filled with zeroes.
|
||||||
fn new_zeroed() -> Self {
|
fn new_zeroed() -> Self {
|
||||||
// SAFETY. An all-zero value of `T: Pod` is always valid.
|
// SAFETY. An all-zero value of `T: Pod` is always valid.
|
||||||
@ -35,7 +35,8 @@ pub unsafe trait Pod: Copy + Sized + Debug {
|
|||||||
/// Creates a new instance from the given bytes.
|
/// Creates a new instance from the given bytes.
|
||||||
fn from_bytes(bytes: &[u8]) -> Self {
|
fn from_bytes(bytes: &[u8]) -> Self {
|
||||||
let mut new_self = Self::new_uninit();
|
let mut new_self = Self::new_uninit();
|
||||||
new_self.as_bytes_mut().copy_from_slice(bytes);
|
let copy_len = new_self.as_bytes().len();
|
||||||
|
new_self.as_bytes_mut().copy_from_slice(&bytes[..copy_len]);
|
||||||
new_self
|
new_self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ jinux-virtio = {path="../../comps/jinux-virtio"}
|
|||||||
typeflags = {path="../typeflags"}
|
typeflags = {path="../typeflags"}
|
||||||
typeflags-util = {path="../typeflags-util"}
|
typeflags-util = {path="../typeflags-util"}
|
||||||
jinux-rights-proc = {path="../jinux-rights-proc"}
|
jinux-rights-proc = {path="../jinux-rights-proc"}
|
||||||
|
jinux-util = {path="../jinux-util"}
|
||||||
|
|
||||||
# parse elf file
|
# parse elf file
|
||||||
xmas-elf = "0.8.0"
|
xmas-elf = "0.8.0"
|
||||||
|
@ -11,7 +11,10 @@
|
|||||||
#![feature(const_option)]
|
#![feature(const_option)]
|
||||||
#![feature(extend_one)]
|
#![feature(extend_one)]
|
||||||
|
|
||||||
use crate::{prelude::*, user_apps::UserApp};
|
use crate::{
|
||||||
|
prelude::*,
|
||||||
|
user_apps::{get_busybox_app, UserApp},
|
||||||
|
};
|
||||||
use jinux_frame::{info, println};
|
use jinux_frame::{info, println};
|
||||||
use process::Process;
|
use process::Process;
|
||||||
|
|
||||||
@ -61,7 +64,12 @@ pub fn init_process() {
|
|||||||
process.pid()
|
process.pid()
|
||||||
);
|
);
|
||||||
|
|
||||||
for app in get_all_apps().into_iter().last() {
|
// FIXME: should be running this apps before we running shell?
|
||||||
|
println!("");
|
||||||
|
println!("[kernel] Running test programs");
|
||||||
|
println!("");
|
||||||
|
// Run test apps
|
||||||
|
for app in get_all_apps().into_iter() {
|
||||||
let UserApp {
|
let UserApp {
|
||||||
app_name,
|
app_name,
|
||||||
app_content,
|
app_content,
|
||||||
@ -69,11 +77,20 @@ pub fn init_process() {
|
|||||||
envp,
|
envp,
|
||||||
} = app;
|
} = app;
|
||||||
info!("[jinux-std/lib.rs] spwan {:?} process", app_name);
|
info!("[jinux-std/lib.rs] spwan {:?} process", app_name);
|
||||||
print!("\n");
|
|
||||||
print!("BusyBox v1.35.0 built-in shell (ash)\n\n");
|
|
||||||
Process::spawn_user_process(app_name.clone(), app_content, argv, Vec::new());
|
Process::spawn_user_process(app_name.clone(), app_content, argv, Vec::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Run busybox ash
|
||||||
|
let UserApp {
|
||||||
|
app_name,
|
||||||
|
app_content,
|
||||||
|
argv,
|
||||||
|
envp,
|
||||||
|
} = get_busybox_app();
|
||||||
|
println!("");
|
||||||
|
println!("BusyBox v1.35.0 built-in shell (ash)\n");
|
||||||
|
Process::spawn_user_process(app_name.clone(), app_content, argv, Vec::new());
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
// We don't have preemptive scheduler now.
|
// We don't have preemptive scheduler now.
|
||||||
// The long running init process should yield its own execution to allow other tasks to go on.
|
// The long running init process should yield its own execution to allow other tasks to go on.
|
||||||
@ -84,7 +101,6 @@ pub fn init_process() {
|
|||||||
|
|
||||||
/// first process never return
|
/// first process never return
|
||||||
pub fn run_first_process() -> ! {
|
pub fn run_first_process() -> ! {
|
||||||
// let elf_file_content = read_hello_world_content();
|
|
||||||
Process::spawn_kernel_process(init_process);
|
Process::spawn_kernel_process(init_process);
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,16 @@
|
|||||||
#![allow(non_camel_case_types)]
|
#![allow(non_camel_case_types)]
|
||||||
use core::mem;
|
use core::mem;
|
||||||
|
|
||||||
use jinux_frame::cpu::GpRegs;
|
use jinux_frame::{cpu::GpRegs, offset_of};
|
||||||
|
use jinux_util::{read_union_fields, union_read_ptr::UnionReadPtr};
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::{prelude::*, process::Pid};
|
||||||
|
|
||||||
use super::sig_num::SigNum;
|
use super::{sig_num::SigNum, signals::user::Uid};
|
||||||
|
|
||||||
pub type sigset_t = u64;
|
pub type sigset_t = u64;
|
||||||
|
// FIXME: this type should be put at suitable place
|
||||||
|
pub type clock_t = i64;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Pod)]
|
#[derive(Debug, Clone, Copy, Pod)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@ -18,7 +21,7 @@ pub struct sigaction_t {
|
|||||||
pub mask: sigset_t,
|
pub mask: sigset_t,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Pod)]
|
#[derive(Clone, Copy, Pod)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct siginfo_t {
|
pub struct siginfo_t {
|
||||||
pub si_signo: i32,
|
pub si_signo: i32,
|
||||||
@ -27,20 +30,116 @@ pub struct siginfo_t {
|
|||||||
_padding: i32,
|
_padding: i32,
|
||||||
/// siginfo_fields should be a union type ( See occlum definition ). But union type have unsafe interfaces.
|
/// siginfo_fields should be a union type ( See occlum definition ). But union type have unsafe interfaces.
|
||||||
/// Here we use a simple byte array.
|
/// Here we use a simple byte array.
|
||||||
pub siginfo_fields: [u8; 128 - mem::size_of::<i32>() * 4],
|
siginfo_fields: siginfo_fields_t,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl siginfo_t {
|
impl siginfo_t {
|
||||||
pub fn new(num: SigNum, code: i32) -> Self {
|
pub fn new(num: SigNum, code: i32) -> Self {
|
||||||
let zero_fields = [0u8; 128 - mem::size_of::<i32>() * 4];
|
|
||||||
siginfo_t {
|
siginfo_t {
|
||||||
si_signo: num.as_u8() as i32,
|
si_signo: num.as_u8() as i32,
|
||||||
si_errno: 0,
|
si_errno: 0,
|
||||||
si_code: code,
|
si_code: code,
|
||||||
_padding: 0,
|
_padding: 0,
|
||||||
siginfo_fields: zero_fields,
|
siginfo_fields: siginfo_fields_t::zero_fields(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_si_addr(&mut self, si_addr: Vaddr) {
|
||||||
|
self.siginfo_fields.sigfault.addr = si_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn si_addr(&self) -> Vaddr {
|
||||||
|
// let siginfo = *self;
|
||||||
|
read_union_fields!(self.siginfo_fields.sigfault.addr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Pod)]
|
||||||
|
#[repr(C)]
|
||||||
|
union siginfo_fields_t {
|
||||||
|
bytes: [u8; 128 - mem::size_of::<i32>() * 4],
|
||||||
|
common: siginfo_common_t,
|
||||||
|
sigfault: siginfo_sigfault_t,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl siginfo_fields_t {
|
||||||
|
fn zero_fields() -> Self {
|
||||||
|
Self {
|
||||||
|
bytes: [0; 128 - mem::size_of::<i32>() * 4],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Pod)]
|
||||||
|
#[repr(C)]
|
||||||
|
union siginfo_common_t {
|
||||||
|
first: siginfo_common_first_t,
|
||||||
|
second: siginfo_common_second_t,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Pod)]
|
||||||
|
#[repr(C)]
|
||||||
|
union siginfo_common_first_t {
|
||||||
|
piduid: siginfo_piduid_t,
|
||||||
|
timer: siginfo_timer_t,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Pod)]
|
||||||
|
#[repr(C)]
|
||||||
|
struct siginfo_piduid_t {
|
||||||
|
pid: Pid,
|
||||||
|
uid: Uid,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Pod)]
|
||||||
|
#[repr(C)]
|
||||||
|
struct siginfo_timer_t {
|
||||||
|
timerid: i32,
|
||||||
|
overrun: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Pod)]
|
||||||
|
#[repr(C)]
|
||||||
|
union siginfo_common_second_t {
|
||||||
|
value: sigval_t,
|
||||||
|
sigchild: siginfo_sigchild_t,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Pod)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub union sigval_t {
|
||||||
|
sigval_int: i32,
|
||||||
|
sigval_ptr: Vaddr, //*mut c_void
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Pod)]
|
||||||
|
#[repr(C)]
|
||||||
|
union siginfo_sigchild_t {
|
||||||
|
status: i32,
|
||||||
|
utime: clock_t,
|
||||||
|
stime: clock_t,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Pod)]
|
||||||
|
#[repr(C)]
|
||||||
|
struct siginfo_sigfault_t {
|
||||||
|
addr: Vaddr, //*const c_void
|
||||||
|
addr_lsb: i16,
|
||||||
|
first: siginfo_sigfault_first_t,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Pod)]
|
||||||
|
#[repr(C)]
|
||||||
|
union siginfo_sigfault_first_t {
|
||||||
|
addr_bnd: siginfo_addr_bnd_t,
|
||||||
|
pkey: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Pod)]
|
||||||
|
#[repr(C)]
|
||||||
|
union siginfo_addr_bnd_t {
|
||||||
|
lower: Vaddr, // *const c_void
|
||||||
|
upper: Vaddr, // *const c_void,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Pod)]
|
#[derive(Clone, Copy, Debug, Pod)]
|
||||||
|
@ -56,6 +56,10 @@ pub fn get_all_apps() -> Vec<UserApp> {
|
|||||||
let signal_test = UserApp::new("/signal_test", read_signal_test_content());
|
let signal_test = UserApp::new("/signal_test", read_signal_test_content());
|
||||||
res.push(signal_test);
|
res.push(signal_test);
|
||||||
|
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_busybox_app() -> UserApp {
|
||||||
// busybox
|
// busybox
|
||||||
let mut busybox = UserApp::new("/busybox", read_busybox_content());
|
let mut busybox = UserApp::new("/busybox", read_busybox_content());
|
||||||
// -l option means the busybox is running as logging shell
|
// -l option means the busybox is running as logging shell
|
||||||
@ -74,9 +78,7 @@ pub fn get_all_apps() -> Vec<UserApp> {
|
|||||||
let envp = to_vec_cstring(&envp).unwrap();
|
let envp = to_vec_cstring(&envp).unwrap();
|
||||||
busybox.set_argv(argv);
|
busybox.set_argv(argv);
|
||||||
busybox.set_envp(envp);
|
busybox.set_envp(envp);
|
||||||
res.push(busybox);
|
busybox
|
||||||
|
|
||||||
res
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_hello_world_content() -> &'static [u8] {
|
fn read_hello_world_content() -> &'static [u8] {
|
||||||
|
@ -18,7 +18,7 @@ use super::{Pager, Vmo, VmoFlags};
|
|||||||
///
|
///
|
||||||
/// Creating a VMO as a _dynamic_ capability with full access rights:
|
/// Creating a VMO as a _dynamic_ capability with full access rights:
|
||||||
/// ```
|
/// ```
|
||||||
/// use kxo_std::vm::{PAGE_SIZE, VmoOptions};
|
/// use jinux_std::vm::{PAGE_SIZE, VmoOptions};
|
||||||
///
|
///
|
||||||
/// let vmo = VmoOptions::new(PAGE_SIZE)
|
/// let vmo = VmoOptions::new(PAGE_SIZE)
|
||||||
/// .alloc()
|
/// .alloc()
|
||||||
@ -28,7 +28,7 @@ use super::{Pager, Vmo, VmoFlags};
|
|||||||
/// Creating a VMO as a _static_ capability with all access rights:
|
/// Creating a VMO as a _static_ capability with all access rights:
|
||||||
/// ```
|
/// ```
|
||||||
/// use jinux_std::prelude::*;
|
/// use jinux_std::prelude::*;
|
||||||
/// use kxo_std::vm::{PAGE_SIZE, VmoOptions};
|
/// use jinux_std::vm::{PAGE_SIZE, VmoOptions};
|
||||||
///
|
///
|
||||||
/// let vmo = VmoOptions::<Full>::new(PAGE_SIZE)
|
/// let vmo = VmoOptions::<Full>::new(PAGE_SIZE)
|
||||||
/// .alloc()
|
/// .alloc()
|
||||||
@ -118,7 +118,7 @@ impl<R: TRights> VmoOptions<R> {
|
|||||||
/// A child VMO created from a parent VMO of _dynamic_ capability is also a
|
/// A child VMO created from a parent VMO of _dynamic_ capability is also a
|
||||||
/// _dynamic_ capability.
|
/// _dynamic_ capability.
|
||||||
/// ```
|
/// ```
|
||||||
/// use kxo_std::vm::{PAGE_SIZE, VmoOptions};
|
/// use jinux_std::vm::{PAGE_SIZE, VmoOptions};
|
||||||
///
|
///
|
||||||
/// let parent_vmo = VmoOptions::new(PAGE_SIZE)
|
/// let parent_vmo = VmoOptions::new(PAGE_SIZE)
|
||||||
/// .alloc()
|
/// .alloc()
|
||||||
@ -150,7 +150,7 @@ impl<R: TRights> VmoOptions<R> {
|
|||||||
/// right regardless of whether the parent is writable or not.
|
/// right regardless of whether the parent is writable or not.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use kxo_std::vm::{PAGE_SIZE, VmoOptions, VmoChildOptions};
|
/// use jinux_std::vm::{PAGE_SIZE, VmoOptions, VmoChildOptions};
|
||||||
///
|
///
|
||||||
/// let parent_vmo = VmoOptions::new(PAGE_SIZE)
|
/// let parent_vmo = VmoOptions::new(PAGE_SIZE)
|
||||||
/// .alloc()
|
/// .alloc()
|
||||||
@ -181,7 +181,7 @@ impl<R: TRights> VmoOptions<R> {
|
|||||||
/// Note that a slice VMO child and its parent cannot not be resizable.
|
/// Note that a slice VMO child and its parent cannot not be resizable.
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use kxo_std::vm::{PAGE_SIZE, VmoOptions};
|
/// use _std::vm::{PAGE_SIZE, VmoOptions};
|
||||||
///
|
///
|
||||||
/// let parent_vmo = VmoOptions::new(PAGE_SIZE)
|
/// let parent_vmo = VmoOptions::new(PAGE_SIZE)
|
||||||
/// .alloc()
|
/// .alloc()
|
||||||
|
@ -3,3 +3,4 @@
|
|||||||
#![forbid(unsafe_code)]
|
#![forbid(unsafe_code)]
|
||||||
|
|
||||||
pub mod frame_ptr;
|
pub mod frame_ptr;
|
||||||
|
pub mod union_read_ptr;
|
||||||
|
42
src/services/libs/jinux-util/src/union_read_ptr.rs
Normal file
42
src/services/libs/jinux-util/src/union_read_ptr.rs
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
|
use pod::Pod;
|
||||||
|
|
||||||
|
/// This ptr is designed to read union field safely.
|
||||||
|
/// Write to union field is safe operation. While reading union field is UB.
|
||||||
|
/// However, if this field is Pod, we can safely read that field.
|
||||||
|
pub struct UnionReadPtr<'a, T: Pod> {
|
||||||
|
bytes: &'a [u8],
|
||||||
|
marker: PhantomData<&'a mut T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T: Pod> UnionReadPtr<'a, T> {
|
||||||
|
pub fn new(object: &'a T) -> Self {
|
||||||
|
let bytes = object.as_bytes();
|
||||||
|
Self {
|
||||||
|
bytes,
|
||||||
|
marker: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_at<F: Pod>(&self, offset: *const F) -> F {
|
||||||
|
let offset = offset as usize;
|
||||||
|
F::from_bytes(&self.bytes[offset..])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// FIXME: This macro requires the first argument to be a `reference` of a Pod type.
|
||||||
|
/// This is because the value_offset macro requires
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! read_union_fields {
|
||||||
|
($container:ident) => ({
|
||||||
|
let offset = value_offset!($container);
|
||||||
|
let union_read_ptr = UnionReadPtr::new(&*$container);
|
||||||
|
union_read_ptr.read_at(offset)
|
||||||
|
});
|
||||||
|
($container:ident.$($field:ident).*) => ({
|
||||||
|
let field_offset = jinux_frame::value_offset!($container.$($field).*);
|
||||||
|
let union_read_ptr = UnionReadPtr::new(&*$container);
|
||||||
|
union_read_ptr.read_at(field_offset)
|
||||||
|
});
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user