mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2025-01-11 15:24:46 +00:00
kern: implement memory debug
This commit is contained in:
parent
6df26d674c
commit
be8473cf65
10 changed files with 155 additions and 2 deletions
|
@ -271,6 +271,12 @@ namespace ams::kern::arch::arm64 {
|
||||||
|
|
||||||
size_t GetNormalMemorySize() const { return this->page_table.GetNormalMemorySize(); }
|
size_t GetNormalMemorySize() const { return this->page_table.GetNormalMemorySize(); }
|
||||||
|
|
||||||
|
size_t GetCodeSize() const { return this->page_table.GetCodeSize(); }
|
||||||
|
size_t GetCodeDataSize() const { return this->page_table.GetCodeDataSize(); }
|
||||||
|
|
||||||
|
size_t GetAliasCodeSize() const { return this->page_table.GetAliasCodeSize(); }
|
||||||
|
size_t GetAliasCodeDataSize() const { return this->page_table.GetAliasCodeDataSize(); }
|
||||||
|
|
||||||
u32 GetAllocateOption() const { return this->page_table.GetAllocateOption(); }
|
u32 GetAllocateOption() const { return this->page_table.GetAllocateOption(); }
|
||||||
|
|
||||||
KPhysicalAddress GetHeapPhysicalAddress(KVirtualAddress address) const {
|
KPhysicalAddress GetHeapPhysicalAddress(KVirtualAddress address) const {
|
||||||
|
|
|
@ -63,6 +63,14 @@ namespace ams::kern::arch::arm64 {
|
||||||
|
|
||||||
constexpr u64 GetIdentityMapTtbr0(s32 core_id) const { return this->ttbr0_identity[core_id]; }
|
constexpr u64 GetIdentityMapTtbr0(s32 core_id) const { return this->ttbr0_identity[core_id]; }
|
||||||
|
|
||||||
|
void DumpMemoryBlocks() const {
|
||||||
|
return this->page_table.DumpMemoryBlocks();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DumpPageTable() const {
|
||||||
|
return this->page_table.DumpPageTable();
|
||||||
|
}
|
||||||
|
|
||||||
size_t CountPageTables() const {
|
size_t CountPageTables() const {
|
||||||
return this->page_table.CountPageTables();
|
return this->page_table.CountPageTables();
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,10 @@ namespace ams::kern::KDumpObject {
|
||||||
void DumpHandle();
|
void DumpHandle();
|
||||||
void DumpHandle(u64 process_id);
|
void DumpHandle(u64 process_id);
|
||||||
|
|
||||||
|
void DumpKernelMemory();
|
||||||
|
void DumpMemory();
|
||||||
|
void DumpMemory(u64 process_id);
|
||||||
|
|
||||||
void DumpProcess();
|
void DumpProcess();
|
||||||
void DumpProcess(u64 process_id);
|
void DumpProcess(u64 process_id);
|
||||||
|
|
||||||
|
|
|
@ -301,6 +301,8 @@ namespace ams::kern {
|
||||||
Result SetupForIpcClient(PageLinkedList *page_list, size_t *out_blocks_needed, KProcessAddress address, size_t size, KMemoryPermission test_perm, KMemoryState dst_state);
|
Result SetupForIpcClient(PageLinkedList *page_list, size_t *out_blocks_needed, KProcessAddress address, size_t size, KMemoryPermission test_perm, KMemoryState dst_state);
|
||||||
Result SetupForIpcServer(KProcessAddress *out_addr, size_t size, KProcessAddress src_addr, KMemoryPermission test_perm, KMemoryState dst_state, KPageTableBase &src_page_table, bool send);
|
Result SetupForIpcServer(KProcessAddress *out_addr, size_t size, KProcessAddress src_addr, KMemoryPermission test_perm, KMemoryState dst_state, KPageTableBase &src_page_table, bool send);
|
||||||
void CleanupForIpcClientOnServerSetupFailure(PageLinkedList *page_list, KProcessAddress address, size_t size, KMemoryPermission prot_perm);
|
void CleanupForIpcClientOnServerSetupFailure(PageLinkedList *page_list, KProcessAddress address, size_t size, KMemoryPermission prot_perm);
|
||||||
|
|
||||||
|
size_t GetSize(KMemoryState state) const;
|
||||||
public:
|
public:
|
||||||
bool GetPhysicalAddress(KPhysicalAddress *out, KProcessAddress virt_addr) const {
|
bool GetPhysicalAddress(KPhysicalAddress *out, KProcessAddress virt_addr) const {
|
||||||
return this->GetImpl().GetPhysicalAddress(out, virt_addr);
|
return this->GetImpl().GetPhysicalAddress(out, virt_addr);
|
||||||
|
@ -423,6 +425,11 @@ namespace ams::kern {
|
||||||
return (this->current_heap_end - this->heap_region_start) + this->mapped_physical_memory_size;
|
return (this->current_heap_end - this->heap_region_start) + this->mapped_physical_memory_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t GetCodeSize() const;
|
||||||
|
size_t GetCodeDataSize() const;
|
||||||
|
size_t GetAliasCodeSize() const;
|
||||||
|
size_t GetAliasCodeDataSize() const;
|
||||||
|
|
||||||
u32 GetAllocateOption() const { return this->allocate_option; }
|
u32 GetAllocateOption() const { return this->allocate_option; }
|
||||||
public:
|
public:
|
||||||
static ALWAYS_INLINE KVirtualAddress GetLinearMappedVirtualAddress(KPhysicalAddress addr) {
|
static ALWAYS_INLINE KVirtualAddress GetLinearMappedVirtualAddress(KPhysicalAddress addr) {
|
||||||
|
|
|
@ -170,6 +170,8 @@ namespace ams::kern {
|
||||||
|
|
||||||
constexpr KProcessAddress GetEntryPoint() const { return this->code_address; }
|
constexpr KProcessAddress GetEntryPoint() const { return this->code_address; }
|
||||||
|
|
||||||
|
constexpr size_t GetMainStackSize() const { return this->main_thread_stack_size; }
|
||||||
|
|
||||||
constexpr KMemoryManager::Pool GetMemoryPool() const { return this->memory_pool; }
|
constexpr KMemoryManager::Pool GetMemoryPool() const { return this->memory_pool; }
|
||||||
|
|
||||||
constexpr u64 GetRandomEntropy(size_t i) const { return this->entropy[i]; }
|
constexpr u64 GetRandomEntropy(size_t i) const { return this->entropy[i]; }
|
||||||
|
|
|
@ -125,6 +125,47 @@ namespace ams::kern::KDumpObject {
|
||||||
MESOSPHERE_RELEASE_LOG("\n\n");
|
MESOSPHERE_RELEASE_LOG("\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DumpMemory(KProcess *process) {
|
||||||
|
const auto process_id = process->GetId();
|
||||||
|
MESOSPHERE_RELEASE_LOG("Process ID=%3lu (%s)\n", process_id, process->GetName());
|
||||||
|
|
||||||
|
/* Dump the memory blocks. */
|
||||||
|
process->GetPageTable().DumpMemoryBlocks();
|
||||||
|
|
||||||
|
/* Collect information about memory totals. */
|
||||||
|
const size_t code = process->GetPageTable().GetCodeSize();
|
||||||
|
const size_t code_data = process->GetPageTable().GetCodeDataSize();
|
||||||
|
const size_t alias_code = process->GetPageTable().GetAliasCodeSize();
|
||||||
|
const size_t alias_code_data = process->GetPageTable().GetAliasCodeDataSize();
|
||||||
|
const size_t normal = process->GetPageTable().GetNormalMemorySize();
|
||||||
|
const size_t main_stack = process->GetMainStackSize();
|
||||||
|
|
||||||
|
size_t shared = 0;
|
||||||
|
{
|
||||||
|
KSharedMemory::ListAccessor accessor;
|
||||||
|
const auto end = accessor.end();
|
||||||
|
for (auto it = accessor.begin(); it != end; ++it) {
|
||||||
|
KSharedMemory *shared_mem = static_cast<KSharedMemory *>(std::addressof(*it));
|
||||||
|
if (shared_mem->GetOwnerProcessId() == process_id) {
|
||||||
|
shared += shared_mem->GetSize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dump the totals. */
|
||||||
|
MESOSPHERE_RELEASE_LOG("---\n");
|
||||||
|
MESOSPHERE_RELEASE_LOG("Code %8zu KB\n", code / 1_KB);
|
||||||
|
MESOSPHERE_RELEASE_LOG("CodeData %8zu KB\n", code_data / 1_KB);
|
||||||
|
MESOSPHERE_RELEASE_LOG("AliasCode %8zu KB\n", alias_code / 1_KB);
|
||||||
|
MESOSPHERE_RELEASE_LOG("AliasCodeData %8zu KB\n", alias_code_data / 1_KB);
|
||||||
|
MESOSPHERE_RELEASE_LOG("Heap %8zu KB\n", normal / 1_KB);
|
||||||
|
MESOSPHERE_RELEASE_LOG("SharedMemory %8zu KB\n", shared / 1_KB);
|
||||||
|
MESOSPHERE_RELEASE_LOG("InitialStack %8zu KB\n", main_stack / 1_KB);
|
||||||
|
MESOSPHERE_RELEASE_LOG("---\n");
|
||||||
|
MESOSPHERE_RELEASE_LOG("TOTAL %8zu KB\n", (code + code_data + alias_code + alias_code_data + normal + main_stack + shared) / 1_KB);
|
||||||
|
MESOSPHERE_RELEASE_LOG("\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
void DumpProcess(KProcess *process) {
|
void DumpProcess(KProcess *process) {
|
||||||
MESOSPHERE_RELEASE_LOG("Process ID=%3lu index=%3zu State=%d (%s)\n", process->GetId(), process->GetSlabIndex(), process->GetState(), process->GetName());
|
MESOSPHERE_RELEASE_LOG("Process ID=%3lu index=%3zu State=%d (%s)\n", process->GetId(), process->GetSlabIndex(), process->GetState(), process->GetName());
|
||||||
}
|
}
|
||||||
|
@ -501,6 +542,47 @@ namespace ams::kern::KDumpObject {
|
||||||
MESOSPHERE_RELEASE_LOG("\n");
|
MESOSPHERE_RELEASE_LOG("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DumpKernelMemory() {
|
||||||
|
MESOSPHERE_RELEASE_LOG("Dump Kernel Memory Info\n");
|
||||||
|
|
||||||
|
{
|
||||||
|
Kernel::GetKernelPageTable().DumpMemoryBlocks();
|
||||||
|
}
|
||||||
|
|
||||||
|
MESOSPHERE_RELEASE_LOG("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void DumpMemory() {
|
||||||
|
MESOSPHERE_RELEASE_LOG("Dump Memory Info\n");
|
||||||
|
|
||||||
|
{
|
||||||
|
/* Lock the list. */
|
||||||
|
KProcess::ListAccessor accessor;
|
||||||
|
const auto end = accessor.end();
|
||||||
|
|
||||||
|
/* Dump each process. */
|
||||||
|
for (auto it = accessor.begin(); it != end; ++it) {
|
||||||
|
DumpMemory(static_cast<KProcess *>(std::addressof(*it)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MESOSPHERE_RELEASE_LOG("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void DumpMemory(u64 process_id) {
|
||||||
|
MESOSPHERE_RELEASE_LOG("Dump Memory Info\n");
|
||||||
|
|
||||||
|
{
|
||||||
|
/* Find and dump the target process. */
|
||||||
|
if (KProcess *process = KProcess::GetProcessFromId(process_id); process != nullptr) {
|
||||||
|
ON_SCOPE_EXIT { process->Close(); };
|
||||||
|
DumpMemory(process);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MESOSPHERE_RELEASE_LOG("\n");
|
||||||
|
}
|
||||||
|
|
||||||
void DumpProcess() {
|
void DumpProcess() {
|
||||||
MESOSPHERE_RELEASE_LOG("Dump Process\n");
|
MESOSPHERE_RELEASE_LOG("Dump Process\n");
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,7 @@ namespace ams::kern {
|
||||||
const char d = (info.attribute & KMemoryAttribute_DeviceShared) ? 'D' : '-';
|
const char d = (info.attribute & KMemoryAttribute_DeviceShared) ? 'D' : '-';
|
||||||
const char u = (info.attribute & KMemoryAttribute_Uncached) ? 'U' : '-';
|
const char u = (info.attribute & KMemoryAttribute_Uncached) ? 'U' : '-';
|
||||||
|
|
||||||
MESOSPHERE_LOG("%p - %p (%9zu KB) %s %s %c%c%c%c [%d, %d]\n", start, end, kb, perm, state, l, i, d, u, info.ipc_lock_count, info.device_use_count);
|
MESOSPHERE_LOG("0x%10lx - 0x%10lx (%9zu KB) %s %s %c%c%c%c [%d, %d]\n", start, end, kb, perm, state, l, i, d, u, info.ipc_lock_count, info.device_use_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1018,6 +1018,39 @@ namespace ams::kern {
|
||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t KPageTableBase::GetSize(KMemoryState state) const {
|
||||||
|
/* Lock the table. */
|
||||||
|
KScopedLightLock lk(this->general_lock);
|
||||||
|
|
||||||
|
/* Iterate, counting blocks with the desired state. */
|
||||||
|
size_t total_size = 0;
|
||||||
|
for (KMemoryBlockManager::const_iterator it = this->memory_block_manager.FindIterator(this->address_space_start); it != this->memory_block_manager.end(); ++it) {
|
||||||
|
/* Get the memory info. */
|
||||||
|
const KMemoryInfo info = it->GetMemoryInfo();
|
||||||
|
if (info.GetState() == state) {
|
||||||
|
total_size += info.GetSize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return total_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t KPageTableBase::GetCodeSize() const {
|
||||||
|
return this->GetSize(KMemoryState_Code);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t KPageTableBase::GetCodeDataSize() const {
|
||||||
|
return this->GetSize(KMemoryState_CodeData);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t KPageTableBase::GetAliasCodeSize() const {
|
||||||
|
return this->GetSize(KMemoryState_AliasCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t KPageTableBase::GetAliasCodeDataSize() const {
|
||||||
|
return this->GetSize(KMemoryState_AliasCodeData);
|
||||||
|
}
|
||||||
|
|
||||||
Result KPageTableBase::AllocateAndMapPagesImpl(PageLinkedList *page_list, KProcessAddress address, size_t num_pages, KMemoryPermission perm) {
|
Result KPageTableBase::AllocateAndMapPagesImpl(PageLinkedList *page_list, KProcessAddress address, size_t num_pages, KMemoryPermission perm) {
|
||||||
MESOSPHERE_ASSERT(this->IsLockedByCurrentThread());
|
MESOSPHERE_ASSERT(this->IsLockedByCurrentThread());
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,15 @@ namespace ams::kern::svc {
|
||||||
KDumpObject::DumpHandle(arg0);
|
KDumpObject::DumpHandle(arg0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case ams::svc::KernelDebugType_Memory:
|
||||||
|
if (arg0 == static_cast<u64>(-2)) {
|
||||||
|
KDumpObject::DumpKernelMemory();
|
||||||
|
} else if (arg0 == static_cast<u64>(-1)) {
|
||||||
|
KDumpObject::DumpMemory();
|
||||||
|
} else {
|
||||||
|
KDumpObject::DumpMemory(arg0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case ams::svc::KernelDebugType_Process:
|
case ams::svc::KernelDebugType_Process:
|
||||||
if (arg0 == static_cast<u64>(-1)) {
|
if (arg0 == static_cast<u64>(-1)) {
|
||||||
KDumpObject::DumpProcess();
|
KDumpObject::DumpProcess();
|
||||||
|
|
|
@ -474,7 +474,9 @@ namespace ams::svc {
|
||||||
KernelDebugType_ThreadCallStack = 1,
|
KernelDebugType_ThreadCallStack = 1,
|
||||||
KernelDebugType_KernelObject = 2,
|
KernelDebugType_KernelObject = 2,
|
||||||
KernelDebugType_Handle = 3,
|
KernelDebugType_Handle = 3,
|
||||||
|
KernelDebugType_Memory = 4,
|
||||||
|
KernelDebugType_PageTable = 5,
|
||||||
|
KernelDebugType_CpuUtilization = 6,
|
||||||
KernelDebugType_Process = 7,
|
KernelDebugType_Process = 7,
|
||||||
KernelDebugType_SuspendProcess = 8,
|
KernelDebugType_SuspendProcess = 8,
|
||||||
KernelDebugType_ResumeProcess = 9,
|
KernelDebugType_ResumeProcess = 9,
|
||||||
|
|
Loading…
Reference in a new issue