71 lines
2.1 KiB
C++
71 lines
2.1 KiB
C++
#include <pslang/jit/host_executable.hpp>
|
|
#include <pslang/jit/linker.hpp>
|
|
#include <pslang/jit/foreign.hpp>
|
|
|
|
#include <system_error>
|
|
|
|
#if defined(__linux__) || defined(__APPLE__)
|
|
#include <sys/mman.h>
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
#include <stdexcept>
|
|
|
|
namespace pslang::jit
|
|
{
|
|
|
|
namespace
|
|
{
|
|
|
|
std::size_t native_page_size()
|
|
{
|
|
#if defined(__linux__) || defined(__APPLE__)
|
|
return getpagesize();
|
|
#else
|
|
throw std::runtime_error("Native page size is not supported for this platform");
|
|
#endif
|
|
}
|
|
|
|
}
|
|
|
|
host_executable_program make_host_executable(std::vector<compiled_module> const & modules)
|
|
{
|
|
#if defined(__linux__) || defined(__APPLE__)
|
|
auto const page_size = native_page_size();
|
|
auto const abi = host_abi();
|
|
|
|
for (auto const & module : modules)
|
|
if (module.abi != abi)
|
|
throw std::runtime_error("Internal error: wrong compiled module ABI for host-executable binary");
|
|
|
|
auto link_info = prepare_link(modules, {.section_alignment = page_size});
|
|
|
|
auto storage = (std::uint8_t *)mmap(nullptr, link_info.total_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
|
|
if (storage == MAP_FAILED)
|
|
throw std::system_error(errno, std::generic_category());
|
|
|
|
host_executable_program result;
|
|
result.mapping.reset(storage, [total_size = link_info.total_size](void * ptr){ munmap(ptr, total_size); });
|
|
|
|
link(modules, link_info, storage);
|
|
|
|
for (auto const & relocation : link_info.relocation_offset)
|
|
*(void **)(storage + relocation.second) = load_foreign(relocation.first);
|
|
|
|
if (mprotect(storage + link_info.code.begin, link_info.code.size, PROT_READ | PROT_EXEC) != 0)
|
|
throw std::system_error(errno, std::generic_category());
|
|
|
|
if (mprotect(storage + link_info.relocations.begin, link_info.relocations.size, PROT_READ) != 0)
|
|
throw std::system_error(errno, std::generic_category());
|
|
|
|
result.functions = std::move(link_info.functions);
|
|
result.globals = std::move(link_info.globals);
|
|
result.entry_points = std::move(link_info.entry_points);
|
|
|
|
return result;
|
|
#else
|
|
throw std::runtime_error("Host-executable modules are not supported for this platform");
|
|
#endif
|
|
}
|
|
|
|
}
|