mirror of
https://github.com/wiiu-env/WiiUPluginSystem.git
synced 2024-12-25 09:31:56 +01:00
[Loader] Refactored the plugin loading.
- Now all plugins in the "sd:/wiiu/plugins" folder will be loaded. - Minor code cleanup
This commit is contained in:
parent
f6ec4bcc56
commit
d0908e7eb6
@ -30,6 +30,7 @@
|
|||||||
|
|
||||||
#include "common/retain_vars.h"
|
#include "common/retain_vars.h"
|
||||||
#include "common/common.h"
|
#include "common/common.h"
|
||||||
|
#include "modules/ModuleLoader.h"
|
||||||
#include "modules/ModuleData.h"
|
#include "modules/ModuleData.h"
|
||||||
|
|
||||||
#include <utils/function_patcher.h>
|
#include <utils/function_patcher.h>
|
||||||
@ -50,19 +51,13 @@
|
|||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "settings/CSettings.h"
|
#include "settings/CSettings.h"
|
||||||
|
|
||||||
static bool loadSamplePlugins();
|
|
||||||
static void ApplyPatches();
|
static void ApplyPatches();
|
||||||
void CallHook(wups_loader_hook_type_t hook_type);
|
void CallHook(wups_loader_hook_type_t hook_type);
|
||||||
static void RestorePatches();
|
static void RestorePatches();
|
||||||
s32 isInMiiMakerHBL();
|
s32 isInMiiMakerHBL();
|
||||||
|
|
||||||
static void copyDataIntoGlobalStruct(std::vector<ModuleData *>* modules);
|
|
||||||
static void loadElf(std::vector<ModuleData *>* modules, const char * elfPath, uint8_t ** space);
|
|
||||||
|
|
||||||
u8 isFirstBoot __attribute__((section(".data"))) = 1;
|
u8 isFirstBoot __attribute__((section(".data"))) = 1;
|
||||||
|
|
||||||
#define PLUGIN_LOCATION_END_ADDRESS 0x01000000
|
|
||||||
|
|
||||||
/* Entry point */
|
/* Entry point */
|
||||||
extern "C" int Menu_Main(int argc, char **argv){
|
extern "C" int Menu_Main(int argc, char **argv){
|
||||||
if(gAppStatus == 2){
|
if(gAppStatus == 2){
|
||||||
@ -93,9 +88,10 @@ extern "C" int Menu_Main(int argc, char **argv){
|
|||||||
|
|
||||||
if(isFirstBoot){
|
if(isFirstBoot){
|
||||||
memset((void*)&gbl_replacement_data,0,sizeof(gbl_replacement_data));
|
memset((void*)&gbl_replacement_data,0,sizeof(gbl_replacement_data));
|
||||||
if(!loadSamplePlugins()){
|
|
||||||
return EXIT_SUCCESS;
|
ModuleLoader * moduleLoader = ModuleLoader::getInstance();
|
||||||
}
|
std::vector<ModuleInformation *> moduleList = moduleLoader->getModuleInformation("sd:/wiiu/plugins/");
|
||||||
|
moduleLoader->loadAndLinkModules(moduleList);
|
||||||
|
|
||||||
//!*******************************************************************
|
//!*******************************************************************
|
||||||
//! Initialize heap memory *
|
//! Initialize heap memory *
|
||||||
@ -221,120 +217,6 @@ s32 isInMiiMakerHBL(){
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool loadSamplePlugins(){
|
|
||||||
if((gSDInitDone & WUPS_SD_MOUNTED) > 0){
|
|
||||||
DEBUG_FUNCTION_LINE("Mounting successful. Loading modules\n");
|
|
||||||
|
|
||||||
std::vector<ModuleData *> modules;
|
|
||||||
|
|
||||||
// Set a pointer to the END of our plugin location.
|
|
||||||
// So our plugins will be stored from PLUGIN_LOCATION_END_ADDRESS backward. Maximum is getApplicationEndAddr() (behind this loader).
|
|
||||||
// Copied the "reserved" direction from brainslug, not sure why we're doing this.
|
|
||||||
unsigned char * space = (unsigned char*)PLUGIN_LOCATION_END_ADDRESS;
|
|
||||||
|
|
||||||
|
|
||||||
// TODO: Load all files from a certain directory, don't use hardcoded paths. (common.h)
|
|
||||||
loadElf(&modules, "sd:/wiiu/plugins/hid_to_vpad.mod",&space);
|
|
||||||
loadElf(&modules, "sd:/wiiu/plugins/sdcafiine.mod",&space);
|
|
||||||
loadElf(&modules, "sd:/wiiu/plugins/padcon.mod",&space);
|
|
||||||
loadElf(&modules, "sd:/wiiu/plugins/swipswapme.mod",&space);
|
|
||||||
|
|
||||||
// Copy the data into the global struct locating in the .data section.
|
|
||||||
copyDataIntoGlobalStruct(&modules);
|
|
||||||
|
|
||||||
// Free memory.
|
|
||||||
for(size_t i = 0; i< modules.size();i++){
|
|
||||||
ModuleData * cur_module = modules[i];
|
|
||||||
if(cur_module != NULL){
|
|
||||||
free(cur_module);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG_FUNCTION_LINE("Flush memory\n");
|
|
||||||
DCFlushRange ((void*)getApplicationEndAddr(),PLUGIN_LOCATION_END_ADDRESS-getApplicationEndAddr());
|
|
||||||
DCInvalidateRange((void*)getApplicationEndAddr(),PLUGIN_LOCATION_END_ADDRESS-getApplicationEndAddr());
|
|
||||||
|
|
||||||
// TODO: keep it mounted for the plugins. But this would require sharing the read/write/open etc. functions from this loader.
|
|
||||||
// Idea: Giving the init hook the pointers. Hiding the __wrap function of the plugin behind the INITIALIZE macro.
|
|
||||||
// Needs to be tested if this is working. This would have the advantage of adopting all right/accesses from the loader (libfat, libntfs, iosuhax etc.)
|
|
||||||
//unmount_sd_fat("sd");
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void copyDataIntoGlobalStruct(std::vector<ModuleData *>* modules){
|
|
||||||
int module_index = 0;
|
|
||||||
// Copy data to global struct.
|
|
||||||
for(size_t i = 0; i< modules->size();i++){
|
|
||||||
ModuleData * cur_module = modules->at(i);
|
|
||||||
|
|
||||||
std::vector<EntryData *> entry_data_list = cur_module->getEntryDataList();
|
|
||||||
std::vector<HookData *> hook_data_list = cur_module->getHookDataList();
|
|
||||||
if(module_index >= MAXIMUM_MODULES ){
|
|
||||||
DEBUG_FUNCTION_LINE("Maximum of %d modules reached. %s won't be loaded!\n",MAXIMUM_MODULES,cur_module->getName().c_str());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if(entry_data_list.size() > MAXIMUM_FUNCTION_PER_MODULE){
|
|
||||||
DEBUG_FUNCTION_LINE("Module %s would replace to many function (%d, maximum is %d). It won't be loaded.\n",cur_module->getName().c_str(),entry_data_list.size(),MAXIMUM_FUNCTION_PER_MODULE);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if(hook_data_list.size() > MAXIMUM_HOOKS_PER_MODULE){
|
|
||||||
DEBUG_FUNCTION_LINE("Module %s would set too many hooks (%d, maximum is %d). It won't be loaded.\n",cur_module->getName().c_str(),hook_data_list.size(),MAXIMUM_HOOKS_PER_MODULE);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
replacement_data_module_t * module_data = &gbl_replacement_data.module_data[module_index];
|
|
||||||
|
|
||||||
strncpy(module_data->module_name,cur_module->getName().c_str(),MAXIMUM_MODULE_NAME_LENGTH-1);
|
|
||||||
|
|
||||||
for(size_t j = 0; j < entry_data_list.size();j++){
|
|
||||||
replacement_data_function_t * function_data = &module_data->functions[j];
|
|
||||||
|
|
||||||
EntryData * cur_entry = entry_data_list[j];
|
|
||||||
DEBUG_FUNCTION_LINE("Adding entry \"%s\" for module \"%s\"\n",cur_entry->getName().c_str(),module_data->module_name);
|
|
||||||
|
|
||||||
//TODO: Warning/Error if string is too long.
|
|
||||||
strncpy(function_data->function_name,cur_entry->getName().c_str(),MAXIMUM_FUNCTION_NAME_LENGTH-1);
|
|
||||||
|
|
||||||
function_data->library = cur_entry->getLibrary();
|
|
||||||
function_data->replaceAddr = (u32) cur_entry->getReplaceAddress();
|
|
||||||
function_data->replaceCall = (u32) cur_entry->getReplaceCall();
|
|
||||||
|
|
||||||
module_data->number_used_functions++;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG_FUNCTION_LINE("Entries for module \"%s\": %d\n",module_data->module_name,module_data->number_used_functions);
|
|
||||||
|
|
||||||
for(size_t j = 0; j < hook_data_list.size();j++){
|
|
||||||
replacement_data_hook_t * hook_data = &module_data->hooks[j];
|
|
||||||
|
|
||||||
HookData * hook_entry = hook_data_list[j];
|
|
||||||
|
|
||||||
DEBUG_FUNCTION_LINE("Set hook for module \"%s\" of type %08X to target %08X\n",module_data->module_name,hook_entry->getType(),(void*) hook_entry->getFunctionPointer());
|
|
||||||
hook_data->func_pointer = (void*) hook_entry->getFunctionPointer();
|
|
||||||
hook_data->type = hook_entry->getType();
|
|
||||||
module_data->number_used_hooks++;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG_FUNCTION_LINE("Hooks for module \"%s\": %d\n",module_data->module_name,module_data->number_used_hooks);
|
|
||||||
|
|
||||||
module_index++;
|
|
||||||
gbl_replacement_data.number_used_modules++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void loadElf(std::vector<ModuleData *>* modules, const char * elfPath, uint8_t ** space){
|
|
||||||
DEBUG_FUNCTION_LINE("Try to load %s\n",elfPath);
|
|
||||||
|
|
||||||
ModuleData * module = new ModuleData(elfPath,space);
|
|
||||||
if(module->isLoadedSuccessfully()){
|
|
||||||
DEBUG_FUNCTION_LINE("%s loading was successful!. \n", elfPath);
|
|
||||||
modules->push_back(module);
|
|
||||||
} else {
|
|
||||||
DEBUG_FUNCTION_LINE("%s loading failed. \n", elfPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Init_SD_USB() {
|
void Init_SD_USB() {
|
||||||
int res = IOSUHAX_Open(NULL);
|
int res = IOSUHAX_Open(NULL);
|
||||||
if(res < 0){
|
if(res < 0){
|
||||||
|
@ -26,13 +26,11 @@
|
|||||||
#include "ElfTools.h"
|
#include "ElfTools.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <libelf.h>
|
#include <libelf.h>
|
||||||
#include <utils/logger.h>
|
#include <utils/logger.h>
|
||||||
|
|
||||||
bool ElfTools::elfLoadSection(const Elf *elf, Elf_Scn *scn, const Elf32_Shdr *shdr,void *destination) {
|
bool ElfTools::elfLoadSection(const Elf *elf, Elf_Scn *scn, const Elf32_Shdr *shdr,void *destination) {
|
||||||
|
if (destination == NULL) { return false; }
|
||||||
assert(destination != NULL);
|
|
||||||
|
|
||||||
switch (shdr->sh_type) {
|
switch (shdr->sh_type) {
|
||||||
case SHT_SYMTAB:
|
case SHT_SYMTAB:
|
||||||
@ -58,29 +56,33 @@ bool ElfTools::loadElfSymtab(Elf *elf, Elf32_Sym **symtab, size_t *symtab_count,
|
|||||||
Elf_Scn *scn;
|
Elf_Scn *scn;
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
||||||
for (scn = elf_nextscn(elf, NULL);
|
for (scn = elf_nextscn(elf, NULL); scn != NULL; scn = elf_nextscn(elf, scn)) {
|
||||||
scn != NULL;
|
|
||||||
scn = elf_nextscn(elf, scn)) {
|
|
||||||
|
|
||||||
Elf32_Shdr *shdr;
|
Elf32_Shdr *shdr;
|
||||||
|
|
||||||
shdr = elf32_getshdr(scn);
|
shdr = elf32_getshdr(scn);
|
||||||
if (shdr == NULL)
|
if (shdr == NULL){
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (shdr->sh_type == SHT_SYMTAB) {
|
if (shdr->sh_type == SHT_SYMTAB) {
|
||||||
size_t sym;
|
size_t sym;
|
||||||
|
|
||||||
assert (*symtab == NULL);
|
if (*symtab != NULL){
|
||||||
*symtab = (Elf32_Sym *)malloc(shdr->sh_size);
|
|
||||||
if (*symtab == NULL)
|
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
*symtab = (Elf32_Sym *)malloc(shdr->sh_size);
|
||||||
|
if (*symtab == NULL){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
*symtab_count = shdr->sh_size / sizeof(Elf32_Sym);
|
*symtab_count = shdr->sh_size / sizeof(Elf32_Sym);
|
||||||
*symtab_strndx = shdr->sh_link;
|
*symtab_strndx = shdr->sh_link;
|
||||||
|
|
||||||
if (!elfLoadSection(elf, scn, shdr, *symtab))
|
if (!elfLoadSection(elf, scn, shdr, *symtab)){
|
||||||
goto exit_error;
|
goto exit_error;
|
||||||
|
}
|
||||||
|
|
||||||
for (sym = 0; sym < *symtab_count; sym++){
|
for (sym = 0; sym < *symtab_count; sym++){
|
||||||
(*symtab)[sym].st_other = 0;
|
(*symtab)[sym].st_other = 0;
|
||||||
@ -90,8 +92,9 @@ bool ElfTools::loadElfSymtab(Elf *elf, Elf32_Sym **symtab, size_t *symtab_count,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*symtab == NULL)
|
if (*symtab == NULL){
|
||||||
goto exit_error;
|
goto exit_error;
|
||||||
|
}
|
||||||
|
|
||||||
result = true;
|
result = true;
|
||||||
exit_error:
|
exit_error:
|
||||||
@ -354,7 +357,7 @@ bool ElfTools::elfLinkOne(char type, size_t offset, int addend, void *destinatio
|
|||||||
value = addend - (int)symbol_addr;
|
value = addend - (int)symbol_addr;
|
||||||
break;
|
break;
|
||||||
} default:
|
} default:
|
||||||
DEBUG_FUNCTION_LINE("Module_ElfLinkOne01: %02X\n",type);
|
DEBUG_FUNCTION_LINE("Unknown relocation type: %02X\n",type);
|
||||||
goto exit_error;
|
goto exit_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -414,7 +417,6 @@ bool ElfTools::elfLinkOne(char type, size_t offset, int addend, void *destinatio
|
|||||||
(*(int *)target & 0x00000003) | (value & 0xfffffffc);
|
(*(int *)target & 0x00000003) | (value & 0xfffffffc);
|
||||||
break;
|
break;
|
||||||
}default:
|
}default:
|
||||||
DEBUG_FUNCTION_LINE("Module_ElfLinkOne01: %02X\n",type);
|
|
||||||
goto exit_error;
|
goto exit_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,27 +1,19 @@
|
|||||||
/* based on module.c
|
/****************************************************************************
|
||||||
* by Alex Chadwick
|
* Copyright (C) 2018 Maschell
|
||||||
*
|
*
|
||||||
* Copyright (C) 2014, Alex Chadwick
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* Modified 2018, Maschell
|
* 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.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* This program is distributed in the hope that it will be useful,
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* in the Software without restriction, including without limitation the rights
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* GNU General Public License for more details.
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* You should have received a copy of the GNU General Public License
|
||||||
* all copies or substantial portions of the Software.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
****************************************************************************/
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _MODULE_DATA_H_
|
#ifndef _MODULE_DATA_H_
|
||||||
#define _MODULE_DATA_H_
|
#define _MODULE_DATA_H_
|
||||||
@ -30,6 +22,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include "EntryData.h"
|
#include "EntryData.h"
|
||||||
#include "HookData.h"
|
#include "HookData.h"
|
||||||
|
#include "ModuleInformation.h"
|
||||||
#include <utils/logger.h>
|
#include <utils/logger.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@ -44,14 +37,8 @@ extern "C" {
|
|||||||
|
|
||||||
class ModuleData{
|
class ModuleData{
|
||||||
public:
|
public:
|
||||||
ModuleData(std::string path, uint8_t ** space){
|
ModuleData(ModuleInformation * moduleInformation){
|
||||||
this->path = path;
|
this->moduleInformation = moduleInformation;
|
||||||
if(checkFile()){
|
|
||||||
DEBUG_FUNCTION_LINE("Checkfile successfully, loading now \n");
|
|
||||||
this->loadedSuccessfully = load(space);
|
|
||||||
} else {
|
|
||||||
this->loadedSuccessfully = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~ModuleData(){
|
~ModuleData(){
|
||||||
@ -68,50 +55,6 @@ class ModuleData{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setName(const char * name){
|
|
||||||
this->name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setAuthor(const char * author){
|
|
||||||
this->author = author;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setVersion(const char * version){
|
|
||||||
this->version = version;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setLicense(const char * license){
|
|
||||||
this->license = license;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setSize(size_t size){
|
|
||||||
this->size = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string getName(){
|
|
||||||
return this->name;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string getAuthor(){
|
|
||||||
return this->author;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string getVersion(){
|
|
||||||
return this->version;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string getLicense(){
|
|
||||||
return this->license;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string getPath(){
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isLoadedSuccessfully(){
|
|
||||||
return loadedSuccessfully;
|
|
||||||
}
|
|
||||||
|
|
||||||
void addEntryData(EntryData * entry_data){
|
void addEntryData(EntryData * entry_data){
|
||||||
entry_data_list.push_back(entry_data);
|
entry_data_list.push_back(entry_data);
|
||||||
}
|
}
|
||||||
@ -128,26 +71,13 @@ class ModuleData{
|
|||||||
return hook_data_list;
|
return hook_data_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ModuleInformation * getModuleInformation(){
|
||||||
|
return moduleInformation;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool checkFile();
|
ModuleInformation * moduleInformation;
|
||||||
|
|
||||||
bool load(uint8_t ** space);
|
|
||||||
|
|
||||||
bool loadElf(Elf *elf);
|
|
||||||
|
|
||||||
bool metadataRead(Elf *elf, Elf32_Sym *symtab, size_t symtab_count, size_t symtab_strndx);
|
|
||||||
|
|
||||||
bool linkModuleElf(Elf *elf, uint8_t **space);
|
|
||||||
|
|
||||||
bool loadedSuccessfully = false;
|
|
||||||
|
|
||||||
std::string path;
|
|
||||||
std::string name;
|
|
||||||
std::string author;
|
|
||||||
std::string version;
|
|
||||||
std::string license;
|
|
||||||
size_t size;
|
|
||||||
|
|
||||||
std::vector<EntryData *> entry_data_list;
|
std::vector<EntryData *> entry_data_list;
|
||||||
std::vector<HookData *> hook_data_list;
|
std::vector<HookData *> hook_data_list;
|
||||||
|
@ -23,12 +23,11 @@
|
|||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ModuleData.h"
|
#include "ModuleInformation.h"
|
||||||
#include <utils/logger.h>
|
#include <utils/logger.h>
|
||||||
#include <dynamic_libs/os_types.h>
|
#include <dynamic_libs/os_types.h>
|
||||||
#include <libelf.h>
|
#include <libelf.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <wups.h>
|
#include <wups.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
@ -37,20 +36,23 @@
|
|||||||
#include <utils/utils.h>
|
#include <utils/utils.h>
|
||||||
#include "ElfTools.h"
|
#include "ElfTools.h"
|
||||||
|
|
||||||
bool ModuleData::checkFile() {
|
bool ModuleInformation::checkFileExtenstion(const char * path) {
|
||||||
|
if(path == NULL){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
const char *extension;
|
const char *extension;
|
||||||
|
|
||||||
const char * path_c = getPath().c_str();
|
|
||||||
|
|
||||||
/* find the file extension */
|
/* find the file extension */
|
||||||
extension = strrchr(path_c, '.');
|
extension = strrchr(path, '.');
|
||||||
if (extension == NULL){
|
if (extension == NULL){
|
||||||
extension = strchr(path_c, '\0');
|
extension = strchr(path, '\0');
|
||||||
}else{
|
}else{
|
||||||
extension++;
|
extension++;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(extension != NULL);
|
if(extension == NULL){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (strcmp(extension, "mod") == 0 ||
|
if (strcmp(extension, "mod") == 0 ||
|
||||||
strcmp(extension, "o") == 0 ||
|
strcmp(extension, "o") == 0 ||
|
||||||
@ -61,14 +63,13 @@ bool ModuleData::checkFile() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ModuleData::load(uint8_t ** space) {
|
bool ModuleInformation::openAndParseElf() {
|
||||||
bool result = false;
|
bool result = false;
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
Elf *elf = NULL;
|
Elf *elf = NULL;
|
||||||
|
|
||||||
/* check for compile errors */
|
/* check for compile errors */
|
||||||
if (elf_version(EV_CURRENT) == EV_NONE){
|
if (elf_version(EV_CURRENT) == EV_NONE){
|
||||||
DEBUG_FUNCTION_LINE("Compiler errors in '%s' \n", getPath().c_str());
|
|
||||||
goto exit_error;
|
goto exit_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,10 +93,7 @@ bool ModuleData::load(uint8_t ** space) {
|
|||||||
DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Archives not yet supported.\n", getPath().c_str());
|
DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Archives not yet supported.\n", getPath().c_str());
|
||||||
goto exit_error;
|
goto exit_error;
|
||||||
case ELF_K_ELF:
|
case ELF_K_ELF:
|
||||||
if(!this->loadElf(elf)){
|
result = this->parseElf(elf);
|
||||||
goto exit_error;
|
|
||||||
}
|
|
||||||
result = linkModuleElf(elf,space);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Invalid ELF file.\n", getPath().c_str());
|
DEBUG_FUNCTION_LINE("Warning: Ignoring '%s' - Invalid ELF file.\n", getPath().c_str());
|
||||||
@ -112,7 +110,7 @@ exit_error:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ModuleData::loadElf( Elf *elf) {
|
bool ModuleInformation::parseElf( Elf *elf) {
|
||||||
bool res = false;
|
bool res = false;
|
||||||
Elf_Scn *scn;
|
Elf_Scn *scn;
|
||||||
Elf32_Ehdr *ehdr;
|
Elf32_Ehdr *ehdr;
|
||||||
@ -124,8 +122,8 @@ bool ModuleData::loadElf( Elf *elf) {
|
|||||||
|
|
||||||
const char * path_c = getPath().c_str();
|
const char * path_c = getPath().c_str();
|
||||||
|
|
||||||
assert(elf != NULL);
|
if(elf == NULL){ goto exit_error; }
|
||||||
assert(elf_kind(elf) == ELF_K_ELF);
|
if(elf_kind(elf) != ELF_K_ELF){ goto exit_error; }
|
||||||
|
|
||||||
ident = elf_getident(elf, &sz);
|
ident = elf_getident(elf, &sz);
|
||||||
|
|
||||||
@ -174,9 +172,7 @@ bool ModuleData::loadElf( Elf *elf) {
|
|||||||
goto exit_error;
|
goto exit_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(symtab != NULL);
|
if(symtab == NULL){ goto exit_error; }
|
||||||
|
|
||||||
DEBUG_FUNCTION_LINE("Reading metadata from path %s.\n", path_c);
|
|
||||||
|
|
||||||
if(!metadataRead(elf, symtab, symtab_count, symtab_strndx)){
|
if(!metadataRead(elf, symtab, symtab_count, symtab_strndx)){
|
||||||
goto exit_error;
|
goto exit_error;
|
||||||
@ -241,7 +237,7 @@ exit_error:
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ModuleData::metadataRead(Elf *elf, Elf32_Sym *symtab, size_t symtab_count, size_t symtab_strndx) {
|
bool ModuleInformation::metadataRead(Elf *elf, Elf32_Sym *symtab, size_t symtab_count, size_t symtab_strndx) {
|
||||||
char *metadata = NULL, *metadata_cur, *metadata_end;
|
char *metadata = NULL, *metadata_cur, *metadata_end;
|
||||||
const char *game, *name, *author, *version, *license, *wups;
|
const char *game, *name, *author, *version, *license, *wups;
|
||||||
|
|
||||||
@ -315,7 +311,9 @@ bool ModuleData::metadataRead(Elf *elf, Elf32_Sym *symtab, size_t symtab_count,
|
|||||||
|
|
||||||
char *eq;
|
char *eq;
|
||||||
|
|
||||||
assert(metadata_cur >= metadata && metadata_cur < metadata_end);
|
if(metadata_cur < metadata || metadata_cur >= metadata_end){
|
||||||
|
goto exit_error;
|
||||||
|
}
|
||||||
|
|
||||||
if (*metadata_cur == '\0'){
|
if (*metadata_cur == '\0'){
|
||||||
continue;
|
continue;
|
||||||
@ -404,180 +402,3 @@ exit_error:
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ModuleData::linkModuleElf(Elf *elf, uint8_t **space) {
|
|
||||||
Elf_Scn *scn;
|
|
||||||
size_t symtab_count, section_count, shstrndx, symtab_strndx, entries_count, hooks_count;
|
|
||||||
Elf32_Sym *symtab = NULL;
|
|
||||||
uint8_t **destinations = NULL;
|
|
||||||
wups_loader_entry_t *entries = NULL;
|
|
||||||
wups_loader_hook_t *hooks = NULL;
|
|
||||||
bool result = false;
|
|
||||||
|
|
||||||
std::vector<wups_loader_entry_t *> entry_t_list;
|
|
||||||
std::vector<wups_loader_hook_t *> hook_t_list;
|
|
||||||
|
|
||||||
std::vector<EntryData *> entry_data_list;
|
|
||||||
std::vector<HookData *> hook_data_list;
|
|
||||||
|
|
||||||
if (!ElfTools::loadElfSymtab(elf, &symtab, &symtab_count, &symtab_strndx)){
|
|
||||||
goto exit_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(symtab != NULL);
|
|
||||||
|
|
||||||
if (elf_getshdrnum(elf, §ion_count) != 0){
|
|
||||||
goto exit_error;
|
|
||||||
}
|
|
||||||
if (elf_getshdrstrndx(elf, &shstrndx) != 0){
|
|
||||||
goto exit_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
destinations = (uint8_t **) malloc(sizeof(uint8_t *) * section_count);
|
|
||||||
|
|
||||||
for (scn = elf_nextscn(elf, NULL); scn != NULL; scn = elf_nextscn(elf, scn)) {
|
|
||||||
Elf32_Shdr *shdr;
|
|
||||||
|
|
||||||
shdr = elf32_getshdr(scn);
|
|
||||||
if (shdr == NULL){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((shdr->sh_type == SHT_PROGBITS || shdr->sh_type == SHT_NOBITS) &&
|
|
||||||
(shdr->sh_flags & SHF_ALLOC)) {
|
|
||||||
|
|
||||||
const char *name;
|
|
||||||
|
|
||||||
destinations[elf_ndxscn(scn)] = NULL;
|
|
||||||
|
|
||||||
name = elf_strptr(elf, shstrndx, shdr->sh_name);
|
|
||||||
if (name == NULL){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp(name, ".wups.meta") == 0) {
|
|
||||||
continue;
|
|
||||||
} else if (strcmp(name, ".wups.load") == 0) {
|
|
||||||
if (entries != NULL){
|
|
||||||
goto exit_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
entries_count = shdr->sh_size / sizeof(wups_loader_entry_t);
|
|
||||||
entries = (wups_loader_entry_t *) malloc(sizeof(wups_loader_entry_t) * entries_count);
|
|
||||||
|
|
||||||
if (entries == NULL){
|
|
||||||
goto exit_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
destinations[elf_ndxscn(scn)] = (uint8_t *)entries;
|
|
||||||
if (!ElfTools::elfLoadSection(elf, scn, shdr, entries)){
|
|
||||||
goto exit_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
ElfTools::elfLoadSymbols(elf_ndxscn(scn), entries, symtab, symtab_count);
|
|
||||||
|
|
||||||
for(size_t i = 0;i< entries_count;i++){
|
|
||||||
entry_t_list.push_back(&entries[i]);
|
|
||||||
}
|
|
||||||
}else if (strcmp(name, ".wups.hooks") == 0) {
|
|
||||||
if (hooks != NULL){
|
|
||||||
goto exit_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
hooks_count = shdr->sh_size / sizeof(wups_loader_hook_t);
|
|
||||||
hooks = (wups_loader_hook_t *) malloc(sizeof(wups_loader_hook_t) * hooks_count);
|
|
||||||
|
|
||||||
if (hooks == NULL){
|
|
||||||
goto exit_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
destinations[elf_ndxscn(scn)] = (uint8_t *)hooks;
|
|
||||||
if (!ElfTools::elfLoadSection(elf, scn, shdr, hooks)){
|
|
||||||
goto exit_error;
|
|
||||||
}
|
|
||||||
ElfTools::elfLoadSymbols(elf_ndxscn(scn), hooks, symtab, symtab_count);
|
|
||||||
|
|
||||||
for(size_t i = 0;i< hooks_count;i++){
|
|
||||||
hook_t_list.push_back(&hooks[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
*space -= shdr->sh_size;
|
|
||||||
|
|
||||||
if (shdr->sh_addralign > 3)
|
|
||||||
*space = (uint8_t *)((int)*space &
|
|
||||||
~(shdr->sh_addralign - 1));
|
|
||||||
else
|
|
||||||
*space = (uint8_t *)((int)*space & ~3);
|
|
||||||
|
|
||||||
destinations[elf_ndxscn(scn)] = *space;
|
|
||||||
|
|
||||||
assert(*space != NULL);
|
|
||||||
if((u32) *space < getApplicationEndAddr()){
|
|
||||||
DEBUG_FUNCTION_LINE("Not enough space to load function %s into memory at %08X.\n",name,*space);
|
|
||||||
goto exit_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG_FUNCTION_LINE("Copy section %s to %08X\n",name,*space);
|
|
||||||
if (!ElfTools::elfLoadSection(elf, scn, shdr, *space)){
|
|
||||||
goto exit_error;
|
|
||||||
}
|
|
||||||
ElfTools::elfLoadSymbols(elf_ndxscn(scn), *space, symtab, symtab_count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entries == NULL){
|
|
||||||
goto exit_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (scn = elf_nextscn(elf, NULL); scn != NULL; scn = elf_nextscn(elf, scn)) {
|
|
||||||
Elf32_Shdr *shdr;
|
|
||||||
|
|
||||||
shdr = elf32_getshdr(scn);
|
|
||||||
if (shdr == NULL){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((shdr->sh_type == SHT_PROGBITS || shdr->sh_type == SHT_NOBITS) &&
|
|
||||||
(shdr->sh_flags & SHF_ALLOC) &&
|
|
||||||
destinations[elf_ndxscn(scn)] != NULL) {
|
|
||||||
|
|
||||||
if (!ElfTools::elfLink(elf, elf_ndxscn(scn), destinations[elf_ndxscn(scn)], symtab, symtab_count, symtab_strndx, true)){
|
|
||||||
goto exit_error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(size_t j=0;j<hook_t_list.size();j++){
|
|
||||||
wups_loader_hook_t * hook = hook_t_list[j];
|
|
||||||
|
|
||||||
DEBUG_FUNCTION_LINE("Saving hook of module \"%s\". Type: %08X, target: %08X\n",getName().c_str(),hook->type,(void*) hook->target);
|
|
||||||
HookData * hook_data = new HookData((void *) hook->target,hook->type);
|
|
||||||
addHookData(hook_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(size_t j=0;j<entry_t_list.size();j++){
|
|
||||||
wups_loader_entry_t * entry = entry_t_list[j];
|
|
||||||
DEBUG_FUNCTION_LINE("Saving entry \"%s\" of module \"%s\". Library: %08X, target: %08X, call_addr: %08X\n",entry->_function.name,getName().c_str(),entry->_function.library,entry->_function.target, (void *) entry->_function.call_addr);
|
|
||||||
EntryData * entry_data = new EntryData(entry->_function.name,entry->_function.library, (void *) entry->_function.target, (void *) entry->_function.call_addr);
|
|
||||||
addEntryData(entry_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
result = true;
|
|
||||||
exit_error:
|
|
||||||
if (!result) DEBUG_FUNCTION_LINE("exit_error\n");
|
|
||||||
if (destinations != NULL){
|
|
||||||
free(destinations);
|
|
||||||
}
|
|
||||||
if (symtab != NULL){
|
|
||||||
free(symtab);
|
|
||||||
}
|
|
||||||
if (hooks != NULL){
|
|
||||||
free(hooks);
|
|
||||||
}
|
|
||||||
if (entries != NULL){
|
|
||||||
free(entries);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
133
loader/src/modules/ModuleInformation.h
Normal file
133
loader/src/modules/ModuleInformation.h
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
/* based on module.c
|
||||||
|
* by Alex Chadwick
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014, Alex Chadwick
|
||||||
|
* Modified 2018, Maschell
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _MODULE_INFORMATION_H_
|
||||||
|
#define _MODULE_INFORMATION_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include "EntryData.h"
|
||||||
|
#include "HookData.h"
|
||||||
|
#include <utils/logger.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <libelf.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class ModuleInformation{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
|
||||||
|
returns ModuleInformation* if a valid plugin was found at the given path. Otherwise returns NULL
|
||||||
|
**/
|
||||||
|
static ModuleInformation * loadModuleInformation(std::string path){
|
||||||
|
if(ModuleInformation::checkFileExtenstion(path.c_str())){
|
||||||
|
DEBUG_FUNCTION_LINE("Checkfile successfully, loading now Module Information\n");
|
||||||
|
ModuleInformation * moduleInformation = new ModuleInformation(path);
|
||||||
|
if(moduleInformation->openAndParseElf()){
|
||||||
|
return moduleInformation;
|
||||||
|
}else{
|
||||||
|
delete moduleInformation;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string getName(){
|
||||||
|
return this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string getAuthor(){
|
||||||
|
return this->author;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string getVersion(){
|
||||||
|
return this->version;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string getLicense(){
|
||||||
|
return this->license;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string getPath(){
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getSize(){
|
||||||
|
return this->size;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
ModuleInformation(std::string path){
|
||||||
|
this->path = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setName(const char * name){
|
||||||
|
this->name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setAuthor(const char * author){
|
||||||
|
this->author = author;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setVersion(const char * version){
|
||||||
|
this->version = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setLicense(const char * license){
|
||||||
|
this->license = license;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setSize(size_t size){
|
||||||
|
this->size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool checkFileExtenstion(const char * path);
|
||||||
|
|
||||||
|
bool openAndParseElf();
|
||||||
|
|
||||||
|
bool parseElf(Elf *elf);
|
||||||
|
|
||||||
|
bool metadataRead(Elf *elf, Elf32_Sym *symtab, size_t symtab_count, size_t symtab_strndx);
|
||||||
|
|
||||||
|
bool loadedSuccessfully = false;
|
||||||
|
|
||||||
|
std::string path;
|
||||||
|
std::string name;
|
||||||
|
std::string author;
|
||||||
|
std::string version;
|
||||||
|
std::string license;
|
||||||
|
size_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
414
loader/src/modules/ModuleLoader.cpp
Normal file
414
loader/src/modules/ModuleLoader.cpp
Normal file
@ -0,0 +1,414 @@
|
|||||||
|
/* based on module.c
|
||||||
|
* by Alex Chadwick
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014, Alex Chadwick
|
||||||
|
* Modified 2018, Maschell
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "ElfTools.h"
|
||||||
|
#include "ModuleData.h"
|
||||||
|
#include "ModuleLoader.h"
|
||||||
|
#include "utils/StringTools.h"
|
||||||
|
#include "common/retain_vars.h"
|
||||||
|
|
||||||
|
ModuleLoader * ModuleLoader::instance = NULL;
|
||||||
|
|
||||||
|
std::vector<ModuleInformation *> ModuleLoader::getModuleInformation(const char * path){
|
||||||
|
std::vector<ModuleInformation *> result;
|
||||||
|
struct dirent *dp;
|
||||||
|
DIR *dfd = NULL;
|
||||||
|
|
||||||
|
if(path == NULL){
|
||||||
|
DEBUG_FUNCTION_LINE("Path was NULL");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((dfd = opendir(path)) == NULL){
|
||||||
|
DEBUG_FUNCTION_LINE("Couldn't open dir %s",path);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((dp = readdir(dfd)) != NULL){
|
||||||
|
struct stat stbuf ;
|
||||||
|
std::string full_file_path = StringTools::strfmt("%s/%s",path,dp->d_name);
|
||||||
|
StringTools::RemoveDoubleSlashs(full_file_path);
|
||||||
|
if( stat(full_file_path.c_str(),&stbuf ) == -1 ){
|
||||||
|
DEBUG_FUNCTION_LINE("Unable to stat file: %s\n",full_file_path.c_str()) ;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ( stbuf.st_mode & S_IFMT ) == S_IFDIR ){ // Skip directories
|
||||||
|
continue;
|
||||||
|
}else{
|
||||||
|
DEBUG_FUNCTION_LINE("Found file: %s\n",full_file_path.c_str()) ;
|
||||||
|
ModuleInformation * module = ModuleInformation::loadModuleInformation(full_file_path);
|
||||||
|
if(module != NULL){
|
||||||
|
DEBUG_FUNCTION_LINE("Found plugin %s by %s. Size: %d kb \n",module->getName().c_str(),module->getAuthor().c_str(),module->getSize()/1024) ;
|
||||||
|
result.push_back(module);
|
||||||
|
} else {
|
||||||
|
DEBUG_FUNCTION_LINE("%s is not a valid plugin\n",full_file_path.c_str()) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModuleLoader::loadAndLinkModules(std::vector<ModuleInformation *> moduleInformation){
|
||||||
|
std::vector<ModuleData *> loadedModules;
|
||||||
|
for(size_t i = 0;i < moduleInformation.size(); i++){
|
||||||
|
DEBUG_FUNCTION_LINE("loadAndLinkModules for %d\n",i) ;
|
||||||
|
ModuleInformation * cur_info = moduleInformation[i];
|
||||||
|
ModuleData * moduleData = loadAndLinkModule(cur_info);
|
||||||
|
if(moduleData == NULL){
|
||||||
|
DEBUG_FUNCTION_LINE("loadAndLinkModules failed for %d\n",i) ;
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
loadedModules.push_back(moduleData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
copyModuleDataIntoGlobalStruct(loadedModules);
|
||||||
|
clearModuleData(loadedModules);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModuleLoader::clearModuleData(std::vector<ModuleData *> moduleData){
|
||||||
|
for(size_t i = 0;i < moduleData.size(); i++){
|
||||||
|
ModuleData * curModuleData = moduleData[i];
|
||||||
|
if(curModuleData != NULL){
|
||||||
|
delete curModuleData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ModuleData * ModuleLoader::loadAndLinkModule(ModuleInformation * moduleInformation){
|
||||||
|
DEBUG_FUNCTION_LINE("\n");
|
||||||
|
ModuleData * result = NULL;
|
||||||
|
int fd = -1;
|
||||||
|
Elf *elf = NULL;
|
||||||
|
|
||||||
|
if(moduleInformation == NULL){
|
||||||
|
DEBUG_FUNCTION_LINE("moduleInformation was NULL\n");
|
||||||
|
goto exit_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(moduleInformation->getSize() > ((u32) this->getCurrentStoreAddress() - (u32) this->startAddress)){
|
||||||
|
DEBUG_FUNCTION_LINE("Not enough space left to loader the plugin into memory\n");
|
||||||
|
goto exit_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check for compile errors */
|
||||||
|
if (elf_version(EV_CURRENT) == EV_NONE){
|
||||||
|
goto exit_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd = open(moduleInformation->getPath().c_str(), O_RDONLY, 0);
|
||||||
|
|
||||||
|
if (fd == -1){
|
||||||
|
DEBUG_FUNCTION_LINE("failed to open '%s' \n", moduleInformation->getPath().c_str());
|
||||||
|
goto exit_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
elf = elf_begin(fd, ELF_C_READ, NULL);
|
||||||
|
|
||||||
|
if (elf == NULL){
|
||||||
|
DEBUG_FUNCTION_LINE("elf was NULL\n");
|
||||||
|
goto exit_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_FUNCTION_LINE("\n");
|
||||||
|
result = new ModuleData(moduleInformation);
|
||||||
|
if(result == NULL){
|
||||||
|
DEBUG_FUNCTION_LINE("Failed to create object\n");
|
||||||
|
goto exit_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!this->loadAndLinkElf(result, elf, this->getCurrentStoreAddress())){
|
||||||
|
delete result;
|
||||||
|
result = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit_error:
|
||||||
|
if (elf != NULL){
|
||||||
|
elf_end(elf);
|
||||||
|
}
|
||||||
|
if (fd != -1){
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ModuleLoader::loadAndLinkElf(ModuleData * moduleData, Elf *elf, void * endAddress) {
|
||||||
|
if(moduleData == NULL || elf == NULL || endAddress == NULL){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_FUNCTION_LINE("\n");
|
||||||
|
|
||||||
|
u32 curAddress = (u32) endAddress;
|
||||||
|
|
||||||
|
Elf_Scn *scn;
|
||||||
|
size_t symtab_count, section_count, shstrndx, symtab_strndx, entries_count, hooks_count;
|
||||||
|
Elf32_Sym *symtab = NULL;
|
||||||
|
uint8_t **destinations = NULL;
|
||||||
|
wups_loader_entry_t *entries = NULL;
|
||||||
|
wups_loader_hook_t *hooks = NULL;
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
std::vector<wups_loader_entry_t *> entry_t_list;
|
||||||
|
std::vector<wups_loader_hook_t *> hook_t_list;
|
||||||
|
|
||||||
|
std::vector<EntryData *> entry_data_list;
|
||||||
|
std::vector<HookData *> hook_data_list;
|
||||||
|
|
||||||
|
if (!ElfTools::loadElfSymtab(elf, &symtab, &symtab_count, &symtab_strndx)){
|
||||||
|
goto exit_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(symtab == NULL){
|
||||||
|
goto exit_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elf_getshdrnum(elf, §ion_count) != 0){
|
||||||
|
goto exit_error;
|
||||||
|
}
|
||||||
|
if (elf_getshdrstrndx(elf, &shstrndx) != 0){
|
||||||
|
goto exit_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
destinations = (uint8_t **) malloc(sizeof(uint8_t *) * section_count);
|
||||||
|
|
||||||
|
for (scn = elf_nextscn(elf, NULL); scn != NULL; scn = elf_nextscn(elf, scn)) {
|
||||||
|
Elf32_Shdr *shdr;
|
||||||
|
|
||||||
|
shdr = elf32_getshdr(scn);
|
||||||
|
if (shdr == NULL){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((shdr->sh_type == SHT_PROGBITS || shdr->sh_type == SHT_NOBITS) &&
|
||||||
|
(shdr->sh_flags & SHF_ALLOC)) {
|
||||||
|
|
||||||
|
const char *name;
|
||||||
|
|
||||||
|
destinations[elf_ndxscn(scn)] = NULL;
|
||||||
|
|
||||||
|
name = elf_strptr(elf, shstrndx, shdr->sh_name);
|
||||||
|
if (name == NULL){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(name, ".wups.meta") == 0) {
|
||||||
|
continue;
|
||||||
|
} else if (strcmp(name, ".wups.load") == 0) {
|
||||||
|
if (entries != NULL){
|
||||||
|
goto exit_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
entries_count = shdr->sh_size / sizeof(wups_loader_entry_t);
|
||||||
|
entries = (wups_loader_entry_t *) malloc(sizeof(wups_loader_entry_t) * entries_count);
|
||||||
|
|
||||||
|
if (entries == NULL){
|
||||||
|
goto exit_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
destinations[elf_ndxscn(scn)] = (uint8_t *)entries;
|
||||||
|
if (!ElfTools::elfLoadSection(elf, scn, shdr, entries)){
|
||||||
|
goto exit_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
ElfTools::elfLoadSymbols(elf_ndxscn(scn), entries, symtab, symtab_count);
|
||||||
|
|
||||||
|
for(size_t i = 0;i< entries_count;i++){
|
||||||
|
entry_t_list.push_back(&entries[i]);
|
||||||
|
}
|
||||||
|
}else if (strcmp(name, ".wups.hooks") == 0) {
|
||||||
|
if (hooks != NULL){
|
||||||
|
goto exit_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
hooks_count = shdr->sh_size / sizeof(wups_loader_hook_t);
|
||||||
|
hooks = (wups_loader_hook_t *) malloc(sizeof(wups_loader_hook_t) * hooks_count);
|
||||||
|
|
||||||
|
if (hooks == NULL){
|
||||||
|
goto exit_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
destinations[elf_ndxscn(scn)] = (uint8_t *)hooks;
|
||||||
|
if (!ElfTools::elfLoadSection(elf, scn, shdr, hooks)){
|
||||||
|
goto exit_error;
|
||||||
|
}
|
||||||
|
ElfTools::elfLoadSymbols(elf_ndxscn(scn), hooks, symtab, symtab_count);
|
||||||
|
|
||||||
|
for(size_t i = 0;i< hooks_count;i++){
|
||||||
|
hook_t_list.push_back(&hooks[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
curAddress -= shdr->sh_size;
|
||||||
|
|
||||||
|
if (shdr->sh_addralign > 3){
|
||||||
|
curAddress = (u32)((int)curAddress & ~(shdr->sh_addralign - 1));
|
||||||
|
} else {
|
||||||
|
curAddress = (u32)((int)curAddress & ~3);
|
||||||
|
}
|
||||||
|
destinations[elf_ndxscn(scn)] = (uint8_t *) curAddress;
|
||||||
|
|
||||||
|
if((u32) curAddress < (u32) this->startAddress){
|
||||||
|
DEBUG_FUNCTION_LINE("Not enough space to load function %s into memory at %08X.\n",name,curAddress);
|
||||||
|
goto exit_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_FUNCTION_LINE("Copy section %s to %08X\n",name,curAddress);
|
||||||
|
if (!ElfTools::elfLoadSection(elf, scn, shdr, (void*) curAddress)){
|
||||||
|
goto exit_error;
|
||||||
|
}
|
||||||
|
ElfTools::elfLoadSymbols(elf_ndxscn(scn), (void*) curAddress, symtab, symtab_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entries == NULL){
|
||||||
|
goto exit_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (scn = elf_nextscn(elf, NULL); scn != NULL; scn = elf_nextscn(elf, scn)) {
|
||||||
|
Elf32_Shdr *shdr;
|
||||||
|
|
||||||
|
shdr = elf32_getshdr(scn);
|
||||||
|
if (shdr == NULL){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((shdr->sh_type == SHT_PROGBITS || shdr->sh_type == SHT_NOBITS) &&
|
||||||
|
(shdr->sh_flags & SHF_ALLOC) &&
|
||||||
|
destinations[elf_ndxscn(scn)] != NULL) {
|
||||||
|
|
||||||
|
if (!ElfTools::elfLink(elf, elf_ndxscn(scn), destinations[elf_ndxscn(scn)], symtab, symtab_count, symtab_strndx, true)){
|
||||||
|
goto exit_error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(size_t j=0;j<hook_t_list.size();j++){
|
||||||
|
wups_loader_hook_t * hook = hook_t_list[j];
|
||||||
|
|
||||||
|
DEBUG_FUNCTION_LINE("Saving hook of module \"%s\". Type: %08X, target: %08X\n",moduleData->getModuleInformation()->getName().c_str(),hook->type,(void*) hook->target);
|
||||||
|
HookData * hook_data = new HookData((void *) hook->target,hook->type);
|
||||||
|
moduleData->addHookData(hook_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(size_t j=0;j<entry_t_list.size();j++){
|
||||||
|
wups_loader_entry_t * entry = entry_t_list[j];
|
||||||
|
DEBUG_FUNCTION_LINE("Saving entry \"%s\" of module \"%s\". Library: %08X, target: %08X, call_addr: %08X\n",entry->_function.name,moduleData->getModuleInformation()->getName().c_str(),entry->_function.library,entry->_function.target, (void *) entry->_function.call_addr);
|
||||||
|
EntryData * entry_data = new EntryData(entry->_function.name,entry->_function.library, (void *) entry->_function.target, (void *) entry->_function.call_addr);
|
||||||
|
moduleData->addEntryData(entry_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->setCurrentStoreAddress((void *) curAddress);
|
||||||
|
|
||||||
|
result = true;
|
||||||
|
exit_error:
|
||||||
|
if (!result) DEBUG_FUNCTION_LINE("exit_error\n");
|
||||||
|
if (destinations != NULL){
|
||||||
|
free(destinations);
|
||||||
|
}
|
||||||
|
if (symtab != NULL){
|
||||||
|
free(symtab);
|
||||||
|
}
|
||||||
|
if (hooks != NULL){
|
||||||
|
free(hooks);
|
||||||
|
}
|
||||||
|
if (entries != NULL){
|
||||||
|
free(entries);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModuleLoader::copyModuleDataIntoGlobalStruct(std::vector<ModuleData *> modules){
|
||||||
|
// Reset data
|
||||||
|
memset((void*)&gbl_replacement_data,0,sizeof(gbl_replacement_data));
|
||||||
|
int module_index = 0;
|
||||||
|
// Copy data to global struct.
|
||||||
|
for(size_t i = 0; i< modules.size();i++){
|
||||||
|
ModuleData * cur_module = modules.at(i);
|
||||||
|
ModuleInformation * cur_moduleInformation = cur_module->getModuleInformation();
|
||||||
|
|
||||||
|
std::vector<EntryData *> entry_data_list = cur_module->getEntryDataList();
|
||||||
|
std::vector<HookData *> hook_data_list = cur_module->getHookDataList();
|
||||||
|
if(module_index >= MAXIMUM_MODULES ){
|
||||||
|
DEBUG_FUNCTION_LINE("Maximum of %d modules reached. %s won't be loaded!\n",MAXIMUM_MODULES,cur_moduleInformation->getName().c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(entry_data_list.size() > MAXIMUM_FUNCTION_PER_MODULE){
|
||||||
|
DEBUG_FUNCTION_LINE("Module %s would replace to many function (%d, maximum is %d). It won't be loaded.\n",cur_moduleInformation->getName().c_str(),entry_data_list.size(),MAXIMUM_FUNCTION_PER_MODULE);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(hook_data_list.size() > MAXIMUM_HOOKS_PER_MODULE){
|
||||||
|
DEBUG_FUNCTION_LINE("Module %s would set too many hooks (%d, maximum is %d). It won't be loaded.\n",cur_moduleInformation->getName().c_str(),hook_data_list.size(),MAXIMUM_HOOKS_PER_MODULE);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
replacement_data_module_t * module_data = &gbl_replacement_data.module_data[module_index];
|
||||||
|
|
||||||
|
strncpy(module_data->module_name,cur_moduleInformation->getName().c_str(),MAXIMUM_MODULE_NAME_LENGTH-1);
|
||||||
|
|
||||||
|
for(size_t j = 0; j < entry_data_list.size();j++){
|
||||||
|
replacement_data_function_t * function_data = &module_data->functions[j];
|
||||||
|
|
||||||
|
EntryData * cur_entry = entry_data_list[j];
|
||||||
|
DEBUG_FUNCTION_LINE("Adding entry \"%s\" for module \"%s\"\n",cur_entry->getName().c_str(),module_data->module_name);
|
||||||
|
|
||||||
|
//TODO: Warning/Error if string is too long.
|
||||||
|
strncpy(function_data->function_name,cur_entry->getName().c_str(),MAXIMUM_FUNCTION_NAME_LENGTH-1);
|
||||||
|
|
||||||
|
function_data->library = cur_entry->getLibrary();
|
||||||
|
function_data->replaceAddr = (u32) cur_entry->getReplaceAddress();
|
||||||
|
function_data->replaceCall = (u32) cur_entry->getReplaceCall();
|
||||||
|
|
||||||
|
module_data->number_used_functions++;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_FUNCTION_LINE("Entries for module \"%s\": %d\n",module_data->module_name,module_data->number_used_functions);
|
||||||
|
|
||||||
|
for(size_t j = 0; j < hook_data_list.size();j++){
|
||||||
|
replacement_data_hook_t * hook_data = &module_data->hooks[j];
|
||||||
|
|
||||||
|
HookData * hook_entry = hook_data_list[j];
|
||||||
|
|
||||||
|
DEBUG_FUNCTION_LINE("Set hook for module \"%s\" of type %08X to target %08X\n",module_data->module_name,hook_entry->getType(),(void*) hook_entry->getFunctionPointer());
|
||||||
|
hook_data->func_pointer = (void*) hook_entry->getFunctionPointer();
|
||||||
|
hook_data->type = hook_entry->getType();
|
||||||
|
module_data->number_used_hooks++;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG_FUNCTION_LINE("Hooks for module \"%s\": %d\n",module_data->module_name,module_data->number_used_hooks);
|
||||||
|
|
||||||
|
module_index++;
|
||||||
|
gbl_replacement_data.number_used_modules++;
|
||||||
|
}
|
||||||
|
}
|
151
loader/src/modules/ModuleLoader.h
Normal file
151
loader/src/modules/ModuleLoader.h
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
/* based on module.c
|
||||||
|
* by Alex Chadwick
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014, Alex Chadwick
|
||||||
|
* Modified 2018, Maschell
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _MODULE_LOADER_H_
|
||||||
|
#define _MODULE_LOADER_H_
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include "ModuleInformation.h"
|
||||||
|
#include "ModuleData.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <utils/utils.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#define PLUGIN_LOCATION_END_ADDRESS 0x01000000
|
||||||
|
|
||||||
|
class ModuleLoader{
|
||||||
|
|
||||||
|
public:
|
||||||
|
static ModuleLoader *getInstance() {
|
||||||
|
if(!instance){
|
||||||
|
instance = new ModuleLoader((void*)getApplicationEndAddr(),(void *)PLUGIN_LOCATION_END_ADDRESS);
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void destroyInstance() {
|
||||||
|
if(instance){
|
||||||
|
delete instance;
|
||||||
|
instance = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Parses the meta data of all plugins in the given directory.
|
||||||
|
|
||||||
|
\param path the path of the directory which should be scanned.
|
||||||
|
|
||||||
|
\return a list of ModuleInformation objects, one for each valid plugin.
|
||||||
|
**/
|
||||||
|
std::vector<ModuleInformation *> getModuleInformation(const char * path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Gets plugin information from the global struct.
|
||||||
|
|
||||||
|
\return a list of MetaInformation objects for all plugins currently loaded and linked (relocated). Will only contain
|
||||||
|
plugin which are still on the sd card.
|
||||||
|
**/
|
||||||
|
//std::vector<ModuleInformation *> getModulesLoadedInMemory();
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Takes a list of modules that should be linked (relocated) loaded into the memory.
|
||||||
|
The function that should be replaced will be replaced in the order of the given plugin list.
|
||||||
|
So two plugin will override the same function, the plugin first in this list will override the function first.
|
||||||
|
Also the hooks of the plugins will be called in the order their plugin where passed to this method.
|
||||||
|
|
||||||
|
\param A list of plugin that should be linked (relocated) an loaded into memory
|
||||||
|
**/
|
||||||
|
void loadAndLinkModules(std::vector<ModuleInformation *> moduleInformation);
|
||||||
|
private:
|
||||||
|
ModuleLoader(void * startAddress, void * endAddress){
|
||||||
|
// TODO: Check if endAddress > startAddress.
|
||||||
|
this->startAddress = startAddress;
|
||||||
|
this->endAddress = endAddress;
|
||||||
|
this->currentStoreAddress = endAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
~ModuleLoader(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static ModuleLoader *instance;
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Iterates through the vector and delete all it's elements
|
||||||
|
|
||||||
|
\param A list of ModuleData* that should be deleted.
|
||||||
|
**/
|
||||||
|
void clearModuleData(std::vector<ModuleData *> moduleData);
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Load
|
||||||
|
|
||||||
|
\param moduleInformation a ModuleInformation object of the plugin that should be linked (relocated) and loaded.
|
||||||
|
|
||||||
|
\return NULL on error. On success it will return a ModuleData object.
|
||||||
|
**/
|
||||||
|
ModuleData * loadAndLinkModule(ModuleInformation * moduleInformation);
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Loads a plugin into memory (in the startAddress/endAddress range defined in this loader) and relocates it.
|
||||||
|
Modifies the moduleData param. Adds loaded functions and hooks.
|
||||||
|
\param moduleData object where the result should be stored
|
||||||
|
\param elf source elf from where the sections will be loaded
|
||||||
|
\param storeAddressEnd the address where the plugin data will be stored in memory. Saving BACKWARD.
|
||||||
|
|
||||||
|
**/
|
||||||
|
bool loadAndLinkElf(ModuleData * moduleData, Elf *elf, void * storeAddressEnd);
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Copies the needed information into a global, persistent struct. This struct holds information on which
|
||||||
|
function should be override in which order and which hook should be called.
|
||||||
|
\param modules list of modules that should be used.
|
||||||
|
|
||||||
|
**/
|
||||||
|
void copyModuleDataIntoGlobalStruct(std::vector<ModuleData *> modules);
|
||||||
|
|
||||||
|
void * getCurrentStoreAddress(){
|
||||||
|
return this->currentStoreAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setCurrentStoreAddress(void * addr){
|
||||||
|
this->currentStoreAddress = addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void * startAddress = NULL;
|
||||||
|
void * endAddress = NULL;
|
||||||
|
void * currentStoreAddress = NULL;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user