commit - c791d5e82e697eff4e99ced039d29bd8d2029da3
commit + 80a2e72f5b5cd624675a0869774e5c2cff47a47c
blob - f8ced90bcaa3a38a746c653e9d44a09d2fd308c4
blob + a0baec7dd2d222cb9851c15e968d68c23e0ddede
--- .gitignore
+++ .gitignore
*.core
*.pdf
rootfs
-rvemu
+linurv
config.mk.local
blob - 1919ea85b5986250356e8214c1ad812230ceb1d6
blob + a53351c28db4a20b91144e436234f89f1169f586
--- Makefile
+++ Makefile
CFLAGS = ${CFLAGS_OS} ${COPT} -std=c2x
LDFLAGS = ${LDFLAGS_OS} -lpthread
-OBJ = src/rvemu.o src/ecall.o src/cpu.o src/exec.o
+OBJ = src/linurv.o src/ecall.o src/cpu.o src/exec.o
T = asm
PROGS = examples/test.elf \
examples/echo.elf \
examples/hello.elf \
examples/asm.elf
-all: rvemu ${PROGS}
+all: linurv ${PROGS}
od: examples/$T.elf
${CROSS}-objdump -d examples/$T.elf | less
-run: rvemu ${PROGS}
+run: linurv ${PROGS}
mkdir -p rootfs/bin
- cp -f rvemu rootfs/bin
+ cp -f linurv rootfs/bin
cp -f ${PROGS} rootfs/bin
cp -f test.txt rootfs/
- ${CHROOT} rootfs /bin/rvemu /bin/$T.elf
+ ${CHROOT} rootfs /bin/linurv /bin/$T.elf
distclean: clean
(cd tools; ${MAKE} distclean)
clean:
- rm -f rvemu src/*.o examples/*.elf *.core src/syscalls.h
+ rm -f linurv src/*.o examples/*.elf *.core src/syscalls.h
rm -rf rootfs
-install: rvemu
+install: linurv
mkdir -p ${DESTDIR}${PREFIX}/bin
- cp -f rvemu ${DESTDIR}${PREFIX}/bin/
+ cp -f linurv ${DESTDIR}${PREFIX}/bin/
-rvemu: ${OBJ}
+linurv: ${OBJ}
${CC} -o $@ ${OBJ} ${LDFLAGS}
src/ecall.o: src/syscalls.h
blob - 075f9f812a8cba378fee259e930a8050d929f4c7
blob + 6aab3a3a59ada2565b3f6779c303333bfcb266b6
--- src/cpu.c
+++ src/cpu.c
#include <inttypes.h>
-#include "rvemu.h"
+#include "linurv.h"
static u64 regs[31];
u64 pc;
blob - 5c4a53f2813521dd056d4782dafd04e7c74dcae6
blob + 24edc75616e9d0e8c904863d33c37c7de7d42af7
--- src/ecall.c
+++ src/ecall.c
#include <sched.h>
#include <errno.h>
#include "syscalls.h"
-#include "rvemu.h"
+#include "linurv.h"
struct linux_stat64 {
u64 dev;
blob - 156608f9903fa2c229f72dc09bf641c0865a2f3a
blob + 45391396df92dfe98e982e147b7c07508a1ccd41
--- src/exec.c
+++ src/exec.c
#include <fcntl.h>
#include <errno.h>
#include <ctype.h>
-#include "rvemu.h"
+#include "linurv.h"
int is_executable (const Elf64_Ehdr *ehdr)
old_env = environ;
environ = envp;
- st = execvp ("rvemu", argv);
+ st = execvp ("linurv", argv);
environ = old_env;
return st;
#else
- return execvpe ("rvemu", argv, envp);
+ return execvpe ("linurv", argv, envp);
#endif
}
blob - b2820cb92338ed9fca5224d5a138323dc27d6cf7 (mode 644)
blob + /dev/null
--- src/rvemu.c
+++ /dev/null
-#include <sys/resource.h>
-#include <sys/mman.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <libgen.h>
-#include <fcntl.h>
-#include <errno.h>
-#include "rvemu.h"
-
-u64 brkval = 0;
-
-static void load_segment (int fd, Elf64_Phdr phdr)
-{
- size_t end, len, ps;
- int prot = 0;
- void *addr, *ptr;
-
-
- if (phdr.p_filesz > phdr.p_memsz)
- errx (1, "invalid program header: p_filesz > p_memsz");
-
- ps = getpagesize ();
- addr = (void *)(phdr.p_vaddr & ~(ps - 1));
- len = phdr.p_memsz + phdr.p_vaddr - (size_t)addr;
-
- ptr = mmap (
- addr,
- len,
- PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANON | MAP_FIXED,
- -1,
- 0
- );
- eprintf ("mmap (%p, %#zx) = %p;\n", addr, len, ptr);
-
- if (ptr == NULL)
- err (1, "mmap()");
-
- if (phdr.p_filesz > 0) {
- lseek (fd, phdr.p_offset, SEEK_SET);
- read (fd, (void *)phdr.p_vaddr, phdr.p_filesz);
- }
-
- if (phdr.p_flags & (PF_R | PF_X))
- prot |= PROT_READ;
- if (phdr.p_flags & PF_W)
- prot |= PROT_WRITE;
- if (mprotect (addr, len, prot) != 0)
- err (1, "mprotect()");
-
- end = (phdr.p_vaddr + phdr.p_memsz + ps - 1) & ~(ps - 1);
- if (end > brkval)
- brkval = end;
-}
-
-static void load_image (const char *filename)
-{
- Elf64_Ehdr ehdr;
- int fd;
-
- fd = open (filename, O_RDONLY);
- if (fd < 0)
- err (1, "open('%s')", filename);
-
- if (read (fd, &ehdr, sizeof (ehdr)) != sizeof (ehdr))
- err (1, "read('%s')", filename);
-
- if (!is_executable (&ehdr))
- errx (1, "Invalid argument");
-
- pc = ehdr.e_entry;
-
- for (unsigned i = 0; i < ehdr.e_phnum; ++i) {
- Elf64_Phdr phdr;
-
- lseek (fd, ehdr.e_phoff + i * ehdr.e_phentsize, SEEK_SET);
- if (read (fd, &phdr, ehdr.e_phentsize) != ehdr.e_phentsize)
- err (1, "failed to read program header %u", i);
-
- switch (phdr.p_type) {
- case PT_NULL:
- break;
- case PT_LOAD:
- load_segment (fd, phdr);
- break;
- case PT_INTERP:
- case PT_DYNAMIC:
- errx (1, "shared objects not supported");
- default:
- //warnx ("%u: ignoring program header: %x",
- // i, (unsigned)phdr.p_type);
- break;
- }
- }
- close (fd);
-}
-
-static void cpu_push (u64 val)
-{
- cpu_set (REG_sp, cpu_get (REG_sp) - 8);
- write_u64 (cpu_get (REG_sp), val);
-}
-
-static void setup_stack (
- u64 stack_size,
- int argc,
- char **argv,
- int envc,
- char **envp
-) {
- void *ptr;
- void *stack_bottom;
-
- // set stack pointer
- cpu_set (REG_sp, 0x80000000);
-
- stack_bottom = (void *)(u64)(0x80000000 - stack_size);
- ptr = mmap (
- stack_bottom,
- stack_size,
- PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANON | MAP_FIXED,
- -1,
- 0
- );
-
- if (ptr != stack_bottom)
- err (1, "failed to map stack");
-
- // auxv
- cpu_push (0);
- cpu_push (0);
- cpu_push (getegid ());
- cpu_push (14);
- cpu_push (getgid ());
- cpu_push (13);
- cpu_push (geteuid ());
- cpu_push (12);
- cpu_push (getuid ());
- cpu_push (11);
- cpu_push (getpagesize ());
- cpu_push (6);
-
- cpu_push (0);
- for (int i = envc - 1; i >= 0; --i)
- cpu_push ((u64)envp[i]);
- cpu_push (0);
- for (int i = argc - 1; i >= 0; --i)
- cpu_push ((u64)argv[i]);
- cpu_push (argc);
-}
-
-int main (int argc, char *argv[], char *envp[])
-{
- const char *filename;
- struct rlimit rl;
- size_t stack_size;
- int fd, envc;
- char *base;
- void *ptr;
-
- base = basename (argv[0]);
-
- if (strcmp (base, "rvemu") == 0) {
- if (argc < 2)
- errx (1, "usage: rvemu file");
- ++argv;
- --argc;
- }
-
- filename = argv[0];
- load_image (filename);
-
- if (getrlimit (RLIMIT_STACK, &rl) == 0) {
- stack_size = rl.rlim_cur;
- } else {
- stack_size = 1 << 20;
- }
-
- for (envc = 0; envp[envc] != NULL; ++envc);
-
- setup_stack (stack_size, argc, argv, envc, envp);
-
- while (1) {
- const u32 instr = cpu_fetch ();
- cpu_exec (instr);
- }
-
- return 0;
-}
blob - /dev/null
blob + 8528c3aaf97812d6a936b0ea33e916ab0ce836df (mode 644)
--- /dev/null
+++ src/linurv.c
+#include <sys/resource.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <libgen.h>
+#include <fcntl.h>
+#include <errno.h>
+#include "linurv.h"
+
+u64 brkval = 0;
+
+static void load_segment (int fd, Elf64_Phdr phdr)
+{
+ size_t end, len, ps;
+ int prot = 0;
+ void *addr, *ptr;
+
+
+ if (phdr.p_filesz > phdr.p_memsz)
+ errx (1, "invalid program header: p_filesz > p_memsz");
+
+ ps = getpagesize ();
+ addr = (void *)(phdr.p_vaddr & ~(ps - 1));
+ len = phdr.p_memsz + phdr.p_vaddr - (size_t)addr;
+
+ ptr = mmap (
+ addr,
+ len,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON | MAP_FIXED,
+ -1,
+ 0
+ );
+ eprintf ("mmap (%p, %#zx) = %p;\n", addr, len, ptr);
+
+ if (ptr == NULL)
+ err (1, "mmap()");
+
+ if (phdr.p_filesz > 0) {
+ lseek (fd, phdr.p_offset, SEEK_SET);
+ read (fd, (void *)phdr.p_vaddr, phdr.p_filesz);
+ }
+
+ if (phdr.p_flags & (PF_R | PF_X))
+ prot |= PROT_READ;
+ if (phdr.p_flags & PF_W)
+ prot |= PROT_WRITE;
+ if (mprotect (addr, len, prot) != 0)
+ err (1, "mprotect()");
+
+ end = (phdr.p_vaddr + phdr.p_memsz + ps - 1) & ~(ps - 1);
+ if (end > brkval)
+ brkval = end;
+}
+
+static void load_image (const char *filename)
+{
+ Elf64_Ehdr ehdr;
+ int fd;
+
+ fd = open (filename, O_RDONLY);
+ if (fd < 0)
+ err (1, "open('%s')", filename);
+
+ if (read (fd, &ehdr, sizeof (ehdr)) != sizeof (ehdr))
+ err (1, "read('%s')", filename);
+
+ if (!is_executable (&ehdr))
+ errx (1, "Invalid argument");
+
+ pc = ehdr.e_entry;
+
+ for (unsigned i = 0; i < ehdr.e_phnum; ++i) {
+ Elf64_Phdr phdr;
+
+ lseek (fd, ehdr.e_phoff + i * ehdr.e_phentsize, SEEK_SET);
+ if (read (fd, &phdr, ehdr.e_phentsize) != ehdr.e_phentsize)
+ err (1, "failed to read program header %u", i);
+
+ switch (phdr.p_type) {
+ case PT_NULL:
+ break;
+ case PT_LOAD:
+ load_segment (fd, phdr);
+ break;
+ case PT_INTERP:
+ case PT_DYNAMIC:
+ errx (1, "shared objects not supported");
+ default:
+ //warnx ("%u: ignoring program header: %x",
+ // i, (unsigned)phdr.p_type);
+ break;
+ }
+ }
+ close (fd);
+}
+
+static void cpu_push (u64 val)
+{
+ cpu_set (REG_sp, cpu_get (REG_sp) - 8);
+ write_u64 (cpu_get (REG_sp), val);
+}
+
+static void setup_stack (
+ u64 stack_size,
+ int argc,
+ char **argv,
+ int envc,
+ char **envp
+) {
+ void *ptr;
+ void *stack_bottom;
+
+ // set stack pointer
+ cpu_set (REG_sp, 0x80000000);
+
+ stack_bottom = (void *)(u64)(0x80000000 - stack_size);
+ ptr = mmap (
+ stack_bottom,
+ stack_size,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON | MAP_FIXED,
+ -1,
+ 0
+ );
+
+ if (ptr != stack_bottom)
+ err (1, "failed to map stack");
+
+ // auxv
+ cpu_push (0);
+ cpu_push (0);
+ cpu_push (getegid ());
+ cpu_push (14);
+ cpu_push (getgid ());
+ cpu_push (13);
+ cpu_push (geteuid ());
+ cpu_push (12);
+ cpu_push (getuid ());
+ cpu_push (11);
+ cpu_push (getpagesize ());
+ cpu_push (6);
+
+ cpu_push (0);
+ for (int i = envc - 1; i >= 0; --i)
+ cpu_push ((u64)envp[i]);
+ cpu_push (0);
+ for (int i = argc - 1; i >= 0; --i)
+ cpu_push ((u64)argv[i]);
+ cpu_push (argc);
+}
+
+int main (int argc, char *argv[], char *envp[])
+{
+ const char *filename;
+ struct rlimit rl;
+ size_t stack_size;
+ int fd, envc;
+ char *base;
+ void *ptr;
+
+ base = basename (argv[0]);
+
+ if (strcmp (base, "linurv") == 0) {
+ if (argc < 2)
+ errx (1, "usage: linurv file");
+ ++argv;
+ --argc;
+ }
+
+ filename = argv[0];
+ load_image (filename);
+
+ if (getrlimit (RLIMIT_STACK, &rl) == 0) {
+ stack_size = rl.rlim_cur;
+ } else {
+ stack_size = 1 << 20;
+ }
+
+ for (envc = 0; envp[envc] != NULL; ++envc);
+
+ setup_stack (stack_size, argc, argv, envc, envp);
+
+ while (1) {
+ const u32 instr = cpu_fetch ();
+ cpu_exec (instr);
+ }
+
+ return 0;
+}
blob - f1fa870f78600a53528abcc226d280124e392286 (mode 644)
blob + /dev/null
--- src/rvemu.h
+++ /dev/null
-#include <stddef.h>
-#include <stdint.h>
-#include <libelf.h>
-#include <stdio.h>
-#include <err.h>
-
-#define DEBUG 0
-
-#if DEBUG
-# define eprintf(...) fprintf (stderr, __VA_ARGS__)
-#else
-# 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 uint64_t u64;
-
-typedef int8_t i8;
-typedef int16_t i16;
-typedef int32_t i32;
-typedef int64_t i64;
-
-typedef unsigned int uint;
-
-extern u64 pc;
-extern u64 brkval;
-extern const char *interpreter;
-
-u32 cpu_fetch (void);
-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, 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))
-#define read_u32(ptr) (*(const u32 *)(size_t)(ptr))
-#define read_u64(ptr) (*(const u64 *)(size_t)(ptr))
-#define read_i8(ptr) (*(const i8 *)(size_t)(ptr))
-#define read_i16(ptr) (*(const i16 *)(size_t)(ptr))
-#define read_i32(ptr) (*(const i32 *)(size_t)(ptr))
-#define read_i64(ptr) (*(const i64 *)(size_t)(ptr))
-#define write_u8(ptr, val) (*(u8 *)(size_t)(ptr) = (val))
-#define write_u16(ptr, val) (*(u16 *)(size_t)(ptr) = (val))
-#define write_u32(ptr, val) (*(u32 *)(size_t)(ptr) = (val))
-#define write_u64(ptr, val) (*(u64 *)(size_t)(ptr) = (val))
blob - /dev/null
blob + f1fa870f78600a53528abcc226d280124e392286 (mode 644)
--- /dev/null
+++ src/linurv.h
+#include <stddef.h>
+#include <stdint.h>
+#include <libelf.h>
+#include <stdio.h>
+#include <err.h>
+
+#define DEBUG 0
+
+#if DEBUG
+# define eprintf(...) fprintf (stderr, __VA_ARGS__)
+#else
+# 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 uint64_t u64;
+
+typedef int8_t i8;
+typedef int16_t i16;
+typedef int32_t i32;
+typedef int64_t i64;
+
+typedef unsigned int uint;
+
+extern u64 pc;
+extern u64 brkval;
+extern const char *interpreter;
+
+u32 cpu_fetch (void);
+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, 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))
+#define read_u32(ptr) (*(const u32 *)(size_t)(ptr))
+#define read_u64(ptr) (*(const u64 *)(size_t)(ptr))
+#define read_i8(ptr) (*(const i8 *)(size_t)(ptr))
+#define read_i16(ptr) (*(const i16 *)(size_t)(ptr))
+#define read_i32(ptr) (*(const i32 *)(size_t)(ptr))
+#define read_i64(ptr) (*(const i64 *)(size_t)(ptr))
+#define write_u8(ptr, val) (*(u8 *)(size_t)(ptr) = (val))
+#define write_u16(ptr, val) (*(u16 *)(size_t)(ptr) = (val))
+#define write_u32(ptr, val) (*(u32 *)(size_t)(ptr) = (val))
+#define write_u64(ptr, val) (*(u64 *)(size_t)(ptr) = (val))