[Plugin] Added plugin that logs some memory infos

This commit is contained in:
Maschell
2018-02-24 13:49:59 +01:00
parent 55dd57d62f
commit db8643d3f5
9 changed files with 836 additions and 0 deletions

View File

@@ -0,0 +1,27 @@
/****************************************************************************
* Copyright (C) 2018 Maschell
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#include "c_retain_vars.h"
memHeapInfo expHeapPointer[MAX_EXP_HEAP_INFOS] __attribute__((section(".data")));
memHeapInfo frmHeapPointer[MAX_FRM_HEAP_INFOS] __attribute__((section(".data")));
memUnitHeapInfo unitHeapPointer[MAX_UNIT_HEAP_INFOS] __attribute__((section(".data")));
baseHeapInfo baseHeaphandles[MAX_BASE_HEAP_INFOS] __attribute__((section(".data")));
blockHeapInfo blockHeapInfos[MAX_BLOCK_HEAP_INFOS] __attribute__((section(".data")));
memHeapInfo userHeapInfos[MAX_USER_HEAP_INFOS] __attribute__((section(".data")));
u8 gButtonComboCooldown __attribute__((section(".data"))) = 0;

View File

@@ -0,0 +1,32 @@
/****************************************************************************
* Copyright (C) 2018 Maschell
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#ifndef C_RETAINS_VARS_H_
#define C_RETAINS_VARS_H_
#include "memory_defs.h"
extern memHeapInfo expHeapPointer[MAX_EXP_HEAP_INFOS];
extern memHeapInfo frmHeapPointer[MAX_FRM_HEAP_INFOS];
extern memUnitHeapInfo unitHeapPointer[MAX_UNIT_HEAP_INFOS];
extern baseHeapInfo baseHeaphandles[MAX_BASE_HEAP_INFOS];
extern blockHeapInfo blockHeapInfos[MAX_BLOCK_HEAP_INFOS];
extern memHeapInfo userHeapInfos[MAX_USER_HEAP_INFOS];
extern u8 gButtonComboCooldown;
#endif // C_RETAINS_VARS_H_

View File

@@ -0,0 +1,34 @@
#include <wups.h>
#include <string.h>
#include <dynamic_libs/os_functions.h>
#include <dynamic_libs/vpad_functions.h>
#include <utils/logger.h>
#include "main.h"
DECL_FUNCTION(void, __PPCExit, void) {
// We reset them at ende, in case at application even uses the functions
// BEFORE with have our init hook.
memset(expHeapPointer,0,sizeof(expHeapPointer));
memset(unitHeapPointer,0,sizeof(unitHeapPointer));
memset(frmHeapPointer,0,sizeof(frmHeapPointer));
memset(baseHeaphandles,0,sizeof(baseHeaphandles));
memset(userHeapInfos,0,sizeof(userHeapInfos));
real___PPCExit();
}
DECL_FUNCTION(int, VPADRead, int chan, VPADData *buffer, u32 buffer_size, s32 *error) {
int result = real_VPADRead(chan, buffer, buffer_size, error);
int btns = VPAD_BUTTON_R | VPAD_BUTTON_L | VPAD_BUTTON_A | VPAD_BUTTON_B | VPAD_BUTTON_X | VPAD_BUTTON_Y;
if(result > 0 && ((buffer[0].btns_h & (btns)) == btns) && gButtonComboCooldown == 0 && OSIsHomeButtonMenuEnabled()) {
print_memory_info();
gButtonComboCooldown = 0x3C;
}
if(gButtonComboCooldown > 0) {
gButtonComboCooldown--;
}
return result;
}
WUPS_MUST_REPLACE(__PPCExit, WUPS_LOADER_LIBRARY_COREINIT, __PPCExit);
WUPS_MUST_REPLACE(VPADRead, WUPS_LOADER_LIBRARY_VPAD, VPADRead);

View File

@@ -0,0 +1,106 @@
#include <wups.h>
#include <string.h>
#include <dynamic_libs/os_functions.h>
#include <dynamic_libs/socket_functions.h>
#include <utils/logger.h>
#include "main.h"
WUPS_PLUGIN_NAME("Memory Info");
WUPS_PLUGIN_DESCRIPTION("Prints information about the current memory usage when pressing L+R+X+Y+A+B.");
WUPS_PLUGIN_VERSION("v1.0");
WUPS_PLUGIN_AUTHOR("Maschell");
WUPS_PLUGIN_LICENSE("GPL");
INITIALIZE(args) {
InitOSFunctionPointers();
InitSocketFunctionPointers();
log_init();
//InitVPadFunctionPointers();
}
void printMemHeapInfo(memHeapInfo * listStart, u32 listLength, const char * listname) {
for(int i = 0; i<listLength; i++) {
if(listStart[i].handle != 0) {
s32 parent = MEMFindParentHeap(listStart[i].handle);
DEBUG_FUNCTION_LINE("%s:", listname);
if(parent == 0) {
log_print(" parent: <NONE> ");
} else {
log_printf(" parent: 0x%08X ", parent);
}
log_printf(" address 0x%08X handle 0x%08X size %07d kb old size %07d kb flags 0x%04X\n",listStart[i].address,listStart[i].handle,listStart[i].size/1024,listStart[i].oldSize/1024,listStart[i].flags);
}
}
}
void print_memory_info() {
DEBUG_FUNCTION_LINE("Print expanded heap infos\n");
printMemHeapInfo(expHeapPointer,MAX_EXP_HEAP_INFOS, "Expanded heap:");
DEBUG_FUNCTION_LINE("Print frmHeap\n");
printMemHeapInfo(frmHeapPointer,MAX_FRM_HEAP_INFOS, "Frame heap:");
DEBUG_FUNCTION_LINE("Print unitHeap\n");
for(int i = 0; i<MAX_UNIT_HEAP_INFOS; i++) {
if(unitHeapPointer[i].handle != 0) {
DEBUG_FUNCTION_LINE("unitHeap: address 0x%08X handle 0x%08X heapSize %07d kb memSize %07d kb align 0x%08X flags 0x%04X\n",unitHeapPointer[i].address,unitHeapPointer[i].handle,unitHeapPointer[i].heapSize/1024,unitHeapPointer[i].memSize/1024,unitHeapPointer[i].align,unitHeapPointer[i].flags);
}
}
DEBUG_FUNCTION_LINE("Print set base heap info\n");
for(int i = 0; i<MAX_BASE_HEAP_INFOS; i++) {
if(baseHeaphandles[i].newHandle != 0) {
DEBUG_FUNCTION_LINE("MEMSetBaseHeapHandle was called: oldHandle 0x%08X newHandle 0x%08X arena %d\n",baseHeaphandles[i].oldHandle,baseHeaphandles[i].newHandle,baseHeaphandles[i].memArena);
}
}
DEBUG_FUNCTION_LINE("Print set block heap info\n");
for(int i = 0; i<MAX_BLOCK_HEAP_INFOS; i++) {
if(blockHeapInfos[i].startAddress != 0) {
DEBUG_FUNCTION_LINE("MEMInitBlockHeap was called: handle 0x%08X tracking 0x%08X\n",blockHeapInfos[i].handle,blockHeapInfos[i].tracking);
}
}
DEBUG_FUNCTION_LINE("Print set user heap info\n");
printMemHeapInfo(userHeapInfos,MAX_USER_HEAP_INFOS, "User heap:");
DEBUG_FUNCTION_LINE("Testing malloc\n");
u32 size = 0x1000;
bool success = false;
do {
void * result = malloc(size);
if(result != NULL) {
//DEBUG_FUNCTION_LINE("Allocated %d kb from default heap\n",size/1024);
free(result);
result = NULL;
success = true;
} else {
//DEBUG_FUNCTION_LINE("Failed to allocate %d kb from default heap\n",size/1024);
success = false;
}
size += 0x1000;
} while(success);
DEBUG_FUNCTION_LINE("I was able to allocate %07d kb from default heap (alignment 4)\n",size/1024);
for(int i = 0; i<2; i++) {
s32 defaultHeap = MEMGetBaseHeapHandle(i);
if(defaultHeap != 0) {
u32 start = 0;
u32 size_bytes = 0;
OSGetMemBound(i+1,&start,&size_bytes);
DEBUG_FUNCTION_LINE("Memory Bound MEM%d: startAddress 0x%08X size 0x%08X\n",i+1,start,size_bytes);
s32 size = MEMGetAllocatableSizeForExpHeapEx(defaultHeap, 4);
s32 totalSize = MEMGetTotalFreeSizeForExpHeap(defaultHeap);
DEBUG_FUNCTION_LINE("BaseHandle address 0x%08X: MEM%d with %07d kb memory free in one block, %07d kb in total.\n",defaultHeap,i+1,size/1024,totalSize/1024);
s32 parent = MEMFindParentHeap(defaultHeap);
if(parent != 0) {
size = MEMGetAllocatableSizeForExpHeapEx(parent, 4);
s32 totalSize = MEMGetTotalFreeSizeForExpHeap(parent);
DEBUG_FUNCTION_LINE("It's parent heap is 0x%08X: With %07d kb memory free in one block, %07d kb in total.\n",parent,size/1024,totalSize/1024);
} else {
DEBUG_FUNCTION_LINE("No parent found =(\n");
}
}
}
}

View File

@@ -0,0 +1,25 @@
/****************************************************************************
* Copyright (C) 2018 Maschell
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#ifndef MAIN_H_
#define MAIN_H_
#include "memory_defs.h"
#include "c_retain_vars.h"
void print_memory_info();
#endif // MAIN_H_

View File

@@ -0,0 +1,64 @@
/****************************************************************************
* Copyright (C) 2018 Maschell
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#ifndef _MEMORY_DEFS_H_
#define _MEMORY_DEFS_H_
#include <dynamic_libs/os_types.h>
#define MAX_USER_HEAP_INFOS 50
#define MAX_FRM_HEAP_INFOS 50
#define MAX_EXP_HEAP_INFOS 50
#define MAX_UNIT_HEAP_INFOS 50
#define MAX_ALLOCATOR_EXP_INFOS 50
#define MAX_BASE_HEAP_INFOS 50
#define MAX_BLOCK_HEAP_INFOS 50
typedef struct memHeapInfo_ {
s32 handle;
void * address;
u32 size;
u32 oldSize;
u16 flags;
} memHeapInfo;
typedef struct memUnitHeapInfo_ {
s32 handle;
void * address;
u32 heapSize;
u32 memSize;
u32 align;
u16 flags;
} memUnitHeapInfo;
typedef struct baseHeapInfo_ {
s32 oldHandle;
s32 newHandle;
s32 memArena;
} baseHeapInfo;
typedef struct blockHeapInfo_ {
s32 handle;
void * tracking;
void * startAddress;
void * endAddress;
void * initTrackMem;
u32 initTrackMemBytes;
u16 flags;
} blockHeapInfo;
#endif

View File

@@ -0,0 +1,244 @@
#include <wups.h>
#include <dynamic_libs/os_types.h>
#include "memory_defs.h"
#include "c_retain_vars.h"
DECL_FUNCTION(s32, MEMCreateFrmHeapEx, void* address, u32 size, u16 flags) {
s32 result = real_MEMCreateFrmHeapEx(address,size,flags);
for(int i = 0; i<MAX_FRM_HEAP_INFOS; i++) {
if(frmHeapPointer[i].handle == 0) {
frmHeapPointer[i].handle = result;
frmHeapPointer[i].address = address;
frmHeapPointer[i].size = size;
frmHeapPointer[i].flags = flags;
break;
}
}
return result;
}
DECL_FUNCTION(s32, MEMCreateUserHeapHandle, void* startAddress, u32 size) {
s32 result = real_MEMCreateUserHeapHandle(startAddress,size);
for(int i = 0; i<MAX_USER_HEAP_INFOS; i++) {
if(userHeapInfos[i].handle == 0) {
userHeapInfos[i].handle = result;
userHeapInfos[i].address = startAddress;
userHeapInfos[i].size = size;
break;
}
}
return result;
}
DECL_FUNCTION(s32, MEMCreateExpHeapEx, void* address, u32 size, u16 flags) {
u32 oldSize = size;
s32 result = 0;
bool allocated = false;
/*
real_MEMCreateExpHeapEx Just accepts ALL sizes... so.. well..
if(size > 0x3B600000 && (u32) address < 0x11000000){
//We are pretty sure this the MEM2 default heap.
//Let's try to increase it's capacity.
//u32 maximumSize = 0x50000000 - (u32) address;
u32 maximumSize = 0x80000000;
//u32 maximumSize = size + 0x500000;
maximumSize -= 0x500000; // remove 5MB, just to leave at least _some_ space.
u32 curSizeTest = maximumSize;
do{
if(curSizeTest < oldSize){
break;
}
result = real_MEMCreateExpHeapEx(address,curSizeTest,flags);
if(result == 0){ // On failure:
maximumSize -= 0x100000; // reduce by 1MB and try again.
}else{
allocated = true;
break;
}
}while(!allocated); // Until the allocation was successful, or we are below default size.
}*/
if(!allocated || result == 0) {
result = real_MEMCreateExpHeapEx(address,size,flags);
}
for(int i = 0; i<MAX_EXP_HEAP_INFOS; i++) {
if(expHeapPointer[i].handle == 0) {
expHeapPointer[i].handle = result;
expHeapPointer[i].address = address;
expHeapPointer[i].size = size;
expHeapPointer[i].oldSize = oldSize;
expHeapPointer[i].flags = flags;
break;
}
}
return result;
}
DECL_FUNCTION(s32, MEMCreateUnitHeapEx, void* address, u32 heapSize, u32 memSize, u32 align, u16 flags) {
s32 result = real_MEMCreateUnitHeapEx(address,heapSize,memSize,align,flags);
for(int i = 0; i<MAX_UNIT_HEAP_INFOS; i++) {
if(unitHeapPointer[i].handle == 0) {
unitHeapPointer[i].handle = result;
unitHeapPointer[i].address = address;
unitHeapPointer[i].heapSize = heapSize;
unitHeapPointer[i].memSize = memSize;
unitHeapPointer[i].align = align;
unitHeapPointer[i].flags = flags;
break;
}
}
return result;
}
DECL_FUNCTION(void *, MEMDestroyExpHeap, s32 heap) {
void * result = real_MEMDestroyExpHeap(heap);
for(int i = 0; i<MAX_EXP_HEAP_INFOS; i++) {
if(expHeapPointer[i].handle == heap) {
expHeapPointer[i].handle = 0;
expHeapPointer[i].address = 0;
expHeapPointer[i].size = 0;
expHeapPointer[i].flags = 0;
break;
}
}
return result;
}
DECL_FUNCTION(void *, MEMDestroyFrmHeap, s32 heap) {
void * result = real_MEMDestroyFrmHeap(heap);
for(int i = 0; i<MAX_FRM_HEAP_INFOS; i++) {
if(frmHeapPointer[i].handle == heap) {
frmHeapPointer[i].handle = 0;
frmHeapPointer[i].address = 0;
frmHeapPointer[i].size = 0;
frmHeapPointer[i].flags = 0;
break;
}
}
return result;
}
DECL_FUNCTION(void *, MEMDestroyUnitHeap, s32 heap) {
void * result = real_MEMDestroyUnitHeap(heap);
for(int i = 0; i<MAX_UNIT_HEAP_INFOS; i++) {
if(unitHeapPointer[i].handle == heap) {
unitHeapPointer[i].handle = 0;
unitHeapPointer[i].address = 0;
unitHeapPointer[i].heapSize = 0;
unitHeapPointer[i].memSize = 0;
unitHeapPointer[i].align = 0;
unitHeapPointer[i].flags = 0;
break;
}
}
return result;
}
DECL_FUNCTION(s32, MEMSetBaseHeapHandle, s32 arena, s32 heap) {
s32 result = real_MEMSetBaseHeapHandle(arena,heap);
for(int i = 0; i<MAX_BASE_HEAP_INFOS; i++) {
if(baseHeaphandles[i].newHandle == 0) {
baseHeaphandles[i].oldHandle = result;
baseHeaphandles[i].newHandle = heap;
baseHeaphandles[i].memArena = arena;
break;
}
}
return result;
}
DECL_FUNCTION(s32, MEMInitBlockHeap,void * tracking, void * startAddress,void * endAddress, void * initTrackMemory, u32 initTrackMemoryBytes, u16 flags) {
s32 result = real_MEMInitBlockHeap(tracking,startAddress,endAddress,initTrackMemory,initTrackMemoryBytes,flags);
for(int i = 0; i<MAX_BLOCK_HEAP_INFOS; i++) {
if(blockHeapInfos[i].startAddress == NULL) {
blockHeapInfos[i].handle = result;
blockHeapInfos[i].tracking = tracking;
blockHeapInfos[i].startAddress = startAddress;
blockHeapInfos[i].endAddress = endAddress;
blockHeapInfos[i].initTrackMem = initTrackMemory;
blockHeapInfos[i].initTrackMemBytes = initTrackMemoryBytes;
blockHeapInfos[i].flags = flags;
break;
}
}
return result;
}
WUPS_MUST_REPLACE(MEMInitBlockHeap, WUPS_LOADER_LIBRARY_COREINIT, MEMInitBlockHeap);
WUPS_MUST_REPLACE(MEMSetBaseHeapHandle, WUPS_LOADER_LIBRARY_COREINIT, MEMSetBaseHeapHandle);
WUPS_MUST_REPLACE(MEMDestroyUnitHeap, WUPS_LOADER_LIBRARY_COREINIT, MEMDestroyUnitHeap);
WUPS_MUST_REPLACE(MEMDestroyFrmHeap, WUPS_LOADER_LIBRARY_COREINIT, MEMDestroyFrmHeap);
WUPS_MUST_REPLACE(MEMDestroyExpHeap, WUPS_LOADER_LIBRARY_COREINIT, MEMDestroyExpHeap);
WUPS_MUST_REPLACE(MEMCreateUnitHeapEx, WUPS_LOADER_LIBRARY_COREINIT, MEMCreateUnitHeapEx);
WUPS_MUST_REPLACE(MEMCreateExpHeapEx, WUPS_LOADER_LIBRARY_COREINIT, MEMCreateExpHeapEx);
WUPS_MUST_REPLACE(MEMCreateUserHeapHandle, WUPS_LOADER_LIBRARY_COREINIT, MEMCreateUserHeapHandle);
WUPS_MUST_REPLACE(MEMCreateFrmHeapEx, WUPS_LOADER_LIBRARY_COREINIT, MEMCreateFrmHeapEx);
/*
Unused stuff that might get useful in the future.
void * allocateFromExpHeap(s32 * usedHandle, u32 size, u32 align){
void * result = NULL;
for(int i = 0;i<MAX_EXP_HEAP_INFOS;i++){
if(expHeapPointer[i].handle != 0){
result = MEMAllocFromExpHeapEx(expHeapPointer[i].handle, size, align);
if(result != NULL){
*usedHandle = expHeapPointer[i].handle;
return result;
}
}
}
return NULL;
}
void * allocateFromFrmHeap(s32 * usedHandle, u32 size, u32 align){
void * result = NULL;
for(int i = 0;i<MAX_FRM_HEAP_INFOS;i++){
if(frmHeapPointer[i].handle != 0){
result = MEMAllocFromFrmHeapEx(frmHeapPointer[i].handle, size, align);
if(result != NULL){
*usedHandle = frmHeapPointer[i].handle;
return result;
}
}
}
return NULL;
}
void freeToExpHeap(s32 usedHandle, void * addr){
MEMFreeToExpHeap(usedHandle, addr);
}
allocatorExpInfo allocatorExpPointer[MAX_ALLOCATOR_EXP_INFOS] __attribute__((section(".data")));
typedef struct allocatorExpInfo_{
void * allocator;
s32 heap;
s32 align;
} allocatorExpInfo;
DECL(void , MEMInitAllocatorForExpHeap, void* allocator, s32 heap, s32 align){
for(int i = 0;i<MAX_ALLOCATOR_EXP_INFOS;i++){
if(allocatorExpPointer[i].allocator == 0){
allocatorExpPointer[i].allocator = (void*)allocator;
allocatorExpPointer[i].heap = heap;
allocatorExpPointer[i].align = align;
break;
}
}
real_MEMInitAllocatorForExpHeap(allocator,heap,align);
return;
}
*/