mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-07-06 15:22:57 +12:00
Stub fixing, add indexed/anonymous imports
TODO: remove debug printfs
This commit is contained in:
parent
4cd9c6c77e
commit
60a632b365
1 changed files with 107 additions and 14 deletions
|
@ -75,6 +75,12 @@ namespace NamedExportTable {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace IndexedExportTable {
|
||||||
|
enum : u32 {
|
||||||
|
SegmentOffset = 0,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
namespace NamedImportTable {
|
namespace NamedImportTable {
|
||||||
enum : u32 {
|
enum : u32 {
|
||||||
NameOffset = 0,
|
NameOffset = 0,
|
||||||
|
@ -99,8 +105,10 @@ namespace AnonymousImportTable {
|
||||||
namespace ImportModuleTable {
|
namespace ImportModuleTable {
|
||||||
enum : u32 {
|
enum : u32 {
|
||||||
NameOffset = 0,
|
NameOffset = 0,
|
||||||
IndexedOffset = 8,
|
IndexedOffset = 4,
|
||||||
AnonymousOffset = 16,
|
IndexedNum = 8,
|
||||||
|
AnonymousOffset = 12,
|
||||||
|
AnonymousNum = 16,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -138,6 +146,12 @@ public:
|
||||||
CRO(Memory &mem, u32 croPointer, bool isCRO) : mem(mem), croPointer(croPointer), isCRO(isCRO) {}
|
CRO(Memory &mem, u32 croPointer, bool isCRO) : mem(mem), croPointer(croPointer), isCRO(isCRO) {}
|
||||||
~CRO() = default;
|
~CRO() = default;
|
||||||
|
|
||||||
|
std::string getModuleName() {
|
||||||
|
const CROHeaderEntry moduleName = getHeaderEntry(CROHeader::ModuleNameOffset);
|
||||||
|
|
||||||
|
return mem.readString(moduleName.offset, moduleName.size);
|
||||||
|
}
|
||||||
|
|
||||||
u32 getNextCRO() {
|
u32 getNextCRO() {
|
||||||
return mem.read32(croPointer + CROHeader::NextCRO);
|
return mem.read32(croPointer + CROHeader::NextCRO);
|
||||||
}
|
}
|
||||||
|
@ -262,6 +276,17 @@ public:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool fix(u32 fixLevel) {
|
||||||
|
if (fixLevel != 0) {
|
||||||
|
mem.write8(croPointer + CROHeader::ID + 0, 'F');
|
||||||
|
mem.write8(croPointer + CROHeader::ID + 1, 'I');
|
||||||
|
mem.write8(croPointer + CROHeader::ID + 2, 'X');
|
||||||
|
mem.write8(croPointer + CROHeader::ID + 3, 'D');
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Modifies CRO offsets to point at virtual addresses
|
// Modifies CRO offsets to point at virtual addresses
|
||||||
bool rebase(u32 loadedCRS, u32 mapVaddr, u32 dataVaddr, u32 bssVaddr) {
|
bool rebase(u32 loadedCRS, u32 mapVaddr, u32 dataVaddr, u32 bssVaddr) {
|
||||||
rebaseHeader(mapVaddr);
|
rebaseHeader(mapVaddr);
|
||||||
|
@ -280,11 +305,14 @@ public:
|
||||||
rebaseIndexedImportTable(mapVaddr);
|
rebaseIndexedImportTable(mapVaddr);
|
||||||
rebaseAnonymousImportTable(mapVaddr);
|
rebaseAnonymousImportTable(mapVaddr);
|
||||||
|
|
||||||
relocateInternalSymbols(oldDataVaddr);
|
|
||||||
|
|
||||||
// Note: Citra relocates static anonymous symbols and exit symbols only if the file is not a CRS
|
// Note: Citra relocates static anonymous symbols and exit symbols only if the file is not a CRS
|
||||||
if (isCRO) {
|
if (isCRO) {
|
||||||
relocateStaticAnonymousSymbols();
|
relocateStaticAnonymousSymbols();
|
||||||
|
}
|
||||||
|
|
||||||
|
relocateInternalSymbols(oldDataVaddr);
|
||||||
|
|
||||||
|
if (isCRO) {
|
||||||
relocateExitSymbols(loadedCRS);
|
relocateExitSymbols(loadedCRS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -571,7 +599,71 @@ public:
|
||||||
const CROHeaderEntry importModuleTable = getHeaderEntry(CROHeader::ImportModuleTableOffset);
|
const CROHeaderEntry importModuleTable = getHeaderEntry(CROHeader::ImportModuleTableOffset);
|
||||||
|
|
||||||
for (u32 importModule = 0; importModule < importModuleTable.size; importModule++) {
|
for (u32 importModule = 0; importModule < importModuleTable.size; importModule++) {
|
||||||
Helpers::panic("TODO: import modules");
|
const u32 nameOffset = mem.read32(importModuleTable.offset + 20 * importModule + ImportModuleTable::NameOffset);
|
||||||
|
|
||||||
|
const std::string importModuleName = mem.readString(nameOffset, importStringSize);
|
||||||
|
|
||||||
|
std::printf("Importing module \"%s\"\n", importModuleName.c_str());
|
||||||
|
|
||||||
|
// Find import module
|
||||||
|
u32 currentCROPointer = loadedCRS;
|
||||||
|
while (currentCROPointer != 0) {
|
||||||
|
CRO cro(mem, currentCROPointer, true);
|
||||||
|
|
||||||
|
if (importModuleName.compare(cro.getModuleName()) == 0) {
|
||||||
|
std::printf("Found module \"%s\"\n", importModuleName.c_str());
|
||||||
|
|
||||||
|
// Import indexed symbols
|
||||||
|
const CROHeaderEntry indexedExportTable = cro.getHeaderEntry(CROHeader::IndexedExportTableOffset);
|
||||||
|
|
||||||
|
const u32 indexedOffset = mem.read32(importModuleTable.offset + 20 * importModule + ImportModuleTable::IndexedOffset);
|
||||||
|
const u32 indexedNum = mem.read32(importModuleTable.offset + 20 * importModule + ImportModuleTable::IndexedNum);
|
||||||
|
|
||||||
|
std::printf("Importing indexed symbols (num = %u, offset = %X)\n", indexedNum, indexedOffset);
|
||||||
|
|
||||||
|
for (u32 indexedImport = 0; indexedImport < indexedNum; indexedImport++) {
|
||||||
|
if (indexedOffset == 0) {
|
||||||
|
Helpers::panic("Indexed symbol offset is NULL");
|
||||||
|
}
|
||||||
|
|
||||||
|
const u32 importIndex = mem.read32(indexedOffset + 8 * indexedImport + IndexedImportTable::Index);
|
||||||
|
|
||||||
|
const u32 segmentOffset = mem.read32(indexedExportTable.offset + 4 * importIndex + IndexedExportTable::SegmentOffset);
|
||||||
|
const u32 relocationOffset = mem.read32(indexedOffset + 8 * indexedImport + IndexedImportTable::RelocationOffset);
|
||||||
|
|
||||||
|
std::printf("Indexed import %u, index = %u, segment offset = %X, relocation offset = %X\n", indexedImport, importIndex, segmentOffset, relocationOffset);
|
||||||
|
|
||||||
|
patchBatch(relocationOffset, cro.getSegmentAddr(segmentOffset));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Import anonymous symbols
|
||||||
|
const u32 anonymousOffset = mem.read32(importModuleTable.offset + 20 * importModule + ImportModuleTable::AnonymousOffset);
|
||||||
|
const u32 anonymousNum = mem.read32(importModuleTable.offset + 20 * importModule + ImportModuleTable::AnonymousNum);
|
||||||
|
|
||||||
|
std::printf("Importing anonymous symbols (num = %u, offset = %X)\n", anonymousNum, anonymousOffset);
|
||||||
|
|
||||||
|
for (u32 anonymousImport = 0; anonymousImport < anonymousNum; anonymousImport++) {
|
||||||
|
if (anonymousOffset == 0) {
|
||||||
|
Helpers::panic("Anonymous symbol offset is NULL");
|
||||||
|
}
|
||||||
|
|
||||||
|
const u32 segmentOffset = mem.read32(anonymousOffset + 8 * anonymousImport + AnonymousImportTable::SegmentOffset);
|
||||||
|
const u32 relocationOffset = mem.read32(anonymousOffset + 8 * anonymousImport + AnonymousImportTable::RelocationOffset);
|
||||||
|
|
||||||
|
std::printf("Anonymous import %u, segment offset = %X, relocation offset = %X\n", anonymousImport, segmentOffset, relocationOffset);
|
||||||
|
|
||||||
|
patchBatch(relocationOffset, cro.getSegmentAddr(segmentOffset));
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentCROPointer = cro.getNextCRO();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentCROPointer == 0) {
|
||||||
|
Helpers::warn("Unable to find import module %s\n", importModuleName.c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -685,15 +777,15 @@ void LDRService::initialize(u32 messagePointer) {
|
||||||
Helpers::panic("CRS too small\n");
|
Helpers::panic("CRS too small\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((size & mem.pageMask) != 0) {
|
if (!mem.isAligned(size)) {
|
||||||
Helpers::panic("Unaligned CRS size\n");
|
Helpers::panic("Unaligned CRS size\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((crsPointer & mem.pageMask) != 0) {
|
if (!mem.isAligned(crsPointer)) {
|
||||||
Helpers::panic("Unaligned CRS pointer\n");
|
Helpers::panic("Unaligned CRS pointer\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((mapVaddr & mem.pageMask) != 0) {
|
if (!mem.isAligned(mapVaddr)) {
|
||||||
Helpers::panic("Unaligned CRS output vaddr\n");
|
Helpers::panic("Unaligned CRS output vaddr\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -710,7 +802,7 @@ void LDRService::initialize(u32 messagePointer) {
|
||||||
Helpers::panic("Failed to rebase CRS");
|
Helpers::panic("Failed to rebase CRS");
|
||||||
}
|
}
|
||||||
|
|
||||||
//kernel.clearInstructionCache();
|
kernel.clearInstructionCache();
|
||||||
|
|
||||||
loadedCRS = crsPointer;
|
loadedCRS = crsPointer;
|
||||||
|
|
||||||
|
@ -740,22 +832,22 @@ void LDRService::loadCRO(u32 messagePointer, bool isNew) {
|
||||||
const u32 fixLevel = mem.read32(messagePointer + 40);
|
const u32 fixLevel = mem.read32(messagePointer + 40);
|
||||||
const Handle process = mem.read32(messagePointer + 52);
|
const Handle process = mem.read32(messagePointer + 52);
|
||||||
|
|
||||||
log("LDR_RO::LoadCRO (isNew = %d, buffer = %08X, vaddr = %08X, size = %08X, .data vaddr = %08X, .data size = %08X, .bss vaddr = %08X, .bss size = %08X, auto link = %d, fix level = %X, process = %X)\n", isNew, croPointer, mapVaddr, size, dataVaddr, dataSize, bssVaddr, bssSize, autoLink, fixLevel, process);
|
std::printf("LDR_RO::LoadCRO (isNew = %d, buffer = %08X, vaddr = %08X, size = %08X, .data vaddr = %08X, .data size = %08X, .bss vaddr = %08X, .bss size = %08X, auto link = %d, fix level = %X, process = %X)\n", isNew, croPointer, mapVaddr, size, dataVaddr, dataSize, bssVaddr, bssSize, autoLink, fixLevel, process);
|
||||||
|
|
||||||
// Sanity checks
|
// Sanity checks
|
||||||
if (size < CRO_HEADER_SIZE) {
|
if (size < CRO_HEADER_SIZE) {
|
||||||
Helpers::panic("CRO too small\n");
|
Helpers::panic("CRO too small\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((size & mem.pageMask) != 0) {
|
if (!mem.isAligned(size)) {
|
||||||
Helpers::panic("Unaligned CRO size\n");
|
Helpers::panic("Unaligned CRO size\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((croPointer & mem.pageMask) != 0) {
|
if (!mem.isAligned(croPointer)) {
|
||||||
Helpers::panic("Unaligned CRO pointer\n");
|
Helpers::panic("Unaligned CRO pointer\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((mapVaddr & mem.pageMask) != 0) {
|
if (!mem.isAligned(mapVaddr)) {
|
||||||
Helpers::panic("Unaligned CRO output vaddr\n");
|
Helpers::panic("Unaligned CRO output vaddr\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -779,8 +871,9 @@ void LDRService::loadCRO(u32 messagePointer, bool isNew) {
|
||||||
cro.registerCRO(loadedCRS, autoLink);
|
cro.registerCRO(loadedCRS, autoLink);
|
||||||
|
|
||||||
// TODO: add fixing
|
// TODO: add fixing
|
||||||
|
cro.fix(fixLevel);
|
||||||
|
|
||||||
//kernel.clearInstructionCache();
|
kernel.clearInstructionCache();
|
||||||
|
|
||||||
if (isNew) {
|
if (isNew) {
|
||||||
mem.write32(messagePointer, IPC::responseHeader(0x9, 2, 0));
|
mem.write32(messagePointer, IPC::responseHeader(0x9, 2, 0));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue