about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2017-12-30 22:53:08 -0800
committerKartik K. Agaram <vc@akkartik.com>2017-12-30 22:54:41 -0800
commit708eae3109ca71f7a7178684aaaced7c16196559 (patch)
treedf35274d0318ce883c841a97897567631defa11e
parentfe0c9163cb79182e31537862ad7ef0452cdc1e53 (diff)
downloadmu-708eae3109ca71f7a7178684aaaced7c16196559.tar.gz
4174
Temporary hack to debug Kragen Sitaker's VM.
-rw-r--r--subx/020elf.cc72
1 files changed, 72 insertions, 0 deletions
diff --git a/subx/020elf.cc b/subx/020elf.cc
new file mode 100644
index 00000000..b2aa0098
--- /dev/null
+++ b/subx/020elf.cc
@@ -0,0 +1,72 @@
+// https://github.com/kragen/stoneknifeforth/blob/702d2ebe1b/386.c
+
+:(before "End Main")
+assert(argc > 1);
+reset();
+load_elf(argv[1]);
+while (EIP < End_of_program)
+  run_one_instruction();
+
+:(code)
+void load_elf(const string& filename) {
+  int fd = open(filename.c_str(), O_RDONLY);
+  if (fd < 0) die("%s: open", filename.c_str());
+  off_t size = lseek(fd, 0, SEEK_END);
+  lseek(fd, 0, SEEK_SET);
+  uint8_t* elf_contents = static_cast<uint8_t*>(malloc(size));
+  if (elf_contents == NULL) die("malloc(%d)", size);
+  ssize_t read_size = read(fd, elf_contents, size);
+  if (size != read_size) die("read → %d (!= %d)", size, read_size);
+  load_elf_contents(elf_contents, size);
+  free(elf_contents);
+}
+
+void load_elf_contents(uint8_t* elf_contents, size_t length) {
+  uint8_t magic[5] = {0};
+  memcpy(magic, elf_contents, 4);
+  if (0 != memcmp(magic, "\177ELF", 4))
+    die("Invalid ELF file starting with \"%s\"", magic);
+
+  uint32_t e_type = u32_in(&elf_contents[16]);
+  if (0x00030002 != e_type)
+    die("ELF type/machine 0x%x isn't i386 executable", e_type);
+
+  uint32_t e_entry = u32_in(&elf_contents[24]);
+  uint32_t e_phoff = u32_in(&elf_contents[28]);
+  uint32_t p_vaddr = u32_in(&elf_contents[e_phoff + 8]);
+  uint32_t p_memsz = u32_in(&elf_contents[e_phoff + 20]);
+
+  Mem.resize(p_memsz);  // TODO: not sure if this should be + p_vaddr
+  if (length > p_memsz - p_vaddr) length = p_memsz - p_vaddr;
+  for (size_t i = 0;  i < length;  ++i)
+    Mem.at(p_vaddr + i) = elf_contents[i];
+  End_of_program = p_memsz;
+
+  // TODO: need to set up real stack somewhere
+
+  Reg[ESP].u = Reg[EBP].u = End_of_program;
+  EIP = e_entry;
+}
+
+inline uint32_t u32_in(uint8_t* p) {
+  return p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24;
+}
+
+void die(const char* format, ...) {
+  va_list args;
+  va_start(args, format);
+  vfprintf(stderr, format, args);
+  if (errno)
+    perror("‌");
+  else
+    fprintf(stderr, "\n");
+  va_end(args);
+  abort();
+}
+
+:(before "End Types")
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdarg.h>