#include #include "MipsFunctionPatternDb.h" #include "xml/FilteringNodeIterator.h" CMipsFunctionPatternDb::CMipsFunctionPatternDb(Framework::Xml::CNode* node) { Read(node); } CMipsFunctionPatternDb::~CMipsFunctionPatternDb() { } const CMipsFunctionPatternDb::PatternArray& CMipsFunctionPatternDb::GetPatterns() const { return m_patterns; } void CMipsFunctionPatternDb::Read(Framework::Xml::CNode* node) { auto patternsNode = node->Select("FunctionPatterns"); if(!patternsNode) return; m_patterns.reserve(patternsNode->GetChildCount()); for(Framework::Xml::CFilteringNodeIterator patternNodeIterator(patternsNode, "FunctionPattern"); !patternNodeIterator.IsEnd(); patternNodeIterator++) { auto patternNode = (*patternNodeIterator); const char* patternName = patternNode->GetAttribute("Name"); if(patternName == NULL) continue; const char* patternSource = patternNode->GetInnerText(); Pattern pattern = ParsePattern(patternSource); pattern.name = patternName; m_patterns.push_back(pattern); } } CMipsFunctionPatternDb::Pattern CMipsFunctionPatternDb::ParsePattern(const char* source) { Pattern result; result.items.reserve(0x40); bool insideComment = false; std::string currValue; while(1) { char currChar = (*source++); if(currChar == 0) break; if(insideComment) { if(currChar == '\n') { insideComment = false; } continue; } if(currChar == ';') { insideComment = true; continue; } if(isspace(currChar)) { if(currValue.length() != 0) { //Parse value PATTERNITEM item = {0}; if(ParsePatternItem(currValue.c_str(), item)) { result.items.push_back(item); } currValue.clear(); } continue; } currValue += currChar; } return result; } bool CMipsFunctionPatternDb::ParsePatternItem(const char* source, PATTERNITEM& result) { size_t sourceLength = strlen(source); if(!strcmp(source, "XXXXXXXX")) { result.mask = 0; result.value = 0; } else if((sourceLength == 8) && !strcmp(source + 4, "XXXX")) { result.mask = 0xFFFF0000; result.value = 0; sscanf(source, "%x", &result.value); result.value <<= 16; } else { result.mask = 0xFFFFFFFF; result.value = 0; sscanf(source, "%x", &result.value); if(result.value == 0) { return false; } } return true; } bool CMipsFunctionPatternDb::Pattern::Matches(uint32* text, uint32 textSize) const { textSize /= 4; if(textSize < items.size()) return false; unsigned int itemIndex = 0; unsigned int textIndex = 0; unsigned int matchCount = 0; while(1) { if(itemIndex == items.size()) break; if(textIndex == textSize) break; uint32 srcValue = text[textIndex++]; if(textIndex != 1 && srcValue == 0) continue; const PATTERNITEM& item(items[itemIndex++]); srcValue &= item.mask; if(srcValue != item.value) return false; matchCount++; } return (matchCount == items.size()); }