mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 02:32:36 +01:00
Minor fixes
elf_object Loader fix Analyser fix
This commit is contained in:
parent
b89961f01d
commit
06c6c8212d
@ -231,7 +231,6 @@ jit_compiler::jit_compiler(std::unique_ptr<llvm::Module>&& _module, std::unorder
|
||||
.setErrorStr(&result)
|
||||
.setMCJITMemoryManager(std::make_unique<MemoryManager>(std::move(table)))
|
||||
.setOptLevel(llvm::CodeGenOpt::Aggressive)
|
||||
.setRelocationModel(llvm::Reloc::PIC_)
|
||||
.setCodeModel((u64)s_memory <= 0x60000000 ? llvm::CodeModel::Medium : llvm::CodeModel::Large) // TODO
|
||||
.setMCPU(llvm::sys::getHostCPUName())
|
||||
.create());
|
||||
|
@ -2022,15 +2022,15 @@ s32 spursTasksetLoadElf(SPUThread& spu, u32* entryPoint, u32* lowestLoadAddr, u6
|
||||
return CELL_SPURS_TASK_ERROR_INVAL;
|
||||
}
|
||||
|
||||
const spu_exec_loader loader(fs::file(vm::base(vm::cast(elfAddr, HERE)), u32(0 - elfAddr)));
|
||||
const spu_exec_object obj(fs::file(vm::base(vm::cast(elfAddr, HERE)), u32(0 - elfAddr)));
|
||||
|
||||
if (loader != elf_error::ok)
|
||||
if (obj != elf_error::ok)
|
||||
{
|
||||
return CELL_SPURS_TASK_ERROR_NOEXEC;
|
||||
}
|
||||
|
||||
u32 _lowestLoadAddr = CELL_SPURS_TASK_BOTTOM;
|
||||
for (const auto& prog : loader.progs)
|
||||
for (const auto& prog : obj.progs)
|
||||
{
|
||||
if (prog.p_paddr >= CELL_SPURS_TASK_BOTTOM)
|
||||
{
|
||||
@ -2051,7 +2051,7 @@ s32 spursTasksetLoadElf(SPUThread& spu, u32* entryPoint, u32* lowestLoadAddr, u6
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& prog : loader.progs)
|
||||
for (const auto& prog : obj.progs)
|
||||
{
|
||||
if (prog.p_paddr >= CELL_SPURS_TASK_BOTTOM) // ???
|
||||
{
|
||||
@ -2067,7 +2067,7 @@ s32 spursTasksetLoadElf(SPUThread& spu, u32* entryPoint, u32* lowestLoadAddr, u6
|
||||
}
|
||||
}
|
||||
|
||||
*entryPoint = loader.header.e_entry;
|
||||
*entryPoint = obj.header.e_entry;
|
||||
if (lowestLoadAddr) *lowestLoadAddr = _lowestLoadAddr;
|
||||
|
||||
return CELL_OK;
|
||||
|
@ -80,12 +80,231 @@ void ppu_validate(const std::string& fname, const std::vector<ppu_function>& fun
|
||||
}
|
||||
}
|
||||
|
||||
static u32 ppu_test(const vm::cptr<u32> ptr, vm::cptr<void> fend, std::initializer_list<ppu_pattern> pat)
|
||||
{
|
||||
vm::cptr<u32> cur = ptr;
|
||||
|
||||
for (auto& p : pat)
|
||||
{
|
||||
if (cur >= fend)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (*cur == ppu_instructions::NOP())
|
||||
{
|
||||
cur++;
|
||||
|
||||
if (cur >= fend)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ((*cur & p.mask) != p.opcode)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
cur++;
|
||||
}
|
||||
|
||||
return cur.addr() - ptr.addr();
|
||||
}
|
||||
|
||||
static u32 ppu_test(vm::cptr<u32> ptr, vm::cptr<void> fend, std::initializer_list<std::initializer_list<ppu_pattern>> pats)
|
||||
{
|
||||
for (auto pat : pats)
|
||||
{
|
||||
if (const u32 len = ppu_test(ptr, fend, pat))
|
||||
{
|
||||
return len;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
namespace ppu_patterns
|
||||
{
|
||||
using namespace ppu_instructions;
|
||||
|
||||
const std::initializer_list<ppu_pattern> abort1
|
||||
{
|
||||
{ STDU(r1, r1, -0xc0) },
|
||||
{ MFLR(r0) },
|
||||
{ STD(r26, r1, 0x90) },
|
||||
{ STD(r27, r1, 0x98) },
|
||||
{ STD(r28, r1, 0xa0) },
|
||||
{ STD(r29, r1, 0xa8) },
|
||||
{ STD(r30, r1, 0xb0) },
|
||||
{ STD(r31, r1, 0xb8) },
|
||||
{ STD(r0, r1, 0xd0) },
|
||||
{ LI(r3, 4) },
|
||||
{ LI(r4, 0) },
|
||||
{ LI(r11, 0x3dc) },
|
||||
{ SC(0) },
|
||||
{ MR(r29, r1) },
|
||||
{ CLRLDI(r29, r29, 32) },
|
||||
{ LWZ(r4, r2, 0), 0xffff },
|
||||
{ ADDI(r31, r1, 0x70) },
|
||||
{ LI(r3, 1) },
|
||||
{ LI(r5, 0x19) },
|
||||
{ MR(r6, r31) },
|
||||
{ LWZ(r28, r29, 4) },
|
||||
{ LI(r11, 0x193) },
|
||||
{ SC(0) },
|
||||
{ ADDI(r26, r1, 0x78) },
|
||||
{ LD(r3, r28, 0x10) },
|
||||
{ MR(r4, r26) },
|
||||
{ B(0, false, true), 0x3fffffc }, // .hex2str
|
||||
{ LI(r5, 0x10) },
|
||||
{ CLRLDI(r4, r3, 32) },
|
||||
{ MR(r6, r31) },
|
||||
{ LI(r3, 1) },
|
||||
{ LI(r11, 0x193) },
|
||||
{ SC(0) },
|
||||
{ LWZ(r27, r2, 0), 0xffff },
|
||||
{ LI(r3, 1) },
|
||||
{ LI(r5, 1) },
|
||||
{ MR(r4, r27) },
|
||||
{ MR(r6, r31) },
|
||||
{ LI(r11, 0x193) },
|
||||
{ SC(0) },
|
||||
{ LD(r28, r28, 0) },
|
||||
{ CMPDI(cr7, r28, 0) },
|
||||
{ BEQ(cr7, +0x6c) },
|
||||
{ LWZ(r30, r2, 0), 0xffff },
|
||||
{ LI(r3, 1) },
|
||||
{ MR(r4, r30) },
|
||||
{ LI(r5, 0x19) },
|
||||
{ MR(r6, r31) },
|
||||
{ LI(r11, 0x193) },
|
||||
{ SC(0) },
|
||||
{ CLRLDI(r29, r28, 32) },
|
||||
{ CLRLDI(r4, r26, 32) },
|
||||
{ LD(r3, r29, 0x10) },
|
||||
{ 0, 0xffffffff }, // .hex2str
|
||||
{ LI(r5, 0x10) },
|
||||
{ CLRLDI(r4, r3, 32) },
|
||||
{ MR(r6, r31) },
|
||||
{ LI(r3, 1) },
|
||||
{ LI(r11, 0x193) },
|
||||
{ SC(0) },
|
||||
{ LI(r3, 1) },
|
||||
{ MR(r4, r27) },
|
||||
{ LI(r5, 1) },
|
||||
{ MR(r6, r31) },
|
||||
{ LI(r11, 0x193) },
|
||||
{ SC(0) },
|
||||
{ LD(r28, r29, 0) },
|
||||
{ CMPDI(cr7, r28, 0) },
|
||||
{ BNE(cr7, -0x60) },
|
||||
{ LWZ(r4, r2, 0), 0xffff },
|
||||
{ MR(r6, r31) },
|
||||
{ LI(r3, 1) },
|
||||
{ LI(r5, 0x27) },
|
||||
{ LI(r11, 0x193) },
|
||||
{ SC(0) },
|
||||
{ LI(r3, 1) },
|
||||
{ B(0, false, true), 0x3fffffc }, // .sys_process_exit
|
||||
{ LD(r2, r1, 0x28) },
|
||||
{ LI(r3, 1) },
|
||||
{ B(0, false, true), 0x3fffffc }, // .exit
|
||||
};
|
||||
|
||||
const std::initializer_list<ppu_pattern> abort2
|
||||
{
|
||||
{ STDU(r1, r1, -0xc0) },
|
||||
{ MFLR(r0) },
|
||||
{ STD(r27, r1, 0x98) },
|
||||
{ STD(r28, r1, 0xa0) },
|
||||
{ STD(r29, r1, 0xa8) },
|
||||
{ STD(r30, r1, 0xb0) },
|
||||
{ STD(r31, r1, 0xb8) },
|
||||
{ STD(r0, r1, 0xd0) },
|
||||
{ MR(r9, r1) },
|
||||
{ CLRLDI(r9, r9, 32) },
|
||||
{ LWZ(r4, r2, 0), 0xffff },
|
||||
{ ADDI(r31, r1, 0x70) },
|
||||
{ LI(r3, 1) },
|
||||
{ LI(r5, 0x19) },
|
||||
{ MR(r6, r31) },
|
||||
{ LWZ(r29, r9, 4) },
|
||||
{ LI(r11, 0x193) },
|
||||
{ SC(0) },
|
||||
{ ADDI(r27, r1, 0x78) },
|
||||
{ LD(r3, r29, 0x10) },
|
||||
{ MR(r4, r27) },
|
||||
{ B(0, false, true), 0x3fffffc }, // .hex2str
|
||||
{ LI(r5, 0x10) },
|
||||
{ CLRLDI(r4, r3, 32) },
|
||||
{ MR(r6, r31) },
|
||||
{ LI(r3, 1) },
|
||||
{ LI(r11, 0x193) },
|
||||
{ SC(0) },
|
||||
{ LWZ(r28, r2, 0), 0xffff },
|
||||
{ LI(r3, 1) },
|
||||
{ LI(r5, 1) },
|
||||
{ MR(r4, r28) },
|
||||
{ MR(r6, r31) },
|
||||
{ LI(r11, 0x193) },
|
||||
{ SC(0) },
|
||||
{ LD(r29, r29, 0) },
|
||||
{ CMPDI(cr7, r29, 0) },
|
||||
{ BEQ(cr7, +0x6c) },
|
||||
{ LWZ(r30, r2, 0), 0xffff },
|
||||
{ LI(r3, 1) },
|
||||
{ MR(r4, r30) },
|
||||
{ LI(r5, 0x19) },
|
||||
{ MR(r6, r31) },
|
||||
{ LI(r11, 0x193) },
|
||||
{ SC(0) },
|
||||
{ CLRLDI(r29, r29, 32) },
|
||||
{ CLRLDI(r4, r27, 32) },
|
||||
{ LD(r3, r29, 0x10) },
|
||||
{ 0, 0xffffffff }, // .hex2str
|
||||
{ LI(r5, 0x10) },
|
||||
{ CLRLDI(r4, r3, 32) },
|
||||
{ MR(r6, r31) },
|
||||
{ LI(r3, 1) },
|
||||
{ LI(r11, 0x193) },
|
||||
{ SC(0) },
|
||||
{ LI(r3, 1) },
|
||||
{ MR(r4, r28) },
|
||||
{ LI(r5, 1) },
|
||||
{ MR(r6, r31) },
|
||||
{ LI(r11, 0x193) },
|
||||
{ SC(0) },
|
||||
{ LD(r29, r29, 0) },
|
||||
{ CMPDI(cr7, r29, 0) },
|
||||
{ BNE(cr7, -0x60) },
|
||||
{ LWZ(r4, r2, 0), 0xffff },
|
||||
{ MR(r6, r31) },
|
||||
{ LI(r3, 1) },
|
||||
{ LI(r5, 0x27) },
|
||||
{ LI(r11, 0x193) },
|
||||
{ SC(0) },
|
||||
{ LI(r3, 1) },
|
||||
{ B(0, false, true), 0x3fffffc }, // .sys_process_exit
|
||||
{ LD(r2, r1, 0x28) },
|
||||
{ LI(r3, 1) },
|
||||
{ B(0, false, true), 0x3fffffc }, // .exit
|
||||
};
|
||||
|
||||
const std::initializer_list<std::initializer_list<ppu_pattern>> abort
|
||||
{
|
||||
abort1,
|
||||
abort2,
|
||||
};
|
||||
}
|
||||
|
||||
std::vector<ppu_function> ppu_analyse(const std::vector<std::pair<u32, u32>>& segs, const std::vector<std::pair<u32, u32>>& secs, u32 entry, u32 lib_toc)
|
||||
{
|
||||
// Assume first segment is executable
|
||||
const u32 start = segs[0].first;
|
||||
const u32 end = segs[0].first + segs[0].second;
|
||||
const u32 start_toc = entry ? +vm::read32(entry + 4) : lib_toc;
|
||||
const u32 start_toc = entry && !lib_toc ? +vm::read32(entry + 4) : lib_toc;
|
||||
|
||||
// Known TOCs (usually only 1)
|
||||
std::unordered_set<u32> TOCs;
|
||||
@ -186,26 +405,98 @@ std::vector<ppu_function> ppu_analyse(const std::vector<std::pair<u32, u32>>& se
|
||||
// Otherwise, register initial set of functions (likely including the entry point)
|
||||
add_toc(start_toc);
|
||||
|
||||
// Find eh_frame section
|
||||
// Find .eh_frame section
|
||||
for (const auto& sec : secs)
|
||||
{
|
||||
const u32 sec_end = sec.first + sec.second;
|
||||
u32 sec_end = sec.first + sec.second;
|
||||
|
||||
if (sec.first + 32 >= sec_end || vm::read64(sec.first) != 0x0000001c00000000 || vm::read16(sec.first + 8) != 0x017a)
|
||||
// Probe
|
||||
for (vm::cptr<u32> ptr = vm::cast(sec.first); ptr.addr() < sec_end;)
|
||||
{
|
||||
continue;
|
||||
if (ptr % 4 || ptr.addr() < sec.first || ptr.addr() >= sec_end)
|
||||
{
|
||||
sec_end = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
const u32 size = ptr[0] + 4;
|
||||
|
||||
if (size == 4 && ptr.addr() == sec_end - 4)
|
||||
{
|
||||
// Null terminator
|
||||
break;
|
||||
}
|
||||
|
||||
if (size % 4 || size < 0x10 || size > sec_end - ptr.addr())
|
||||
{
|
||||
sec_end = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ptr[1])
|
||||
{
|
||||
const u32 cie_off = ptr.addr() - ptr[1] + 4;
|
||||
|
||||
if (cie_off % 4 || cie_off < sec.first || cie_off >= sec_end)
|
||||
{
|
||||
sec_end = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ptr = vm::cast(ptr.addr() + size);
|
||||
}
|
||||
|
||||
for (vm::cptr<u32> ptr = vm::cast(sec.first); ptr.addr() < sec_end - 4; ptr = vm::cast(ptr.addr() + ptr[0] + 4))
|
||||
// Mine
|
||||
for (vm::cptr<u32> ptr = vm::cast(sec.first); ptr.addr() < sec_end; ptr = vm::cast(ptr.addr() + ptr[0] + 4))
|
||||
{
|
||||
if (const u32 off = ptr[1])
|
||||
if (ptr[0] == 0)
|
||||
{
|
||||
const u32 addr = ptr[3] + (ptr + 2).addr(); // Function offset (64 bit)
|
||||
const u32 size = ptr[5]; // Function size (64 bit)
|
||||
// Null terminator
|
||||
break;
|
||||
}
|
||||
|
||||
LOG_NOTICE(PPU, ".eh_frame: [0x%x] 0x%x, 0x%x (size=0x%x)", ptr, ptr[0], ptr[1], size);
|
||||
if (ptr[1] == 0)
|
||||
{
|
||||
// CIE
|
||||
LOG_NOTICE(PPU, ".eh_frame: [0x%x] CIE 0x%x", ptr, ptr[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get associated CIE (currently unused)
|
||||
const vm::cptr<u32> cie = vm::cast(ptr.addr() - ptr[1] + 4);
|
||||
|
||||
if (!ptr[3]) continue; // TODO (some entries have zero offset)
|
||||
u32 addr = 0;
|
||||
u32 size = 0;
|
||||
|
||||
if ((ptr[2] == -1 || ptr[2] == 0) && ptr[4] == 0)
|
||||
{
|
||||
addr = ptr[3] + ptr.addr() + 8;
|
||||
size = ptr[5];
|
||||
}
|
||||
else if (ptr[2] == 0 && ptr[3] == 0)
|
||||
{
|
||||
}
|
||||
else if (ptr[2] != -1 && ptr[4])
|
||||
{
|
||||
addr = ptr[2];
|
||||
size = ptr[3];
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR(PPU, ".eh_frame: [0x%x] 0x%x, 0x%x, 0x%x, 0x%x, 0x%x", ptr, ptr[0], ptr[1], ptr[2], ptr[3], ptr[4]);
|
||||
continue;
|
||||
}
|
||||
|
||||
LOG_NOTICE(PPU, ".eh_frame: [0x%x] FDE 0x%x (cie=*0x%x, addr=0x%x, size=0x%x)", ptr, ptr[0], cie, addr, size);
|
||||
|
||||
if (!addr) continue; // TODO (some entries have zero offset)
|
||||
|
||||
if (addr % 4 || addr < start || addr >= end)
|
||||
{
|
||||
LOG_ERROR(PPU, ".eh_frame: Invalid function 0x%x", addr);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto& func = add_func(addr, 0, ptr.addr());
|
||||
func.attr += ppu_attr::known_size;
|
||||
@ -230,11 +521,15 @@ std::vector<ppu_function> ppu_analyse(const std::vector<std::pair<u32, u32>>& se
|
||||
if (ptr + 1 <= fend && (ptr[0] & 0xfc000001) == B({}, {}))
|
||||
{
|
||||
// Simple gate
|
||||
func.size = 0x4;
|
||||
func.blocks.emplace(func.addr, func.size);
|
||||
const u32 target = ppu_branch_target(ptr[0] & 0x2 ? 0 : ptr.addr(), s32(ptr[0]) << 6 >> 6);
|
||||
add_func(target, func.toc, func.addr);
|
||||
continue;
|
||||
|
||||
if (target >= start && target < end)
|
||||
{
|
||||
func.size = 0x4;
|
||||
func.blocks.emplace(func.addr, func.size);
|
||||
add_func(target, func.toc, func.addr);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (ptr + 4 <= fend &&
|
||||
@ -244,13 +539,17 @@ std::vector<ppu_function> ppu_analyse(const std::vector<std::pair<u32, u32>>& se
|
||||
(ptr[3] & 0xfc000001) == B({}, {}))
|
||||
{
|
||||
// TOC change gate
|
||||
func.size = 0x10;
|
||||
func.blocks.emplace(func.addr, func.size);
|
||||
const u32 new_toc = func.toc && func.toc != -1 ? func.toc + (ptr[1] << 16) + s16(ptr[2]) : 0;
|
||||
const u32 target = ppu_branch_target(ptr[3] & 0x2 ? 0 : (ptr + 3).addr(), s32(ptr[3]) << 6 >> 6);
|
||||
add_func(target, new_toc, func.addr);
|
||||
add_toc(new_toc);
|
||||
continue;
|
||||
|
||||
if (target >= start && target < end)
|
||||
{
|
||||
func.size = 0x10;
|
||||
func.blocks.emplace(func.addr, func.size);
|
||||
add_func(target, new_toc, func.addr);
|
||||
add_toc(new_toc);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (ptr + 8 <= fend &&
|
||||
@ -269,6 +568,15 @@ std::vector<ppu_function> ppu_analyse(const std::vector<std::pair<u32, u32>>& se
|
||||
continue;
|
||||
}
|
||||
|
||||
if (const u32 len = ppu_test(ptr, fend, ppu_patterns::abort))
|
||||
{
|
||||
// Function .abort
|
||||
LOG_NOTICE(PPU, "Function [0x%x]: 'abort'", func.addr);
|
||||
func.attr += ppu_attr::no_return;
|
||||
func.attr += ppu_attr::known_size;
|
||||
func.size = len;
|
||||
}
|
||||
|
||||
if (ptr + 3 <= fend &&
|
||||
(ptr[0] & 0xffff0000) == LI(r0, 0) &&
|
||||
(ptr[1] & 0xffff0000) == ORIS(r0, r0, 0) &&
|
||||
@ -350,6 +658,13 @@ std::vector<ppu_function> ppu_analyse(const std::vector<std::pair<u32, u32>>& se
|
||||
else if (type == ppu_itype::B || type == ppu_itype::BC)
|
||||
{
|
||||
const u32 target = ppu_branch_target(op.aa ? 0 : iaddr, type == ppu_itype::B ? +op.ll : +op.simm16);
|
||||
|
||||
if (target < start || target >= end)
|
||||
{
|
||||
LOG_WARNING(PPU, "[0x%x] Invalid branch at 0x%x -> 0x%x", func.addr, iaddr, target);
|
||||
continue;
|
||||
}
|
||||
|
||||
const bool is_call = op.lk && target != iaddr;
|
||||
const auto pfunc = is_call ? &add_func(target, 0, func.addr) : nullptr;
|
||||
|
||||
@ -537,9 +852,12 @@ std::vector<ppu_function> ppu_analyse(const std::vector<std::pair<u32, u32>>& se
|
||||
{
|
||||
const u32 target = ppu_branch_target(op.aa ? 0 : iaddr, type == ppu_itype::B ? +op.ll : +op.simm16);
|
||||
|
||||
if (target < func.addr || target >= func.addr + func.size)
|
||||
if (target >= start && target < end)
|
||||
{
|
||||
add_func(target, func.toc, func.addr);
|
||||
if (target < func.addr || target >= func.addr + func.size)
|
||||
{
|
||||
add_func(target, func.toc, func.addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (type == ppu_itype::BCCTR && !op.lk)
|
||||
|
@ -2,7 +2,8 @@
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "../Utilities/BitSet.h"
|
||||
#include "Utilities/BitSet.h"
|
||||
#include "Utilities/BEType.h"
|
||||
|
||||
// PPU Function Attributes
|
||||
enum class ppu_attr : u32
|
||||
@ -24,6 +25,27 @@ struct ppu_function
|
||||
std::map<u32, u32> blocks; // Basic blocks: addr -> size
|
||||
};
|
||||
|
||||
// Aux
|
||||
struct ppu_pattern
|
||||
{
|
||||
be_t<u32> opcode;
|
||||
be_t<u32> mask;
|
||||
|
||||
ppu_pattern() = default;
|
||||
|
||||
ppu_pattern(u32 op)
|
||||
: opcode(op)
|
||||
, mask(0xffffffff)
|
||||
{
|
||||
}
|
||||
|
||||
ppu_pattern(u32 op, u32 ign)
|
||||
: opcode(op & ~ign)
|
||||
, mask(~ign)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
extern void ppu_validate(const std::string& fname, const std::vector<ppu_function>& funcs, u32 reloc);
|
||||
|
||||
extern std::vector<ppu_function> ppu_analyse(const std::vector<std::pair<u32, u32>>& segs, const std::vector<std::pair<u32, u32>>& secs, u32 entry, u32 lib_toc);
|
||||
|
@ -731,13 +731,12 @@ static void ppu_load_imports(const std::shared_ptr<ppu_linkage_info>& link, u32
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
std::shared_ptr<lv2_prx_t> ppu_prx_loader::load() const
|
||||
std::shared_ptr<lv2_prx_t> ppu_load_prx(const ppu_prx_object& elf)
|
||||
{
|
||||
std::vector<std::pair<u32, u32>> segments;
|
||||
std::vector<std::pair<u32, u32>> sections; // Unused
|
||||
std::vector<std::pair<u32, u32>> sections;
|
||||
|
||||
for (const auto& prog : progs)
|
||||
for (const auto& prog : elf.progs)
|
||||
{
|
||||
LOG_NOTICE(LOADER, "** Segment: p_type=0x%x, p_vaddr=0x%llx, p_filesz=0x%llx, p_memsz=0x%llx, flags=0x%x", prog.p_type, prog.p_vaddr, prog.p_filesz, prog.p_memsz, prog.p_flags);
|
||||
|
||||
@ -775,8 +774,30 @@ std::shared_ptr<lv2_prx_t> ppu_prx_loader::load() const
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& s : elf.shdrs)
|
||||
{
|
||||
LOG_NOTICE(LOADER, "** Section: sh_type=0x%x, addr=0x%llx, size=0x%llx, flags=0x%x", s.sh_type, s.sh_addr, s.sh_size, s.sh_flags);
|
||||
|
||||
const u32 addr = vm::cast(s.sh_addr);
|
||||
const u32 size = vm::cast(s.sh_size);
|
||||
|
||||
if (s.sh_type == 1 && addr && size)
|
||||
{
|
||||
for (auto i = 0; i < segments.size(); i++)
|
||||
{
|
||||
const u32 saddr = static_cast<u32>(elf.progs[i].p_vaddr);
|
||||
if (addr >= addr && addr < saddr + elf.progs[i].p_memsz)
|
||||
{
|
||||
// "Relocate" section
|
||||
sections.emplace_back(std::make_pair(addr - saddr + segments[i].first, size));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Do relocations
|
||||
for (auto& prog : progs)
|
||||
for (auto& prog : elf.progs)
|
||||
{
|
||||
switch (const u32 p_type = prog.p_type)
|
||||
{
|
||||
@ -831,9 +852,27 @@ std::shared_ptr<lv2_prx_t> ppu_prx_loader::load() const
|
||||
}
|
||||
|
||||
case 10:
|
||||
{
|
||||
const u32 value = vm::_ref<ppu_bf_t<u32, 6, 24>>(raddr) = static_cast<u32>(rdata - raddr) >> 2;
|
||||
LOG_WARNING(LOADER, "**** RELOCATION(10): 0x%x <- 0x%06x (0x%llx)", raddr, value, rdata);
|
||||
break;
|
||||
}
|
||||
|
||||
case 44:
|
||||
{
|
||||
const u64 value = vm::_ref<u64>(raddr) = rdata - raddr;
|
||||
LOG_TRACE(LOADER, "**** RELOCATION(44): 0x%x <- 0x%016llx (0x%llx)", raddr, value, rdata);
|
||||
break;
|
||||
}
|
||||
|
||||
case 57:
|
||||
default: LOG_ERROR(LOADER, "**** RELOCATION(%u): Illegal/Unknown type! (addr=0x%x)", type, raddr);
|
||||
{
|
||||
const u16 value = vm::_ref<ppu_bf_t<u16, 0, 14>>(raddr) = static_cast<u16>(rdata) >> 2;
|
||||
LOG_WARNING(LOADER, "**** RELOCATION(57): 0x%x <- 0x%04x (0x%llx)", raddr, value, rdata);
|
||||
break;
|
||||
}
|
||||
|
||||
default: LOG_ERROR(LOADER, "**** RELOCATION(%u): Illegal/Unknown type! (addr=0x%x; 0x%llx)", type, raddr, rdata);
|
||||
}
|
||||
}
|
||||
|
||||
@ -848,7 +887,7 @@ std::shared_ptr<lv2_prx_t> ppu_prx_loader::load() const
|
||||
// Create new PRX object
|
||||
auto prx = idm::make_ptr<lv2_prx_t>();
|
||||
|
||||
if (!progs.empty() && progs[0].p_paddr)
|
||||
if (!elf.progs.empty() && elf.progs[0].p_paddr)
|
||||
{
|
||||
struct ppu_prx_library_info
|
||||
{
|
||||
@ -863,7 +902,7 @@ std::shared_ptr<lv2_prx_t> ppu_prx_loader::load() const
|
||||
};
|
||||
|
||||
// Access library information (TODO)
|
||||
const auto& lib_info = vm::cptr<ppu_prx_library_info>(vm::cast(segments[0].first + progs[0].p_paddr - progs[0].p_offset, HERE));
|
||||
const auto& lib_info = vm::cptr<ppu_prx_library_info>(vm::cast(segments[0].first + elf.progs[0].p_paddr - elf.progs[0].p_offset, HERE));
|
||||
const auto& lib_name = std::string(lib_info->name);
|
||||
|
||||
LOG_WARNING(LOADER, "Library %s (rtoc=0x%x):", lib_name, lib_info->toc);
|
||||
@ -872,7 +911,7 @@ std::shared_ptr<lv2_prx_t> ppu_prx_loader::load() const
|
||||
|
||||
ppu_load_imports(link, lib_info->imports_start, lib_info->imports_end);
|
||||
|
||||
prx->funcs = ppu_analyse(segments, sections, 0, lib_info->toc);
|
||||
prx->funcs = ppu_analyse(segments, sections, prx->specials[0xbc9a0086], lib_info->toc);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -886,8 +925,7 @@ std::shared_ptr<lv2_prx_t> ppu_prx_loader::load() const
|
||||
return prx;
|
||||
}
|
||||
|
||||
template<>
|
||||
void ppu_exec_loader::load() const
|
||||
void ppu_load_exec(const ppu_exec_object& elf)
|
||||
{
|
||||
ppu_initialize_modules();
|
||||
|
||||
@ -909,7 +947,7 @@ void ppu_exec_loader::load() const
|
||||
std::vector<ppu_function> exec_set;
|
||||
|
||||
// Allocate memory at fixed positions
|
||||
for (const auto& prog : progs)
|
||||
for (const auto& prog : elf.progs)
|
||||
{
|
||||
LOG_NOTICE(LOADER, "** Segment: p_type=0x%x, p_vaddr=0x%llx, p_filesz=0x%llx, p_memsz=0x%llx, flags=0x%x", prog.p_type, prog.p_vaddr, prog.p_filesz, prog.p_memsz, prog.p_flags);
|
||||
|
||||
@ -932,7 +970,7 @@ void ppu_exec_loader::load() const
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& s : shdrs)
|
||||
for (const auto& s : elf.shdrs)
|
||||
{
|
||||
LOG_NOTICE(LOADER, "** Section: sh_type=0x%x, addr=0x%llx, size=0x%llx, flags=0x%x", s.sh_type, s.sh_addr, s.sh_size, s.sh_flags);
|
||||
|
||||
@ -946,7 +984,7 @@ void ppu_exec_loader::load() const
|
||||
}
|
||||
|
||||
// Load other programs
|
||||
for (auto& prog : progs)
|
||||
for (auto& prog : elf.progs)
|
||||
{
|
||||
switch (const u32 p_type = prog.p_type)
|
||||
{
|
||||
@ -1057,28 +1095,28 @@ void ppu_exec_loader::load() const
|
||||
|
||||
if (g_cfg_load_liblv2)
|
||||
{
|
||||
const ppu_prx_loader loader = fs::file(lle_dir + "/liblv2.sprx");
|
||||
const ppu_prx_object obj = fs::file(lle_dir + "/liblv2.sprx");
|
||||
|
||||
if (loader == elf_error::ok)
|
||||
if (obj == elf_error::ok)
|
||||
{
|
||||
start_funcs.push_back(loader.load()->start.addr());
|
||||
start_funcs.push_back(ppu_load_prx(obj)->start.addr());
|
||||
}
|
||||
else
|
||||
{
|
||||
throw fmt::exception("Failed to load liblv2.sprx: %s", loader.get_error());
|
||||
throw fmt::exception("Failed to load liblv2.sprx: %s", obj.get_error());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const auto& name : g_cfg_load_libs.get_set())
|
||||
{
|
||||
const ppu_prx_loader loader = fs::file(lle_dir + '/' + name);
|
||||
const ppu_prx_object obj = fs::file(lle_dir + '/' + name);
|
||||
|
||||
if (loader == elf_error::ok)
|
||||
if (obj == elf_error::ok)
|
||||
{
|
||||
LOG_WARNING(LOADER, "Loading library: %s", name);
|
||||
|
||||
const auto prx = loader.load();
|
||||
const auto prx = ppu_load_prx(obj);
|
||||
|
||||
// Register start function
|
||||
if (prx->start)
|
||||
@ -1093,7 +1131,7 @@ void ppu_exec_loader::load() const
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_FATAL(LOADER, "Failed to load %s: %s", name, loader.get_error());
|
||||
LOG_FATAL(LOADER, "Failed to load %s: %s", name, obj.get_error());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1221,7 +1259,7 @@ void ppu_exec_loader::load() const
|
||||
}
|
||||
|
||||
// Analyse executable
|
||||
const auto funcs = ppu_analyse(segments, sections, static_cast<u32>(header.e_entry), 0);
|
||||
const auto funcs = ppu_analyse(segments, sections, static_cast<u32>(elf.header.e_entry), 0);
|
||||
|
||||
ppu_validate(vfs::get(Emu.GetPath()), funcs, 0);
|
||||
|
||||
@ -1287,7 +1325,7 @@ void ppu_exec_loader::load() const
|
||||
*entry++ = MR(r12, r19);
|
||||
|
||||
// Branch to initialization
|
||||
make_branch(entry, static_cast<u32>(header.e_entry), true);
|
||||
make_branch(entry, static_cast<u32>(elf.header.e_entry), true);
|
||||
|
||||
// Register entry function (addr, size)
|
||||
ppu_function entry_func;
|
||||
@ -1296,7 +1334,7 @@ void ppu_exec_loader::load() const
|
||||
exec_set.emplace_back(entry_func);
|
||||
|
||||
// Initialize recompiler
|
||||
ppu_initialize("", exec_set, static_cast<u32>(header.e_entry));
|
||||
ppu_initialize("", exec_set, static_cast<u32>(elf.header.e_entry));
|
||||
|
||||
auto ppu = idm::make_ptr<PPUThread>("main_thread");
|
||||
|
||||
|
@ -586,6 +586,11 @@ namespace ppu_instructions
|
||||
r12, r13, r14, r15, r16, r17, r18, r19, r20, r21,
|
||||
r22, r23, r24, r25, r26, r27, r28, r29, r30, r31,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
cr0, cr1, cr2, cr3, cr4, cr5, cr6, cr7,
|
||||
};
|
||||
}
|
||||
|
||||
using namespace fields;
|
||||
@ -595,7 +600,7 @@ namespace ppu_instructions
|
||||
inline u32 ORI(u32 rt, u32 ra, u32 ui) { ppu_opcode_t op{ 0x18u << 26 }; op.rd = rt; op.ra = ra; op.uimm16 = ui; return op.opcode; }
|
||||
inline u32 ORIS(u32 rt, u32 ra, u32 ui) { ppu_opcode_t op{ 0x19u << 26 }; op.rd = rt; op.ra = ra; op.uimm16 = ui; return op.opcode; }
|
||||
inline u32 OR(u32 ra, u32 rs, u32 rb, bool rc = false) { ppu_opcode_t op{ 0x1fu << 26 | 0x1bcu << 1 }; op.rs = rs; op.ra = ra; op.rb = rb; op.rc = rc; return op.opcode; }
|
||||
inline u32 SC(u32 lev) { ppu_opcode_t op{ 0x11u << 26 }; op.lev = lev; return op.opcode; }
|
||||
inline u32 SC(u32 lev) { ppu_opcode_t op{ 0x11u << 26 | 1 << 1 }; op.lev = lev; return op.opcode; }
|
||||
inline u32 B(s32 li, bool aa = false, bool lk = false) { ppu_opcode_t op{ 0x12u << 26 }; op.ll = li; op.aa = aa; op.lk = lk; return op.opcode; }
|
||||
inline u32 BC(u32 bo, u32 bi, s32 bd, bool aa = false, bool lk = false) { ppu_opcode_t op{ 0x10u << 26 }; op.bo = bo; op.bi = bi; op.ds = bd / 4; op.aa = aa; op.lk = lk; return op.opcode; }
|
||||
inline u32 BCLR(u32 bo, u32 bi, u32 bh, bool lk = false) { ppu_opcode_t op{ 0x13u << 26 | 0x10u << 1 }; op.bo = bo; op.bi = bi; op.bh = bh; op.lk = lk; return op.opcode; }
|
||||
@ -607,8 +612,8 @@ namespace ppu_instructions
|
||||
inline u32 STDU(u32 rs, u32 ra, s32 si) { ppu_opcode_t op{ 0x3eu << 26 | 1 }; op.rs = rs; op.ra = ra; op.ds = si / 4; return op.opcode; }
|
||||
inline u32 LD(u32 rt, u32 ra, s32 si) { ppu_opcode_t op{ 0x3au << 26 }; op.rd = rt; op.ra = ra; op.ds = si / 4; return op.opcode; }
|
||||
inline u32 LDU(u32 rt, u32 ra, s32 si) { ppu_opcode_t op{ 0x3au << 26 | 1 }; op.rd = rt; op.ra = ra; op.ds = si / 4; return op.opcode; }
|
||||
//inline u32 CMPI(u32 bf, u32 l, u32 ra, u32 ui) { ppu_opcode_t op{ 0xbu << 26 }; op.crfd = bf; op.l10 = l; op.ra = ra; op.uimm16 = ui; return op.opcode; }
|
||||
//inline u32 CMPLI(u32 bf, u32 l, u32 ra, u32 ui) { ppu_opcode_t op{ 0xau << 26 }; op.crfd = bf; op.l10 = l; op.ra = ra; op.uimm16 = ui; return op.opcode; }
|
||||
inline u32 CMPI(u32 bf, u32 l, u32 ra, u32 ui) { ppu_opcode_t op{ 0xbu << 26 }; op.crfd = bf; op.l10 = l; op.ra = ra; op.uimm16 = ui; return op.opcode; }
|
||||
inline u32 CMPLI(u32 bf, u32 l, u32 ra, u32 ui) { ppu_opcode_t op{ 0xau << 26 }; op.crfd = bf; op.l10 = l; op.ra = ra; op.uimm16 = ui; return op.opcode; }
|
||||
inline u32 RLDICL(u32 ra, u32 rs, u32 sh, u32 mb, bool rc = false) { ppu_opcode_t op{ 30 << 26 }; op.ra = ra; op.rs = rs; op.sh64 = sh; op.mbe64 = mb; op.rc = rc; return op.opcode; }
|
||||
|
||||
namespace implicts
|
||||
@ -627,21 +632,21 @@ namespace ppu_instructions
|
||||
inline u32 MFLR(u32 reg) { return MFSPR(reg, 8 << 5); }
|
||||
inline u32 MTLR(u32 reg) { return MTSPR(8 << 5, reg); }
|
||||
|
||||
//inline u32 BNE(u32 cr, s32 imm) { return BC(4, 2 | cr << 2, imm); }
|
||||
//inline u32 BEQ(u32 cr, s32 imm) { return BC(12, 2 | cr << 2, imm); }
|
||||
//inline u32 BGT(u32 cr, s32 imm) { return BC(12, 1 | cr << 2, imm); }
|
||||
//inline u32 BNE(s32 imm) { return BNE(cr0, imm); }
|
||||
//inline u32 BEQ(s32 imm) { return BEQ(cr0, imm); }
|
||||
//inline u32 BGT(s32 imm) { return BGT(cr0, imm); }
|
||||
inline u32 BNE(u32 cr, s32 imm) { return BC(4, 2 | cr << 2, imm); }
|
||||
inline u32 BEQ(u32 cr, s32 imm) { return BC(12, 2 | cr << 2, imm); }
|
||||
inline u32 BGT(u32 cr, s32 imm) { return BC(12, 1 | cr << 2, imm); }
|
||||
inline u32 BNE(s32 imm) { return BNE(cr0, imm); }
|
||||
inline u32 BEQ(s32 imm) { return BEQ(cr0, imm); }
|
||||
inline u32 BGT(s32 imm) { return BGT(cr0, imm); }
|
||||
|
||||
//inline u32 CMPDI(u32 cr, u32 reg, u32 imm) { return CMPI(cr, 1, reg, imm); }
|
||||
//inline u32 CMPDI(u32 reg, u32 imm) { return CMPDI(cr0, reg, imm); }
|
||||
//inline u32 CMPWI(u32 cr, u32 reg, u32 imm) { return CMPI(cr, 0, reg, imm); }
|
||||
//inline u32 CMPWI(u32 reg, u32 imm) { return CMPWI(cr0, reg, imm); }
|
||||
//inline u32 CMPLDI(u32 cr, u32 reg, u32 imm) { return CMPLI(cr, 1, reg, imm); }
|
||||
//inline u32 CMPLDI(u32 reg, u32 imm) { return CMPLDI(cr0, reg, imm); }
|
||||
//inline u32 CMPLWI(u32 cr, u32 reg, u32 imm) { return CMPLI(cr, 0, reg, imm); }
|
||||
//inline u32 CMPLWI(u32 reg, u32 imm) { return CMPLWI(cr0, reg, imm); }
|
||||
inline u32 CMPDI(u32 cr, u32 reg, u32 imm) { return CMPI(cr, 1, reg, imm); }
|
||||
inline u32 CMPDI(u32 reg, u32 imm) { return CMPDI(cr0, reg, imm); }
|
||||
inline u32 CMPWI(u32 cr, u32 reg, u32 imm) { return CMPI(cr, 0, reg, imm); }
|
||||
inline u32 CMPWI(u32 reg, u32 imm) { return CMPWI(cr0, reg, imm); }
|
||||
inline u32 CMPLDI(u32 cr, u32 reg, u32 imm) { return CMPLI(cr, 1, reg, imm); }
|
||||
inline u32 CMPLDI(u32 reg, u32 imm) { return CMPLDI(cr0, reg, imm); }
|
||||
inline u32 CMPLWI(u32 cr, u32 reg, u32 imm) { return CMPLI(cr, 0, reg, imm); }
|
||||
inline u32 CMPLWI(u32 reg, u32 imm) { return CMPLWI(cr0, reg, imm); }
|
||||
|
||||
inline u32 EXTRDI(u32 x, u32 y, u32 n, u32 b) { return RLDICL(x, y, b + n, 64 - b, false); }
|
||||
inline u32 SRDI(u32 x, u32 y, u32 n) { return RLDICL(x, y, 64 - n, n, false); }
|
||||
|
@ -566,7 +566,7 @@ extern void ppu_initialize(const std::string& name, const std::vector<ppu_functi
|
||||
pm.add(createReassociatePass());
|
||||
pm.add(createInstructionCombiningPass());
|
||||
//pm.add(createBasicAAWrapperPass());
|
||||
pm.add(new MemoryDependenceAnalysis());
|
||||
//pm.add(new MemoryDependenceAnalysis());
|
||||
pm.add(createLICMPass());
|
||||
pm.add(createLoopInstSimplifyPass());
|
||||
pm.add(createGVNPass());
|
||||
|
@ -234,12 +234,11 @@ bool RawSPUThread::write_reg(const u32 addr, const u32 value)
|
||||
return false;
|
||||
}
|
||||
|
||||
template<>
|
||||
void spu_exec_loader::load() const
|
||||
void spu_load_exec(const spu_exec_object& elf)
|
||||
{
|
||||
auto spu = idm::make_ptr<RawSPUThread>("TEST_SPU");
|
||||
|
||||
for (const auto& prog : progs)
|
||||
for (const auto& prog : elf.progs)
|
||||
{
|
||||
if (prog.p_type == 0x1 /* LOAD */ && prog.p_memsz)
|
||||
{
|
||||
@ -248,5 +247,5 @@ void spu_exec_loader::load() const
|
||||
}
|
||||
|
||||
spu->cpu_init();
|
||||
spu->npc = header.e_entry;
|
||||
spu->npc = elf.header.e_entry;
|
||||
}
|
||||
|
@ -8,20 +8,22 @@
|
||||
#include "Emu/Cell/ErrorCodes.h"
|
||||
#include "sys_prx.h"
|
||||
|
||||
extern std::shared_ptr<lv2_prx_t> ppu_load_prx(const ppu_prx_object&);
|
||||
|
||||
logs::channel sys_prx("sys_prx", logs::level::notice);
|
||||
|
||||
s32 prx_load_module(std::string path, u64 flags, vm::ptr<sys_prx_load_module_option_t> pOpt)
|
||||
{
|
||||
sys_prx.warning("prx_load_module(path='%s', flags=0x%llx, pOpt=*0x%x)", path.c_str(), flags, pOpt);
|
||||
|
||||
const ppu_prx_loader loader = fs::file(vfs::get(path));
|
||||
const ppu_prx_object obj = fs::file(vfs::get(path));
|
||||
|
||||
if (loader != elf_error::ok)
|
||||
if (obj != elf_error::ok)
|
||||
{
|
||||
return CELL_PRX_ERROR_ILLEGAL_LIBRARY;
|
||||
}
|
||||
|
||||
const auto prx = loader.load();
|
||||
const auto prx = ppu_load_prx(obj);
|
||||
|
||||
if (!prx)
|
||||
{
|
||||
|
@ -15,14 +15,14 @@ logs::channel sys_spu("sys_spu", logs::level::notice);
|
||||
|
||||
void LoadSpuImage(const fs::file& stream, u32& spu_ep, u32 addr)
|
||||
{
|
||||
const spu_exec_loader loader = stream;
|
||||
const spu_exec_object obj = stream;
|
||||
|
||||
if (loader != elf_error::ok)
|
||||
if (obj != elf_error::ok)
|
||||
{
|
||||
throw fmt::exception("Failed to load SPU image: %s" HERE, loader.get_error());
|
||||
throw fmt::exception("Failed to load SPU image: %s" HERE, obj.get_error());
|
||||
}
|
||||
|
||||
for (const auto& prog : loader.progs)
|
||||
for (const auto& prog : obj.progs)
|
||||
{
|
||||
if (prog.p_type == 0x1 /* LOAD */)
|
||||
{
|
||||
@ -30,7 +30,7 @@ void LoadSpuImage(const fs::file& stream, u32& spu_ep, u32 addr)
|
||||
}
|
||||
}
|
||||
|
||||
spu_ep = loader.header.e_entry;
|
||||
spu_ep = obj.header.e_entry;
|
||||
}
|
||||
|
||||
u32 LoadSpuImage(const fs::file& stream, u32& spu_ep)
|
||||
|
@ -355,8 +355,7 @@ static void arm_patch_refs(u32 refs, u32 addr)
|
||||
|
||||
}
|
||||
|
||||
template<>
|
||||
void arm_exec_loader::load() const
|
||||
void arm_load_exec(const arm_exec_object& elf)
|
||||
{
|
||||
arm_initialize_modules();
|
||||
|
||||
@ -373,7 +372,7 @@ void arm_exec_loader::load() const
|
||||
u32 tls_fsize{};
|
||||
u32 tls_vsize{};
|
||||
|
||||
for (const auto& prog : progs)
|
||||
for (const auto& prog : elf.progs)
|
||||
{
|
||||
if (prog.p_type == 0x1 /* LOAD */ && prog.p_memsz)
|
||||
{
|
||||
@ -397,7 +396,7 @@ void arm_exec_loader::load() const
|
||||
}
|
||||
}
|
||||
|
||||
if (!module_info) module_info.set(start_addr + header.e_entry);
|
||||
if (!module_info) module_info.set(start_addr + elf.header.e_entry);
|
||||
if (!libent) libent.set(start_addr + module_info->libent_top);
|
||||
if (!libstub) libstub.set(start_addr + module_info->libstub_top);
|
||||
|
||||
|
@ -39,6 +39,11 @@ extern atomic_t<u32> g_ppu_core[2];
|
||||
|
||||
extern u64 get_system_time();
|
||||
|
||||
extern void ppu_load_exec(const ppu_exec_object&);
|
||||
extern void spu_load_exec(const spu_exec_object&);
|
||||
extern void arm_load_exec(const arm_exec_object&);
|
||||
extern std::shared_ptr<struct lv2_prx_t> ppu_load_prx(const ppu_prx_object&);
|
||||
|
||||
fs::file g_tty;
|
||||
|
||||
namespace rpcs3
|
||||
@ -173,10 +178,10 @@ void Emulator::Load()
|
||||
}
|
||||
|
||||
const fs::file elf_file(m_path);
|
||||
ppu_exec_loader ppu_exec;
|
||||
ppu_prx_loader ppu_prx;
|
||||
spu_exec_loader spu_exec;
|
||||
arm_exec_loader arm_exec;
|
||||
ppu_exec_object ppu_exec;
|
||||
ppu_prx_object ppu_prx;
|
||||
spu_exec_object spu_exec;
|
||||
arm_exec_object arm_exec;
|
||||
|
||||
if (!elf_file)
|
||||
{
|
||||
@ -230,7 +235,7 @@ void Emulator::Load()
|
||||
|
||||
vfs::dump();
|
||||
|
||||
ppu_exec.load();
|
||||
ppu_load_exec(ppu_exec);
|
||||
|
||||
Emu.GetCallbackManager().Init();
|
||||
fxm::import<GSRender>(PURE_EXPR(Emu.GetCallbacks().get_gs_render())); // TODO: must be created in appropriate sys_rsx syscall
|
||||
@ -240,7 +245,7 @@ void Emulator::Load()
|
||||
// PPU PRX (experimental)
|
||||
m_status = Ready;
|
||||
vm::ps3::init();
|
||||
ppu_prx.load();
|
||||
ppu_load_prx(ppu_prx);
|
||||
GetCallbackManager().Init();
|
||||
}
|
||||
else if (spu_exec.open(elf_file) == elf_error::ok)
|
||||
@ -248,23 +253,23 @@ void Emulator::Load()
|
||||
// SPU executable (experimental)
|
||||
m_status = Ready;
|
||||
vm::ps3::init();
|
||||
spu_exec.load();
|
||||
spu_load_exec(spu_exec);
|
||||
}
|
||||
else if (arm_exec.open(elf_file) == elf_error::ok)
|
||||
{
|
||||
// ARMv7 executable
|
||||
m_status = Ready;
|
||||
vm::psv::init();
|
||||
arm_exec.load();
|
||||
arm_load_exec(arm_exec);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR(LOADER, "Invalid or unsupported file format: %s", m_path);
|
||||
|
||||
LOG_WARNING(LOADER, "** ppu_exec_loader -> %s", ppu_exec.get_error());
|
||||
LOG_WARNING(LOADER, "** ppu_prx_loader -> %s", ppu_prx.get_error());
|
||||
LOG_WARNING(LOADER, "** spu_exec_loader -> %s", spu_exec.get_error());
|
||||
LOG_WARNING(LOADER, "** arm_exec_loader -> %s", arm_exec.get_error());
|
||||
LOG_WARNING(LOADER, "** ppu_exec -> %s", ppu_exec.get_error());
|
||||
LOG_WARNING(LOADER, "** ppu_prx -> %s", ppu_prx.get_error());
|
||||
LOG_WARNING(LOADER, "** spu_exec -> %s", spu_exec.get_error());
|
||||
LOG_WARNING(LOADER, "** arm_exec -> %s", arm_exec.get_error());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -340,7 +340,7 @@ SettingsDialog::SettingsDialog(wxWindow* parent)
|
||||
for (const auto& prxf : fs::dir(lle_dir))
|
||||
{
|
||||
// List found unselected modules
|
||||
if (!prxf.is_directory && ppu_prx_loader(fs::file(lle_dir + prxf.name)) == elf_error::ok && !set.count(prxf.name))
|
||||
if (!prxf.is_directory && ppu_prx_object(fs::file(lle_dir + prxf.name)) == elf_error::ok && !set.count(prxf.name))
|
||||
{
|
||||
lle_module_list_unselected.push_back(prxf.name);
|
||||
}
|
||||
|
@ -127,14 +127,7 @@ struct elf_shdr
|
||||
en_t<sz_t> sh_entsize;
|
||||
};
|
||||
|
||||
// Default elf_loader::load() return type, specialized to change.
|
||||
template<typename T>
|
||||
struct elf_load_result
|
||||
{
|
||||
using type = void;
|
||||
};
|
||||
|
||||
// ELF loader errors
|
||||
// ELF loading error
|
||||
enum class elf_error
|
||||
{
|
||||
ok = 0,
|
||||
@ -154,7 +147,7 @@ enum class elf_error
|
||||
header_os,
|
||||
};
|
||||
|
||||
// ELF loader error information
|
||||
// ELF loading error information
|
||||
template<>
|
||||
struct unveil<elf_error>
|
||||
{
|
||||
@ -183,11 +176,11 @@ struct unveil<elf_error>
|
||||
}
|
||||
};
|
||||
|
||||
// ELF loader with specified parameters.
|
||||
// ELF object with specified parameters.
|
||||
// en_t: endianness (specify le_t or be_t)
|
||||
// sz_t: size (specify u32 for ELF32, u64 for ELF64)
|
||||
template<template<typename T> class en_t, typename sz_t, elf_machine Machine, elf_os OS, elf_type Type>
|
||||
class elf_loader
|
||||
class elf_object
|
||||
{
|
||||
elf_error m_error{};
|
||||
|
||||
@ -208,9 +201,9 @@ public:
|
||||
std::vector<shdr_t> shdrs;
|
||||
|
||||
public:
|
||||
elf_loader() = default;
|
||||
elf_object() = default;
|
||||
|
||||
elf_loader(const fs::file& stream, u64 offset = 0)
|
||||
elf_object(const fs::file& stream, u64 offset = 0)
|
||||
{
|
||||
open(stream, offset);
|
||||
}
|
||||
@ -346,14 +339,9 @@ public:
|
||||
{
|
||||
return m_error;
|
||||
}
|
||||
|
||||
// Format-specific loader function (must be specialized)
|
||||
typename elf_load_result<elf_loader>::type load() const;
|
||||
};
|
||||
|
||||
using ppu_exec_loader = elf_loader<be_t, u64, elf_machine::ppc64, elf_os::none, elf_type::exec>;
|
||||
using ppu_prx_loader = elf_loader<be_t, u64, elf_machine::ppc64, elf_os::lv2, elf_type::prx>;
|
||||
using spu_exec_loader = elf_loader<be_t, u32, elf_machine::spu, elf_os::none, elf_type::exec>;
|
||||
using arm_exec_loader = elf_loader<le_t, u32, elf_machine::arm, elf_os::none, elf_type::none>;
|
||||
|
||||
template<> struct elf_load_result<ppu_prx_loader> { using type = std::shared_ptr<struct lv2_prx_t>; };
|
||||
using ppu_exec_object = elf_object<be_t, u64, elf_machine::ppc64, elf_os::none, elf_type::exec>;
|
||||
using ppu_prx_object = elf_object<be_t, u64, elf_machine::ppc64, elf_os::lv2, elf_type::prx>;
|
||||
using spu_exec_object = elf_object<be_t, u32, elf_machine::spu, elf_os::none, elf_type::exec>;
|
||||
using arm_exec_object = elf_object<le_t, u32, elf_machine::arm, elf_os::none, elf_type::none>;
|
||||
|
Loading…
Reference in New Issue
Block a user