Exemple #1
0
void UnloadModules()
{
	for(u32 i=0; i<g_modules_list.GetCount(); ++i)
	{
		g_modules_list[i].SetLoaded(false);
	}

	g_modules_funcs_list.Clear();
}
SectionInfo::~SectionInfo()
{
	sections_list.RemoveFAt(section_num);

	for(u32 i=section_num + 1; i<sections_list.GetCount(); ++i)
	{
		sections_list[i].shdr.sh_offset -= code.GetCount();
		sections_list[i].shdr.sh_name -= name.length();
	}

	section_offs -= code.GetCount();
	section_name_offs -= name.length();
}
Exemple #3
0
bool UnloadFunc(u32 id)
{
	for(u32 i=0; i<g_modules_funcs_list.GetCount(); ++i)
	{
		if(g_modules_funcs_list[i].id == id)
		{
			g_modules_funcs_list.RemoveAt(i);

			return true;
		}
	}

	return false;
}
Exemple #4
0
Module::Module(const char* name, u16 id)
	: m_is_loaded(false)
	, m_name(name)
	, m_id(id)
{
	g_modules_list.Add(this);
}
Exemple #5
0
bool UnloadFunc(u32 id)
{
	std::lock_guard<std::mutex> lock(g_funcs_lock);

	for(u32 i=0; i<g_modules_funcs_list.GetCount(); ++i)
	{
		if(g_modules_funcs_list[i].id == id)
		{
			g_modules_funcs_list.RemoveFAt(i);

			return true;
		}
	}

	return false;
}
Exemple #6
0
Module* GetModuleByName(const wxString& name)
{
	for(u32 i=0; i<g_modules_list.GetCount(); ++i)
	{
		if(g_modules_list[i].GetName().Cmp(name) == 0) return &g_modules_list[i];
	}

	return nullptr;
}
Exemple #7
0
Module* GetModuleById(u16 id)
{
	for(u32 i=0; i<g_modules_list.GetCount(); ++i)
	{
		if(g_modules_list[i].GetID() == id) return &g_modules_list[i];
	}

	return nullptr;
}
Exemple #8
0
bool IsLoadedFunc(u32 id)
{
	for(u32 i=0; i<g_modules_funcs_list.GetCount(); ++i)
	{
		if(g_modules_funcs_list[i].id == id) return true;
	}

	return false;
}
Exemple #9
0
void Module::Load()
{
	for(u32 i=0; i<m_funcs_list.GetCount(); ++i)
	{
		if(IsLoadedFunc(m_funcs_list[i].id)) continue;

		g_modules_funcs_list.Add(m_funcs_list[i]);
	}
}
Exemple #10
0
void StaticExecute(u32 code)
{
	if (code < g_static_funcs_list.GetCount())
	{
		(*g_static_funcs_list[code].func)();
	}
	else
	{
		ConLog.Error("StaticExecute(%d): unknown function or illegal opcode", code);
	}
}
SectionInfo::SectionInfo(const wxString& _name)
{
	name = _name.ToStdString();
	memset(&shdr, 0, sizeof(Elf64_Shdr));

	section_num = sections_list.Add(this);

	shdr.sh_offset = section_offs;
	shdr.sh_name = section_name_offs;

	section_name_offs += name.length() + 1;
}
Exemple #12
0
bool CallFunc(u32 num)
{
	for(u32 i=0; i<g_modules_funcs_list.GetCount(); ++i)
	{
		if(g_modules_funcs_list[i].id == num)
		{
			(*g_modules_funcs_list[i].func)();
			return true;
		}
	}

	return false;
}
Exemple #13
0
bool CallFunc(u32 id, s64& ret)
{
	for(u32 i=0; i<g_modules_funcs_list.GetCount(); ++i)
	{
		if(g_modules_funcs_list[i].id == id)
		{
			ret = g_modules_funcs_list[i].func();

			return true;
		}
	}

	return false;
}
void SectionInfo::SetDataSize(u32 size, u32 align)
{
	if(align) shdr.sh_addralign = align;
	if(shdr.sh_addralign) size = Memory.AlignAddr(size, shdr.sh_addralign);

	if(code.GetCount())
	{
		for(u32 i=section_num + 1; i<sections_list.GetCount(); ++i)
		{
			sections_list[i].shdr.sh_offset -= code.GetCount();
		}

		section_offs -= code.GetCount();
	}

	code.SetCount(size);

	section_offs += size;

	for(u32 i=section_num + 1; i<sections_list.GetCount(); ++i)
	{
		sections_list[i].shdr.sh_offset += size;
	}
}
Exemple #15
0
void UnloadModules()
{
	for(u32 i=0; i<3; ++i)
	{
		for(u32 j=0; j<g_max_module_id; ++j)
		{
			if(g_modules[i][j])
			{
				g_modules[i][j]->UnLoad();
			}
		}
	}

	g_modules_funcs_list.Clear();
}
Exemple #16
0
void UnloadModules()
{
	for(u32 i=0; i<3; ++i)
	{
		for(u32 j=0; j<g_max_module_id; ++j)
		{
			if(g_modules[i][j])
			{
				g_modules[i][j]->UnLoad();
			}
		}
	}

	std::lock_guard<std::mutex> lock(g_funcs_lock);
	g_modules_funcs_list.Clear();
}
Exemple #17
0
bool Module::Load(u32 id)
{
	if(IsLoadedFunc(id)) return false;

	for(u32 i=0; i<m_funcs_list.GetCount(); ++i)
	{
		if(m_funcs_list[i].id == id)
		{
			g_modules_funcs_list.Add(m_funcs_list[i]);

			return true;
		}
	}

	return false;
}
Exemple #18
0
bool CallFunc(u32 num)
{
	func_caller* func = nullptr;
	{
		std::lock_guard<std::mutex> lock(g_funcs_lock);

		for(u32 i=0; i<g_modules_funcs_list.GetCount(); ++i)
		{
			if(g_modules_funcs_list[i].id == num)
			{
				func = g_modules_funcs_list[i].func;
				break;
			}
		}
	}
	if (func)
	{
		(*func)();
		return true;
	}
	return false;
}
Exemple #19
0
void StaticAnalyse(void* ptr, u32 size, u32 base)
{
	u32* data = (u32*)ptr; size /= 4;

	if(!Ini.HLEHookStFunc.GetValue())
		return;

	// TODO: optimize search
	for (u32 i = 0; i < size; i++)
	{
		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)
			{
				bool found = true;
				u32 can_skip = 0;
				for (u32 k = i, x = 0; x + 1 <= g_static_funcs_list[j].ops.GetCount(); k++, x++)
				{
					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.Write("Function '%s' hooked (addr=0x%x)", g_static_funcs_list[j].name, 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; // 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", g_static_funcs_list[j].name);
					}
					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", g_static_funcs_list[j].name);
							}
						}
					}
				}
				else
				{
					res |= GSR_EXCESS;
					ConLog.Error("Function '%s' hooked twice", g_static_funcs_list[j].name);
				}
			}

			// 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", std::string(name, 9).c_str());
			}
			else
			{
				ConLog.Error("Function group [%s] failed:%s%s", std::string(name, 9).c_str(),
					(res & GSR_MISSING ? " missing;" : ""),
					(res & GSR_EXCESS ? " excess;" : ""));
			}
		}
	}
}
Exemple #20
0
void StaticFinalize()
{
	g_static_funcs_list.Clear();
}