about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--subx/010---vm.cc3
-rw-r--r--subx/020syscalls.cc78
-rwxr-xr-xsubx/ex8bin0 -> 313 bytes
-rw-r--r--subx/ex8.subx99
4 files changed, 180 insertions, 0 deletions
diff --git a/subx/010---vm.cc b/subx/010---vm.cc
index 5bdd1dd1..33ebe51a 100644
--- a/subx/010---vm.cc
+++ b/subx/010---vm.cc
@@ -120,6 +120,9 @@ inline uint8_t* mem_addr_u8(uint32_t addr) {
 inline int8_t* mem_addr_i8(uint32_t addr) {
   return reinterpret_cast<int8_t*>(&Mem.at(addr-Mem_offset));
 }
+inline char* mem_addr_string(uint32_t addr) {
+  return reinterpret_cast<char*>(&Mem.at(addr-Mem_offset));
+}
 inline uint32_t* mem_addr_u32(uint32_t addr) {
   return reinterpret_cast<uint32_t*>(&Mem.at(addr-Mem_offset));
 }
diff --git a/subx/020syscalls.cc b/subx/020syscalls.cc
index 177ba6f1..2f6ca994 100644
--- a/subx/020syscalls.cc
+++ b/subx/020syscalls.cc
@@ -21,12 +21,90 @@ void process_int80() {
     exit(/*exit code*/Reg[EBX].u);
     break;
   case 3:
+    trace(91, "run") << "read: " << Reg[EBX].u << ' ' << Reg[ECX].u << '/' << mem_addr_string(Reg[ECX].u) << ' ' << Reg[EDX].u << end();
     Reg[EAX].i = read(/*file descriptor*/Reg[EBX].u, /*memory buffer*/mem_addr_u8(Reg[ECX].u), /*size*/Reg[EDX].u);
+    trace(91, "run") << "result: " << Reg[EAX].i << end();
+    if (Reg[EAX].i == -1) raise << strerror(errno) << '\n' << end();
     break;
   case 4:
+    trace(91, "run") << "write: " << Reg[EBX].u << ' ' << Reg[ECX].u << '/' << mem_addr_string(Reg[ECX].u) << ' ' << Reg[EDX].u << end();
     Reg[EAX].i = write(/*file descriptor*/Reg[EBX].u, /*memory buffer*/mem_addr_u8(Reg[ECX].u), /*size*/Reg[EDX].u);
+    trace(91, "run") << "result: " << Reg[EAX].i << end();
+    if (Reg[EAX].i == -1) raise << strerror(errno) << '\n' << end();
+    break;
+  case 5: {
+    check_flags(ECX);
+    check_mode(EDX);
+    trace(91, "run") << "open: " << Reg[EBX].u << '/' << mem_addr_string(Reg[EBX].u) << ' ' << Reg[ECX].u << end();
+    Reg[EAX].i = open(/*filename*/mem_addr_string(Reg[EBX].u), /*flags*/Reg[ECX].u, /*mode*/0640);
+    trace(91, "run") << "result: " << Reg[EAX].i << end();
+    if (Reg[EAX].i == -1) raise << strerror(errno) << '\n' << end();
+    break;
+  }
+  case 6:
+    trace(91, "run") << "close: " << Reg[EBX].u << end();
+    Reg[EAX].i = close(/*file descriptor*/Reg[EBX].u);
+    trace(91, "run") << "result: " << Reg[EAX].i << end();
+    if (Reg[EAX].i == -1) raise << strerror(errno) << '\n' << end();
+    break;
+  case 8:
+    check_mode(ECX);
+    trace(91, "run") << "creat: " << Reg[EBX].u << '/' << mem_addr_string(Reg[EBX].u) << end();
+    Reg[EAX].i = creat(/*filename*/mem_addr_string(Reg[EBX].u), /*mode*/0640);
+    trace(91, "run") << "result: " << Reg[EAX].i << end();
+    if (Reg[EAX].i == -1) raise << strerror(errno) << '\n' << end();
+    break;
+  case 10:
+    trace(91, "run") << "unlink: " << Reg[EBX].u << '/' << mem_addr_string(Reg[EBX].u) << end();
+    Reg[EAX].i = unlink(/*filename*/mem_addr_string(Reg[EBX].u));
+    trace(91, "run") << "result: " << Reg[EAX].i << end();
+    if (Reg[EAX].i == -1) raise << strerror(errno) << '\n' << end();
+    break;
+  case 38:
+    trace(91, "run") << "rename: " << Reg[EBX].u << '/' << mem_addr_string(Reg[EBX].u) << " -> " << Reg[ECX].u << '/' << mem_addr_string(Reg[ECX].u) << end();
+    Reg[EAX].i = rename(/*old filename*/mem_addr_string(Reg[EBX].u), /*new filename*/mem_addr_string(Reg[ECX].u));
+    trace(91, "run") << "result: " << Reg[EAX].i << end();
+    if (Reg[EAX].i == -1) raise << strerror(errno) << '\n' << end();
+    break;
+  case 45:  // brk: modify size of data segment
+    trace(91, "run") << "grow data segment to " << Reg[EBX].u << end();
+    resize_mem(/*new end address*/Reg[EBX].u);
     break;
   default:
     raise << HEXWORD << EIP << ": unimplemented syscall " << Reg[EAX].u << '\n' << end();
   }
 }
