#include "shm_manager.h" #include "shm_object.h" #include "shm_config.h" extern bg::detail::ShmContext g_shm_ctx; namespace bg { namespace detail { ShmManager::ShmManager(const bg::ShmOptions& options) : m_options(options) { snprintf(this->m_magic, 0x40uLL, "ByteGame/ShmManager-%s", this->m_options.identifier); } ShmManager::~ShmManager() { if(m_singletons) { m_singletons->clear(); bg::ShmFree(m_singletons); this->m_singletons = nullptr; } for(size_t i = 0LL; this->m_block_count > i; ++i) { DeleteBlock(i); } } void* ShmManager::AllocateRawMemory(size_t* bytes, size_t alignment) { void* result = nullptr; if((alignment & (alignment - 1)) != 0) { SHM_ERROR("invalid alignment(%#lx).", (const char*)alignment); return result; } *bytes = PALIGN_UP(*bytes, alignment); if(m_block_count) { result = AllocateInBlock(m_block_count - 1, *bytes, alignment); if(result) { return result; } } if(CreateBlock(m_block_count, *bytes)) { size_t index = m_block_count > 1 ? m_block_count - 1 : 0; result = AllocateInBlock(index, *bytes, alignment); if(!result) { SHM_ERROR("newly created block(%lu) still cannot satisfy requirement, addr(%#lx), used size(%#lx), real size(%#lx), real bytes(%#lx), alignment(%#lx).", m_block_count, m_blocks[index].addr, m_blocks[index].used_size, m_blocks[index].real_size); return result; } } else { SHM_ERROR("failed to create block(%lu), real bytes(%#lx).", this->m_block_count, *bytes); } return result; } bool ShmManager::HasSingleton(const bg::detail::TypeName& type) { auto itor = m_singletons->find(type); if(itor == m_singletons->end()) { return false; } return true; } void* ShmManager::GetSingleton(const bg::detail::TypeName& type, size_t bytes, bool* first_call) { if(!m_singletons) { m_singletons = (bg::detail::ShmManager::SingletonMap*)bg::ShmMalloc(sizeof(bg::detail::ShmManager::SingletonMap)); if(!m_singletons) { m_singletons = nullptr; return nullptr; } new(m_singletons) SingletonMap; } auto itor = m_singletons->find(type); if(itor != m_singletons->end()) { return itor->second; } uint8_t index{}; if(bytes <= BYTES_COMP_VALUE) { index = m_size_map.m_index_to_class[SMALL_BYTES_TO_INDEX(bytes)]; } else { if(bytes > CLASS_MAX_BYTES) { bg::detail::Span* span = m_page_heap.AllocateSpan(BYTES_TO_PAGES(bytes + PAGE_BYTES)); if(span) { void* chunk_span = (void*)PAGES_TO_BYTES(span->m_start_page); if(chunk_span) { m_singletons->operator[](type) = chunk_span; if(first_call) { *first_call = 1; SHM_INFO("singleton(%s: %p) created.", type.c_str(), chunk_span); } return chunk_span; } } return nullptr; } index = m_size_map.m_index_to_class[BIG_BYTES_TO_INDEX(bytes)]; } if(index > CLASS_MAX_COUNT) { return nullptr; } ChunkCache::ClassCache* cheche = &this->m_chunk_cache.m_caches[index]; size_t size = this->m_size_map.ClassToSize(index); if(cheche == (bg::detail::ChunkCache::ClassCache*)cheche->free_list.m_next) { bg::detail::Span* span = m_page_heap.AllocateSpan(m_size_map.m_class_to_pages[index]); if(span) { m_page_heap.RegisterSpan(span); span->m_size_class = index; span->m_chunk_list = (void*)PAGES_TO_BYTES(span->m_start_page); uintptr_t end_memory = (uintptr_t)PAGES_TO_BYTES(span->m_start_page + span->m_page_count); uintptr_t end_ptr = (uintptr_t)span->m_chunk_list + size; uintptr_t ptr = (uintptr_t)span->m_chunk_list; for(; end_ptr < end_memory; ) { *((uintptr_t*)ptr) = end_ptr; auto temp = end_ptr + size; if(temp > end_memory) { break; } ptr = end_ptr; end_ptr = temp; } *(uintptr_t*)ptr = 0ll; cheche->free_list.InstertNextSpan(span); ++cheche->span_count; } } if(cheche == (bg::detail::ChunkCache::ClassCache*)cheche->free_list.m_next) { return nullptr; } auto next_span = cheche->free_list.m_next; ++next_span->m_used_count; auto chunk_span = next_span->m_chunk_list; next_span->m_chunk_list = *(void**)chunk_span; if(*(void**)chunk_span == nullptr) { cheche->free_list.RemoveNextSpan(); --this->m_chunk_cache.m_caches[index].span_count; } m_singletons->operator[](type) = chunk_span; if(first_call) { *first_call = 1; SHM_INFO("singleton(%s: %p) created.", type.c_str(), chunk_span); } return chunk_span; } void ShmManager::FreeSingleton(const bg::detail::TypeName& type) { if(m_singletons) { auto itor = m_singletons->find(type); if(itor == m_singletons->end()) { return; } SHM_INFO("singleton(%s: %p) destroyed.", type.c_str()); bg::detail::Span* span = m_page_heap.GetSpanMap(BYTES_TO_PAGES((uintptr_t)itor->second)); if(span) { do { if(span->m_size_class == 0xff) { m_page_heap.DeallocateSpan(span); } else { if(span->m_used_count && span->m_size_class <= CLASS_MAX_COUNT) { span->m_used_count -= 1; auto chunk_list = span->m_chunk_list; *(uintptr_t*)itor->second = (uintptr_t)span->m_chunk_list; span->m_chunk_list = itor->second; if(chunk_list) { if(span->m_used_count == 0) { if(m_chunk_cache.m_caches[span->m_size_class].span_count > 1) { span->m_prev->RemoveNextSpan(); span->m_in_use = false; span->m_used_count = 0LL; span->m_size_class = -1; span->m_chunk_list = 0LL; m_page_heap.DeallocateSpan(span); } } } else { if(span->m_used_count == 0) { if(m_chunk_cache.m_caches[span->m_size_class].span_count) { span->m_used_count = 0LL; span->m_size_class = -1; span->m_chunk_list = 0LL; m_page_heap.DeallocateSpan(span); break; } } m_chunk_cache.m_caches[span->m_size_class].free_list.m_next->InstertNextSpan(span); m_chunk_cache.m_caches[span->m_size_class].span_count++; } } } } while(false); } m_singletons->erase(itor); } return; } bool ShmManager::OnResume(const char* identifier) { char magic[64]; // [rsp+0h] [rbp-60h] BYREF int size = snprintf(magic, 0x40uLL, "ByteGame/ShmManager-%s", identifier); if(!strncmp(magic, this->m_magic, size)) { size_t index = 0; for(; index < m_block_count; ++index) { if(!AttachBlock(index)) { SHM_ERROR("failed to attach block(%lu), address(%#lx), used size(%#lx), real size(%#lx), mmap size(%#lx).", index, m_blocks[index].addr, m_blocks[index].used_size, m_blocks[index].real_size, m_blocks[index].mmap_size); return false; } } if(m_block_count <= index) { m_version++; return true; } } SHM_ERROR("magic mismatch, expected: %s, actual: %s.", magic, this->m_magic); return false; } bool ShmManager::OnCreate(void) { return m_size_map.Init(); } bool ShmManager::DeleteBlock(size_t index) { SHM_ASSERT_RETURN_FALSE(index > m_block_count); char path[256]; if(m_blocks[index].addr) { m_options.AddFixedAddress((uintptr_t)m_blocks[index].addr); snprintf(path, 0x100uLL, "%s-%03zu.mmap", this->m_options.identifier, index); bg::detail::ShmObjectDelete(m_blocks[index].addr, m_blocks[index].mmap_size, path); SHM_INFO("block(%lu) deleted, address(%#lx), used size(%#lx), real size(%#lx), mmap size(%#lx), path(%s).", index, m_blocks[index].addr, m_blocks[index].used_size, m_blocks[index].real_size, m_blocks[index].mmap_size, path); new (m_blocks[index].addr) ShmBlock(); } return true; } void* ShmManager::AllocateInBlock(size_t index, size_t bytes, size_t alignment) { size_t v7; // r8 char* v8; // r12 __int64 v9; // rdx __int64 v10; // rax __int64 v11; // rbx size_t v12; // rcx size_t mmap_size; // rsi size_t real_size; // rdi size_t shm_block_grow_size; // r10 const char* v16; // r15 const char* v17; // rcx size_t v18; // rdx size_t v20; // [rsp+0h] [rbp-40h] char* v21; // [rsp+8h] [rbp-38h] if(this->m_block_count <= index) { return 0LL; } else { v7 = 0LL; v8 = (char*)this + 32 * index; v9 = *((uintptr_t*)v8 + 3113); v10 = *((uintptr_t*)v8 + 3114); v11 = v10 + v9; if(((v10 + v9) & (alignment - 1)) != 0) { v7 = alignment - ((v10 + v9) & (alignment - 1)); v11 += v7; } v12 = v11 + bytes; mmap_size = this->m_blocks[index].mmap_size; if(v11 + bytes > mmap_size + v9) { return 0LL; } else { real_size = this->m_blocks[index].real_size; if(v12 <= real_size + v9) { LABEL_13: *((uintptr_t*)v8 + 3114) = v7 + bytes + v10; return (void*)v11; } shm_block_grow_size = this->m_options.shm_block_grow_size; v16 = (const char*)(shm_block_grow_size + real_size); if(v12 > shm_block_grow_size + real_size + v9) { v17 = (const char*)(v12 - v9); v16 = v17; //v18 = (uintptr_t)&v17[-real_size] % shm_block_grow_size; v18 = 0; if(v18) v16 = &v17[shm_block_grow_size - v18]; } v21 = (char*)index; if((unsigned __int64)v16 > mmap_size) v16 = (const char*)mmap_size; v20 = v7; if(ResizeBlock(index, v16)) { v10 = *((uintptr_t*)v8 + 3114); v7 = v20; goto LABEL_13; } return nullptr; } } } bool ShmManager::CreateBlock(size_t index, size_t min_size) { size_t shm_block_grow_size; // rcx size_t shm_block_mmap_size; // rax __int64 v8; // rax uintptr_t fixed_addr; // [rsp+8h] [rbp-138h] BYREF size_t real_size; // [rsp+10h] [rbp-130h] BYREF size_t mmap_size; // [rsp+18h] [rbp-128h] BYREF char path[256]; // [rsp+20h] [rbp-120h] BYREF if(index > 0xFF) { return 0LL; } else { shm_block_grow_size = this->m_options.shm_block_grow_size; shm_block_mmap_size = this->m_options.shm_block_mmap_size; fixed_addr = 0LL; real_size = shm_block_grow_size; mmap_size = shm_block_mmap_size; if(shm_block_grow_size < min_size) real_size = min_size; if(shm_block_mmap_size < min_size) mmap_size = min_size; m_options.PopFixedAddress(&fixed_addr); snprintf(path, 0x100uLL, "%s-%03zu.mmap", this->m_options.identifier, index); v8 = (uintptr_t)bg::detail::ShmObjectCreate(path, fixed_addr, &real_size, &mmap_size); if(!v8) { if(fixed_addr) m_options.AddFixedAddress(fixed_addr); return false; } m_blocks[index].addr = (void*)v8; m_blocks[index].real_size = real_size; m_blocks[index].mmap_size = mmap_size; m_blocks[index].used_size = 0; if(this->m_block_count != index) return true; this->m_block_count = index + 1; } return true; } bool ShmManager::AttachBlock(size_t index) { __int64 result; // rax char* v3; // rbx size_t v4; // rax __int64 v6; // rdx size_t real_size; // [rsp+0h] [rbp-130h] BYREF size_t mmap_size; // [rsp+8h] [rbp-128h] BYREF char path[256]; // [rsp+10h] [rbp-120h] BYREF if(this->m_block_count <= index) { return 0LL; } else { result = 1LL; v3 = (char*)this + 32 * index; if(*((uintptr_t*)v3 + 3113)) { v4 = *((uintptr_t*)v3 + 3116); real_size = 0LL; mmap_size = v4; snprintf(path, 0x100uLL, "%s-%03zu.mmap", this->m_options.identifier, index); v6 = (uintptr_t)bg::detail::ShmObjectAttach(path, (uintptr_t) * ((const char**)v3 + 3113), &real_size, &mmap_size); result = 0LL; if(v6) { return 1LL; } } } return result; } bool ShmManager::ResizeBlock(size_t index, size_t new_size) { bool v3; // cc unsigned int v5; // r13d size_t new_sizea; // [rsp+8h] [rbp-128h] BYREF char path[256]; // [rsp+10h] [rbp-120h] BYREF SHM_ASSERT_RETURN_FALSE(index < m_block_count); if(m_blocks[index].mmap_size < new_size) { SHM_ERROR("new size(%#lx) too large, block(%lu), mmap size(%#lx).", new_size, index, m_blocks[index].mmap_size); return false; } else { snprintf(path, 0x100uLL, "%s-%03zu.mmap", this->m_options.identifier, index); if(bg::detail::ShmObjectResize(path, &new_size)) { SHM_INFO("block(%lu) resized, old size(%#lx), new size(%#lx), used size(%#lx), mmap size(%#lx).", index, m_blocks[index].addr, m_blocks[index].real_size, new_size, m_blocks[index].used_size, m_blocks[index].mmap_size); this->m_blocks[index].real_size = new_sizea; return true; } } return false; } } void* ShmMalloc(size_t bytes) { int64_t v6; // rbx uint8_t index; // r15 __int64 v9; // r14 __int64 v10; // r13 bg::detail::Span* v11; // r12 bg::detail::Span* m_next; // r8 void** result; // rax bool v14; // zf bg::detail::Span* Span; // rax bg::detail::PageHeap* v16; // rdi bg::detail::Span* v17; // rax size_t m_start_page; // rcx size_t m_page_count; // rdi void** p_m_chunk_list; // rax void** v21; // rcx void** v22; // rdx void** v23; // rdi void** v24; // rsi __int64 v25; // rax bg::detail::Span* v26; // rcx bg::detail::Span* m_prev; // rdx bg::detail::Span* v28; // [rsp+0h] [rbp-40h] bg::detail::PageHeap* v29; // [rsp+8h] [rbp-38h] v6 = (int64_t)g_shm_ctx.mgr; if(!v6) { return nullptr; } if(bytes <= BYTES_COMP_VALUE) { index = g_shm_ctx.mgr->m_size_map.m_index_to_class[SMALL_BYTES_TO_INDEX(bytes)]; } else { if(bytes > CLASS_MAX_BYTES) { Span = g_shm_ctx.mgr->m_page_heap.AllocateSpan(BYTES_TO_PAGES(bytes + 0x1FFF)); if(Span) { return (void**)(*(uintptr_t*)(Span + 16) << 13); } return nullptr; } auto temp1 = BIG_BYTES_TO_INDEX(bytes); index = g_shm_ctx.mgr->m_size_map.m_index_to_class[BIG_BYTES_TO_INDEX(bytes)]; } if(index > CLASS_MAX_COUNT) { v9 = g_shm_ctx.mgr->m_size_map.m_class_to_size[index]; v10 = index; v11 = &g_shm_ctx.mgr->m_chunk_cache.m_caches[index].free_list; if(v11 != v11->m_next) goto LABEL_7; v29 = &g_shm_ctx.mgr->m_page_heap; v16 = &g_shm_ctx.mgr->m_page_heap; goto LABEL_18; } v9 = g_shm_ctx.mgr->m_size_map.m_class_to_size[index]; v10 = index; v11 = &g_shm_ctx.mgr->m_chunk_cache.m_caches[index].free_list; if(v11 == v11->m_next) { v29 = &g_shm_ctx.mgr->m_page_heap; v16 = &g_shm_ctx.mgr->m_page_heap; LABEL_18: v17 = v16->AllocateSpan(g_shm_ctx.mgr->m_size_map.m_class_to_pages[index]); if(v17) { v28 = v17; v29->RegisterSpan(v17); m_next = v28; m_start_page = v28->m_start_page; m_page_count = v28->m_page_count; p_m_chunk_list = &v28->m_chunk_list; v28->m_size_class = index; v21 = (void**)(m_start_page << 13); v22 = (void**)((char*)v21 + v9); v23 = &v21[1024 * m_page_count]; if((void**)((char*)v21 + v9) <= v23) { while(1) { v24 = v22; v22 = (void**)((char*)v22 + v9); *p_m_chunk_list = v21; p_m_chunk_list = v21; if(v23 < v22) break; v21 = v24; } } else { v21 = &v28->m_chunk_list; } *v21 = 0LL; v25 = v6 + (v10 << 6); v26 = *(bg::detail::Span**)(v25 + 40); v28->m_prev = v11; v28->m_next = v26; *(uintptr_t*)(*(uintptr_t*)(v25 + 40) + 32LL) = (uintptr_t)v28; *(uintptr_t*)(v25 + 40) = (uintptr_t)v28; ++* (uintptr_t*)(v25 + 56); goto LABEL_8; } return 0LL; } LABEL_7: m_next = v11->m_next; LABEL_8: result = (void**)m_next->m_chunk_list; ++m_next->m_used_count; v14 = *result == 0LL; m_next->m_chunk_list = *result; if(v14) { m_prev = m_next->m_prev; m_prev->m_next = m_next->m_next; m_next->m_next->m_prev = m_prev; m_next->m_prev = 0LL; m_next->m_next = 0LL; --* (uintptr_t*)(v6 + (v10 << 6) + 56); } return result; } void ShmFree(void* ptr) { __int64 v6; // rcx __int64 v7; // rsi __int64 v8; // rax bg::detail::Span* v9; // rsi __int64 m_size_class; // rax size_t m_used_count; // rdx void* m_chunk_list; // r9 size_t v13; // rdx bool v14; // dl __int64 v15; // rax bg::detail::Span* m_prev; // rdx __int64 v17; // rax bg::detail::Span* v18; // rdi bg::detail::Span* v19; // rcx v6 = (int64_t)g_shm_ctx.mgr; if(!v6) { return; } if(ptr) { if((uintptr_t)ptr >> 13 > 0x7FFFFFFFFLL) { } else { v7 = *(uintptr_t*)(v6 + 8 * ((uintptr_t)ptr >> 38) + 9136); if(v7) { v8 = *(uintptr_t*)(v7 + 8 * (((uintptr_t)ptr >> 28) & 0x3FF)); if(v8) { v9 = *(bg::detail::Span**)(v8 + 8 * (((uintptr_t)ptr >> 13) & 0x7FFF)); if(v9) { m_size_class = v9->m_size_class; if((char)m_size_class == 0xFF) { ((bg::detail::PageHeap*)(v6 + 9136))->DeallocateSpan(v9); } else { m_used_count = v9->m_used_count; if(m_used_count && (unsigned __int8)m_size_class <= 0x56u) { m_chunk_list = v9->m_chunk_list; v13 = m_used_count - 1; *(uintptr_t*)ptr = (uintptr_t)m_chunk_list; v9->m_used_count = v13; v14 = v13 == 0; v9->m_chunk_list = (void*)ptr; if(m_chunk_list) { if(v14) { v15 = v6 + (m_size_class << 6) + 48; if(*(uintptr_t*)(v15 + 8) > 1uLL) { m_prev = v9->m_prev; m_prev->m_next = v9->m_next; v9->m_next->m_prev = m_prev; v9->m_prev = 0LL; v9->m_next = 0LL; --* (uintptr_t*)(v15 + 8); LABEL_14: v9->m_used_count = 0LL; v9->m_size_class = -1; v9->m_chunk_list = 0LL; ((bg::detail::PageHeap*)(v6 + 9136))->DeallocateSpan(v9); return; } } } else { v17 = v6 + (m_size_class << 6); if(v14) { if(*(uintptr_t*)(v17 + 56)) goto LABEL_14; v18 = *(bg::detail::Span**)(v17 + 40); v9->m_prev = (bg::detail::Span*)v17; v9->m_next = v18; *(uintptr_t*)(*(uintptr_t*)(v17 + 40) + 32LL) = (uintptr_t)v9; *(uintptr_t*)(v17 + 40) = (uintptr_t)v9; ++* (uintptr_t*)(v17 + 56); } else { v19 = *(bg::detail::Span**)(v17 + 40); v9->m_prev = (bg::detail::Span*)v17; v9->m_next = v19; *(uintptr_t*)(*(uintptr_t*)(v17 + 40) + 32LL) = (uintptr_t)v9; ++* (uintptr_t*)(v17 + 56); *(uintptr_t*)(v17 + 40) = (uintptr_t)v9; } } } else { } } return; } } } } } } void* ShmRealloc(void* old_ptr, size_t new_bytes) { __int64 v6; // r14 unsigned __int64 v9; // r15 unsigned __int64 v10; // r10 __int64 v11; // r11 __int64 v12; // rax __int64 v13; // rax __int64 v14; // rax __int64 v15; // rbx size_t v16; // rbx size_t v17; // rdx void** result; // rax bg::detail::Span* v19; // rax bg::detail::Span* v20; // rax void** m_chunk_list; // rdi void* v22; // rdx size_t v23; // rdx __int64 v24; // rax __int64 v25; // rax bg::detail::Span* v26; // rsi uint8_t m_size_class; // al size_t m_used_count; // rcx __int64 v29; // rdx void* v30; // rax size_t v31; // rcx bg::detail::PageHeap* v32; // rdi bool v33; // cl __int64 v34; // rdx bg::detail::Span* v35; // rcx bg::detail::Span* v36; // rax bg::detail::Span* m_next; // rax void** v38; // rdi void* v39; // rdx bg::detail::Span* v40; // rdx __int64 Span; // rax __int64 v42; // r14 bg::detail::Span* v43; // rcx bg::detail::Span* v44; // rdx __int64 v45; // rax bg::detail::PageHeap* v46; // rdi bg::detail::Span* v47; // rax size_t v48; // r8 void** v49; // rsi size_t v50; // rdi unsigned __int64 v51; // rdx size_t v52; // r8 void** v53; // rcx __int64 v54; // rdx bg::detail::Span* v55; // rsi bg::detail::PageHeap* v56; // rdi bg::detail::Span* v57; // rax size_t m_start_page; // rcx size_t m_page_count; // r8 void** p_m_chunk_list; // rsi void** v61; // rcx void** v62; // rdx void** v63; // r8 void** v64; // rdi __int64 v65; // rdx bg::detail::Span* v66; // rsi bg::detail::Span* m_prev; // rdx __int64 v68; // [rsp+0h] [rbp-70h] __int64 v69; // [rsp+0h] [rbp-70h] __int64 v70; // [rsp+0h] [rbp-70h] __int64 v71; // [rsp+8h] [rbp-68h] unsigned __int64 v72; // [rsp+8h] [rbp-68h] unsigned __int64 v73; // [rsp+8h] [rbp-68h] __int64 v74; // [rsp+8h] [rbp-68h] unsigned __int64 v75; // [rsp+8h] [rbp-68h] unsigned __int64 v76; // [rsp+8h] [rbp-68h] bg::detail::PageHeap* v77; // [rsp+10h] [rbp-60h] bg::detail::PageHeap* v78; // [rsp+10h] [rbp-60h] bg::detail::PageHeap* v79; // [rsp+10h] [rbp-60h] bg::detail::PageHeap* v80; // [rsp+10h] [rbp-60h] __int64 v81; // [rsp+18h] [rbp-58h] __int64 v82; // [rsp+18h] [rbp-58h] bg::detail::Span* v83; // [rsp+18h] [rbp-58h] __int64 v84; // [rsp+20h] [rbp-50h] __int64 v85; // [rsp+20h] [rbp-50h] bg::detail::Span* v86; // [rsp+20h] [rbp-50h] __int64 v87; // [rsp+28h] [rbp-48h] __int64 v88; // [rsp+28h] [rbp-48h] __int64 v89; // [rsp+28h] [rbp-48h] bg::detail::Span* v90; // [rsp+30h] [rbp-40h] unsigned __int64 v91; // [rsp+30h] [rbp-40h] bg::detail::Span* v92; // [rsp+30h] [rbp-40h] __int64 v93; // [rsp+30h] [rbp-40h] __int64 v94; // [rsp+30h] [rbp-40h] uint8_t dest; // [rsp+38h] [rbp-38h] void** desta; // [rsp+38h] [rbp-38h] uint8_t destb; // [rsp+38h] [rbp-38h] void* destc; // [rsp+38h] [rbp-38h] void* destd; // [rsp+38h] [rbp-38h] v6 = (int64_t)g_shm_ctx.mgr; if(!v6) { return 0LL; } if(!old_ptr) return bg::ShmMalloc(new_bytes); if(!new_bytes) { bg::ShmFree((void*)old_ptr); return 0LL; } if((uintptr_t)old_ptr >> 13 > 0x7FFFFFFFFLL) { LABEL_51: return 0LL; } v9 = ((uintptr_t)old_ptr >> 13) & 0x7FFF; v10 = ((uintptr_t)old_ptr >> 28) & 0x3FF; v11 = v6 + 8 * ((uintptr_t)old_ptr >> 38); v12 = *(uintptr_t*)(v11 + 9136); if(!v12) goto LABEL_51; v13 = *(uintptr_t*)(v12 + 8 * v10); if(!v13) goto LABEL_51; v14 = *(uintptr_t*)(v13 + 8 * v9); if(!v14) goto LABEL_51; v15 = *(unsigned __int8*)(v14 + 1); if((char)v15 == 0xFF) { v16 = *(uintptr_t*)(v14 + 24) << 13; } else { if((unsigned __int8)v15 > 0x56u) { v11 = v6 + 8 * ((uintptr_t)old_ptr >> 38); v10 = ((uintptr_t)old_ptr >> 28) & 0x3FF; } v16 = *(uintptr_t*)(v6 + 8 * v15 + 7744); } v17 = v16 + (v16 >> 2); if(v16 > v16 >> 2) v17 = -1LL; if(new_bytes < v16 >> 1 || (result = (void**)old_ptr, new_bytes > v16)) { if(new_bytes >= v17 || new_bytes <= v16) goto LABEL_19; if(v17 <= 0x400) { destb = *(char*)(v6 + ((v17 + 7) >> 3) + 5568); } else { if(v17 > 0x40000) { v93 = v11; destc = (void*)v10; Span = (uintptr_t)((bg::detail::PageHeap*)(v6 + 9136))->AllocateSpan((v17 + 0x1FFF) >> 13); v10 = (unsigned __int64)destc; v11 = v93; if(Span) { desta = (void**)(*(uintptr_t*)(Span + 16) << 13); if(desta) goto LABEL_27; } goto LABEL_19; } destb = *(char*)(v6 + ((v17 + 15487) >> 7) + 5568); } if(destb > 0x56u) { v71 = v11; v77 = (bg::detail::PageHeap*)v10; v10 = (unsigned __int64)v77; v11 = v71; v85 = destb; v82 = *(uintptr_t*)(v6 + 8LL * destb + 7744); v89 = destb; v36 = (bg::detail::Span*)(v6 + ((unsigned __int64)destb << 6)); v92 = v36; if(v36 != v36->m_next) goto LABEL_47; v78 = (bg::detail::PageHeap*)(v6 + 9136); v69 = v71; v72 = v10; v10 = v72; v11 = v69; v46 = (bg::detail::PageHeap*)(v6 + 9136); } else { v85 = destb; v82 = *(uintptr_t*)(v6 + 8LL * destb + 7744); v89 = destb; v36 = (bg::detail::Span*)(v6 + ((unsigned __int64)destb << 6)); v92 = v36; if(v36 != v36->m_next) { LABEL_47: m_next = v36->m_next; goto LABEL_48; } v78 = (bg::detail::PageHeap*)(v6 + 9136); v46 = (bg::detail::PageHeap*)(v6 + 9136); } v68 = v11; v73 = v10; v47 = (bg::detail::Span*)v46->bg::detail::PageHeap::AllocateSpan(*(uintptr_t*)(v6 + 8 * v85 + 8440)); v10 = v73; v11 = v68; if(!v47) { LABEL_19: if(new_bytes <= 0x400) { dest = *(char*)(v6 + ((new_bytes + 7) >> 3) + 5568); goto LABEL_22; } if(new_bytes <= 0x40000) { dest = *(char*)(v6 + ((new_bytes + 15487) >> 7) + 5568); LABEL_22: if(dest > 0x56u) { v74 = v11; v79 = (bg::detail::PageHeap*)v10; v10 = (unsigned __int64)v79; v11 = v74; v81 = dest; v87 = *(char*)(v6 + 8LL * dest + 7744); v84 = dest; v19 = (bg::detail::Span*)(v6 + ((unsigned __int64)dest << 6)); v90 = v19; if(v19 != v19->m_next) goto LABEL_24; v80 = (bg::detail::PageHeap*)(v6 + 9136); v70 = v74; v75 = v10; v10 = v75; v11 = v70; v56 = (bg::detail::PageHeap*)(v6 + 9136); } else { v81 = dest; v87 = *(char*)(v6 + 8LL * dest + 7744); v84 = dest; v19 = (bg::detail::Span*)(v6 + ((unsigned __int64)dest << 6)); v90 = v19; if(v19 != v19->m_next) { LABEL_24: v20 = v19->m_next; goto LABEL_25; } v80 = (bg::detail::PageHeap*)(v6 + 9136); v56 = (bg::detail::PageHeap*)(v6 + 9136); } v68 = v11; v76 = v10; v57 = v56->AllocateSpan(*(uintptr_t*)(v6 + 8 * v81 + 8440)); if(v57) { v83 = v57; v80->RegisterSpan(v57); v20 = v83; v10 = v76; v11 = v68; m_start_page = v83->m_start_page; m_page_count = v83->m_page_count; p_m_chunk_list = &v83->m_chunk_list; v83->m_size_class = dest; v61 = (void**)(m_start_page << 13); v62 = (void**)((char*)v61 + v87); v63 = &v61[1024 * m_page_count]; if((void**)((char*)v61 + v87) <= v63) { while(1) { v64 = v62; v62 = (void**)((char*)v62 + v87); *p_m_chunk_list = v61; p_m_chunk_list = v61; if(v63 < v62) break; v61 = v64; } } else { v61 = &v83->m_chunk_list; } *v61 = 0LL; v65 = v6 + (v84 << 6); v66 = *(bg::detail::Span**)(v65 + 40); v83->m_prev = v90; v83->m_next = v66; *(uintptr_t*)(*(uintptr_t*)(v65 + 40) + 32LL) = (uintptr_t)v83; *(uintptr_t*)(v65 + 40) = (uintptr_t)v83; ++* (uintptr_t*)(v65 + 56); LABEL_25: m_chunk_list = (void**)v20->m_chunk_list; ++v20->m_used_count; v22 = *m_chunk_list; desta = m_chunk_list; v20->m_chunk_list = *m_chunk_list; if(!v22) { m_prev = v20->m_prev; m_prev->m_next = v20->m_next; v20->m_next->m_prev = m_prev; v20->m_prev = 0LL; v20->m_next = 0LL; --* (uintptr_t*)(v6 + (v84 << 6) + 56); } goto LABEL_27; } return 0LL; } v94 = v11; destd = (void*)v10; v45 = (uintptr_t)((bg::detail::PageHeap*)(v6 + 9136))->AllocateSpan((new_bytes + 0x1FFF) >> 13); v10 = (unsigned __int64)destd; v11 = v94; if(!v45) return 0LL; result = (void**)(*(uintptr_t*)(v45 + 16) << 13); desta = result; if(!result) return result; LABEL_27: v23 = new_bytes; if(v16 <= new_bytes) v23 = v16; v88 = v11; v91 = v10; memcpy(desta, (const void*)old_ptr, v23); v24 = *(uintptr_t*)(v88 + 9136); if(v24 && (v25 = *(uintptr_t*)(v24 + 8 * v91)) != 0 && (v26 = *(bg::detail::Span**)(v25 + 8 * v9)) != 0LL) { m_size_class = v26->m_size_class; if(m_size_class == 0xFF) { ((bg::detail::PageHeap*)(v6 + 9136))->DeallocateSpan(v26); return desta; } m_used_count = v26->m_used_count; if(m_used_count && m_size_class <= 0x56u) { v29 = m_size_class; v30 = v26->m_chunk_list; v31 = m_used_count - 1; v32 = (bg::detail::PageHeap*)(v6 + 9136); *(uintptr_t*)old_ptr = (uintptr_t)v30; v26->m_used_count = v31; v33 = v31 == 0; v26->m_chunk_list = (void*)old_ptr; if(v30) { result = desta; if(!v33) return result; v34 = v6 + (v29 << 6) + 48; if(*(uintptr_t*)(v34 + 8) <= 1uLL) return result; v35 = v26->m_prev; v35->m_next = v26->m_next; v26->m_next->m_prev = v35; v26->m_prev = 0LL; v26->m_next = 0LL; --* (uintptr_t*)(v34 + 8); } else { v42 = (v29 << 6) + v6; if(!v33) { v44 = *(bg::detail::Span**)(v42 + 40); result = desta; v26->m_prev = (bg::detail::Span*)v42; v26->m_next = v44; *(uintptr_t*)(*(uintptr_t*)(v42 + 40) + 32LL) = (uintptr_t)v26; *(uintptr_t*)(v42 + 40) = (uintptr_t)v26; ++* (uintptr_t*)(v42 + 56); return result; } if(!*(uintptr_t*)(v42 + 56)) { v43 = *(bg::detail::Span**)(v42 + 40); v26->m_prev = (bg::detail::Span*)v42; v26->m_next = v43; *(uintptr_t*)(*(uintptr_t*)(v42 + 40) + 32LL) = (uintptr_t)v26; *(uintptr_t*)(v42 + 40) = (uintptr_t)v26; ++* (uintptr_t*)(v42 + 56); return desta; } } v26->m_used_count = 0LL; v26->m_size_class = -1; v26->m_chunk_list = 0LL; v32->DeallocateSpan(v26); return desta; } } else { } return desta; } v86 = v47; v78->RegisterSpan(v47); m_next = v86; v10 = v73; v11 = v68; v48 = v86->m_page_count; v49 = &v86->m_chunk_list; v86->m_size_class = destb; v50 = v86->m_start_page << 13; v51 = v50 + v82; v52 = v50 + (v48 << 13); if(v50 + v82 > v52) { v53 = &v86->m_chunk_list; } else { do { v53 = (void**)(v51 - v82); v51 += v82; *v49 = v53; v49 = v53; } while(v52 >= v51); } *v53 = 0LL; v54 = v6 + (v89 << 6); v55 = *(bg::detail::Span**)(v54 + 40); v86->m_prev = v92; v86->m_next = v55; *(uintptr_t*)(*(uintptr_t*)(v54 + 40) + 32LL) = (uintptr_t)v86; *(uintptr_t*)(v54 + 40) = (uintptr_t)v86; ++* (uintptr_t*)(v54 + 56); LABEL_48: v38 = (void**)m_next->m_chunk_list; ++m_next->m_used_count; v39 = *v38; desta = v38; m_next->m_chunk_list = *v38; if(!v39) { v40 = m_next->m_prev; v40->m_next = m_next->m_next; m_next->m_next->m_prev = v40; m_next->m_prev = 0LL; m_next->m_next = 0LL; --* (uintptr_t*)(v6 + (v89 << 6) + 56); } goto LABEL_27; } return result; } void* ShmCalloc(size_t n, size_t bytes) { __int64 v6; // r12 size_t v7; // rbx void** v8; // r12 uint8_t v10; // r14 __int64 v11; // r11 __int64 v12; // r15 __int64 v13; // r10 bg::detail::Span* v14; // r13 bg::detail::Span* m_next; // rax void** m_chunk_list; // rdx bool v17; // zf __int64 Span; // rax bg::detail::PageHeap* v19; // rdi bg::detail::Span* v20; // rax size_t m_start_page; // rcx size_t m_page_count; // r8 void** p_m_chunk_list; // rsi void** v24; // rcx void** v25; // rdx void** v26; // r8 void** v27; // rdi __int64 v28; // rdx bg::detail::Span* v29; // rsi bg::detail::Span* m_prev; // rcx bg::detail::Span* v31; // [rsp+8h] [rbp-48h] __int64 v32; // [rsp+10h] [rbp-40h] bg::detail::PageHeap* v33; // [rsp+18h] [rbp-38h] v6 = (int64_t)g_shm_ctx.mgr; if(!v6) { return nullptr; } v7 = bytes * n; if(bytes && n != v7 / bytes) return 0LL; if(v7 <= 0x400) { v10 = *(char*)(v6 + ((v7 + 7) >> 3) + 5568); } else { if(v7 > 0x40000) { Span = (uintptr_t)((bg::detail::PageHeap*)(v6 + 9136))->AllocateSpan((v7 + 0x1FFF) >> 13); if(Span) { v8 = (void**)(*(uintptr_t*)(Span + 16) << 13); if(v8) { LABEL_16: memset(v8, 0, v7); return v8; } } return 0LL; } v10 = *(char*)(v6 + ((v7 + 15487) >> 7) + 5568); } if(v10 > 0x56u) { v12 = *(uintptr_t*)(v6 + 8LL * v10 + 7744); v13 = v10; v14 = (bg::detail::Span*)(v6 + ((unsigned __int64)v10 << 6)); if(v14 != v14->m_next) goto LABEL_12; v33 = (bg::detail::PageHeap*)(v6 + 9136); v13 = v10; v11 = v10; v19 = (bg::detail::PageHeap*)(v6 + 9136); } else { v11 = v10; v12 = *(uintptr_t*)(v6 + 8LL * v10 + 7744); v13 = v10; v14 = (bg::detail::Span*)(v6 + ((unsigned __int64)v10 << 6)); if(v14 != v14->m_next) { LABEL_12: m_next = v14->m_next; goto LABEL_13; } v33 = (bg::detail::PageHeap*)(v6 + 9136); v19 = (bg::detail::PageHeap*)(v6 + 9136); } v32 = v13; v20 = (bg::detail::Span*)v19->AllocateSpan(*(uintptr_t*)(v6 + 8 * v11 + 8440)); if(v20) { v31 = v20; v33->RegisterSpan(v20); m_next = v31; v13 = v32; m_start_page = v31->m_start_page; m_page_count = v31->m_page_count; p_m_chunk_list = &v31->m_chunk_list; v31->m_size_class = v10; v24 = (void**)(m_start_page << 13); v25 = (void**)((char*)v24 + v12); v26 = &v24[1024 * m_page_count]; if((void**)((char*)v24 + v12) <= v26) { while(1) { v27 = v25; v25 = (void**)((char*)v25 + v12); *p_m_chunk_list = v24; p_m_chunk_list = v24; if(v26 < v25) break; v24 = v27; } } else { v24 = &v31->m_chunk_list; } *v24 = 0LL; v28 = v6 + (v32 << 6); v29 = *(bg::detail::Span**)(v28 + 40); v31->m_prev = v14; v31->m_next = v29; *(uintptr_t*)(*(uintptr_t*)(v28 + 40) + 32LL) = (uintptr_t)v31; *(uintptr_t*)(v28 + 40) = (uintptr_t)v31; ++* (uintptr_t*)(v28 + 56); LABEL_13: m_chunk_list = (void**)m_next->m_chunk_list; ++m_next->m_used_count; v17 = *m_chunk_list == 0LL; m_next->m_chunk_list = *m_chunk_list; if(v17) { m_prev = m_next->m_prev; m_prev->m_next = m_next->m_next; m_next->m_next->m_prev = m_prev; m_next->m_prev = 0LL; m_next->m_next = 0LL; --* (uintptr_t*)(v6 + (v13 << 6) + 56); } v8 = m_chunk_list; goto LABEL_16; } return 0LL; } }