mirror of
https://github.com/darlinghq/darlingserver.git
synced 2024-11-23 12:29:41 +00:00
commit
5bd9a87821
@ -56,6 +56,7 @@ typedef int (*dtape_hook_task_free_pages_f)(void* task_context, uintptr_t addres
|
|||||||
typedef uintptr_t (*dtape_hook_task_map_file_f)(void* task_context, int fd, size_t page_count, int protection, uintptr_t address_hint, size_t page_offset, dtape_memory_flags_t flags);
|
typedef uintptr_t (*dtape_hook_task_map_file_f)(void* task_context, int fd, size_t page_count, int protection, uintptr_t address_hint, size_t page_offset, dtape_memory_flags_t flags);
|
||||||
typedef uintptr_t (*dtape_hook_task_get_next_region_f)(void* task_context, uintptr_t address);
|
typedef uintptr_t (*dtape_hook_task_get_next_region_f)(void* task_context, uintptr_t address);
|
||||||
typedef bool (*dtape_hook_task_change_protection_f)(void* task_context, uintptr_t address, size_t page_count, int protection);
|
typedef bool (*dtape_hook_task_change_protection_f)(void* task_context, uintptr_t address, size_t page_count, int protection);
|
||||||
|
typedef bool (*dtape_hook_task_sync_memory_f)(void* task_context, uintptr_t address, size_t size, int sync_flags);
|
||||||
typedef void (*dtape_hook_task_context_dispose_f)(void* task_context);
|
typedef void (*dtape_hook_task_context_dispose_f)(void* task_context);
|
||||||
|
|
||||||
#if DSERVER_EXTENDED_DEBUG
|
#if DSERVER_EXTENDED_DEBUG
|
||||||
@ -101,6 +102,7 @@ typedef struct dtape_hooks {
|
|||||||
dtape_hook_task_map_file_f task_map_file;
|
dtape_hook_task_map_file_f task_map_file;
|
||||||
dtape_hook_task_get_next_region_f task_get_next_region;
|
dtape_hook_task_get_next_region_f task_get_next_region;
|
||||||
dtape_hook_task_change_protection_f task_change_protection;
|
dtape_hook_task_change_protection_f task_change_protection;
|
||||||
|
dtape_hook_task_sync_memory_f task_sync_memory;
|
||||||
dtape_hook_task_context_dispose_f task_context_dispose;
|
dtape_hook_task_context_dispose_f task_context_dispose;
|
||||||
|
|
||||||
#if DSERVER_EXTENDED_DEBUG
|
#if DSERVER_EXTENDED_DEBUG
|
||||||
|
@ -594,8 +594,28 @@ kern_return_t mach_vm_map_external(vm_map_t target_map, mach_vm_offset_t* addres
|
|||||||
dtape_stub_unsafe();
|
dtape_stub_unsafe();
|
||||||
};
|
};
|
||||||
|
|
||||||
kern_return_t mach_vm_msync(vm_map_t map, mach_vm_address_t address, mach_vm_size_t size, vm_sync_t sync_flags) {
|
kern_return_t mach_vm_msync(vm_map_t map, mach_vm_offset_t address, mach_vm_size_t size, vm_sync_t sync_flags) {
|
||||||
dtape_stub_unsafe();
|
int linux_flags = 0;
|
||||||
|
|
||||||
|
// TODO: give the Linux bits names/macros
|
||||||
|
|
||||||
|
if (sync_flags & VM_SYNC_ASYNCHRONOUS) {
|
||||||
|
linux_flags |= 1 << 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sync_flags & VM_SYNC_SYNCHRONOUS) {
|
||||||
|
linux_flags |= 1 << 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sync_flags & VM_SYNC_INVALIDATE) {
|
||||||
|
linux_flags |= 1 << 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dtape_hooks->task_sync_memory(map->dtape_task->context, address, size, linux_flags)) {
|
||||||
|
return KERN_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return KERN_SUCCESS;
|
||||||
};
|
};
|
||||||
|
|
||||||
kern_return_t mach_vm_page_info(vm_map_t map, mach_vm_address_t address, vm_page_info_flavor_t flavor, vm_page_info_t info, mach_msg_type_number_t* count) {
|
kern_return_t mach_vm_page_info(vm_map_t map, mach_vm_address_t address, vm_page_info_flavor_t flavor, vm_page_info_t info, mach_msg_type_number_t* count) {
|
||||||
|
@ -149,6 +149,7 @@ enum dserver_s2c_msgnum {
|
|||||||
dserver_s2c_msgnum_mmap,
|
dserver_s2c_msgnum_mmap,
|
||||||
dserver_s2c_msgnum_munmap,
|
dserver_s2c_msgnum_munmap,
|
||||||
dserver_s2c_msgnum_mprotect,
|
dserver_s2c_msgnum_mprotect,
|
||||||
|
dserver_s2c_msgnum_msync,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum dserver_s2c_msgnum dserver_s2c_msgnum_t;
|
typedef enum dserver_s2c_msgnum dserver_s2c_msgnum_t;
|
||||||
@ -207,10 +208,24 @@ typedef struct dserver_s2c_reply_mprotect {
|
|||||||
int errno_result;
|
int errno_result;
|
||||||
} dserver_s2c_reply_mprotect_t;
|
} dserver_s2c_reply_mprotect_t;
|
||||||
|
|
||||||
|
typedef struct dserver_s2c_call_msync {
|
||||||
|
dserver_s2c_callhdr_t header;
|
||||||
|
uint64_t address;
|
||||||
|
uint64_t size;
|
||||||
|
int sync_flags;
|
||||||
|
} dserver_s2c_call_msync_t;
|
||||||
|
|
||||||
|
typedef struct dserver_s2c_reply_msync {
|
||||||
|
dserver_s2c_replyhdr_t header;
|
||||||
|
int return_value;
|
||||||
|
int errno_result;
|
||||||
|
} dserver_s2c_reply_msync_t;
|
||||||
|
|
||||||
typedef union dserver_s2c_call {
|
typedef union dserver_s2c_call {
|
||||||
dserver_s2c_call_mmap_t mmap;
|
dserver_s2c_call_mmap_t mmap;
|
||||||
dserver_s2c_call_munmap_t munmap;
|
dserver_s2c_call_munmap_t munmap;
|
||||||
dserver_s2c_call_mprotect_t mprotect;
|
dserver_s2c_call_mprotect_t mprotect;
|
||||||
|
dserver_s2c_call_msync_t msync;
|
||||||
} dserver_s2c_call_t;
|
} dserver_s2c_call_t;
|
||||||
|
|
||||||
#if __cplusplus
|
#if __cplusplus
|
||||||
|
@ -180,6 +180,7 @@ namespace DarlingServer {
|
|||||||
void freePages(uintptr_t address, size_t pageCount);
|
void freePages(uintptr_t address, size_t pageCount);
|
||||||
uintptr_t mapFile(int fd, size_t pageCount, int protection, uintptr_t addressHint, size_t pageOffset, bool fixed, bool overwrite);
|
uintptr_t mapFile(int fd, size_t pageCount, int protection, uintptr_t addressHint, size_t pageOffset, bool fixed, bool overwrite);
|
||||||
void changeProtection(uintptr_t address, size_t pageCount, int protection);
|
void changeProtection(uintptr_t address, size_t pageCount, int protection);
|
||||||
|
void syncMemory(uintptr_t address, size_t size, int sync_flags);
|
||||||
|
|
||||||
uintptr_t getNextRegion(uintptr_t address) const;
|
uintptr_t getNextRegion(uintptr_t address) const;
|
||||||
|
|
||||||
|
@ -126,6 +126,7 @@ namespace DarlingServer {
|
|||||||
uintptr_t _mmap(uintptr_t address, size_t length, int protection, int flags, int fd, off_t offset, int& outErrno);
|
uintptr_t _mmap(uintptr_t address, size_t length, int protection, int flags, int fd, off_t offset, int& outErrno);
|
||||||
int _munmap(uintptr_t address, size_t length, int& outErrno);
|
int _munmap(uintptr_t address, size_t length, int& outErrno);
|
||||||
int _mprotect(uintptr_t address, size_t length, int protection, int& outErrno);
|
int _mprotect(uintptr_t address, size_t length, int protection, int& outErrno);
|
||||||
|
int _msync(uintptr_t address, size_t size, int sync_flags, int& outErrno);
|
||||||
|
|
||||||
void _deferLocked(bool wait, std::unique_lock<std::shared_mutex>& lock);
|
void _deferLocked(bool wait, std::unique_lock<std::shared_mutex>& lock);
|
||||||
void _undeferLocked(std::unique_lock<std::shared_mutex>& lock);
|
void _undeferLocked(std::unique_lock<std::shared_mutex>& lock);
|
||||||
@ -235,6 +236,7 @@ namespace DarlingServer {
|
|||||||
void freePages(uintptr_t address, size_t pageCount);
|
void freePages(uintptr_t address, size_t pageCount);
|
||||||
uintptr_t mapFile(int fd, size_t pageCount, int protection, uintptr_t addressHint, size_t pageOffset, bool fixed, bool overwrite);
|
uintptr_t mapFile(int fd, size_t pageCount, int protection, uintptr_t addressHint, size_t pageOffset, bool fixed, bool overwrite);
|
||||||
void changeProtection(uintptr_t address, size_t pageCount, int protection);
|
void changeProtection(uintptr_t address, size_t pageCount, int protection);
|
||||||
|
void syncMemory(uintptr_t address, size_t size, int sync_flags);
|
||||||
|
|
||||||
void defer(bool wait = false);
|
void defer(bool wait = false);
|
||||||
void undefer();
|
void undefer();
|
||||||
|
@ -633,6 +633,16 @@ void DarlingServer::Process::changeProtection(uintptr_t address, size_t pageCoun
|
|||||||
return thread->changeProtection(address, pageCount, protection);
|
return thread->changeProtection(address, pageCount, protection);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void DarlingServer::Process::syncMemory(uintptr_t address, size_t size, int sync_flags) {
|
||||||
|
auto thread = _pickS2CThread();
|
||||||
|
|
||||||
|
if (!thread) {
|
||||||
|
throw std::system_error(ESRCH, std::generic_category());
|
||||||
|
}
|
||||||
|
|
||||||
|
return thread->syncMemory(address, size, sync_flags);
|
||||||
|
};
|
||||||
|
|
||||||
static const std::regex memoryRegionEntryAddressRegex("([0-9a-fA-F]+)\\-([0-9a-fA-F]+)");
|
static const std::regex memoryRegionEntryAddressRegex("([0-9a-fA-F]+)\\-([0-9a-fA-F]+)");
|
||||||
|
|
||||||
uintptr_t DarlingServer::Process::getNextRegion(uintptr_t address) const {
|
uintptr_t DarlingServer::Process::getNextRegion(uintptr_t address) const {
|
||||||
|
@ -302,6 +302,15 @@ struct DTapeHooks {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static bool dtape_hook_task_sync_memory(void* task_context, uintptr_t address, size_t size, int sync_flags) {
|
||||||
|
try {
|
||||||
|
static_cast<DarlingServer::Process*>(task_context)->syncMemory(address, size, sync_flags);
|
||||||
|
return true;
|
||||||
|
} catch (std::system_error e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
static void dtape_hook_task_context_dispose(void* task_context) {
|
static void dtape_hook_task_context_dispose(void* task_context) {
|
||||||
static_cast<DarlingServer::Process*>(task_context)->_dispose();
|
static_cast<DarlingServer::Process*>(task_context)->_dispose();
|
||||||
};
|
};
|
||||||
@ -363,6 +372,7 @@ struct DTapeHooks {
|
|||||||
.task_map_file = dtape_hook_task_map_file,
|
.task_map_file = dtape_hook_task_map_file,
|
||||||
.task_get_next_region = dtape_hook_task_get_next_region,
|
.task_get_next_region = dtape_hook_task_get_next_region,
|
||||||
.task_change_protection = dtape_hook_task_change_protection,
|
.task_change_protection = dtape_hook_task_change_protection,
|
||||||
|
.task_sync_memory = dtape_hook_task_sync_memory,
|
||||||
.task_context_dispose = dtape_hook_task_context_dispose,
|
.task_context_dispose = dtape_hook_task_context_dispose,
|
||||||
|
|
||||||
#if DSERVER_EXTENDED_DEBUG
|
#if DSERVER_EXTENDED_DEBUG
|
||||||
|
@ -1171,6 +1171,34 @@ int DarlingServer::Thread::_mprotect(uintptr_t address, size_t length, int prote
|
|||||||
return reply->return_value;
|
return reply->return_value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int DarlingServer::Thread::_msync(uintptr_t address, size_t size, int sync_flags, int& outErrno) {
|
||||||
|
Message callMessage(sizeof(dserver_s2c_call_msync_t), 0);
|
||||||
|
auto call = reinterpret_cast<dserver_s2c_call_msync_t*>(callMessage.data().data());
|
||||||
|
|
||||||
|
call->header.call_number = dserver_callnum_s2c;
|
||||||
|
call->header.s2c_number = dserver_s2c_msgnum_msync;
|
||||||
|
call->address = address;
|
||||||
|
call->size = size;
|
||||||
|
call->sync_flags = sync_flags;
|
||||||
|
|
||||||
|
s2cLog.debug() << "Performing _msync with address=" << call->address << ", size=" << call->size << ", sync_flags=" << call->sync_flags << s2cLog.endLog;
|
||||||
|
|
||||||
|
auto maybeReplyMessage = _s2cPerform(std::move(callMessage), dserver_s2c_msgnum_msync, sizeof(dserver_s2c_reply_msync_t));
|
||||||
|
if (!maybeReplyMessage) {
|
||||||
|
s2cLog.debug() << "_msync call interrupted" << s2cLog.endLog;
|
||||||
|
outErrno = EINTR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto replyMessage = std::move(*maybeReplyMessage);
|
||||||
|
auto reply = reinterpret_cast<dserver_s2c_reply_msync_t*>(replyMessage.data().data());
|
||||||
|
|
||||||
|
s2cLog.debug() << "_msync returned return_value=" << reply->return_value << ", errno_result=" << reply->errno_result << s2cLog.endLog;
|
||||||
|
|
||||||
|
outErrno = reply->errno_result;
|
||||||
|
return reply->return_value;
|
||||||
|
};
|
||||||
|
|
||||||
uintptr_t DarlingServer::Thread::allocatePages(size_t pageCount, int protection, uintptr_t addressHint, bool fixed, bool overwrite) {
|
uintptr_t DarlingServer::Thread::allocatePages(size_t pageCount, int protection, uintptr_t addressHint, bool fixed, bool overwrite) {
|
||||||
int err = 0;
|
int err = 0;
|
||||||
int flags = MAP_PRIVATE | MAP_ANONYMOUS;
|
int flags = MAP_PRIVATE | MAP_ANONYMOUS;
|
||||||
@ -1215,6 +1243,13 @@ void DarlingServer::Thread::changeProtection(uintptr_t address, size_t pageCount
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void DarlingServer::Thread::syncMemory(uintptr_t address, size_t size, int sync_flags) {
|
||||||
|
int err = 0;
|
||||||
|
if (_msync(address, size, sync_flags, err) < 0) {
|
||||||
|
throw std::system_error(err, std::generic_category(), "S2C msync call failed");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void DarlingServer::Thread::waitUntilRunning() {
|
void DarlingServer::Thread::waitUntilRunning() {
|
||||||
std::shared_lock lock(_rwlock);
|
std::shared_lock lock(_rwlock);
|
||||||
_runningCondvar.wait(lock, [&]() {
|
_runningCondvar.wait(lock, [&]() {
|
||||||
|
Loading…
Reference in New Issue
Block a user