+
+// SubX is oblivious to file permissions, directories, symbolic links, terminals, and much else besides.
+// Also ignoring any concurrency considerations for now.
+void check_flags(int reg) {
+  uint32_t flags = Reg[reg].u;
+  if (flags != ((flags & O_RDONLY) | (flags & O_WRONLY))) {
+    raise << HEXWORD << EIP << ": most POSIX flags to the open() syscall are not supported. Just O_RDONLY and O_WRONLY for now. Zero concurrent access support.\n" << end();
+    exit(1);
+  }
+  if ((flags & O_RDONLY) && (flags & O_WRONLY)) {
+    raise << HEXWORD << EIP << ": can't open a file for both reading and writing at once. See http://man7.org/linux/man-pages/man2/open.2.html.\n" << end();
+    exit(1);
+  }
+}
+
+void check_mode(int reg) {
+  if (Reg[reg].u != 0600) {
+    raise << HEXWORD << EIP << ": SubX is oblivious to file permissions; register " << reg << " must be 0.\n" << end();
+    exit(1);
+  }
+}
+
+void resize_mem(uint32_t new_end_address) {
+  if (new_end_address < Mem_offset) {
+    raise << HEXWORD << EIP << ": can't shrink data segment to before code segment\n";
+    return;
+  }
+  int32_t new_size = new_end_address - Mem_offset;
+  if (new_size < SIZE(Mem)) {
+    raise << HEXWORD << EIP << ": shrinking data segment is not supported.\n" << end();
+    return;
+  }
+  Mem.resize(new_size);  // will throw exception on failure
+}
diff --git a/subx/ex8 b/subx/ex8
new file mode 100755
index 00000000..d756271e
--- /dev/null
+++ b/subx/ex8
Binary files differdiff --git a/subx/ex8.subx b/subx/ex8.subx
new file mode 100644
index 00000000..0512157f
--- /dev/null
+++ b/subx/ex8.subx
@@ -0,0 +1,99 @@
+## example showing file syscalls
+# Create a file, open it for writing, write a character to it, close it, open
+# it for reading, read a character from it, close it, delete it, and return
+# the character read.
+#
+# To run:
+#   $ subx translate ex8.subx ex8
+#   $ subx run ex8
+# Expected result:
+#   $ echo $?
+#   97
+
+== 0x08048074  # code segment, after leaving room for ELF header and segment headers
+# instruction                     effective address                                                   operand     displacement    immediate
+# op          subop               mod             rm32          base        index         scale       r32
+# 1-3 bytes   3 bits              2 bits          3 bits        3 bits      3 bits        2 bits      2 bits      0/1/2/4 bytes   0/1/2/4 bytes
+
+  ## creat(filename)
+  bb/copy                         .               .             .           .             .           .           .               0x08049131/imm32/fname  # copy to EBX
+  b9/copy                         .               .             .           .             .           .           .               0x180/imm32/fixed-perms # copy 0 to ECX
+  b8/copy                         .               .             .           .             .           .           .               8/imm32/creat           # copy 8 to EAX
+  cd/syscall                      .               .             .           .             .           .           .               0x80/imm8               # int 80h
+
+  ## fd = open(filename, O_WRONLY, 0)
+  bb/copy                         .               .             .           .             .           .           .               0x08049131/imm32/fname  # copy to EBX
+  b9/copy                         .               .             .           .             .           .           .               1/imm32/wronly          # copy 1 to ECX
+  ba/copy                         .               .             .           .             .           .           .               0x180/imm32/fixed-perms # copy 0 to EDX
+  b8/copy                         .               .             .           .             .           .           .               5/imm32/open            # copy 5 to EAX
+  cd/syscall                      .               .             .           .             .           .           .               0x80/imm8               # int 80h
+  # save fd
+  bb/copy                         .               .             .           .             .           .           .               0x08049125/imm32/fd     # copy to EBX
+  89/copy                         0/mod/indirect  3/rm32/EBX                                          0/r32/EAX                                           # copy EAX to *EBX
+
+  ## write(fd, "a", 1)
+  # load fd
+  bb/copy                         .               .             .           .             .           .           .               0x08049125/imm32/fd     # copy to EBX
+  8b/copy                         0/mod/indirect  3/rm32/EBX                                          3/r32/EBX                                           # copy *EBX to EBX
+  #
+  b9/copy                         .               .             .           .             .           .           .               0x08049129/imm32/a      # copy to ECX
+  ba/copy                         .               .             .           .             .           .           .               1/imm32/size            # copy 1 to EDX
+  b8/copy                         .               .             .           .             .           .           .               4/imm32/write           # copy 4 to EAX
+  cd/syscall                      .               .             .           .             .           .           .               0x80/imm8               # int 80h
+
+  ## close(fd)
+  # load fd
+  bb/copy                         .               .             .           .             .           .           .               0x08049125/imm32/fd     # copy to EBX
+  8b/copy                         0/mod/indirect  3/rm32/EBX                                          3/r32/EBX                                           # copy *EBX to EBX
+  #
+  b8/copy                         .               .             .           .             .           .           .               6/imm32/close           # copy 6 to EAX
+  cd/syscall                      .               .             .           .             .           .           .               0x80/imm8               # int 80h
+
+  ## fd = open(filename, O_RDONLY, 0)
+  bb/copy                         .               .             .           .             .           .           .               0x08049131/imm32/fname  # copy to EBX
+  b9/copy                         .               .             .           .             .           .           .               0/imm32/rdonly          # copy 0 to ECX
+  ba/copy                         .               .             .           .             .           .           .               0x180/imm32/fixed-perms # copy 0 to EDX
+  b8/copy                         .               .             .           .             .           .           .               5/imm32/open            # copy 5 to EAX
+  cd/syscall                      .               .             .           .             .           .           .               0x80/imm8               # int 80h
+  # save fd
+  bb/copy                         .               .             .           .             .           .           .               0x08049125/imm32/fd     # copy to EBX
+  89/copy                         0/mod/indirect  3/rm32/EBX                                          0/r32/EAX                                           # copy EAX to *EBX
+
+  ## read(fd, b, 1)
+  # load fd
+  bb/copy                         .               .             .           .             .           .           .               0x08049125/imm32/fd     # copy to EBX
+  8b/copy                         0/mod/indirect  3/rm32/EBX                                          3/r32/EBX                                           # copy *EBX to EBX
+  #
+  b9/copy                         .               .             .           .             .           .           .               0x0804912d/imm32/b      # copy to ECX
+  ba/copy                         .               .             .           .             .           .           .               1/imm32/size            # copy 1 to EDX
+  b8/copy                         .               .             .           .             .           .           .               3/imm32/read            # copy 3 to EAX
+  cd/syscall                      .               .             .           .             .           .           .               0x80/imm8               # int 80h
+
+  ## close(fd)
+  # load fd
+  bb/copy                         .               .             .           .             .           .           .               0x08049125/imm32/fd     # copy to EBX
+  8b/copy                         0/mod/indirect  3/rm32/EBX                                          3/r32/EBX                                           # copy *EBX to EBX
+  #
+  b8/copy                         .               .             .           .             .           .           .               6/imm32/close           # copy 8 to EAX
+  cd/syscall                      .               .             .           .             .           .           .               0x80/imm8               # int 80h
+
+  ## unlink(filename)
+  bb/copy                         .               .             .           .             .           .           .               0x08049131/imm32/fname  # copy to EBX
+  b8/copy                         .               .             .           .             .           .           .               0xa/imm32/unlink        # copy 8 to EAX
+  cd/syscall                      .               .             .           .             .           .           .               0x80/imm8               # int 80h
+
+  ## exit(b)
+  # load b
+  bb                              .               .             .           .             .           .           .               0x0804912d/imm32/b      # copy to EBX
+  8b/copy                         0/mod/indirect  3/rm32/EBX                                          3/r32/EBX                                           # copy *EBX to EBX
+  #
+  b8/copy                         .               .             .           .             .           .           .               1/imm32/exit            # copy 1 to EAX
+  cd/syscall                      .               .             .           .             .           .           .               0x80/imm8               # int 80h
+
+== 0x08049125  # data segment
+00 00 00 00  # fd
+61 00 00 00  # a: string to write to file: 'a'
+00 00 00 00  # b: space for string read from file
+2e 66 6f 6f 00 00 00 00  # filename: '.foo'
+
+# vim:ft=subx:nowrap:tw&
/a>
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131