#include "Xalloc.hpp" namespace Xalloc { class SmartSMAPClass { private: AllocatorV1 *allocator = nullptr; public: SmartSMAPClass(AllocatorV1 *allocator) { this->allocator = allocator; this->allocator->Xstac(); } ~SmartSMAPClass() { this->allocator->Xclac(); } }; #define SmartSMAP SmartSMAPClass XALLOC_CONCAT(SmartSMAP##_, __COUNTER__)(this) AllocatorV1::AllocatorV1(void *Address, bool UserMode, bool SMAPEnabled) { SmartSMAP; void *Position = Address; UserMapping = UserMode; SMAPUsed = SMAPEnabled; for (Xuint64_t i = 0; i < 0x20; i++) { void *Page = Xalloc_REQUEST_PAGE(); if (UserMapping) Xalloc_MAP_MEMORY(Position, Page, Xalloc_MAP_MEMORY_READ_WRITE | Xalloc_MAP_MEMORY_USER); else Xalloc_MAP_MEMORY(Position, Page, Xalloc_MAP_MEMORY_READ_WRITE); Xalloc_trace("Preallocate Heap Memory (%#llx-%#llx [%#llx])...", Position, (Xuint64_t)Position + Xalloc_PAGE_SIZE, Page); Position = (void *)((Xuint64_t)Position + Xalloc_PAGE_SIZE); } Xuint64_t HeapLength = 16 * Xalloc_PAGE_SIZE; this->HeapStart = Address; this->HeapEnd = (void *)((Xuint64_t)this->HeapStart + HeapLength); HeapSegment *StartSegment = (HeapSegment *)Address; StartSegment->Length = HeapLength - sizeof(HeapSegment); StartSegment->Next = nullptr; StartSegment->Last = nullptr; StartSegment->IsFree = true; this->LastSegment = StartSegment; } AllocatorV1::~AllocatorV1() { SmartSMAP; Xalloc_trace("Destructor not implemented yet."); } void AllocatorV1::ExpandHeap(Xuint64_t Length) { if (Length % Xalloc_PAGE_SIZE) { Length -= Length % Xalloc_PAGE_SIZE; Length += Xalloc_PAGE_SIZE; } Xuint64_t PageCount = Length / Xalloc_PAGE_SIZE; HeapSegment *NewSegment = (HeapSegment *)this->HeapEnd; for (Xuint64_t i = 0; i < PageCount; i++) { void *Page = Xalloc_REQUEST_PAGE(); if (UserMapping) Xalloc_MAP_MEMORY(this->HeapEnd, Page, Xalloc_MAP_MEMORY_READ_WRITE | Xalloc_MAP_MEMORY_USER); else Xalloc_MAP_MEMORY(this->HeapEnd, Page, Xalloc_MAP_MEMORY_READ_WRITE); // Xalloc_trace("Expanding Heap Memory (%#llx-%#llx [%#llx])...", this->HeapEnd, (Xuint64_t)this->HeapEnd + Xalloc_PAGE_SIZE, Page); this->HeapEnd = (void *)((Xuint64_t)this->HeapEnd + Xalloc_PAGE_SIZE); } NewSegment->IsFree = true; NewSegment->Last = this->LastSegment; this->LastSegment->Next = NewSegment; this->LastSegment = NewSegment; NewSegment->Next = nullptr; NewSegment->Length = Length - sizeof(HeapSegment); NewSegment->CombineBackward(this->LastSegment); } void *AllocatorV1::Malloc(Xuint64_t Size) { SmartSMAP; if (this->HeapStart == nullptr) { Xalloc_err("Memory allocation not initialized yet!"); return 0; } if (Size < 0x10) { // Xalloc_warn("Allocation size is too small, using 0x10 instead!"); Size = 0x10; } // #ifdef DEBUG // if (Size < 1024) // debug("Allocating %dB", Size); // else if (TO_KB(Size) < 1024) // debug("Allocating %dKB", TO_KB(Size)); // else if (TO_MB(Size) < 1024) // debug("Allocating %dMB", TO_MB(Size)); // else if (TO_GB(Size) < 1024) // debug("Allocating %dGB", TO_GB(Size)); // #endif if (Size % 0x10 > 0) // it is not a multiple of 0x10 { Size -= (Size % 0x10); Size += 0x10; } if (Size == 0) { return nullptr; } HeapSegment *CurrentSegment = (HeapSegment *)this->HeapStart; while (true) { if (CurrentSegment->IsFree) { if (CurrentSegment->Length > Size) { CurrentSegment->Split(Size, this->LastSegment); CurrentSegment->IsFree = false; return (void *)((Xuint64_t)CurrentSegment + sizeof(HeapSegment)); } if (CurrentSegment->Length == Size) { CurrentSegment->IsFree = false; return (void *)((Xuint64_t)CurrentSegment + sizeof(HeapSegment)); } } if (CurrentSegment->Next == nullptr) break; CurrentSegment = CurrentSegment->Next; } ExpandHeap(Size); return this->Malloc(Size); } void AllocatorV1::Free(void *Address) { SmartSMAP; if (this->HeapStart == nullptr) { Xalloc_err("Memory allocation not initialized yet!"); return; } HeapSegment *Segment = (HeapSegment *)Address - 1; Segment->IsFree = true; Segment->CombineForward(this->LastSegment); Segment->CombineBackward(this->LastSegment); } void *AllocatorV1::Calloc(Xuint64_t NumberOfBlocks, Xuint64_t Size) { SmartSMAP; if (this->HeapStart == nullptr) { Xalloc_err("Memory allocation not initialized yet!"); return 0; } if (Size < 0x10) { // Xalloc_warn("Allocation size is too small, using 0x10 instead!"); Size = 0x10; } void *Block = this->Malloc(NumberOfBlocks * Size); if (Block) Xmemset(Block, 0, NumberOfBlocks * Size); return Block; } void *AllocatorV1::Realloc(void *Address, Xuint64_t Size) { SmartSMAP; if (this->HeapStart == nullptr) { Xalloc_err("Memory allocation not initialized yet!"); return 0; } if (!Address && Size == 0) { this->Free(Address); return nullptr; } else if (!Address) { return this->Calloc(Size, sizeof(char)); } if (Size < 0x10) { // Xalloc_warn("Allocation size is too small, using 0x10 instead!"); Size = 0x10; } void *newAddress = this->Calloc(Size, sizeof(char)); Xmemcpy(newAddress, Address, Size); return newAddress; } }