#include "shm.h" #include "shm_object.h" #include "shm_manager.h" bg::detail::ShmContext g_shm_ctx; namespace bg { ShmOptions::ShmOptions(bool resume, const char* identifier, ShmLogger* logger) { this->main_address = 0x600000000000LL; this->resume = resume; this->logger = logger; this->shm_block_mmap_size = 0x100000000LL; this->replace_sys_alloc = false; this->fix_vptr_on_init = 1; this->shm_block_grow_size = 0x2000000LL; snprintf(this->identifier, 64, "%s", identifier); this->fixed_address_count = bg::ShmOptions::FillDefaultFixedAddresses(this->fixed_addresses, 0x10uLL); } bool ShmOptions::AddFixedAddress(uintptr_t addr) { if(fixed_address_count <= 0) { fixed_address_count++; fixed_addresses[fixed_address_count] = addr; return true; } return false; } bool ShmOptions::PopFixedAddress(uintptr_t* addr) { if(fixed_address_count) { fixed_address_count--; if(addr) { *addr = fixed_addresses[fixed_address_count]; return true; } return true; } return false; } size_t ShmOptions::FillDefaultFixedAddresses(uintptr_t* result, size_t max_count) { if(!max_count) { return max_count; } for(size_t i = 0; i < max_count; ++i) { result[i] = (126 - i) << 40; } return max_count; } bool ShmInit(const ShmOptions& options) { char path[256]; bg::detail::ShmManager* manager; size_t total_bytes = sizeof(bg::detail::ShmManager); bool result; if(g_shm_ctx.mgr) { return true; } if(options.logger) { g_shm_ctx.logger = options.logger; } snprintf(path, 256, "%s-mgr.mmap", options.identifier); if(!options.resume) { manager = (bg::detail::ShmManager*)bg::detail::ShmObjectCreate(path, options.main_address, &total_bytes, &total_bytes); } else { manager = (bg::detail::ShmManager*)bg::detail::ShmObjectAttach(path, options.main_address, &total_bytes, &total_bytes); } if(manager) { if(options.resume || (new(manager) bg::detail::ShmManager(options), options.resume)) { result = manager->OnResume(options.identifier); } else { result = manager->OnCreate(); } if(!result) { manager->~ShmManager(); bg::detail::ShmObjectDelete(manager, total_bytes, path); return false; } g_shm_ctx.mgr = manager; g_shm_ctx.mmap_size = total_bytes; snprintf(g_shm_ctx.path, 0x100uLL, "%s", path); if(!bg::detail::VptrManager::Init()) { bg::ShmFini(); return false; } if(!options.fix_vptr_on_init) { return true; } bg::detail::VptrManager::FixVptr(); return true; } return false; } void ShmFini() { if(g_shm_ctx.mgr) { bg::detail::VptrManager::Fini(); g_shm_ctx.mgr->~ShmManager(); bg::detail::ShmObjectDelete(g_shm_ctx.mgr, g_shm_ctx.mmap_size, g_shm_ctx.path); g_shm_ctx.mgr = nullptr; g_shm_ctx.mmap_size = 0LL; memset(g_shm_ctx.path, 0, sizeof(g_shm_ctx.path)); } } void ShmFixVptr() { bg::detail::VptrManager::FixVptr(); } }