commit 502e1ef880c10f53d5a8c8ea78a8b9f2fd4a5977 from: Benjamin Stürz date: Sun Jun 16 00:35:27 2024 UTC many minor changes - initialize the loglevel from LINURV_LOGLEVEL - improve logging of ecall - fix running programs by exec*p - fix *stat*() commit - 1927278bfae34067f3006f13d739c0351f14a1d2 commit + 502e1ef880c10f53d5a8c8ea78a8b9f2fd4a5977 blob - 038e3eabdf2b72e8a0eb09c150efc3ad81ad0ebf blob + bb18a8d865b5c24e0ade1a9488bb36d2f20106de --- Makefile +++ Makefile @@ -30,7 +30,7 @@ run: linurv ${PROGS} cp -f linurv rootfs/bin cp -f ${PROGS} rootfs/bin cp -f test.txt rootfs/ - ${CHROOT} rootfs /bin/linurv /bin/$T.elf + ${CHROOT} rootfs /bin/linurv -v /bin/$T.elf distclean: clean (cd tools; ${MAKE} distclean) blob - 60f901e6468c5e851aa49a7cac9874e15027d194 blob + 4f3bb6e1a4bb70d41d87025a1e948d9fc9a1ce9d --- examples/test.c +++ examples/test.c @@ -1,4 +1,7 @@ +#include +#include #include +#include #include #include #include @@ -59,7 +62,7 @@ int main (int argc, char *argv[]) { printf ("Result: %u\n", mul (3, 2)); - execl ("/bin/ksh", "/bin/ksh", NULL); + execlp ("ksh", "ksh", NULL); return 0; } blob - 9531dd891e95809b8f341424073df5a2e1596f40 blob + bc34f26155fd92483965e8e475cd02bf467bb46d --- src/ecall.c +++ src/ecall.c @@ -104,15 +104,15 @@ static void stat_to_linux_stat (struct linux_stat64 *l { 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->ino = st->st_ino; + lst->mode = st->st_mode; + lst->nlink = st->st_nlink; + lst->uid = st->st_uid; + lst->gid = st->st_gid; + lst->rdev = st->st_rdev; + lst->size = st->st_size; + lst->blksize = st->st_blksize; + lst->blocks = st->st_blocks; lst->atime = st->st_atim.tv_sec; lst->atime_ns = st->st_atim.tv_nsec; lst->mtime = st->st_mtim.tv_sec; @@ -249,11 +249,35 @@ static int mmap_prot (int x) o |= PROT_READ; if (x & 0x02) o |= PROT_WRITE; + return o; +} + +static int map_at (int fd) +{ + return fd == -100 ? AT_FDCWD : fd; +} + +static int map_access (int x) +{ + int o = 0; + + if (x == 0) + return F_OK; + + if (x & 1) + o |= X_OK; + if (x & 2) + o |= W_OK; + if (x & 4) + o |= R_OK; + return o; } #define ptr(T, x) ((T *)(x)) #define str(x) ptr (const char, x) +#define dbg0(fmt) debug (fmt ": %ld", ret) +#define dbg(fmt, ...) debug (fmt ": %ld", __VA_ARGS__, ret) void ecall (void) { struct linux_stat64 lst; @@ -268,27 +292,36 @@ void ecall (void) const u64 a4 = cpu_get (14); const u64 a5 = cpu_get (15); const u64 a7 = cpu_get (17); + const int i0 = (int)a0; + const int i1 = (int)a1; + const int i2 = (int)a2; + const int i3 = (int)a3; + const int i4 = (int)a4; const char *name = NULL; if (a7 <= SYS_debug) name = syscall_names[a7]; - debug ( - "ecall a7=%"PRIu64" [%s], a0=%"PRIu64", a1=%"PRIu64", a2=%"PRIu64", a3=%"PRIu64", a4=%"PRIu64", a5=%"PRIu64, - a7, name, a0, a1, a2, a3, a4, a5 - ); + //debug ( + // "ecall a7=%"PRIu64" [%s], a0=%"PRIu64", a1=%"PRIu64", a2=%"PRIu64", a3=%"PRIu64", a4=%"PRIu64", a5=%"PRIu64, + // a7, name, a0, a1, a2, a3, a4, a5 + //); - int tmp, tmp2; - i64 ret; + int tmp, tmp2, tmp3; + long ret; + _Static_assert (sizeof (ret) == sizeof (i64)); switch (a7) { case SYS_getcwd: ret = map (getcwd ((char *)a0, (size_t)a1) != NULL ? 0 : -1); + dbg0 ("getcwd()"); break; case SYS_dup: - ret = map (dup ((int)a0)); + ret = map (dup (i0)); + dbg ("dup(%d)", i0); break; case SYS_dup3: - ret = map (dup3 ((int)a0, (int)a1, (int)a2)); + ret = map (dup3 (i0, i1, i2)); + dbg ("dup3(%d, %d, %d)", i0, i1, i2); break; case SYS_fcntl: ret = enosys ("fcntl"); @@ -297,25 +330,32 @@ void ecall (void) ret = enosys ("ioctl"); break; case SYS_flock: - ret = map (flock ((int)a0, (int)a1)); + ret = map (flock (i0, i1)); + dbg ("flock(%d, %d)", i0, i1); break; case SYS_mknodat: - ret = map (mknodat ((int)a0, str (a1), (mode_t)a2, (dev_t)a3)); + ret = map (mknodat (i0, str (a1), (mode_t)a2, (dev_t)a3)); + dbg ("mknodat(%d, \"%s\", %o, %d)", i0, str (a1), i2, i3); break; case SYS_mkdirat: - ret = map (mkdirat ((int)a0, str (a1), (mode_t)a2)); + ret = map (mkdirat (i0, str (a1), (mode_t)a2)); + dbg ("mkdirat(%d, \"%s\", %o)", i0, str (a1), i2); break; case SYS_unlinkat: - ret = map (unlinkat ((int)a0, str (a1), (int)a2)); + ret = map (unlinkat (i0, str (a1), i2)); + dbg ("unlinkat(%d, \"%s\", %d)", i0, str (a1), i2); break; case SYS_symlinkat: - ret = map (symlinkat (str (a0), (int)a1, str (a2))); + ret = map (symlinkat (str (a0), i1, str (a2))); + dbg ("symlinkat(\"%s\", %d, \"%s\")", str (a0), i1, str (a2)); break; case SYS_linkat: - ret = map (linkat ((int)a0, str (a1), (int)a2, str (a3), (int)a4)); + ret = map (linkat (i0, str (a1), i2, str (a3), i4)); + dbg ("linkat(%d, \"%s\", %d, \"%s\", %d)", i0, str (a1), i2, str (a3), i4); break; case SYS_renameat: - ret = map (renameat ((int)a0, str (a1), (int)a2, str (a3))); + ret = map (renameat (i0, str (a1), i2, str (a3))); + dbg ("renameat(%d, \"%s\", %d, \"%s\")", i0, str (a1), i2, str (a3)); break; case SYS_umount: ret = enosys ("umount"); @@ -337,54 +377,70 @@ void ecall (void) break; case SYS_truncate: ret = map (truncate (str (a0), (off_t)a1)); + dbg ("truncate(\"%s\", %llu)", str (a0), (unsigned long long)a1); break; - break; case SYS_ftruncate: - ret = map (ftruncate ((int)a0, (off_t)a1)); + ret = map (ftruncate (i0, (off_t)a1)); + dbg ("ftruncate(%d, %llu)", i0, (unsigned long long)a1); break; case SYS_fallocate: ret = enosys ("fallocate"); break; case SYS_faccessat: - ret = map (faccessat ((int)a0, str (a1), (int)a2, (int)a3)); + tmp = map_at (i0); + tmp2 = map_access (i2); + tmp3 = 0; + if (i3 & 0x200) + tmp3 |= AT_EACCESS; + ret = map (faccessat (tmp, str (a1), tmp2, tmp3)); + dbg ("faccessat(%d, \"%s\", %o, %d)", tmp, str (a1), tmp2, tmp3); break; case SYS_chdir: ret = map (chdir (str (a0))); + dbg ("chdir(\"%s\")", str (a0)); break; case SYS_fchdir: - ret = map (fchdir ((int)a0)); + ret = map (fchdir (i0)); + dbg ("fchdir(%d)", i0); break; case SYS_chroot: ret = map (chroot (str (a0))); + dbg ("chroot(\"%s\")", str (a0)); break; case SYS_fchmod: - ret = map (fchmod ((int)a0, (mode_t)a1)); + ret = map (fchmod (i0, (mode_t)a1)); + dbg ("fchmod(%d, %o)", i0, i1); break; case SYS_fchmodat: - ret = map (fchmodat ((int)a0, str (a1), (mode_t)a2, (int)a3)); + tmp = map_at (i0); + ret = map (fchmodat (tmp, str (a1), (mode_t)a2, i3)); + dbg ("fchmodat(%d, \"%s\", %o, %d)", tmp, str (a1), i2, i3); break; case SYS_fchownat: - ret = map (fchownat ((int)a0, str (a1), (uid_t)a2, (gid_t)a3, (int)a4)); + tmp = map_at (i0); + ret = map (fchownat (tmp, str (a1), (uid_t)a2, (gid_t)a3, i4)); + dbg ("fchownat(%d, \"%s\", %d, %d, %d)", tmp, str (a1), i2, i3, i4); break; case SYS_fchown: - ret = map (fchown ((int)a0, (uid_t)a1, (gid_t)a2)); + ret = map (fchown (i0, (uid_t)a1, (gid_t)a2)); + dbg ("fchown(%d, %d, %d)", i0, i1, i2); break; case SYS_openat: - tmp = (int)a0; - if (tmp == -100) - tmp = AT_FDCWD; - tmp2 = open_flags ((int)a2); - debug ("openat(%d, %s, %d, %d);", tmp, str (a1), tmp2, (int)a3); - ret = map (openat (tmp, str (a1), tmp2, (int)a3)); + tmp = map_at (i0); + tmp2 = open_flags (i2); + ret = map (openat (tmp, str (a1), tmp2, i3)); + dbg ("openat(%d, %s, %d, %d)", tmp, str (a1), tmp2, i3); break; case SYS_close: - ret = map (close ((int)a0)); + ret = map (close (i0)); + dbg ("close(%d)", i0); break; case SYS_vhangup: ret = enosys ("vhangup"); break; case SYS_pipe2: - ret = map (pipe2 (ptr (int, a0), (int)a1)); + ret = map (pipe2 (ptr (int, a0), i1)); + dbg ("pipe2(%p, %d)", ptr (int, a0), i1); break; case SYS_quotactl: ret = enosys ("quotactl"); @@ -393,25 +449,32 @@ void ecall (void) ret = enosys ("getdents64"); break; case SYS_lseek: - ret = map (lseek ((int)a0, (off_t)a1, (int)a2)); + ret = map (lseek (i0, (off_t)a1, i2)); + dbg ("lseek(%d, %llu, %d)", i0, (unsigned long long)a1, i2); break; case SYS_read: - ret = map (read ((int)a0, ptr (void, a1), (size_t)a2)); + ret = map (read (i0, ptr (void, a1), (size_t)a2)); + dbg ("read(%d, %p, %zu)", i0, ptr (void, a1), (size_t)a2); break; case SYS_write: - ret = map (write ((int)a0, ptr (const void, a1), (size_t)a2)); + ret = map (write (i0, ptr (const void, a1), (size_t)a2)); + dbg ("write(%d, %p, %zu)", i0, ptr (const void, a1), (size_t)a2); break; case SYS_readv: - ret = map (readv ((int)a0, ptr (const struct iovec, a1), (int)a2)); + ret = map (readv (i0, ptr (const struct iovec, a1), i2)); + dbg ("readv(%d, %p, %d)", i0, ptr (const struct iovec, a1), i2); break; case SYS_writev: - ret = map (writev ((int)a0, ptr (const struct iovec, a1), (int)a2)); + ret = map (writev (i0, ptr (const struct iovec, a1), i2)); + dbg ("writev(%d, %p, %d)", i0, ptr (const struct iovec, a1), i2); break; case SYS_pread: - ret = map (pread ((int)a0, ptr (void, a1), (size_t)a2, (off_t)a3)); + ret = map (pread (i0, ptr (void, a1), (size_t)a2, (off_t)a3)); + dbg ("pread(%d, %p, %zu, %llu)", i0, ptr (void, a1), (size_t)a2, (unsigned long long)a3); break; case SYS_pwrite: - ret = map (pwrite ((int)a0, ptr (const void, a1), (size_t)a2, (off_t)a3)); + ret = map (pwrite (i0, ptr (const void, a1), (size_t)a2, (off_t)a3)); + dbg ("pwrite(%d, %p, %zu, %llu)", i0, ptr (const void, a1), (size_t)a2, (unsigned long long)a3); break; case SYS_preadv: ret = enosys ("preadv"); @@ -441,27 +504,35 @@ void ecall (void) ret = enosys ("tee"); break; case SYS_readlinkat: - ret = map (readlinkat ((int)a0, str (a1), ptr (char, a2), (size_t)a3)); + ret = map (readlinkat (i0, str (a1), ptr (char, a2), (size_t)a3)); + dbg ("readlinkat(%d, \"%s\", %p, %zu)", i0, str (a1), ptr (char, a2), (size_t)a3); break; case SYS_fstatat: - ret = map (fstatat ((int)a0, str (a1), &st, (int)a3)); + tmp = map_at (i0); + ret = map (fstatat (tmp, str (a1), &st, i3)); stat_to_linux_stat (&lst, &st); memcpy (ptr (void, a2), &lst, sizeof (lst)); + dbg ("fstatat(%d, \"%s\", %p, %d)", tmp, str (a1), ptr (void, a2), i3); break; case SYS_fstat: - ret = map (fstat ((int)a0, &st)); + tmp = map_at (i0); + ret = map (fstat (tmp, &st)); stat_to_linux_stat (&lst, &st); memcpy (ptr (void, a1), &lst, sizeof (lst)); + dbg ("fstat(%d, %p)", tmp, ptr (void, a1)); break; case SYS_sync: sync (); + debug ("sync()"); ret = 0; break; case SYS_fsync: - ret = map (fsync ((int)a0)); + ret = map (fsync (i0)); + dbg ("fsync(%d)", i0); break; case SYS_fdatasync: - ret = map (fdatasync ((int)a0)); + ret = map (fdatasync (i0)); + dbg ("fdatasync(%d)", i0); break; case SYS_sync_file_range: ret = enosys ("sync_file_range"); @@ -480,6 +551,7 @@ void ecall (void) break; case SYS_acct: ret = acct (str (a0)); + dbg ("acct(\"%s\")", str (a0)); break; case SYS_capget: ret = enosys ("capget"); @@ -491,7 +563,8 @@ void ecall (void) ret = enosys ("personality"); break; case SYS_exit: - exit (a0); + debug ("exit(%d)", i0); + exit (i0); ret = -1; break; case SYS_exit_group: @@ -587,12 +660,15 @@ void ecall (void) break; case SYS_sched_yield: ret = map (sched_yield ()); + dbg0 ("sched_yield()"); break; case SYS_sched_get_priority_max: - ret = map (sched_get_priority_max ((int)a0)); + ret = map (sched_get_priority_max (i0)); + dbg ("sched_get_priority_max(%d)", i0); break; case SYS_sched_get_priority_min: - ret = map (sched_get_priority_min ((int)a0)); + ret = map (sched_get_priority_min (i0)); + dbg ("sched_get_priority_min(%d)", i0); break; case SYS_sched_rr_get_interval: ret = enosys ("sched_rr_get_interval"); @@ -601,7 +677,8 @@ void ecall (void) ret = enosys ("restart_syscall"); break; case SYS_kill: - ret = map (kill ((pid_t)a0, (int)a1)); + ret = map (kill ((pid_t)a0, i1)); + dbg ("kill(%d, %d)", i0, i1); break; case SYS_tkill: ret = enosys ("tkill"); @@ -613,7 +690,8 @@ void ecall (void) ret = enosys ("signalstack"); break; case SYS_sigsuspend: - ret = enosys ("sigsuspend"); + //ret = enosys ("sigsuspend"); + ret = 0; break; case SYS_sigaction: ret = enosys ("sigaction"); @@ -634,33 +712,43 @@ void ecall (void) ret = enosys ("sigreturn"); break; case SYS_setpriority: - ret = map (setpriority ((int)a0, (id_t)a1, (int)a2)); + ret = map (setpriority (i0, (id_t)a1, i2)); + dbg ("setpriority(%d, %d, %d)", i0, i1, i2); break; case SYS_getpriority: - ret = map (getpriority ((int)a0, (id_t)a1)); + ret = map (getpriority (i0, (id_t)a1)); + dbg ("getpriority(%d, %d)", i0, i1); break; case SYS_reboot: ret = enosys ("reboot"); break; case SYS_setregid: ret = map (setregid ((gid_t)a0, (gid_t)a1)); + dbg ("setregid(%d, %d)", i0, i1); break; case SYS_setgid: ret = map (setgid ((gid_t)a0)); + dbg ("setgid(%d)", i0); break; case SYS_setreuid: ret = map (setreuid ((uid_t)a0, (uid_t)a1)); + dbg ("setreuid(%d, %d)", i0, i1); break; case SYS_setuid: ret = map (setuid ((uid_t)a0)); + dbg ("setuid(%d)", i0); break; case SYS_setresuid: #ifdef __NetBSD__ - if (a0 != a1 || a0 != a2) + if (a0 != a1 || a0 != a2) { ret = enosys ("setresuid"); - ret = map (setuid ((uid_t)a0)); + } else { + ret = map (setuid ((uid_t)a0)); + dbg ("setresuid(%d, %d, %d)", i0, i1, i2); + } #else ret = map (setresuid ((uid_t)a0, (uid_t)a1, (uid_t)a2)); + dbg ("setresuid(%d, %d, %d)", i0, i1, i2); #endif break; case SYS_getresuid: @@ -668,22 +756,28 @@ void ecall (void) ret = enosys ("getresuid"); #else ret = map (getresuid (ptr (uid_t, a0), ptr (uid_t, a1), ptr (uid_t, a2))); + dbg ("getresuid(%p, %p, %p)", ptr (uid_t, a0), ptr (uid_t, a1), ptr (uid_t, a2)); #endif break; case SYS_setresgid: #ifdef __NetBSD__ - if (a0 != a1 || a0 != a2) + if (a0 != a1 || a0 != a2) { ret = enosys ("setresgid"); - ret = map (setgid ((uid_t)a0)); + } else { + ret = map (setgid ((uid_t)a0)); + dbg ("setresgid(%d, %d, %d)", i0, i1, i2); + } #else ret = map (setresgid ((gid_t)a0, (gid_t)a1, (gid_t)a2)); + dbg ("setresgid(%d, %d, %d)", i0, i1, i2); #endif break; case SYS_getresgid: #ifdef __NetBSD__ - ret = -enosys ("getresgid"); + ret = enosys ("getresgid"); #else ret = map (getresgid (ptr (gid_t, a0), ptr (gid_t, a1), ptr (gid_t, a2))); + dbg ("getresgid(%p, %p, %p)", ptr (gid_t, a0), ptr (gid_t, a1), ptr (gid_t, a2)); #endif break; case SYS_setfsuid: @@ -697,15 +791,19 @@ void ecall (void) break; case SYS_setpgid: ret = map (setpgid ((pid_t)a0, (pid_t)a1)); + dbg ("setpgid(%d, %d)", i0, i1); break; case SYS_getpgid: ret = map (getpgid ((pid_t)a0)); + dbg ("getpgid(%d)", i0); break; case SYS_getsid: ret = map (getsid ((pid_t)a0)); + dbg ("getsid(%d)", i0); break; case SYS_setsid: ret = map (setsid ()); + dbg0 ("setsid()"); break; case SYS_setgroups: ret = enosys ("setgroups"); @@ -714,6 +812,7 @@ void ecall (void) ret = map (uname (&un)); utsname_to_linux_utsname (&lun, &un); memcpy (ptr (void, a0), &lun, sizeof (lun)); + dbg ("uname(%p)", ptr (void, a0)); break; case SYS_sethostname: ret = enosys ("sethostname"); @@ -732,6 +831,7 @@ void ecall (void) break; case SYS_umask: ret = map (umask ((mode_t)a0)); + dbg ("umask(%o)", i0); break; case SYS_prctl: ret = enosys ("prctl"); @@ -750,21 +850,27 @@ void ecall (void) break; case SYS_getpid: ret = map (getpid ()); + dbg0 ("getpid()"); break; case SYS_getppid: ret = map (getppid ()); + dbg0 ("getppid()"); break; case SYS_getuid: ret = map (getuid ()); + dbg0 ("getuid()"); break; case SYS_geteuid: ret = map (geteuid ()); + dbg0 ("geteuid()"); break; case SYS_getgid: ret = map (getgid ()); + dbg0 ("getgid()"); break; case SYS_getegid: ret = map (getegid ()); + dbg0 ("getegid()"); break; case SYS_gettid: ret = enosys ("gettid"); @@ -781,19 +887,23 @@ void ecall (void) ret = enosys ("mq_*"); break; case SYS_msgget: - ret = map(msgget ((key_t)a0, (int)a1)); + ret = map(msgget ((key_t)a0, i1)); + dbg ("msgget(%d, %d)", i0, i1); 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)); + ret = map (msgrcv (i0, ptr (void, a1), (size_t)a2, (long)a3, i4)); + dbg ("msgrcv(%d, %p, %zu, %ld, %d)", i0, ptr (void, a1), (size_t)a2, (long)a3, i4); break; case SYS_msgsnd: - ret = map (msgsnd ((int)a0, ptr (const void, a1), (size_t)a2, (int)a3)); + ret = map (msgsnd (i0, ptr (const void, a1), (size_t)a2, i3)); + dbg ("msgsnd(%d, %p, %zu, %d)", i0, ptr (const void, a1), (size_t)a2, i3); break; case SYS_semget: - ret = map (semget ((key_t)a0, (int)a1, (int)a2)); + ret = map (semget ((key_t)a0, i1, i2)); + dbg ("semget(%d, %d, %d)", i0, i1, i2); break; case SYS_semctl: ret = enosys ("semctl"); @@ -832,9 +942,11 @@ void ecall (void) break; case SYS_brk: ret = map (my_brk (a0)); + debug ("brk(%p): %p", ptr (void, a0), (void *)ret); break; case SYS_munmap: ret = map (munmap (ptr (void, a0), (size_t)a1)); + dbg ("munmap(%p, %zu)", ptr (void, a0), (size_t)a1); break; case SYS_mremap: ret = enosys ("mremap"); @@ -850,26 +962,28 @@ void ecall (void) break; case SYS_clone: if (a0 == 17 && a1 == 0) { - // fork ret = map (fork ()); + if (ret != 0) + dbg0 ("fork()"); } else { ret = enosys ("clone"); } break; case SYS_execve: + debug ("execve(\"%s\", %p, %p)", str (a0), ptr (char *, a1), ptr (char *, a2)); ret = map (my_execve (str (a0), ptr (char *, a1), ptr (char *, a2))); + debug ("execve failed with %d", ret); break; case SYS_mmap: - tmp = mmap_flags ((int)a3); - tmp2 = mmap_prot ((int)a2); - debug ("mmap (%p, %zu, %d, %d, %d, %lld);", ptr (void, a0), (size_t)a1, tmp2, tmp, (int)a4, (off_t)a5); - ptr = mmap (ptr (void, a0), (size_t)a1, tmp2, tmp, (int)a4, (off_t)a5); - debug ("ptr = %p", ptr); + tmp = mmap_flags (i3); + tmp2 = mmap_prot (i2); + ptr = mmap (ptr (void, a0), (size_t)a1, tmp2, tmp, i4, (off_t)a5); if (ptr == NULL) { ret = -map_errno (errno); } else { ret = (u64)ptr; } + debug ("mmap(%p, %zu, %o, %d, %d, %llu): %p", ptr (void, a0), (size_t)a1, tmp2, tmp, i4, (unsigned long long)a5, (void *)ret); break; case SYS_fadvise64: ret = enosys ("fadvise64"); @@ -881,29 +995,37 @@ void ecall (void) ret = enosys ("swapoff"); break; case SYS_mprotect: - tmp = mmap_prot ((int)a2); + tmp = mmap_prot (a2); ret = map (mprotect (ptr (void, a0), (size_t)a1, tmp)); + dbg ("mprotect(%p, %zu, %d)", ptr (void, a0), (size_t)a1, tmp); break; case SYS_msync: - ret = map (msync (ptr (void, a0), (size_t)a1, (int)a2)); + ret = map (msync (ptr (void, a0), (size_t)a1, i2)); + dbg ("msync(%p, %zu, %d)", ptr (void, a0), (size_t)a1, i2); break; case SYS_mlock: ret = map (mlock (ptr (void, a0), (size_t)a1)); + dbg ("mlock(%p, %zu)", ptr (void, a0), (size_t)a1); break; case SYS_munlock: ret = map (munlock (ptr (void, a0), (size_t)a1)); + dbg ("munlock(%p, %zu)", ptr (void, a0), (size_t)a1); break; case SYS_mlockall: - ret = map (mlockall ((int)a0)); + ret = map (mlockall (i0)); + dbg ("mlockall(%d)", i0); break; case SYS_munlockall: ret = map (munlockall ()); + dbg0 ("munlockall()"); break; case SYS_mincore: ret = enosys ("mincore"); break; case SYS_madvise: - ret = map (madvise (ptr (void, a0), (size_t)a1, (int)a2)); + // TODO: MADV_* + ret = map (madvise (ptr (void, a0), (size_t)a1, i2)); + dbg ("madvise(%p, %zu, %d)", ptr (void, a0), (size_t)a1, i2); break; case SYS_remap_file_pages: ret = enosys ("remap_file_pages"); @@ -1059,30 +1181,39 @@ void ecall (void) ret = enosys ("kexec_file_load"); break; case SYS_open: - tmp = open_flags ((int)a1); - ret = map (open ((const char *)(size_t)a0, tmp, (int)a2)); + tmp = open_flags (i1); + ret = map (open (str (a0), tmp, i2)); + dbg ("open(\"%s\", %o, %d)", str (a0), tmp, i2); break; case SYS_link: ret = map (link (str (a0), str (a1))); + dbg ("link(\"%s\", \"%s\")", str (a0), str (a1)); break; case SYS_unlink: ret = map (unlink (str (a0))); + dbg ("unlink(\"%s\")", str (a0)); break; case SYS_mkdir: ret = map (mkdir (str (a0), (mode_t)a1)); + dbg ("mkdir(\"%s\", %o)", str (a0), i1); break; case SYS_access: - ret = map (access (str (a0), (int)a1)); + // TODO: *_OK + tmp = map_access (i1); + ret = map (access (str (a0), tmp)); + dbg ("access(\"%s\", %d)", str (a0), tmp); break; case SYS_stat: ret = map (stat (str (a0), &st)); stat_to_linux_stat (&lst, &st); memcpy (ptr (void, a1), &lst, sizeof (lst)); + dbg ("stat(\"%s\", %p)", str (a0), ptr (void, a1)); break; case SYS_lstat: ret = map (lstat (str (a0), &st)); stat_to_linux_stat (&lst, &st); memcpy (ptr (void, a1), &lst, sizeof (lst)); + dbg ("lstat(\"%s\", %p)", str (a0), ptr (void, a1)); break; case SYS_time: ret = enosys ("time"); blob - bfafe890605229b56f681ae7470de4cf224f94fe blob + cb238ae4659091f4c53a5e07cf31b2bb9ecc5897 --- src/exec.c +++ src/exec.c @@ -21,7 +21,6 @@ int is_executable (const Elf64_Ehdr *ehdr) int my_execve (const char *path, char **argv, char **envp) { - Elf64_Ehdr ehdr; char buffer[256], *nl, *s; int fd; @@ -29,6 +28,7 @@ int my_execve (const char *path, char **argv, char **e fd = open (path, O_RDONLY); if (fd < 0) return -1; + memset (buffer, 0, sizeof (buffer)); read (fd, buffer, 2); @@ -58,8 +58,9 @@ int my_execve (const char *path, char **argv, char **e close (fd); if (is_executable (&ehdr)) { + // TODO: otherwise the emulator can't find the executable + argv[0] = strdup (path); #if defined(__FreeBSD__) - extern char **environ; char **old_env; int st; blob - 61c6296fb607bcc75bf8caf387157710c9e5b6f3 blob + 71aa357d88b64ae841025838798dd4c7ccb427ad --- src/linurv.c +++ src/linurv.c @@ -11,7 +11,7 @@ #include #include "linurv.h" -static const char *levelstr[] = { +const char *levelstr[] = { [LOG_SILENT] = "FATAL", [LOG_ERROR] = "ERROR", [LOG_WARN] = "WARN ", @@ -183,7 +183,35 @@ static int usage (void) return 1; } -int main (int argc, char *argv[], char *envp[]) +static void set_loglevel(enum log_level level) +{ + curlevel = level; + setenv ("LINURV_LOGLEVEL", levelstr[level], 1); +} + +static void parse_loglevel (const char *s) +{ + for (int i = 0; i <= LOG_VDEBUG; ++i) { + if (strcasecmp (s, levelstr[i]) == 0) { + set_loglevel (i); + return; + } + } + errx (1, "invalid loglevel: %s", s); +} + +static void parse_env (void) +{ + char *s = getenv ("LINURV_LOGLEVEL"); + + if (s != NULL) { + parse_loglevel (s); + } else { + set_loglevel (LOG_WARN); + } +} + +int main (int argc, char *argv[]) { const char *filename; struct rlimit rl; @@ -192,25 +220,22 @@ int main (int argc, char *argv[], char *envp[]) char *base; int option; - curlevel = LOG_WARN; + parse_env (); base = basename (argv[0]); + printf ("progname: %s\n", getprogname ()); + if (strcmp (base, "linurv") == 0) { while ((option = getopt (argc, argv, "vl:")) != -1) { switch (option) { case 'l': - for (int i = 0; i <= LOG_VDEBUG; ++i) { - if (strcmp (optarg, levelstr[i]) == 0) { - curlevel = i; - break; - } - } + parse_loglevel (optarg); break; case 'v': if (curlevel < LOG_DEBUG) { - curlevel = LOG_DEBUG; + set_loglevel (LOG_DEBUG); } else if (curlevel == LOG_DEBUG) { - curlevel = LOG_VDEBUG; + set_loglevel (LOG_VDEBUG); } break; default: @@ -221,6 +246,7 @@ int main (int argc, char *argv[], char *envp[]) argc -= optind; } + if (argc < 1) return usage (); @@ -233,9 +259,9 @@ int main (int argc, char *argv[], char *envp[]) stack_size = 1 << 20; } - for (envc = 0; envp[envc] != NULL; ++envc); + for (envc = 0; environ[envc] != NULL; ++envc); - setup_stack (stack_size, argc, argv, envc, envp); + setup_stack (stack_size, argc, argv, envc, environ); while (1) { const u32 instr = cpu_fetch (); blob - 9d4d706388fd3ee14b387733af2623db578b5fc2 blob + e139c889771a6f6a503315250cf80acbad06cd75 --- src/linurv.h +++ src/linurv.h @@ -64,7 +64,9 @@ typedef unsigned int uint; extern u64 pc; extern u64 brkval; extern const char *interpreter; +extern const char *levelstr[]; extern enum log_level curlevel; +extern char **environ; u32 cpu_fetch (void); u64 cpu_get (size_t reg);