diff options
Diffstat (limited to 'run/runner.cpp')
| -rw-r--r-- | run/runner.cpp | 94 |
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); +} |
