forked from rcore-os/zCore
add crate 'linux-loader' and 'linux-syscall'
This commit is contained in:
parent
54decd2113
commit
26d124dee4
|
@ -0,0 +1 @@
|
|||
libc.so filter=lfs diff=lfs merge=lfs -text
|
|
@ -3,6 +3,8 @@ members = [
|
|||
"zircon-object",
|
||||
"zircon-syscall",
|
||||
"zircon-userboot",
|
||||
"linux-syscall",
|
||||
"linux-loader",
|
||||
"zircon-hal-unix",
|
||||
"zircon-hal-bare"
|
||||
]
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
[package]
|
||||
name = "linux-loader"
|
||||
version = "0.1.0"
|
||||
authors = ["Runji Wang <wangrunji0408@163.com>"]
|
||||
edition = "2018"
|
||||
description = "Linux programs loader and runner."
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
log = "0.4"
|
||||
env_logger = "0.7"
|
||||
xmas-elf = "0.7"
|
||||
elfloader = "0.9"
|
||||
structopt = { version = "0.3", default-features = false }
|
||||
linux-syscall = { path = "../linux-syscall" }
|
||||
zircon-object = { path = "../zircon-object" }
|
||||
zircon-hal-unix = { path = "../zircon-hal-unix" }
|
|
@ -0,0 +1,80 @@
|
|||
#![allow(dead_code)]
|
||||
|
||||
use alloc::collections::btree_map::BTreeMap;
|
||||
use alloc::string::String;
|
||||
use alloc::vec::Vec;
|
||||
use core::ptr::null;
|
||||
|
||||
pub struct ProcInitInfo {
|
||||
pub args: Vec<String>,
|
||||
pub envs: Vec<String>,
|
||||
pub auxv: BTreeMap<u8, usize>,
|
||||
}
|
||||
|
||||
impl ProcInitInfo {
|
||||
pub unsafe fn push_at(&self, stack_top: usize) -> usize {
|
||||
let mut writer = StackWriter { sp: stack_top };
|
||||
// from stack_top:
|
||||
// program name
|
||||
writer.push_str(&self.args[0]);
|
||||
// environment strings
|
||||
let envs: Vec<_> = self
|
||||
.envs
|
||||
.iter()
|
||||
.map(|arg| {
|
||||
writer.push_str(arg.as_str());
|
||||
writer.sp
|
||||
})
|
||||
.collect();
|
||||
// argv strings
|
||||
let argv: Vec<_> = self
|
||||
.args
|
||||
.iter()
|
||||
.map(|arg| {
|
||||
writer.push_str(arg.as_str());
|
||||
writer.sp
|
||||
})
|
||||
.collect();
|
||||
// auxiliary vector entries
|
||||
writer.push_slice(&[null::<u8>(), null::<u8>()]);
|
||||
for (&type_, &value) in self.auxv.iter() {
|
||||
writer.push_slice(&[type_ as usize, value]);
|
||||
}
|
||||
// envionment pointers
|
||||
writer.push_slice(&[null::<u8>()]);
|
||||
writer.push_slice(envs.as_slice());
|
||||
// argv pointers
|
||||
writer.push_slice(&[null::<u8>()]);
|
||||
writer.push_slice(argv.as_slice());
|
||||
// argc
|
||||
writer.push_slice(&[argv.len()]);
|
||||
writer.sp
|
||||
}
|
||||
}
|
||||
|
||||
struct StackWriter {
|
||||
sp: usize,
|
||||
}
|
||||
|
||||
impl StackWriter {
|
||||
fn push_slice<T: Copy>(&mut self, vs: &[T]) {
|
||||
use core::{
|
||||
mem::{align_of, size_of},
|
||||
slice,
|
||||
};
|
||||
self.sp -= vs.len() * size_of::<T>();
|
||||
self.sp -= self.sp % align_of::<T>();
|
||||
unsafe { slice::from_raw_parts_mut(self.sp as *mut T, vs.len()) }.copy_from_slice(vs);
|
||||
}
|
||||
fn push_str(&mut self, s: &str) {
|
||||
self.push_slice(&[b'\0']);
|
||||
self.push_slice(s.as_bytes());
|
||||
}
|
||||
}
|
||||
|
||||
pub const AT_PHDR: u8 = 3;
|
||||
pub const AT_PHENT: u8 = 4;
|
||||
pub const AT_PHNUM: u8 = 5;
|
||||
pub const AT_PAGESZ: u8 = 6;
|
||||
pub const AT_BASE: u8 = 7;
|
||||
pub const AT_ENTRY: u8 = 9;
|
|
@ -0,0 +1,274 @@
|
|||
#![no_std]
|
||||
#![feature(asm)]
|
||||
#![feature(global_asm)]
|
||||
#![deny(warnings, unused_must_use)]
|
||||
|
||||
extern crate alloc;
|
||||
extern crate log;
|
||||
|
||||
use {
|
||||
alloc::{collections::BTreeMap, string::String, sync::Arc, vec::Vec},
|
||||
linux_syscall::Syscall,
|
||||
xmas_elf::{
|
||||
program::{Flags, ProgramHeader, SegmentData, Type},
|
||||
sections::SectionData,
|
||||
symbol_table::{DynEntry64, Entry},
|
||||
ElfFile,
|
||||
},
|
||||
zircon_object::{task::*, vm::*, ZxError, ZxResult},
|
||||
};
|
||||
|
||||
mod abi;
|
||||
|
||||
pub fn run(
|
||||
_ldso_data: &[u8],
|
||||
libc_data: &[u8],
|
||||
mut args: Vec<String>,
|
||||
envs: Vec<String>,
|
||||
) -> Arc<Process> {
|
||||
let job = Job::root();
|
||||
let proc = Process::create(&job, "proc", 0).unwrap();
|
||||
let thread = Thread::create(&proc, "thread", 0).unwrap();
|
||||
let vmar = proc.vmar();
|
||||
|
||||
const VBASE: usize = 0x4_00000000;
|
||||
|
||||
// libc.so
|
||||
let entry = {
|
||||
let elf = ElfFile::new(libc_data).unwrap();
|
||||
let size = elf.load_segment_size();
|
||||
let syscall_entry_offset = elf
|
||||
.get_symbol_address("rcore_syscall_entry")
|
||||
.expect("failed to locate syscall entry") as usize;
|
||||
let vmar = vmar.create_child(VBASE, size).unwrap();
|
||||
let vmo = vmar.load_from_elf(&elf).unwrap();
|
||||
// fill syscall entry
|
||||
extern "C" {
|
||||
fn syscall_entry();
|
||||
}
|
||||
vmo.write(
|
||||
syscall_entry_offset,
|
||||
&(syscall_entry as usize).to_ne_bytes(),
|
||||
);
|
||||
elf.relocate(VBASE).unwrap();
|
||||
VBASE + elf.header.pt2.entry_point() as usize
|
||||
};
|
||||
|
||||
// ld.so
|
||||
// let entry = {
|
||||
// let elf = ElfFile::new(ldso_data).unwrap();
|
||||
// let size = elf.load_segment_size();
|
||||
// let vmar = vmar.create_child(VBASE + 0x400000, size).unwrap();
|
||||
// let first_vmo = vmar.load_from_elf(&elf).unwrap();
|
||||
// elf.relocate(VBASE + 0x400000).unwrap();
|
||||
// VBASE + 0x400000 + elf.header.pt2.entry_point() as usize
|
||||
// };
|
||||
|
||||
const STACK_SIZE: usize = 0x8000;
|
||||
let stack = Vec::<u8>::with_capacity(STACK_SIZE);
|
||||
let mut sp = (stack.as_ptr() as usize + STACK_SIZE) & !0xf;
|
||||
|
||||
args.insert(0, String::from("libc.so"));
|
||||
let info = abi::ProcInitInfo {
|
||||
args,
|
||||
envs,
|
||||
auxv: {
|
||||
let mut map = BTreeMap::new();
|
||||
map.insert(abi::AT_BASE, VBASE);
|
||||
map.insert(abi::AT_PAGESZ, PAGE_SIZE);
|
||||
map
|
||||
},
|
||||
};
|
||||
sp = unsafe { info.push_at(sp) };
|
||||
|
||||
thread
|
||||
.start(entry, sp, 0, 0)
|
||||
.expect("failed to start main thread");
|
||||
proc
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
global_asm!(
|
||||
r#"
|
||||
.intel_syntax noprefix
|
||||
syscall_entry:
|
||||
push rbp
|
||||
push rax
|
||||
call handle_syscall
|
||||
add rsp, 16
|
||||
ret
|
||||
"#
|
||||
);
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
global_asm!(
|
||||
r#"
|
||||
.intel_syntax noprefix
|
||||
_syscall_entry:
|
||||
push rbp
|
||||
push rax
|
||||
call _handle_syscall
|
||||
add rsp, 16
|
||||
ret
|
||||
"#
|
||||
);
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn handle_syscall(
|
||||
a0: usize,
|
||||
a1: usize,
|
||||
a2: usize,
|
||||
a3: usize,
|
||||
a4: usize,
|
||||
a5: usize,
|
||||
num: u32, // pushed %eax
|
||||
) -> isize {
|
||||
let syscall = Syscall {
|
||||
thread: Thread::current(),
|
||||
};
|
||||
syscall.syscall(num, [a0, a1, a2, a3, a4, a5])
|
||||
}
|
||||
|
||||
pub trait ElfExt {
|
||||
fn load_segment_size(&self) -> usize;
|
||||
fn get_symbol_address(&self, symbol: &str) -> Option<u64>;
|
||||
fn dynsym(&self) -> Result<&[DynEntry64], &'static str>;
|
||||
fn relocate(&self, base: usize) -> Result<(), &'static str>;
|
||||
}
|
||||
|
||||
impl ElfExt for ElfFile<'_> {
|
||||
/// Get total size of all LOAD segments.
|
||||
fn load_segment_size(&self) -> usize {
|
||||
self.program_iter()
|
||||
.filter(|ph| ph.get_type().unwrap() == Type::Load)
|
||||
.map(|ph| pages((ph.virtual_addr() + ph.mem_size()) as usize))
|
||||
.max()
|
||||
.unwrap()
|
||||
* PAGE_SIZE
|
||||
}
|
||||
|
||||
/// Get address of the given `symbol`.
|
||||
fn get_symbol_address(&self, symbol: &str) -> Option<u64> {
|
||||
for section in self.section_iter() {
|
||||
if let SectionData::SymbolTable64(entries) = section.get_data(self).unwrap() {
|
||||
for e in entries {
|
||||
if e.get_name(self).unwrap() == symbol {
|
||||
return Some(e.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn dynsym(&self) -> Result<&[DynEntry64], &'static str> {
|
||||
match self
|
||||
.find_section_by_name(".dynsym")
|
||||
.ok_or(".dynsym not found")?
|
||||
.get_data(self)
|
||||
.map_err(|_| "corrupted .dynsym")?
|
||||
{
|
||||
SectionData::DynSymbolTable64(dsym) => Ok(dsym),
|
||||
_ => Err("bad .dynsym"),
|
||||
}
|
||||
}
|
||||
|
||||
fn relocate(&self, base: usize) -> Result<(), &'static str> {
|
||||
let data = self
|
||||
.find_section_by_name(".rela.dyn")
|
||||
.ok_or(".rela.dyn not found")?
|
||||
.get_data(self)
|
||||
.map_err(|_| "corrupted .rela.dyn")?;
|
||||
let entries = match data {
|
||||
SectionData::Rela64(entries) => entries,
|
||||
_ => return Err("bad .rela.dyn"),
|
||||
};
|
||||
let dynsym = self.dynsym()?;
|
||||
for entry in entries {
|
||||
const REL_GOT: u32 = 6;
|
||||
const REL_PLT: u32 = 7;
|
||||
const REL_RELATIVE: u32 = 8;
|
||||
match entry.get_type() {
|
||||
REL_GOT | REL_PLT => {
|
||||
let dynsym = &dynsym[entry.get_symbol_table_index() as usize];
|
||||
let symval = if dynsym.shndx() == 0 {
|
||||
let name = dynsym.get_name(self)?;
|
||||
panic!("need to find symbol: {:?}", name);
|
||||
} else {
|
||||
base + dynsym.value() as usize
|
||||
};
|
||||
let value = symval + entry.get_addend() as usize;
|
||||
unsafe {
|
||||
let ptr = (base + entry.get_offset() as usize) as *mut usize;
|
||||
ptr.write(value);
|
||||
}
|
||||
}
|
||||
REL_RELATIVE => {
|
||||
let value = base + entry.get_addend() as usize;
|
||||
unsafe {
|
||||
let ptr = (base + entry.get_offset() as usize) as *mut usize;
|
||||
ptr.write(value);
|
||||
}
|
||||
}
|
||||
t => unimplemented!("unknown type: {}", t),
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait VmarExt {
|
||||
fn load_from_elf(&self, elf: &ElfFile) -> ZxResult<Arc<VMObjectPaged>>;
|
||||
}
|
||||
|
||||
impl VmarExt for VmAddressRegion {
|
||||
/// Create `VMObject` from all LOAD segments of `elf` and map them to this VMAR.
|
||||
/// Return the first `VMObject`.
|
||||
fn load_from_elf(&self, elf: &ElfFile) -> ZxResult<Arc<VMObjectPaged>> {
|
||||
let mut first_vmo = None;
|
||||
for ph in elf.program_iter() {
|
||||
if ph.get_type().unwrap() != Type::Load {
|
||||
continue;
|
||||
}
|
||||
let vmo = make_vmo(&elf, ph)?;
|
||||
let offset = ph.virtual_addr() as usize / PAGE_SIZE * PAGE_SIZE;
|
||||
let flags = ph.flags().to_mmu_flags();
|
||||
self.map(offset, vmo.clone(), 0, vmo.len(), flags)?;
|
||||
first_vmo.get_or_insert(vmo);
|
||||
}
|
||||
Ok(first_vmo.unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
trait FlagsExt {
|
||||
fn to_mmu_flags(&self) -> MMUFlags;
|
||||
}
|
||||
|
||||
impl FlagsExt for Flags {
|
||||
fn to_mmu_flags(&self) -> MMUFlags {
|
||||
let mut flags = MMUFlags::empty();
|
||||
if self.is_read() {
|
||||
flags.insert(MMUFlags::READ);
|
||||
}
|
||||
if self.is_write() {
|
||||
flags.insert(MMUFlags::WRITE);
|
||||
}
|
||||
if self.is_execute() {
|
||||
flags.insert(MMUFlags::EXECUTE);
|
||||
}
|
||||
flags
|
||||
}
|
||||
}
|
||||
|
||||
fn make_vmo(elf: &ElfFile, ph: ProgramHeader) -> ZxResult<Arc<VMObjectPaged>> {
|
||||
assert_eq!(ph.get_type().unwrap(), Type::Load);
|
||||
let page_offset = ph.virtual_addr() as usize % PAGE_SIZE;
|
||||
let pages = pages(ph.mem_size() as usize + page_offset);
|
||||
let vmo = VMObjectPaged::new(pages);
|
||||
let data = match ph.get_data(&elf).unwrap() {
|
||||
SegmentData::Undefined(data) => data,
|
||||
_ => return Err(ZxError::INVALID_ARGS),
|
||||
};
|
||||
vmo.write(page_offset, data);
|
||||
Ok(vmo)
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
#![deny(warnings, unused_must_use)]
|
||||
|
||||
extern crate log;
|
||||
|
||||
use {linux_loader::*, std::path::PathBuf, structopt::StructOpt, zircon_object::object::*};
|
||||
|
||||
#[derive(Debug, StructOpt)]
|
||||
#[structopt()]
|
||||
struct Opt {
|
||||
#[structopt(parse(from_os_str))]
|
||||
ldso_path: PathBuf,
|
||||
|
||||
#[structopt(parse(from_os_str))]
|
||||
libc_path: PathBuf,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
zircon_hal_unix::init();
|
||||
env_logger::init();
|
||||
|
||||
let opt = Opt::from_args();
|
||||
let ldso_data = std::fs::read(opt.ldso_path).expect("failed to read file");
|
||||
let libc_data = std::fs::read(opt.libc_path).expect("failed to read file");
|
||||
|
||||
let args = vec![]; // TODO
|
||||
let envs = vec![]; // TODO
|
||||
let proc = run(&ldso_data, &libc_data, args, envs);
|
||||
proc.wait_signal(Signal::PROCESS_TERMINATED);
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
[package]
|
||||
name = "linux-syscall"
|
||||
version = "0.1.0"
|
||||
authors = ["Runji Wang <wangrunji0408@163.com>"]
|
||||
edition = "2018"
|
||||
description = "Linux syscalls implementation"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
log = "0.4"
|
||||
bitflags = "1.2"
|
||||
zircon-object = { path = "../zircon-object" }
|
|
@ -0,0 +1,340 @@
|
|||
//! x86_64 syscall ids
|
||||
//! Reference: https://git.musl-libc.org/cgit/musl/tree/arch/x86_64/bits/syscall.h.in
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
pub const SYS_READ: u32 = 0;
|
||||
pub const SYS_WRITE: u32 = 1;
|
||||
pub const SYS_OPEN: u32 = 2;
|
||||
pub const SYS_CLOSE: u32 = 3;
|
||||
pub const SYS_STAT: u32 = 4;
|
||||
pub const SYS_FSTAT: u32 = 5;
|
||||
pub const SYS_LSTAT: u32 = 6;
|
||||
pub const SYS_POLL: u32 = 7;
|
||||
pub const SYS_LSEEK: u32 = 8;
|
||||
pub const SYS_MMAP: u32 = 9;
|
||||
pub const SYS_MPROTECT: u32 = 10;
|
||||
pub const SYS_MUNMAP: u32 = 11;
|
||||
pub const SYS_BRK: u32 = 12;
|
||||
pub const SYS_RT_SIGACTION: u32 = 13;
|
||||
pub const SYS_RT_SIGPROCMASK: u32 = 14;
|
||||
pub const SYS_RT_SIGRETURN: u32 = 15;
|
||||
pub const SYS_IOCTL: u32 = 16;
|
||||
pub const SYS_PREAD64: u32 = 17;
|
||||
pub const SYS_PWRITE64: u32 = 18;
|
||||
pub const SYS_READV: u32 = 19;
|
||||
pub const SYS_WRITEV: u32 = 20;
|
||||
pub const SYS_ACCESS: u32 = 21;
|
||||
pub const SYS_PIPE: u32 = 22;
|
||||
pub const SYS_SELECT: u32 = 23;
|
||||
pub const SYS_SCHED_YIELD: u32 = 24;
|
||||
pub const SYS_MREMAP: u32 = 25;
|
||||
pub const SYS_MSYNC: u32 = 26;
|
||||
pub const SYS_MINCORE: u32 = 27;
|
||||
pub const SYS_MADVISE: u32 = 28;
|
||||
pub const SYS_SHMGET: u32 = 29;
|
||||
pub const SYS_SHMAT: u32 = 30;
|
||||
pub const SYS_SHMCTL: u32 = 31;
|
||||
pub const SYS_DUP: u32 = 32;
|
||||
pub const SYS_DUP2: u32 = 33;
|
||||
pub const SYS_PAUSE: u32 = 34;
|
||||
pub const SYS_NANOSLEEP: u32 = 35;
|
||||
pub const SYS_GETITIMER: u32 = 36;
|
||||
pub const SYS_ALARM: u32 = 37;
|
||||
pub const SYS_SETITIMER: u32 = 38;
|
||||
pub const SYS_GETPID: u32 = 39;
|
||||
pub const SYS_SENDFILE: u32 = 40;
|
||||
pub const SYS_SOCKET: u32 = 41;
|
||||
pub const SYS_CONNECT: u32 = 42;
|
||||
pub const SYS_ACCEPT: u32 = 43;
|
||||
pub const SYS_SENDTO: u32 = 44;
|
||||
pub const SYS_RECVFROM: u32 = 45;
|
||||
pub const SYS_SENDMSG: u32 = 46;
|
||||
pub const SYS_RECVMSG: u32 = 47;
|
||||
pub const SYS_SHUTDOWN: u32 = 48;
|
||||
pub const SYS_BIND: u32 = 49;
|
||||
pub const SYS_LISTEN: u32 = 50;
|
||||
pub const SYS_GETSOCKNAME: u32 = 51;
|
||||
pub const SYS_GETPEERNAME: u32 = 52;
|
||||
pub const SYS_SOCKETPAIR: u32 = 53;
|
||||
pub const SYS_SETSOCKOPT: u32 = 54;
|
||||
pub const SYS_GETSOCKOPT: u32 = 55;
|
||||
pub const SYS_CLONE: u32 = 56;
|
||||
pub const SYS_FORK: u32 = 57;
|
||||
pub const SYS_VFORK: u32 = 58;
|
||||
pub const SYS_EXECVE: u32 = 59;
|
||||
pub const SYS_EXIT: u32 = 60;
|
||||
pub const SYS_WAIT4: u32 = 61;
|
||||
pub const SYS_KILL: u32 = 62;
|
||||
pub const SYS_UNAME: u32 = 63;
|
||||
pub const SYS_SEMGET: u32 = 64;
|
||||
pub const SYS_SEMOP: u32 = 65;
|
||||
pub const SYS_SEMCTL: u32 = 66;
|
||||
pub const SYS_SHMDT: u32 = 67;
|
||||
pub const SYS_MSGGET: u32 = 68;
|
||||
pub const SYS_MSGSND: u32 = 69;
|
||||
pub const SYS_MSGRCV: u32 = 70;
|
||||
pub const SYS_MSGCTL: u32 = 71;
|
||||
pub const SYS_FCNTL: u32 = 72;
|
||||
pub const SYS_FLOCK: u32 = 73;
|
||||
pub const SYS_FSYNC: u32 = 74;
|
||||
pub const SYS_FDATASYNC: u32 = 75;
|
||||
pub const SYS_TRUNCATE: u32 = 76;
|
||||
pub const SYS_FTRUNCATE: u32 = 77;
|
||||
pub const SYS_GETDENTS: u32 = 78;
|
||||
pub const SYS_GETCWD: u32 = 79;
|
||||
pub const SYS_CHDIR: u32 = 80;
|
||||
pub const SYS_FCHDIR: u32 = 81;
|
||||
pub const SYS_RENAME: u32 = 82;
|
||||
pub const SYS_MKDIR: u32 = 83;
|
||||
pub const SYS_RMDIR: u32 = 84;
|
||||
pub const SYS_CREAT: u32 = 85;
|
||||
pub const SYS_LINK: u32 = 86;
|
||||
pub const SYS_UNLINK: u32 = 87;
|
||||
pub const SYS_SYMLINK: u32 = 88;
|
||||
pub const SYS_READLINK: u32 = 89;
|
||||
pub const SYS_CHMOD: u32 = 90;
|
||||
pub const SYS_FCHMOD: u32 = 91;
|
||||
pub const SYS_CHOWN: u32 = 92;
|
||||
pub const SYS_FCHOWN: u32 = 93;
|
||||
pub const SYS_LCHOWN: u32 = 94;
|
||||
pub const SYS_UMASK: u32 = 95;
|
||||
pub const SYS_GETTIMEOFDAY: u32 = 96;
|
||||
pub const SYS_GETRLIMIT: u32 = 97;
|
||||
pub const SYS_GETRUSAGE: u32 = 98;
|
||||
pub const SYS_SYSINFO: u32 = 99;
|
||||
pub const SYS_TIMES: u32 = 100;
|
||||
pub const SYS_PTRACE: u32 = 101;
|
||||
pub const SYS_GETUID: u32 = 102;
|
||||
pub const SYS_SYSLOG: u32 = 103;
|
||||
pub const SYS_GETGID: u32 = 104;
|
||||
pub const SYS_SETUID: u32 = 105;
|
||||
pub const SYS_SETGID: u32 = 106;
|
||||
pub const SYS_GETEUID: u32 = 107;
|
||||
pub const SYS_GETEGID: u32 = 108;
|
||||
pub const SYS_SETPGID: u32 = 109;
|
||||
pub const SYS_GETPPID: u32 = 110;
|
||||
pub const SYS_GETPGRP: u32 = 111;
|
||||
pub const SYS_SETSID: u32 = 112;
|
||||
pub const SYS_SETREUID: u32 = 113;
|
||||
pub const SYS_SETREGID: u32 = 114;
|
||||
pub const SYS_GETGROUPS: u32 = 115;
|
||||
pub const SYS_SETGROUPS: u32 = 116;
|
||||
pub const SYS_SETRESUID: u32 = 117;
|
||||
pub const SYS_GETRESUID: u32 = 118;
|
||||
pub const SYS_SETRESGID: u32 = 119;
|
||||
pub const SYS_GETRESGID: u32 = 120;
|
||||
pub const SYS_GETPGID: u32 = 121;
|
||||
pub const SYS_SETFSUID: u32 = 122;
|
||||
pub const SYS_SETFSGID: u32 = 123;
|
||||
pub const SYS_GETSID: u32 = 124;
|
||||
pub const SYS_CAPGET: u32 = 125;
|
||||
pub const SYS_CAPSET: u32 = 126;
|
||||
pub const SYS_RT_SIGPENDING: u32 = 127;
|
||||
pub const SYS_RT_SIGTIMEDWAIT: u32 = 128;
|
||||
pub const SYS_RT_SIGQUEUEINFO: u32 = 129;
|
||||
pub const SYS_RT_SIGSUSPEND: u32 = 130;
|
||||
pub const SYS_SIGALTSTACK: u32 = 131;
|
||||
pub const SYS_UTIME: u32 = 132;
|
||||
pub const SYS_MKNOD: u32 = 133;
|
||||
pub const SYS_USELIB: u32 = 134;
|
||||
pub const SYS_PERSONALITY: u32 = 135;
|
||||
pub const SYS_USTAT: u32 = 136;
|
||||
pub const SYS_STATFS: u32 = 137;
|
||||
pub const SYS_FSTATFS: u32 = 138;
|
||||
pub const SYS_SYSFS: u32 = 139;
|
||||
pub const SYS_GETPRIORITY: u32 = 140;
|
||||
pub const SYS_SETPRIORITY: u32 = 141;
|
||||
pub const SYS_SCHED_SETPARAM: u32 = 142;
|
||||
pub const SYS_SCHED_GETPARAM: u32 = 143;
|
||||
pub const SYS_SCHED_SETSCHEDULER: u32 = 144;
|
||||
pub const SYS_SCHED_GETSCHEDULER: u32 = 145;
|
||||
pub const SYS_SCHED_GET_PRIORITY_MAX: u32 = 146;
|
||||
pub const SYS_SCHED_GET_PRIORITY_MIN: u32 = 147;
|
||||
pub const SYS_SCHED_RR_GET_INTERVAL: u32 = 148;
|
||||
pub const SYS_MLOCK: u32 = 149;
|
||||
pub const SYS_MUNLOCK: u32 = 150;
|
||||
pub const SYS_MLOCKALL: u32 = 151;
|
||||
pub const SYS_MUNLOCKALL: u32 = 152;
|
||||
pub const SYS_VHANGUP: u32 = 153;
|
||||
pub const SYS_MODIFY_LDT: u32 = 154;
|
||||
pub const SYS_PIVOT_ROOT: u32 = 155;
|
||||
pub const SYS__SYSCTL: u32 = 156;
|
||||
pub const SYS_PRCTL: u32 = 157;
|
||||
pub const SYS_ARCH_PRCTL: u32 = 158;
|
||||
pub const SYS_ADJTIMEX: u32 = 159;
|
||||
pub const SYS_SETRLIMIT: u32 = 160;
|
||||
pub const SYS_CHROOT: u32 = 161;
|
||||
pub const SYS_SYNC: u32 = 162;
|
||||
pub const SYS_ACCT: u32 = 163;
|
||||
pub const SYS_SETTIMEOFDAY: u32 = 164;
|
||||
pub const SYS_MOUNT: u32 = 165;
|
||||
pub const SYS_UMOUNT2: u32 = 166;
|
||||
pub const SYS_SWAPON: u32 = 167;
|
||||
pub const SYS_SWAPOFF: u32 = 168;
|
||||
pub const SYS_REBOOT: u32 = 169;
|
||||
pub const SYS_SETHOSTNAME: u32 = 170;
|
||||
pub const SYS_SETDOMAINNAME: u32 = 171;
|
||||
pub const SYS_IOPL: u32 = 172;
|
||||
pub const SYS_IOPERM: u32 = 173;
|
||||
pub const SYS_CREATE_MODULE: u32 = 174;
|
||||
pub const SYS_INIT_MODULE: u32 = 175;
|
||||
pub const SYS_DELETE_MODULE: u32 = 176;
|
||||
pub const SYS_GET_KERNEL_SYMS: u32 = 177;
|
||||
pub const SYS_QUERY_MODULE: u32 = 178;
|
||||
pub const SYS_QUOTACTL: u32 = 179;
|
||||
pub const SYS_NFSSERVCTL: u32 = 180;
|
||||
pub const SYS_GETPMSG: u32 = 181;
|
||||
pub const SYS_PUTPMSG: u32 = 182;
|
||||
pub const SYS_AFS_SYSCALL: u32 = 183;
|
||||
pub const SYS_TUXCALL: u32 = 184;
|
||||
pub const SYS_SECURITY: u32 = 185;
|
||||
pub const SYS_GETTID: u32 = 186;
|
||||
pub const SYS_READAHEAD: u32 = 187;
|
||||
pub const SYS_SETXATTR: u32 = 188;
|
||||
pub const SYS_LSETXATTR: u32 = 189;
|
||||
pub const SYS_FSETXATTR: u32 = 190;
|
||||
pub const SYS_GETXATTR: u32 = 191;
|
||||
pub const SYS_LGETXATTR: u32 = 192;
|
||||
pub const SYS_FGETXATTR: u32 = 193;
|
||||
pub const SYS_LISTXATTR: u32 = 194;
|
||||
pub const SYS_LLISTXATTR: u32 = 195;
|
||||
pub const SYS_FLISTXATTR: u32 = 196;
|
||||
pub const SYS_REMOVEXATTR: u32 = 197;
|
||||
pub const SYS_LREMOVEXATTR: u32 = 198;
|
||||
pub const SYS_FREMOVEXATTR: u32 = 199;
|
||||
pub const SYS_TKILL: u32 = 200;
|
||||
pub const SYS_TIME: u32 = 201;
|
||||
pub const SYS_FUTEX: u32 = 202;
|
||||
pub const SYS_SCHED_SETAFFINITY: u32 = 203;
|
||||
pub const SYS_SCHED_GETAFFINITY: u32 = 204;
|
||||
pub const SYS_SET_THREAD_AREA: u32 = 205;
|
||||
pub const SYS_IO_SETUP: u32 = 206;
|
||||
pub const SYS_IO_DESTROY: u32 = 207;
|
||||
pub const SYS_IO_GETEVENTS: u32 = 208;
|
||||
pub const SYS_IO_SUBMIT: u32 = 209;
|
||||
pub const SYS_IO_CANCEL: u32 = 210;
|
||||
pub const SYS_GET_THREAD_AREA: u32 = 211;
|
||||
pub const SYS_LOOKUP_DCOOKIE: u32 = 212;
|
||||
pub const SYS_EPOLL_CREATE: u32 = 213;
|
||||
pub const SYS_EPOLL_CTL_OLD: u32 = 214;
|
||||
pub const SYS_EPOLL_WAIT_OLD: u32 = 215;
|
||||
pub const SYS_REMAP_FILE_PAGES: u32 = 216;
|
||||
pub const SYS_GETDENTS64: u32 = 217;
|
||||
pub const SYS_SET_TID_ADDRESS: u32 = 218;
|
||||
pub const SYS_RESTART_SYSCALL: u32 = 219;
|
||||
pub const SYS_SEMTIMEDOP: u32 = 220;
|
||||
pub const SYS_FADVISE64: u32 = 221;
|
||||
pub const SYS_TIMER_CREATE: u32 = 222;
|
||||
pub const SYS_TIMER_SETTIME: u32 = 223;
|
||||
pub const SYS_TIMER_GETTIME: u32 = 224;
|
||||
pub const SYS_TIMER_GETOVERRUN: u32 = 225;
|
||||
pub const SYS_TIMER_DELETE: u32 = 226;
|
||||
pub const SYS_CLOCK_SETTIME: u32 = 227;
|
||||
pub const SYS_CLOCK_GETTIME: u32 = 228;
|
||||
pub const SYS_CLOCK_GETRES: u32 = 229;
|
||||
pub const SYS_CLOCK_NANOSLEEP: u32 = 230;
|
||||
pub const SYS_EXIT_GROUP: u32 = 231;
|
||||
pub const SYS_EPOLL_WAIT: u32 = 232;
|
||||
pub const SYS_EPOLL_CTL: u32 = 233;
|
||||
pub const SYS_TGKILL: u32 = 234;
|
||||
pub const SYS_UTIMES: u32 = 235;
|
||||
pub const SYS_VSERVER: u32 = 236;
|
||||
pub const SYS_MBIND: u32 = 237;
|
||||
pub const SYS_SET_MEMPOLICY: u32 = 238;
|
||||
pub const SYS_GET_MEMPOLICY: u32 = 239;
|
||||
pub const SYS_MQ_OPEN: u32 = 240;
|
||||
pub const SYS_MQ_UNLINK: u32 = 241;
|
||||
pub const SYS_MQ_TIMEDSEND: u32 = 242;
|
||||
pub const SYS_MQ_TIMEDRECEIVE: u32 = 243;
|
||||
pub const SYS_MQ_NOTIFY: u32 = 244;
|
||||
pub const SYS_MQ_GETSETATTR: u32 = 245;
|
||||
pub const SYS_KEXEC_LOAD: u32 = 246;
|
||||
pub const SYS_WAITID: u32 = 247;
|
||||
pub const SYS_ADD_KEY: u32 = 248;
|
||||
pub const SYS_REQUEST_KEY: u32 = 249;
|
||||
pub const SYS_KEYCTL: u32 = 250;
|
||||
pub const SYS_IOPRIO_SET: u32 = 251;
|
||||
pub const SYS_IOPRIO_GET: u32 = 252;
|
||||
pub const SYS_INOTIFY_INIT: u32 = 253;
|
||||
pub const SYS_INOTIFY_ADD_WATCH: u32 = 254;
|
||||
pub const SYS_INOTIFY_RM_WATCH: u32 = 255;
|
||||
pub const SYS_MIGRATE_PAGES: u32 = 256;
|
||||
pub const SYS_OPENAT: u32 = 257;
|
||||
pub const SYS_MKDIRAT: u32 = 258;
|
||||
pub const SYS_MKNODAT: u32 = 259;
|
||||
pub const SYS_FCHOWNAT: u32 = 260;
|
||||
pub const SYS_FUTIMESAT: u32 = 261;
|
||||
pub const SYS_NEWFSTATAT: u32 = 262;
|
||||
pub const SYS_UNLINKAT: u32 = 263;
|
||||
pub const SYS_RENAMEAT: u32 = 264;
|
||||
pub const SYS_LINKAT: u32 = 265;
|
||||
pub const SYS_SYMLINKAT: u32 = 266;
|
||||
pub const SYS_READLINKAT: u32 = 267;
|
||||
pub const SYS_FCHMODAT: u32 = 268;
|
||||
pub const SYS_FACCESSAT: u32 = 269;
|
||||
pub const SYS_PSELECT6: u32 = 270;
|
||||
pub const SYS_PPOLL: u32 = 271;
|
||||
pub const SYS_UNSHARE: u32 = 272;
|
||||
pub const SYS_SET_ROBUST_LIST: u32 = 273;
|
||||
pub const SYS_GET_ROBUST_LIST: u32 = 274;
|
||||
pub const SYS_SPLICE: u32 = 275;
|
||||
pub const SYS_TEE: u32 = 276;
|
||||
pub const SYS_SYNC_FILE_RANGE: u32 = 277;
|
||||
pub const SYS_VMSPLICE: u32 = 278;
|
||||
pub const SYS_MOVE_PAGES: u32 = 279;
|
||||
pub const SYS_UTIMENSAT: u32 = 280;
|
||||
pub const SYS_EPOLL_PWAIT: u32 = 281;
|
||||
pub const SYS_SIGNALFD: u32 = 282;
|
||||
pub const SYS_TIMERFD_CREATE: u32 = 283;
|
||||
pub const SYS_EVENTFD: u32 = 284;
|
||||
pub const SYS_FALLOCATE: u32 = 285;
|
||||
pub const SYS_TIMERFD_SETTIME: u32 = 286;
|
||||
pub const SYS_TIMERFD_GETTIME: u32 = 287;
|
||||
pub const SYS_ACCEPT4: u32 = 288;
|
||||
pub const SYS_SIGNALFD4: u32 = 289;
|
||||
pub const SYS_EVENTFD2: u32 = 290;
|
||||
pub const SYS_EPOLL_CREATE1: u32 = 291;
|
||||
pub const SYS_DUP3: u32 = 292;
|
||||
pub const SYS_PIPE2: u32 = 293;
|
||||
pub const SYS_INOTIFY_INIT1: u32 = 294;
|
||||
pub const SYS_PREADV: u32 = 295;
|
||||
pub const SYS_PWRITEV: u32 = 296;
|
||||
pub const SYS_RT_TGSIGQUEUEINFO: u32 = 297;
|
||||
pub const SYS_PERF_EVENT_OPEN: u32 = 298;
|
||||
pub const SYS_RECVMMSG: u32 = 299;
|
||||
pub const SYS_FANOTIFY_INIT: u32 = 300;
|
||||
pub const SYS_FANOTIFY_MARK: u32 = 301;
|
||||
pub const SYS_PRLIMIT64: u32 = 302;
|
||||
pub const SYS_NAME_TO_HANDLE_AT: u32 = 303;
|
||||
pub const SYS_OPEN_BY_HANDLE_AT: u32 = 304;
|
||||
pub const SYS_CLOCK_ADJTIME: u32 = 305;
|
||||
pub const SYS_SYNCFS: u32 = 306;
|
||||
pub const SYS_SENDMMSG: u32 = 307;
|
||||
pub const SYS_SETNS: u32 = 308;
|
||||
pub const SYS_GETCPU: u32 = 309;
|
||||
pub const SYS_PROCESS_VM_READV: u32 = 310;
|
||||
pub const SYS_PROCESS_VM_WRITEV: u32 = 311;
|
||||
pub const SYS_KCMP: u32 = 312;
|
||||
pub const SYS_FINIT_MODULE: u32 = 313;
|
||||
pub const SYS_SCHED_SETATTR: u32 = 314;
|
||||
pub const SYS_SCHED_GETATTR: u32 = 315;
|
||||
pub const SYS_RENAMEAT2: u32 = 316;
|
||||
pub const SYS_SECCOMP: u32 = 317;
|
||||
pub const SYS_GETRANDOM: u32 = 318;
|
||||
pub const SYS_MEMFD_CREATE: u32 = 319;
|
||||
pub const SYS_KEXEC_FILE_LOAD: u32 = 320;
|
||||
pub const SYS_BPF: u32 = 321;
|
||||
pub const SYS_EXECVEAT: u32 = 322;
|
||||
pub const SYS_USERFAULTFD: u32 = 323;
|
||||
pub const SYS_MEMBARRIER: u32 = 324;
|
||||
pub const SYS_MLOCK2: u32 = 325;
|
||||
pub const SYS_COPY_FILE_RANGE: u32 = 326;
|
||||
pub const SYS_PREADV2: u32 = 327;
|
||||
pub const SYS_PWRITEV2: u32 = 328;
|
||||
pub const SYS_PKEY_MPROTECT: u32 = 329;
|
||||
pub const SYS_PKEY_ALLOC: u32 = 330;
|
||||
pub const SYS_PKEY_FREE: u32 = 331;
|
||||
pub const SYS_STATX: u32 = 332;
|
||||
pub const SYS_IO_PGETEVENTS: u32 = 333;
|
||||
pub const SYS_RSEQ: u32 = 334;
|
|
@ -0,0 +1,117 @@
|
|||
use core::fmt;
|
||||
|
||||
pub type SysResult = Result<usize, SysError>;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[repr(isize)]
|
||||
#[derive(Debug)]
|
||||
pub enum SysError {
|
||||
EUNDEF = 0,
|
||||
EPERM = 1,
|
||||
ENOENT = 2,
|
||||
ESRCH = 3,
|
||||
EINTR = 4,
|
||||
EIO = 5,
|
||||
ENXIO = 6,
|
||||
E2BIG = 7,
|
||||
ENOEXEC = 8,
|
||||
EBADF = 9,
|
||||
ECHILD = 10,
|
||||
EAGAIN = 11,
|
||||
ENOMEM = 12,
|
||||
EACCES = 13,
|
||||
EFAULT = 14,
|
||||
ENOTBLK = 15,
|
||||
EBUSY = 16,
|
||||
EEXIST = 17,
|
||||
EXDEV = 18,
|
||||
ENODEV = 19,
|
||||
ENOTDIR = 20,
|
||||
EISDIR = 21,
|
||||
EINVAL = 22,
|
||||
ENFILE = 23,
|
||||
EMFILE = 24,
|
||||
ENOTTY = 25,
|
||||
ETXTBSY = 26,
|
||||
EFBIG = 27,
|
||||
ENOSPC = 28,
|
||||
ESPIPE = 29,
|
||||
EROFS = 30,
|
||||
EMLINK = 31,
|
||||
EPIPE = 32,
|
||||
EDOM = 33,
|
||||
ERANGE = 34,
|
||||
EDEADLK = 35,
|
||||
ENAMETOOLONG = 36,
|
||||
ENOLCK = 37,
|
||||
ENOSYS = 38,
|
||||
ENOTEMPTY = 39,
|
||||
ELOOP = 40,
|
||||
ENOTSOCK = 80,
|
||||
ENOPROTOOPT = 92,
|
||||
EPFNOSUPPORT = 96,
|
||||
EAFNOSUPPORT = 97,
|
||||
ENOBUFS = 105,
|
||||
EISCONN = 106,
|
||||
ENOTCONN = 107,
|
||||
ECONNREFUSED = 111,
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
impl fmt::Display for SysError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use self::SysError::*;
|
||||
let explain = match self {
|
||||
EPERM => "Operation not permitted",
|
||||
ENOENT => "No such file or directory",
|
||||
ESRCH => "No such process",
|
||||
EINTR => "Interrupted system call",
|
||||
EIO => "I/O error",
|
||||
ENXIO => "No such device or address",
|
||||
E2BIG => "Argument list too long",
|
||||
ENOEXEC => "Exec format error",
|
||||
EBADF => "Bad file number",
|
||||
ECHILD => "No child processes",
|
||||
EAGAIN => "Try again",
|
||||
ENOMEM => "Out of memory",
|
||||
EACCES => "Permission denied",
|
||||
EFAULT => "Bad address",
|
||||
ENOTBLK => "Block device required",
|
||||
EBUSY => "Device or resource busy",
|
||||
EEXIST => "File exists",
|
||||
EXDEV => "Cross-device link",
|
||||
ENODEV => "No such device",
|
||||
ENOTDIR => "Not a directory",
|
||||
EISDIR => "Is a directory",
|
||||
EINVAL => "Invalid argument",
|
||||
ENFILE => "File table overflow",
|
||||
EMFILE => "Too many open files",
|
||||
ENOTTY => "Not a typewriter",
|
||||
ETXTBSY => "Text file busy",
|
||||
EFBIG => "File too large",
|
||||
ENOSPC => "No space left on device",
|
||||
ESPIPE => "Illegal seek",
|
||||
EROFS => "Read-only file system",
|
||||
EMLINK => "Too many links",
|
||||
EPIPE => "Broken pipe",
|
||||
EDOM => "Math argument out of domain of func",
|
||||
ERANGE => "Math result not representable",
|
||||
EDEADLK => "Resource deadlock would occur",
|
||||
ENAMETOOLONG => "File name too long",
|
||||
ENOLCK => "No record locks available",
|
||||
ENOSYS => "Function not implemented",
|
||||
ENOTEMPTY => "Directory not empty",
|
||||
ELOOP => "Too many symbolic links encountered",
|
||||
ENOTSOCK => "Socket operation on non-socket",
|
||||
ENOPROTOOPT => "Protocol not available",
|
||||
EPFNOSUPPORT => "Protocol family not supported",
|
||||
EAFNOSUPPORT => "Address family not supported by protocol",
|
||||
ENOBUFS => "No buffer space available",
|
||||
EISCONN => "Transport endpoint is already connected",
|
||||
ENOTCONN => "Transport endpoint is not connected",
|
||||
ECONNREFUSED => "Connection refused",
|
||||
_ => "Unknown error",
|
||||
};
|
||||
write!(f, "{}", explain)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
#![no_std]
|
||||
#![deny(warnings, unsafe_code, unused_must_use, unreachable_patterns)]
|
||||
|
||||
//#[macro_use]
|
||||
extern crate alloc;
|
||||
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
use {
|
||||
crate::consts::*, crate::error::*, crate::util::*, alloc::sync::Arc, zircon_object::object::*,
|
||||
zircon_object::task::Thread,
|
||||
};
|
||||
|
||||
mod consts;
|
||||
mod error;
|
||||
mod util;
|
||||
|
||||
pub struct Syscall {
|
||||
pub thread: Arc<Thread>,
|
||||
}
|
||||
|
||||
impl Syscall {
|
||||
pub fn syscall(&self, num: u32, args: [usize; 6]) -> isize {
|
||||
info!("syscall => num={}, args={:x?}", num, args);
|
||||
let [a0, a1, _a2, _a3, _a4, _a5] = args;
|
||||
let ret = match num {
|
||||
SYS_ARCH_PRCTL => self.sys_arch_prctl(a0 as _, a1 as _),
|
||||
SYS_SET_TID_ADDRESS => self.sys_set_tid_address(a0.into()),
|
||||
_ => {
|
||||
warn!("syscall unimplemented");
|
||||
Err(SysError::ENOSYS)
|
||||
}
|
||||
};
|
||||
info!("syscall <= {:?}", ret);
|
||||
match ret {
|
||||
Ok(_) => 0,
|
||||
Err(err) => -(err as isize),
|
||||
}
|
||||
}
|
||||
|
||||
fn sys_arch_prctl(&self, code: i32, addr: usize) -> SysResult {
|
||||
const ARCH_SET_FS: i32 = 0x1002;
|
||||
match code {
|
||||
ARCH_SET_FS => {
|
||||
info!("sys_arch_prctl: set FSBASE to {:#x}", addr);
|
||||
Ok(0)
|
||||
}
|
||||
_ => Err(SysError::EINVAL),
|
||||
}
|
||||
}
|
||||
|
||||
fn sys_set_tid_address(&self, tidptr: UserOutPtr<u32>) -> SysResult {
|
||||
warn!("set_tid_address: {:?}. unimplemented!", tidptr);
|
||||
// self.thread.clear_child_tid = tidptr as usize;
|
||||
let tid = self.thread.id();
|
||||
Ok(tid as usize)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
#![allow(unsafe_code, dead_code)]
|
||||
|
||||
use {
|
||||
crate::ZxResult,
|
||||
alloc::string::String,
|
||||
alloc::vec::Vec,
|
||||
core::fmt::{Debug, Error, Formatter},
|
||||
core::marker::PhantomData,
|
||||
zircon_object::ZxError,
|
||||
};
|
||||
|
||||
pub struct UserPtr<T, P: Policy> {
|
||||
ptr: *mut T,
|
||||
mark: PhantomData<P>,
|
||||
}
|
||||
|
||||
pub trait Policy {}
|
||||
pub trait Read: Policy {}
|
||||
pub trait Write: Policy {}
|
||||
pub enum In {}
|
||||
pub enum Out {}
|
||||
pub enum InOut {}
|
||||
|
||||
impl Policy for In {}
|
||||
impl Policy for Out {}
|
||||
impl Policy for InOut {}
|
||||
impl Read for In {}
|
||||
impl Write for Out {}
|
||||
impl Read for InOut {}
|
||||
impl Write for InOut {}
|
||||
|
||||
pub type UserInPtr<T> = UserPtr<T, In>;
|
||||
pub type UserOutPtr<T> = UserPtr<T, Out>;
|
||||
pub type UserInOutPtr<T> = UserPtr<T, InOut>;
|
||||
|
||||
impl<T, P: Policy> Debug for UserPtr<T, P> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
|
||||
write!(f, "{:?}", self.ptr)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, P: Policy> From<usize> for UserPtr<T, P> {
|
||||
fn from(x: usize) -> Self {
|
||||
UserPtr {
|
||||
ptr: x as _,
|
||||
mark: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, P: Read> UserPtr<T, P> {
|
||||
pub fn read(&self) -> ZxResult<T> {
|
||||
// TODO: check ptr and return err
|
||||
Ok(unsafe { self.ptr.read() })
|
||||
}
|
||||
|
||||
pub fn read_array(&self, len: usize) -> ZxResult<Vec<T>> {
|
||||
let mut ret = Vec::with_capacity(len);
|
||||
unsafe {
|
||||
ret.set_len(len);
|
||||
let src = core::slice::from_raw_parts(self.ptr, len);
|
||||
ret.as_mut_slice().copy_from_slice(src);
|
||||
}
|
||||
Ok(ret)
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: Read> UserPtr<u8, P> {
|
||||
pub fn read_string(&self, len: usize) -> ZxResult<String> {
|
||||
let src = unsafe { core::slice::from_raw_parts(self.ptr, len) };
|
||||
let s = core::str::from_utf8(src).map_err(|_| ZxError::INVALID_ARGS)?;
|
||||
Ok(String::from(s))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, P: Write> UserPtr<T, P> {
|
||||
pub fn write(&self, value: T) -> ZxResult<()> {
|
||||
unsafe {
|
||||
self.ptr.write(value);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn write_if_not_null(&self, value: T) -> ZxResult<()> {
|
||||
if self.ptr.is_null() {
|
||||
return Ok(());
|
||||
}
|
||||
self.write(value)
|
||||
}
|
||||
|
||||
pub fn write_array(&self, values: &[T]) -> ZxResult<()> {
|
||||
unsafe {
|
||||
core::slice::from_raw_parts_mut(self.ptr, values.len()).copy_from_slice(values);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
Binary file not shown.
|
@ -45,7 +45,7 @@ impl Thread {
|
|||
let handle = std::thread::spawn(move || {
|
||||
TLS.with(|t| t.replace(Some(tls)));
|
||||
unsafe {
|
||||
asm!("call $0" :: "r"(entry), "{rsp}"(stack), "{rdi}"(arg1), "{rsi}"(arg2) :: "volatile" "intel");
|
||||
asm!("jmp $0" :: "r"(entry), "{rsp}"(stack), "{rdi}"(arg1), "{rsi}"(arg2) :: "volatile" "intel");
|
||||
}
|
||||
unreachable!()
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue