mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-01-01 12:08:12 +00:00
SPU Analyser: Detect invalid relative branches
This commit is contained in:
parent
8e15de5c83
commit
d699db2d19
@ -1024,7 +1024,7 @@ void spu_cache::initialize(bool build_existing_cache)
|
||||
}
|
||||
}
|
||||
|
||||
if (new_entry != umax && !spu_thread::is_exec_code(new_entry, { reinterpret_cast<const u8*>(ls.data()), SPU_LS_SIZE }))
|
||||
if (new_entry != umax && !spu_thread::is_exec_code(new_entry, { reinterpret_cast<const u8*>(ls.data()), SPU_LS_SIZE }, 0, true))
|
||||
{
|
||||
new_entry = umax;
|
||||
}
|
||||
@ -1033,7 +1033,7 @@ void spu_cache::initialize(bool build_existing_cache)
|
||||
{
|
||||
new_entry = start_new;
|
||||
|
||||
while (new_entry < next_func && (ls[start_new / 4] < 0x3fffc || !spu_thread::is_exec_code(new_entry, { reinterpret_cast<const u8*>(ls.data()), SPU_LS_SIZE })))
|
||||
while (new_entry < next_func && (ls[start_new / 4] < 0x3fffc || !spu_thread::is_exec_code(new_entry, { reinterpret_cast<const u8*>(ls.data()), SPU_LS_SIZE }, 0, true)))
|
||||
{
|
||||
new_entry += 4;
|
||||
}
|
||||
@ -2281,13 +2281,13 @@ std::vector<u32> spu_thread::discover_functions(u32 base_addr, std::span<const u
|
||||
calls.erase(std::remove_if(calls.begin(), calls.end(), [&](u32 caller)
|
||||
{
|
||||
// Check the validity of both the callee code and the following caller code
|
||||
return !is_exec_code(caller, ls, base_addr) || !is_exec_code(caller + 4, ls, base_addr);
|
||||
return !is_exec_code(caller, ls, base_addr, true) || !is_exec_code(caller + 4, ls, base_addr, true);
|
||||
}), calls.end());
|
||||
|
||||
branches.erase(std::remove_if(branches.begin(), branches.end(), [&](u32 caller)
|
||||
{
|
||||
// Check the validity of the callee code
|
||||
return !is_exec_code(caller, ls, base_addr);
|
||||
return !is_exec_code(caller, ls, base_addr, true);
|
||||
}), branches.end());
|
||||
|
||||
std::vector<u32> addrs;
|
||||
|
@ -4119,9 +4119,11 @@ bool spu_thread::check_mfc_interrupts(u32 next_pc)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool spu_thread::is_exec_code(u32 addr, std::span<const u8> ls_ptr, u32 base_addr)
|
||||
bool spu_thread::is_exec_code(u32 addr, std::span<const u8> ls_ptr, u32 base_addr, bool avoid_dead_code)
|
||||
{
|
||||
for (u32 i = 0; i < 30; i++)
|
||||
bool had_conditional = false;
|
||||
|
||||
for (u32 i = 0; i < 40; i++)
|
||||
{
|
||||
if (addr & ~0x3FFFC)
|
||||
{
|
||||
@ -4179,6 +4181,51 @@ bool spu_thread::is_exec_code(u32 addr, std::span<const u8> ls_ptr, u32 base_add
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case spu_itype::BR:
|
||||
case spu_itype::BRNZ:
|
||||
case spu_itype::BRZ:
|
||||
case spu_itype::BRHNZ:
|
||||
case spu_itype::BRHZ:
|
||||
case spu_itype::BRSL:
|
||||
{
|
||||
const s32 rel = bf_t<s32, 0, 18>::extract(static_cast<s32>(u32{op.i16} << 2));
|
||||
|
||||
if (rel == 0 && !had_conditional && avoid_dead_code)
|
||||
{
|
||||
// Infinite loop 100%, detect that as invalid code
|
||||
return false;
|
||||
}
|
||||
|
||||
// Detect "invalid" relative branches
|
||||
// Branch offsets that, although are the only way to get X code address using relative address
|
||||
// Rely on overflow/underflow of SPU memory bounds
|
||||
// Thus they would behave differently if SPU LS memory size was to increase (evolving the CELL architecture was the original plan)
|
||||
// Making them highly unlikely to be valid code
|
||||
|
||||
if (rel < 0)
|
||||
{
|
||||
if (addr < 0u - rel)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (SPU_LS_SIZE - addr <= rel + 0u)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (usz res_i = 1; res_i < results.size(); res_i++)
|
||||
{
|
||||
@ -4203,6 +4250,8 @@ bool spu_thread::is_exec_code(u32 addr, std::span<const u8> ls_ptr, u32 base_add
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
had_conditional = true;
|
||||
}
|
||||
|
||||
addr = spu_branch_target(results[0]);
|
||||
|
@ -835,7 +835,7 @@ public:
|
||||
void set_events(u32 bits);
|
||||
void set_interrupt_status(bool enable);
|
||||
bool check_mfc_interrupts(u32 next_pc);
|
||||
static bool is_exec_code(u32 addr, std::span<const u8> ls_ptr, u32 base_addr = 0); // Only a hint, do not rely on it other than debugging purposes
|
||||
static bool is_exec_code(u32 addr, std::span<const u8> ls_ptr, u32 base_addr = 0, bool avoid_dead_code = false); // Only a hint, do not rely on it other than debugging purposes
|
||||
static std::vector<u32> discover_functions(u32 base_addr, std::span<const u8> ls, bool is_known_addr, u32 /*entry*/);
|
||||
u32 get_ch_count(u32 ch);
|
||||
s64 get_ch_value(u32 ch);
|
||||
|
Loading…
Reference in New Issue
Block a user