mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-07-04 05:51:19 +12:00
165 lines
4.9 KiB
C++
165 lines
4.9 KiB
C++
#include "Cafe/OS/RPL/rpl.h"
|
|
#include "Cafe/OS/RPL/rpl_symbol_storage.h"
|
|
|
|
struct rplSymbolLib_t
|
|
{
|
|
char* libName;
|
|
rplSymbolLib_t* next;
|
|
};
|
|
|
|
struct
|
|
{
|
|
rplSymbolLib_t* libs;
|
|
std::mutex m_symbolStorageMutex;
|
|
std::unordered_map<uint32, RPLStoredSymbol*> map_symbolByAddress;
|
|
// allocator for strings
|
|
char* strAllocatorBlock;
|
|
sint32 strAllocatorOffset;
|
|
std::vector<void*> list_strAllocatedBlocks;
|
|
}rplSymbolStorage = { 0 };
|
|
|
|
#define STR_ALLOC_BLOCK_SIZE (128*1024) // allocate 128KB blocks at once
|
|
|
|
char* rplSymbolStorage_allocDupString(const char* str)
|
|
{
|
|
sint32 len = (sint32)strlen(str);
|
|
if (rplSymbolStorage.strAllocatorBlock == nullptr || (rplSymbolStorage.strAllocatorOffset + len + 1) >= STR_ALLOC_BLOCK_SIZE)
|
|
{
|
|
// allocate new block
|
|
rplSymbolStorage.strAllocatorBlock = (char*)malloc(STR_ALLOC_BLOCK_SIZE);
|
|
rplSymbolStorage.strAllocatorOffset = 0;
|
|
rplSymbolStorage.list_strAllocatedBlocks.emplace_back(rplSymbolStorage.strAllocatorBlock);
|
|
}
|
|
cemu_assert_debug((rplSymbolStorage.strAllocatorOffset + len + 1) <= STR_ALLOC_BLOCK_SIZE);
|
|
char* allocatedStr = rplSymbolStorage.strAllocatorBlock + rplSymbolStorage.strAllocatorOffset;
|
|
rplSymbolStorage.strAllocatorOffset += len + 1;
|
|
strcpy(allocatedStr, str);
|
|
return allocatedStr;
|
|
}
|
|
|
|
char* rplSymbolStorage_storeLibname(const char* libName)
|
|
{
|
|
if (rplSymbolStorage.libs == NULL)
|
|
{
|
|
rplSymbolLib_t* libEntry = new rplSymbolLib_t();
|
|
libEntry->libName = rplSymbolStorage_allocDupString(libName);
|
|
libEntry->next = NULL;
|
|
rplSymbolStorage.libs = libEntry;
|
|
return libEntry->libName;
|
|
}
|
|
rplSymbolLib_t* libItr = rplSymbolStorage.libs;
|
|
while (libItr)
|
|
{
|
|
if (boost::iequals(libItr->libName, libName))
|
|
return libItr->libName;
|
|
// next
|
|
libItr = libItr->next;
|
|
}
|
|
// create new entry
|
|
rplSymbolLib_t* libEntry = new rplSymbolLib_t();
|
|
libEntry->libName = rplSymbolStorage_allocDupString(libName);
|
|
libEntry->next = rplSymbolStorage.libs;
|
|
rplSymbolStorage.libs = libEntry;
|
|
return libEntry->libName;
|
|
}
|
|
|
|
RPLStoredSymbol* rplSymbolStorage_store(const char* libName, const char* symbolName, MPTR address)
|
|
{
|
|
std::unique_lock<std::mutex> lck(rplSymbolStorage.m_symbolStorageMutex);
|
|
char* libNameStorage = rplSymbolStorage_storeLibname(libName);
|
|
char* symbolNameStorage = rplSymbolStorage_allocDupString(symbolName);
|
|
RPLStoredSymbol* storedSymbol = new RPLStoredSymbol();
|
|
storedSymbol->address = address;
|
|
storedSymbol->libName = libNameStorage;
|
|
storedSymbol->symbolName = symbolNameStorage;
|
|
storedSymbol->flags = 0;
|
|
rplSymbolStorage.map_symbolByAddress[address] = storedSymbol;
|
|
return storedSymbol;
|
|
}
|
|
|
|
RPLStoredSymbol* rplSymbolStorage_getByAddress(MPTR address)
|
|
{
|
|
std::unique_lock<std::mutex> lck(rplSymbolStorage.m_symbolStorageMutex);
|
|
return rplSymbolStorage.map_symbolByAddress[address];
|
|
}
|
|
|
|
RPLStoredSymbol* rplSymbolStorage_getByClosestAddress(MPTR address)
|
|
{
|
|
// highly inefficient but doesn't matter for now
|
|
std::unique_lock<std::mutex> lck(rplSymbolStorage.m_symbolStorageMutex);
|
|
for(uint32 i=0; i<4096; i++)
|
|
{
|
|
RPLStoredSymbol* symbol = rplSymbolStorage.map_symbolByAddress[address];
|
|
if(symbol)
|
|
return symbol;
|
|
address -= 4;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
void rplSymbolStorage_remove(RPLStoredSymbol* storedSymbol)
|
|
{
|
|
std::unique_lock<std::mutex> lck(rplSymbolStorage.m_symbolStorageMutex);
|
|
if (rplSymbolStorage.map_symbolByAddress[storedSymbol->address] == storedSymbol)
|
|
rplSymbolStorage.map_symbolByAddress[storedSymbol->address] = nullptr;
|
|
delete storedSymbol;
|
|
}
|
|
|
|
void rplSymbolStorage_removeRange(MPTR address, sint32 length)
|
|
{
|
|
while (length > 0)
|
|
{
|
|
RPLStoredSymbol* symbol = rplSymbolStorage_getByAddress(address);
|
|
if (symbol)
|
|
rplSymbolStorage_remove(symbol);
|
|
address += 4;
|
|
length -= 4;
|
|
}
|
|
}
|
|
|
|
void rplSymbolStorage_createJumpProxySymbol(MPTR jumpAddress, MPTR destAddress)
|
|
{
|
|
RPLStoredSymbol* destSymbol = rplSymbolStorage_getByAddress(destAddress);
|
|
if (destSymbol)
|
|
rplSymbolStorage_store((char*)destSymbol->libName, (char*)destSymbol->symbolName, jumpAddress);
|
|
}
|
|
|
|
std::unordered_map<uint32, RPLStoredSymbol*>& rplSymbolStorage_lockSymbolMap()
|
|
{
|
|
rplSymbolStorage.m_symbolStorageMutex.lock();
|
|
return rplSymbolStorage.map_symbolByAddress;
|
|
}
|
|
|
|
void rplSymbolStorage_unlockSymbolMap()
|
|
{
|
|
rplSymbolStorage.m_symbolStorageMutex.unlock();
|
|
}
|
|
|
|
void rplSymbolStorage_init()
|
|
{
|
|
cemu_assert_debug(rplSymbolStorage.map_symbolByAddress.empty());
|
|
cemu_assert_debug(rplSymbolStorage.strAllocatorBlock == nullptr);
|
|
}
|
|
|
|
void rplSymbolStorage_unloadAll()
|
|
{
|
|
// free symbols
|
|
for (auto& it : rplSymbolStorage.map_symbolByAddress)
|
|
delete it.second;
|
|
rplSymbolStorage.map_symbolByAddress.clear();
|
|
// free libs
|
|
rplSymbolLib_t* lib = rplSymbolStorage.libs;
|
|
while (lib)
|
|
{
|
|
rplSymbolLib_t* next = lib->next;
|
|
delete lib;
|
|
lib = next;
|
|
}
|
|
rplSymbolStorage.libs = nullptr;
|
|
// free strings
|
|
for (auto it : rplSymbolStorage.list_strAllocatedBlocks)
|
|
free(it);
|
|
rplSymbolStorage.list_strAllocatedBlocks.clear();
|
|
rplSymbolStorage.strAllocatorBlock = nullptr;
|
|
rplSymbolStorage.strAllocatorOffset = 0;
|
|
}
|