commit - 5f8048ab7e609ab2283a4a1e9a4e74276ec1f547
commit + 52a430f311f2ce1fe38eb2fb7d5867df29e13e7e
blob - b862efd1a319407c20f8397f6fa3a7b6fd65b9b9
blob + 2739ea77906d91f6c1a52c00b357948a4c7390ef
--- .gitignore
+++ .gitignore
*.core
*.o
*.elf
+rootfs
+syscalls.h
rvemu
blob - c683707ec93490fb754776ec570d1ce24be25248
blob + 6634c2708ac436e52f5c1fb974b170cf6de574cb
--- Makefile
+++ Makefile
.SUFFIXES:
.SUFFIXES: .c .S .o .elf
-CROSS = riscv32-unknown-linux-musl
-CFLAGS = -fno-PIC -O3
-LDFLAGS = -s -Wl,--image-base,0x78000000 -no-pie -static -lpthread -lutil
-OBJ = rvemu.o syscall.o cpu.o exec.o
+SUDO = doas
+PREFIX = /usr/local
+
+CROSS = riscv64-unknown-linux-musl
+CFLAGS = -fPIC -O3
+LDFLAGS = -s -pie -static -lpthread
+OBJ = rvemu.o ecall.o cpu.o exec.o
PROGS = test.elf hello.elf
all: rvemu ${PROGS}
clean:
- rm -f rvemu *.o *.elf *.core
+ rm -f rvemu *.o *.elf *.core syscalls.h
+ rm -rf rootfs
-run: rvemu test.elf
- ./rvemu test.elf
+install: rvemu
+ mkdir -p ${DESTDIR}${PREFIX}/bin
+ cp -f rvemu ${DESTDIR}${PREFIX}/bin/
+run: rvemu ${PROGS}
+ mkdir -p rootfs/bin
+ cp -f rvemu rootfs/bin
+ cp -f ${PROGS} rootfs
+ ${SUDO} chroot rootfs /bin/rvemu /test.elf
+
rvemu: ${OBJ}
${CC} -o $@ ${OBJ} ${LDFLAGS}
+ecall.o: syscalls.h
+
+syscalls.h: syscalls.inc
+ sed 's/^\.set \(SYS_[a-z0-9_]*\), \([0-9]*\)$$/#define \1 \2/' \
+ < syscalls.inc > syscalls.h
+
.c.o: rvemu.h
${CC} -c -o $@ $< ${CFLAGS}
blob - be1763527ea5c72f4c66c475b65c59b496befb2e
blob + f12b40ff570310c03a64afafdf2dcb151c7f4878
--- cpu.c
+++ cpu.c
#include "rvemu.h"
-static u32 regs[31];
-u32 pc;
+static u64 regs[31];
+u64 pc;
-
-void cpu_set (size_t reg, u32 val)
+void cpu_set (size_t reg, u64 val)
{
if (reg > 0)
regs[reg - 1] = val;
}
-u32 cpu_get (size_t reg)
+u64 cpu_get (size_t reg)
{
return reg > 0 ? regs[reg - 1] : 0;
}
return i;
}
+static i64 extend (i32 x)
+{
+ return x;
+}
+
void cpu_exec (u32 instr)
{
const char *name;
const u8 rs1 = (instr >> 15) & 0x1f;
const u8 rs2 = (instr >> 20) & 0x1f;
const u8 funct7 = instr >> 25;
- const u32 imm_i = (i32)instr >> 20;
- const u32 imm_s = ((i32)instr >> 25 << 5) | ((instr >> 7) & 0x1f);
- const u32 imm_b = (instr >> 31 << 12)
+ const u64 imm_i = extend ((i32)instr >> 20);
+ const u64 imm_s = extend (((i32)instr >> 25 << 5) | ((instr >> 7) & 0x1f));
+ const u64 imm_b = extend (((i32)instr >> 31 << 12)
| (((instr >> 25) & 0x3f) << 5)
| (((instr >> 8) & 0xf) << 1)
- | (((instr >> 7) & 1) << 11);
- const u32 imm_u = instr & 0xfffff000;
- const u32 imm_j = ((i32)instr >> 31 << 20)
+ | (((instr >> 7) & 1) << 11));
+ const u64 imm_u = extend (instr & 0xfffff000);
+ const u64 imm_j = extend (((i32)instr >> 31 << 20)
| (((instr >> 21) & 0x3ff) << 1)
| (((instr >> 20) & 1) << 11)
- | (((instr >> 12) & 0xff) << 12);
+ | (((instr >> 12) & 0xff) << 12));
+ const u8 shamt = imm_i & 0x3f;
- u32 a, b, c;
+ u64 a, b, c;
switch (instr & 0x7f) {
case 0b0110111: // lui rd, uimm
eprintf ("lui x%u, %u\n", (uint)rd, imm_u);
c = a != b;
case 0b100:
name = "blt";
- c = (i32)a < (i32)b;
+ c = (i64)a < (i64)b;
break;
case 0b101:
name = "bge";
- c = (i32)a >= (i32)b;
+ c = (i64)a >= (i64)b;
break;
case 0b110:
name = "bltu";
switch (funct3) {
case 0b000: // lb
name = "lb";
- b = (i32)read_i8 (a);
+ b = (i64)read_i8 (a);
break;
case 0b001: // lh
name = "lh";
- b = (i32)read_i16 (a);
+ b = (i64)read_i16 (a);
break;
case 0b010: // lw
name = "lw";
- b = read_u32 (a);
+ b = (i64)read_i32 (a);
break;
+ case 0b011: // ld
+ name = "ld";
+ b = read_u64 (a);
+ break;
case 0b100: // lbu
name = "lbu";
b = read_u8 (a);
name = "lhu";
b = read_u16 (a);
break;
+ case 0b110: // lwu
+ name = "lwu";
+ b = read_u32 (a);
+ break;
default:
goto ud;
}
name = "sw";
write_u32 (b, a);
break;
+ case 0b011: // sd
+ name = "sd";
+ write_u64 (b, a);
+ break;
default:
goto ud;
}
break;
case 0b001: // slli
name = "slli";
- c = a << (b & 0x1f);
+ c = a << shamt;
break;
case 0b010: // slti
name = "slti";
- c = (i32)a < (i32)b;
+ c = (i64)a < (i64)b;
break;
case 0b011: // sltiu
name = "sltiu";
case 0b101: // srli/srai
if ((instr >> 30) & 1) {
name = "srai";
- c = (i32)a >> b;
+ c = (i64)a >> shamt;
} else {
name = "srli";
- c = a >> b;
+ c = a >> shamt;
}
break;
case 0b110: // ori
default:
goto ud;
}
- eprintf ("%s x%u, x%u, %d\n", name, (uint)rd, (uint)rs1, (int)imm_i);
+ eprintf ("%s x%u, x%u, %lld\n", name, (uint)rd, (uint)rs1, (i64)imm_i);
+ cpu_set (rd, c);
+ break;
+ case 0b0011011: // aluiw rd, rs1, iimm
+ a = cpu_get (rs1);
+ b = imm_i;
+ c = (instr >> 30) & 1;
+ switch (funct3) {
+ case 0b000: // addiw
+ name = "addiw";
+ c = a + b;
+ break;
+ case 0b001: // slliw
+ if (shamt >> 5)
+ goto ud;
+ name = "slliw";
+ c = a << shamt;
+ break;
+ case 0b101: // srliw/sraiw
+ if (shamt >> 5)
+ goto ud;
+ if (c) {
+ name = "srai";
+ c = (i64)a >> shamt;
+ } else {
+ name = "srli";
+ c = a >> shamt;
+ }
+ break;
+ default:
+ goto ud;
+ }
+ c &= 0x00000000ffffffff;
+ c = extend (c);
+ eprintf ("%s x%u, x%u, %lld\n", name, (uint)rd, (uint)rs1, (i64)imm_i);
cpu_set (rd, c);
break;
case 0b0110011: // alu rd, rs1, rs2
break;
case 0b010: // slt
name = "slt";
- a = (i32)a < (i32)b;
+ a = (i64)a < (i64)b;
break;
case 0b011: // sltu
name = "sltu";
case 0b101: // srl/sra
if (c) {
name = "sra";
- a = (i32)a >> b;
+ a = (i64)a >> (b & 0x3f);
} else {
name = "srl";
- a >>= b;
+ a >>= (b & 0x3f);
}
break;
case 0b110: // or
eprintf ("%s x%u, x%u, x%u\n", name, (uint)rd, (uint)rs1, (uint)rs2);
cpu_set (rd, a);
break;
+ case 0b0111011: // aluw
+ a = cpu_get (rs1);
+ b = cpu_get (rs2);
+ c = (instr >> 30) & 1;
+ switch (funct3) {
+ case 0b000: // addw/subw
+ if (c) {
+ name = "subw";
+ c = a - b;
+ } else {
+ name = "addw";
+ c = a + b;
+ }
+ break;
+ case 0b001: // sllw
+ name = "sllw";
+ c = a << (b & 0x1f);
+ break;
+ case 0b101: // srlw/sraiw
+ if (c) {
+ name = "sraw";
+ c = (i64)a >> (b & 0x1f);
+ } else {
+ name = "srlw";
+ c = a >> (b & 0x1f);
+ }
+ break;
+ default:
+ goto ud;
+ }
+ eprintf ("%s x%u, x%u, x%u\n", name, (uint)rd, (uint)rs1, (uint)rs2);
+ cpu_set (rd, extend ((i32)a));
+ break;
case 0b0001111: // fence/fence.tso/pause
eprintf ("fence\n");
break;
break;
default:
ud:
- errx (1, "%08x: invalid instruction: %08x", pc - 4, instr);
+ errx (1, "%08llx: invalid instruction: %08x", pc - 4, instr);
}
}
blob - 7f8efcda3a12cf5aff8ecfa2b29bb63f61b90cd3
blob + 66eb875ea57dc87a40bf8b6cb2d3386f35feeb06
--- exec.c
+++ exec.c
#include "rvemu.h"
-int is_executable (const Elf32_Ehdr *ehdr)
+int is_executable (const Elf64_Ehdr *ehdr)
{
return IS_ELF (*ehdr)
- && ehdr->e_ident[EI_CLASS] == ELFCLASS32
+ && ehdr->e_ident[EI_CLASS] == ELFCLASS64
&& ehdr->e_ident[EI_DATA] == ELFDATA2LSB
&& ehdr->e_machine == EM_RISCV
;
}
-static char **copyv (u32 v)
+int my_execve (const char *path, char **argv, char **envp)
{
- char **a;
- int n;
- for (n = 0; read_u32 (v + n * 4) != 0; ++n);
-
- a = calloc (n + 1, sizeof (char *));
- for (int i = 0; i < n; ++i)
- a[i] = (char *)(size_t)read_u32 (v + i * 4);
-
- return a;
-}
-
-int my_execve (const char *path, u32 argv, u32 envp)
-{
-
- Elf32_Ehdr ehdr;
+ Elf64_Ehdr ehdr;
char buffer[256], *nl, *s, **args, **env;
int fd;
read (fd, &ehdr, sizeof (ehdr));
close (fd);
- args = copyv (argv);
- env = copyv (envp);
-
if (is_executable (&ehdr)) {
- path = interpreter;
+ return execvpe ("rvemu", argv, envp);
}
- return execve (path, args, env);
+ return execve (path, argv, envp);
}
blob - /dev/null
blob + f2631d600322b6a3bc1d74865ef5cd3f54fe743a (mode 644)
--- /dev/null
+++ ecall.c
+#include <sys/resource.h>
+#include <sys/utsname.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/msg.h>
+#include <sys/sem.h>
+#include <signal.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sched.h>
+#include <errno.h>
+#include "syscalls.h"
+#include "rvemu.h"
+
+struct linux_stat64 {
+ u64 dev;
+ u64 ino;
+ u32 mode;
+ u32 nlink;
+ u32 uid;
+ u32 gid;
+ u64 rdev;
+ u64 __pad1;
+ u64 size;
+ u32 blksize;
+ u32 __pad2;
+ u64 blocks;
+ u32 atime;
+ u32 atime_ns;
+ u32 mtime;
+ u32 mtime_ns;
+ u32 ctime;
+ u32 ctime_ns;
+ u32 __unused4;
+ u32 __unused5;
+};
+
+struct linux_utsname {
+ char sysname[65];
+ char nodename[65];
+ char release[65];
+ char version[65];
+ char machine[65];
+};
+
+static int map_errno (int err)
+{
+ const int errnos[] = {
+ [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,
+ };
+ return errnos[err];
+}
+
+static int map (int x) {
+ return x < 0 ? -map_errno (errno) : x;
+}
+
+
+static void stat_to_linux_stat (struct linux_stat64 *lst, const struct stat *st)
+{
+ memset (lst, 0, sizeof (*lst));
+ lst->dev = st->st_dev;
+ lst->ino = st->st_dev;
+ lst->mode = st->st_dev;
+ lst->nlink = st->st_dev;
+ lst->uid = st->st_dev;
+ lst->gid = st->st_dev;
+ lst->rdev = st->st_dev;
+ lst->size = st->st_dev;
+ lst->blksize = st->st_dev;
+ lst->blocks = st->st_dev;
+ lst->atime = st->st_atim.tv_sec;
+ lst->atime_ns = st->st_atim.tv_nsec;
+ lst->mtime = st->st_mtim.tv_sec;
+ lst->mtime_ns = st->st_mtim.tv_nsec;
+ lst->ctime = st->st_ctim.tv_sec;
+ lst->ctime_ns = st->st_ctim.tv_nsec;
+}
+
+static void utsname_to_linux_utsname (struct linux_utsname *lun, const struct utsname *un)
+{
+ memset (lun, 0, sizeof (*lun));
+ strlcpy (lun->sysname, un->sysname, 65);
+ strlcpy (lun->nodename, un->nodename, 65);
+ strlcpy (lun->release, un->release, 65);
+ strlcpy (lun->version, un->version, 65);
+ strlcpy (lun->machine, un->machine, 65);
+}
+
+static int enosys (const char *sys)
+{
+ warnx ("unimplemented syscall: %s", sys);
+ return -map_errno (ENOSYS);
+}
+
+static u64 my_brk (u64 new)
+{
+ void *ptr;
+
+ if (new < brkval)
+ return brkval;
+ if (new >= 0x78000000) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ new = (new + 4095) & ~0x3ff;
+ ptr = mmap (
+ (void *)brkval,
+ new - brkval,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON,
+ -1,
+ 0
+ );
+ if (ptr == NULL)
+ return -1;
+ brkval = new;
+ return brkval;
+}
+
+#define ptr(T, x) ((T *)(x))
+#define str(x) ptr (const char, x)
+void ecall (void)
+{
+ struct linux_stat64 lst;
+ struct linux_utsname lun;
+ struct stat st;
+ struct utsname un;
+ void *ptr;
+ const u64 a0 = cpu_get (10);
+ const u64 a1 = cpu_get (11);
+ const u64 a2 = cpu_get (12);
+ const u64 a3 = cpu_get (13);
+ const u64 a4 = cpu_get (14);
+ const u64 a5 = cpu_get (15);
+ const u64 a7 = cpu_get (17);
+ u64 ret;
+ switch (a7) {
+ case SYS_getcwd:
+ ret = enosys ("getcwd");
+ break;
+ case SYS_dup:
+ ret = map (dup ((int)a0));
+ break;
+ case SYS_dup3:
+ ret = map (dup3 ((int)a0, (int)a1, (int)a2));
+ break;
+ case SYS_fcntl:
+ ret = enosys ("fcntl");
+ break;
+ case SYS_ioctl:
+ ret = enosys ("ioctl");
+ break;
+ case SYS_flock:
+ ret = map (flock ((int)a0, (int)a1));
+ break;
+ case SYS_mknodat:
+ ret = map (mknodat ((int)a0, str (a1), (mode_t)a2, (dev_t)a3));
+
+ case SYS_mkdirat:
+ ret = map (mkdirat ((int)a0, str (a1), (mode_t)a2));
+ break;
+ case SYS_unlinkat:
+ ret = map (unlinkat ((int)a0, str (a1), (int)a2));
+ break;
+ case SYS_symlinkat:
+ ret = map (symlinkat (str (a0), (int)a1, str (a2)));
+ break;
+ case SYS_linkat:
+ ret = map (linkat ((int)a0, str (a1), (int)a2, str (a3), (int)a4));
+ break;
+ case SYS_renameat:
+ ret = map (renameat ((int)a0, str (a1), (int)a2, str (a3)));
+ break;
+ case SYS_umount:
+ ret = enosys ("umount");
+ break;
+ case SYS_mount:
+ ret = enosys ("mount");
+ break;
+ case SYS_pivot_root:
+ ret = enosys ("pivot_root");
+ break;
+ case SYS_nfsservctl:
+ ret = enosys ("nfsservctl");
+ break;
+ case SYS_statfs:
+ ret = enosys ("statfs");
+ break;
+ case SYS_fstatfs:
+ ret = enosys ("fstatfs");
+ break;
+ case SYS_truncate:
+ ret = map (truncate (str (a0), (off_t)a1));
+ break;
+ break;
+ case SYS_ftruncate:
+ ret = map (ftruncate ((int)a0, (off_t)a1));
+ break;
+ case SYS_fallocate:
+ ret = enosys ("fallocate");
+ break;
+ case SYS_faccessat:
+ ret = map (faccessat ((int)a0, str (a1), (int)a2, (int)a3));
+ break;
+ case SYS_chdir:
+ ret = map (chdir (str (a0)));
+ break;
+ case SYS_fchdir:
+ ret = map (fchdir ((int)a0));
+ break;
+ case SYS_chroot:
+ ret = map (chroot (str (a0)));
+ break;
+ case SYS_fchmod:
+ ret = map (fchmod ((int)a0, (mode_t)a1));
+ break;
+ case SYS_fchmodat:
+ ret = map (fchmodat ((int)a0, str (a1), (mode_t)a2, (int)a3));
+ break;
+ case SYS_fchownat:
+ ret = map (fchownat ((int)a0, str (a1), (uid_t)a2, (gid_t)a3, (int)a4));
+ break;
+ case SYS_fchown:
+ ret = map (fchown ((int)a0, (uid_t)a1, (gid_t)a2));
+ break;
+ case SYS_openat:
+ ret = map (openat ((int)a0, str (a1), (int)a2, (int)a3));
+ break;
+ case SYS_close:
+ ret = map (close ((int)a0));
+ break;
+ case SYS_vhangup:
+ ret = enosys ("vhangup");
+ break;
+ case SYS_pipe2:
+ ret = map (pipe2 (ptr (int, a0), (int)a1));
+ break;
+ case SYS_quotactl:
+ ret = enosys ("quotactl");
+ break;
+ case SYS_getdents64:
+ ret = enosys ("getdents64");
+ break;
+ case SYS_lseek:
+ ret = map (lseek ((int)a0, (off_t)a1, (int)a2));
+ break;
+ case SYS_read:
+ ret = map (read ((int)a0, ptr (void, a1), (size_t)a2));
+ break;
+ case SYS_write:
+ ret = map (write ((int)a0, ptr (const void, a1), (size_t)a2));
+ break;
+ case SYS_readv:
+ ret = enosys ("readv");
+ break;
+ case SYS_writev:
+ ret = enosys ("writev");
+ break;
+ case SYS_pread:
+ ret = map (pread ((int)a0, ptr (void, a1), (size_t)a2, (off_t)a3));
+ break;
+ case SYS_pwrite:
+ ret = map (pwrite ((int)a0, ptr (const void, a1), (size_t)a2, (off_t)a3));
+ break;
+ case SYS_preadv:
+ ret = enosys ("preadv");
+ break;
+ case SYS_pwritev:
+ ret = enosys ("pwritev");
+ break;
+ case SYS_sendfile:
+ ret = enosys ("sendfile");
+ break;
+ case SYS_pselect6:
+ ret = enosys ("pselect6");
+ break;
+ case SYS_ppoll:
+ ret = enosys ("ppoll");
+ break;
+ case SYS_signalfd4:
+ ret = enosys ("signalfd4");
+ break;
+ case SYS_vmsplice:
+ ret = enosys ("vmsplice");
+ break;
+ case SYS_splice:
+ ret = enosys ("splice");
+ break;
+ case SYS_tee:
+ ret = enosys ("tee");
+ break;
+ case SYS_readlinkat:
+ ret = map (readlinkat ((int)a0, str (a1), ptr (char, a2), (size_t)a3));
+ break;
+ case SYS_fstatat:
+ ret = map (fstatat ((int)a0, str (a1), &st, (int)a3));
+ stat_to_linux_stat (&lst, &st);
+ memcpy (ptr (void, a2), &lst, sizeof (lst));
+ break;
+ case SYS_fstat:
+ ret = map (fstat ((int)a0, &st));
+ stat_to_linux_stat (&lst, &st);
+ memcpy (ptr (void, a1), &lst, sizeof (lst));
+ break;
+ case SYS_sync:
+ sync ();
+ ret = 0;
+ break;
+ case SYS_fsync:
+ ret = map (fsync ((int)a0));
+ break;
+ case SYS_fdatasync:
+ ret = map (fdatasync ((int)a0));
+ break;
+ case SYS_sync_file_range:
+ ret = enosys ("sync_file_range");
+ break;
+ case SYS_timerfd_create:
+ ret = enosys ("timerfd_create");
+ break;
+ case SYS_timerfd_settime:
+ ret = enosys ("timerfd_settime");
+ break;
+ case SYS_timerfd_gettime:
+ ret = enosys ("timerfd_gettime");
+ break;
+ case SYS_utimensat:
+ ret = enosys ("utimensat");
+ break;
+ case SYS_acct:
+ ret = acct (str (a0));
+ break;
+ case SYS_capget:
+ ret = enosys ("capget");
+ break;
+ case SYS_capset:
+ ret = enosys ("capset");
+ break;
+ case SYS_personality:
+ ret = enosys ("personality");
+ break;
+ case SYS_exit:
+ exit (a0);
+ ret = -1;
+ break;
+ case SYS_exit_group:
+ ret = enosys ("exit_group");
+ break;
+ case SYS_waitid:
+ ret = enosys ("waitid");
+ break;
+ case SYS_set_tid_address:
+ ret = enosys ("set_tid_address");
+ break;
+ case SYS_unshare:
+ ret = enosys ("unshare");
+ break;
+ case SYS_futex:
+ ret = enosys ("futex");
+ break;
+ case SYS_set_robust_limit:
+ ret = enosys ("set_robust_limit");
+ break;
+ case SYS_get_robust_limit:
+ ret = enosys ("get_robust_limit");
+ break;
+ case SYS_nanosleep:
+ ret = enosys ("nanosleep");
+ break;
+ case SYS_gettimer:
+ ret = enosys ("gettimer");
+ break;
+ case SYS_settimer:
+ ret = enosys ("settimer");
+ break;
+ case SYS_kexec_load:
+ ret = enosys ("kexec_load");
+ break;
+ case SYS_kexec_init_module:
+ ret = enosys ("kexec_init_module");
+ break;
+ case SYS_kexec_delete_module:
+ ret = enosys ("kexec_delete_module");
+ break;
+ case SYS_timer_create:
+ ret = enosys ("timer_create");
+ break;
+ case SYS_timer_gettime:
+ ret = enosys ("timer_gettime");
+ break;
+ case SYS_timer_getoverrun:
+ ret = enosys ("timer_getoverrun");
+ break;
+ case SYS_timer_settime:
+ ret = enosys ("timer_settime");
+ break;
+ case SYS_timer_delete:
+ ret = enosys ("timer_delete");
+ break;
+ case SYS_clock_settime:
+ ret = enosys ("clock_settime");
+ break;
+ case SYS_clock_gettime:
+ ret = enosys ("clock_gettime");
+ break;
+ case SYS_clock_getres:
+ ret = enosys ("clock_getres");
+ break;
+ case SYS_clock_nanosleep:
+ ret = enosys ("clock_nanosleep");
+ break;
+ case SYS_syslog:
+ ret = enosys ("syslog");
+ break;
+ case SYS_ptrace:
+ ret = enosys ("ptrace");
+ break;
+ case SYS_sched_setparam:
+ ret = enosys ("sched_setparam");
+ break;
+ case SYS_sched_setscheduler:
+ ret = enosys ("sched_setscheduler");
+ break;
+ case SYS_sched_getscheduler:
+ ret = enosys ("sched_getscheduler");
+ break;
+ case SYS_sched_getparam:
+ ret = enosys ("sched_getparam");
+ break;
+ case SYS_sched_setaffinity:
+ ret = enosys ("sched_setaffinity");
+ break;
+ case SYS_sched_getaffinity:
+ ret = enosys ("sched_getaffinity");
+ break;
+ case SYS_sched_yield:
+ ret = map (sched_yield ());
+ break;
+ case SYS_sched_get_priority_max:
+ ret = map (sched_get_priority_max ((int)a0));
+ break;
+ case SYS_sched_get_priority_min:
+ ret = map (sched_get_priority_min ((int)a0));
+ break;
+ case SYS_sched_rr_get_interval:
+ ret = enosys ("sched_rr_get_interval");
+ break;
+ case SYS_restart_syscall:
+ ret = enosys ("restart_syscall");
+ break;
+ case SYS_kill:
+ ret = map (kill ((pid_t)a0, (int)a1));
+ break;
+ case SYS_tkill:
+ ret = enosys ("tkill");
+ break;
+ case SYS_tgkill:
+ ret = enosys ("tgkill");
+ break;
+ case SYS_signalstack:
+ ret = enosys ("signalstack");
+ break;
+ case SYS_sigsuspend:
+ ret = enosys ("sigsuspend");
+ break;
+ case SYS_sigaction:
+ ret = enosys ("sigaction");
+ break;
+ case SYS_rt_sigprocmask:
+ ret = enosys ("rt_sigprocmask");
+ break;
+ case SYS_sigpending:
+ ret = enosys ("sigpending");
+ break;
+ case SYS_sigtimedwait:
+ ret = enosys ("sigtimedwait");
+ break;
+ case SYS_sigqueueinfo:
+ ret = enosys ("sigqueueinfo");
+ break;
+ case SYS_sigreturn:
+ ret = enosys ("sigreturn");
+ break;
+ case SYS_setpriority:
+ ret = map (setpriority ((int)a0, (id_t)a1, (int)a2));
+ break;
+ case SYS_getpriority:
+ ret = map (getpriority ((int)a0, (id_t)a1));
+ break;
+ case SYS_reboot:
+ ret = enosys ("reboot");
+ break;
+ case SYS_setregid:
+ ret = map (setregid ((gid_t)a0, (gid_t)a1));
+ break;
+ case SYS_setgid:
+ ret = map (setgid ((gid_t)a0));
+ break;
+ case SYS_setreuid:
+ ret = map (setreuid ((uid_t)a0, (uid_t)a1));
+ break;
+ case SYS_setuid:
+ ret = map (setuid ((uid_t)a0));
+ break;
+ case SYS_setresuid:
+ ret = map (setresuid ((uid_t)a0, (uid_t)a1, (uid_t)a2));
+ break;
+ case SYS_getresuid:
+ ret = map (getresuid (ptr (uid_t, a0), ptr (uid_t, a1), ptr (uid_t, a2)));
+ break;
+ case SYS_setresgid:
+ ret = map (setresgid ((gid_t)a0, (gid_t)a1, (gid_t)a2));
+ break;
+ case SYS_getresgid:
+ ret = map (getresgid (ptr (gid_t, a0), ptr (gid_t, a1), ptr (gid_t, a2)));
+ break;
+ case SYS_setfsuid:
+ ret = enosys ("setfsuid");
+ break;
+ case SYS_setfsgid:
+ ret = enosys ("setfsgid");
+ break;
+ case SYS_times:
+ ret = enosys ("times");
+ break;
+ case SYS_setpgid:
+ ret = map (setpgid ((pid_t)a0, (pid_t)a1));
+ break;
+ case SYS_getpgid:
+ ret = map (getpgid ((pid_t)a0));
+ break;
+ case SYS_getsid:
+ ret = map (getsid ((pid_t)a0));
+ break;
+ case SYS_setsid:
+ ret = map (setsid ());
+ break;
+ case SYS_setgroups:
+ ret = enosys ("setgroups");
+ break;
+ case SYS_uname:
+ ret = map (uname (&un));
+ utsname_to_linux_utsname (&lun, &un);
+ memcpy (ptr (void, a0), &lun, sizeof (lun));
+ break;
+ case SYS_sethostname:
+ ret = enosys ("sethostname");
+ break;
+ case SYS_setdomainname:
+ ret = enosys ("setdomainname");
+ break;
+ case SYS_getrlimit:
+ ret = enosys ("getrlimit");
+ break;
+ case SYS_setrlimit:
+ ret = enosys ("setrlimit");
+ break;
+ case SYS_getrusage:
+ ret = enosys ("getrusage");
+ break;
+ case SYS_umask:
+ ret = map (umask ((mode_t)a0));
+ break;
+ case SYS_prctl:
+ ret = enosys ("prctl");
+ break;
+ case SYS_getcpu:
+ ret = enosys ("getcpu");
+ break;
+ case SYS_gettimeofday:
+ ret = enosys ("gettimeofday");
+ break;
+ case SYS_settimeofday:
+ ret = enosys ("settimeofday");
+ break;
+ case SYS_adjtimex:
+ ret = enosys ("adjtimex");
+ break;
+ case SYS_getpid:
+ ret = map (getpid ());
+ break;
+ case SYS_getuid:
+ ret = map (getuid ());
+ break;
+ case SYS_geteuid:
+ ret = map (geteuid ());
+ break;
+ case SYS_getgid:
+ ret = map (getgid ());
+ break;
+ case SYS_getegid:
+ ret = map (getegid ());
+ break;
+ case SYS_gettid:
+ ret = enosys ("gettid");
+ break;
+ case SYS_sysinfo:
+ ret = enosys ("sysinfo");
+ break;
+ case 180:
+ case 181:
+ case 182:
+ case 183:
+ case 184:
+ case 185:
+ ret = enosys ("mq_*");
+ break;
+ case SYS_msgget:
+ ret = map(msgget ((key_t)a0, (int)a1));
+ break;
+ case SYS_msgctl:
+ ret = enosys ("msgctl");
+ break;
+ case SYS_msgrcv:
+ ret = map (msgrcv ((int)a0, ptr (void, a1), (size_t)a2, (long)a3, (int)a4));
+ break;
+ case SYS_msgsnd:
+ ret = map (msgsnd ((int)a0, ptr (const void, a1), (size_t)a2, (int)a3));
+ break;
+ case SYS_semget:
+ ret = map (semget ((key_t)a0, (int)a1, (int)a2));
+ break;
+ case SYS_semctl:
+ ret = enosys ("semctl");
+ break;
+ case SYS_semtimedop:
+ ret = enosys ("semtimedop");
+ break;
+ case SYS_semop:
+ ret = enosys ("semop");
+ break;
+ case 194:
+ case 195:
+ case 196:
+ case 197:
+ ret = enosys ("shm*");
+ break;
+ case 198:
+ case 199:
+ case 200:
+ case 201:
+ case 202:
+ case 203:
+ case 204:
+ case 205:
+ case 206:
+ case 207:
+ case 208:
+ case 209:
+ case 210:
+ case 211:
+ case 212:
+ ret = enosys ("socket api");
+ break;
+ case SYS_readahead:
+ ret = enosys ("readahead");
+ break;
+ case SYS_brk:
+ ret = map (my_brk (a0));
+ break;
+ case SYS_munmap:
+ ret = map (munmap (ptr (void, a0), (size_t)a1));
+ break;
+ case SYS_mremap:
+ ret = enosys ("mremap");
+ break;
+ case SYS_add_key:
+ ret = enosys ("add_key");
+ break;
+ case SYS_request_key:
+ ret = enosys ("request_key");
+ break;
+ case SYS_keyctl:
+ ret = enosys ("keyctl");
+ break;
+ case SYS_clone:
+ if (a0 == 17 && a1 == 0) {
+ // fork
+ ret = map (fork ());
+ } else {
+ ret = enosys ("clone");
+ }
+ break;
+ case SYS_execve:
+ ret = map (my_execve (str (a0), ptr (char *, a1), ptr (char *, a2)));
+ break;
+ case SYS_mmap:
+ ptr = mmap (ptr (void, a0), (size_t)a1, (int)a2, (int)a3, (int)a4, (off_t)a5);
+ if (ptr == NULL) {
+ ret = -map_errno (errno);
+ } else {
+ ret = (u64)ptr;
+ }
+ break;
+ case SYS_fadvise64:
+ ret = enosys ("fadvise64");
+ break;
+ case SYS_swapon:
+ ret = enosys ("swapon");
+ break;
+ case SYS_swapoff:
+ ret = enosys ("swapoff");
+ break;
+ case SYS_mprotect:
+ ret = map (mprotect (ptr (void, a0), (size_t)a1, (int)a2));
+ break;
+ case SYS_msync:
+ ret = map (msync (ptr (void, a0), (size_t)a1, (int)a2));
+ break;
+ case SYS_mlock:
+ ret = map (mlock (ptr (void, a0), (size_t)a1));
+ break;
+ case SYS_munlock:
+ ret = map (munlock (ptr (void, a0), (size_t)a1));
+ break;
+ case SYS_mlockall:
+ ret = map (mlockall ((int)a0));
+ break;
+ case SYS_munlockall:
+ ret = map (munlockall ());
+ break;
+ case SYS_mincore:
+ ret = enosys ("mincore");
+ break;
+ case SYS_madvise:
+ ret = map (madvise (ptr (void, a0), (size_t)a1, (int)a2));
+ break;
+ case SYS_remap_file_pages:
+ ret = enosys ("remap_file_pages");
+ break;
+ case SYS_mbind:
+ ret = enosys ("mbind");
+ break;
+ case SYS_get_mempolicy:
+ ret = enosys ("get_mempolicy");
+ break;
+ case SYS_set_mempolicy:
+ ret = enosys ("set_mempolicy");
+ break;
+ case SYS_migrate_pages:
+ ret = enosys ("migrate_pages");
+ break;
+ case SYS_move_pages:
+ ret = enosys ("move_pages");
+ break;
+ case SYS_rt_tgsigqueueinfo:
+ ret = enosys ("rt_tgsigqueueinfo");
+ break;
+ case SYS_perf_event_open:
+ ret = enosys ("perf_event_open");
+ break;
+ case SYS_accept4:
+ ret = enosys ("accept4");
+ break;
+ case SYS_recvmsg:
+ ret = enosys ("recvmsg");
+ break;
+ case 244:
+ case 245:
+ case 246:
+ case 247:
+ case 248:
+ case 249:
+ case 250:
+ case 251:
+ case 252:
+ case 253:
+ case 254:
+ case 255:
+ case 256:
+ case 257:
+ case 258:
+ case 259:
+ ret = enosys ("arch-specific");
+ break;
+ case 260:
+ ret = enosys ("wait4");
+ break;
+ case SYS_prlimit64:
+ ret = enosys ("prlimit64");
+ break;
+ case SYS_fanotify_init:
+ ret = enosys ("fanotify_init");
+ break;
+ case SYS_fanotify_mark:
+ ret = enosys ("fanotify_mark");
+ break;
+ case SYS_name_to_handle_at:
+ ret = enosys ("name_to_handle_at");
+ break;
+ case SYS_open_by_handle_at:
+ ret = enosys ("open_by_handle_at");
+ break;
+ case SYS_clock_adjtime:
+ ret = enosys ("clock_adjtime");
+ break;
+ case SYS_syncfs:
+ ret = enosys ("syncfs");
+ break;
+ case SYS_setns:
+ ret = enosys ("setns");
+ break;
+ case SYS_sendmsg:
+ ret = enosys ("sendmsg");
+ break;
+ case SYS_process_vm_readv:
+ ret = enosys ("process_vm_readv");
+ break;
+ case SYS_process_vm_writev:
+ ret = enosys ("process_vm_writev");
+ break;
+ case SYS_kcmp:
+ ret = enosys ("kcmp");
+ break;
+ case SYS_finit_module:
+ ret = enosys ("finit_module");
+ break;
+ case SYS_sched_setattr:
+ ret = enosys ("sched_setattr");
+ break;
+ case SYS_sched_getattr:
+ ret = enosys ("sched_getattr");
+ break;
+ case SYS_renameat2:
+ ret = enosys ("renameat2");
+ break;
+ case SYS_seccomp:
+ ret = enosys ("seccomp");
+ break;
+ case SYS_getrandom:
+ ret = enosys ("getrandom");
+ break;
+ case SYS_memfd_create:
+ ret = enosys ("seccomp");
+ break;
+ case SYS_bpf:
+ ret = enosys ("bpf");
+ break;
+ case SYS_execveat:
+ ret = enosys ("execveat");
+ break;
+ case SYS_userfaultfd:
+ ret = enosys ("usefaultfd");
+ break;
+ case SYS_membarrier:
+ ret = enosys ("membarrier");
+ break;
+ case SYS_mlock2:
+ ret = enosys ("mlock2");
+ break;
+ case SYS_copy_file_range:
+ ret = enosys ("copy_file_range");
+ break;
+ case SYS_preadv2:
+ ret = enosys ("preadv2");
+ break;
+ case SYS_pwritev2:
+ ret = enosys ("pwritev2");
+ break;
+ case SYS_pkey_mprotect:
+ ret = enosys ("pkey_mprotect");
+ break;
+ case SYS_pkey_alloc:
+ ret = enosys ("pkey_alloc");
+ break;
+ case SYS_pkey_free:
+ ret = enosys ("pkey_free");
+ break;
+ case SYS_statx:
+ ret = enosys ("statx");
+ break;
+ case SYS_io_pgetevents:
+ ret = enosys ("io_pgetevents");
+ break;
+ case SYS_rseq:
+ ret = enosys ("rseq");
+ break;
+ case SYS_kexec_file_load:
+ ret = enosys ("kexec_file_load");
+ break;
+ case SYS_open:
+ ret = map (open ((const char *)(size_t)a0, (int)a1, (int)a2));
+ break;
+ case SYS_link:
+ ret = map (link (str (a0), str (a1)));
+ break;
+ case SYS_unlink:
+ ret = map (unlink (str (a0)));
+ break;
+ case SYS_mkdir:
+ ret = map (mkdir (str (a0), (mode_t)a1));
+ break;
+ case SYS_access:
+ ret = map (access (str (a0), (int)a1));
+ break;
+ case SYS_stat:
+ ret = map (stat (str (a0), &st));
+ stat_to_linux_stat (&lst, &st);
+ memcpy (ptr (void, a1), &lst, sizeof (lst));
+ break;
+ case SYS_lstat:
+ ret = map (lstat (str (a0), &st));
+ stat_to_linux_stat (&lst, &st);
+ memcpy (ptr (void, a1), &lst, sizeof (lst));
+ break;
+ case SYS_time:
+ ret = enosys ("time");
+ break;
+ case SYS_getmainvars:
+ ret = enosys ("getmainvars");
+ break;
+ case SYS_debug:
+ fprintf (stderr, "DEBUG: %llu\n", a0);
+ ret = 0;
+ break;
+ default:
+ warnx ("%08llx: unimplemented syscall %llu", pc - 4, a7);
+ ret = -map_errno (ENOSYS);
+ break;
+ }
+ cpu_set (REG_a0, ret);
+}
+
blob - 10f6646bd6ae37bf7de1a9d35d7eccec7fbf3f7d
blob + f5eebd803603f22e5415e2c2dbd56c756d929182
--- rvemu.c
+++ rvemu.c
#include <errno.h>
#include "rvemu.h"
-const char *interpreter = "./rvemu";
-u32 brkval;
+u64 brkval;
static void load_image (const char *filename)
{
- Elf32_Ehdr ehdr;
+ Elf64_Ehdr ehdr;
int fd;
fd = open (filename, O_RDONLY);
pc = ehdr.e_entry;
for (unsigned i = 0; i < ehdr.e_phnum; ++i) {
- Elf32_Phdr phdr;
+ Elf64_Phdr phdr;
u32 flags = 0, end;
void *ptr;
case PT_NULL:
break;
case PT_LOAD:
- eprintf ("loading %08x into %08x flags %x memsz %u\n",
+ eprintf ("loading %016llx into %016llx flags %x memsz %u\n",
phdr.p_offset, phdr.p_vaddr, phdr.p_flags, phdr.p_memsz);
if (phdr.p_filesz == phdr.p_memsz) {
ptr = mmap (
- (void *)(size_t)phdr.p_vaddr,
+ (void *)phdr.p_vaddr,
phdr.p_memsz,
flags,
MAP_PRIVATE | MAP_COPY,
);
} else if (phdr.p_filesz == 0) {
ptr = mmap (
- (void *)(size_t)phdr.p_vaddr,
+ (void *)phdr.p_vaddr,
phdr.p_memsz,
flags,
MAP_ANON | MAP_PRIVATE,
0
);
} else {
- errx (1, "%u: p_filesz: %u, p_memsz: %u",
+ errx (1, "%u: p_filesz: %llu, p_memsz: %llu",
i, phdr.p_filesz, phdr.p_memsz);
}
- if ((size_t)ptr != (size_t)phdr.p_vaddr)
+ if ((u64)ptr != phdr.p_vaddr)
err (1, "%u: failed to map program header", i);
- end = (((u32)(size_t)ptr + phdr.p_memsz) + 4095) & ~0x3ff;
+ end = (((u64)ptr + phdr.p_memsz) + 4095) & ~0x3ff;
if (end > brkval)
brkval = end;
break;
close (fd);
}
-static void cpu_push (u32 val)
+static void cpu_push (u64 val)
{
- cpu_set (2, cpu_get (2) - 4);
- write_u32 (cpu_get (2), val);
+ cpu_set (REG_sp, cpu_get (REG_sp) - 8);
+ write_u64 (cpu_get (REG_sp), val);
}
-static void cpu_push_str (const char *ptr)
-{
- if ((size_t)ptr > 0x80000000) {
- const size_t len = strlen (ptr);
- char *nptr = sbrk (len + 1);
- memcpy (nptr, ptr, len + 1);
- assert ((size_t)nptr < 0x80000000);
- ptr = nptr;
- }
- cpu_push ((u32)(size_t)ptr);
-}
-
static void setup_stack (
- u32 stack_size,
+ u64 stack_size,
int argc,
char **argv,
int envc,
void *stack_bottom;
// set stack pointer
- cpu_set (2, 0x80000000);
+ cpu_set (REG_sp, 0x80000000);
- stack_bottom = (void *)(size_t)(0x80000000 - stack_size);
+ stack_bottom = (void *)(u64)(0x80000000 - stack_size);
ptr = mmap (
stack_bottom,
stack_size,
cpu_push (0);
for (int i = envc - 1; i >= 0; --i)
- cpu_push_str (envp[i]);
+ cpu_push ((u64)envp[i]);
cpu_push (0);
for (int i = argc; i >= 0; --i)
- cpu_push_str (argv[i]);
+ cpu_push ((u64)argv[i]);
cpu_push (argc);
}
char *base;
void *ptr;
+ eprintf ("&main = %p\n", &main);
+
base = basename (argv[0]);
if (strcmp (base, "rvemu") == 0) {
blob - 982df935a81ad7877a60e5f5f7198413aa9a8819
blob + f1fa870f78600a53528abcc226d280124e392286
--- rvemu.h
+++ rvemu.h
# define eprintf(...)
#endif
+enum {
+ REG_zero,
+ REG_ra,
+ REG_sp,
+ REG_gp,
+ REG_tp,
+ REG_t0,
+ REG_t1,
+ REG_t2,
+ REG_s0,
+ REG_s1,
+ REG_a0,
+ REG_a1,
+ REG_a2,
+ REG_a3,
+ REG_a4,
+ REG_a5,
+ REG_a6,
+ REG_a7,
+ REG_s2,
+ REG_s3,
+ REG_s4,
+ REG_s5,
+ REG_s6,
+ REG_s7,
+ REG_s8,
+ REG_s9,
+ REG_s10,
+ REG_s11,
+ REG_t3,
+ REG_t4,
+ REG_t5,
+ REG_t6,
+};
+
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef unsigned int uint;
-extern u32 pc;
-extern u32 brkval;
+extern u64 pc;
+extern u64 brkval;
extern const char *interpreter;
u32 cpu_fetch (void);
-u32 cpu_get (size_t reg);
-void cpu_set (size_t reg, u32 val);
+u64 cpu_get (size_t reg);
+void cpu_set (size_t reg, u64 val);
void cpu_exec (u32 instr);
void ecall (void);
-int my_execve (const char *path, u32 argv, u32 envp);
-int is_executable (const Elf32_Ehdr *);
+int my_execve (const char *path, char **argv, char **envp);
+int is_executable (const Elf64_Ehdr *);
#define read_u8(ptr) (*(const u8 *)(size_t)(ptr))
#define read_u16(ptr) (*(const u16 *)(size_t)(ptr))
blob - 687d4a84e1e49fbedc28cb07e931e816c372b093 (mode 644)
blob + /dev/null
--- syscall.c
+++ /dev/null
-#include <sys/resource.h>
-#include <sys/utsname.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/msg.h>
-#include <sys/sem.h>
-#include <signal.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <sched.h>
-#include <errno.h>
-#include "rvemu.h"
-
-struct linux_stat64 {
- u64 dev;
- u64 ino;
- u32 mode;
- u32 nlink;
- u32 uid;
- u32 gid;
- u64 rdev;
- u64 __pad1;
- u64 size;
- u32 blksize;
- u32 __pad2;
- u64 blocks;
- u32 atime;
- u32 atime_ns;
- u32 mtime;
- u32 mtime_ns;
- u32 ctime;
- u32 ctime_ns;
- u32 __unused4;
- u32 __unused5;
-};
-
-struct linux_utsname {
- char sysname[65];
- char nodename[65];
- char release[65];
- char version[65];
- char machine[65];
-};
-
-static int map_errno (int err)
-{
- const int errnos[] = {
- [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,
- };
- return errnos[err];
-}
-
-static int map (int x) {
- return x < 0 ? -map_errno (errno) : x;
-}
-
-
-static void stat_to_linux_stat (struct linux_stat64 *lst, const struct stat *st)
-{
- memset (lst, 0, sizeof (*lst));
- lst->dev = st->st_dev;
- lst->ino = st->st_dev;
- lst->mode = st->st_dev;
- lst->nlink = st->st_dev;
- lst->uid = st->st_dev;
- lst->gid = st->st_dev;
- lst->rdev = st->st_dev;
- lst->size = st->st_dev;
- lst->blksize = st->st_dev;
- lst->blocks = st->st_dev;
- lst->atime = st->st_atim.tv_sec;
- lst->atime_ns = st->st_atim.tv_nsec;
- lst->mtime = st->st_mtim.tv_sec;
- lst->mtime_ns = st->st_mtim.tv_nsec;
- lst->ctime = st->st_ctim.tv_sec;
- lst->ctime_ns = st->st_ctim.tv_nsec;
-}
-
-static void utsname_to_linux_utsname (struct linux_utsname *lun, const struct utsname *un)
-{
- memset (lun, 0, sizeof (*lun));
- strlcpy (lun->sysname, un->sysname, 65);
- strlcpy (lun->nodename, un->nodename, 65);
- strlcpy (lun->release, un->release, 65);
- strlcpy (lun->version, un->version, 65);
- strlcpy (lun->machine, un->machine, 65);
-}
-
-static int enosys (const char *sys)
-{
- warnx ("unimplemented syscall: %s", sys);
- return -map_errno (ENOSYS);
-}
-
-static u32 my_brk (u32 new)
-{
- void *ptr;
-
- if (new < brkval)
- return brkval;
- if (new >= 0x78000000) {
- errno = ENOMEM;
- return -1;
- }
-
- new = (new + 4095) & ~0x3ff;
- ptr = mmap (
- (void *)(size_t)brkval,
- new - brkval,
- PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANON,
- -1,
- 0
- );
- if (ptr == NULL)
- return -1;
- brkval = new;
- return brkval;
-}
-
-#define ptr(T, x) ((T *)(size_t)(x))
-#define str(x) ptr (const char, x)
-void ecall (void)
-{
- struct linux_stat64 lst;
- struct linux_utsname lun;
- struct stat st;
- struct utsname un;
- void *ptr;
- const u32 a0 = cpu_get (10);
- const u32 a1 = cpu_get (11);
- const u32 a2 = cpu_get (12);
- const u32 a3 = cpu_get (13);
- const u32 a4 = cpu_get (14);
- const u32 a5 = cpu_get (15);
- const u32 a7 = cpu_get (17);
- u32 ret;
- switch (a7) {
- case 17: // getcwd
- ret = enosys ("getcwd");
- break;
- case 23: // dup
- ret = map (dup ((int)a0));
- break;
- case 24: // dup3
- ret = map (dup3 ((int)a0, (int)a1, (int)a2));
- break;
- case 25: // fcntl
- ret = enosys ("fcntl");
- break;
- case 29: // ioctl
- ret = enosys ("ioctl");
- break;
- case 32: // flock
- ret = map (flock ((int)a0, (int)a1));
- break;
- case 33: // mknodat
- ret = map (mknodat ((int)a0, str (a1), (mode_t)a2, (dev_t)a3));
-
- case 34: // mkdirat
- ret = map (mkdirat ((int)a0, str (a1), (mode_t)a2));
- break;
- case 35: // unlinkat
- ret = map (unlinkat ((int)a0, str (a1), (int)a2));
- break;
- case 36: // symlinkat
- ret = map (symlinkat (str (a0), (int)a1, str (a2)));
- break;
- case 37: // linkat
- ret = map (linkat ((int)a0, str (a1), (int)a2, str (a3), (int)a4));
- break;
- case 38: // renameat
- ret = map (renameat ((int)a0, str (a1), (int)a2, str (a3)));
- break;
- case 39: // umount
- ret = enosys ("umount");
- break;
- case 40: // mount
- ret = enosys ("mount");
- break;
- case 41: // pivot_root
- ret = enosys ("pivot_root");
- break;
- case 42: // nfsservctl
- ret = enosys ("nfsservctl");
- break;
- case 43: // statfs
- ret = enosys ("statfs");
- break;
- case 44: // fstatfs
- ret = enosys ("fstatfs");
- break;
- case 45: // truncate
- ret = map (truncate (str (a0), (off_t)a1));
- break;
- break;
- case 46: // ftruncate
- ret = map (ftruncate ((int)a0, (off_t)a1));
- break;
- case 47: // fallocate
- ret = enosys ("fallocate");
- break;
- case 48: // faccessat
- ret = map (faccessat ((int)a0, str (a1), (int)a2, (int)a3));
- break;
- case 49: // chdir
- ret = map (chdir (str (a0)));
- break;
- case 50: // fchdir
- ret = map (fchdir ((int)a0));
- break;
- case 51: // chroot
- ret = map (chroot (str (a0)));
- break;
- case 52: // fchmod
- ret = map (fchmod ((int)a0, (mode_t)a1));
- break;
- case 53: // fchmodat
- ret = map (fchmodat ((int)a0, str (a1), (mode_t)a2, (int)a3));
- break;
- case 54: // fchownat
- ret = map (fchownat ((int)a0, str (a1), (uid_t)a2, (gid_t)a3, (int)a4));
- break;
- case 55: // fchown
- ret = map (fchown ((int)a0, (uid_t)a1, (gid_t)a2));
- break;
- case 56: // openat
- ret = map (openat ((int)a0, str (a1), (int)a2, (int)a3));
- break;
- case 57: // close
- ret = map (close ((int)a0));
- break;
- case 58: // vhangup
- ret = enosys ("vhangup");
- break;
- case 59: // pipe2
- ret = map (pipe2 (ptr (int, a0), (int)a1));
- break;
- case 60: // quotactl
- ret = enosys ("quotactl");
- break;
- case 61: // getdents64
- ret = enosys ("getdents64");
- break;
- case 62: // lseek
- ret = map (lseek ((int)a0, (off_t)a1, (int)a2));
- break;
- case 63: // read
- ret = map (read ((int)a0, ptr (void, a1), (size_t)a2));
- break;
- case 64: // write
- ret = map (write ((int)a0, ptr (const void, a1), (size_t)a2));
- break;
- case 65: // readv
- ret = enosys ("readv");
- break;
- case 66: // writev
- ret = enosys ("writev");
- break;
- case 67: // pread
- ret = map (pread ((int)a0, ptr (void, a1), (size_t)a2, (off_t)a3));
- break;
- case 68: // pwrite
- ret = map (pwrite ((int)a0, ptr (const void, a1), (size_t)a2, (off_t)a3));
- break;
- case 69: // preadv
- ret = enosys ("preadv");
- break;
- case 70: // pwritev
- ret = enosys ("pwritev");
- break;
- case 71: // pwritev
- ret = enosys ("sendfile");
- break;
- case 72: // pselect6
- ret = enosys ("pselect6");
- break;
- case 73: // ppoll
- ret = enosys ("ppoll");
- break;
- case 74: // signalfd4
- ret = enosys ("signalfd4");
- break;
- case 75: // vmsplice
- ret = enosys ("vmsplice");
- break;
- case 76: // splice
- ret = enosys ("splice");
- break;
- case 77: // tee
- ret = enosys ("tee");
- break;
- case 78: // readlinkat
- ret = map (readlinkat ((int)a0, str (a1), ptr (char, a2), (size_t)a3));
- break;
- case 79: // fstatat
- ret = map (fstatat ((int)a0, str (a1), &st, (int)a3));
- stat_to_linux_stat (&lst, &st);
- memcpy (ptr (void, a2), &lst, sizeof (lst));
- break;
- case 80: // fstat
- ret = map (fstat ((int)a0, &st));
- stat_to_linux_stat (&lst, &st);
- memcpy (ptr (void, a1), &lst, sizeof (lst));
- break;
- case 81: // sync
- sync ();
- ret = 0;
- break;
- case 82: // fsync
- ret = map (fsync ((int)a0));
- break;
- case 83: // fdatasync
- ret = map (fdatasync ((int)a0));
- break;
- case 84: // sync_file_range
- ret = enosys ("sync_file_range");
- break;
- case 85: // timerfd_create
- ret = enosys ("timerfd_create");
- break;
- case 86: // timerfd_settime
- ret = enosys ("timerfd_settime");
- break;
- case 87: // timerfd_gettime
- ret = enosys ("timerfd_gettime");
- break;
- case 88: // utimensat
- ret = enosys ("utimensat");
- break;
- case 89: // acct
- ret = acct (str (a0));
- break;
- case 90: // capget
- ret = enosys ("capget");
- break;
- case 91: // capset
- ret = enosys ("capset");
- break;
- case 92: // personality
- ret = enosys ("personality");
- break;
- case 93: // exit
- exit (a0);
- ret = -1;
- break;
- case 94: // exit_group
- ret = enosys ("exit_group");
- break;
- case 95: // waitid
- ret = enosys ("waitid");
- break;
- case 96: // set_tid_address
- ret = enosys ("set_tid_address");
- break;
- case 97: // unshare
- ret = enosys ("unshare");
- break;
- case 98: // futex
- ret = enosys ("futex");
- break;
- case 99: // set_robust_limit
- ret = enosys ("set_robust_limit");
- break;
- case 100: // get_robust_limit
- ret = enosys ("get_robust_limit");
- break;
- case 101: // nanosleep
- ret = enosys ("nanosleep");
- break;
- case 102: // gettimer
- ret = enosys ("gettimer");
- break;
- case 103: // settimer
- ret = enosys ("settimer");
- break;
- case 104: // kexec_load
- ret = enosys ("kexec_load");
- break;
- case 105: // kexec_init_module
- ret = enosys ("kexec_init_module");
- break;
- case 106: // kexec_delete_module
- ret = enosys ("kexec_delete_module");
- break;
- case 107: // timer_create
- ret = enosys ("timer_create");
- break;
- case 108: // timer_gettime
- ret = enosys ("timer_gettime");
- break;
- case 109: // timer_getoverrun
- ret = enosys ("timer_getoverrun");
- break;
- case 110: // timer_settime
- ret = enosys ("timer_settime");
- break;
- case 111: // timer_delete
- ret = enosys ("timer_delete");
- break;
- case 112: // clock_settime
- ret = enosys ("clock_settime");
- break;
- case 113: // clock_gettime
- ret = enosys ("clock_gettime");
- break;
- case 114: // clock_getres
- ret = enosys ("clock_getres");
- break;
- case 115: // clock_nanosleep
- ret = enosys ("clock_nanosleep");
- break;
- case 116: // syslog
- ret = enosys ("syslog");
- break;
- case 117: // ptrace
- ret = enosys ("ptrace");
- break;
- case 118: // sched_setparam
- ret = enosys ("sched_setparam");
- break;
- case 119: // sched_setscheduler
- ret = enosys ("sched_setscheduler");
- break;
- case 120: // sched_getscheduler
- ret = enosys ("sched_getscheduler");
- break;
- case 121: // sched_getparam
- ret = enosys ("sched_getparam");
- break;
- case 122: // sched_setaffinity
- ret = enosys ("sched_setaffinity");
- break;
- case 123: // sched_getaffinity
- ret = enosys ("sched_getaffinity");
- break;
- case 124: // sched_yield
- ret = map (sched_yield ());
- break;
- case 125: // sched_get_priority_max
- ret = map (sched_get_priority_max ((int)a0));
- break;
- case 126: // sched_get_priority_min
- ret = map (sched_get_priority_min ((int)a0));
- break;
- case 127: // sched_rr_get_interval
- ret = enosys ("sched_rr_get_interval");
- break;
- case 128: // restart_syscall
- ret = enosys ("restart_syscall");
- break;
- case 129: // kill
- ret = map (kill ((pid_t)a0, (int)a1));
- break;
- case 130: // tkill
- ret = enosys ("tkill");
- break;
- case 131: // tgkill
- ret = enosys ("tgkill");
- break;
- case 132: // signalstack
- ret = enosys ("signalstack");
- break;
- case 133: // sigaction
- ret = enosys ("sigaction");
- break;
- case 134: // sigaction
- ret = enosys ("sigaction");
- break;
- case 135: // rt_sigprocmask
- ret = enosys ("rt_sigprocmask");
- break;
- case 136: // sigpending
- ret = enosys ("sigpending");
- break;
- case 137: // sigtimedwait
- ret = enosys ("sigtimedwait");
- break;
- case 138: // sigqueueinfo
- ret = enosys ("sigqueueinfo");
- break;
- case 139: // sigreturn
- ret = enosys ("sigreturn");
- break;
- case 140: // setpriority
- ret = map (setpriority ((int)a0, (id_t)a1, (int)a2));
- break;
- case 141: // getpriority
- ret = map (getpriority ((int)a0, (id_t)a1));
- break;
- case 142: // reboot
- ret = enosys ("reboot");
- break;
- case 143: // setregid
- ret = map (setregid ((gid_t)a0, (gid_t)a1));
- break;
- case 144: // setgid
- ret = map (setgid ((gid_t)a0));
- break;
- case 145: // setreuid
- ret = map (setreuid ((uid_t)a0, (uid_t)a1));
- break;
- case 146: // setuid
- ret = map (setuid ((uid_t)a0));
- break;
- case 147: // setresuid
- ret = map (setresuid ((uid_t)a0, (uid_t)a1, (uid_t)a2));
- break;
- case 148: // getresuid
- ret = map (getresuid (ptr (uid_t, a0), ptr (uid_t, a1), ptr (uid_t, a2)));
- break;
- case 149: // setresgid
- ret = map (setresgid ((gid_t)a0, (gid_t)a1, (gid_t)a2));
- break;
- case 150: // getresgid
- ret = map (getresgid (ptr (gid_t, a0), ptr (gid_t, a1), ptr (gid_t, a2)));
- break;
- case 151: // setfsuid
- ret = enosys ("setfsuid");
- break;
- case 152: // setfsgid
- ret = enosys ("setfsgid");
- break;
- case 153: // times
- ret = enosys ("times");
- break;
- case 154: // setpgid
- ret = map (setpgid ((pid_t)a0, (pid_t)a1));
- break;
- case 155: // getpgid
- ret = map (getpgid ((pid_t)a0));
- break;
- case 156: // getsid
- ret = map (getsid ((pid_t)a0));
- break;
- case 158: // setsid
- ret = map (setsid ());
- break;
- case 159: // setgroups
- ret = enosys ("setgroups");
- break;
- case 160: // uname
- ret = map (uname (&un));
- utsname_to_linux_utsname (&lun, &un);
- memcpy (ptr (void, a0), &lun, sizeof (lun));
- break;
- case 161: // sethostname
- ret = enosys ("sethostname");
- break;
- case 162: // setdomainname
- ret = enosys ("setdomainname");
- break;
- case 163: // getrlimit
- ret = enosys ("getrlimit");
- break;
- case 164: // setrlimit
- ret = enosys ("setrlimit");
- break;
- case 165: // getrusage
- ret = enosys ("getrusage");
- break;
- case 166: // umask
- ret = map (umask ((mode_t)a0));
- break;
- case 167: // prctl
- ret = enosys ("prctl");
- break;
- case 168: // getcpu
- ret = enosys ("getcpu");
- break;
- case 169: // gettimeofday
- ret = enosys ("gettimeofday");
- break;
- case 170: // settimeofday
- ret = enosys ("settimeofday");
- break;
- case 171: // adjtimex
- ret = enosys ("adjtimex");
- break;
- case 172: // getpid
- ret = map (getpid ());
- break;
- case 174: // getuid
- ret = map (getuid ());
- break;
- case 175: // geteuid
- ret = map (geteuid ());
- break;
- case 176: // getgid
- ret = map (getgid ());
- break;
- case 177: // getegid
- ret = map (getegid ());
- break;
- case 178: // gettid
- ret = enosys ("gettid");
- break;
- case 179: // sysinfo
- ret = enosys ("sysinfo");
- break;
- case 180:
- case 181:
- case 182:
- case 183:
- case 184:
- case 185:
- ret = enosys ("mq_*");
- break;
- case 186: // msgget
- ret = map (msgget ((key_t)a0, (int)a1));
- break;
- case 187: // msgctl
- ret = enosys ("msgctl");
- break;
- case 188: // msgrcv
- ret = map (msgrcv ((int)a0, ptr (void, a1), (size_t)a2, (long)a3, (int)a4));
- break;
- case 189: // msgsnd
- ret = map (msgsnd ((int)a0, ptr (const void, a1), (size_t)a2, (int)a3));
- break;
- case 190: // semget
- ret = map (semget ((key_t)a0, (int)a1, (int)a2));
- break;
- case 191: // semctl
- ret = enosys ("semctl");
- break;
- case 192: // semtimedop
- ret = enosys ("semtimedop");
- break;
- case 193: // semop
- ret = enosys ("semop");
- break;
- case 194:
- case 195:
- case 196:
- case 197:
- ret = enosys ("shm*");
- break;
- case 198:
- case 199:
- case 200:
- case 201:
- case 202:
- case 203:
- case 204:
- case 205:
- case 206:
- case 207:
- case 208:
- case 209:
- case 210:
- case 211:
- case 212:
- ret = enosys ("socket api");
- break;
- case 213: // readahead
- ret = enosys ("readahead");
- break;
- case 214: // brk
- ret = map (my_brk (a0));
- break;
- case 215: // munmap
- ret = map (munmap (ptr (void, a0), (size_t)a1));
- break;
- case 216: // mremap
- ret = enosys ("mremap");
- break;
- case 217: // add_key
- ret = enosys ("add_key");
- break;
- case 218: // request_key
- ret = enosys ("request_key");
- break;
- case 219: // keyctl
- ret = enosys ("keyctl");
- break;
- case 220: // clone
- if (a0 == 17 && a1 == 0) {
- // fork
- ret = map (fork ());
- } else {
- ret = enosys ("clone");
- }
- break;
- case 221: // execve
- ret = map (my_execve (str (a0), a1, a2));
- break;
- case 222: // mmap
- ptr = mmap (ptr (void, a0), (size_t)a1, (int)a2, (int)a3, (int)a4, (off_t)a5);
- if (ptr == NULL) {
- ret = -map_errno (errno);
- } else if ((size_t)ptr > INT32_MAX) {
- ret = -map_errno (EINVAL);
- } else {
- ret = (size_t)ptr;
- }
- break;
- case 223: // fadvise64
- ret = enosys ("fadvise64");
- break;
- case 224: // swapon
- ret = enosys ("swapon");
- break;
- case 225: // swapoff
- ret = enosys ("swapoff");
- break;
- case 226: // mprotect
- ret = map (mprotect (ptr (void, a0), (size_t)a1, (int)a2));
- break;
- case 227: // msync
- ret = map (msync (ptr (void, a0), (size_t)a1, (int)a2));
- break;
- case 228: // mlock
- ret = map (mlock (ptr (void, a0), (size_t)a1));
- break;
- case 229: // munlock
- ret = map (munlock (ptr (void, a0), (size_t)a1));
- break;
- case 230: // mlockall
- ret = map (mlockall ((int)a0));
- break;
- case 231: // munlockall
- ret = map (munlockall ());
- break;
- case 232: // mincore
- ret = enosys ("mincore");
- break;
- case 233: // madvise
- ret = map (madvise (ptr (void, a0), (size_t)a1, (int)a2));
- break;
- case 234: // remap_file_pages
- ret = enosys ("remap_file_pages");
- break;
- case 235: // mbind
- ret = enosys ("mbind");
- break;
- case 236: // get_mempolicy
- ret = enosys ("get_mempolicy");
- break;
- case 237: // set_mempolicy
- ret = enosys ("set_mempolicy");
- break;
- case 238: // migrate_pages
- ret = enosys ("migrate_pages");
- break;
- case 239: // move_pages
- ret = enosys ("move_pages");
- break;
- case 240: // rt_tgsigqueueinfo
- ret = enosys ("rt_tgsigqueueinfo");
- break;
- case 241: // perf_event_open
- ret = enosys ("perf_event_open");
- break;
- case 242: // accept4
- ret = enosys ("accept4");
- break;
- case 243: // recvmsg
- ret = enosys ("recvmsg");
- break;
- case 244:
- case 245:
- case 246:
- case 247:
- case 248:
- case 249:
- case 250:
- case 251:
- case 252:
- case 253:
- case 254:
- case 255:
- case 256:
- case 257:
- case 258:
- case 259:
- ret = enosys ("arch-specific");
- break;
- case 260:
- ret = enosys ("wait4");
- break;
- case 261: // prlimit64
- ret = enosys ("prlimit64");
- break;
- case 262: // fanotify_init
- ret = enosys ("fanotify_init");
- break;
- case 263: // fanotify_mark
- ret = enosys ("fanotify_mark");
- break;
- case 264: // name_to_handle_at
- ret = enosys ("name_to_handle_at");
- break;
- case 265: // open_by_handle_at
- ret = enosys ("open_by_handle_at");
- break;
- case 266: // clock_adjtime
- ret = enosys ("clock_adjtime");
- break;
- case 267: // syncfs
- ret = enosys ("syncfs");
- break;
- case 268: // setns
- ret = enosys ("setns");
- break;
- case 269: // sendmsg
- ret = enosys ("sendmsg");
- break;
- case 270: // process_vm_readv
- ret = enosys ("process_vm_readv");
- break;
- case 271: // process_vm_writev
- ret = enosys ("process_vm_writev");
- break;
- case 272: // kcmp
- ret = enosys ("kcmp");
- break;
- case 273: // finit_module
- ret = enosys ("finit_module");
- break;
- case 274: // sched_setattr
- ret = enosys ("sched_setattr");
- break;
- case 275: // sched_getattr
- ret = enosys ("sched_getattr");
- break;
- case 276: // renameat2
- ret = enosys ("renameat2");
- break;
- case 277: // seccomp
- ret = enosys ("seccomp");
- break;
- case 278: // getrandom
- ret = enosys ("getrandom");
- break;
- case 279: // memfd_create
- ret = enosys ("seccomp");
- break;
- case 280: // bpf
- ret = enosys ("bpf");
- break;
- case 281: // execveat
- ret = enosys ("execveat");
- break;
- case 282: // userfaultfd
- ret = enosys ("usefaultfd");
- break;
- case 283: // membarrier
- ret = enosys ("membarrier");
- break;
- case 284: // mlock2
- ret = enosys ("mlock2");
- break;
- case 285: // copy_file_range
- ret = enosys ("copy_file_range");
- break;
- case 286: // preadv2
- ret = enosys ("preadv2");
- break;
- case 287: // pwritev2
- ret = enosys ("pwritev2");
- break;
- case 288: // pkey_mprotect
- ret = enosys ("pkey_mprotect");
- break;
- case 289: // pkey_alloc
- ret = enosys ("pkey_alloc");
- break;
- case 290: // pkey_free
- ret = enosys ("pkey_free");
- break;
- case 291: // statx
- ret = enosys ("statx");
- break;
- case 292: // io_pgetevents
- ret = enosys ("io_pgetevents");
- break;
- case 293: // rseq
- ret = enosys ("rseq");
- break;
- case 294: // kexec_file_load
- ret = enosys ("kexec_file_load");
- break;
- case 1024: // open
- ret = map (open ((const char *)(size_t)a0, (int)a1, (int)a2));
- break;
- case 1025: // link
- ret = map (link (str (a0), str (a1)));
- break;
- case 1026: // unlink
- ret = map (unlink (str (a0)));
- break;
- case 1030: // mkdir
- ret = map (mkdir (str (a0), (mode_t)a1));
- break;
- case 1033: // access
- ret = map (access (str (a0), (int)a1));
- break;
- case 1038: // stat
- ret = map (stat (str (a0), &st));
- stat_to_linux_stat (&lst, &st);
- memcpy (ptr (void, a1), &lst, sizeof (lst));
- break;
- case 1039: // lstat
- ret = map (lstat (str (a0), &st));
- stat_to_linux_stat (&lst, &st);
- memcpy (ptr (void, a1), &lst, sizeof (lst));
- break;
- case 1062: // time
- ret = enosys ("time");
- break;
- case 2011: // getmainvars
- ret = enosys ("getmainvars");
- break;
- case 2048:
- fprintf (stderr, "DEBUG: %u\n", a0);
- ret = 0;
- break;
- default:
- warnx ("%08x: unimplemented syscall %u", pc - 4, a7);
- ret = -map_errno (ENOSYS);
- break;
- }
- cpu_set (10, ret);
-}
-
blob - 5df22c2c59aad064533fec3b092b5bd3b62773b7
blob + f107b56f5fe7a8f694784c2a8903a7c54f1e5c14
--- syscalls.inc
+++ syscalls.inc
.set SYS_pwrite, 68
.set SYS_preadv, 69
.set SYS_pwritev, 70
-.set SYS_pwritev, 71
+.set SYS_sendfile, 71
.set SYS_pselect6, 72
.set SYS_ppoll, 73
.set SYS_signalfd4, 74
.set SYS_tkill, 130
.set SYS_tgkill, 131
.set SYS_signalstack, 132
-.set SYS_sigaction, 133
+.set SYS_sigsuspend, 133
.set SYS_sigaction, 134
.set SYS_rt_sigprocmask, 135
.set SYS_sigpending, 136
.set SYS_lstat, 1039
.set SYS_time, 1062
.set SYS_getmainvars, 2011
+.set SYS_debug, 2048
blob - e2cf2fffaab6a3f386b08769438e3f48c8d37b19
blob + 85a84552dd1982a85a006dc9c3b5193fa5b25c11
--- test.S
+++ test.S
arg0:
path: .string "./hello.elf"
argv:
- .int arg0
- .int 0
+ .dword arg0
+ .dword 0
envp:
- .int 0
+ .dword 0
.section .text
.global _start
li a7, SYS_write
ecall
-
li a0, 0
li a7, SYS_exit
ecall
-# printhex(u32 a0)
+# printhex(u64 a0)
printhex:
addi sp, sp, -12
sw s0, 8(sp)
sw s1, 4(sp)
- li s0, 28
+ li s0, 52
mv s1, a0
.Loop: