1 // https://github.com/kragen/stoneknifeforth/blob/702d2ebe1b/386.c
 2 
 3 :(before "End Main")
 4 assert(argc > 1);
 5 reset();
 6 load_elf(argv[1]);
 7 while (EIP < End_of_program)
 8   run_one_instruction();
 9 
10 :(code)
11 void load_elf(const string& filename) {
12   int fd = open(filename.c_str(), O_RDONLY);
13   if (fd < 0) die("%s: open", filename.c_str());
14   off_t size = lseek(fd, 0, SEEK_END);
15   lseek(fd, 0, SEEK_SET);
16   uint8_t* elf_contents = static_cast<uint8_t*>(malloc(size));
17   if (elf_contents == NULL) die("malloc(%d)", size);
18   ssize_t read_size = read(fd, elf_contents, size);
19   if (size != read_size) die("read → %d (!= %d)", size, read_size);
20   load_elf_contents(elf_contents, size);
21   free(elf_contents);
22 }
23 
24 void load_elf_contents(uint8_t* elf_contents, size_t length) {
25   uint8_t magic[5] = {0};
26   memcpy(magic, elf_contents, 4);
27   if (0 != memcmp(magic, "\177ELF", 4))
28     die("Invalid ELF file starting with \"%s\"", magic);
29 
30   uint32_t e_type = u32_in(&elf_contents[16]);
31   if (0x00030002 != e_type)
32     die("ELF type/machine 0x%x isn't i386 executable", e_type);
33 
34   uint32_t e_entry = u32_in(&elf_contents[24]);
35   uint32_t e_phoff = u32_in(&elf_contents[28]);
36   uint32_t p_vaddr = u32_in(&elf_contents[e_phoff + 8]);
37   uint32_t p_memsz = u32_in(&elf_contents[e_phoff + 20]);
38 
39   Mem.resize(p_memsz);  // TODO: not sure if this should be + p_vaddr
40   if (length > p_memsz - p_vaddr) length = p_memsz - p_vaddr;
41   for (size_t i = 0;  i < length;  ++i)
42     Mem.at(p_vaddr + i) = elf_contents[i];
43   End_of_program = p_memsz;
44 
45   // TODO: need to set up real stack somewhere
46 
47   Reg[ESP].u = Reg[EBP].u = End_of_program;
48   EIP = e_entry;
49 }
50 
51 inline uint32_t u32_in(uint8_t* p) {
52   return p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24;
53 }
54 
55 void die(const char* format, ...) {
56   va_list args;
57   va_start(args, format);
58   vfprintf(stderr, format, args);
59   if (errno)
60     perror("<200c>");
61   else
62     fprintf(stderr, "\n");
63   va_end(args);
64   abort();
65 }
66 
67 :(before "End Types")
68 #include <sys/types.h>
69 #include <sys/stat.h>
70 #include <fcntl.h>
71 #include <unistd.h>
72 #include <stdarg.h>
73 #include <errno.h>