diff --git a/loader/src/common/retain_vars.cpp b/loader/src/common/retain_vars.cpp index 3541a88..87df32e 100644 --- a/loader/src/common/retain_vars.cpp +++ b/loader/src/common/retain_vars.cpp @@ -12,3 +12,7 @@ int ntfs_mount_count __attribute__((section(".data"))) = 0; struct buffer_store drc_store __attribute__((section(".data"))); struct buffer_store tv_store __attribute__((section(".data"))); + + +char gbl_common_data[0x20000] __attribute__((section(".data"))); +char * gbl_common_data_ptr __attribute__((section(".data"))) = gbl_common_data; diff --git a/loader/src/plugin/ElfTools.cpp b/loader/src/plugin/ElfTools.cpp index 0bf0fab..3d3055c 100644 --- a/loader/src/plugin/ElfTools.cpp +++ b/loader/src/plugin/ElfTools.cpp @@ -268,8 +268,21 @@ bool ElfTools::elfLink(Elf *elf, size_t shndx, void *destination, Elf32_Sym *sym break; } case SHN_COMMON: { - DEBUG_FUNCTION_LINE("case SHN_COMMON\n"); - return false; + u32 align = symtab[symbol].st_value; + u32 size = symtab[symbol].st_size; + + uint32_t address = pluginData->getMemoryForCommonBySymbol(symbol, align, size); + if(address == NULL){ + DEBUG_FUNCTION_LINE("Failed to get memory for common relocation\n"); + return false; + } + + if (!ElfTools::elfLinkOne(ELF32_R_TYPE(rela[i].r_info), rela[i].r_offset,rela[i].r_addend, destination, address)) { + DEBUG_FUNCTION_LINE("elfLinkOne failed\n"); + return false; + } + + break; } case SHN_UNDEF: { if (allow_globals) { diff --git a/loader/src/plugin/PluginData.cpp b/loader/src/plugin/PluginData.cpp new file mode 100644 index 0000000..be62055 --- /dev/null +++ b/loader/src/plugin/PluginData.cpp @@ -0,0 +1,43 @@ +/**************************************************************************** + * Copyright (C) 2018 Maschell + * + * This program is free software: you can redistribute it and/or modify + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ****************************************************************************/ + +#include +#include +#include +#include "PluginData.h" +#include "PluginLoader.h" + +ImportRPLInformation * PluginData::getImportRPLInformationBySectionHeaderIndex(int section_header_index) { + for(size_t i = 0; i< importRPLInformation_list.size(); i++) { + if(importRPLInformation_list[i] != NULL && importRPLInformation_list[i]->getSectionHeaderIndex() == section_header_index) { + return importRPLInformation_list[i]; + } + } + return NULL; +} + +uint32_t PluginData::getMemoryForCommonBySymbol(size_t symbol, size_t align, size_t size) { + std::map::iterator it = memoryBySymbol.find(symbol); + if(it == memoryBySymbol.end()) { + memoryBySymbol[symbol] = PluginLoader::getInstance()->getMemoryFromDataSection(align, size); + DEBUG_FUNCTION_LINE("Setting value %08X\n",memoryBySymbol.find(symbol)->second); + } else { + DEBUG_FUNCTION_LINE("Using cached value %08X\n",memoryBySymbol.find(symbol)->second); + } + + return memoryBySymbol.find(symbol)->second; +} diff --git a/loader/src/plugin/PluginData.h b/loader/src/plugin/PluginData.h index ede5015..6f7ebd2 100644 --- a/loader/src/plugin/PluginData.h +++ b/loader/src/plugin/PluginData.h @@ -20,6 +20,7 @@ #include #include +#include #include "FunctionData.h" #include "HookData.h" #include "PluginInformation.h" @@ -108,19 +109,15 @@ public: \return A pointer to the corresponding ImportRPLInformation, return NULL if no corresponding information was found. **/ - ImportRPLInformation * getImportRPLInformationBySectionHeaderIndex(int section_header_index) { - for(size_t i = 0; i< importRPLInformation_list.size(); i++) { - if(importRPLInformation_list[i] != NULL && importRPLInformation_list[i]->getSectionHeaderIndex() == section_header_index) { - return importRPLInformation_list[i]; - } - } - return NULL; - } + ImportRPLInformation * getImportRPLInformationBySectionHeaderIndex(int section_header_index); + PluginInformation * getPluginInformation() { return pluginInformation; } + uint32_t getMemoryForCommonBySymbol(size_t symbol, size_t align, size_t size); + private: PluginInformation * pluginInformation; @@ -129,6 +126,8 @@ private: std::vector hook_data_list; std::vector relocation_data_list; std::vector importRPLInformation_list; + + std::map memoryBySymbol; }; diff --git a/loader/src/plugin/PluginLoader.cpp b/loader/src/plugin/PluginLoader.cpp index f7e1f34..d463ad9 100644 --- a/loader/src/plugin/PluginLoader.cpp +++ b/loader/src/plugin/PluginLoader.cpp @@ -489,3 +489,18 @@ void PluginLoader::copyPluginDataIntoGlobalStruct(std::vector plug DCFlushRange((void*)&gbl_replacement_data,sizeof(gbl_replacement_data)); ICInvalidateRange((void*)&gbl_replacement_data,sizeof(gbl_replacement_data)); } + +uint32_t PluginLoader::getMemoryFromDataSection(size_t align, size_t size) { + uint32_t ptr = (u32)gbl_common_data_ptr; + ptr = (ptr + (align - 1)) & -align; // Round up to align boundary + uint32_t result = ptr; + + if((result + size) >= (ptr + sizeof(gbl_common_data))) { + DEBUG_FUNCTION_LINE("No more space =( %08X > %08X\n",(result + size),(ptr + sizeof(gbl_common_data))); + return 0; + } + ptr += size; + gbl_common_data_ptr = (char *) ptr; + + return result; +} diff --git a/loader/src/plugin/PluginLoader.h b/loader/src/plugin/PluginLoader.h index edc23af..03aa996 100644 --- a/loader/src/plugin/PluginLoader.h +++ b/loader/src/plugin/PluginLoader.h @@ -27,8 +27,8 @@ #define _PLUGIN_LOADER_H_ #include -#include "PluginInformation.h" #include "PluginData.h" +#include "PluginInformation.h" #include "dynamic_libs/os_types.h" #include "dynamic_libs/os_functions.h" @@ -42,6 +42,8 @@ extern "C" { } #endif +extern char gbl_common_data[0x20000]; +extern char * gbl_common_data_ptr; #define PLUGIN_LOCATION_END_ADDRESS 0x01000000 @@ -123,6 +125,8 @@ public: this->currentStoreAddress = endAddress; } + uint32_t getMemoryFromDataSection(size_t align, size_t size); + private: PluginLoader(void * startAddress, void * endAddress) { // TODO: Check if endAddress > startAddress.