about summary refs log tree commit diff stats
path: root/subx
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2018-06-30 09:41:22 -0700
committerKartik Agaram <vc@akkartik.com>2018-06-30 09:41:22 -0700
commitb141a448ce0964f2a854b59a799875b94d2f1ec0 (patch)
treea8b9498262f3e1652ddb299eb11c583fd69116c5 /subx
parente1eefb8a8a25312754b64f7b74f76c0ee05cace7 (diff)
downloadmu-b141a448ce0964f2a854b59a799875b94d2f1ec0.tar.gz
4289 - beginnings of a translator to ELF
The source 'language' is still entirely open. We'll see how it evolves
as I write programs in machine code.
Diffstat (limited to 'subx')
-rw-r--r--subx/001help.cc5
-rw-r--r--subx/010core.cc4
-rw-r--r--subx/021translate.cc96
-rwxr-xr-xsubx/ex1bin0 -> 96 bytes
-rw-r--r--subx/ex1.hex6
5 files changed, 107 insertions, 4 deletions
diff --git a/subx/001help.cc b/subx/001help.cc
index d8d81ff0..c4cc3a00 100644
--- a/subx/001help.cc
+++ b/subx/001help.cc
@@ -8,9 +8,8 @@ if (argc <= 1 || is_equal(argv[1], "--help")) {
   cerr << "Usage:\n"
        << "  subx test\n"
        << "  subx --help\n"
-       << "  subx run <elf file>\n"
-       << "Planned:\n"
-       << "  subx compile <ascii file> <elf file>\n"
+       << "  subx run <ELF binary>\n"
+       << "  subx translate <input 'source' file> <output ELF binary>\n"
        ;
   return 0;
 }
diff --git a/subx/010core.cc b/subx/010core.cc
index 050ac932..07029ff0 100644
--- a/subx/010core.cc
+++ b/subx/010core.cc
@@ -152,8 +152,10 @@ void run_one_instruction() {
 }
 
 void load_program(const string& text_bytes) {
-  uint32_t addr = 1;
   istringstream in(text_bytes);
+  load_program(in, 1);
+}
+void load_program(istream& in, uint32_t addr) {
   in >> std::noskipws;
   while (has_data(in)) {
     char c1 = next_hex_byte(in);
diff --git a/subx/021translate.cc b/subx/021translate.cc
new file mode 100644
index 00000000..de945fbc
--- /dev/null
+++ b/subx/021translate.cc
@@ -0,0 +1,96 @@
+:(before "End Includes")
+const int START = 0x08048000;
+:(before "End Main")
+if (is_equal(argv[1], "translate")) {
+  assert(argc > 3);
+  ifstream in(argv[2]);
+  Mem.resize(1024);
+  load_program(in, 1);  // since we're not going to run it right now, we can load it anywhere
+  dump_elf(argv[3]);
+}
+
+:(code)
+// write out the current Memory contents from address 1 to End_of_program to a
+// bare-bones ELF file with a single section/segment and a hard-coded origin address.
+void dump_elf(const char* filename) {
+  ofstream out(filename, ios::binary);
+  dump_elf_header(out);
+  for (size_t i = 1;  i < End_of_program;  ++i) {
+    char c = Mem.at(i);
+    out.write(&c, sizeof(c));
+  }
+  out.close();
+}
+
+void dump_elf_header(ostream& out) {
+  char c = '\0';
+#define O(X)  c = (X); out.write(&c, sizeof(c))
+// host is required to be little-endian
+#define emit(X)  out.write(reinterpret_cast<const char*>(&X), sizeof(X))
+  //// ehdr
+  // e_ident
+  O(0x7f); O(/*E*/0x45); O(/*L*/0x4c); O(/*F*/0x46);
+    O(0x1);  // 32-bit format
+    O(0x1);  // little-endian
+    O(0x1); O(0x0);
+  for (size_t i = 0;  i < 8;  ++i) { O(0x0); }
+  // e_type
+  O(0x02); O(0x00);
+  // e_machine
+  O(0x03); O(0x00);
+  // e_version
+  O(0x01); O(0x00); O(0x00); O(0x00);
+  // e_entry
+  int e_entry = START + /*size of ehdr*/52 + /*size of phdr*/32;
+  emit(e_entry);
+  // e_phoff -- immediately after ELF header
+  int e_phoff = 52;
+  emit(e_phoff);
+  // e_shoff; unused
+  int dummy32 = 0;
+  emit(dummy32);
+  // e_flags; unused
+  emit(dummy32);
+  // e_ehsize
+  uint16_t e_ehsize = 52;
+  emit(e_ehsize);
+  // e_phentsize
+  uint16_t e_phentsize = 0x20;
+  emit(e_phentsize);
+  // e_phnum
+  uint16_t e_phnum = 0x1;
+  emit(e_phnum);
+  // e_shentsize
+  uint16_t dummy16 = 0x0;
+  emit(dummy16);
+  // e_shnum
+  emit(dummy16);
+  // e_shstrndx
+  emit(dummy16);
+
+  //// phdr
+  // p_type
+  uint32_t p_type = 0x1;
+  emit(p_type);
+  // p_offset
+  emit(dummy32);
+  // p_vaddr
+  emit(START);
+  // p_paddr
+  emit(START);
+  // p_filesz
+  uint32_t size = (End_of_program-1) + /*size of ehdr*/52 + /*size of phdr*/32;
+  emit(size);
+  // p_memsz
+  emit(size);
+  // p_flags
+  uint32_t p_flags = 0x5;
+  emit(p_flags);
+  // p_align
+  uint32_t p_align = 0x1000;
+  emit(p_align);
+#undef O
+}
+
+:(before "End Includes")
+using std::ios;
diff --git a/subx/ex1 b/subx/ex1
new file mode 100755
index 00000000..205f8d60
--- /dev/null
+++ b/subx/ex1
Binary files differdiff --git a/subx/ex1.hex b/subx/ex1.hex
new file mode 100644
index 00000000..5a6317bd
--- /dev/null
+++ b/subx/ex1.hex
@@ -0,0 +1,6 @@
+# opcode        ModR/M                    SIB                   displacement    immediate
+# instruction   mod, reg, Reg/Mem bits    scale, index, base
+# 1-3 bytes     0/1 byte                  0/1 byte              0/1/2/4 bytes   0/1/2/4 bytes
+  bb                                                                            2a 00 00 00  # copy 0x2a (42) to EBX
+  05                                                                            01 00 00 00  # copy 1 to EAX
+  cd                                                                            80           # int 80h