Skip to content

Commit

Permalink
Add fibbonaci benchmark
Browse files Browse the repository at this point in the history
To make it work I also added some opcodes, cli argument support, and
sped up the memory compare thing in ptraceomatic.
  • Loading branch information
Theodore Dubois committed Jun 5, 2017
1 parent 8cd8c25 commit 1cba915
Show file tree
Hide file tree
Showing 10 changed files with 97 additions and 53 deletions.
8 changes: 6 additions & 2 deletions emu/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ int cpu_step(struct cpu_state *cpu) {
case 0x05: TRACEI("add imm, eax");
READIMM; ADD(imm, ax); break;

case 0x08: TRACEI("or reg8, modrm8");
READMODRM; OR(modrm_reg8, modrm_val8_w); break;
case 0x09: TRACEI("or reg, modrm");
READMODRM; OR(modrm_reg, modrm_val_w); break;
case 0x0b: TRACEI("or modrm, reg");
Expand Down Expand Up @@ -271,10 +273,12 @@ int cpu_step(struct cpu_state *cpu) {
READMODRM; CMP(modrm_reg8, modrm_val8); break;
case 0x39: TRACEI("cmp reg, modrm");
READMODRM; CMP(modrm_reg, modrm_val); break;
case 0x3a: TRACEI("cmp modrm8, reg8");
READMODRM; CMP(modrm_val8, modrm_reg8); break;
case 0x3b: TRACEI("cmp modrm, reg");
READMODRM; CMP(modrm_val, modrm_reg); break;
case 0x3c: TRACEI("cmp al, imm8");
READIMM8; CMP(cpu->al, imm8); break;
case 0x3c: TRACEI("cmp imm8, al\t");
READIMM8; CMP(imm8, cpu->al); break;
case 0x3d: TRACEI("cmp imm, eax\t");
READIMM; CMP(imm, ax); break;

Expand Down
2 changes: 1 addition & 1 deletion emu/memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ void *tlb_handle_miss(struct mem *mem, addr_t addr, int type) {
// 1 is not a valid page so this won't look like a hit
tlb->page_if_writable = TLB_PAGE_EMPTY;
tlb->data = pt->data;
pt->dirty = 1;
mem->dirty_page = PAGE(addr);
return (char *) tlb->data + OFFSET(addr);
}

Expand Down
3 changes: 2 additions & 1 deletion emu/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
struct mem {
struct pt_entry **pt;
struct tlb_entry *tlb;
page_t dirty_page;
};

// Initialize a mem struct
Expand Down Expand Up @@ -67,7 +68,7 @@ forceinline void *mem_read_ptr(struct mem *mem, addr_t addr) {
forceinline void *mem_write_ptr(struct mem *mem, addr_t addr) {
struct tlb_entry entry = mem->tlb[TLB_INDEX(addr)];
if (entry.page_if_writable == TLB_PAGE(addr)) {
mem->pt[PAGE(addr)]->dirty = 1;
mem->dirty_page = PAGE(addr);
return (char *) entry.data + OFFSET(addr);
}
return tlb_handle_miss(mem, addr, TLB_WRITE);
Expand Down
7 changes: 5 additions & 2 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@
int main(int argc, char *const args[]) {
int err;
current = process_create();
char *const argv[] = {args[1], NULL};
char *const envp[] = {NULL};
char *argv[argc];
for (int i = 0; i < argc; i++) {
argv[i] = args[i + 1];
}
char *envp[] = {NULL};
if ((err = sys_execve(args[1], argv, envp)) < 0) {
return -err;
}
Expand Down
2 changes: 1 addition & 1 deletion misc.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#include <sys/types.h>

// debug output utilities
#if 1
#if 0
#define TRACE(msg, ...) printf(msg, ##__VA_ARGS__)
#else
#define TRACE(msg, ...) (void)NULL
Expand Down
8 changes: 7 additions & 1 deletion sys/calls.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,13 @@ int handle_interrupt(struct cpu_state *cpu, int interrupt) {
cpu->eax = result;
} else if (interrupt == INT_GPF) {
// page fault handling is a thing
return handle_pagefault(cpu->segfault_addr);
printf("page fault at %x\n", cpu->segfault_addr);
int res = handle_pagefault(cpu->segfault_addr);
if (res == 0) {
printf("could not handle, exiting\n");
sys_exit(1);
}
return res;
} else {
printf("exiting\n");
sys_exit(interrupt);
Expand Down
69 changes: 39 additions & 30 deletions sys/exec/exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
static inline dword_t align_stack(dword_t sp);
static inline size_t user_strlen(dword_t p);
static inline void user_memset(addr_t start, dword_t len, byte_t val);
static inline dword_t copy_data(dword_t sp, const char *data, size_t count);
static inline dword_t copy_string(dword_t sp, const char *string);
static inline dword_t copy_strings(dword_t sp, char *const strings[]);
static unsigned count_args(char *const args[]);
Expand Down Expand Up @@ -201,6 +200,13 @@ int sys_execve(const char *file, char *const argv[], char *const envp[]) {
// on 64-bit linux, there's 8. make ptraceomatic happy. (a major theme in this file)
sp -= sizeof(void *);

// now the really complicated part: initializing the stack. plan of attack is
// 1. start at the bottom, copy the filename, arguments, and environment
// 2. copy the stuff elf aux points to
// 3. figure out how much space is needed for aux, argv, and envp, reserve
// it, and then align the stack
// 4. go up to the top and copy argc, argv, envp, and auxv

// filename, argc, argv
addr_t file_addr = sp = copy_string(sp, file);
addr_t envp_addr = sp = copy_strings(sp, envp);
Expand All @@ -212,11 +218,11 @@ int sys_execve(const char *file, char *const argv[], char *const envp[]) {
// 16 random bytes so no system call is needed to seed a userspace RNG
char random[16] = {};
if (getentropy(random, sizeof(random)) < 0)
abort(); // if this fails, something is badly wrong
addr_t random_addr = sp = copy_data(sp, random, sizeof(random));
sp &=~ 0x7;
abort(); // if this fails, something is very badly wrong indeed
addr_t random_addr = sp -= sizeof(random);
user_put_count(sp, random, sizeof(random));

// elf aux
// declare elf aux so we can know how big it is
struct aux_ent aux[] = {
{AX_SYSINFO, vdso_entry},
{AX_SYSINFO_EHDR, vdso_addr},
Expand All @@ -240,36 +246,45 @@ int sys_execve(const char *file, char *const argv[], char *const envp[]) {
{AX_PLATFORM, platform_addr},
{0, 0}
};
sp = copy_data(sp, (const char *) aux, sizeof(aux));

// envp
// the way linux aligns the stack at this point is kinda funky
// calculate how much space is needed for argv, envp, and auxv, subtract
// that from sp, then align, then copy argv/envp/auxv from that down
size_t argc = count_args(argv);
size_t envc = count_args(envp);
sp -= sizeof(dword_t); // null terminator
sp -= envc * sizeof(dword_t);
dword_t p = sp;
while (envc-- > 0) {
user_put(p, envp_addr);
envp_addr += user_strlen(envp_addr) + 1;
p += sizeof(dword_t);
}
sp -= ((argc + 1) + (envc + 1) + 1) * sizeof(dword_t);
sp -= sizeof(aux);
sp &=~ 0xf;

// now copy down, start using p so sp is preserved
addr_t p = sp;

// argc
user_put(p, argc); p += sizeof(dword_t);

// argv
size_t argc = count_args(argv);
sp -= sizeof(dword_t); // null terminator
sp -= argc * sizeof(dword_t);
p = sp;
while (argc-- > 0) {
user_put(p, argv_addr);
argv_addr += user_strlen(argv_addr) + 1;
p += sizeof(dword_t); // null terminator
}
p += sizeof(dword_t); // null terminator

// envp
while (envc-- > 0) {
user_put(p, envp_addr);
envp_addr += user_strlen(envp_addr) + 1;
p += sizeof(dword_t);
}
p += sizeof(dword_t); // null terminator

// argc
sp -= sizeof(dword_t); user_put(sp, count_args(argv));
// copy auxv
user_put_count(p, (const char *) aux, sizeof(aux));
p += sizeof(aux);

current->cpu.esp = sp;
current->cpu.eip = header.entry_point;
/* pt_dump(current->cpu.pt); */
curmem.dirty_page = 0xffffd;

err = 0;
out_free_interp:
Expand Down Expand Up @@ -306,18 +321,12 @@ static inline dword_t copy_string(addr_t sp, const char *string) {
}

static inline dword_t copy_strings(addr_t sp, char *const strings[]) {
for (unsigned i = 0; strings[i] != NULL; i++) {
sp = copy_string(sp, strings[i]);
for (unsigned i = count_args(strings); i > 0; i--) {
sp = copy_string(sp, strings[i - 1]);
}
return sp;
}

static inline dword_t copy_data(addr_t sp, const char *data, size_t count) {
sp -= count;
user_put_count(sp, data, count);
return sp;
}

static inline size_t user_strlen(addr_t p) {
size_t len = 0;
while (user_get8(p++) != 0) len++;
Expand Down
19 changes: 19 additions & 0 deletions tests/fibbonaci.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#include <stdio.h>
#include <stdlib.h>

unsigned long fib(unsigned long n) {
if (n <= 1)
return 1;
return fib(n - 1) + fib(n - 2);
}

int main(int argc, const char *argv[]) {
if (argc != 2) {
printf("argc is %d\n", argc);
printf("please specify a number to fibbonaci\n");
return 1;
}
unsigned long n = strtoul(argv[1], NULL, 10);
printf("%lu\n", fib(n));
return 0;
}
1 change: 1 addition & 0 deletions tests/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ executable('hello-libc', ['hello-clib.c'], c_args: ['-m32'], link_args: ['-m32']

# simple benchmark
executable('looper', ['looper.c', 'nothing.c'], c_args: ['-m32'], link_args: ['-m32'])
executable('fibbonaci', ['fibbonaci.c'], c_args: ['-m32'], link_args: ['-m32', '-static'])
31 changes: 16 additions & 15 deletions tools/ptraceomatic.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,22 +40,20 @@ int compare_cpus(struct cpu_state *cpu, int pid) {
CHECK_REG(rbp, ebp);
CHECK_REG(rip, eip);

return 0;
// compare pages marked dirty
int fd = open_mem(pid);
for (unsigned i = 0; i < PT_SIZE; i++) {
if (cpu->mem.pt[i] && cpu->mem.pt[i]->dirty) {
cpu->mem.pt[i]->dirty = 0;
char page[PAGE_SIZE];
trycall(lseek(fd, i<<PAGE_BITS, SEEK_SET), "compare seek mem");
trycall(read(fd, page, PAGE_SIZE), "compare read mem");
if (memcmp(page, cpu->mem.pt[i]->data, PAGE_SIZE) != 0) {
printf("page %x doesn't match\n", i);
debugger;
return -1;
}
}
page_t dirty_page = cpu->mem.dirty_page;
char real_page[PAGE_SIZE];
trycall(lseek(fd, dirty_page<<PAGE_BITS, SEEK_SET), "compare seek mem");
trycall(read(fd, real_page, PAGE_SIZE), "compare read mem");
void *fake_page = cpu->mem.pt[dirty_page]->data;

if (memcmp(real_page, fake_page, PAGE_SIZE) != 0) {
printf("page %x doesn't match\n", dirty_page);
debugger;
return -1;
}

close(fd);
return 0;
}
Expand Down Expand Up @@ -149,8 +147,11 @@ void prepare_tracee(int pid) {
int main(int argc, char *const args[]) {
int err;
current = process_create();
char *const argv[] = {args[1], NULL};
char *const envp[] = {NULL};
char *argv[argc];
for (int i = 0; i < argc; i++) {
argv[i] = args[i + 1];
}
char *envp[] = {NULL};
if ((err = sys_execve(args[1], argv, envp)) < 0) {
return -err;
}
Expand Down

0 comments on commit 1cba915

Please sign in to comment.