mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-13 02:08:49 +12:00
parent
8011cc8ec4
commit
01dbb8eb9a
42 changed files with 1687 additions and 613 deletions
|
@ -5,7 +5,7 @@
|
|||
|
||||
extern ArrayF<SFunc> g_static_funcs_list;
|
||||
|
||||
void StaticAnalyse(void* ptr, u32 size)
|
||||
void StaticAnalyse(void* ptr, u32 size, u32 base)
|
||||
{
|
||||
u32* data = (u32*)ptr; size /= 4;
|
||||
|
||||
|
@ -17,35 +17,167 @@ void StaticAnalyse(void* ptr, u32 size)
|
|||
{
|
||||
for (u32 j = 0; j < g_static_funcs_list.GetCount(); j++)
|
||||
{
|
||||
if ((data[i] & g_static_funcs_list[j].ops[0].mask) == g_static_funcs_list[j].ops[0].crc && (i + g_static_funcs_list[j].ops.GetCount()) < size)
|
||||
if ((data[i] & g_static_funcs_list[j].ops[0].mask) == g_static_funcs_list[j].ops[0].crc)
|
||||
{
|
||||
bool found = true;
|
||||
for (u32 k = i + 1, x = 1; x < g_static_funcs_list[j].ops.GetCount(); k++, x++)
|
||||
u32 can_skip = 0;
|
||||
for (u32 k = i, x = 0; x + 1 <= g_static_funcs_list[j].ops.GetCount(); k++, x++)
|
||||
{
|
||||
// skip NOP
|
||||
if (data[k] == se32(0x60000000))
|
||||
{
|
||||
k++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((data[k] & g_static_funcs_list[j].ops[x].mask) != g_static_funcs_list[j].ops[x].crc)
|
||||
if (k >= size)
|
||||
{
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// skip NOP
|
||||
if (data[k] == se32(0x60000000))
|
||||
{
|
||||
x--;
|
||||
continue;
|
||||
}
|
||||
|
||||
const u32 mask = g_static_funcs_list[j].ops[x].mask;
|
||||
const u32 crc = g_static_funcs_list[j].ops[x].crc;
|
||||
|
||||
if (!mask)
|
||||
{
|
||||
// TODO: define syntax
|
||||
if (crc < 4) // skip various number of instructions that don't match next pattern entry
|
||||
{
|
||||
can_skip += crc;
|
||||
k--; // process this position again
|
||||
}
|
||||
else if (data[k] != crc) // skippable pattern ("optional" instruction), no mask allowed
|
||||
{
|
||||
k--;
|
||||
if (can_skip) // cannot define this behaviour properly
|
||||
{
|
||||
ConLog.Warning("StaticAnalyse(): can_skip = %d (unchanged)", can_skip);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (can_skip) // cannot define this behaviour properly
|
||||
{
|
||||
ConLog.Warning("StaticAnalyse(): can_skip = %d (set to 0)", can_skip);
|
||||
can_skip = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((data[k] & mask) != crc) // masked pattern
|
||||
{
|
||||
if (can_skip)
|
||||
{
|
||||
can_skip--;
|
||||
}
|
||||
else
|
||||
{
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
can_skip = 0;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
{
|
||||
ConLog.Success("Function '%s' hooked", wxString(g_static_funcs_list[j].name).wx_str());
|
||||
data[i] = re(0x39600000 | j); // li r11, j
|
||||
ConLog.Write("Function '%s' hooked (addr=0x%x)", wxString(g_static_funcs_list[j].name).wx_str(), i * 4 + base);
|
||||
g_static_funcs_list[j].found++;
|
||||
data[i+0] = re32(0x39600000 | j); // li r11, j
|
||||
data[i+1] = se32(0x44000003); // sc 3
|
||||
data[i+2] = se32(0x4e800020); // blr
|
||||
i += 2; // ???
|
||||
i += 2; // skip modified code
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check function groups
|
||||
for (u32 i = 0; i < g_static_funcs_list.GetCount(); i++)
|
||||
{
|
||||
if (g_static_funcs_list[i].found) // start from some group
|
||||
{
|
||||
const u64 group = g_static_funcs_list[i].group;
|
||||
|
||||
enum GroupSearchResult : u32
|
||||
{
|
||||
GSR_SUCCESS = 0, // every function from this group has been found once
|
||||
GSR_MISSING = 1, // (error) some function not found
|
||||
GSR_EXCESS = 2, // (error) some function found twice or more
|
||||
};
|
||||
u32 res = GSR_SUCCESS;
|
||||
|
||||
// analyse
|
||||
for (u32 j = i; j < g_static_funcs_list.GetCount(); j++) if (g_static_funcs_list[j].group == group)
|
||||
{
|
||||
u32 count = g_static_funcs_list[j].found;
|
||||
|
||||
if (count == 0) // not found
|
||||
{
|
||||
// check if this function has been found with different pattern
|
||||
for (u32 k = i; k < g_static_funcs_list.GetCount(); k++) if (g_static_funcs_list[k].group == group)
|
||||
{
|
||||
if (k != j && g_static_funcs_list[k].ptr == g_static_funcs_list[j].ptr)
|
||||
{
|
||||
count += g_static_funcs_list[k].found;
|
||||
}
|
||||
}
|
||||
if (count == 0)
|
||||
{
|
||||
res |= GSR_MISSING;
|
||||
ConLog.Error("Function '%s' not found", wxString(g_static_funcs_list[j].name).wx_str());
|
||||
}
|
||||
else if (count > 1)
|
||||
{
|
||||
res |= GSR_EXCESS;
|
||||
}
|
||||
}
|
||||
else if (count == 1) // found
|
||||
{
|
||||
// ensure that this function has NOT been found with different pattern
|
||||
for (u32 k = i; k < g_static_funcs_list.GetCount(); k++) if (g_static_funcs_list[k].group == group)
|
||||
{
|
||||
if (k != j && g_static_funcs_list[k].ptr == g_static_funcs_list[j].ptr)
|
||||
{
|
||||
if (g_static_funcs_list[k].found)
|
||||
{
|
||||
res |= GSR_EXCESS;
|
||||
ConLog.Error("Function '%s' hooked twice", wxString(g_static_funcs_list[j].name).wx_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
res |= GSR_EXCESS;
|
||||
ConLog.Error("Function '%s' hooked twice", wxString(g_static_funcs_list[j].name).wx_str());
|
||||
}
|
||||
}
|
||||
|
||||
// clear data
|
||||
for (u32 j = i; j < g_static_funcs_list.GetCount(); j++)
|
||||
{
|
||||
if (g_static_funcs_list[j].group == group) g_static_funcs_list[j].found = 0;
|
||||
}
|
||||
|
||||
char name[9] = "????????";
|
||||
|
||||
*(u64*)name = group;
|
||||
|
||||
if (res == GSR_SUCCESS)
|
||||
{
|
||||
ConLog.Success("Function group [%s] successfully hooked", wxString(name, 9).wx_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
ConLog.Error("Function group [%s] failed:%s%s", wxString(name, 9).wx_str(),
|
||||
wxString(res & GSR_MISSING ? " missing;" : "").wx_str(),
|
||||
wxString(res & GSR_EXCESS ? " excess;" : "").wx_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StaticExecute(u32 code)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue