57 lines
1.6 KiB
C++
57 lines
1.6 KiB
C++
#include <pslang/jit/executable.hpp>
|
|
|
|
#include <stdexcept>
|
|
#include <system_error>
|
|
|
|
#ifdef __linux__
|
|
#include <sys/mman.h>
|
|
#endif
|
|
|
|
#ifdef __APPLE__
|
|
#include <sys/mman.h>
|
|
#endif
|
|
|
|
namespace pslang::jit
|
|
{
|
|
|
|
std::shared_ptr<std::uint8_t> 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<std::uint8_t>(ptr, [total_size](void * ptr){ munmap(ptr, total_size); });
|
|
#else
|
|
throw std::runtime_error("Host-executable modules are not supported for this platform");
|
|
#endif
|
|
}
|
|
|
|
}
|