Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #5088 from sepalani/mega_signature
SignatureDB: Support for WiiTools MEGA files added
- Loading branch information
Showing
10 changed files
with
256 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
169 changes: 169 additions & 0 deletions
169
Source/Core/Core/PowerPC/SignatureDB/MEGASignatureDB.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
// Copyright 2017 Dolphin Emulator Project | ||
// Licensed under GPLv2+ | ||
// Refer to the license.txt file included. | ||
|
||
#include "Core/PowerPC/SignatureDB/MEGASignatureDB.h" | ||
|
||
#include <cstddef> | ||
#include <cstdlib> | ||
#include <fstream> | ||
#include <limits> | ||
|
||
#include "Common/FileUtil.h" | ||
#include "Common/Logging/Log.h" | ||
#include "Common/StringUtil.h" | ||
|
||
#include "Core/PowerPC/PPCSymbolDB.h" | ||
#include "Core/PowerPC/PowerPC.h" | ||
|
||
static constexpr size_t INSTRUCTION_HEXSTRING_LENGTH = 8; | ||
|
||
MEGASignatureDB::MEGASignatureDB() = default; | ||
MEGASignatureDB::~MEGASignatureDB() = default; | ||
|
||
bool MEGASignatureDB::Load(const std::string& file_path) | ||
{ | ||
std::string line; | ||
std::ifstream ifs; | ||
OpenFStream(ifs, file_path, std::ios_base::in); | ||
|
||
if (!ifs) | ||
return false; | ||
for (size_t i = 1; std::getline(ifs, line); ++i) | ||
{ | ||
std::istringstream iss(line); | ||
MEGASignature sig; | ||
|
||
if (GetCode(&sig, &iss) && GetName(&sig, &iss) && GetRefs(&sig, &iss)) | ||
{ | ||
m_signatures.push_back(sig); | ||
} | ||
else | ||
{ | ||
WARN_LOG(OSHLE, "MEGA database failed to parse line %zu", i); | ||
} | ||
} | ||
return true; | ||
} | ||
|
||
void MEGASignatureDB::Apply(PPCSymbolDB* symbol_db) const | ||
{ | ||
for (auto& it : symbol_db->AccessSymbols()) | ||
{ | ||
u32 hash = it.first; | ||
auto& symbol = it.second; | ||
for (const auto& sig : m_signatures) | ||
{ | ||
if (Compare(symbol.address, symbol.size, sig)) | ||
{ | ||
symbol.name = sig.name; | ||
INFO_LOG(OSHLE, "Found %s at %08x (size: %08x)!", sig.name.c_str(), symbol.address, | ||
symbol.size); | ||
break; | ||
} | ||
} | ||
} | ||
symbol_db->Index(); | ||
} | ||
|
||
void MEGASignatureDB::List() const | ||
{ | ||
for (const auto& entry : m_signatures) | ||
{ | ||
DEBUG_LOG(OSHLE, "%s : %zu bytes", entry.name.c_str(), entry.code.size() * sizeof(u32)); | ||
} | ||
INFO_LOG(OSHLE, "%zu functions known in current MEGA database.", m_signatures.size()); | ||
} | ||
|
||
bool MEGASignatureDB::GetCode(MEGASignature* sig, std::istringstream* iss) const | ||
{ | ||
std::string code; | ||
if ((*iss >> code) && (code.length() % INSTRUCTION_HEXSTRING_LENGTH) == 0) | ||
{ | ||
for (size_t i = 0; i < code.length(); i += INSTRUCTION_HEXSTRING_LENGTH) | ||
{ | ||
std::string instruction = code.substr(i, INSTRUCTION_HEXSTRING_LENGTH); | ||
u32 num = static_cast<u32>(strtoul(instruction.c_str(), nullptr, 16)); | ||
if (num != 0 || instruction == "........") | ||
{ | ||
sig->code.emplace_back(num); | ||
} | ||
else | ||
{ | ||
WARN_LOG(OSHLE, "MEGA database failed to parse code"); | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
return false; | ||
} | ||
|
||
bool MEGASignatureDB::GetFunctionName(std::istringstream* iss, std::string* name) const | ||
{ | ||
std::string buffer; | ||
|
||
std::getline(*iss, buffer); | ||
size_t next = buffer.find(" ^"); | ||
*name = StripSpaces(buffer.substr(0, next)); | ||
|
||
if (name->empty()) | ||
return false; | ||
|
||
if (next == std::string::npos) | ||
next = buffer.length(); | ||
iss->str(buffer.substr(next)); | ||
iss->clear(); | ||
return true; | ||
} | ||
|
||
bool MEGASignatureDB::GetName(MEGASignature* sig, std::istringstream* iss) const | ||
{ | ||
std::string unknown; | ||
return (*iss >> unknown) && GetFunctionName(iss, &sig->name); | ||
} | ||
|
||
bool MEGASignatureDB::GetRefs(MEGASignature* sig, std::istringstream* iss) const | ||
{ | ||
std::string num, ref; | ||
u32 ref_count = 1; | ||
while (*iss && (*iss >> num) && !num.empty()) | ||
{ | ||
num = num.substr(1); | ||
const char* ptr = num.c_str(); | ||
char* endptr; | ||
u64 offset = strtoul(ptr, &endptr, 16); | ||
|
||
if (ptr == endptr || offset > std::numeric_limits<u32>::max()) | ||
{ | ||
WARN_LOG(OSHLE, "MEGA database failed to parse reference %u offset", ref_count); | ||
return false; | ||
} | ||
|
||
if (!GetFunctionName(iss, &ref)) | ||
{ | ||
WARN_LOG(OSHLE, "MEGA database failed to parse reference %u name", ref_count); | ||
return false; | ||
} | ||
sig->refs.emplace_back(static_cast<u32>(offset), ref); | ||
|
||
ref_count += 1; | ||
num.clear(); | ||
ref.clear(); | ||
} | ||
return true; | ||
} | ||
|
||
bool MEGASignatureDB::Compare(u32 address, u32 size, const MEGASignature& sig) const | ||
{ | ||
if (size != sig.code.size() * sizeof(u32)) | ||
return false; | ||
|
||
for (size_t i = 0; i < sig.code.size(); ++i) | ||
{ | ||
if (sig.code[i] != 0 && | ||
PowerPC::HostRead_U32(static_cast<u32>(address + i * sizeof(u32))) != sig.code[i]) | ||
return false; | ||
} | ||
return true; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
// Copyright 2017 Dolphin Emulator Project | ||
// Licensed under GPLv2+ | ||
// Refer to the license.txt file included. | ||
|
||
#pragma once | ||
|
||
#include <sstream> | ||
#include <string> | ||
#include <vector> | ||
|
||
#include "Common/CommonTypes.h" | ||
|
||
class PPCSymbolDB; | ||
|
||
struct MEGASignatureReference | ||
{ | ||
MEGASignatureReference(u32 ref_offset, std::string ref_name) | ||
: offset(ref_offset), name(std::move(ref_name)) | ||
{ | ||
} | ||
u32 offset; | ||
std::string name; | ||
}; | ||
|
||
struct MEGASignature | ||
{ | ||
std::vector<u32> code; | ||
std::string name; | ||
std::vector<MEGASignatureReference> refs; | ||
}; | ||
|
||
// MEGA files from Megazig's WiiTools IDA plugin | ||
// -> https://github.com/Megazig/WiiTools | ||
// | ||
// Each line contains a function signature composed of: | ||
// - Hexstring representation with "." acting as a wildcard | ||
// - Name, represented as follow: ":0000 function_name" | ||
// - References located in the hexstring at offset: "^offset reference_name" | ||
class MEGASignatureDB | ||
{ | ||
public: | ||
MEGASignatureDB(); | ||
~MEGASignatureDB(); | ||
|
||
bool Load(const std::string& file_path); | ||
void Apply(PPCSymbolDB* symbol_db) const; | ||
void List() const; | ||
|
||
private: | ||
bool GetCode(MEGASignature* sig, std::istringstream* iss) const; | ||
bool GetFunctionName(std::istringstream* iss, std::string* name) const; | ||
bool GetName(MEGASignature* sig, std::istringstream* iss) const; | ||
bool GetRefs(MEGASignature* sig, std::istringstream* iss) const; | ||
bool Compare(u32 address, u32 size, const MEGASignature& sig) const; | ||
|
||
std::vector<MEGASignature> m_signatures; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters