#include #include #include #ifdef __linux__ #include #endif #ifdef __APPLE__ #include #endif namespace pslang::jit { std::shared_ptr make_host_executable(binary_storage const & storage) { #if defined(__linux__) || defined(__APPLE__) auto const page_size = native_page_size(); for (auto const & range : storage.data) { if ((range.begin % page_size) != 0) throw std::runtime_error("Data range start is not aligned to page boundary"); if ((range.end % page_size) != 0) throw std::runtime_error("Data range end is not aligned to page boundary"); } for (auto const & range : storage.code) { if ((range.begin % page_size) != 0) throw std::runtime_error("Code range start is not aligned to page boundary"); if ((range.end % page_size) != 0) throw std::runtime_error("Code range end is not aligned to page boundary"); } auto total_size = storage.storage.size(); auto ptr = (std::uint8_t *)mmap(nullptr, total_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); if (ptr == MAP_FAILED) throw std::system_error(errno, std::generic_category()); std::copy(storage.storage.begin(), storage.storage.end(), ptr); for (auto const & range : storage.code) if (mprotect(ptr + range.begin, range.end - range.begin, PROT_READ | PROT_EXEC) != 0) throw std::system_error(errno, std::generic_category()); return std::shared_ptr(ptr, [total_size](void * ptr){ munmap(ptr, total_size); }); #else throw std::runtime_error("Host-executable modules are not supported for this platform"); #endif } }