commit a8ceaca4fff83dffd72f34c096e41d5a0cdfce5c from: Benjamin Stürz date: Tue Feb 20 19:24:05 2024 UTC cleanup commit - 112859b68b19ef3ede8c8d6b462e29e3a4231197 commit + a8ceaca4fff83dffd72f34c096e41d5a0cdfce5c blob - d5a600d820bf688595bba5fe8d1422b4282f2199 blob + c0e9ed862854b37f31f7b51c55cc177ce45f5806 --- .gitignore +++ .gitignore @@ -6,12 +6,13 @@ tools/libexec tools/riscv64-unknown-linux-musl tools/share tools/src +src/syscalls.h +src/*.o *.swp *.core *.o *.elf *.pdf rootfs -syscalls.h rvemu blob - c1b64dea367cf49f7f9f16f859eb4ff99407573e blob + cc581bb65cc25b6023263787fb09d3492a7b8c5e --- Makefile +++ Makefile @@ -9,8 +9,8 @@ TARGET = riscv64-unknown-linux-musl CROSS = ./tools/bin/${TARGET} CFLAGS = -std=c2x -fPIC -O0 -g LDFLAGS = -pie -static -lpthread -OBJ = rvemu.o ecall.o cpu.o exec.o -PROGS = test.elf hello.elf +OBJ = src/rvemu.o src/ecall.o src/cpu.o src/exec.o +PROGS = test.elf all: rvemu ${PROGS} @@ -18,7 +18,7 @@ od: test.elf ${CROSS}-objdump -d test.elf | less clean: - rm -f rvemu *.o *.elf *.core syscalls.h + rm -f rvemu src/*.o *.elf *.core src/syscalls.h rm -rf rootfs install: rvemu @@ -35,21 +35,15 @@ run: rvemu ${PROGS} rvemu: ${OBJ} ${CC} -o $@ ${OBJ} ${LDFLAGS} -ecall.o: syscalls.h +src/ecall.o: src/syscalls.h -syscalls.h: syscalls.inc +src/syscalls.h: src/syscalls.inc sed 's/^\.set \(SYS_[a-z0-9_]*\), \([0-9]*\)$$/#define \1 \2/' \ - < syscalls.inc > syscalls.h + < src/syscalls.inc > $@ -.c.o: rvemu.h +.c.o: src/rvemu.h ${CC} -c -o $@ $< ${CFLAGS} -.S.o: syscalls.inc - ${CROSS}-as -o $@ $< - -.c.elf: linker.ld +.c.elf: ${CROSS}-gcc -o $@ $< - -.o.elf: linker.ld - ${CROSS}-ld -s -T linker.ld -o $@ $< blob - 44537fe39bb4e8ea22f90917381b9327ef99beb9 (mode 644) blob + /dev/null --- cpu.c +++ /dev/null @@ -1,394 +0,0 @@ -#include "rvemu.h" - -static u64 regs[31]; -u64 pc; - -void cpu_set (size_t reg, u64 val) -{ - if (reg > 0) - regs[reg - 1] = val; -} - -u64 cpu_get (size_t reg) -{ - return reg > 0 ? regs[reg - 1] : 0; -} - -u32 cpu_fetch (void) -{ - const u32 i = *(const u32 *)(size_t)pc; - //eprintf ("%08x: %08x\n", cpu->pc, i); - pc += 4; - return i; -} - -static i64 extend (i32 x) -{ - return x; -} - -#define log(fmt, ...) eprintf ("%08llx: " fmt "\n", pc - 4, __VA_ARGS__) -void cpu_exec (u32 instr) -{ - const char *name; - const u8 rd = (instr >> 7) & 0x1f; - const u8 funct3 = (instr >> 12) & 0x7; - const u8 rs1 = (instr >> 15) & 0x1f; - const u8 rs2 = (instr >> 20) & 0x1f; - const u8 funct7 = instr >> 25; - const u8 funct6 = instr >> 26; - 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 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)); - const u16 funct10 = (funct7 << 3) | funct3; - const u8 shamt = imm_i & 0x3f; - - u64 a, b, c; - switch (instr & 0x7f) { - case 0b0110111: // lui rd, uimm - log ("lui x%u, %llu", (uint)rd, imm_u); - cpu_set (rd, imm_u); - break; - case 0b0010111: // auipc rd, uimm - log ("auipc x%u, %llu", (uint)rd, imm_u); - cpu_set (rd, pc + imm_u - 4); - break; - case 0b1101111: // jal rd, jimm - log ("jal x%u, %lld", (uint)rd, imm_j); - cpu_set (rd, pc); - pc += imm_j - 4; - break; - case 0b1100111: // jalr rd, rs1, iimm - switch (funct3) { - case 0b000: - log ("jalr x%u, x%u, %lld", (uint)rd, (uint)rs1, imm_i); - cpu_set (rd, pc); - pc = cpu_get (rs1); - break; - default: - goto ud; - } - break; - case 0b1100011: // bcc rs1, rs2, bimm - a = cpu_get (rs1); - b = cpu_get (rs2); - switch (funct3) { - case 0b000: - name = "beq"; - c = a == b; - break; - case 0b001: - name = "bne"; - c = a != b; - break; - case 0b100: - name = "blt"; - c = (i64)a < (i64)b; - break; - case 0b101: - name = "bge"; - c = (i64)a >= (i64)b; - break; - case 0b110: - name = "bltu"; - c = a < b; - break; - case 0b111: - name = "bgeu"; - c = a >= b; - break; - default: - goto ud; - } - log ("%s x%u, x%u, %d", name, (uint)rs1, (uint)rs2, (int)imm_b); - if (c) - pc += imm_b - 4; - break; - case 0b0000011: // lx rd, iimm(rs1) - a = cpu_get (rs1) + imm_i; - switch (funct3) { - case 0b000: // lb - name = "lb"; - b = (i64)read_i8 (a); - break; - case 0b001: // lh - name = "lh"; - b = (i64)read_i16 (a); - break; - case 0b010: // lw - name = "lw"; - 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); - break; - case 0b101: // lhu - name = "lhu"; - b = read_u16 (a); - break; - case 0b110: // lwu - name = "lwu"; - b = read_u32 (a); - break; - default: - goto ud; - } - log ("%s x%u, %d(x%u)", name, (uint)rd, (int)imm_i, (uint)rs1); - cpu_set (rd, b); - break; - case 0b0100011: // sx rs2, simm(rs1) - a = cpu_get (rs2); - b = cpu_get (rs1) + imm_s; - switch (funct3) { - case 0b000: // sb - name = "sb"; - write_u8 (b, a); - break; - case 0b001: // sh - name = "sh"; - write_u16 (b, a); - break; - case 0b010: // sw - name = "sw"; - write_u32 (b, a); - break; - case 0b011: // sd - name = "sd"; - write_u64 (b, a); - break; - default: - goto ud; - } - log ("%s x%u, %d(x%u)", name, (uint)rs2, (int)imm_s, (uint)rs1); - break; - case 0b0010011: // alui rd, rs1, iimm - a = cpu_get (rs1); - b = imm_i; - switch (funct3) { - case 0b000: // addi - name = "addi"; - c = a + b; - break; - case 0b001: // slli - if (funct6 != 0) - goto ud; - name = "slli"; - c = a << shamt; - break; - case 0b010: // slti - name = "slti"; - c = (i64)a < (i64)b; - break; - case 0b011: // sltiu - name = "sltiu"; - c = a < b; - break; - case 0b100: // xori - name = "xori"; - c = a ^ b; - break; - case 0b101: // srli/srai - switch (funct6) { - case 0b000000: - name = "srli"; - c = a >> shamt; - break; - case 0b010000: - name = "srai"; - c = (i64)a >> shamt; - break; - default: - goto ud; - } - break; - case 0b110: // ori - name = "ori"; - c = a | b; - break; - case 0b111: // andi - name = "andi"; - c = a & b; - break; - default: - goto ud; - } - log ("%s x%u, x%u, %lld", 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; - switch (funct7) { - case 0b0000000: - name = "srliw"; - c = (u32)a >> shamt; - break; - case 0b0100000: - name = "sraiw"; - c = (i32)a >> shamt; - break; - default: - goto ud; - } - break; - default: - goto ud; - } - c &= 0x00000000ffffffff; - c = extend (c); - log ("%s x%u, x%u, %lld", name, (uint)rd, (uint)rs1, (i64)imm_i); - cpu_set (rd, c); - break; - case 0b0110011: // alu rd, rs1, rs2 - a = cpu_get (rs1); - b = cpu_get (rs2); - switch (funct10) { - case 0b0000000'000: - name = "add"; - c = a + b; - break; - case 0b0000001'000: - name = "mul"; - c = a * b; - break; - case 0b0100000'000: - name = "sub"; - c = a - b; - break; - case 0b0000000'001: - name = "sll"; - c = a << b; - break; - case 0b0000000'010: - name = "slt"; - c = (i64)a < (i64)b; - break; - case 0b0000000'011: - name = "sltu"; - c = a < b; - break; - case 0b0000000'100: - name = "xor"; - c = a ^ b; - break; - case 0b0000001'100: - name = "div"; - c = b != 0 ? (i64)a / (i64)b : -1; - break; - case 0b0000000'101: - name = "srl"; - c = a >> (b & 0x3f); - break; - case 0b0000001'101: - name = "divu"; - c = b != 0 ? a / b : -1; - break; - case 0b0100000'101: - name = "sra"; - c = (i64)a >> (b & 0x3f); - break; - case 0b0000000'110: - name = "or"; - c = a | b; - break; - case 0b0000001'110: - name = "rem"; - c = b != 0 ? (i64)a % (i64)b : -1; - break; - case 0b0000000'111: - name = "and"; - c = a & b; - break; - case 0b0000001'111: - name = "remu"; - c = b != 0 ? a % b : -1; - break; - } - log ("%s x%u, x%u, x%u", name, (uint)rd, (uint)rs1, (uint)rs2); - cpu_set (rd, c); - break; - case 0b0111011: // aluw - a = cpu_get (rs1); - b = cpu_get (rs2); - switch (funct10) { - case 0b0000000'000: // addw - name = "addw"; - c = a + b; - break; - case 0b0100000'000: // subw - name = "addw"; - c = a - b; - break; - case 0b0000000'001: // sllw - name = "sllw"; - c = a << (b & 0x1f); - break; - case 0b0000000'101: // srlw - name = "srlw"; - c = a >> (b & 0x1f); - break; - case 0b0100000'101: // sraw - name = "sraw"; - c = (i64)a >> (b & 0x1f); - break; - default: - goto ud; - } - log ("%s x%u, x%u, x%u", name, (uint)rd, (uint)rs1, (uint)rs2); - cpu_set (rd, extend ((i32)a)); - break; - case 0b0001111: // fence/fence.tso/pause - eprintf ("%08llx: efence\n", pc - 4); - break; - case 0b1110011: // ecall/ebreak - if ((instr >> 20) & 1) { - eprintf ("%08llx: ebreak\n", pc - 4); - __asm __volatile__ ("int $3"); - } else { - log ( - "ecall a0=%llu, a1=%llu, a2=%llu, a3=%llu, a4=%llu, a5=%llu, a7=%llu", - cpu_get (10), - cpu_get (11), - cpu_get (12), - cpu_get (13), - cpu_get (14), - cpu_get (15), - cpu_get (17) - ); - ecall (); - } - break; - default: - ud: - errx (1, "%08llx: invalid instruction: %08x", pc - 4, instr); - } -} - blob - /dev/null blob + 44537fe39bb4e8ea22f90917381b9327ef99beb9 (mode 644) --- /dev/null +++ src/cpu.c @@ -0,0 +1,394 @@ +#include "rvemu.h" + +static u64 regs[31]; +u64 pc; + +void cpu_set (size_t reg, u64 val) +{ + if (reg > 0) + regs[reg - 1] = val; +} + +u64 cpu_get (size_t reg) +{ + return reg > 0 ? regs[reg - 1] : 0; +} + +u32 cpu_fetch (void) +{ + const u32 i = *(const u32 *)(size_t)pc; + //eprintf ("%08x: %08x\n", cpu->pc, i); + pc += 4; + return i; +} + +static i64 extend (i32 x) +{ + return x; +} + +#define log(fmt, ...) eprintf ("%08llx: " fmt "\n", pc - 4, __VA_ARGS__) +void cpu_exec (u32 instr) +{ + const char *name; + const u8 rd = (instr >> 7) & 0x1f; + const u8 funct3 = (instr >> 12) & 0x7; + const u8 rs1 = (instr >> 15) & 0x1f; + const u8 rs2 = (instr >> 20) & 0x1f; + const u8 funct7 = instr >> 25; + const u8 funct6 = instr >> 26; + 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 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)); + const u16 funct10 = (funct7 << 3) | funct3; + const u8 shamt = imm_i & 0x3f; + + u64 a, b, c; + switch (instr & 0x7f) { + case 0b0110111: // lui rd, uimm + log ("lui x%u, %llu", (uint)rd, imm_u); + cpu_set (rd, imm_u); + break; + case 0b0010111: // auipc rd, uimm + log ("auipc x%u, %llu", (uint)rd, imm_u); + cpu_set (rd, pc + imm_u - 4); + break; + case 0b1101111: // jal rd, jimm + log ("jal x%u, %lld", (uint)rd, imm_j); + cpu_set (rd, pc); + pc += imm_j - 4; + break; + case 0b1100111: // jalr rd, rs1, iimm + switch (funct3) { + case 0b000: + log ("jalr x%u, x%u, %lld", (uint)rd, (uint)rs1, imm_i); + cpu_set (rd, pc); + pc = cpu_get (rs1); + break; + default: + goto ud; + } + break; + case 0b1100011: // bcc rs1, rs2, bimm + a = cpu_get (rs1); + b = cpu_get (rs2); + switch (funct3) { + case 0b000: + name = "beq"; + c = a == b; + break; + case 0b001: + name = "bne"; + c = a != b; + break; + case 0b100: + name = "blt"; + c = (i64)a < (i64)b; + break; + case 0b101: + name = "bge"; + c = (i64)a >= (i64)b; + break; + case 0b110: + name = "bltu"; + c = a < b; + break; + case 0b111: + name = "bgeu"; + c = a >= b; + break; + default: + goto ud; + } + log ("%s x%u, x%u, %d", name, (uint)rs1, (uint)rs2, (int)imm_b); + if (c) + pc += imm_b - 4; + break; + case 0b0000011: // lx rd, iimm(rs1) + a = cpu_get (rs1) + imm_i; + switch (funct3) { + case 0b000: // lb + name = "lb"; + b = (i64)read_i8 (a); + break; + case 0b001: // lh + name = "lh"; + b = (i64)read_i16 (a); + break; + case 0b010: // lw + name = "lw"; + 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); + break; + case 0b101: // lhu + name = "lhu"; + b = read_u16 (a); + break; + case 0b110: // lwu + name = "lwu"; + b = read_u32 (a); + break; + default: + goto ud; + } + log ("%s x%u, %d(x%u)", name, (uint)rd, (int)imm_i, (uint)rs1); + cpu_set (rd, b); + break; + case 0b0100011: // sx rs2, simm(rs1) + a = cpu_get (rs2); + b = cpu_get (rs1) + imm_s; + switch (funct3) { + case 0b000: // sb + name = "sb"; + write_u8 (b, a); + break; + case 0b001: // sh + name = "sh"; + write_u16 (b, a); + break; + case 0b010: // sw + name = "sw"; + write_u32 (b, a); + break; + case 0b011: // sd + name = "sd"; + write_u64 (b, a); + break; + default: + goto ud; + } + log ("%s x%u, %d(x%u)", name, (uint)rs2, (int)imm_s, (uint)rs1); + break; + case 0b0010011: // alui rd, rs1, iimm + a = cpu_get (rs1); + b = imm_i; + switch (funct3) { + case 0b000: // addi + name = "addi"; + c = a + b; + break; + case 0b001: // slli + if (funct6 != 0) + goto ud; + name = "slli"; + c = a << shamt; + break; + case 0b010: // slti + name = "slti"; + c = (i64)a < (i64)b; + break; + case 0b011: // sltiu + name = "sltiu"; + c = a < b; + break; + case 0b100: // xori + name = "xori"; + c = a ^ b; + break; + case 0b101: // srli/srai + switch (funct6) { + case 0b000000: + name = "srli"; + c = a >> shamt; + break; + case 0b010000: + name = "srai"; + c = (i64)a >> shamt; + break; + default: + goto ud; + } + break; + case 0b110: // ori + name = "ori"; + c = a | b; + break; + case 0b111: // andi + name = "andi"; + c = a & b; + break; + default: + goto ud; + } + log ("%s x%u, x%u, %lld", 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; + switch (funct7) { + case 0b0000000: + name = "srliw"; + c = (u32)a >> shamt; + break; + case 0b0100000: + name = "sraiw"; + c = (i32)a >> shamt; + break; + default: + goto ud; + } + break; + default: + goto ud; + } + c &= 0x00000000ffffffff; + c = extend (c); + log ("%s x%u, x%u, %lld", name, (uint)rd, (uint)rs1, (i64)imm_i); + cpu_set (rd, c); + break; + case 0b0110011: // alu rd, rs1, rs2 + a = cpu_get (rs1); + b = cpu_get (rs2); + switch (funct10) { + case 0b0000000'000: + name = "add"; + c = a + b; + break; + case 0b0000001'000: + name = "mul"; + c = a * b; + break; + case 0b0100000'000: + name = "sub"; + c = a - b; + break; + case 0b0000000'001: + name = "sll"; + c = a << b; + break; + case 0b0000000'010: + name = "slt"; + c = (i64)a < (i64)b; + break; + case 0b0000000'011: + name = "sltu"; + c = a < b; + break; + case 0b0000000'100: + name = "xor"; + c = a ^ b; + break; + case 0b0000001'100: + name = "div"; + c = b != 0 ? (i64)a / (i64)b : -1; + break; + case 0b0000000'101: + name = "srl"; + c = a >> (b & 0x3f); + break; + case 0b0000001'101: + name = "divu"; + c = b != 0 ? a / b : -1; + break; + case 0b0100000'101: + name = "sra"; + c = (i64)a >> (b & 0x3f); + break; + case 0b0000000'110: + name = "or"; + c = a | b; + break; + case 0b0000001'110: + name = "rem"; + c = b != 0 ? (i64)a % (i64)b : -1; + break; + case 0b0000000'111: + name = "and"; + c = a & b; + break; + case 0b0000001'111: + name = "remu"; + c = b != 0 ? a % b : -1; + break; + } + log ("%s x%u, x%u, x%u", name, (uint)rd, (uint)rs1, (uint)rs2); + cpu_set (rd, c); + break; + case 0b0111011: // aluw + a = cpu_get (rs1); + b = cpu_get (rs2); + switch (funct10) { + case 0b0000000'000: // addw + name = "addw"; + c = a + b; + break; + case 0b0100000'000: // subw + name = "addw"; + c = a - b; + break; + case 0b0000000'001: // sllw + name = "sllw"; + c = a << (b & 0x1f); + break; + case 0b0000000'101: // srlw + name = "srlw"; + c = a >> (b & 0x1f); + break; + case 0b0100000'101: // sraw + name = "sraw"; + c = (i64)a >> (b & 0x1f); + break; + default: + goto ud; + } + log ("%s x%u, x%u, x%u", name, (uint)rd, (uint)rs1, (uint)rs2); + cpu_set (rd, extend ((i32)a)); + break; + case 0b0001111: // fence/fence.tso/pause + eprintf ("%08llx: efence\n", pc - 4); + break; + case 0b1110011: // ecall/ebreak + if ((instr >> 20) & 1) { + eprintf ("%08llx: ebreak\n", pc - 4); + __asm __volatile__ ("int $3"); + } else { + log ( + "ecall a0=%llu, a1=%llu, a2=%llu, a3=%llu, a4=%llu, a5=%llu, a7=%llu", + cpu_get (10), + cpu_get (11), + cpu_get (12), + cpu_get (13), + cpu_get (14), + cpu_get (15), + cpu_get (17) + ); + ecall (); + } + break; + default: + ud: + errx (1, "%08llx: invalid instruction: %08x", pc - 4, instr); + } +} + blob - /dev/null blob + 23d31d68cbaa4919d7ea80f36ba6af592227e811 (mode 644) --- /dev/null +++ src/ecall.c @@ -0,0 +1,967 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 = map (readv ((int)a0, ptr (const struct iovec, a1), (int)a2)); + break; + case SYS_writev: + ret = map (writev ((int)a0, ptr (const struct iovec, a1), (int)a2)); + 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: + warnx ("set_tid_address(): not implemented"); + ret = getpid (); + 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: + //eprintf ("mmap (%p, %zu, %d, %d, %d, %lld);\n", ptr (void, a0), (size_t)a1, (int)a2, (int)a3, (int)a4, (off_t)a5); + 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 - /dev/null blob + 66eb875ea57dc87a40bf8b6cb2d3386f35feeb06 (mode 644) --- /dev/null +++ src/exec.c @@ -0,0 +1,63 @@ +#include +#include +#include +#include +#include +#include +#include "rvemu.h" + + +int is_executable (const Elf64_Ehdr *ehdr) +{ + return IS_ELF (*ehdr) + && ehdr->e_ident[EI_CLASS] == ELFCLASS64 + && ehdr->e_ident[EI_DATA] == ELFDATA2LSB + && ehdr->e_machine == EM_RISCV + ; +} + +int my_execve (const char *path, char **argv, char **envp) +{ + + Elf64_Ehdr ehdr; + char buffer[256], *nl, *s, **args, **env; + int fd; + + fd = open (path, O_RDONLY); + if (fd < 0) + return -1; + + memset (buffer, 0, sizeof (buffer)); + read (fd, buffer, 2); + + if (buffer[0] == '#' && buffer[1] == '!') { + read (fd, buffer, sizeof (buffer)); + close (fd); + + nl = memchr (buffer, '\n', sizeof (buffer)); + if (nl == NULL) { + errno = EINVAL; + return -1; + } + + *nl = '\0'; + + s = buffer; + while (isspace (*s)) + ++s; + + return my_execve (s, argv, envp); + } + + memset (&ehdr, 0, sizeof (ehdr)); + lseek (fd, 0, SEEK_SET); + read (fd, &ehdr, sizeof (ehdr)); + close (fd); + + if (is_executable (&ehdr)) { + return execvpe ("rvemu", argv, envp); + } + + return execve (path, argv, envp); +} + blob - /dev/null blob + a0d8b14d8d05941c2315f86aa3a6da4ba0551ba4 (mode 644) --- /dev/null +++ src/rvemu.c @@ -0,0 +1,193 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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, + -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; + 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_STACK, + -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"); + + filename = argv[1]; + } else { + 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 + f1fa870f78600a53528abcc226d280124e392286 (mode 644) --- /dev/null +++ src/rvemu.h @@ -0,0 +1,85 @@ +#include +#include +#include +#include +#include + +#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 + f107b56f5fe7a8f694784c2a8903a7c54f1e5c14 (mode 644) --- /dev/null +++ src/syscalls.inc @@ -0,0 +1,234 @@ +.set SYS_getcwd, 17 +.set SYS_dup, 23 +.set SYS_dup3, 24 +.set SYS_fcntl, 25 +.set SYS_ioctl, 29 +.set SYS_flock, 32 +.set SYS_mknodat, 33 +.set SYS_mkdirat, 34 +.set SYS_unlinkat, 35 +.set SYS_symlinkat, 36 +.set SYS_linkat, 37 +.set SYS_renameat, 38 +.set SYS_umount, 39 +.set SYS_mount, 40 +.set SYS_pivot_root, 41 +.set SYS_nfsservctl, 42 +.set SYS_statfs, 43 +.set SYS_fstatfs, 44 +.set SYS_truncate, 45 +.set SYS_ftruncate, 46 +.set SYS_fallocate, 47 +.set SYS_faccessat, 48 +.set SYS_chdir, 49 +.set SYS_fchdir, 50 +.set SYS_chroot, 51 +.set SYS_fchmod, 52 +.set SYS_fchmodat, 53 +.set SYS_fchownat, 54 +.set SYS_fchown, 55 +.set SYS_openat, 56 +.set SYS_close, 57 +.set SYS_vhangup, 58 +.set SYS_pipe2, 59 +.set SYS_quotactl, 60 +.set SYS_getdents64, 61 +.set SYS_lseek, 62 +.set SYS_read, 63 +.set SYS_write, 64 +.set SYS_readv, 65 +.set SYS_writev, 66 +.set SYS_pread, 67 +.set SYS_pwrite, 68 +.set SYS_preadv, 69 +.set SYS_pwritev, 70 +.set SYS_sendfile, 71 +.set SYS_pselect6, 72 +.set SYS_ppoll, 73 +.set SYS_signalfd4, 74 +.set SYS_vmsplice, 75 +.set SYS_splice, 76 +.set SYS_tee, 77 +.set SYS_readlinkat, 78 +.set SYS_fstatat, 79 +.set SYS_fstat, 80 +.set SYS_sync, 81 +.set SYS_fsync, 82 +.set SYS_fdatasync, 83 +.set SYS_sync_file_range, 84 +.set SYS_timerfd_create, 85 +.set SYS_timerfd_settime, 86 +.set SYS_timerfd_gettime, 87 +.set SYS_utimensat, 88 +.set SYS_acct, 89 +.set SYS_capget, 90 +.set SYS_capset, 91 +.set SYS_personality, 92 +.set SYS_exit, 93 +.set SYS_exit_group, 94 +.set SYS_waitid, 95 +.set SYS_set_tid_address, 96 +.set SYS_unshare, 97 +.set SYS_futex, 98 +.set SYS_set_robust_limit, 99 +.set SYS_get_robust_limit, 100 +.set SYS_nanosleep, 101 +.set SYS_gettimer, 102 +.set SYS_settimer, 103 +.set SYS_kexec_load, 104 +.set SYS_kexec_init_module, 105 +.set SYS_kexec_delete_module, 106 +.set SYS_timer_create, 107 +.set SYS_timer_gettime, 108 +.set SYS_timer_getoverrun, 109 +.set SYS_timer_settime, 110 +.set SYS_timer_delete, 111 +.set SYS_clock_settime, 112 +.set SYS_clock_gettime, 113 +.set SYS_clock_getres, 114 +.set SYS_clock_nanosleep, 115 +.set SYS_syslog, 116 +.set SYS_ptrace, 117 +.set SYS_sched_setparam, 118 +.set SYS_sched_setscheduler, 119 +.set SYS_sched_getscheduler, 120 +.set SYS_sched_getparam, 121 +.set SYS_sched_setaffinity, 122 +.set SYS_sched_getaffinity, 123 +.set SYS_sched_yield, 124 +.set SYS_sched_get_priority_max, 125 +.set SYS_sched_get_priority_min, 126 +.set SYS_sched_rr_get_interval, 127 +.set SYS_restart_syscall, 128 +.set SYS_kill, 129 +.set SYS_tkill, 130 +.set SYS_tgkill, 131 +.set SYS_signalstack, 132 +.set SYS_sigsuspend, 133 +.set SYS_sigaction, 134 +.set SYS_rt_sigprocmask, 135 +.set SYS_sigpending, 136 +.set SYS_sigtimedwait, 137 +.set SYS_sigqueueinfo, 138 +.set SYS_sigreturn, 139 +.set SYS_setpriority, 140 +.set SYS_getpriority, 141 +.set SYS_reboot, 142 +.set SYS_setregid, 143 +.set SYS_setgid, 144 +.set SYS_setreuid, 145 +.set SYS_setuid, 146 +.set SYS_setresuid, 147 +.set SYS_getresuid, 148 +.set SYS_setresgid, 149 +.set SYS_getresgid, 150 +.set SYS_setfsuid, 151 +.set SYS_setfsgid, 152 +.set SYS_times, 153 +.set SYS_setpgid, 154 +.set SYS_getpgid, 155 +.set SYS_getsid, 156 +.set SYS_setsid, 158 +.set SYS_setgroups, 159 +.set SYS_uname, 160 +.set SYS_sethostname, 161 +.set SYS_setdomainname, 162 +.set SYS_getrlimit, 163 +.set SYS_setrlimit, 164 +.set SYS_getrusage, 165 +.set SYS_umask, 166 +.set SYS_prctl, 167 +.set SYS_getcpu, 168 +.set SYS_gettimeofday, 169 +.set SYS_settimeofday, 170 +.set SYS_adjtimex, 171 +.set SYS_getpid, 172 +.set SYS_getuid, 174 +.set SYS_geteuid, 175 +.set SYS_getgid, 176 +.set SYS_getegid, 177 +.set SYS_gettid, 178 +.set SYS_sysinfo, 179 +.set SYS_msgget, 186 +.set SYS_msgctl, 187 +.set SYS_msgrcv, 188 +.set SYS_msgsnd, 189 +.set SYS_semget, 190 +.set SYS_semctl, 191 +.set SYS_semtimedop, 192 +.set SYS_semop, 193 +.set SYS_readahead, 213 +.set SYS_brk, 214 +.set SYS_munmap, 215 +.set SYS_mremap, 216 +.set SYS_add_key, 217 +.set SYS_request_key, 218 +.set SYS_keyctl, 219 +.set SYS_clone, 220 +.set SYS_execve, 221 +.set SYS_mmap, 222 +.set SYS_fadvise64, 223 +.set SYS_swapon, 224 +.set SYS_swapoff, 225 +.set SYS_mprotect, 226 +.set SYS_msync, 227 +.set SYS_mlock, 228 +.set SYS_munlock, 229 +.set SYS_mlockall, 230 +.set SYS_munlockall, 231 +.set SYS_mincore, 232 +.set SYS_madvise, 233 +.set SYS_remap_file_pages, 234 +.set SYS_mbind, 235 +.set SYS_get_mempolicy, 236 +.set SYS_set_mempolicy, 237 +.set SYS_migrate_pages, 238 +.set SYS_move_pages, 239 +.set SYS_rt_tgsigqueueinfo, 240 +.set SYS_perf_event_open, 241 +.set SYS_accept4, 242 +.set SYS_recvmsg, 243 +.set SYS_prlimit64, 261 +.set SYS_fanotify_init, 262 +.set SYS_fanotify_mark, 263 +.set SYS_name_to_handle_at, 264 +.set SYS_open_by_handle_at, 265 +.set SYS_clock_adjtime, 266 +.set SYS_syncfs, 267 +.set SYS_setns, 268 +.set SYS_sendmsg, 269 +.set SYS_process_vm_readv, 270 +.set SYS_process_vm_writev, 271 +.set SYS_kcmp, 272 +.set SYS_finit_module, 273 +.set SYS_sched_setattr, 274 +.set SYS_sched_getattr, 275 +.set SYS_renameat2, 276 +.set SYS_seccomp, 277 +.set SYS_getrandom, 278 +.set SYS_memfd_create, 279 +.set SYS_bpf, 280 +.set SYS_execveat, 281 +.set SYS_userfaultfd, 282 +.set SYS_membarrier, 283 +.set SYS_mlock2, 284 +.set SYS_copy_file_range, 285 +.set SYS_preadv2, 286 +.set SYS_pwritev2, 287 +.set SYS_pkey_mprotect, 288 +.set SYS_pkey_alloc, 289 +.set SYS_pkey_free, 290 +.set SYS_statx, 291 +.set SYS_io_pgetevents, 292 +.set SYS_rseq, 293 +.set SYS_kexec_file_load, 294 +.set SYS_open, 1024 +.set SYS_link, 1025 +.set SYS_unlink, 1026 +.set SYS_mkdir, 1030 +.set SYS_access, 1033 +.set SYS_stat, 1038 +.set SYS_lstat, 1039 +.set SYS_time, 1062 +.set SYS_getmainvars, 2011 +.set SYS_debug, 2048 blob - 23d31d68cbaa4919d7ea80f36ba6af592227e811 (mode 644) blob + /dev/null --- ecall.c +++ /dev/null @@ -1,967 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#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 = map (readv ((int)a0, ptr (const struct iovec, a1), (int)a2)); - break; - case SYS_writev: - ret = map (writev ((int)a0, ptr (const struct iovec, a1), (int)a2)); - 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: - warnx ("set_tid_address(): not implemented"); - ret = getpid (); - 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: - //eprintf ("mmap (%p, %zu, %d, %d, %d, %lld);\n", ptr (void, a0), (size_t)a1, (int)a2, (int)a3, (int)a4, (off_t)a5); - 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 - 66eb875ea57dc87a40bf8b6cb2d3386f35feeb06 (mode 644) blob + /dev/null --- exec.c +++ /dev/null @@ -1,63 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include "rvemu.h" - - -int is_executable (const Elf64_Ehdr *ehdr) -{ - return IS_ELF (*ehdr) - && ehdr->e_ident[EI_CLASS] == ELFCLASS64 - && ehdr->e_ident[EI_DATA] == ELFDATA2LSB - && ehdr->e_machine == EM_RISCV - ; -} - -int my_execve (const char *path, char **argv, char **envp) -{ - - Elf64_Ehdr ehdr; - char buffer[256], *nl, *s, **args, **env; - int fd; - - fd = open (path, O_RDONLY); - if (fd < 0) - return -1; - - memset (buffer, 0, sizeof (buffer)); - read (fd, buffer, 2); - - if (buffer[0] == '#' && buffer[1] == '!') { - read (fd, buffer, sizeof (buffer)); - close (fd); - - nl = memchr (buffer, '\n', sizeof (buffer)); - if (nl == NULL) { - errno = EINVAL; - return -1; - } - - *nl = '\0'; - - s = buffer; - while (isspace (*s)) - ++s; - - return my_execve (s, argv, envp); - } - - memset (&ehdr, 0, sizeof (ehdr)); - lseek (fd, 0, SEEK_SET); - read (fd, &ehdr, sizeof (ehdr)); - close (fd); - - if (is_executable (&ehdr)) { - return execvpe ("rvemu", argv, envp); - } - - return execve (path, argv, envp); -} - blob - 8f4a68660eee0892775ff39ba5a6f7f43029bf82 (mode 644) blob + /dev/null --- hello.S +++ /dev/null @@ -1,17 +0,0 @@ -.include "syscalls.inc" - -.section .rodata -str: .string "Hello World\n" - -.section .text -.global _start -_start: - li a0, 1 - la a1, str - li a2, 12 - li a7, SYS_write - ecall - - li a0, 0 - li a7, SYS_exit - ecall blob - a5826bdff3660ddabb245f576fe5539b00f2243e (mode 644) blob + /dev/null --- linker.ld +++ /dev/null @@ -1,23 +0,0 @@ -ENTRY(_start) - -SECTIONS { - . = 1M; - - .text : ALIGN(4K) { - *(.text*) - } - - .rodata : ALIGN(4K) { - *(.rodata*) - } - - .data : ALIGN(4K) { - *(.data*) - } - - .bss : ALIGN(4K) { - *(COMMON) - *(.bss*) - } - -} blob - a0d8b14d8d05941c2315f86aa3a6da4ba0551ba4 (mode 644) blob + /dev/null --- rvemu.c +++ /dev/null @@ -1,193 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#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, - -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; - 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_STACK, - -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"); - - filename = argv[1]; - } else { - 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 --- rvemu.h +++ /dev/null @@ -1,85 +0,0 @@ -#include -#include -#include -#include -#include - -#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 - f107b56f5fe7a8f694784c2a8903a7c54f1e5c14 (mode 644) blob + /dev/null --- syscalls.inc +++ /dev/null @@ -1,234 +0,0 @@ -.set SYS_getcwd, 17 -.set SYS_dup, 23 -.set SYS_dup3, 24 -.set SYS_fcntl, 25 -.set SYS_ioctl, 29 -.set SYS_flock, 32 -.set SYS_mknodat, 33 -.set SYS_mkdirat, 34 -.set SYS_unlinkat, 35 -.set SYS_symlinkat, 36 -.set SYS_linkat, 37 -.set SYS_renameat, 38 -.set SYS_umount, 39 -.set SYS_mount, 40 -.set SYS_pivot_root, 41 -.set SYS_nfsservctl, 42 -.set SYS_statfs, 43 -.set SYS_fstatfs, 44 -.set SYS_truncate, 45 -.set SYS_ftruncate, 46 -.set SYS_fallocate, 47 -.set SYS_faccessat, 48 -.set SYS_chdir, 49 -.set SYS_fchdir, 50 -.set SYS_chroot, 51 -.set SYS_fchmod, 52 -.set SYS_fchmodat, 53 -.set SYS_fchownat, 54 -.set SYS_fchown, 55 -.set SYS_openat, 56 -.set SYS_close, 57 -.set SYS_vhangup, 58 -.set SYS_pipe2, 59 -.set SYS_quotactl, 60 -.set SYS_getdents64, 61 -.set SYS_lseek, 62 -.set SYS_read, 63 -.set SYS_write, 64 -.set SYS_readv, 65 -.set SYS_writev, 66 -.set SYS_pread, 67 -.set SYS_pwrite, 68 -.set SYS_preadv, 69 -.set SYS_pwritev, 70 -.set SYS_sendfile, 71 -.set SYS_pselect6, 72 -.set SYS_ppoll, 73 -.set SYS_signalfd4, 74 -.set SYS_vmsplice, 75 -.set SYS_splice, 76 -.set SYS_tee, 77 -.set SYS_readlinkat, 78 -.set SYS_fstatat, 79 -.set SYS_fstat, 80 -.set SYS_sync, 81 -.set SYS_fsync, 82 -.set SYS_fdatasync, 83 -.set SYS_sync_file_range, 84 -.set SYS_timerfd_create, 85 -.set SYS_timerfd_settime, 86 -.set SYS_timerfd_gettime, 87 -.set SYS_utimensat, 88 -.set SYS_acct, 89 -.set SYS_capget, 90 -.set SYS_capset, 91 -.set SYS_personality, 92 -.set SYS_exit, 93 -.set SYS_exit_group, 94 -.set SYS_waitid, 95 -.set SYS_set_tid_address, 96 -.set SYS_unshare, 97 -.set SYS_futex, 98 -.set SYS_set_robust_limit, 99 -.set SYS_get_robust_limit, 100 -.set SYS_nanosleep, 101 -.set SYS_gettimer, 102 -.set SYS_settimer, 103 -.set SYS_kexec_load, 104 -.set SYS_kexec_init_module, 105 -.set SYS_kexec_delete_module, 106 -.set SYS_timer_create, 107 -.set SYS_timer_gettime, 108 -.set SYS_timer_getoverrun, 109 -.set SYS_timer_settime, 110 -.set SYS_timer_delete, 111 -.set SYS_clock_settime, 112 -.set SYS_clock_gettime, 113 -.set SYS_clock_getres, 114 -.set SYS_clock_nanosleep, 115 -.set SYS_syslog, 116 -.set SYS_ptrace, 117 -.set SYS_sched_setparam, 118 -.set SYS_sched_setscheduler, 119 -.set SYS_sched_getscheduler, 120 -.set SYS_sched_getparam, 121 -.set SYS_sched_setaffinity, 122 -.set SYS_sched_getaffinity, 123 -.set SYS_sched_yield, 124 -.set SYS_sched_get_priority_max, 125 -.set SYS_sched_get_priority_min, 126 -.set SYS_sched_rr_get_interval, 127 -.set SYS_restart_syscall, 128 -.set SYS_kill, 129 -.set SYS_tkill, 130 -.set SYS_tgkill, 131 -.set SYS_signalstack, 132 -.set SYS_sigsuspend, 133 -.set SYS_sigaction, 134 -.set SYS_rt_sigprocmask, 135 -.set SYS_sigpending, 136 -.set SYS_sigtimedwait, 137 -.set SYS_sigqueueinfo, 138 -.set SYS_sigreturn, 139 -.set SYS_setpriority, 140 -.set SYS_getpriority, 141 -.set SYS_reboot, 142 -.set SYS_setregid, 143 -.set SYS_setgid, 144 -.set SYS_setreuid, 145 -.set SYS_setuid, 146 -.set SYS_setresuid, 147 -.set SYS_getresuid, 148 -.set SYS_setresgid, 149 -.set SYS_getresgid, 150 -.set SYS_setfsuid, 151 -.set SYS_setfsgid, 152 -.set SYS_times, 153 -.set SYS_setpgid, 154 -.set SYS_getpgid, 155 -.set SYS_getsid, 156 -.set SYS_setsid, 158 -.set SYS_setgroups, 159 -.set SYS_uname, 160 -.set SYS_sethostname, 161 -.set SYS_setdomainname, 162 -.set SYS_getrlimit, 163 -.set SYS_setrlimit, 164 -.set SYS_getrusage, 165 -.set SYS_umask, 166 -.set SYS_prctl, 167 -.set SYS_getcpu, 168 -.set SYS_gettimeofday, 169 -.set SYS_settimeofday, 170 -.set SYS_adjtimex, 171 -.set SYS_getpid, 172 -.set SYS_getuid, 174 -.set SYS_geteuid, 175 -.set SYS_getgid, 176 -.set SYS_getegid, 177 -.set SYS_gettid, 178 -.set SYS_sysinfo, 179 -.set SYS_msgget, 186 -.set SYS_msgctl, 187 -.set SYS_msgrcv, 188 -.set SYS_msgsnd, 189 -.set SYS_semget, 190 -.set SYS_semctl, 191 -.set SYS_semtimedop, 192 -.set SYS_semop, 193 -.set SYS_readahead, 213 -.set SYS_brk, 214 -.set SYS_munmap, 215 -.set SYS_mremap, 216 -.set SYS_add_key, 217 -.set SYS_request_key, 218 -.set SYS_keyctl, 219 -.set SYS_clone, 220 -.set SYS_execve, 221 -.set SYS_mmap, 222 -.set SYS_fadvise64, 223 -.set SYS_swapon, 224 -.set SYS_swapoff, 225 -.set SYS_mprotect, 226 -.set SYS_msync, 227 -.set SYS_mlock, 228 -.set SYS_munlock, 229 -.set SYS_mlockall, 230 -.set SYS_munlockall, 231 -.set SYS_mincore, 232 -.set SYS_madvise, 233 -.set SYS_remap_file_pages, 234 -.set SYS_mbind, 235 -.set SYS_get_mempolicy, 236 -.set SYS_set_mempolicy, 237 -.set SYS_migrate_pages, 238 -.set SYS_move_pages, 239 -.set SYS_rt_tgsigqueueinfo, 240 -.set SYS_perf_event_open, 241 -.set SYS_accept4, 242 -.set SYS_recvmsg, 243 -.set SYS_prlimit64, 261 -.set SYS_fanotify_init, 262 -.set SYS_fanotify_mark, 263 -.set SYS_name_to_handle_at, 264 -.set SYS_open_by_handle_at, 265 -.set SYS_clock_adjtime, 266 -.set SYS_syncfs, 267 -.set SYS_setns, 268 -.set SYS_sendmsg, 269 -.set SYS_process_vm_readv, 270 -.set SYS_process_vm_writev, 271 -.set SYS_kcmp, 272 -.set SYS_finit_module, 273 -.set SYS_sched_setattr, 274 -.set SYS_sched_getattr, 275 -.set SYS_renameat2, 276 -.set SYS_seccomp, 277 -.set SYS_getrandom, 278 -.set SYS_memfd_create, 279 -.set SYS_bpf, 280 -.set SYS_execveat, 281 -.set SYS_userfaultfd, 282 -.set SYS_membarrier, 283 -.set SYS_mlock2, 284 -.set SYS_copy_file_range, 285 -.set SYS_preadv2, 286 -.set SYS_pwritev2, 287 -.set SYS_pkey_mprotect, 288 -.set SYS_pkey_alloc, 289 -.set SYS_pkey_free, 290 -.set SYS_statx, 291 -.set SYS_io_pgetevents, 292 -.set SYS_rseq, 293 -.set SYS_kexec_file_load, 294 -.set SYS_open, 1024 -.set SYS_link, 1025 -.set SYS_unlink, 1026 -.set SYS_mkdir, 1030 -.set SYS_access, 1033 -.set SYS_stat, 1038 -.set SYS_lstat, 1039 -.set SYS_time, 1062 -.set SYS_getmainvars, 2011 -.set SYS_debug, 2048