Fixed build and a bug

This commit is contained in:
Subv 2015-12-25 09:15:27 -05:00 committed by Sean Maas
parent 5c343b6169
commit 4caae2df5e

View File

@ -142,7 +142,7 @@ struct CROHeader {
u8 GetImportPatchesSegmentOffset() { return segment_offset >> 4; } u8 GetImportPatchesSegmentOffset() { return segment_offset >> 4; }
SegmentTableEntry* GetSegmentTableEntry(u32 index, bool relocated = false); SegmentTableEntry* GetSegmentTableEntry(u32 index, bool relocated = false);
void RelocateSegmentsTable(u32 base, u32 data_section0, u32 data_section1); void RelocateSegmentsTable(u32 base, u32 data_section0, u32 data_section1, u32& prev_data_section0);
ExportTableEntry* GetExportTableEntry(u32 index); ExportTableEntry* GetExportTableEntry(u32 index);
void RelocateExportsTable(u32 base); void RelocateExportsTable(u32 base);
@ -183,10 +183,12 @@ SegmentTableEntry* CROHeader::GetSegmentTableEntry(u32 index, bool relocated) {
return reinterpret_cast<SegmentTableEntry*>(reinterpret_cast<u8*>(this) + segment_table_offset + sizeof(SegmentTableEntry) * index); return reinterpret_cast<SegmentTableEntry*>(reinterpret_cast<u8*>(this) + segment_table_offset + sizeof(SegmentTableEntry) * index);
} }
void CROHeader::RelocateSegmentsTable(u32 base, u32 data_section0, u32 data_section1) { void CROHeader::RelocateSegmentsTable(u32 base, u32 data_section0, u32 data_section1, u32& prev_data_section0) {
prev_data_section0 = 0;
for (int i = 0; i < segment_table_num; ++i) { for (int i = 0; i < segment_table_num; ++i) {
SegmentTableEntry* entry = GetSegmentTableEntry(i); SegmentTableEntry* entry = GetSegmentTableEntry(i);
if (entry->segment_id == 2) { if (entry->segment_id == 2) {
prev_data_section0 = entry->segment_offset;
entry->segment_offset = data_section0; entry->segment_offset = data_section0;
} else if (entry->segment_id == 3) { } else if (entry->segment_id == 3) {
entry->segment_offset = data_section1; entry->segment_offset = data_section1;
@ -292,13 +294,17 @@ void CROHeader::RelocateOffsets(u32 base) {
unk_offset += base; unk_offset += base;
} }
static void ApplyPatch(Patch* patch, u32 patch_base, u32 patch_address) { static void ApplyPatch(Patch* patch, u32 patch_base, u32 patch_address, u32* patch_address1 = nullptr) {
if (!patch_address1)
patch_address1 = &patch_address;
switch (patch->type) { switch (patch->type) {
case 2: case 2:
Memory::Write32(patch_address, patch_base + patch->x); Memory::Write32(patch_address, patch_base + patch->x);
break; break;
case 3: case 3:
Memory::Write32(patch_address, patch_base + patch->x - patch_address); Memory::Write32(patch_address, patch_base + patch->x - *patch_address1);
break; break;
default: default:
LOG_CRITICAL(Service_APT, "Unknown patch type %u", patch->type); LOG_CRITICAL(Service_APT, "Unknown patch type %u", patch->type);
@ -338,14 +344,22 @@ static void ApplyUnk3Patches(CROHeader* header, u32 base) {
} }
} }
static void ApplyRelocationPatches(CROHeader* header, u32 base) { static void ApplyRelocationPatches(CROHeader* header, u32 base, u32 section0) {
for (int i = 0; i < header->relocation_patches_num; ++i) { for (int i = 0; i < header->relocation_patches_num; ++i) {
Patch* patch = header->GetRelocationPatchEntry(i); Patch* patch = header->GetRelocationPatchEntry(i);
u32 segment_id = patch->GetTargetSegment(); u32 segment_id = patch->GetTargetSegment();
SegmentTableEntry* target_segment = header->GetSegmentTableEntry(segment_id); SegmentTableEntry* target_segment = header->GetSegmentTableEntry(segment_id);
u32 target_segment_offset = target_segment->segment_offset;
if (segment_id == 2)
target_segment_offset = section0;
SegmentTableEntry* base_segment = header->GetSegmentTableEntry(patch->unk); SegmentTableEntry* base_segment = header->GetSegmentTableEntry(patch->unk);
u32 patch_address = target_segment->segment_offset + patch->GetSegmentOffset();
ApplyPatch(patch, base_segment->segment_offset, patch_address); u32 patch_address = target_segment_offset + patch->GetSegmentOffset();
u32 patch_address1 = target_segment->segment_offset + patch->GetSegmentOffset();
ApplyPatch(patch, base_segment->segment_offset, patch_address, &patch_address1);
} }
} }
@ -357,13 +371,13 @@ static void ApplyExitPatches(CROHeader* header, u32 base) {
char* entry_name = reinterpret_cast<char*>(Memory::GetPointer(entry->name_offset)); char* entry_name = reinterpret_cast<char*>(Memory::GetPointer(entry->name_offset));
if (!strcmp(entry_name, "__aeabi_atexit")) { if (!strcmp(entry_name, "__aeabi_atexit")) {
// Only apply these patches if some previous CRO exports "nnroAeabiAtexit_" // Only apply these patches if some previous CRO exports "nnroAeabiAtexit_"
auto export = loaded_exports.find("nnroAeabiAtexit_"); auto export_ = loaded_exports.find("nnroAeabiAtexit_");
if (export == loaded_exports.end()) if (export_ == loaded_exports.end())
return; return;
// Patch it! // Patch it!
Patch* first_patch = reinterpret_cast<Patch*>(Memory::GetPointer(entry->symbol_offset)); Patch* first_patch = reinterpret_cast<Patch*>(Memory::GetPointer(entry->symbol_offset));
ApplyListPatches(header, first_patch, export->second.cro_offset); ApplyListPatches(header, first_patch, export_->second.cro_offset);
return; return;
} }
} }
@ -377,11 +391,11 @@ static void ApplyImportTable1Patches(CROHeader* header, u32 base, bool relocated
if (!patch->unk2) { if (!patch->unk2) {
// The name offset is already relocated // The name offset is already relocated
std::string entry_name = reinterpret_cast<char*>(Memory::GetPointer(entry->name_offset)); std::string entry_name = reinterpret_cast<char*>(Memory::GetPointer(entry->name_offset));
auto export = loaded_exports.find(entry_name); auto export_ = loaded_exports.find(entry_name);
if (export == loaded_exports.end()) if (export_ == loaded_exports.end())
continue; continue;
u32 patch_base = export->second.cro_offset; u32 patch_base = export_->second.cro_offset;
Patch* first_patch = reinterpret_cast<Patch*>(Memory::GetPointer(entry->symbol_offset)); Patch* first_patch = reinterpret_cast<Patch*>(Memory::GetPointer(entry->symbol_offset));
ApplyListPatches(header, first_patch, patch_base, relocated); ApplyListPatches(header, first_patch, patch_base, relocated);
@ -437,11 +451,11 @@ static void LoadExportsTable(CROHeader* header, u32 base) {
for (int i = 0; i < header->export_table_num; ++i) { for (int i = 0; i < header->export_table_num; ++i) {
ExportTableEntry* entry = header->GetExportTableEntry(i); ExportTableEntry* entry = header->GetExportTableEntry(i);
SegmentTableEntry* target_segment = header->GetSegmentTableEntry(entry->GetTargetSegment()); SegmentTableEntry* target_segment = header->GetSegmentTableEntry(entry->GetTargetSegment());
ExportedSymbol export; ExportedSymbol export_;
export.cro_base = base; export_.cro_base = base;
export.cro_offset = target_segment->segment_offset + entry->GetSegmentOffset(); export_.cro_offset = target_segment->segment_offset + entry->GetSegmentOffset();
export.name = reinterpret_cast<char*>(Memory::GetPointer(entry->name_offset)); export_.name = reinterpret_cast<char*>(Memory::GetPointer(entry->name_offset));
loaded_exports[export.name] = export; loaded_exports[export_.name] = export_;
} }
} }
@ -488,9 +502,10 @@ static void LinkCROs(CROHeader* new_cro, u32 base) {
static void LoadCRO(u32 base, u8* cro, bool relocate_segments, u32 data_section0, u32 data_section1, bool crs) { static void LoadCRO(u32 base, u8* cro, bool relocate_segments, u32 data_section0, u32 data_section1, bool crs) {
CROHeader* header = reinterpret_cast<CROHeader*>(cro); CROHeader* header = reinterpret_cast<CROHeader*>(cro);
u32 prev_section0 = 0;
if (relocate_segments) { if (relocate_segments) {
// Relocate segments // Relocate segments
header->RelocateSegmentsTable(base, data_section0, data_section1); header->RelocateSegmentsTable(base, data_section0, data_section1, prev_section0);
} }
// Rebase export table // Rebase export table
@ -513,7 +528,7 @@ static void LoadCRO(u32 base, u8* cro, bool relocate_segments, u32 data_section0
ApplyUnk3Patches(header, base); ApplyUnk3Patches(header, base);
// Apply relocation patches // Apply relocation patches
ApplyRelocationPatches(header, base); ApplyRelocationPatches(header, base, prev_section0 + base);
// Apply import table 1 patches // Apply import table 1 patches
ApplyExitPatches(header, base); ApplyExitPatches(header, base);
@ -581,7 +596,7 @@ static void Initialize(Service::Interface* self) {
memcpy(cro->data(), crs_buffer_ptr, crs_size); memcpy(cro->data(), crs_buffer_ptr, crs_size);
// TODO(Subv): Check what the real hardware returns for MemoryState // TODO(Subv): Check what the real hardware returns for MemoryState
Kernel::g_current_process->address_space->MapMemoryBlock(address, cro, 0, crs_size, Kernel::MemoryState::Code); Kernel::g_current_process->vm_manager.MapMemoryBlock(address, cro, 0, crs_size, Kernel::MemoryState::Code);
LoadCRO(address, Memory::GetPointer(address), false, 0, 0, true); LoadCRO(address, Memory::GetPointer(address), false, 0, 0, true);
@ -631,7 +646,7 @@ static void LoadExeCRO(Service::Interface* self) {
memcpy(cro->data(), cro_buffer, size); memcpy(cro->data(), cro_buffer, size);
// TODO(Subv): Check what the real hardware returns for MemoryState // TODO(Subv): Check what the real hardware returns for MemoryState
Kernel::g_current_process->address_space->MapMemoryBlock(address, cro, 0, size, Kernel::MemoryState::Code); Kernel::g_current_process->vm_manager.MapMemoryBlock(address, cro, 0, size, Kernel::MemoryState::Code);
LoadCRO(address, Memory::GetPointer(address), true, cmd_buff[4], cmd_buff[7], false); LoadCRO(address, Memory::GetPointer(address), true, cmd_buff[4], cmd_buff[7], false);