add crate 'linux-loader' and 'linux-syscall'

This commit is contained in:
Runji Wang 2020-01-22 21:22:11 +08:00
parent 54decd2113
commit 26d124dee4
13 changed files with 1034 additions and 1 deletions

1
.gitattributes vendored Normal file
View File

@ -0,0 +1 @@
libc.so filter=lfs diff=lfs merge=lfs -text

View File

@ -3,6 +3,8 @@ members = [
"zircon-object",
"zircon-syscall",
"zircon-userboot",
"linux-syscall",
"linux-loader",
"zircon-hal-unix",
"zircon-hal-bare"
]

18
linux-loader/Cargo.toml Normal file
View File

@ -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" }

80
linux-loader/src/abi.rs Normal file
View File

@ -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;

274
linux-loader/src/lib.rs Normal file
View File

@ -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)
}

29
linux-loader/src/main.rs Normal file
View File

@ -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);
}

13
linux-syscall/Cargo.toml Normal file
View File

@ -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" }

340
linux-syscall/src/consts.rs Normal file
View File

@ -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;

117
linux-syscall/src/error.rs Normal file
View File

@ -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)
}
}

59
linux-syscall/src/lib.rs Normal file
View File

@ -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)
}
}

97
linux-syscall/src/util.rs Normal file
View File

@ -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(())
}
}

BIN
prebuilt/libc.so (Stored with Git LFS) Executable file

Binary file not shown.

View File

@ -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!()
});