Пример #1
0
static std::string
GX2PointerAsString(const void *pointer)
{
   fmt::MemoryWriter format;
   format.write("{:08X}", memory_untranslate(pointer));
   return format.str();
}
Пример #2
0
static BOOL
spinTryLock(OSSpinLock *spinlock)
{
   uint32_t owner, expected;
   auto thread = OSGetCurrentThread();

   if (!thread) {
      return FALSE;
   }

   owner = memory_untranslate(thread);

   if (spinlock->owner.load(std::memory_order_relaxed) == owner) {
      ++spinlock->recursion;
      return TRUE;
   }

   expected = 0;

   if (spinlock->owner.compare_exchange_weak(expected, owner, std::memory_order_release, std::memory_order_relaxed)) {
      return TRUE;
   } else {
      return FALSE;
   }
}
static int
MEM_DynLoad_DefaultAlloc(int size, int alignment, be_val<uint32_t> *outPtr)
{
   auto heap = MEMGetBaseHeapHandle(BaseHeapType::MEM2);
   auto memory = MEMAllocFromExpHeapEx(reinterpret_cast<ExpandedHeap*>(heap), size, alignment);
   *outPtr = memory_untranslate(memory);
   return 0;
}
Пример #4
0
z_stream *
getZStream(WZStream *in)
{
   auto zstream = &gStreamMap[memory_untranslate(in)];
   zstream->opaque = in;
   zstream->zalloc = &zlibAllocWrapper;
   zstream->zfree = &zlibFreeWrapper;
   return zstream;
}
void
MEMiDumpExpHeap(ExpandedHeap *heap)
{
   gLog->debug("MEMiDumpExpHeap({:8x})", memory_untranslate(heap));
   gLog->debug("Status Address Size Group");

   for (auto block = heap->freeBlockList; block; block = block->next) {
      gLog->debug("FREE {:8x} {:8x} {:d}", block->addr, block->size, block->group);
   }

   for (auto block = heap->usedBlockList; block; block = block->next) {
      gLog->debug("USED {:8x} {:8x} {:d}", block->addr, block->size, block->group);
   }
}
Пример #6
0
static CommonHeap *
findHeapContainingBlock(MemoryList *list, void *block)
{
   CommonHeap *heap = nullptr;
   uint32_t addr = memory_untranslate(block);

   while ((heap = reinterpret_cast<CommonHeap*>(MEMGetNextListObject(list, heap)))) {
      if (addr >= heap->dataStart && addr < heap->dataEnd) {
         auto child = findHeapContainingBlock(&heap->list, block);
         return child ? child : heap;
      }
   }

   return nullptr;
}
void
MEMFreeToExpHeap(ExpandedHeap *heap, uint8_t *address)
{
   ScopedSpinLock lock(&heap->lock);
   auto base = memory_untranslate(address);

   if (!base) {
      return;
   }

   if (base < heap->bottom || base >= heap->top) {
      gLog->warn("FreeToExpHeap outside heap region; {:08x} not within {:08x}-{:08x}", base, heap->bottom, heap->top);
      return;
   }

   // Get the block header
   base = base - static_cast<uint32_t>(sizeof(ExpandedHeapBlock));

   // Remove used blocked
   auto usedBlock = make_virtual_ptr<ExpandedHeapBlock>(base);
   auto addr = usedBlock->addr;
   auto size = usedBlock->size;
   eraseBlock(heap->usedBlockList, usedBlock);

   // Create free block
   auto freeBlock = make_virtual_ptr<ExpandedHeapBlock>(addr);
   freeBlock->addr = addr;
   freeBlock->size = size;
   insertBlock(heap->freeBlockList, freeBlock);

   // Merge with next free if contiguous
   auto nextFree = freeBlock->next;

   if (nextFree && nextFree->addr == freeBlock->addr + freeBlock->size) {
      freeBlock->size += nextFree->size;
      eraseBlock(heap->freeBlockList, nextFree);
   }

   // Merge with previous free if contiguous
   auto prevFree = freeBlock->prev;

   if (prevFree && freeBlock->addr == prevFree->addr + prevFree->size) {
      prevFree->size += freeBlock->size;
      eraseBlock(heap->freeBlockList, freeBlock);
   }
}
Пример #8
0
static MemoryList *
findListContainingBlock(void *block)
{
   be_val<uint32_t> start, size, end;
   uint32_t addr = memory_untranslate(block);
   OSGetForegroundBucket(&start, &size);
   end = start + size;

   if (addr >= start && addr <= end) {
      return sForegroundMemlist;
   } else {
      OSGetMemBound(OSMemoryType::MEM1, &start, &size);
      end = start + size;

      if (addr >= start && addr <= end) {
         return sMEM1Memlist;
      } else {
         return sMEM2Memlist;
      }
   }
}
Пример #9
0
static BOOL
spinReleaseLock(OSSpinLock *spinlock)
{
   uint32_t owner;
   auto thread = OSGetCurrentThread();

   if (!thread) {
      return FALSE;
   }

   owner = memory_untranslate(OSGetCurrentThread());

   if (spinlock->recursion > 0u) {
      --spinlock->recursion;
      return TRUE;
   } else if (spinlock->owner.load(std::memory_order_relaxed) == owner) {
      spinlock->owner = 0u;
      return TRUE;
   }

   return FALSE;
}
ExpandedHeap *
MEMCreateExpHeapEx(ExpandedHeap *heap, uint32_t size, uint16_t flags)
{
   // Allocate memory
   auto base = memory_untranslate(heap);

   // Setup state
   heap->size = size;
   heap->bottom = base;
   heap->top = base + size;
   heap->mode = HeapMode::FirstFree;
   heap->group = 0;
   heap->usedBlockList = nullptr;
   heap->freeBlockList = make_virtual_ptr<ExpandedHeapBlock>(base + sizeof(ExpandedHeap));
   heap->freeBlockList->addr = heap->freeBlockList.getAddress();
   heap->freeBlockList->size = heap->size - sizeof(ExpandedHeap);
   heap->freeBlockList->next = nullptr;
   heap->freeBlockList->prev = nullptr;

   // Setup common header
   MEMiInitHeapHead(heap, HeapType::ExpandedHeap, heap->freeBlockList->addr, heap->freeBlockList->addr + heap->freeBlockList->size);
   return heap;
}
Пример #11
0
void
eraseZStream(WZStream *in)
{
   gStreamMap.erase(memory_untranslate(in));
}
uint32_t
MEMResizeForMBlockExpHeap(ExpandedHeap *heap, uint8_t *mblock, uint32_t size)
{
   ScopedSpinLock lock(&heap->lock);

   // Get the block header
   auto address = memory_untranslate(mblock);
   auto base = address - static_cast<uint32_t>(sizeof(ExpandedHeapBlock));

   auto block = make_virtual_ptr<ExpandedHeapBlock>(base);
   auto nextAddr = block->addr + block->size;

   auto freeBlock = findBlock(heap->freeBlockList, nextAddr);
   auto freeBlockSize = 0u;

   auto dataSize = (block->addr + block->size) - address;
   auto difSize = static_cast<int32_t>(size) - static_cast<int32_t>(dataSize);
   auto newSize = block->size + difSize;

   if (difSize == 0) {
      // No difference, return current size
      return size;
   } else if (difSize > 0) {
      if (!freeBlock) {
         // No free block to expand into, return fail
         return 0;
      } else if (freeBlock->size < static_cast<uint32_t>(difSize)) {
         // Free block is too small, return fail
         return 0;
      } else {
         if (freeBlock->size - difSize < minimumBlockSize) {
            // The free block will be smaller than minimum size, so just absorb it completely
            freeBlockSize = 0;
            newSize = freeBlock->size;
         } else {
            // Free block is large enough, we just reduce its size
            freeBlockSize = freeBlock->size - difSize;
         }
      }
   } else if (difSize < 0) {
      if (freeBlock) {
         // Increase size of free block
         freeBlockSize = freeBlock->size - difSize;
      } else if (difSize < minimumBlockSize) {
         // We can't fit a new free block in the gap, so return current size
         return block->size;
      } else {
         // Create a new free block in the gap
         freeBlockSize = -difSize;
      }
   }

   // Update free block
   if (freeBlockSize) {
      auto old = freeBlock;
      freeBlock = make_virtual_ptr<ExpandedHeapBlock>(block->addr + newSize);
      freeBlock->addr = block->addr + newSize;
      freeBlock->size = freeBlockSize;
      replaceBlock(heap->freeBlockList, old, freeBlock);
   } else {
      // We have totally consumed the free block
      eraseBlock(heap->freeBlockList, freeBlock);
   }

   // Resize block
   block->size = newSize;
   return size;
}