mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-25 03:50:14 +00:00
Fixed build and a bug
This commit is contained in:
parent
91318a33b9
commit
e72867b819
@ -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);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user