summaryrefslogtreecommitdiff
path: root/run/runner.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'run/runner.cpp')
-rw-r--r--run/runner.cpp94
1 files changed, 94 insertions, 0 deletions
diff --git a/run/runner.cpp b/run/runner.cpp
new file mode 100644
index 0000000..8f19bfb
--- /dev/null
+++ b/run/runner.cpp
@@ -0,0 +1,94 @@
+
+#include <cstdio>
+#include <cerrno>
+#include <cstring>
+#include <cassert>
+#include <csignal>
+
+#include <iostream>
+
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/mman.h>
+
+#include "common.hpp"
+#include "dos_emu.hpp"
+
+int loader_socket;
+
+enum ErrorCode {
+ ok,
+ socket_creation_failed,
+ connection_error
+};
+
+static ErrorCode connect_to_loader();
+static BinaryLoadMessage receive_message();
+static void load_binary(BinaryLoadMessage const& message);
+static void register_signal_handlers();
+
+int main(int, char*[]) {
+ if(connect_to_loader() != ok) {
+ return -1;
+ }
+ BinaryLoadMessage message = receive_message();
+ load_binary(message);
+ register_signal_handlers();
+
+ asm ("JMP *%0 \n\t"
+ :
+ : "r" (message.eip));
+}
+
+static ErrorCode connect_to_loader() {
+ if ((loader_socket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
+ perror("socket");
+ return socket_creation_failed;
+ }
+
+ sockaddr_un addr;
+ addr.sun_family = AF_UNIX;
+ std::strncpy(addr.sun_path, socket_name.c_str(), sizeof addr.sun_path);
+
+ size_t len = strnlen(addr.sun_path, sizeof addr.sun_path) + sizeof(addr.sun_family);
+ if (connect(loader_socket, (struct sockaddr *)&addr, len) == -1) {
+ perror("connect");
+ return connection_error;
+ }
+ return ok;
+}
+
+static BinaryLoadMessage receive_message() {
+ BinaryLoadMessage message;
+ uint32_t bytes_received = recv(loader_socket, &message, sizeof message, 0);
+ assert((bytes_received == sizeof message) && "Didn't receive full BinaryLoadMessage");
+ return message;
+}
+
+static void load_binary(BinaryLoadMessage const& message) {
+ uint8_t* binary = static_cast<uint8_t*>(mmap((void*)message.base_address, message.binary_size - message.base_address, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
+ if(binary == MAP_FAILED) {
+ std::cerr << "error during mmap: " << errno << " " << strerror(errno) << std::endl;
+ exit(1);
+ }
+
+ assert((binary == (void*)message.base_address) && "binary couldn't be loaded on the prefered address.");
+
+ uint8_t x[message.base_address];
+ recv(loader_socket, x, sizeof(x), 0);
+
+ size_t bytes_received = recv(loader_socket, binary, message.binary_size - message.base_address, 0);
+
+ assert((bytes_received == message.binary_size - (size_t)message.base_address) && "bytes_received did not match expected");
+}
+
+static void register_signal_handlers() {
+ struct sigaction sa;
+
+ memset(&sa, 0, sizeof sa);
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_SIGINFO;
+ sa.sa_sigaction = dos_emu_handler;
+
+ sigaction(SIGSEGV, &sa, NULL);
+}