master
王晓智 6 years ago
commit c3c5649c65

1
.gitignore vendored

@ -1,3 +1,4 @@
build/
target/
.DS_Store
.vscode

@ -21,6 +21,7 @@ env:
- ARCH="aarch64" SRC="all"
- ARCH="riscv32" SRC="all"
- ARCH="riscv64" SRC="all"
- ARCH="mipsel" SRC="all"
matrix:
allow_failures:
@ -42,7 +43,7 @@ install:
if [ $TRAVIS_OS_NAME = linux ]; then
export FILE="gcc-arm-8.2-2018.11-x86_64-aarch64-elf";
wget https://developer.arm.com/-/media/Files/downloads/gnu-a/8.2-2018.11/$FILE.tar.xz;
tar -xvf $FILE.tar.xz;
tar -xf $FILE.tar.xz;
export PATH=$PATH:$PWD/$FILE/bin;
sudo apt update;
sudo apt install linux-headers-$(uname -r);
@ -73,7 +74,7 @@ install:
sudo apt update;
sudo apt install linux-headers-$(uname -r);
wget https://musl.cc/riscv32-linux-musl-cross.tgz;
tar -xvf riscv32-linux-musl-cross.tgz;
tar -xf riscv32-linux-musl-cross.tgz;
export PATH=$PATH:$PWD/riscv32-linux-musl-cross/bin;
fi;
fi
@ -82,10 +83,19 @@ install:
sudo apt update;
sudo apt install linux-headers-$(uname -r);
wget https://musl.cc/riscv64-linux-musl-cross.tgz;
tar -xvf riscv64-linux-musl-cross.tgz;
tar -xf riscv64-linux-musl-cross.tgz;
export PATH=$PATH:$PWD/riscv64-linux-musl-cross/bin;
fi;
fi
- if [ $ARCH = mipsel ]; then
if [ $TRAVIS_OS_NAME = linux ]; then
sudo apt update;
sudo apt install linux-headers-$(uname -r);
wget https://musl.cc/mipsel-linux-musln32-cross.tgz;
tar -xvf mipsel-linux-musln32-cross.tgz;
export PATH=$PATH:$PWD/mipsel-linux-musln32-cross/bin;
fi;
fi
before_script:

