2020-04-28 14:43:07 +02:00
# include <coreinit/cache.h>
# include "ModuleDataPersistence.h"
# include "DynamicLinkingHelper.h"
2021-12-07 18:23:18 +01:00
bool ModuleDataPersistence : : saveModuleData ( module_information_t * moduleInformation , const std : : shared_ptr < ModuleData > & module ) {
2020-04-28 14:43:07 +02:00
int32_t module_count = moduleInformation - > number_used_modules ;
2020-05-17 19:05:51 +02:00
if ( module_count > = MAXIMUM_MODULES ) {
2020-04-29 12:06:47 +02:00
DEBUG_FUNCTION_LINE ( " Reached maximum module count of %d " , MAXIMUM_MODULES ) ;
2020-04-28 14:43:07 +02:00
return false ;
}
// Copy data to global struct.
2020-05-17 19:05:51 +02:00
module_information_single_t * module_data = & ( moduleInformation - > module_data [ module_count ] ) ;
2020-04-28 14:43:07 +02:00
2021-12-07 18:23:18 +01:00
DEBUG_FUNCTION_LINE ( " Saving relocation data for module at %08X " , module - > getEntrypoint ( ) ) ;
2020-04-28 14:43:07 +02:00
// Relocation
2021-12-07 18:23:18 +01:00
auto relocationData = module - > getRelocationDataList ( ) ;
2021-09-23 18:38:29 +02:00
for ( auto const & reloc : relocationData ) {
2021-09-18 11:55:01 +02:00
if ( ! DynamicLinkingHelper : : addRelocationEntry ( & ( moduleInformation - > linking_data ) , module_data - > linking_entries ,
DYN_LINK_RELOCATION_LIST_LENGTH , reloc ) ) {
2020-04-29 12:06:47 +02:00
DEBUG_FUNCTION_LINE ( " Failed to add relocation entry \n " ) ;
2020-04-28 14:43:07 +02:00
return false ;
}
}
2021-12-07 18:23:18 +01:00
auto exportData = module - > getExportDataList ( ) ;
2021-09-23 18:38:29 +02:00
for ( auto const & curExport : exportData ) {
2020-05-17 21:14:27 +02:00
bool found = false ;
2021-09-23 18:38:29 +02:00
for ( auto & export_entry : module_data - > export_entries ) {
2021-09-17 16:22:54 +02:00
if ( export_entry . address = = 0 ) {
2021-12-07 18:23:18 +01:00
export_entry . type = curExport - > getType ( ) ;
2021-09-17 16:22:54 +02:00
export_entry . name [ 0 ] = ' \0 ' ;
2021-12-07 18:23:18 +01:00
strncat ( export_entry . name , curExport - > getName ( ) . c_str ( ) , sizeof ( export_entry . name ) - 1 ) ;
export_entry . address = ( uint32_t ) curExport - > getAddress ( ) ;
2020-05-17 21:14:27 +02:00
found = true ;
break ;
}
}
if ( ! found ) {
DEBUG_FUNCTION_LINE ( " Failed to found enough exports slots " ) ;
2020-05-29 17:36:10 +02:00
break ;
}
}
2021-12-07 18:23:18 +01:00
auto hookData = module - > getHookDataList ( ) ;
2021-09-23 18:38:29 +02:00
for ( auto const & curHook : hookData ) {
2020-05-29 17:36:10 +02:00
bool found = false ;
2021-09-23 18:38:29 +02:00
for ( auto & hook_entry : module_data - > hook_entries ) {
2021-09-17 16:22:54 +02:00
if ( hook_entry . target = = 0 ) {
2021-12-07 18:23:18 +01:00
hook_entry . type = curHook - > getType ( ) ;
hook_entry . target = ( uint32_t ) curHook - > getTarget ( ) ;
2020-05-29 17:36:10 +02:00
found = true ;
break ;
}
}
if ( ! found ) {
DEBUG_FUNCTION_LINE ( " Failed to found enough hook slots " ) ;
break ;
2020-05-17 21:14:27 +02:00
}
}
2021-12-07 18:23:18 +01:00
strncpy ( module_data - > module_export_name , module - > getExportName ( ) . c_str ( ) , MAXIMUM_EXPORT_MODULE_NAME_LENGTH ) ;
2020-05-17 21:14:27 +02:00
2021-12-07 18:23:18 +01:00
uint32_t entryCount = module - > getFunctionSymbolDataList ( ) . size ( ) ;
2021-12-07 18:01:15 +01:00
if ( entryCount > 0 ) {
auto ptr = & moduleInformation - > function_symbols [ moduleInformation - > number_used_function_symbols ] ;
module_data - > function_symbol_entries = ptr ;
uint32_t sym_offset = 0 ;
2021-12-07 18:23:18 +01:00
for ( auto & curFuncSym : module - > getFunctionSymbolDataList ( ) ) {
2021-12-07 18:01:15 +01:00
if ( moduleInformation - > number_used_function_symbols > = FUNCTION_SYMBOL_LIST_LENGTH ) {
DEBUG_FUNCTION_LINE ( " Function symbol list is full " ) ;
break ;
}
2021-12-07 18:23:18 +01:00
module_data - > function_symbol_entries [ sym_offset ] . address = curFuncSym - > getAddress ( ) ;
module_data - > function_symbol_entries [ sym_offset ] . name = ( char * ) curFuncSym - > getName ( ) ;
module_data - > function_symbol_entries [ sym_offset ] . size = curFuncSym - > getSize ( ) ;
2021-12-07 18:01:15 +01:00
sym_offset + + ;
moduleInformation - > number_used_function_symbols + + ;
}
module_data - > number_used_function_symbols = sym_offset ;
} else {
module_data - > function_symbol_entries = nullptr ;
module_data - > number_used_function_symbols = 0 ;
}
2021-12-07 18:23:18 +01:00
module_data - > bssAddr = module - > getBSSAddr ( ) ;
module_data - > bssSize = module - > getBSSSize ( ) ;
module_data - > sbssAddr = module - > getSBSSAddr ( ) ;
module_data - > sbssSize = module - > getSBSSSize ( ) ;
module_data - > startAddress = module - > getStartAddress ( ) ;
module_data - > endAddress = module - > getEndAddress ( ) ;
module_data - > entrypoint = module - > getEntrypoint ( ) ;
2022-01-23 22:07:38 +01:00
module_data - > skipInitFini = module - > isSkipInitFini ( ) ;
2021-12-07 18:23:18 +01:00
module_data - > initBeforeRelocationDoneHook = module - > isInitBeforeRelocationDoneHook ( ) ;
2020-04-28 14:43:07 +02:00
moduleInformation - > number_used_modules + + ;
2020-05-17 19:05:51 +02:00
DCFlushRange ( ( void * ) moduleInformation , sizeof ( module_information_t ) ) ;
ICInvalidateRange ( ( void * ) moduleInformation , sizeof ( module_information_t ) ) ;
2020-04-28 14:43:07 +02:00
return true ;
}
2021-12-07 18:23:18 +01:00
std : : vector < std : : shared_ptr < ModuleData > > ModuleDataPersistence : : loadModuleData ( module_information_t * moduleInformation ) {
std : : vector < std : : shared_ptr < ModuleData > > result ;
2021-09-17 16:22:54 +02:00
if ( moduleInformation = = nullptr ) {
2020-04-28 14:43:07 +02:00
DEBUG_FUNCTION_LINE ( " moduleInformation == NULL \n " ) ;
return result ;
}
2020-05-17 19:05:51 +02:00
DCFlushRange ( ( void * ) moduleInformation , sizeof ( module_information_t ) ) ;
ICInvalidateRange ( ( void * ) moduleInformation , sizeof ( module_information_t ) ) ;
2020-04-28 14:43:07 +02:00
int32_t module_count = moduleInformation - > number_used_modules ;
2020-05-17 19:05:51 +02:00
if ( module_count > MAXIMUM_MODULES ) {
DEBUG_FUNCTION_LINE ( " moduleInformation->module_count was bigger then allowed. %d > %d. Limiting to %d \n " , module_count , MAXIMUM_MODULES , MAXIMUM_MODULES ) ;
2020-04-28 14:43:07 +02:00
module_count = MAXIMUM_MODULES ;
}
2020-05-17 19:05:51 +02:00
for ( int32_t i = 0 ; i < module_count ; i + + ) {
2020-04-28 14:43:07 +02:00
// Copy data from struct.
2020-05-17 19:05:51 +02:00
module_information_single_t * module_data = & ( moduleInformation - > module_data [ i ] ) ;
2021-12-07 18:23:18 +01:00
auto moduleData = std : : make_shared < ModuleData > ( ) ;
moduleData - > setBSSLocation ( module_data - > bssAddr , module_data - > bssSize ) ;
moduleData - > setSBSSLocation ( module_data - > sbssAddr , module_data - > sbssSize ) ;
moduleData - > setEntrypoint ( module_data - > entrypoint ) ;
moduleData - > setStartAddress ( module_data - > startAddress ) ;
moduleData - > setEndAddress ( module_data - > endAddress ) ;
moduleData - > setExportName ( module_data - > module_export_name ) ;
2022-01-23 22:07:38 +01:00
moduleData - > setSkipInitFini ( module_data - > skipInitFini ) ;
2021-12-07 18:23:18 +01:00
moduleData - > setInitBeforeRelocationDoneHook ( module_data - > initBeforeRelocationDoneHook ) ;
2020-05-29 17:30:10 +02:00
2021-09-23 18:38:29 +02:00
for ( auto & export_entrie : module_data - > export_entries ) {
2021-09-17 16:22:54 +02:00
export_data_t * export_entry = & export_entrie ;
2020-06-07 14:17:02 +02:00
if ( export_entry - > address = = 0 ) {
2020-05-17 21:14:27 +02:00
continue ;
}
2021-12-07 18:23:18 +01:00
auto exportData = std : : make_shared < ExportData > ( static_cast < wums_entry_type_t > ( export_entry - > type ) , export_entry - > name , reinterpret_cast < const void * > ( export_entry - > address ) ) ;
moduleData - > addExportData ( exportData ) ;
2020-05-17 21:14:27 +02:00
}
2021-09-23 18:38:29 +02:00
for ( auto & hook_entry : module_data - > hook_entries ) {
2021-09-17 16:22:54 +02:00
if ( hook_entry . target = = 0 ) {
2020-05-29 17:36:10 +02:00
continue ;
}
2021-12-07 18:23:18 +01:00
auto hookData = std : : make_shared < HookData > ( static_cast < wums_hook_type_t > ( hook_entry . type ) , reinterpret_cast < const void * > ( hook_entry . target ) ) ;
moduleData - > addHookData ( hookData ) ;
2020-05-29 17:36:10 +02:00
}
2021-09-23 18:38:29 +02:00
for ( auto & linking_entry : module_data - > linking_entries ) {
2021-09-17 16:22:54 +02:00
if ( linking_entry . destination = = nullptr ) {
2020-04-28 14:43:07 +02:00
break ;
}
2021-09-17 16:22:54 +02:00
dyn_linking_import_t * importEntry = linking_entry . importEntry ;
if ( importEntry = = nullptr ) {
2020-04-28 14:43:07 +02:00
DEBUG_FUNCTION_LINE ( " importEntry was NULL, skipping relocation entry \n " ) ;
continue ;
}
2021-09-17 16:22:54 +02:00
dyn_linking_function_t * functionEntry = linking_entry . functionEntry ;
2020-04-28 14:43:07 +02:00
2021-09-17 16:22:54 +02:00
if ( functionEntry = = nullptr ) {
2020-04-28 14:43:07 +02:00
DEBUG_FUNCTION_LINE ( " functionEntry was NULL, skipping relocation entry \n " ) ;
continue ;
}
2021-12-07 18:23:18 +01:00
auto rplInfo = std : : make_shared < ImportRPLInformation > ( importEntry - > importName , importEntry - > isData ) ;
auto reloc = std : : make_shared < RelocationData > ( linking_entry . type , linking_entry . offset , linking_entry . addend , linking_entry . destination , functionEntry - > functionName , rplInfo ) ;
2020-05-17 13:11:52 +02:00
2021-12-07 18:23:18 +01:00
moduleData - > addRelocationData ( reloc ) ;
2020-04-28 14:43:07 +02:00
}
2021-12-07 18:01:15 +01:00
if ( module_data - > function_symbol_entries ! = nullptr & & module_data - > number_used_function_symbols > 0 ) {
for ( uint32_t j = 0 ; j < module_data - > number_used_function_symbols ; j + + ) {
auto symbol = & module_data - > function_symbol_entries [ j ] ;
2021-12-07 18:23:18 +01:00
auto functionSymbolData = std : : make_shared < FunctionSymbolData > ( symbol - > name , symbol - > address , symbol - > size ) ;
moduleData - > addFunctionSymbolData ( functionSymbolData ) ;
2021-12-07 18:01:15 +01:00
}
}
2020-04-28 14:43:07 +02:00
result . push_back ( moduleData ) ;
}
return result ;
}