2020-04-29 18:02:36 +02:00
# include <coreinit/cache.h>
# include "PluginContainer.h"
# include "PluginInformationFactory.h"
# include "PluginMetaInformationFactory.h"
# include "PluginContainerPersistence.h"
# include "DynamicLinkingHelper.h"
# include "common/plugin_defines.h"
# include "PluginInformation.h"
# include "RelocationData.h"
bool PluginContainerPersistence : : savePlugin ( plugin_information_t * pluginInformation , PluginContainer & plugin ) {
int32_t plugin_count = pluginInformation - > number_used_plugins ;
auto pluginName = plugin . getMetaInformation ( ) . getName ( ) ;
//auto pluginPath = plugin.getMetaInformation().getPath();
if ( plugin_count > = MAXIMUM_PLUGINS - 1 ) {
DEBUG_FUNCTION_LINE ( " Maximum of %d plugins reached. %s won't be loaded! \n " , MAXIMUM_PLUGINS , pluginName . c_str ( ) ) ;
return false ;
}
// Copy data to global struct.
plugin_information_single_t * plugin_data = & ( pluginInformation - > plugin_data [ plugin_count ] ) ;
DEBUG_FUNCTION_LINE ( " %08X " , plugin_data ) ;
// Make sure everything is reset.
//plugin_data = {};
memset ( ( void * ) plugin_data , 0 , sizeof ( plugin_information_single_t ) ) ;
auto pluginMetaInfo = plugin . getMetaInformation ( ) ;
auto plugin_meta_data = & plugin_data - > meta ;
if ( pluginMetaInfo . getName ( ) . size ( ) > = MAXIMUM_PLUGIN_META_FIELD_LENGTH ) {
DEBUG_FUNCTION_LINE ( " Warning: name will be truncated. " ) ;
}
strncpy ( plugin_meta_data - > name , pluginMetaInfo . getName ( ) . c_str ( ) , MAXIMUM_PLUGIN_META_FIELD_LENGTH - 1 ) ;
if ( pluginMetaInfo . getAuthor ( ) . size ( ) > = MAXIMUM_PLUGIN_META_FIELD_LENGTH ) {
DEBUG_FUNCTION_LINE ( " Warning: author will be truncated. " ) ;
}
strncpy ( plugin_meta_data - > author , pluginMetaInfo . getAuthor ( ) . c_str ( ) , MAXIMUM_PLUGIN_META_FIELD_LENGTH - 1 ) ;
if ( pluginMetaInfo . getVersion ( ) . size ( ) > = MAXIMUM_PLUGIN_META_FIELD_LENGTH ) {
DEBUG_FUNCTION_LINE ( " Warning: version will be truncated. " ) ;
}
strncpy ( plugin_meta_data - > version , pluginMetaInfo . getVersion ( ) . c_str ( ) , MAXIMUM_PLUGIN_META_FIELD_LENGTH - 1 ) ;
if ( pluginMetaInfo . getLicense ( ) . size ( ) > = MAXIMUM_PLUGIN_META_FIELD_LENGTH ) {
DEBUG_FUNCTION_LINE ( " Warning: license will be truncated. " ) ;
}
strncpy ( plugin_meta_data - > license , pluginMetaInfo . getLicense ( ) . c_str ( ) , MAXIMUM_PLUGIN_META_FIELD_LENGTH - 1 ) ;
if ( pluginMetaInfo . getBuildTimestamp ( ) . size ( ) > = MAXIMUM_PLUGIN_META_FIELD_LENGTH ) {
DEBUG_FUNCTION_LINE ( " Warning: build timestampt will be truncated. " ) ;
}
strncpy ( plugin_meta_data - > buildTimestamp , pluginMetaInfo . getBuildTimestamp ( ) . c_str ( ) , MAXIMUM_PLUGIN_META_FIELD_LENGTH - 1 ) ;
if ( pluginMetaInfo . getDescription ( ) . size ( ) > = MAXIMUM_PLUGIN_DESCRIPTION_LENGTH ) {
DEBUG_FUNCTION_LINE ( " Warning: description will be truncated. " ) ;
DEBUG_FUNCTION_LINE ( " %s " , pluginMetaInfo . getDescription ( ) . c_str ( ) ) ;
}
strncpy ( plugin_meta_data - > descripion , pluginMetaInfo . getDescription ( ) . c_str ( ) , MAXIMUM_PLUGIN_DESCRIPTION_LENGTH - 1 ) ;
plugin_meta_data - > size = pluginMetaInfo . getSize ( ) ;
auto pluginInfo = plugin . getPluginInformation ( ) ;
// Relocation
std : : vector < RelocationData > relocationData = pluginInfo . getRelocationDataList ( ) ;
for ( auto & reloc : relocationData ) {
2020-05-03 10:21:05 +02:00
if ( ! DynamicLinkingHelper : : addReloationEntry ( & ( pluginInformation - > linking_data ) , plugin_data - > info . linking_entries , PLUGIN_DYN_LINK_RELOCATION_LIST_LENGTH , reloc ) ) {
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 ( ) ;
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 ) ;
return false ;
}
if ( hook_data_list . size ( ) > MAXIMUM_HOOKS_PER_PLUGIN ) {
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 ;
}
if ( pluginName . length ( ) > MAXIMUM_PLUGIN_NAME_LENGTH - 1 ) {
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 ;
for ( auto & curFunction : pluginInfo . getFunctionDataList ( ) ) {
replacement_data_function_t * function_data = & plugin_data - > info . functions [ i ] ;
if ( strlen ( curFunction . getName ( ) . c_str ( ) ) > MAXIMUM_FUNCTION_NAME_LENGTH - 1 ) {
DEBUG_FUNCTION_LINE ( " Could not add function \" %s \" for plugin \" %s \" function name is too long. " , curFunction . getName ( ) . c_str ( ) , pluginName . c_str ( ) ) ;
continue ;
}
DEBUG_FUNCTION_LINE ( " Adding function \" %s \" for plugin \" %s \" " , curFunction . getName ( ) . c_str ( ) , pluginName . c_str ( ) ) ;
strncpy ( function_data - > function_name , curFunction . getName ( ) . c_str ( ) , MAXIMUM_FUNCTION_NAME_LENGTH - 1 ) ;
function_data - > library = curFunction . getLibrary ( ) ;
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 ( ) ;
plugin_data - > info . number_used_functions + + ;
i + + ;
}
i = 0 ;
for ( auto & curHook : pluginInfo . getHookDataList ( ) ) {
replacement_data_hook_t * hook_data = & plugin_data - > info . hooks [ i ] ;
DEBUG_FUNCTION_LINE ( " Set hook for plugin \" %s \" of type %08X to target %08X " , plugin_data - > meta . name , curHook . getType ( ) , ( void * ) curHook . getFunctionPointer ( ) ) ;
hook_data - > func_pointer = ( void * ) curHook . getFunctionPointer ( ) ;
hook_data - > type = curHook . getType ( ) ;
plugin_data - > info . number_used_hooks + + ;
i + + ;
}
/* Saving SectionInfos */
for ( auto & curSection : pluginInfo . getSectionInfoList ( ) ) {
bool foundFreeSlot = false ;
uint32_t slot = 0 ;
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 ) {
foundFreeSlot = true ;
slot = i ;
break ;
}
}
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 ( ) ) ;
break ;
}
strncpy ( sectionInfo - > name , curSection . first . c_str ( ) , MAXIMUM_PLUGIN_SECTION_NAME_LENGTH - 1 ) ;
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 ( ) ;
/* Copy plugin data */
auto pluginData = plugin . getPluginData ( ) ;
auto plugin_data_data = & plugin_data - > data ;
plugin_data_data - > buffer = ( char * ) pluginData . buffer ;
plugin_data_data - > bufferLength = pluginData . length ;
plugin_data_data - > memoryType = pluginData . memoryType ;
plugin_data_data - > heapHandle = ( int ) pluginData . heapHandle ;
pluginInformation - > number_used_plugins + + ;
DCFlushRange ( ( void * ) pluginInformation , sizeof ( plugin_information_t ) ) ;
ICInvalidateRange ( ( void * ) pluginInformation , sizeof ( plugin_information_t ) ) ;
return true ;
}
std : : vector < PluginContainer > PluginContainerPersistence : : loadPlugins ( plugin_information_t * pluginInformation ) {
std : : vector < PluginContainer > result ;
if ( pluginInformation = = NULL ) {
DEBUG_FUNCTION_LINE ( " pluginInformation == NULL " ) ;
return result ;
}
DCFlushRange ( ( void * ) pluginInformation , sizeof ( plugin_information_t ) ) ;
ICInvalidateRange ( ( void * ) pluginInformation , sizeof ( plugin_information_t ) ) ;
int32_t plugin_count = pluginInformation - > number_used_plugins ;
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 ) ;
plugin_count = MAXIMUM_PLUGINS ;
}
for ( int32_t i = 0 ; i < plugin_count ; i + + ) {
// Copy data from struct.
plugin_information_single_t * plugin_data = & ( pluginInformation - > plugin_data [ i ] ) ;
PluginMetaInformation metaInformation ;
plugin_meta_info_t * meta = & ( plugin_data - > meta ) ;
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 ) ;
PluginData pluginData ;
plugin_data_t * data = & ( plugin_data - > data ) ;
pluginData . buffer = data - > buffer ;
pluginData . length = data - > bufferLength ;
pluginData . memoryType = ( eMemoryTypes ) data - > memoryType ;
pluginData . heapHandle = ( MEMHeapHandle ) data - > heapHandle ;
pluginData . loadReader ( ) ;
PluginInformation pluginInformation ;
pluginInformation . setTrampolinId ( plugin_data - > info . trampolinId ) ;
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 ) {
continue ;
}
DEBUG_FUNCTION_LINE ( " Add SectionInfo %s " , sectionInfo - > name ) ;
pluginInformation . addSectionInfo ( SectionInfo ( sectionInfo - > name , sectionInfo - > addr , sectionInfo - > size ) ) ;
}
/* load hook data */
uint32_t hookCount = plugin_data - > info . number_used_hooks ;
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 ) ;
hookCount = MAXIMUM_HOOKS_PER_PLUGIN ;
}
for ( uint32_t j = 0 ; j < hookCount ; j + + ) {
replacement_data_hook_t * hook_entry = & ( plugin_data - > info . hooks [ j ] ) ;
HookData curHook ( hook_entry - > func_pointer , hook_entry - > type ) ;
pluginInformation . addHookData ( curHook ) ;
}
/* load function replacement data */
uint32_t functionReplaceCount = plugin_data - > info . number_used_functions ;
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 ) ;
functionReplaceCount = MAXIMUM_FUNCTION_PER_PLUGIN ;
}
for ( uint32_t j = 0 ; j < functionReplaceCount ; j + + ) {
replacement_data_function_t * entry = & ( plugin_data - > info . functions [ j ] ) ;
FunctionData func ( ( void * ) entry - > physicalAddr , ( void * ) entry - > virtualAddr , entry - > function_name , entry - > library , ( void * ) entry - > replaceAddr , ( void * ) entry - > replaceCall ) ;
pluginInformation . addFunctionData ( func ) ;
}
/* load relocation data */
2020-05-03 10:21:05 +02:00
for ( uint32_t j = 0 ; j < PLUGIN_DYN_LINK_RELOCATION_LIST_LENGTH ; j + + ) {
2020-04-29 18:02:36 +02:00
dyn_linking_relocation_entry_t * linking_entry = & ( plugin_data - > info . linking_entries [ j ] ) ;
if ( linking_entry - > destination = = NULL ) {
break ;
}
dyn_linking_import_t * importEntry = linking_entry - > importEntry ;
if ( importEntry = = NULL ) {
DEBUG_FUNCTION_LINE ( " importEntry was NULL, skipping relocation entry " ) ;
continue ;
}
if ( importEntry - > importName = = NULL ) {
DEBUG_FUNCTION_LINE ( " importEntry->importName was NULL, skipping relocation entry " ) ;
continue ;
}
dyn_linking_function_t * functionEntry = linking_entry - > functionEntry ;
if ( functionEntry = = NULL ) {
DEBUG_FUNCTION_LINE ( " functionEntry was NULL, skipping relocation entry " ) ;
continue ;
}
if ( functionEntry - > functionName = = NULL ) {
DEBUG_FUNCTION_LINE ( " functionEntry->functionName was NULL, skipping relocation entry " ) ;
continue ;
}
ImportRPLInformation rplInfo ( importEntry - > importName , importEntry - > isData ) ;
RelocationData reloc ( linking_entry - > type , linking_entry - > offset , linking_entry - > addend , linking_entry - > destination , functionEntry - > functionName , rplInfo ) ;
pluginInformation . addRelocationData ( reloc ) ;
}
PluginContainer container ;
container . setMetaInformation ( metaInformation ) ;
container . setPluginData ( pluginData ) ;
container . setPluginInformation ( pluginInformation ) ;
result . push_back ( container ) ;
}
return result ;
}