kern_return_t CollectorHeapIntrospector::enumerate(task_t task, void* context, unsigned typeMask, vm_address_t zoneAddress, memory_reader_t reader, vm_range_recorder_t recorder) { RemoteMemoryReader memoryReader(task, reader); CollectorHeapIntrospector* zone = memoryReader(reinterpret_cast<CollectorHeapIntrospector*>(zoneAddress)); CollectorHeap* heap = memoryReader(zone->m_heap); if (!heap->blocks) return 0; CollectorBlock** blocks = memoryReader(heap->blocks); for (unsigned i = 0; i < heap->usedBlocks; i++) { vm_address_t remoteBlockAddress = reinterpret_cast<vm_address_t>(blocks[i]); vm_range_t ptrRange = { remoteBlockAddress, sizeof(CollectorBlock) }; if (typeMask & (MALLOC_PTR_REGION_RANGE_TYPE | MALLOC_ADMIN_REGION_RANGE_TYPE)) (*recorder)(task, context, MALLOC_PTR_REGION_RANGE_TYPE, &ptrRange, 1); // Recording individual cells causes frequent false-positives. Any garbage cells // which have yet to be collected are labeled as leaks. Recording on a per-block // basis provides less detail but avoids these false-positives. if (memoryReader(blocks[i])->usedCells && (typeMask & MALLOC_PTR_IN_USE_RANGE_TYPE)) (*recorder)(task, context, MALLOC_PTR_IN_USE_RANGE_TYPE, &ptrRange, 1); } return 0; }
bool decodeForSize(const Vector<char>& data, int fmt) { void* rxi = 0; bool result = false; MemReader memoryReader((unsigned char*)data.data(), data.size()); if (m_sizeInitialized) { if (!m_decoder->setSize(m_w, m_h)) return m_decoder->setFailed(); return true; } if (!m_memoryManager) return false; // The rest of the code expects that the first 8 bytes has already been read. // The signature for these files is 8 bytes. memoryReader.SetOffset(8); switch (fmt) { case RxIImageDecoder::FormatRdi: rxi = RdiBirth(m_memoryManager, &memoryReader); break; case RxIImageDecoder::FormatRgi: rxi = RgiBirth(m_memoryManager, &memoryReader); break; case RxIImageDecoder::FormatRpi: rxi = RpiBirth(m_memoryManager, &memoryReader); break; case RxIImageDecoder::FormatRwi: rxi = RwiBirth(m_memoryManager, &memoryReader); break; case RxIImageDecoder::FormatUnknown: ASSERT_NOT_REACHED(); } if (!rxi) return false; switch (fmt) { case RxIImageDecoder::FormatRdi: result = RdiGetWH(rxi, &m_w, &m_h); break; case RxIImageDecoder::FormatRgi: result = RgiGetWH(rxi, &m_w, &m_h); break; case RxIImageDecoder::FormatRpi: result = RpiGetWH(rxi, &m_w, &m_h); break; case RxIImageDecoder::FormatRwi: result = RwiGetWH(rxi, &m_w, &m_h); break; case RxIImageDecoder::FormatUnknown: ASSERT_NOT_REACHED(); break; } if (!result) { delete m_memoryReader; m_memoryReader = 0; return false; } m_sizeInitialized = true; switch (fmt) { case RxIImageDecoder::FormatRdi: RdiDeath(rxi); break; case RxIImageDecoder::FormatRgi: RgiDeath(rxi); break; case RxIImageDecoder::FormatRpi: RpiDeath(rxi); break; case RxIImageDecoder::FormatRwi: RwiDeath(rxi); break; case RxIImageDecoder::FormatUnknown: ASSERT_NOT_REACHED(); break; } // We can fill in the size now that the header is available. if (!m_decoder->setSize(m_w, m_h)) return m_decoder->setFailed(); return true; }