From 9a15e549c74026fe8a57dae2a063463ab34ac97f Mon Sep 17 00:00:00 2001 From: Maschell Date: Mon, 18 Jun 2018 22:22:11 +0200 Subject: [PATCH] Add support for handling relocations which leads to high addresses (and require a big jump) --- loader/src/plugin/DynamicLinkingHelper.cpp | 45 ++++++++++++++++----- loader/src/plugin/ElfTools.cpp | 2 +- loader/src/plugin/dynamic_linking_defines.h | 1 + 3 files changed, 38 insertions(+), 10 deletions(-) diff --git a/loader/src/plugin/DynamicLinkingHelper.cpp b/loader/src/plugin/DynamicLinkingHelper.cpp index f31015a..beff42c 100644 --- a/loader/src/plugin/DynamicLinkingHelper.cpp +++ b/loader/src/plugin/DynamicLinkingHelper.cpp @@ -58,19 +58,19 @@ dyn_linking_import_t * DynamicLinkingHelper::getOrAddImport(const char* importNa return result; } -bool DynamicLinkingHelper::addReloationEntry(RelocationData * relocationData){ +bool DynamicLinkingHelper::addReloationEntry(RelocationData * relocationData) { return addReloationEntry(relocationData->getType(), relocationData->getOffset(), relocationData->getAddend(), relocationData->getDestination(), relocationData->getName(), relocationData->getImportRPLInformation()); } -bool DynamicLinkingHelper::addReloationEntry(char type, size_t offset, int addend, void *destination, std::string name, ImportRPLInformation * rplInfo){ +bool DynamicLinkingHelper::addReloationEntry(char type, size_t offset, int addend, void *destination, std::string name, ImportRPLInformation * rplInfo) { dyn_linking_import_t * importInfoGbl = DynamicLinkingHelper::getOrAddImport(rplInfo->getName().c_str(),rplInfo->isData()); - if(importInfoGbl == NULL){ + if(importInfoGbl == NULL) { DEBUG_FUNCTION_LINE("Getting import info failed. Probably maximum of %d rpl files to import reached.\n",DYN_LINK_IMPORT_LIST_LENGTH); return false; } dyn_linking_function_t * functionInfo = DynamicLinkingHelper::getOrAddFunctionEntryByName(name.c_str()); - if(functionInfo == NULL){ + if(functionInfo == NULL) { DEBUG_FUNCTION_LINE("Getting import info failed. Probably maximum of %d function to be relocated reached.\n",DYN_LINK_FUNCTION_LIST_LENGTH); return false; } @@ -78,8 +78,8 @@ bool DynamicLinkingHelper::addReloationEntry(char type, size_t offset, int adden return addReloationEntry(type, offset, addend, destination, functionInfo, importInfoGbl); } -bool DynamicLinkingHelper::addReloationEntry(char type, size_t offset, int addend, void *destination, dyn_linking_function_t * functionName, dyn_linking_import_t * importInfo){ - for(int i = 0; i < DYN_LINK_RELOCATION_LIST_LENGTH; i++) { +bool DynamicLinkingHelper::addReloationEntry(char type, size_t offset, int addend, void *destination, dyn_linking_function_t * functionName, dyn_linking_import_t * importInfo) { + for(int i = 0; i < DYN_LINK_RELOCATION_LIST_LENGTH; i++) { dyn_linking_relocation_entry_t * curEntry = &gbl_dyn_linking_data.entries[i]; if(curEntry->functionEntry != NULL) { continue; @@ -143,15 +143,42 @@ bool DynamicLinkingHelper::fillRelocations(std::vectoraddress) { DEBUG_FUNCTION_LINE("OSDynLoad_FindExport failed for %s on import %s\n", functionEntry->functionName,importEntry->importName); return false; - }else{ + } else { //DEBUG_FUNCTION_LINE("OSDynLoad_FindExport successful for %s on import %s: %08X\n",functionEntry->functionName,importEntry->importName,functionEntry->address); + + /* + 90 61 ff e0 stw r3,-32(r1) + 3c 60 12 34 lis r3,4660 + 60 63 56 78 ori r3,r3,22136 + 7c 69 03 a6 mtctr r3 + 80 61 ff e0 lwz r3,-32(r1) + 4e 80 04 20 bctr*/ + functionEntry->big_jump[0] = 0x9061FFE0; + functionEntry->big_jump[1] = 0x3C600000 | ((((u32) functionEntry->address) >> 16) & 0x0000FFFF); // lis r3, real_addr@h + functionEntry->big_jump[2] = 0x60630000 | (((u32) functionEntry->address) & 0x0000ffff); // ori r3, r3, real_addr@l + functionEntry->big_jump[3] = 0x7C6903A6; // mtctr r3 + functionEntry->big_jump[4] = 0x8061FFE0; // lwz r3,-32(r1) + functionEntry->big_jump[5] = 0x4E800420; // bctr + DCFlushRange((void*)functionEntry->big_jump, sizeof(functionEntry->big_jump)); + ICInvalidateRange((unsigned char*)functionEntry->big_jump, sizeof(functionEntry->big_jump)); + + //DEBUG_FUNCTION_LINE("Created jump code address: %08X big_jump: %08X for %s \n",functionEntry->address,functionEntry->big_jump,functionEntry->functionName); + //dumpHex(functionEntry->big_jump,sizeof(functionEntry->big_jump)); } } else { //DEBUG_FUNCTION_LINE("We cached the address of function %s :%08X\n",functionEntry->functionName,functionEntry->address); } - //DEBUG_FUNCTION_LINE("We would link now: type: %02X offset: %08X addend: %d destination: %08X target: %08X for %s\n",curEntry->type, curEntry->offset, curEntry->addend, curEntry->destination, functionEntry->address,functionEntry->functionName); + + //DEBUG_FUNCTION_LINE("Linking: t: %02X o: %08X a: %d dest: %08X tar: %08X big_j: %08X\n",curEntry->type, curEntry->offset, curEntry->addend, curEntry->destination, functionEntry->address, (u32) functionEntry->big_jump); + DEBUG_FUNCTION_LINE("Resolving relocation to %s\n",functionEntry->functionName); - ElfTools::elfLinkOne(curEntry->type, curEntry->offset, curEntry->addend, curEntry->destination, (u32) functionEntry->address); + + if(!curEntry->importEntry->isData && (u32) functionEntry->address > 0x04000000) { + ElfTools::elfLinkOne(curEntry->type, curEntry->offset, curEntry->addend, curEntry->destination, (u32) functionEntry->big_jump); + } else { + ElfTools::elfLinkOne(curEntry->type, curEntry->offset, curEntry->addend, curEntry->destination, (u32) functionEntry->address); + } + } PluginLoader::flushCache(); diff --git a/loader/src/plugin/ElfTools.cpp b/loader/src/plugin/ElfTools.cpp index dbd65de..0bf0fab 100644 --- a/loader/src/plugin/ElfTools.cpp +++ b/loader/src/plugin/ElfTools.cpp @@ -442,7 +442,7 @@ bool ElfTools::elfLinkOne(char type, size_t offset, int addend, void *destinatio case R_PPC_ADDR16_HA: case R_PPC_SECTOFF_HA: case R_PPC_EMB_NADDR16_HA: { - *(short *)target = (value >> 16) + ((value >> 15) & 1); + *(short *)target = (((value >> 16) + ((value & 0x8000) ? 1 : 0))) & 0xFFFF; break; } case R_PPC_ADDR16_LO: diff --git a/loader/src/plugin/dynamic_linking_defines.h b/loader/src/plugin/dynamic_linking_defines.h index 15f40a2..7dbf5f2 100644 --- a/loader/src/plugin/dynamic_linking_defines.h +++ b/loader/src/plugin/dynamic_linking_defines.h @@ -35,6 +35,7 @@ extern "C" { typedef struct _dyn_linking_function_t { char functionName[DYN_LINK_FUNCTION_NAME_LENGTH+1]; void * address; + u32 big_jump[6]; } dyn_linking_function_t; typedef struct _dyn_linking_import_t {