2020-04-29 18:02:36 +02:00
# include <coreinit/cache.h>
# include "PluginContainer.h"
# include "PluginInformationFactory.h"
# include "PluginMetaInformationFactory.h"
# include "PluginContainerPersistence.h"
2020-05-17 20:45:10 +02:00
# include "PluginDataPersistence.h"
2020-04-29 18:02:36 +02:00
# include "DynamicLinkingHelper.h"
2020-12-26 14:17:50 +01:00
# include "../common/plugin_defines.h"
2020-04-29 18:02:36 +02:00
# include "PluginInformation.h"
# include "RelocationData.h"
2020-05-03 12:30:15 +02:00
bool PluginContainerPersistence : : savePlugin ( plugin_information_t * pluginInformation , PluginContainer & plugin ) {
2020-04-29 18:02:36 +02:00
int32_t plugin_count = pluginInformation - > number_used_plugins ;
auto pluginName = plugin . getMetaInformation ( ) . getName ( ) ;
2020-05-03 12:30:15 +02:00
if ( plugin_count > = MAXIMUM_PLUGINS - 1 ) {
2020-12-28 14:40:53 +01:00
DEBUG_FUNCTION_LINE ( " Maximum of %d plugins reached. %s won't be loaded! " , MAXIMUM_PLUGINS , pluginName . c_str ( ) ) ;
2020-04-29 18:02:36 +02:00
return false ;
}
// Copy data to global struct.
2020-05-03 12:30:15 +02:00
plugin_information_single_t * plugin_data = & ( pluginInformation - > plugin_data [ plugin_count ] ) ;
2020-04-29 18:02:36 +02:00
// Make sure everything is reset.
2020-05-03 12:30:15 +02:00
memset ( ( void * ) plugin_data , 0 , sizeof ( plugin_information_single_t ) ) ;
2020-04-29 18:02:36 +02:00
2020-12-26 14:17:50 +01:00
const auto & pluginMetaInfo = plugin . getMetaInformation ( ) ;
2020-05-03 12:30:15 +02:00
auto plugin_meta_data = & plugin_data - > meta ;
2020-04-29 18:02:36 +02:00
2020-05-03 12:30:15 +02:00
if ( pluginMetaInfo . getName ( ) . size ( ) > = MAXIMUM_PLUGIN_META_FIELD_LENGTH ) {
2020-04-29 18:02:36 +02:00
DEBUG_FUNCTION_LINE ( " Warning: name will be truncated. " ) ;
}
2020-05-03 12:30:15 +02:00
strncpy ( plugin_meta_data - > name , pluginMetaInfo . getName ( ) . c_str ( ) , MAXIMUM_PLUGIN_META_FIELD_LENGTH - 1 ) ;
if ( pluginMetaInfo . getAuthor ( ) . size ( ) > = MAXIMUM_PLUGIN_META_FIELD_LENGTH ) {
2020-04-29 18:02:36 +02:00
DEBUG_FUNCTION_LINE ( " Warning: author will be truncated. " ) ;
}
2020-05-03 12:30:15 +02:00
strncpy ( plugin_meta_data - > author , pluginMetaInfo . getAuthor ( ) . c_str ( ) , MAXIMUM_PLUGIN_META_FIELD_LENGTH - 1 ) ;
2020-04-29 18:02:36 +02:00
2020-05-03 12:30:15 +02:00
if ( pluginMetaInfo . getVersion ( ) . size ( ) > = MAXIMUM_PLUGIN_META_FIELD_LENGTH ) {
2020-04-29 18:02:36 +02:00
DEBUG_FUNCTION_LINE ( " Warning: version will be truncated. " ) ;
}
2020-05-03 12:30:15 +02:00
strncpy ( plugin_meta_data - > version , pluginMetaInfo . getVersion ( ) . c_str ( ) , MAXIMUM_PLUGIN_META_FIELD_LENGTH - 1 ) ;
2020-04-29 18:02:36 +02:00
2020-05-03 12:30:15 +02:00
if ( pluginMetaInfo . getLicense ( ) . size ( ) > = MAXIMUM_PLUGIN_META_FIELD_LENGTH ) {
2020-04-29 18:02:36 +02:00
DEBUG_FUNCTION_LINE ( " Warning: license will be truncated. " ) ;
}
2020-05-03 12:30:15 +02:00
strncpy ( plugin_meta_data - > license , pluginMetaInfo . getLicense ( ) . c_str ( ) , MAXIMUM_PLUGIN_META_FIELD_LENGTH - 1 ) ;
2020-04-29 18:02:36 +02:00
2020-05-03 12:30:15 +02:00
if ( pluginMetaInfo . getBuildTimestamp ( ) . size ( ) > = MAXIMUM_PLUGIN_META_FIELD_LENGTH ) {
2020-04-29 18:02:36 +02:00
DEBUG_FUNCTION_LINE ( " Warning: build timestampt will be truncated. " ) ;
}
2020-05-03 12:30:15 +02:00
strncpy ( plugin_meta_data - > buildTimestamp , pluginMetaInfo . getBuildTimestamp ( ) . c_str ( ) , MAXIMUM_PLUGIN_META_FIELD_LENGTH - 1 ) ;
2020-04-29 18:02:36 +02:00
2020-05-03 12:30:15 +02:00
if ( pluginMetaInfo . getDescription ( ) . size ( ) > = MAXIMUM_PLUGIN_DESCRIPTION_LENGTH ) {
2020-04-29 18:02:36 +02:00
DEBUG_FUNCTION_LINE ( " Warning: description will be truncated. " ) ;
DEBUG_FUNCTION_LINE ( " %s " , pluginMetaInfo . getDescription ( ) . c_str ( ) ) ;
}
2020-05-03 12:30:15 +02:00
strncpy ( plugin_meta_data - > descripion , pluginMetaInfo . getDescription ( ) . c_str ( ) , MAXIMUM_PLUGIN_DESCRIPTION_LENGTH - 1 ) ;
2020-04-29 18:02:36 +02:00
plugin_meta_data - > size = pluginMetaInfo . getSize ( ) ;
auto pluginInfo = plugin . getPluginInformation ( ) ;
// Relocation
std : : vector < RelocationData > relocationData = pluginInfo . getRelocationDataList ( ) ;
2020-05-03 12:30:15 +02:00
for ( auto & reloc : relocationData ) {
if ( ! DynamicLinkingHelper : : addReloationEntry ( & ( pluginInformation - > linking_data ) , plugin_data - > info . linking_entries , PLUGIN_DYN_LINK_RELOCATION_LIST_LENGTH , reloc ) ) {
2020-05-03 10:21:05 +02:00
DEBUG_FUNCTION_LINE ( " Failed to add a relocation entry " ) ;
2020-04-29 18:02:36 +02:00
return false ;
}
}
std : : vector < FunctionData > function_data_list = pluginInfo . getFunctionDataList ( ) ;
std : : vector < HookData > hook_data_list = pluginInfo . getHookDataList ( ) ;
2020-05-03 12:30:15 +02:00
if ( function_data_list . size ( ) > MAXIMUM_FUNCTION_PER_PLUGIN ) {
DEBUG_FUNCTION_LINE ( " Plugin %s would replace to many function (%d, maximum is %d). It won't be loaded. " , pluginName . c_str ( ) , function_data_list . size ( ) , MAXIMUM_FUNCTION_PER_PLUGIN ) ;
2020-04-29 18:02:36 +02:00
return false ;
}
2020-05-03 12:30:15 +02:00
if ( hook_data_list . size ( ) > MAXIMUM_HOOKS_PER_PLUGIN ) {
2020-04-29 18:02:36 +02:00
DEBUG_FUNCTION_LINE ( " Plugin %s would set too many hooks (%d, maximum is %d). It won't be loaded. " , pluginName . c_str ( ) , hook_data_list . size ( ) , MAXIMUM_HOOKS_PER_PLUGIN ) ;
return false ;
}
2020-05-03 12:30:15 +02:00
if ( pluginName . length ( ) > MAXIMUM_PLUGIN_NAME_LENGTH - 1 ) {
2020-04-29 18:02:36 +02:00
DEBUG_FUNCTION_LINE ( " Name for plugin %s was too long to be stored. " , pluginName . c_str ( ) ) ;
return false ;
}
/* Store function replacement information */
uint32_t i = 0 ;
2020-05-03 12:30:15 +02:00
for ( auto & curFunction : pluginInfo . getFunctionDataList ( ) ) {
2020-06-13 16:57:53 +02:00
function_replacement_data_t * function_data = & plugin_data - > info . functions [ i ] ;
2020-05-03 12:30:15 +02:00
if ( strlen ( curFunction . getName ( ) . c_str ( ) ) > MAXIMUM_FUNCTION_NAME_LENGTH - 1 ) {
2020-04-29 18:02:36 +02:00
DEBUG_FUNCTION_LINE ( " Could not add function \" %s \" for plugin \" %s \" function name is too long. " , curFunction . getName ( ) . c_str ( ) , pluginName . c_str ( ) ) ;
continue ;
}
2021-02-19 19:41:04 +01:00
DEBUG_FUNCTION_LINE_VERBOSE ( " Adding function \" %s \" for plugin \" %s \" " , curFunction . getName ( ) . c_str ( ) , pluginName . c_str ( ) ) ;
2020-04-29 18:02:36 +02:00
2020-05-03 12:30:15 +02:00
strncpy ( function_data - > function_name , curFunction . getName ( ) . c_str ( ) , MAXIMUM_FUNCTION_NAME_LENGTH - 1 ) ;
2020-04-29 18:02:36 +02:00
2020-06-13 16:57:53 +02:00
function_data - > VERSION = FUNCTION_REPLACEMENT_DATA_STRUCT_VERSION ;
function_data - > library = ( function_replacement_library_type_t ) curFunction . getLibrary ( ) ;
2020-04-29 18:02:36 +02:00
function_data - > replaceAddr = ( uint32_t ) curFunction . getReplaceAddress ( ) ;
function_data - > replaceCall = ( uint32_t ) curFunction . getReplaceCall ( ) ;
function_data - > physicalAddr = ( uint32_t ) curFunction . getPhysicalAddress ( ) ;
function_data - > virtualAddr = ( uint32_t ) curFunction . getVirtualAddress ( ) ;
2020-06-19 17:04:39 +02:00
function_data - > targetProcess = curFunction . getTargetProcess ( ) ;
2020-04-29 18:02:36 +02:00
plugin_data - > info . number_used_functions + + ;
i + + ;
}
i = 0 ;
2020-05-03 12:30:15 +02:00
for ( auto & curHook : pluginInfo . getHookDataList ( ) ) {
replacement_data_hook_t * hook_data = & plugin_data - > info . hooks [ i ] ;
2020-04-29 18:02:36 +02:00
2021-02-19 19:41:04 +01:00
DEBUG_FUNCTION_LINE_VERBOSE ( " Set hook for plugin \" %s \" of type %08X to target %08X " , plugin_data - > meta . name , curHook . getType ( ) , ( void * ) curHook . getFunctionPointer ( ) ) ;
2020-04-29 18:02:36 +02:00
2020-05-03 12:30:15 +02:00
hook_data - > func_pointer = ( void * ) curHook . getFunctionPointer ( ) ;
hook_data - > type = curHook . getType ( ) ;
2020-04-29 18:02:36 +02:00
plugin_data - > info . number_used_hooks + + ;
i + + ;
}
/* Saving SectionInfos */
2020-05-03 12:30:15 +02:00
for ( auto & curSection : pluginInfo . getSectionInfoList ( ) ) {
2020-04-29 18:02:36 +02:00
bool foundFreeSlot = false ;
uint32_t slot = 0 ;
2020-05-03 12:30:15 +02:00
for ( uint32_t i = 0 ; i < MAXIMUM_PLUGIN_SECTION_LENGTH ; i + + ) {
plugin_section_info_t * sectionInfo = & ( plugin_data - > info . sectionInfos [ i ] ) ;
if ( sectionInfo - > addr = = 0 & & sectionInfo - > size = = 0 ) {
2020-04-29 18:02:36 +02:00
foundFreeSlot = true ;
slot = i ;
break ;
}
}
2020-05-03 12:30:15 +02:00
if ( foundFreeSlot ) {
plugin_section_info_t * sectionInfo = & ( plugin_data - > info . sectionInfos [ slot ] ) ;
if ( strlen ( curSection . first . c_str ( ) ) > MAXIMUM_PLUGIN_SECTION_NAME_LENGTH - 1 ) {
DEBUG_FUNCTION_LINE ( " Could not add section info \" %s \" for plugin \" %s \" section name is too long. " , curSection . first . c_str ( ) , pluginName . c_str ( ) ) ;
2020-04-29 18:02:36 +02:00
break ;
}
2020-05-03 12:30:15 +02:00
strncpy ( sectionInfo - > name , curSection . first . c_str ( ) , MAXIMUM_PLUGIN_SECTION_NAME_LENGTH - 1 ) ;
2020-04-29 18:02:36 +02:00
sectionInfo - > addr = curSection . second . getAddress ( ) ;
sectionInfo - > size = curSection . second . getSize ( ) ;
} else {
DEBUG_FUNCTION_LINE ( " Failed to store SectionInfos " ) ;
return false ;
}
}
plugin_data - > info . trampolinId = pluginInfo . getTrampolinId ( ) ;
2020-05-03 12:23:50 +02:00
plugin_data - > info . allocatedTextMemoryAddress = pluginInfo . allocatedTextMemoryAddress ;
plugin_data - > info . allocatedDataMemoryAddress = pluginInfo . allocatedDataMemoryAddress ;
2020-04-29 18:02:36 +02:00
/* Copy plugin data */
auto pluginData = plugin . getPluginData ( ) ;
2020-05-03 12:30:15 +02:00
auto plugin_data_data = & plugin_data - > data ;
2020-04-29 18:02:36 +02:00
2020-05-17 20:45:10 +02:00
PluginDataPersistence : : save ( plugin_data_data , pluginData ) ;
2020-04-29 18:02:36 +02:00
pluginInformation - > number_used_plugins + + ;
2020-05-03 12:30:15 +02:00
DCFlushRange ( ( void * ) pluginInformation , sizeof ( plugin_information_t ) ) ;
ICInvalidateRange ( ( void * ) pluginInformation , sizeof ( plugin_information_t ) ) ;
2020-04-29 18:02:36 +02:00
return true ;
}
2020-05-03 12:30:15 +02:00
std : : vector < PluginContainer > PluginContainerPersistence : : loadPlugins ( plugin_information_t * pluginInformation ) {
2020-04-29 18:02:36 +02:00
std : : vector < PluginContainer > result ;
2020-12-26 14:17:50 +01:00
if ( pluginInformation = = nullptr ) {
2020-04-29 18:02:36 +02:00
DEBUG_FUNCTION_LINE ( " pluginInformation == NULL " ) ;
return result ;
}
2020-05-03 12:30:15 +02:00
DCFlushRange ( ( void * ) pluginInformation , sizeof ( plugin_information_t ) ) ;
ICInvalidateRange ( ( void * ) pluginInformation , sizeof ( plugin_information_t ) ) ;
2020-04-29 18:02:36 +02:00
int32_t plugin_count = pluginInformation - > number_used_plugins ;
2020-05-03 12:30:15 +02:00
if ( plugin_count > MAXIMUM_PLUGINS ) {
DEBUG_FUNCTION_LINE ( " pluginInformation->plugin_count was bigger then allowed. %d > %d. Limiting to %d " , plugin_count , MAXIMUM_PLUGINS , MAXIMUM_PLUGINS ) ;
2020-04-29 18:02:36 +02:00
plugin_count = MAXIMUM_PLUGINS ;
}
2020-05-03 12:30:15 +02:00
for ( int32_t i = 0 ; i < plugin_count ; i + + ) {
2020-04-29 18:02:36 +02:00
// Copy data from struct.
2020-05-03 12:30:15 +02:00
plugin_information_single_t * plugin_data = & ( pluginInformation - > plugin_data [ i ] ) ;
2020-04-29 18:02:36 +02:00
PluginMetaInformation metaInformation ;
2020-05-03 12:30:15 +02:00
plugin_meta_info_t * meta = & ( plugin_data - > meta ) ;
2020-04-29 18:02:36 +02:00
metaInformation . setAuthor ( meta - > author ) ;
metaInformation . setVersion ( meta - > version ) ;
metaInformation . setBuildTimestamp ( meta - > buildTimestamp ) ;
metaInformation . setLicense ( meta - > license ) ;
metaInformation . setDescription ( meta - > descripion ) ;
metaInformation . setSize ( meta - > size ) ;
metaInformation . setName ( meta - > name ) ;
2020-05-03 12:30:15 +02:00
plugin_data_t * data = & ( plugin_data - > data ) ;
2020-04-29 18:02:36 +02:00
2020-05-17 20:45:10 +02:00
PluginData pluginData = PluginDataPersistence : : load ( data ) ;
2020-04-29 18:02:36 +02:00
2020-12-26 14:17:50 +01:00
PluginInformation curPluginInformation ;
2020-04-29 18:02:36 +02:00
2020-12-26 14:17:50 +01:00
curPluginInformation . setTrampolinId ( plugin_data - > info . trampolinId ) ;
curPluginInformation . allocatedTextMemoryAddress = plugin_data - > info . allocatedTextMemoryAddress ;
curPluginInformation . allocatedDataMemoryAddress = plugin_data - > info . allocatedDataMemoryAddress ;
2020-04-29 18:02:36 +02:00
2020-12-26 14:17:50 +01:00
for ( auto & curItem : plugin_data - > info . sectionInfos ) {
plugin_section_info_t * sectionInfo = & curItem ;
2020-05-03 12:30:15 +02:00
if ( sectionInfo - > addr = = 0 & & sectionInfo - > size = = 0 ) {
2020-04-29 18:02:36 +02:00
continue ;
}
2021-02-19 19:41:04 +01:00
DEBUG_FUNCTION_LINE_VERBOSE ( " Add SectionInfo %s " , sectionInfo - > name ) ;
2020-12-26 14:17:50 +01:00
std : : string name ( sectionInfo - > name ) ;
curPluginInformation . addSectionInfo ( SectionInfo ( name , sectionInfo - > addr , sectionInfo - > size ) ) ;
2020-04-29 18:02:36 +02:00
}
/* load hook data */
uint32_t hookCount = plugin_data - > info . number_used_hooks ;
2020-05-03 12:30:15 +02:00
if ( hookCount > MAXIMUM_HOOKS_PER_PLUGIN ) {
DEBUG_FUNCTION_LINE ( " number_used_hooks was bigger then allowed. %d > %d. Limiting to %d " , hookCount , MAXIMUM_HOOKS_PER_PLUGIN , MAXIMUM_HOOKS_PER_PLUGIN ) ;
2020-04-29 18:02:36 +02:00
hookCount = MAXIMUM_HOOKS_PER_PLUGIN ;
}
2020-05-03 12:30:15 +02:00
for ( uint32_t j = 0 ; j < hookCount ; j + + ) {
replacement_data_hook_t * hook_entry = & ( plugin_data - > info . hooks [ j ] ) ;
2020-04-29 18:02:36 +02:00
HookData curHook ( hook_entry - > func_pointer , hook_entry - > type ) ;
2020-12-26 14:17:50 +01:00
curPluginInformation . addHookData ( curHook ) ;
2020-04-29 18:02:36 +02:00
}
/* load function replacement data */
uint32_t functionReplaceCount = plugin_data - > info . number_used_functions ;
2020-05-03 12:30:15 +02:00
if ( functionReplaceCount > MAXIMUM_FUNCTION_PER_PLUGIN ) {
DEBUG_FUNCTION_LINE ( " number_used_functions was bigger then allowed. %d > %d. Limiting to %d " , functionReplaceCount , MAXIMUM_FUNCTION_PER_PLUGIN , MAXIMUM_FUNCTION_PER_PLUGIN ) ;
2020-04-29 18:02:36 +02:00
functionReplaceCount = MAXIMUM_FUNCTION_PER_PLUGIN ;
}
2020-05-03 12:30:15 +02:00
for ( uint32_t j = 0 ; j < functionReplaceCount ; j + + ) {
2020-06-13 16:57:53 +02:00
function_replacement_data_t * entry = & ( plugin_data - > info . functions [ j ] ) ;
2020-06-19 17:04:39 +02:00
FunctionData func ( ( void * ) entry - > physicalAddr , ( void * ) entry - > virtualAddr , entry - > function_name , ( function_replacement_library_type_t ) entry - > library , ( void * ) entry - > replaceAddr , ( void * ) entry - > replaceCall , entry - > targetProcess ) ;
2020-12-26 14:17:50 +01:00
curPluginInformation . addFunctionData ( func ) ;
2020-04-29 18:02:36 +02:00
}
/* load relocation data */
2020-12-26 14:17:50 +01:00
for ( auto & linking_entrie : plugin_data - > info . linking_entries ) {
dyn_linking_relocation_entry_t * linking_entry = & linking_entrie ;
if ( linking_entry - > destination = = nullptr ) {
2020-04-29 18:02:36 +02:00
break ;
}
2020-05-03 12:30:15 +02:00
dyn_linking_import_t * importEntry = linking_entry - > importEntry ;
2020-12-26 14:17:50 +01:00
if ( importEntry = = nullptr ) {
2020-04-29 18:02:36 +02:00
DEBUG_FUNCTION_LINE ( " importEntry was NULL, skipping relocation entry " ) ;
continue ;
}
2020-12-26 14:17:50 +01:00
if ( importEntry - > importName = = nullptr ) {
2020-04-29 18:02:36 +02:00
DEBUG_FUNCTION_LINE ( " importEntry->importName was NULL, skipping relocation entry " ) ;
continue ;
}
2020-05-03 12:30:15 +02:00
dyn_linking_function_t * functionEntry = linking_entry - > functionEntry ;
2020-04-29 18:02:36 +02:00
2020-12-26 14:17:50 +01:00
if ( functionEntry = = nullptr ) {
2020-04-29 18:02:36 +02:00
DEBUG_FUNCTION_LINE ( " functionEntry was NULL, skipping relocation entry " ) ;
continue ;
}
2020-12-26 14:17:50 +01:00
if ( functionEntry - > functionName = = nullptr ) {
2020-04-29 18:02:36 +02:00
DEBUG_FUNCTION_LINE ( " functionEntry->functionName was NULL, skipping relocation entry " ) ;
continue ;
}
ImportRPLInformation rplInfo ( importEntry - > importName , importEntry - > isData ) ;
2020-12-26 14:17:50 +01:00
std : : string functionName ( functionEntry - > functionName ) ;
RelocationData reloc ( linking_entry - > type , linking_entry - > offset , linking_entry - > addend , linking_entry - > destination , functionName , rplInfo ) ;
curPluginInformation . addRelocationData ( reloc ) ;
2020-04-29 18:02:36 +02:00
}
PluginContainer container ;
container . setMetaInformation ( metaInformation ) ;
container . setPluginData ( pluginData ) ;
2020-12-26 14:17:50 +01:00
container . setPluginInformation ( curPluginInformation ) ;
2020-04-29 18:02:36 +02:00
result . push_back ( container ) ;
}
return result ;
}