Skip to content

Commit 1a47719

Browse files
authored
Merge pull request #102 from syswonder/dev
Merge dev into main
2 parents 714a944 + 34d4927 commit 1a47719

File tree

132 files changed

+2610
-1530
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

132 files changed

+2610
-1530
lines changed

Cargo.lock

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ members = [
1212
"crates/axfs_vfs",
1313
"crates/axio",
1414
"crates/capability",
15-
"crates/crate_interface",
1615
"crates/driver_9p",
1716
"crates/driver_block",
1817
"crates/driver_common",
@@ -22,11 +21,8 @@ members = [
2221
"crates/driver_virtio",
2322
"crates/dtb",
2423
"crates/flatten_objects",
25-
"crates/handler_table",
26-
"crates/kernel_guard",
2724
"crates/lazy_init",
2825
"crates/linked_list",
29-
"crates/memory_addr",
3026
"crates/page_table",
3127
"crates/page_table_entry",
3228
"crates/percpu",
@@ -71,7 +67,3 @@ lto = true
7167
[profile.reldebug]
7268
inherits = "release"
7369
debug = true
74-
75-
76-
[patch.crates-io]
77-
crate_interface = { path = "crates/crate_interface" }

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ RuxOS was inspired by [Unikraft](https://github.com/unikraft/unikraft) and [Arce
2121
* [x] SMP scheduling with single run queue
2222
* [x] File system
2323
* [x] Compatible with Linux apps
24+
* [x] Dynamically loading apps
2425
* [ ] Interrupt driven device I/O
2526
* [ ] Async I/O
2627

@@ -63,6 +64,9 @@ The currently supported applications (Rust), as well as their dependent modules
6364
| [iperf](apps/c/iperf/) | alloc, paging, net, fs, blkfs, select, fp_simd | A network performance test tool |
6465
| [redis](apps/c/redis/) | alloc, paging, fp_simd, irq, multitask, fs, blkfs, net, pipe, epoll, poll, virtio-9p, rtc | A Redis server on Ruxos |
6566
| [sqlite3](apps/c/sqlite3/) | alloc, paging, fs, fp_simd, blkfs | A simple test for Sqlite3 API |
67+
| [cpp](apps/c/cpp/) | alloc, paging, irq, multitask, fs, random-hw | C++ benchmark |
68+
| [dl](apps/c/dl/) | paging, alloc, irq, musl, multitask, fs, pipe, poll, rtc, signal, virtio-9p | An example for dynamically loading apps |
69+
6670

6771
## Build & Run
6872

api/arceos_api/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ default = []
1515
irq = ["ruxfeat/irq"]
1616
rtc = ["ruxfeat/rtc"]
1717
alloc = ["dep:axalloc", "ruxfeat/alloc"]
18+
paging = ["alloc", "ruxfeat/paging"]
1819
multitask = ["ruxtask/multitask", "ruxfeat/multitask"]
1920
fs = ["dep:ruxfs", "ruxfeat/fs"]
2021
net = ["dep:axnet", "ruxfeat/net"]

api/ruxfeat/Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,16 +41,16 @@ sched_rr = ["ruxtask/sched_rr", "irq"]
4141
sched_cfs = ["ruxtask/sched_cfs", "irq"]
4242

4343
# File system
44-
fs = ["alloc", "paging", "dep:ruxfs", "ruxruntime/fs"] # TODO: try to remove "paging"
44+
fs = ["alloc", "dep:ruxfs", "ruxruntime/fs"]
4545
blkfs = ["ruxdriver/virtio-blk", "ruxruntime/blkfs"]
4646
myfs = ["ruxfs?/myfs"]
4747
9pfs = []
4848

4949
# Networking
50-
net = ["alloc", "paging", "ruxdriver/virtio-net", "dep:axnet", "ruxruntime/net"]
50+
net = ["alloc", "ruxdriver/virtio-net", "dep:axnet", "ruxruntime/net"]
5151

5252
# Display
53-
display = ["alloc", "paging", "ruxdriver/virtio-gpu", "dep:ruxdisplay", "ruxruntime/display"]
53+
display = ["alloc", "ruxdriver/virtio-gpu", "dep:ruxdisplay", "ruxruntime/display"]
5454

5555
# 9P
5656
virtio-9p = ["9pfs", "ruxdriver/virtio-9p", "rux9p/virtio-9p", "ruxruntime/virtio-9p"]

api/ruxos_posix_api/Cargo.toml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,15 @@ authors = [
1111
"Shiping Yuan <robert_yuan@pku.edu.com>",
1212
]
1313
description = "POSIX-compatible APIs for Ruxos modules"
14-
license = "GPL-3.0-or-later OR Apache-2.0"
14+
license = "Mulan PSL v2"
1515
repository = "https://github.com/syswonder/ruxos/tree/main/api/ruxos_posix_api"
1616

1717
[features]
1818
default = []
1919

2020
smp = ["ruxfeat/smp"]
2121
alloc = ["dep:axalloc", "ruxfeat/alloc"]
22+
paging = ["alloc", "ruxfeat/paging"]
2223
multitask = ["ruxfeat/multitask", "ruxtask/multitask", "dep:ruxfutex"]
2324
fd = ["alloc"]
2425
fs = ["dep:ruxfs", "ruxfeat/fs", "fd"]
@@ -51,12 +52,17 @@ axnet = { path = "../../modules/axnet", optional = true }
5152
# Other crates
5253
axio = { path = "../../crates/axio" }
5354
axerrno = { path = "../../crates/axerrno" }
54-
memory_addr = { path = "../../crates/memory_addr" }
55+
memory_addr = "0.1.0"
5556
static_assertions = "1.1.0"
5657
spin = { version = "0.9" }
58+
spinlock = { path = "../../crates/spinlock" }
5759
lazy_static = { version = "1.4", features = ["spin_no_std"] }
5860
flatten_objects = { path = "../../crates/flatten_objects" }
61+
page_table = { path = "../../crates/page_table" }
62+
crate_interface = "0.1.1"
5963

64+
cfg-if = "1.0"
65+
elf = { version = "0.7", default-features = false }
6066
bitflags = "2.2"
6167

6268
[build-dependencies]

api/ruxos_posix_api/build.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,10 @@ typedef struct {{
125125
"EINVAL",
126126
"CLONE_.*",
127127
"AT_.*",
128-
"MAP_FAILED",
128+
"MAP_.+",
129+
"PROT_.+",
130+
"MS_.+",
131+
"MREMAP_.+",
129132
];
130133

131134
#[derive(Debug)]

api/ruxos_posix_api/src/imp/cap.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
use core::ffi::c_int;
2+
3+
#[derive(Debug, Clone, Copy)]
4+
struct UserCapHeader {
5+
/// Linux Cap Version:
6+
/// Version1 = 0x19980330,
7+
/// Version2 = 0x20071026,
8+
/// Version3 = 0x20080522,
9+
version: u32,
10+
pid: i32,
11+
}
12+
13+
/// The effective, permitted, and inheritable fields are bit masks of the capabilities.
14+
/// Note that the CAP_* values are bit indexes and need to be bit-shifted before ORing into the bit fields.
15+
#[derive(Debug, Clone, Copy)]
16+
struct UserCapData {
17+
effective: u32,
18+
permitted: u32,
19+
inheritable: u32,
20+
}
21+
22+
/// get thread capabilities. specific to Linux.
23+
pub fn sys_cap_get(cap_user_header: usize, cap_user_data: usize) -> c_int {
24+
let hdrp = cap_user_header as *const UserCapHeader;
25+
let datap = cap_user_data as *mut UserCapData;
26+
unsafe {
27+
debug!(
28+
"sys_cap_get <= pid {:?}, version {:x?} ",
29+
(*hdrp).pid,
30+
(*hdrp).version
31+
);
32+
}
33+
syscall_body!(sys_cap_get, {
34+
unsafe {
35+
// allow all
36+
(*datap).effective = u32::MAX;
37+
(*datap).inheritable = u32::MAX;
38+
(*datap).permitted = u32::MAX;
39+
};
40+
Ok(0)
41+
})
42+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#![allow(unused)]
2+
3+
pub const AT_NULL: usize = 0;
4+
pub const AT_IGNORE: usize = 1;
5+
6+
pub const AT_EXECFD: usize = 2;
7+
8+
/// The address of the program headers of the executable.
9+
pub const AT_PHDR: usize = 3;
10+
11+
pub const AT_PHENT: usize = 4;
12+
pub const AT_PHNUM: usize = 5;
13+
pub const AT_PAGESZ: usize = 6;
14+
15+
/// The base address of the program interpreter (usually, the dynamic linker).
16+
pub const AT_BASE: usize = 7;
17+
18+
pub const AT_FLAGS: usize = 8;
19+
pub const AT_ENTRY: usize = 9;
20+
pub const AT_NOTELF: usize = 10;
21+
pub const AT_UID: usize = 11;
22+
pub const AT_EUID: usize = 12;
23+
pub const AT_GID: usize = 13;
24+
pub const AT_EGID: usize = 14;
25+
pub const AT_PLATFORM: usize = 15;
26+
pub const AT_HWCAP: usize = 16;
27+
pub const AT_CLKTCK: usize = 17;
28+
pub const AT_DCACHEBSIZE: usize = 19;
29+
pub const AT_ICACHEBSIZE: usize = 20;
30+
pub const AT_UCACHEBSIZE: usize = 21;
31+
pub const AT_SECURE: usize = 23;
32+
pub const AT_RANDOM: usize = 25;
33+
34+
/// A pointer to a string containing the pathname used to execute the program.
35+
pub const AT_EXECFN: usize = 31;
36+
37+
/// The address of a page containing the vDSO that the kernel creates
38+
pub const AT_SYSINFO_EHDR: usize = 33;
39+
40+
/// The entry point to the system call function in the vDSO. Not present/needed on all architectures (e.g., absent on x86-64).
41+
pub const AT_SYSINFO: usize = 32;
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
use crate::{ctypes::kstat, *};
2+
use alloc::{vec, vec::Vec};
3+
use core::ptr::null_mut;
4+
5+
#[derive(Debug)]
6+
pub struct ElfProg {
7+
pub base: usize,
8+
pub entry: usize,
9+
pub interp_path: Vec<u8>,
10+
pub phent: usize,
11+
pub phnum: usize,
12+
pub phdr: usize,
13+
}
14+
15+
impl ElfProg {
16+
/// read elf from `path`, and copy LOAD segments to a alloacated memory
17+
///
18+
/// and load interp, if needed.
19+
pub fn new(filepath: &str) -> Self {
20+
debug!("sys_execve: new elf prog: {filepath}");
21+
22+
// open file
23+
let fd = sys_open(filepath.as_ptr() as _, ctypes::O_RDWR as _, 0);
24+
25+
// get file size
26+
let mut buf = ctypes::kstat {
27+
..Default::default()
28+
};
29+
sys_fstat(fd, &mut buf as *const kstat as *mut _);
30+
let filesize = buf.st_size as usize;
31+
32+
// read file
33+
let mut file = vec![0u8; filesize];
34+
sys_read(fd, file.as_mut_ptr() as *mut _, filesize);
35+
debug!("sys_execve: read file size 0x{filesize:x}");
36+
sys_close(fd);
37+
38+
// parse elf
39+
let file = elf::ElfBytes::<elf::endian::AnyEndian>::minimal_parse(&file)
40+
.expect("parse ELF failed");
41+
42+
// get program's LOAD mem size
43+
let mut min_addr = 0;
44+
let mut max_addr = 0;
45+
let segs = file.segments().unwrap();
46+
for seg in segs {
47+
if seg.p_type == elf::abi::PT_LOAD {
48+
min_addr = min_addr.min(seg.p_vaddr);
49+
max_addr = max_addr.max(seg.p_vaddr + seg.p_memsz);
50+
}
51+
}
52+
let msize = (max_addr - min_addr) as usize;
53+
54+
// alloc memory for LOAD
55+
let prot = ctypes::PROT_WRITE | ctypes::PROT_READ | ctypes::PROT_EXEC;
56+
let flags = ctypes::MAP_ANONYMOUS | ctypes::MAP_PRIVATE;
57+
let base = crate::sys_mmap(null_mut(), msize, prot as _, flags as _, -1, 0) as usize;
58+
59+
// copy LOAD segments
60+
for seg in segs {
61+
if seg.p_type == elf::abi::PT_LOAD {
62+
let data = file.segment_data(&seg).unwrap();
63+
let dst = (seg.p_vaddr as usize + base) as *mut u8;
64+
unsafe { dst.copy_from_nonoverlapping(data.as_ptr(), data.len()) };
65+
}
66+
}
67+
68+
// phdr
69+
let phdr = base + file.ehdr.e_phoff as usize;
70+
71+
// get entry
72+
let entry = file.ehdr.e_entry as usize + base;
73+
74+
// parse interpreter
75+
let mut interp_path = vec![];
76+
for seg in file.segments().unwrap() {
77+
if seg.p_type == elf::abi::PT_INTERP {
78+
let data = file.segment_data(&seg).unwrap().to_vec();
79+
interp_path = data;
80+
break;
81+
}
82+
}
83+
84+
// get address of .text for debugging
85+
let text_section_addr = base
86+
+ file
87+
.section_header_by_name(".text")
88+
.unwrap()
89+
.unwrap()
90+
.sh_offset as usize;
91+
debug!(
92+
"sys_execve: loaded ELF in 0x{:x}, .text is 0x{:x}",
93+
base, text_section_addr
94+
);
95+
96+
// create retval
97+
Self {
98+
base,
99+
entry,
100+
interp_path,
101+
phent: file.ehdr.e_phentsize as usize,
102+
phnum: file.ehdr.e_phnum as usize,
103+
phdr,
104+
}
105+
}
106+
}

0 commit comments

Comments
 (0)