@ -1,4 +1,4 @@
# arch = {riscv32, riscv64, x86_64, aarch64}
# arch = {riscv32, riscv64, x86_64, aarch64, mipsel}
# mode = {debug, release}
arch ?= riscv32
mode ?= debug
@ -6,6 +6,8 @@ out_dir ?= build/$(arch)
out_img ?= build/$(arch).img
out_qcow2 ?= build/$(arch).qcow2
rcore_fs_fuse_revision ?= 585eb61
rust_src_dir := rust/src/bin
rust_bin_path := rust/target/$(arch)-rcore/$(mode)
rust_bins := $(patsubst $(rust_src_dir)/%.rs, $(rust_bin_path)/%, $(wildcard $(rust_src_dir)/*.rs))
@ -13,8 +15,8 @@ ucore_bin_path := ucore/build/$(arch)
biscuit_bin_path := biscuit/build/$(arch)
busybox := $(out_dir)/busybox
alpine_version_major := 3.9
alpine_version_full := 3.9.2
alpine_file := alpine-minirootfs-3.9.2-$(arch).tar.gz
alpine_version_full := 3.9.3
alpine_file := alpine-minirootfs-3.9.3-$(arch).tar.gz
alpine := alpine/$(alpine_file)
rust_build_args := --target targets/$(arch)-rcore.json
@ -37,24 +39,20 @@ rust:
@cp $(rust_bins) $(out_dir)/rust
ucore:
ifneq ($(arch), x86_64)
@echo Building ucore programs
@mkdir -p ucore/build
@cd ucore/build && cmake $(cmake_build_args) .. && make
@rm -rf $(out_dir)/ucore && mkdir -p $(out_dir)/ucore
@cp $(ucore_bin_path)/* $(out_dir)/ucore
endif
biscuit:
ifeq ($(arch), $(filter $(arch), x86_64 aarch64 riscv64))
ifneq ($(shell uname)-$(arch), Darwin-riscv64)
ifneq ($(shell uname)-$(arch), Darwin-$(filter $(arch), riscv32 riscv64 aarch64))
@echo Building biscuit programs
@mkdir -p biscuit/build
@cd biscuit/build && cmake $(cmake_build_args) .. && make
@rm -rf $(out_dir)/biscuit && mkdir -p $(out_dir)/biscuit
@cp $(biscuit_bin_path)/* $(out_dir)/biscuit
endif
endif
$(busybox):
ifeq ($(arch), x86_64)
@ -68,14 +66,13 @@ ifeq ($(arch), $(filter $(arch), x86_64 aarch64))
@mv tmp/bin/busybox $(busybox)
@rm -rf tmp && rm busybox.tar.xz
endif
ifeq ($(arch), riscv64)
@wget https://github.com/rcore-os/busybox-riscv-prebuilts/raw/master/busybox-1.30.1-riscv64/busybox -O $(busybox)
ifeq ($(arch), $(filter $(arch), riscv64 riscv32 mipsel))
@wget https://github.com/rcore-os/busybox-prebuilts/raw/master/busybox-1.30.1-${arch}/busybox -O $(busybox)
endif
busybox: $(busybox)
nginx:
ifneq ($(arch), riscv32)
ifneq ($(shell uname), Darwin)
@echo Building nginx
mkdir -p $(out_dir)/usr/local/nginx/conf
@ -84,10 +81,8 @@ ifneq ($(shell uname), Darwin)
@cp nginx/build/$(arch)/nginx $(out_dir)
@cp nginx/nginx.conf $(out_dir)/usr/local/nginx/conf
endif
endif
redis:
ifneq ($(arch), riscv64)
ifneq ($(shell uname), Darwin)
@echo Building redis
@mkdir -p $(out_dir)
@ -96,7 +91,6 @@ ifneq ($(shell uname), Darwin)
@cp redis/build/$(arch)/redis-cli $(out_dir)/redis-cli
@cp redis/redis.conf $(out_dir)/redis.conf
endif
endif
iperf3:
ifeq ($(arch), x86_64)
@ -110,7 +104,7 @@ endif
endif
$(alpine):
wget "http://dl-cdn.alpinelinux.org/alpine/v3.9/releases/$(arch)/$(alpine_file)" -O $(alpine)
-wget "http://dl-cdn.alpinelinux.org/alpine/v3.9/releases/$(arch)/$(alpine_file)" -O $(alpine)
alpine: $(alpine)
ifeq ($(arch), $(filter $(arch), x86_64 aarch64))
@ -119,7 +113,14 @@ ifeq ($(arch), $(filter $(arch), x86_64 aarch64))
@cd $(out_dir) && tar xvf ../../$(alpine)
endif
build: rust ucore biscuit $(busybox) nginx redis iperf3
test:
ifeq ($(arch), $(filter $(arch), x86_64 aarch64))
@echo setup test DIR
@mkdir -p $(out_dir)
@cp -r testsuits_alpine $(out_dir)/test
endif
build: rust ucore biscuit $(busybox) nginx redis iperf3 test
sfsimg: $(out_qcow2)
@ -132,9 +133,9 @@ $(out_qcow2): $(out_img)
@qemu-img resize $@ +1G
rcore-fs-fuse:
ifeq ($(shell which rcore-fs-fuse),)
ifneq ($(shell rcore-fs-fuse dir image git-version), $(rcore_fs_fuse_revision))
@echo Installing rcore-fs-fuse
@cargo install rcore-fs-fuse --git https://github.com/rcore-os/rcore-fs --rev ff3dd7d
@cargo install rcore-fs-fuse --git https://github.com/rcore-os/rcore-fs --rev $(rcore_fs_fuse_revision) --force
endif
clean:

@ -36,37 +36,41 @@ To build biscuit programs, install musl toolchain first:
# 2.1 for macOS musl toolchain for x86_64(,aarch64)
$ brew install FileSottile/musl-cross/musl-cross {--with-aarch64}
# 2.2 for ubuntu 16.04, we should build gcc-musl for newest musl-1.1.21, please see build-gcc-musl.md for instructions
# 2.3 for riscv musl toolchain, please install [musl-riscv-toolchain](https://github.com/jiegec/musl-riscv-toolchain)
# 2.3 for riscv musl toolchain, please install [musl-riscv-toolchain](https://github.com/jiegec/musl-riscv-toolchain), however, this one might not be able to build redis on rv64 for lack of libatomic
```
Then, build userspace programs for rCore:
```bash
$ make {ucore,biscuit,rust,nginx,redis,all} arch={x86_64,aarch64,riscv32,riscv64}
$ make {ucore,biscuit,rust,nginx,redis,all} arch={x86_64,aarch64,riscv32,riscv64,mipsel}
$ make alpine arch={x86_64,aarch64} # if you want to use alpine rootfs
$ make sfsimg arch={x86_64,aarch64,riscv32,riscv64}
$ make test arch={x86_64} # test alpine real apps, e.g. python, gcc, rust, go, lua, etc.(need rootfs with these real apps)
$ make sfsimg arch={x86_64,aarch64,riscv32,riscv64,mipsel}
```
A rootfs is created at `build/$(arch)` and converted to `qcow2`.
## Support matrix
| | x86_64 | aarch64 | riscv32 | riscv64 |
| ------------------ | ------ | ------- | ------- | ------- |
| ucore | ❌ | ✅ | ✅ | ✅ |
| rust | ✅ | ✅ | ✅ | ✅ |
| biscuit | ✅ | ✅ | ❌ | ✅ |
| nginx (linux only) | ✅ | ✅ | ❌ | ✅ |
| redis (linux only) | ✅ | ✅ | ✅ | ❌ |
| busybox | ✅ | ✅ | ❌ | ✅ |
| alpine rootfs | ✅ | ✅ | ❌ | ❌ |
| iperf3 | ✅ | ❌ | ❌ | ❌ |
| | x86_64 | aarch64 | riscv32 | riscv64 | mipsel |
| ------------------ | ------ | ------- | ------- | ------- | ------ |
| ucore | ✅ | ✅ | ✅ | ✅ | ❗ |
| rust | ✅ | ✅ | ✅ | ✅ | ✅ |
| biscuit | ✅ | ✅ | ✅ | ✅ | ✅ |
| nginx (linux only) | ✅ | ✅ | ❗ | ✅ | ❗ |
| redis (linux only) | ✅ | ✅ | ✅ | ✅ | ✅ |
| busybox | ✅ | ✅ | ✅ | ✅ | ✅ |
| alpine rootfs | ✅ | ✅ | ❌ | ❌ | ❌ |
| iperf3 | ✅ | ❌ | ❌ | ❌ | ❌ |
| test | ✅ | ❌ | ❌ | ❌ | ❌ |
Note: ❗ means workarounds are used so that they may not work properly. ❌ means failure in compiling or not existed on such platform.
## How to run real world programs
### How to use Redis
If redis is dynamically linked to musl (default if you use commands above), you might need to copy `ld-musl-$(arch).so.1` to rootfs `/lib` . Alpine rootfs includes one as well.
If redis is dynamically linked to musl (default if you use commands above), you might need to copy `ld-musl-$(arch).so.1` to rootfs `/lib` by yourself .Alpine rootfs includes one as well.
After building redis, you should be able to run redis-server in rCore. Then, start `redis-server` in rCore:
@ -155,4 +159,22 @@ $ printf
Built within rCore
```
Note: the long linker args can be replaced by invoking gcc instead later when we fix the problem. If you encountered `rcore-fs-fuse` panicking, consider upgrading it to latest version.
Note: the long linker args can be replaced by invoking gcc instead later when we fix the problem. If you encountered `rcore-fs-fuse` panicking, consider upgrading it to latest version.
### How to test real alpine apps
#### simple test for alpine minifs with little apps
```bash
1. make alpine arch=x86_64
2. make test arch=x86_64
3. make sfsimg arch=x86_64
4. cd $(RCORE_ROOT)/kernel; make run arch=x86_64 mode=release
```
#### test gcc/go/python2/python3/ruby/lua/java/rust
```bash
1. download x86_64.qcow2.realapps.xz from cloud tsinghua
2. xz -d x86_64.qcow2.realapps.xz; mv x86_64.qcow2.realapps x86_64.qcow2
3. mv x86_64.qcow2 $(RCORE_ROOT)/user/build
4. cd $(RCORE_ROOT)/kernel; make run arch=x86_64 mode=release
```

@ -23,17 +23,18 @@ find_path(KERNEL_HEADERS_DIR
)
# Toolchain
set(PREFIX ${ARCH}-linux-musl-)
if (${ARCH} STREQUAL x86_64)
set(PREFIX x86_64-linux-musl-)
set(CMAKE_C_FLAGS "-m64 -mno-red-zone")
elseif (${ARCH} STREQUAL riscv32)
set(PREFIX riscv64-unknown-elf-)
set(CMAKE_C_FLAGS "-march=rv32imac -mabi=ilp32 -mcmodel=medany")
set(CMAKE_C_FLAGS "-march=rv32imafdc -mabi=ilp32d -mcmodel=medany")
elseif (${ARCH} STREQUAL riscv64)
set(PREFIX riscv64-linux-musl-)
set(CMAKE_C_FLAGS "-march=rv64imafdc -mabi=lp64d -mcmodel=medany")
elseif (${ARCH} STREQUAL aarch64)
set(PREFIX aarch64-linux-musl-)
elseif (${ARCH} STREQUAL mipsel)
set(PREFIX ${ARCH}-linux-musln32-)
else ()
message("Unsupported arch: ${ARCH}")
endif ()

@ -34,7 +34,7 @@ void dprint(int fd, char *par, int left, int rec)
spec = 's';
else
spec = '-';
printf("%crwxr-xr-x %ld %s\n", spec, st.st_size, de->d_name);
printf("%crwxr-xr-x %ld %s\n", spec, (long)st.st_size, de->d_name);
}
if (!rec) {
if (closedir(dir) == -1)

@ -2798,12 +2798,18 @@ static volatile int go;
static void *_locker(void *v)
{
while (go != 1)
while (go != 1) {
#if defined(__x86_64__)
asm volatile("pause\n":::"memory");
#elif defined(__aarch64__)
asm volatile("yield\n":::"memory");
#elif defined(__mips__) || defined(__riscv32__) || defined(__riscv64__)
asm volatile("nop\n":::"memory");
#else
#warning Yield instruction is not implemented
#endif
}
pthread_mutex_t *m = (pthread_mutex_t *)v;
int i;
for (i = 0; i < ltimes; i++) {
@ -2917,12 +2923,17 @@ static void _condtest(const int nt)
go = 0;
if (pthread_create(&t[i], NULL, _condsleep, &args[i]))
errx(-1, "pthread_ create");
while (go == 0)
while (go == 0) {
#if defined(__x86_64__)
asm volatile("pause\n":::"memory");
#elif defined(__aarch64__)
asm volatile("yield\n":::"memory");
#elif defined(__mips__) || defined(__riscv32__) || defined(__riscv64__)
asm volatile("nop\n":::"memory");
#else
#warning Yield instruction is not implemented
#endif
}
}
for (i = 0; i < nt; i++)

@ -3,11 +3,17 @@ iperf3_tarball := iperf3-$(iperf3_version).tar.gz
iperf3_tarball_path := src/$(iperf3_tarball)
build_dir := build/$(arch)
iperf3_dir := $(build_dir)/iperf-$(iperf3_version)
cc := $(arch)-linux-musl-gcc
strip := $(arch)-linux-musl-strip
prefix := $(arch)-linux-musl-
bin_unstripped := build/$(arch)/iperf3_unstripped
bin := build/$(arch)/iperf3
ifeq ($(arch), mipsel)
prefix := mipsel-linux-musln32-
endif
cc := $(prefix)gcc
strip := $(prefix)strip
$(iperf3_tarball_path):
wget https://github.com/esnet/iperf/archive/$(iperf3_version).tar.gz -O $(iperf3_tarball_path)

@ -3,11 +3,17 @@ nginx_tarball := nginx-$(nginx_version).tar.gz
nginx_tarball_path := src/nginx-$(nginx_version).tar.gz
build_dir := build/$(arch)
nginx_dir := $(build_dir)/nginx-$(nginx_version)
cc := $(arch)-linux-musl-gcc
strip := $(arch)-linux-musl-strip
prefix := $(arch)-linux-musl-
bin_unstripped := build/$(arch)/nginx_unstripped
bin := build/$(arch)/nginx
ifeq ($(arch), mipsel)
prefix := mipsel-linux-musln32-
endif
cc := $(prefix)gcc
strip := $(prefix)strip
$(nginx_tarball_path):
wget https://nginx.org/download/$(nginx_tarball) -O $(nginx_tarball_path)
@ -21,9 +27,10 @@ $(nginx_dir)/objs/nginx: $(nginx_dir)
sed -i 's/ngx_feature_run=yes/ngx_feature_run=no/' $(nginx_dir)/auto/cc/name
sed -i 's/ngx_test="$$CC /ngx_test="gcc /' $(nginx_dir)/auto/types/sizeof
cd $(nginx_dir) && ./configure --with-cc=$(cc) --with-cc-opt=-static --with-ld-opt=-static --without-pcre --without-http_rewrite_module --without-http_gzip_module --with-poll_module --without-http_upstream_zone_module
cd $(nginx_dir) && echo "#ifndef NGX_SYS_NERR\n#define NGX_SYS_NERR 132\n#endif\n" >> objs/ngx_auto_config.h
cd $(nginx_dir) && echo "#ifndef NGX_HAVE_SVSVSHM\n#define NGX_HAVE_SYSVSHM 1\n#endif\n" >> objs/ngx_auto_config.h
cd $(nginx_dir) && make
cd $(nginx_dir) && printf "#ifndef NGX_SYS_NERR\n#define NGX_SYS_NERR 132\n#endif\n" >> objs/ngx_auto_config.h
cd $(nginx_dir) && printf "#ifndef NGX_HAVE_SVSVSHM\n#define NGX_HAVE_SYSVSHM 1\n#endif\n" >> objs/ngx_auto_config.h
# FIXME: overflow will occur on 32-bit platforms, this is only a temporary workaround
cd $(nginx_dir) && make CFLAGS="${CFLGAS} -Wno-error=overflow"
$(bin_unstripped): $(nginx_dir)/objs/nginx
cp $(nginx_dir)/objs/nginx $(bin_unstripped)

@ -3,13 +3,19 @@ redis_tarball := redis-$(redis_version).tar.gz
redis_tarball_path := src/redis-$(redis_version).tar.gz
build_dir := build/$(arch)
redis_dir := $(build_dir)/redis-$(redis_version)
cc := $(arch)-linux-musl-gcc
strip := $(arch)-linux-musl-strip
prefix := $(arch)-linux-musl-
bin_server_unstripped := build/$(arch)/redis-server-unstripped
bin_server := build/$(arch)/redis-server
bin_cli_unstripped := build/$(arch)/redis-cli-unstripped
bin_cli := build/$(arch)/redis-cli
ifeq ($(arch), mipsel)
prefix := mipsel-linux-musln32-
endif
cc := $(prefix)gcc
strip := $(prefix)strip
# $ARCH is also used in redis internal Makefile, avoid clashing
undefine ARCH
@ -25,7 +31,9 @@ $(redis_dir)/src/redis-server: $(redis_dir)/src/config.h
sed -i 's/#define HAVE_EPOLL 1//' $(redis_dir)/src/config.h
# our accept does not have backlog
sed -i 's/#define MAX_ACCEPTS_PER_CALL 1000/#define MAX_ACCEPTS_PER_CALL 1/' $(redis_dir)/src/networking.c
cd $(redis_dir) && make CC=$(cc) MALLOC=libc
# note: on some platforms gcc seems to forget linking with libatomic, fix it anyway
sed -i 's/-ldl -pthread -lrt/-ldl -pthread -lrt -latomic/' $(redis_dir)/src/Makefile
cd $(redis_dir) && make CC=$(cc) LDFLAGS="${LDFLAGS} -static" MALLOC=libc
$(bin_server_unstripped): $(redis_dir)/src/redis-server
cp $(redis_dir)/src/redis-server $(bin_server_unstripped)

7
rust/Cargo.lock generated

@ -62,6 +62,7 @@ dependencies = [
"buddy_system_allocator 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"isomorphic_drivers 0.1.0 (git+https://github.com/rcore-os/isomorphic_drivers)",
"smoltcp 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"treebitmap 0.3.1 (git+https://github.com/jiegec/treebitmap)",
]
[[package]]
@ -80,6 +81,11 @@ name = "spin"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "treebitmap"
version = "0.3.1"
source = "git+https://github.com/jiegec/treebitmap#a89d725c1308719e327993dc5c5c0357c43dccf1"
[[package]]
name = "volatile"
version = "0.2.6"
@ -96,4 +102,5 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum managed 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fdcec5e97041c7f0f1c5b7d93f12e57293c831c646f4cc7a5db59460c7ea8de6"
"checksum smoltcp 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fef582369edb298c6c41319a544ca9c4e83622f226055ccfcb35974fbb55ed34"
"checksum spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44363f6f51401c34e7be73db0db371c04705d35efbe9f7d6082e03a921a32c55"
"checksum treebitmap 0.3.1 (git+https://github.com/jiegec/treebitmap)" = "<none>"
"checksum volatile 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6af0edf5b4faacc31fc51159244d78d65ec580f021afcef7bd53c04aeabc7f29"

@ -7,4 +7,5 @@ edition = "2018"
[dependencies]
buddy_system_allocator = "0.1"
isomorphic_drivers = { git = "https://github.com/rcore-os/isomorphic_drivers", default-features = false, features = ["log"]}
smoltcp = { version = "0.5.0", default-features = false, features = ["alloc", "log", "proto-ipv4", "socket-tcp", "socket-raw"] }
smoltcp = { version = "0.5.0", default-features = false, features = ["alloc", "log", "proto-ipv4", "socket-tcp", "socket-raw"] }
treebitmap = { git = "https://github.com/jiegec/treebitmap" , features = ["alloc"] }

@ -32,7 +32,8 @@ pub fn main() {
color_text!("!", 97),
);
let text = "reguler \x1b[4munderline\x1b[24m \x1b[7mreverse\x1b[27m \x1b[9mstrikethrough\x1b[29m";
let text =
"reguler \x1b[4munderline\x1b[24m \x1b[7mreverse\x1b[27m \x1b[9mstrikethrough\x1b[29m";
println!("\x1b[47m{}\x1b[0m", color_text!(text, 30));
for i in 31..38 {
println!("{}", color_text!(text, i));

@ -7,7 +7,6 @@ extern crate rcore_user;
use rcore_user::syscall::*;
// IMPORTANT: Must define main() like this
#[no_mangle]
pub fn main() {

@ -0,0 +1,203 @@
#![feature(alloc)]
#![no_std]
#![no_main]
#[macro_use]
extern crate rcore_user;
extern crate alloc;
extern crate treebitmap;
use alloc::format;
use core::default::Default;
use core::mem::size_of;
use rcore_user::syscall::{sys_ioctl, sys_read, sys_sendto, sys_setsockopt, sys_socket};
use treebitmap::*;
#[repr(C)]
#[derive(Default)]
pub struct SockAddrLl {
sll_family: u16,
sll_protocol: u16,
sll_ifindex: u32,
sll_hatype: u16,
sll_pkttype: u8,
sll_halen: u8,
sll_addr: [u8; 8],
}
#[repr(C)]
#[derive(Default)]
pub struct SockAddrIn {
sin_family: u16,
sin_port: u16,
sin_addr: u32,
sin_zero: [u8; 8],
}
#[repr(C)]
#[derive(Default)]
pub struct SockAddrHa {
sha_family: u16,
sha_data: [u8; 14],
}
#[repr(C)]
#[derive(Default)]
struct ArpReq {
arp_pa: SockAddrIn,
arp_ha: SockAddrHa,
arp_flags: u32,
arp_netmask: SockAddrIn,
arp_dev: [u8; 16],
}
pub fn get_routing_table() -> IpLookupTable<Ipv4Addr, (u32, [u8; 6], &'static str)> {
let mut table = IpLookupTable::new();
// iface 0 10.0.0.0/24 00:16:31:ff:a4:9f enp0s4f0
table.insert(
Ipv4Addr::new(10, 0, 0, 0),
24,
(0, [0x00, 0x16, 0x31, 0xff, 0xa4, 0x9f], "enp0s4f0\0"),
);
// iface 1 10.0.1.0/24 54:51:9f:71:c0:01 enp0s5f0
table.insert(
Ipv4Addr::new(10, 0, 1, 0),
24,
(1, [0x54, 0x51, 0x9f, 0x71, 0xc0, 0x01], "enp0s5f0\0"),
);
table
}
// IMPORTANT: Must define main() like this
#[no_mangle]
pub unsafe fn main() {
println!("Raw socket test");
// raw socket, icmp
let capture_fd = sys_socket(2, 3, 1);
// inet socket, udp
let arp_fd = sys_socket(2, 2, 0);
// packet socket, raw
let packet_fd = sys_socket(17, 3, 0);
// netlink socket, raw
let netlink_fd = sys_socket(16, 3, 0);
let table = get_routing_table();
let mut buffer = [0u8; 2048];
// set header included
let included = 1u32;
sys_setsockopt(
capture_fd as usize,
0,
3,
&included as *const u32 as usize,
4,
);
let mut addr: SockAddrLl = Default::default();
// packet
addr.sll_family = 17;
const ETHER_HEADER_LEN: usize = 6 + 6 + 2;
// ethertype 0x0800 ipv4
buffer[12] = 0x08;
buffer[13] = 0x00;
let mut arp: ArpReq = Default::default();
// inet
arp.arp_pa.sin_family = 2;
loop {
let len = sys_read(
capture_fd as usize,
buffer.as_mut_ptr().add(ETHER_HEADER_LEN),
buffer.len(),
) as usize;
println!("Got packet of len {}", len);
// check ethertype and ip version ihl
if ETHER_HEADER_LEN + len > 20
&& buffer[12] == 0x08
&& buffer[13] == 0x00
&& buffer[ETHER_HEADER_LEN + 0] == 0x45
{
// ipv4
let ttl = buffer[ETHER_HEADER_LEN + 8];
if ttl > 1 {
if buffer[ETHER_HEADER_LEN + 19] == 2 {
// to myself
println!("packet to myself");
continue;
}
let lookup_ip = Ipv4Addr::new(
buffer[ETHER_HEADER_LEN + 16],
buffer[ETHER_HEADER_LEN + 17],
buffer[ETHER_HEADER_LEN + 18],
buffer[ETHER_HEADER_LEN + 19],
);
let route_match = table.longest_match(lookup_ip);
match route_match {
Some((_, _, (out_if, mac, name))) => {
let dst_ip = (buffer[ETHER_HEADER_LEN + 19] as u32) << 24
| (buffer[ETHER_HEADER_LEN + 18] as u32) << 16
| (buffer[ETHER_HEADER_LEN + 17] as u32) << 8
| (buffer[ETHER_HEADER_LEN + 16] as u32);
arp.arp_pa.sin_addr = dst_ip;
arp.arp_dev[0..9].copy_from_slice(name.as_bytes());
// SIOCGARP
if sys_ioctl(arp_fd as usize, 0x8954, &arp as *const ArpReq as usize) < 0 {
println!("dst ip not in arp table, skipping");
continue;
}
let message = format!("from {}.{}.{}.{} {:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X} to {}.{}.{}.{} {:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X} dev {}:{} with ttl {}", buffer[ETHER_HEADER_LEN + 12],
buffer[ETHER_HEADER_LEN+ 13],
buffer[ETHER_HEADER_LEN+ 14],
buffer[ETHER_HEADER_LEN+ 15],
mac[0],
mac[1],
mac[2],
mac[3],
mac[4],
mac[5],
buffer[ETHER_HEADER_LEN+ 16],
buffer[ETHER_HEADER_LEN+ 17],
buffer[ETHER_HEADER_LEN+ 18],
buffer[ETHER_HEADER_LEN+ 19],
arp.arp_ha.sha_data[0],
arp.arp_ha.sha_data[1],
arp.arp_ha.sha_data[2],
arp.arp_ha.sha_data[3],
arp.arp_ha.sha_data[4],
arp.arp_ha.sha_data[5],
out_if,
name,
ttl,
);
println!("{}", message);
// fill dst and src mac
// todo: get mac from if instead of hard coding
buffer[0..6].copy_from_slice(&arp.arp_ha.sha_data[0..6]);
buffer[6..12].copy_from_slice(mac);
buffer[ETHER_HEADER_LEN + 8] = ttl - 1;
let checksum = (buffer[ETHER_HEADER_LEN + 10] as u16) << 8
| (buffer[ETHER_HEADER_LEN + 11] as u16);
buffer[ETHER_HEADER_LEN + 10] = ((checksum + 0x0100) >> 8) as u8;
buffer[ETHER_HEADER_LEN + 11] = (checksum + 0x0100) as u8;
addr.sll_ifindex = *out_if;
sys_sendto(
packet_fd as usize,
buffer.as_ptr(),
len as usize + ETHER_HEADER_LEN,
0,
&addr as *const SockAddrLl as usize,
size_of::<SockAddrLl>(),
);
}
None => continue,
}
}
}
}
}

@ -10,7 +10,7 @@ use alloc::vec::Vec;
use core::ptr;
use rcore_user::io::get_line;
use rcore_user::syscall::{sys_exec, sys_vfork, sys_wait, sys_getcwd, sys_chdir, sys_access};
use rcore_user::syscall::{sys_access, sys_chdir, sys_exec, sys_getcwd, sys_vfork, sys_wait};
// IMPORTANT: Must define main() like this
#[no_mangle]

@ -5,7 +5,10 @@
#[macro_use]
extern crate rcore_user;
use rcore_user::syscall::{sys_arch_prctl, sys_vfork, sys_getpid, sys_sleep};
use rcore_user::syscall::{sys_arch_prctl, sys_getpid, sys_sleep, sys_vfork};
#[cfg(target_arch = "mips")]
use rcore_user::syscall::sys_set_theaad_area;
fn set_tls(tls: usize, pid: usize) {
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
@ -23,6 +26,8 @@ fn set_tls(tls: usize, pid: usize) {
// set fs base
sys_arch_prctl(0x1002, &DATA[pid] as *const usize as usize);
}
#[cfg(target_arch = "mips")]
sys_set_theaad_area(tls);
}
fn get_tls() -> usize {
@ -39,6 +44,10 @@ fn get_tls() -> usize {
unsafe {
asm!("mov %fs:0, $0" : "=r"(tls) :);
}
#[cfg(target_arch = "mips")]
unsafe {
asm!("rdhwr $0, $$29" : "=r"(tls) :);
}
tls
}

@ -194,8 +194,8 @@ impl fmt::Write for StdOut {
pub const O_RDONLY: usize = 0; // open for reading only
pub const O_WRONLY: usize = 1; // open for writing only
pub const O_RDWR: usize = 2; // open for reading and writing
// then or in any of these:
// then or in any of these:
pub const O_CREAT: usize = 0x00000004; // create file if it does not exist
pub const O_EXCL: usize = 0x00000008; // error if O_CREAT and the file exists
pub const O_TRUNC: usize = 0x00000010; // truncate file upon open
pub const O_APPEND: usize = 0x00000020; // append on each write
pub const O_APPEND: usize = 0x00000020; // append on each write

@ -1,9 +1,9 @@
use crate::syscall::sys_exit;
use crate::ALLOCATOR;
use super::syscall::*;
use core::alloc::Layout;
use core::panic::PanicInfo;
use super::syscall::*;
#[linkage = "weak"]
#[no_mangle]
@ -14,7 +14,15 @@ fn main() {
fn init_heap() {
const HEAP_SIZE: usize = 0x1000;
static mut HEAP: [u8; HEAP_SIZE] = [0; HEAP_SIZE];
unsafe { ALLOCATOR.lock().init(HEAP.as_ptr() as usize, HEAP_SIZE); }
unsafe {
ALLOCATOR.lock().init(HEAP.as_ptr() as usize, HEAP_SIZE);
}
}
/// MIPS use __start for entry point instead of _start
#[no_mangle]
pub extern "C" fn __start(argc: isize, argv: *const *const u8) -> ! {
_start(argc, argv)
}
#[no_mangle]

@ -10,10 +10,10 @@ extern crate alloc;
#[macro_use]
pub mod io;
pub mod syscall;
pub mod lang_items;
pub mod syscall;
use buddy_system_allocator::LockedHeap;
#[global_allocator]
static ALLOCATOR: LockedHeap = LockedHeap::empty();
static ALLOCATOR: LockedHeap = LockedHeap::empty();

@ -2,35 +2,57 @@ use crate::ALLOCATOR;
use alloc::string::String;
#[inline(always)]
fn sys_call(syscall_id: SyscallId, arg0: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) -> i32 {
fn sys_call(
syscall_id: SyscallId,
arg0: usize,
arg1: usize,
arg2: usize,
arg3: usize,
arg4: usize,
arg5: usize,
) -> i32 {
let id = syscall_id as usize;
let ret: i32;
let mut ret: i32;
let failed: i32;
unsafe {
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
asm!("ecall"
asm!("ecall"
: "={x10}" (ret)
: "{x17}" (id), "{x10}" (arg0), "{x11}" (arg1), "{x12}" (arg2), "{x13}" (arg3), "{x14}" (arg4), "{x15}" (arg5)
: "memory"
: "volatile");
#[cfg(target_arch = "x86")]
asm!("int 0x80"
asm!("int 0x80"
: "={eax}" (ret)
: "{eax}" (id), "{edx}" (arg0), "{ecx}" (arg1), "{ebx}" (arg2), "{edi}" (arg3), "{esi}" (arg4)
: "memory"
: "intel" "volatile");
#[cfg(target_arch = "x86_64")]
asm!("syscall"
asm!("syscall"
: "={rax}" (ret)
: "{rax}" (id), "{rdi}" (arg0), "{rsi}" (arg1), "{rdx}" (arg2), "{r10}" (arg3), "{r8}" (arg4), "{r9}" (arg5)
: "rcx" "r11" "memory"
: "intel" "volatile");
#[cfg(target_arch = "aarch64")]
asm!("svc 0"
asm!("svc 0"
: "={x0}" (ret)
: "{x8}" (id), "{x0}" (arg0), "{x1}" (arg1), "{x2}" (arg2), "{x3}" (arg3), "{x4}" (arg4), "{x5}" (arg5)
: "memory"
: "volatile");
#[cfg(target_arch = "mips")]
{
asm!("syscall"
// v0 for syscall id
: "={$2}" (ret), "={$7}" (failed)
// v0, a0, a1, a2, a3, a4, a5
: "{$2}" (id), "{$4}" (arg0), "{$5}" (arg1), "{$6}" (arg2), "{$7}" (arg3), "{$8}" (arg4), "{$9}" (arg5)
: "memory"
: "volatile");
if failed != 0 {
ret = - ret;
}
}
}
ret
}
@ -38,7 +60,9 @@ fn sys_call(syscall_id: SyscallId, arg0: usize, arg1: usize, arg2: usize, arg3:
pub fn enlarge_heap() {
const HEAP_SIZE: usize = 16 * 1024 * 1024;
let addr = sys_mmap(0, HEAP_SIZE, 0x3, 0x22, 0, 0) as usize;
unsafe { ALLOCATOR.lock().init(addr, HEAP_SIZE); }
unsafe {
ALLOCATOR.lock().init(addr, HEAP_SIZE);
}
}
pub fn sys_exit(code: usize) -> ! {
@ -46,9 +70,16 @@ pub fn sys_exit(code: usize) -> ! {
unreachable!()
}
pub fn sys_exec(name: *const u8, argv: *const *const u8, envp: *const *const u8) -> i32 {
sys_call(SyscallId::Exec, name as usize, argv as usize, envp as usize, 0, 0, 0)
sys_call(
SyscallId::Exec,
name as usize,
argv as usize,
envp as usize,
0,
0,
0,
)
}
pub fn sys_write(fd: usize, base: *const u8, len: usize) -> i32 {
@ -65,7 +96,15 @@ pub fn sys_open(path: &str, flags: usize) -> i32 {
let end = unsafe { &mut *(path.as_ptr().offset(path.len() as isize) as *mut u8) };
let backup = replace(end, 0);
const AT_FDCWD: isize = -100;
let ret = sys_call(SyscallId::Openat, AT_FDCWD as usize, path.as_ptr() as usize, flags, 0, 0, 0);
let ret = sys_call(
SyscallId::Openat,
AT_FDCWD as usize,
path.as_ptr() as usize,
flags,
0,
0,
0,
);
*end = backup;
ret
}
@ -89,7 +128,15 @@ pub fn sys_vfork() -> i32 {
const CLONE_VFORK: usize = 0x00004000;
const CLONE_VM: usize = 0x00000100;
const SIGCHILD: usize = 17;
sys_call(SyscallId::Clone, CLONE_VFORK | CLONE_VM | SIGCHILD, sp, 0, 0, 0, 0)
sys_call(
SyscallId::Clone,
CLONE_VFORK | CLONE_VM | SIGCHILD,
sp,
0,
0,
0,
0,
)
}
/// Wait the process exit.
@ -122,13 +169,29 @@ pub fn sys_getcwd() -> String {
/// Change the current working directory
pub fn sys_chdir(path: &str) {
let path = String::from(path) + "\0";
sys_call(SyscallId::Chdir, path.as_bytes().as_ptr() as usize, 0, 0, 0, 0, 0);
sys_call(
SyscallId::Chdir,
path.as_bytes().as_ptr() as usize,
0,
0,
0,
0,
0,
);
}
/// Check file accessibility
pub fn sys_access(path: &str) -> i32 {
let path = String::from(path) + "\0";
sys_call(SyscallId::FAccessAt, -100isize as usize, path.as_bytes().as_ptr() as usize, 0, 0, 0, 0)
sys_call(
SyscallId::FAccessAt,
-100isize as usize,
path.as_bytes().as_ptr() as usize,
0,
0,
0,
0,
)
}
#[repr(C)]
@ -141,9 +204,17 @@ pub struct TimeSpec {
pub fn sys_sleep(time: usize) -> i32 {
let ts = TimeSpec {
sec: time as u64,
nsec: 0
nsec: 0,
};
sys_call(SyscallId::Sleep, &ts as *const TimeSpec as usize, 0, 0, 0, 0, 0)
sys_call(
SyscallId::Sleep,
&ts as *const TimeSpec as usize,
0,
0,
0,
0,
0,
)
}
pub fn sys_get_time() -> i32 {
@ -164,13 +235,59 @@ pub fn sys_map_pci_device(vendor: usize, product: usize) -> i32 {
pub fn sys_get_paddr(vaddr: &[u64], paddr: &mut [u64]) -> i32 {
assert_eq!(vaddr.len(), paddr.len());
sys_call(SyscallId::GetPaddr, vaddr.as_ptr() as usize, paddr.as_ptr() as usize, vaddr.len(), 0, 0, 0)
sys_call(
SyscallId::GetPaddr,
vaddr.as_ptr() as usize,
paddr.as_ptr() as usize,
vaddr.len(),
0,
0,
0,
)
}
pub fn sys_mmap(addr: usize, len: usize, prot: usize, flags: usize, fd: usize, offset: usize) -> i32 {
pub fn sys_mmap(
addr: usize,
len: usize,
prot: usize,
flags: usize,
fd: usize,
offset: usize,
) -> i32 {
sys_call(SyscallId::Mmap, addr, len, prot, flags, fd, offset)
}
pub fn sys_socket(domain: usize, socket_type: usize, protocol: usize) -> i32 {
sys_call(SyscallId::Socket, domain, socket_type, protocol, 0, 0, 0)
}
pub fn sys_setsockopt(fd: usize, level: usize, opt: usize, optval: usize, optlen: usize) -> i32 {
sys_call(SyscallId::SetSockOpt, fd, level, opt, optval, optlen, 0)
}
pub fn sys_sendto(
fd: usize,
base: *const u8,
len: usize,
flags: usize,
addr: usize,
addr_len: usize,
) -> i32 {
sys_call(
SyscallId::SendTo,
fd,
base as usize,
len,
flags,
addr,
addr_len,
)
}
pub fn sys_ioctl(fd: usize, request: usize, arg1: usize) -> i32 {
sys_call(SyscallId::Ioctl, fd, request, arg1, 0, 0, 0)
}
#[cfg(target_arch = "x86_64")]
#[allow(dead_code)]
enum SyscallId {
@ -181,9 +298,13 @@ enum SyscallId {
Seek = 8,
Mmap = 9,
Munmap = 11,
Ioctl = 16,
Yield = 24,
Sleep = 35,
GetPid = 39,
Socket = 41,
SendTo = 44,
SetSockOpt = 54,
Clone = 56,
Exec = 59,
Exit = 60,
@ -204,7 +325,52 @@ enum SyscallId {
GetPaddr = 998,
}
#[cfg(not(target_arch = "x86_64"))]
#[cfg(target_arch = "mips")]
pub fn sys_set_theaad_area(tls: usize) {
sys_call(SyscallId::SetThreadArea, tls, 0, 0, 0, 0, 0);
}
// only for mips N32 abi
// see https://git.linux-mips.org/cgit/ralf/linux.git/tree/arch/mips/include/uapi/asm/unistd.h
#[cfg(target_arch = "mips")]
#[allow(dead_code)]
enum SyscallId {
Read = 4003,
Write = 4004,
Close = 4006,
Fstat = 4198,
Seek = 4018,
Mmap = 4090,
Munmap = 4091,
Ioctl = 4054,
Yield = 4162,
Sleep = 4166,
GetPid = 4020,
Socket = 4183,
SendTo = 4180,
SetSockOpt = 4181,
Clone = 4120,
Exec = 4011,
Exit = 4001,
Wait = 4114,
Kill = 4037,
Fsync = 4118,
GetCwd = 4203,
Chdir = 4012,
GetTime = 4078,
SetPriority = 4097,
SetThreadArea = 4283,
ArchPrctl = -1,
GetDirEntry64 = 4219,
Openat = 4288,
FAccessAt = 4300,
Dup3 = 4327,
// custom
MapPciDevice = 999,
GetPaddr = 998,
}
#[cfg(not(any(target_arch = "x86_64", target_arch = "mips")))]
#[allow(dead_code)]
enum SyscallId {
Read = 63,
@ -214,7 +380,11 @@ enum SyscallId {
Seek = 62,
Mmap = 222,
Munmap = 215,
Ioctl = 29,
Yield = 124,
Socket = 198,
SendTo = 206,
SetSockOpt = 208,
Sleep = 101,
GetPid = 172,
Clone = 220,

@ -0,0 +1,32 @@
{
"arch": "mips",
"cpu": "mips32r2",
"llvm-target": "mipsel-unknown-none",
"data-layout": "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64",
"target-endian": "little",
"target-pointer-width": "32",
"target-c-int-width": "32",
"os": "none",
"features": "+mips32r2,+soft-float",
"max-atomic-width": "32",
"linker": "rust-lld",
"linker-flavor": "ld.lld",
"executables": true,
"panic-strategy": "abort",
"relocation-model": "static",
"abi-blacklist": [
"cdecl",
"stdcall",
"fastcall",
"vectorcall",
"thiscall",
"aapcs",
"win64",
"sysv64",
"ptx-kernel",
"msp430-interrupt",
"x86-interrupt"
],
"eliminate-frame-pointer": false
}

Binary file not shown.

@ -0,0 +1,6 @@
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World");
}
}

@ -0,0 +1,27 @@
/* sbrk and brk example */
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main(int argc, char ** argv)
{
int *curr_brk, *tmp_brk = NULL;
int num,i;
if(argc >1) { num=atoi(argv[1]);}
printf("Welcome to sbrk example:%d num %d\n", getpid(),num);
for(i=0;i<num;i++) {
/* sbrk(0) gives current program break location */
tmp_brk = curr_brk = sbrk(0);
printf("%d: Program Break Location1:%p\n", i, curr_brk);
/* brk(addr) increments/decrements program break location */
brk((char*)curr_brk + 4096);
curr_brk = sbrk(0);
printf("%d: Program break Location2:%p\n", i, curr_brk);
*(curr_brk-20)=1;
// brk(tmp_brk);
// curr_brk = sbrk(0);
// printf("Program Break Location3:%p\n", curr_brk);
}
return 0;
}

@ -0,0 +1,18 @@
#define _GNU_SOURCE
#include <assert.h>
#include <unistd.h>
int main(void) {
void *b;
char *p, *end;
b = sbrk(0);
p = (char *)b;
end = p + 0x1000000;
brk(end);
while (p < end) {
*(p++) = 1;
}
brk(b);
return 0;
}

@ -0,0 +1,10 @@
gcc -c dlmain.c -o dlmain.o
gcc -c func.c -o func.o
cc -shared -fPIC func.c -o libfunc.so
gcc dlmain.c libfunc.so -o dlmain
go build hello.go
javac HelloWorld.java
#java HelloWorld

Binary file not shown.

@ -0,0 +1,6 @@
#include "func.h"
int main()
{
func();
return 0;
}

Binary file not shown.

@ -0,0 +1,26 @@
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
extern char **environ;
char **env ;
int main()
{
env= environ;
while(*environ){
puts(*environ);
environ++;
}
char * p;
puts("----------------------\n");
if((p=getenv("USER")))
printf("USER =%s\n",p);
setenv("USER","test",1);
printf("USER=%s\n",getenv("USER"));
//unsetenv("USER");
//printf("USER=%s\n",getenv("USER"));
char * argv[]={"env2", NULL};
execve("./env2",argv,env);
return 0;
}

Binary file not shown.

@ -0,0 +1,26 @@
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
extern char **environ;
char **env ;
int main()
{
env= environ;
while(*environ){
puts(*environ);
environ++;
}
char * p;
puts("----------------------\n");
if((p=getenv("USER")))
printf("USER =%s\n",p);
setenv("USER","test",1);
printf("USER=%s\n",getenv("USER"));
//unsetenv("USER");
//printf("USER=%s\n",getenv("USER"));
char * argv[]={"env2", NULL};
execve("./env2",argv,env);
return 0;
}

@ -0,0 +1,490 @@
# 1 "env1.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "env1.c"
# 1 "/usr/include/stdlib.h" 1 3 4
# 1 "/usr/include/features.h" 1 3 4
# 9 "/usr/include/stdlib.h" 2 3 4
# 19 "/usr/include/stdlib.h" 3 4
# 1 "/usr/include/bits/alltypes.h" 1 3 4
# 18 "/usr/include/bits/alltypes.h" 3 4
# 18 "/usr/include/bits/alltypes.h" 3 4
typedef int wchar_t;
# 101 "/usr/include/bits/alltypes.h" 3 4
typedef unsigned long size_t;
# 20 "/usr/include/stdlib.h" 2 3 4
int atoi (const char *);
long atol (const char *);
long long atoll (const char *);
double atof (const char *);
float strtof (const char *restrict, char **restrict);
double strtod (const char *restrict, char **restrict);
long double strtold (const char *restrict, char **restrict);
long strtol (const char *restrict, char **restrict, int);
unsigned long strtoul (const char *restrict, char **restrict, int);
long long strtoll (const char *restrict, char **restrict, int);
unsigned long long strtoull (const char *restrict, char **restrict, int);
int rand (void);
void srand (unsigned);
void *malloc (size_t);
void *calloc (size_t, size_t);
void *realloc (void *, size_t);
void free (void *);
void *aligned_alloc(size_t, size_t);
_Noreturn void abort (void);
int atexit (void (*) (void));
_Noreturn void exit (int);
_Noreturn void _Exit (int);
int at_quick_exit (void (*) (void));
_Noreturn void quick_exit (int);
char *getenv (const char *);
int system (const char *);
void *bsearch (const void *, const void *, size_t, size_t, int (*)(const void *, const void *));
void qsort (void *, size_t, size_t, int (*)(const void *, const void *));
int abs (int);
long labs (long);
long long llabs (long long);
typedef struct { int quot, rem; } div_t;
typedef struct { long quot, rem; } ldiv_t;
typedef struct { long long quot, rem; } lldiv_t;
div_t div (int, int);
ldiv_t ldiv (long, long);
lldiv_t lldiv (long long, long long);
int mblen (const char *, size_t);
int mbtowc (wchar_t *restrict, const char *restrict, size_t);
int wctomb (char *, wchar_t);
size_t mbstowcs (wchar_t *restrict, const char *restrict, size_t);
size_t wcstombs (char *restrict, const wchar_t *restrict, size_t);
size_t __ctype_get_mb_cur_max(void);
# 99 "/usr/include/stdlib.h" 3 4
int posix_memalign (void **, size_t, size_t);
int setenv (const char *, const char *, int);
int unsetenv (const char *);
int mkstemp (char *);
int mkostemp (char *, int);
char *mkdtemp (char *);
int getsubopt (char **, char *const *, char **);
int rand_r (unsigned *);
char *realpath (const char *restrict, char *restrict);
long int random (void);
void srandom (unsigned int);
char *initstate (unsigned int, char *, size_t);
char *setstate (char *);
int putenv (char *);
int posix_openpt (int);
int grantpt (int);
int unlockpt (int);
char *ptsname (int);
char *l64a (long);
long a64l (const char *);
void setkey (const char *);
double drand48 (void);
double erand48 (unsigned short [3]);
long int lrand48 (void);
long int nrand48 (unsigned short [3]);
long mrand48 (void);
long jrand48 (unsigned short [3]);
void srand48 (long);
unsigned short *seed48 (unsigned short [3]);
void lcong48 (unsigned short [7]);
# 1 "/usr/include/alloca.h" 1 3 4
# 9 "/usr/include/alloca.h" 3 4
# 1 "/usr/include/bits/alltypes.h" 1 3 4
# 10 "/usr/include/alloca.h" 2 3 4
void *alloca(size_t);
# 139 "/usr/include/stdlib.h" 2 3 4
char *mktemp (char *);
int mkstemps (char *, int);
int mkostemps (char *, int, int);
void *valloc (size_t);
void *memalign(size_t, size_t);
int getloadavg(double *, int);
int clearenv(void);
# 2 "env1.c" 2
# 1 "/usr/include/stdio.h" 1 3 4
# 22 "/usr/include/stdio.h" 3 4
# 1 "/usr/include/bits/alltypes.h" 1 3 4
typedef __builtin_va_list va_list;
typedef __builtin_va_list __isoc_va_list;
# 116 "/usr/include/bits/alltypes.h" 3 4
typedef long ssize_t;
# 203 "/usr/include/bits/alltypes.h" 3 4
typedef long off_t;
# 356 "/usr/include/bits/alltypes.h" 3 4
typedef struct _IO_FILE FILE;
# 23 "/usr/include/stdio.h" 2 3 4
# 50 "/usr/include/stdio.h" 3 4
typedef union _G_fpos64_t {
char __opaque[16];
long long __lldata;
double __align;
} fpos_t;
extern FILE *const stdin;
extern FILE *const stdout;
extern FILE *const stderr;
FILE *fopen(const char *restrict, const char *restrict);
FILE *freopen(const char *restrict, const char *restrict, FILE *restrict);
int fclose(FILE *);
int remove(const char *);
int rename(const char *, const char *);
int feof(FILE *);
int ferror(FILE *);
int fflush(FILE *);
void clearerr(FILE *);
int fseek(FILE *, long, int);
long ftell(FILE *);
void rewind(FILE *);
int fgetpos(FILE *restrict, fpos_t *restrict);
int fsetpos(FILE *, const fpos_t *);
size_t fread(void *restrict, size_t, size_t, FILE *restrict);
size_t fwrite(const void *restrict, size_t, size_t, FILE *restrict);
int fgetc(FILE *);
int getc(FILE *);
int getchar(void);
int ungetc(int, FILE *);
int fputc(int, FILE *);
int putc(int, FILE *);
int putchar(int);
char *fgets(char *restrict, int, FILE *restrict);
int fputs(const char *restrict, FILE *restrict);
int puts(const char *);
int printf(const char *restrict, ...);
int fprintf(FILE *restrict, const char *restrict, ...);
int sprintf(char *restrict, const char *restrict, ...);
int snprintf(char *restrict, size_t, const char *restrict, ...);
int vprintf(const char *restrict, __isoc_va_list);
int vfprintf(FILE *restrict, const char *restrict, __isoc_va_list);
int vsprintf(char *restrict, const char *restrict, __isoc_va_list);
int vsnprintf(char *restrict, size_t, const char *restrict, __isoc_va_list);
int scanf(const char *restrict, ...);
int fscanf(FILE *restrict, const char *restrict, ...);
int sscanf(const char *restrict, const char *restrict, ...);
int vscanf(const char *restrict, __isoc_va_list);
int vfscanf(FILE *restrict, const char *restrict, __isoc_va_list);
int vsscanf(const char *restrict, const char *restrict, __isoc_va_list);
void perror(const char *);
int setvbuf(FILE *restrict, char *restrict, int, size_t);
void setbuf(FILE *restrict, char *restrict);
char *tmpnam(char *);
FILE *tmpfile(void);
FILE *fmemopen(void *restrict, size_t, const char *restrict);
FILE *open_memstream(char **, size_t *);
FILE *fdopen(int, const char *);
FILE *popen(const char *, const char *);
int pclose(FILE *);
int fileno(FILE *);
int fseeko(FILE *, off_t, int);
off_t ftello(FILE *);
int dprintf(int, const char *restrict, ...);
int vdprintf(int, const char *restrict, __isoc_va_list);
void flockfile(FILE *);
int ftrylockfile(FILE *);
void funlockfile(FILE *);
int getc_unlocked(FILE *);
int getchar_unlocked(void);
int putc_unlocked(int, FILE *);
int putchar_unlocked(int);
ssize_t getdelim(char **restrict, size_t *restrict, int, FILE *restrict);
ssize_t getline(char **restrict, size_t *restrict, FILE *restrict);
int renameat(int, const char *, int, const char *);
char *ctermid(char *);
char *tempnam(const char *, const char *);
char *cuserid(char *);
void setlinebuf(FILE *);
void setbuffer(FILE *, char *, size_t);
int fgetc_unlocked(FILE *);
int fputc_unlocked(int, FILE *);
int fflush_unlocked(FILE *);
size_t fread_unlocked(void *, size_t, size_t, FILE *);
size_t fwrite_unlocked(const void *, size_t, size_t, FILE *);
void clearerr_unlocked(FILE *);
int feof_unlocked(FILE *);
int ferror_unlocked(FILE *);
int fileno_unlocked(FILE *);
int getw(FILE *);
int putw(int, FILE *);
char *fgetln(FILE *, size_t *);
int asprintf(char **, const char *, ...);
int vasprintf(char **, const char *, __isoc_va_list);
# 3 "env1.c" 2
# 1 "/usr/include/unistd.h" 1 3 4
# 33 "/usr/include/unistd.h" 3 4
# 1 "/usr/include/bits/alltypes.h" 1 3 4
# 121 "/usr/include/bits/alltypes.h" 3 4
typedef long intptr_t;
# 276 "/usr/include/bits/alltypes.h" 3 4
typedef int pid_t;
# 286 "/usr/include/bits/alltypes.h" 3 4
typedef unsigned uid_t;
typedef unsigned gid_t;
# 301 "/usr/include/bits/alltypes.h" 3 4
typedef unsigned useconds_t;
# 34 "/usr/include/unistd.h" 2 3 4
int pipe(int [2]);
int pipe2(int [2], int);
int close(int);
int posix_close(int, int);
int dup(int);
int dup2(int, int);
int dup3(int, int, int);
off_t lseek(int, off_t, int);
int fsync(int);
int fdatasync(int);
ssize_t read(int, void *, size_t);
ssize_t write(int, const void *, size_t);
ssize_t pread(int, void *, size_t, off_t);
ssize_t pwrite(int, const void *, size_t, off_t);
int chown(const char *, uid_t, gid_t);
int fchown(int, uid_t, gid_t);
int lchown(const char *, uid_t, gid_t);
int fchownat(int, const char *, uid_t, gid_t, int);
int link(const char *, const char *);
int linkat(int, const char *, int, const char *, int);
int symlink(const char *, const char *);
int symlinkat(const char *, int, const char *);
ssize_t readlink(const char *restrict, char *restrict, size_t);
ssize_t readlinkat(int, const char *restrict, char *restrict, size_t);
int unlink(const char *);
int unlinkat(int, const char *, int);
int rmdir(const char *);
int truncate(const char *, off_t);
int ftruncate(int, off_t);
int access(const char *, int);
int faccessat(int, const char *, int, int);
int chdir(const char *);
int fchdir(int);
char *getcwd(char *, size_t);
unsigned alarm(unsigned);
unsigned sleep(unsigned);
int pause(void);
pid_t fork(void);
int execve(const char *, char *const [], char *const []);
int execv(const char *, char *const []);
int execle(const char *, const char *, ...);
int execl(const char *, const char *, ...);
int execvp(const char *, char *const []);
int execlp(const char *, const char *, ...);
int fexecve(int, char *const [], char *const []);
_Noreturn void _exit(int);
pid_t getpid(void);
pid_t getppid(void);
pid_t getpgrp(void);
pid_t getpgid(pid_t);
int setpgid(pid_t, pid_t);
pid_t setsid(void);
pid_t getsid(pid_t);
char *ttyname(int);
int ttyname_r(int, char *, size_t);
int isatty(int);
pid_t tcgetpgrp(int);
int tcsetpgrp(int, pid_t);
uid_t getuid(void);
uid_t geteuid(void);
gid_t getgid(void);
gid_t getegid(void);
int getgroups(int, gid_t []);
int setuid(uid_t);
int seteuid(uid_t);
int setgid(gid_t);
int setegid(gid_t);
char *getlogin(void);
int getlogin_r(char *, size_t);
int gethostname(char *, size_t);
char *ctermid(char *);
int getopt(int, char * const [], const char *);
extern char *optarg;
extern int optind, opterr, optopt;
long pathconf(const char *, int);
long fpathconf(int, int);
long sysconf(int);
size_t confstr(int, char *, size_t);
int setreuid(uid_t, uid_t);
int setregid(gid_t, gid_t);
int lockf(int, int, off_t);
long gethostid(void);
int nice(int);
void sync(void);
pid_t setpgrp(void);
char *crypt(const char *, const char *);
void encrypt(char *, int);
void swab(const void *restrict, void *restrict, ssize_t);
int usleep(unsigned);
unsigned ualarm(unsigned, unsigned);
int brk(void *);
void *sbrk(intptr_t);
pid_t vfork(void);
int vhangup(void);
int chroot(const char *);
int getpagesize(void);
int getdtablesize(void);
int sethostname(const char *, size_t);
int getdomainname(char *, size_t);
int setdomainname(const char *, size_t);
int setgroups(size_t, const gid_t *);
char *getpass(const char *);
int daemon(int, int);
void setusershell(void);
void endusershell(void);
char *getusershell(void);
int acct(const char *);
long syscall(long, ...);
int execvpe(const char *, char *const [], char *const []);
int issetugid(void);
int getentropy(void *, size_t);
# 252 "/usr/include/unistd.h" 3 4
# 1 "/usr/include/bits/posix.h" 1 3 4
# 253 "/usr/include/unistd.h" 2 3 4
# 4 "env1.c" 2
# 5 "env1.c"
extern char **environ;
char **env ;
int main()
{
env= environ;
while(*environ){
puts(*environ);
environ++;
}
char * p;
puts("----------------------\n");
if((p=getenv("USER")))
printf("USER =%s\n",p);
setenv("USER","test",1);
printf("USER=%s\n",getenv("USER"));
char * argv[]={"env2",
# 23 "env1.c" 3 4
((void*)0)
# 23 "env1.c"
};
execve("./env2",argv,env);
return 0;
}

Binary file not shown.

@ -0,0 +1,94 @@
.file "env1.c"
.text
.comm env,8,8
.section .rodata
.LC0:
.string "----------------------\n"
.LC1:
.string "USER"
.LC2:
.string "USER =%s\n"
.LC3:
.string "test"
.LC4:
.string "USER=%s\n"
.LC5:
.string "env2"
.LC6:
.string "./env2"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $48, %rsp
movq %fs:40, %rax
movq %rax, -8(%rbp)
xorl %eax, %eax
movq environ(%rip), %rax
movq %rax, env(%rip)
jmp .L2
.L3:
movq environ(%rip), %rax
movq (%rax), %rax
movq %rax, %rdi
call puts@PLT
movq environ(%rip), %rax
addq $8, %rax
movq %rax, environ(%rip)
.L2:
movq environ(%rip), %rax
movq (%rax), %rax
testq %rax, %rax
jne .L3
leaq .LC0(%rip), %rdi
call puts@PLT
leaq .LC1(%rip), %rdi
call getenv@PLT
movq %rax, -40(%rbp)
cmpq $0, -40(%rbp)
je .L4
movq -40(%rbp), %rax
movq %rax, %rsi
leaq .LC2(%rip), %rdi
movl $0, %eax
call printf@PLT
.L4:
movl $1, %edx
leaq .LC3(%rip), %rsi
leaq .LC1(%rip), %rdi
call setenv@PLT
leaq .LC1(%rip), %rdi
call getenv@PLT
movq %rax, %rsi
leaq .LC4(%rip), %rdi
movl $0, %eax
call printf@PLT
leaq .LC5(%rip), %rax
movq %rax, -32(%rbp)
movq $0, -24(%rbp)
movq env(%rip), %rdx
leaq -32(%rbp), %rax
movq %rax, %rsi
leaq .LC6(%rip), %rdi
call execve@PLT
movl $0, %eax
movq -8(%rbp), %rcx
xorq %fs:40, %rcx
je .L6
call __stack_chk_fail@PLT
.L6:
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Alpine 8.2.0) 8.2.0"
.section .note.GNU-stack,"",@progbits

Binary file not shown.

@ -0,0 +1,25 @@
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
//extern char **environ;
//char **env = environ;
int main(int argc, char * argv [] , char ** environ)
{
puts("child, evn2----------------------\n");
while(*environ){
puts(*environ);
environ++;
}
char * p;
puts("----------------------\n");
if((p=getenv("USER")))
printf("USER =%s\n",p);
setenv("USER","TEST",1);
printf("USER=%s\n",getenv("USER"));
unsetenv("USER");
printf("USER=%s\n",getenv("USER"));
setenv("USER","TEST",1);
return 0;
}

@ -0,0 +1,243 @@
env2: file format elf64-x86-64
Disassembly of section .init:
0000000000001000 <_init>:
1000: 50 push %rax
1001: e8 ad 01 00 00 callq 11b3 <frame_dummy>
1006: e8 ce 02 00 00 callq 12d9 <__do_global_ctors_aux>
100b: 58 pop %rax
100c: c3 retq
Disassembly of section .plt:
0000000000001010 <.plt>:
1010: ff 35 82 2f 00 00 pushq 0x2f82(%rip) # 3f98 <_GLOBAL_OFFSET_TABLE_+0x8>
1016: ff 25 84 2f 00 00 jmpq *0x2f84(%rip) # 3fa0 <_GLOBAL_OFFSET_TABLE_+0x10>
101c: 0f 1f 40 00 nopl 0x0(%rax)
0000000000001020 <unsetenv@plt>:
1020: ff 25 82 2f 00 00 jmpq *0x2f82(%rip) # 3fa8 <unsetenv>
1026: 68 00 00 00 00 pushq $0x0
102b: e9 e0 ff ff ff jmpq 1010 <.plt>
0000000000001030 <printf@plt>:
1030: ff 25 7a 2f 00 00 jmpq *0x2f7a(%rip) # 3fb0 <printf>
1036: 68 01 00 00 00 pushq $0x1
103b: e9 d0 ff ff ff jmpq 1010 <.plt>
0000000000001040 <getenv@plt>:
1040: ff 25 72 2f 00 00 jmpq *0x2f72(%rip) # 3fb8 <getenv>
1046: 68 02 00 00 00 pushq $0x2
104b: e9 c0 ff ff ff jmpq 1010 <.plt>
0000000000001050 <puts@plt>:
1050: ff 25 6a 2f 00 00 jmpq *0x2f6a(%rip) # 3fc0 <puts>
1056: 68 03 00 00 00 pushq $0x3
105b: e9 b0 ff ff ff jmpq 1010 <.plt>
0000000000001060 <setenv@plt>:
1060: ff 25 62 2f 00 00 jmpq *0x2f62(%rip) # 3fc8 <setenv>
1066: 68 04 00 00 00 pushq $0x4
106b: e9 a0 ff ff ff jmpq 1010 <.plt>
0000000000001070 <__libc_start_main@plt>:
1070: ff 25 5a 2f 00 00 jmpq *0x2f5a(%rip) # 3fd0 <__libc_start_main>
1076: 68 05 00 00 00 pushq $0x5
107b: e9 90 ff ff ff jmpq 1010 <.plt>
Disassembly of section .plt.got:
0000000000001080 <__cxa_finalize@plt>:
1080: ff 25 52 2f 00 00 jmpq *0x2f52(%rip) # 3fd8 <__cxa_finalize>
1086: 66 90 xchg %ax,%ax
0000000000001088 <__deregister_frame_info@plt>:
1088: ff 25 52 2f 00 00 jmpq *0x2f52(%rip) # 3fe0 <__deregister_frame_info>
108e: 66 90 xchg %ax,%ax
0000000000001090 <__register_frame_info@plt>:
1090: ff 25 62 2f 00 00 jmpq *0x2f62(%rip) # 3ff8 <__register_frame_info>
1096: 66 90 xchg %ax,%ax
Disassembly of section .text:
0000000000001098 <_start>:
1098: 48 31 ed xor %rbp,%rbp
109b: 48 89 e7 mov %rsp,%rdi
109e: 48 8d 35 6b 2d 00 00 lea 0x2d6b(%rip),%rsi # 3e10 <_DYNAMIC>
10a5: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp
10a9: e8 00 00 00 00 callq 10ae <_start_c>
00000000000010ae <_start_c>:
10ae: 50 push %rax
10af: 48 8d 57 08 lea 0x8(%rdi),%rdx
10b3: 48 8b 37 mov (%rdi),%rsi
10b6: 45 31 c9 xor %r9d,%r9d
10b9: 4c 8d 05 3b 02 00 00 lea 0x23b(%rip),%r8 # 12fb <_fini>
10c0: 48 8d 0d 39 ff ff ff lea -0xc7(%rip),%rcx # 1000 <_init>
10c7: 48 8d 3d 0c 01 00 00 lea 0x10c(%rip),%rdi # 11da <main>
10ce: e8 9d ff ff ff callq 1070 <__libc_start_main@plt>
00000000000010d3 <deregister_tm_clones>:
10d3: 48 8d 3d 2e 2f 00 00 lea 0x2f2e(%rip),%rdi # 4008 <__TMC_END__>
10da: 48 8d 05 27 2f 00 00 lea 0x2f27(%rip),%rax # 4008 <__TMC_END__>
10e1: 48 39 f8 cmp %rdi,%rax
10e4: 74 0e je 10f4 <deregister_tm_clones+0x21>
10e6: 48 8b 05 03 2f 00 00 mov 0x2f03(%rip),%rax # 3ff0 <_ITM_deregisterTMCloneTable>
10ed: 48 85 c0 test %rax,%rax
10f0: 74 02 je 10f4 <deregister_tm_clones+0x21>
10f2: ff e0 jmpq *%rax
10f4: c3 retq
00000000000010f5 <register_tm_clones>:
10f5: 48 8d 3d 0c 2f 00 00 lea 0x2f0c(%rip),%rdi # 4008 <__TMC_END__>
10fc: 48 8d 35 05 2f 00 00 lea 0x2f05(%rip),%rsi # 4008 <__TMC_END__>
1103: b9 02 00 00 00 mov $0x2,%ecx
1108: 48 29 fe sub %rdi,%rsi
110b: 48 c1 fe 03 sar $0x3,%rsi
110f: 48 89 f0 mov %rsi,%rax
1112: 48 99 cqto
1114: 48 f7 f9 idiv %rcx
1117: 48 89 c6 mov %rax,%rsi
111a: 48 85 c0 test %rax,%rax
111d: 74 0e je 112d <register_tm_clones+0x38>
111f: 48 8b 05 c2 2e 00 00 mov 0x2ec2(%rip),%rax # 3fe8 <_ITM_registerTMCloneTable>
1126: 48 85 c0 test %rax,%rax
1129: 74 02 je 112d <register_tm_clones+0x38>
112b: ff e0 jmpq *%rax
112d: c3 retq
000000000000112e <__do_global_dtors_aux>:
112e: 80 3d eb 2e 00 00 00 cmpb $0x0,0x2eeb(%rip) # 4020 <completed.6136>
1135: 75 7b jne 11b2 <__do_global_dtors_aux+0x84>
1137: 55 push %rbp
1138: 48 83 3d 98 2e 00 00 cmpq $0x0,0x2e98(%rip) # 3fd8 <__cxa_finalize>
113f: 00
1140: 48 89 e5 mov %rsp,%rbp
1143: 41 54 push %r12
1145: 53 push %rbx
1146: 74 0c je 1154 <__do_global_dtors_aux+0x26>
1148: 48 8b 3d b1 2e 00 00 mov 0x2eb1(%rip),%rdi # 4000 <__dso_handle>
114f: e8 2c ff ff ff callq 1080 <__cxa_finalize@plt>
1154: 48 8d 05 a5 2c 00 00 lea 0x2ca5(%rip),%rax # 3e00 <__DTOR_LIST__>
115b: 48 8d 1d a6 2c 00 00 lea 0x2ca6(%rip),%rbx # 3e08 <__DTOR_END__>
1162: 48 29 c3 sub %rax,%rbx
1165: 49 89 c4 mov %rax,%r12
1168: 48 c1 fb 03 sar $0x3,%rbx
116c: 48 ff cb dec %rbx
116f: 48 8b 05 b2 2e 00 00 mov 0x2eb2(%rip),%rax # 4028 <dtor_idx.6138>
1176: 48 39 d8 cmp %rbx,%rax
1179: 73 10 jae 118b <__do_global_dtors_aux+0x5d>
117b: 48 ff c0 inc %rax
117e: 48 89 05 a3 2e 00 00 mov %rax,0x2ea3(%rip) # 4028 <dtor_idx.6138>
1185: 41 ff 14 c4 callq *(%r12,%rax,8)
1189: eb e4 jmp 116f <__do_global_dtors_aux+0x41>
118b: e8 43 ff ff ff callq 10d3 <deregister_tm_clones>
1190: 48 83 3d 48 2e 00 00 cmpq $0x0,0x2e48(%rip) # 3fe0 <__deregister_frame_info>
1197: 00
1198: 74 0c je 11a6 <__do_global_dtors_aux+0x78>
119a: 48 8d 3d 37 0f 00 00 lea 0xf37(%rip),%rdi # 20d8 <__EH_FRAME_BEGIN__>
11a1: e8 e2 fe ff ff callq 1088 <__deregister_frame_info@plt>
11a6: 5b pop %rbx
11a7: 41 5c pop %r12
11a9: c6 05 70 2e 00 00 01 movb $0x1,0x2e70(%rip) # 4020 <completed.6136>
11b0: 5d pop %rbp
11b1: c3 retq
11b2: c3 retq
00000000000011b3 <frame_dummy>:
11b3: 48 83 3d 3d 2e 00 00 cmpq $0x0,0x2e3d(%rip) # 3ff8 <__register_frame_info>
11ba: 00
11bb: 74 18 je 11d5 <frame_dummy+0x22>
11bd: 55 push %rbp
11be: 48 8d 35 7b 2e 00 00 lea 0x2e7b(%rip),%rsi # 4040 <object.6148>
11c5: 48 8d 3d 0c 0f 00 00 lea 0xf0c(%rip),%rdi # 20d8 <__EH_FRAME_BEGIN__>
11cc: 48 89 e5 mov %rsp,%rbp
11cf: e8 bc fe ff ff callq 1090 <__register_frame_info@plt>
11d4: 5d pop %rbp
11d5: e9 1b ff ff ff jmpq 10f5 <register_tm_clones>
00000000000011da <main>:
11da: 55 push %rbp
11db: 48 89 e5 mov %rsp,%rbp
11de: 48 83 ec 30 sub $0x30,%rsp
11e2: 89 7d ec mov %edi,-0x14(%rbp)
11e5: 48 89 75 e0 mov %rsi,-0x20(%rbp)
11e9: 48 89 55 d8 mov %rdx,-0x28(%rbp)
11ed: 48 8d 3d 0c 0e 00 00 lea 0xe0c(%rip),%rdi # 2000 <_fini+0xd05>
11f4: e8 57 fe ff ff callq 1050 <puts@plt>
11f9: eb 14 jmp 120f <main+0x35>
11fb: 48 8b 45 d8 mov -0x28(%rbp),%rax
11ff: 48 8b 00 mov (%rax),%rax
1202: 48 89 c7 mov %rax,%rdi
1205: e8 46 fe ff ff callq 1050 <puts@plt>
120a: 48 83 45 d8 08 addq $0x8,-0x28(%rbp)
120f: 48 8b 45 d8 mov -0x28(%rbp),%rax
1213: 48 8b 00 mov (%rax),%rax
1216: 48 85 c0 test %rax,%rax
1219: 75 e0 jne 11fb <main+0x21>
121b: 48 8d 3d 01 0e 00 00 lea 0xe01(%rip),%rdi # 2023 <_fini+0xd28>
1222: e8 29 fe ff ff callq 1050 <puts@plt>
1227: 48 8d 3d 0d 0e 00 00 lea 0xe0d(%rip),%rdi # 203b <_fini+0xd40>
122e: e8 0d fe ff ff callq 1040 <getenv@plt>
1233: 48 89 45 f8 mov %rax,-0x8(%rbp)
1237: 48 83 7d f8 00 cmpq $0x0,-0x8(%rbp)
123c: 74 18 je 1256 <main+0x7c>
123e: 48 8b 45 f8 mov -0x8(%rbp),%rax
1242: 48 89 c6 mov %rax,%rsi
1245: 48 8d 3d f4 0d 00 00 lea 0xdf4(%rip),%rdi # 2040 <_fini+0xd45>
124c: b8 00 00 00 00 mov $0x0,%eax
1251: e8 da fd ff ff callq 1030 <printf@plt>
1256: ba 01 00 00 00 mov $0x1,%edx
125b: 48 8d 35 e8 0d 00 00 lea 0xde8(%rip),%rsi # 204a <_fini+0xd4f>
1262: 48 8d 3d d2 0d 00 00 lea 0xdd2(%rip),%rdi # 203b <_fini+0xd40>
1269: e8 f2 fd ff ff callq 1060 <setenv@plt>
126e: 48 8d 3d c6 0d 00 00 lea 0xdc6(%rip),%rdi # 203b <_fini+0xd40>
1275: e8 c6 fd ff ff callq 1040 <getenv@plt>
127a: 48 89 c6 mov %rax,%rsi
127d: 48 8d 3d cb 0d 00 00 lea 0xdcb(%rip),%rdi # 204f <_fini+0xd54>
1284: b8 00 00 00 00 mov $0x0,%eax
1289: e8 a2 fd ff ff callq 1030 <printf@plt>
128e: 48 8d 3d a6 0d 00 00 lea 0xda6(%rip),%rdi # 203b <_fini+0xd40>
1295: e8 86 fd ff ff callq 1020 <unsetenv@plt>
129a: 48 8d 3d 9a 0d 00 00 lea 0xd9a(%rip),%rdi # 203b <_fini+0xd40>
12a1: e8 9a fd ff ff callq 1040 <getenv@plt>
12a6: 48 89 c6 mov %rax,%rsi
12a9: 48 8d 3d 9f 0d 00 00 lea 0xd9f(%rip),%rdi # 204f <_fini+0xd54>
12b0: b8 00 00 00 00 mov $0x0,%eax
12b5: e8 76 fd ff ff callq 1030 <printf@plt>
12ba: ba 01 00 00 00 mov $0x1,%edx
12bf: 48 8d 35 84 0d 00 00 lea 0xd84(%rip),%rsi # 204a <_fini+0xd4f>
12c6: 48 8d 3d 6e 0d 00 00 lea 0xd6e(%rip),%rdi # 203b <_fini+0xd40>
12cd: e8 8e fd ff ff callq 1060 <setenv@plt>
12d2: b8 00 00 00 00 mov $0x0,%eax
12d7: c9 leaveq
12d8: c3 retq
00000000000012d9 <__do_global_ctors_aux>:
12d9: 55 push %rbp
12da: 48 89 e5 mov %rsp,%rbp
12dd: 53 push %rbx
12de: 48 8d 1d 0b 2b 00 00 lea 0x2b0b(%rip),%rbx # 3df0 <__CTOR_LIST__>
12e5: 52 push %rdx
12e6: 48 8b 03 mov (%rbx),%rax
12e9: 48 83 f8 ff cmp $0xffffffffffffffff,%rax
12ed: 74 08 je 12f7 <__do_global_ctors_aux+0x1e>
12ef: ff d0 callq *%rax
12f1: 48 83 eb 08 sub $0x8,%rbx
12f5: eb ef jmp 12e6 <__do_global_ctors_aux+0xd>
12f7: 58 pop %rax
12f8: 5b pop %rbx
12f9: 5d pop %rbp
12fa: c3 retq
Disassembly of section .fini:
00000000000012fb <_fini>:
12fb: 50 push %rax
12fc: e8 2d fe ff ff callq 112e <__do_global_dtors_aux>
1301: 58 pop %rax
1302: c3 retq

Binary file not shown.

@ -0,0 +1,32 @@
#include <stdio.h>
int main()
{
int child, grandson;
char *sargs[] = { "/bin/echo", "Son ", "Hello", "World!", NULL};
char *gargs[] = { "/bin/echo", "Grandson ", "Hello", "World!", NULL};
if (!(child = fork()))
{
/* child */
printf("child:s1: pid %d: %d is my father\n", getpid(), getppid());
if(!(grandson=fork()))
{
printf("grandson: pid %d: %d is my father\n", getpid(), getppid());
execve("/bin/echo", gargs, NULL);
printf("pid %d: I am back, something is wrong!\n", getpid());
}else{
printf("child:s2: pid %d: %d is my father\n", getpid(), getppid());
wait4(grandson, NULL, 0, NULL);
execve("/bin/echo", sargs, NULL);
printf("pid %d: I am back, something is wrong!\n", getpid());
}
}
else
{
int myself = getpid();
printf("parent: pid %d: %d is my son\n", myself, child);
wait4(child, NULL, 0, NULL);
printf("pid %d: done\n", myself);
}
return 0;
}

Binary file not shown.

Binary file not shown.

@ -0,0 +1,38 @@
#include <stdio.h>
#include <string.h>
#define DEPTH 4
#define SLEEP_TIME 1
void forktree(const char *cur);
void
forkchild(const char *cur, char branch) {
char nxt[DEPTH + 1];
if (strlen(cur) >= DEPTH)
return;
snprintf(nxt, DEPTH + 1, "%s%c", cur, branch);
if (fork() == 0) {
forktree(nxt);
//yield();
exit(0);
}
}
void
forktree(const char *cur) {
printf("%04x: I am '%s'\n", getpid(), cur);
forkchild(cur, '0');
forkchild(cur, '1');
}
int
main(void) {
printf("forktree process will sleep %d ticks\n",SLEEP_TIME);
sleep(SLEEP_TIME);
forktree("");
return 0;
}

@ -0,0 +1,5 @@
#include "func.h"
void func()
{
printf("Hello World!\n");
}

@ -0,0 +1,5 @@
#ifndef __FUNC_H
#define __FUNC_H
#include<stdio.h>
void func();
#endif

Binary file not shown.

@ -0,0 +1,5 @@
package main
import "fmt"
func main() {
fmt.Println("hello world")
}

@ -0,0 +1 @@
print("Hello World")

@ -0,0 +1 @@
print "Hello, World!"

@ -0,0 +1 @@
print("Hello, World!")

@ -0,0 +1 @@
puts "Hello, world"

@ -0,0 +1 @@
echo Hello World from shell

Binary file not shown.

@ -0,0 +1,3 @@
fn main() {
println!("Hello, world!");
}

Binary file not shown.

Binary file not shown.

@ -0,0 +1,19 @@
#include <stdio.h>
#include <stdlib.h>
int *temp[1024*1024];
void test(int i)
{
// char temp[1024*1024] = {0};
char *loc;
temp[i]=malloc(1024*1024);
*temp[i] =i;
printf("%s %d num = %d!\r\n", __FUNCTION__, __LINE__, *temp[i]);
i++;
//if(i==10) return;
test(i++);
}
int main(void)
{
test(0);
return 0;
}

Binary file not shown.

@ -0,0 +1,77 @@
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t condition_var = PTHREAD_COND_INITIALIZER;
void *functionCount1();
void *functionCount2();
int count = 0;
#define COUNT_DONE 10
#define COUNT_HALT1 3
#define COUNT_HALT2 6
main()
{
pthread_t thread1, thread2;
pthread_create( &thread1, NULL, &functionCount1, NULL);
pthread_create( &thread2, NULL, &functionCount2, NULL);
pthread_join( thread1, NULL);
pthread_join( thread2, NULL);
printf("Final count: %d\n",count);
exit(EXIT_SUCCESS);
}
// Write numbers 1-3 and 8-10 as permitted by functionCount2()
void *functionCount1()
{
for(;;)
{
// Lock mutex and then wait for signal to relase mutex
pthread_mutex_lock( &count_mutex );
// Wait while functionCount2() operates on count
// mutex unlocked if condition varialbe in functionCount2() signaled.
pthread_cond_wait( &condition_var, &count_mutex );
count++;
printf("Counter value functionCount1: %d\n",count);
pthread_mutex_unlock( &count_mutex );
if(count >= COUNT_DONE) return(NULL);
}
}
// Write numbers 4-7
void *functionCount2()
{
for(;;)
{
pthread_mutex_lock( &count_mutex );
if( count < COUNT_HALT1 || count > COUNT_HALT2 )
{
// Condition of if statement has been met.
// Signal to free waiting thread by freeing the mutex.
// Note: functionCount1() is now permitted to modify "count".
pthread_cond_signal( &condition_var );
}
else
{
count++;
printf("Counter value functionCount2: %d\n",count);
}
pthread_mutex_unlock( &count_mutex );
if(count >= COUNT_DONE) return(NULL);
}
}

Binary file not shown.

@ -0,0 +1,48 @@
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *print_message_function( void *ptr );
main()
{
pthread_t thread1, thread2;
const char *message1 = "Thread 1";
const char *message2 = "Thread 2";
int iret1, iret2;
/* Create independent threads each of which will execute function */
iret1 = pthread_create( &thread1, NULL, print_message_function, (void*) message1);
if(iret1)
{
fprintf(stderr,"Error - pthread_create() return code: %d\n",iret1);
exit(EXIT_FAILURE);
}
iret2 = pthread_create( &thread2, NULL, print_message_function, (void*) message2);
if(iret2)
{
fprintf(stderr,"Error - pthread_create() return code: %d\n",iret2);
exit(EXIT_FAILURE);
}
printf("pthread_create() for thread 1 returns: %d\n",iret1);
printf("pthread_create() for thread 2 returns: %d\n",iret2);
/* Wait till threads are complete before main continues. Unless we */
/* wait we run the risk of executing an exit which will terminate */
/* the process and all threads before the threads have completed. */
pthread_join( thread1, NULL);
pthread_join( thread2, NULL);
exit(EXIT_SUCCESS);
}
void *print_message_function( void *ptr )
{
char *message;
message = (char *) ptr;
printf("%s \n", message);
}

Binary file not shown.

@ -0,0 +1,37 @@
#include <stdio.h>
#include <pthread.h>
#define NTHREADS 10
void *thread_function(void *);
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
int counter = 0;
main()
{
pthread_t thread_id[NTHREADS];
int i, j;
for(i=0; i < NTHREADS; i++)
{
pthread_create( &thread_id[i], NULL, thread_function, NULL );
}
for(j=0; j < NTHREADS; j++)
{
pthread_join( thread_id[j], NULL);
}
/* Now that all threads are complete I can print the final result. */
/* Without the join I could be printing a value before all the threads */
/* have been completed. */
printf("Final counter value: %d\n", counter);
}
void *thread_function(void *dummyPtr)
{
printf("Thread number %ld\n", pthread_self());
pthread_mutex_lock( &mutex1 );
counter++;
pthread_mutex_unlock( &mutex1 );
}

Binary file not shown.

@ -0,0 +1,42 @@
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *functionC();
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
int counter = 0;
main()
{
int rc1, rc2;
pthread_t thread1, thread2;
/* Create independent threads each of which will execute functionC */
if( (rc1=pthread_create( &thread1, NULL, &functionC, NULL)) )
{
printf("Thread creation failed: %d\n", rc1);
}
if( (rc2=pthread_create( &thread2, NULL, &functionC, NULL)) )
{
printf("Thread creation failed: %d\n", rc2);
}
/* Wait till threads are complete before main continues. Unless we */
/* wait we run the risk of executing an exit which will terminate */
/* the process and all threads before the threads have completed. */
pthread_join( thread1, NULL);
pthread_join( thread2, NULL);
exit(EXIT_SUCCESS);
}
void *functionC()
{
pthread_mutex_lock( &mutex1 );
counter++;
printf("Counter value: %d\n",counter);
pthread_mutex_unlock( &mutex1 );
}

Binary file not shown.

@ -0,0 +1,16 @@
#include <stdio.h>
char a[4096]="\0";
FILE *fp;
void main(int argc, char** argv){
if (argc >1) {
fp = fopen(argv[1], "r");
int i=0;
while (!feof(fp))
{
fscanf(fp, "%c", &a[i]);
printf("%c",a[i]);
i++;
}
}
}

Binary file not shown.

@ -0,0 +1,52 @@
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/uio.h>
char head[1024],foo[48], bar[51], baz[49];
struct iovec iov[3];
int main ()
{
ssize_t nr;
int fd, i;
fd = open ("hello.sh", O_RDONLY);
if (fd==-1){
perror ("open");
return 1;
}
nr=read(fd, head, sizeof(head));
if(nr==-1) {
perror("read");
return 2;
}
printf ("read size %d, head: %s\n", nr, (char *) head);
/* set up our iovec structures */
iov[0].iov_base = foo;
iov[0].iov_len = sizeof (foo);
iov[1].iov_base = bar;
iov[1].iov_len = sizeof (bar);
iov[2].iov_base = baz;
iov[2].iov_len = sizeof (baz);
/* read into the structures with a single call */
nr = readv (fd, iov, 3);
if (nr==-1) {
perror ("readv");
return 1;
}
for (i = 0; i < 3; i++)
printf ("IOV%d: size:%d %s\n", i, nr, (char *) iov[i].iov_base);
if (close (fd)) {
perror ("close");
return 1;
}
return 0;
}

Binary file not shown.

@ -0,0 +1,16 @@
#include <stdio.h>
#include <stdlib.h>
void test(int i)
{
char temp[1024*1024] = {0};
temp[0] = i;
temp[0] ++;
printf("%s %d num = %d!\r\n", __FUNCTION__, __LINE__, temp[0]);
test(temp[0]);
}
int main(void)
{
test(0);
return 0;
}

@ -35,6 +35,8 @@ elseif (${ARCH} STREQUAL aarch64)
set(PREFIX aarch64-elf-)
endif ()
set(CMAKE_C_FLAGS "-mgeneral-regs-only")
elseif (${ARCH} STREQUAL mipsel)
set(PREFIX ${ARCH}-linux-musln32-)
else()
message("Unsupported arch: ${ARCH}")
endif ()

@ -0,0 +1,14 @@
// See LICENSE for license details.
#ifndef __LIBS_MIPSEL_H__
#define __LIBS_MIPSEL_H__
#define do_div(n, base) \
({ \
int __res; \
__res = ((unsigned long)n) % (unsigned)base; \
n = ((unsigned long)n) / (unsigned)base; \
__res; \
})
#endif

@ -0,0 +1,75 @@
#ifndef __LIBS_ATOMIC_H__
#define __LIBS_ATOMIC_H__
// TODO: implement atomic operations for aarch64
/* Atomic operations that C can't guarantee us. Useful for resource counting etc.. */
static inline void set_bit(int nr, volatile void *addr) __attribute__((always_inline));
static inline void clear_bit(int nr, volatile void *addr) __attribute__((always_inline));
static inline void change_bit(int nr, volatile void *addr) __attribute__((always_inline));
static inline bool test_and_set_bit(int nr, volatile void *addr) __attribute__((always_inline));
static inline bool test_and_clear_bit(int nr, volatile void *addr) __attribute__((always_inline));
static inline bool test_bit(int nr, volatile void *addr) __attribute__((always_inline));
/* *
* set_bit - Atomically set a bit in memory
* @nr: the bit to set
* @addr: the address to start counting from
*
* Note that @nr may be almost arbitrarily large; this function is not
* restricted to acting on a single-word quantity.
* */
static inline void set_bit(int nr, volatile void *addr) {
/* unimplemented */
}
/* *
* clear_bit - Atomically clears a bit in memory
* @nr: the bit to clear
* @addr: the address to start counting from
* */
static inline void clear_bit(int nr, volatile void *addr) {
/* unimplemented */
}
/* *
* change_bit - Atomically toggle a bit in memory
* @nr: the bit to change
* @addr: the address to start counting from
* */
static inline void change_bit(int nr, volatile void *addr) {
/* unimplemented */
}
/* *
* test_bit - Determine whether a bit is set
* @nr: the bit to test
* @addr: the address to count from
* */
static inline bool test_bit(int nr, volatile void *addr) {
/* unimplemented */
return 0;
}
/* *
* test_and_set_bit - Atomically set a bit and return its old value
* @nr: the bit to set
* @addr: the address to count from
* */
static inline bool test_and_set_bit(int nr, volatile void *addr) {
/* unimplemented */
return 0;
}
/* *
* test_and_clear_bit - Atomically clear a bit and return its old value
* @nr: the bit to clear
* @addr: the address to count from
* */
static inline bool test_and_clear_bit(int nr, volatile void *addr) {
/* unimplemented */
return 0;
}
#endif /* !__LIBS_ATOMIC_H__ */

@ -0,0 +1,14 @@
#include <regdef.h>
.text
.globl __start
.global _start
# seems different toolchains look for different entry points
_start:
__start:
# call user-program function
lw a0, 0(sp)
addiu a1, sp, 8
b umain
nop

@ -0,0 +1,55 @@
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 1985 MIPS Computer Systems, Inc.
* Copyright (C) 1994, 95, 99, 2003 by Ralf Baechle
* Copyright (C) 1990 - 1992, 1999 Silicon Graphics, Inc.
*/
#ifndef _ASM_REGDEF_H
#define _ASM_REGDEF_H
/*
* Symbolic register names for 32 bit ABI
*/
#define zero $0 /* wired zero */
#define AT $1 /* assembler temp - uppercase because of ".set at" */
#define v0 $2 /* return value */
#define v1 $3
#define a0 $4 /* argument registers */
#define a1 $5
#define a2 $6
#define a3 $7
#define t0 $8 /* caller saved */
#define t1 $9
#define t2 $10
#define t3 $11
#define t4 $12
#define t5 $13
#define t6 $14
#define t7 $15
#define s0 $16 /* callee saved */
#define s1 $17
#define s2 $18
#define s3 $19
#define s4 $20
#define s5 $21
#define s6 $22
#define s7 $23
#define t8 $24 /* caller saved */
#define t9 $25
#define jp $25 /* PIC jump register */
#define k0 $26 /* kernel scratch */
#define k1 $27
#define gp $28 /* global pointer */
#define sp $29 /* stack pointer */
#define fp $30 /* frame pointer */
#define s8 $30 /* same like fp! */
#define ra $31 /* return address */
#endif /* _ASM_REGDEF_H */

@ -4,21 +4,13 @@ _start:
# set ebp for backtrace
movl $0x0, %ebp
# load argc and argv
movl (%esp), %ebx
lea 0x4(%esp), %ecx
# move down the esp register
# since it may cause page fault in backtrace
subl $0x20, %esp
# save argc and argv on stack
pushl %ecx
pushl %ebx
# call user-program function
# according to fastcall ABI, the first 6 parameters are in registes
# so we do not need to copy (argc, argv) as on i386
call umain
1: jmp 1b

@ -24,8 +24,8 @@ main(void) {
assert(pid > 0);
cprintf("I am the parent, waiting now..\n");
assert(waitpid(pid, &code) == 0 && code == magic);
assert(waitpid(pid, &code) != 0 && wait() != 0);
assert(waitpid(pid, &code) > 0 && code == magic);
assert(waitpid(pid, &code) <= 0 && wait() <= 0);
cprintf("waitpid %d ok.\n", pid);
cprintf("exit pass.\n");

@ -19,12 +19,12 @@ main(void) {
}
for (; n > 0; n --) {
if (wait() != 0) {
if (wait() <= 0) {
panic("wait stopped early\n");
}
}
if (wait() == 0) {
if (wait() > 0) {
panic("wait got too many\n");
}

@ -32,7 +32,7 @@ typedef unsigned long long uint64_t;
#if __riscv_xlen == 64 || defined(__x86_64__) || defined(__aarch64__)
typedef int64_t intptr_t;
typedef uint64_t uintptr_t;
#elif __riscv_xlen == 32 || defined(__i386__)
#elif __riscv_xlen == 32 || defined(__i386__) || defined(__mips__)
typedef int32_t intptr_t;
typedef uint32_t uintptr_t;
#endif

@ -36,7 +36,7 @@ struct proghdr {
uint64_t p_memsz; // size of segment in memory (bigger if contains bss
uint64_t p_align; // required alignment, invariably hardware page size
};
#elif __riscv_xlen == 32 || defined(__i386__)
#elif __riscv_xlen == 32 || defined(__i386__) || defined(__mipsel)
struct proghdr {
uint32_t p_type; // loadable code or data, dynamic linking info,etc.
uint32_t p_offset; // file offset of segment

@ -33,6 +33,35 @@
/* ONLY FOR LAB6 */
#define SYS_set_priority 141
#elif defined(__mips__)
#define MIPS_SYSCALL 4000
#define SYS_exit (MIPS_SYSCALL + 1)
#define SYS_fork (MIPS_SYSCALL + 2)
#define SYS_wait (MIPS_SYSCALL + 114)
#define SYS_exec (MIPS_SYSCALL + 11)
#define SYS_clone (MIPS_SYSCALL + 120)
#define SYS_yield (MIPS_SYSCALL + 162)
#define SYS_sleep (MIPS_SYSCALL + 166)
#define SYS_kill (MIPS_SYSCALL + 37)
#define SYS_gettime (MIPS_SYSCALL + 78)
#define SYS_getpid (MIPS_SYSCALL + 20)
#define SYS_mmap (MIPS_SYSCALL + 90)
#define SYS_munmap (MIPS_SYSCALL + 91)
#define SYS_shmem (-1)
#define SYS_pgdir (-1)
#define SYS_openat (MIPS_SYSCALL + 288)
#define SYS_close (MIPS_SYSCALL + 6)
#define SYS_read (MIPS_SYSCALL + 3)
#define SYS_write (MIPS_SYSCALL + 4)
#define SYS_seek (MIPS_SYSCALL + 18)
#define SYS_fstat (MIPS_SYSCALL + 198)
#define SYS_fsync (MIPS_SYSCALL + 118)
#define SYS_getcwd (MIPS_SYSCALL + 203)
#define SYS_getdirentry64 (MIPS_SYSCALL + 219)
#define SYS_dup3 (MIPS_SYSCALL + 327)
/* ONLY FOR LAB6 */
#define SYS_set_priority 141
#else
#define SYS_exit 93

@ -64,7 +64,7 @@ main(void) {
cprintf("fork ok.\n");
for (i = 0; i < total; i ++) {
if (wait() != 0) {
if (wait() <= 0) {
cprintf("wait failed.\n");
goto failed;
}

@ -65,6 +65,22 @@ syscall(int num, ...) {
"m" (a[4])
: "cc", "memory"
);
#elif defined(__mips__)
// mips n32 abi
register long a0 __asm__("$4") = a[0];
register long a1 __asm__("$5") = a[1];
register long a2 __asm__("$6") = a[2];
register long a3 __asm__("$7") = a[3];
register long a4 __asm__("$8") = a[4];
register long a5 __asm__("$9") = a[5];
register long v0 __asm__("$2");
__asm__ __volatile__ (
"addu $2,$0,%2 ; syscall"
: "=&r"(v0), "=r"(a3)
: "ir"(num), "0"(v0), "1"(a3), "r"(a0), "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5)
: "$1", "$3", "$10", "$11", "$12", "$13",
"$14", "$15", "$24", "$25", "hi", "lo", "memory");
ret = a3 ? -v0 : v0;
#endif
return ret;
}

Loading…
Cancel
Save