Added global big and little endian support to the pattern parser
This commit is contained in:
parent
989eade5d7
commit
8297e22f10
@ -6,6 +6,7 @@
|
|||||||
#include "lang/pattern_data.hpp"
|
#include "lang/pattern_data.hpp"
|
||||||
#include "ast_node.hpp"
|
#include "ast_node.hpp"
|
||||||
|
|
||||||
|
#include <bit>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -14,13 +15,15 @@ namespace hex::lang {
|
|||||||
|
|
||||||
class Evaluator {
|
class Evaluator {
|
||||||
public:
|
public:
|
||||||
Evaluator(prv::Provider* &provider);
|
Evaluator(prv::Provider* &provider, std::endian dataEndianess);
|
||||||
|
|
||||||
std::pair<Result, std::vector<PatternData*>> evaluate(const std::vector<ASTNode*>& ast);
|
std::pair<Result, std::vector<PatternData*>> evaluate(const std::vector<ASTNode*>& ast);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<std::string, ASTNode*> m_types;
|
std::unordered_map<std::string, ASTNode*> m_types;
|
||||||
prv::Provider* &m_provider;
|
prv::Provider* &m_provider;
|
||||||
|
std::endian m_dataEndianess;
|
||||||
|
|
||||||
|
|
||||||
std::pair<PatternData*, size_t> createStructPattern(ASTNodeVariableDecl *varDeclNode, u64 offset);
|
std::pair<PatternData*, size_t> createStructPattern(ASTNodeVariableDecl *varDeclNode, u64 offset);
|
||||||
std::pair<PatternData*, size_t> createUnionPattern(ASTNodeVariableDecl *varDeclNode, u64 offset);
|
std::pair<PatternData*, size_t> createUnionPattern(ASTNodeVariableDecl *varDeclNode, u64 offset);
|
||||||
|
@ -95,6 +95,11 @@ namespace hex::lang {
|
|||||||
provider->read(left->getOffset(), leftBuffer.data(), left->getSize());
|
provider->read(left->getOffset(), leftBuffer.data(), left->getSize());
|
||||||
provider->read(right->getOffset(), rightBuffer.data(), right->getSize());
|
provider->read(right->getOffset(), rightBuffer.data(), right->getSize());
|
||||||
|
|
||||||
|
if (PatternData::s_endianess != std::endian::native) {
|
||||||
|
std::reverse(leftBuffer.begin(), leftBuffer.end());
|
||||||
|
std::reverse(rightBuffer.begin(), rightBuffer.end());
|
||||||
|
}
|
||||||
|
|
||||||
if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending)
|
if (sortSpecs->Specs->SortDirection == ImGuiSortDirection_Ascending)
|
||||||
return leftBuffer > rightBuffer;
|
return leftBuffer > rightBuffer;
|
||||||
else
|
else
|
||||||
@ -117,6 +122,7 @@ namespace hex::lang {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void resetPalette() { PatternData::s_paletteOffset = 0; }
|
static void resetPalette() { PatternData::s_paletteOffset = 0; }
|
||||||
|
static void setEndianess(std::endian endianess) { PatternData::s_endianess = endianess; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void createDefaultEntry(std::string value) {
|
void createDefaultEntry(std::string value) {
|
||||||
@ -136,6 +142,9 @@ namespace hex::lang {
|
|||||||
ImGui::Text("%s", value.c_str());
|
ImGui::Text("%s", value.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static inline std::endian s_endianess = std::endian::native;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Type m_type;
|
Type m_type;
|
||||||
u64 m_offset;
|
u64 m_offset;
|
||||||
@ -145,6 +154,7 @@ namespace hex::lang {
|
|||||||
std::string m_name;
|
std::string m_name;
|
||||||
|
|
||||||
static inline u8 s_paletteOffset = 0;
|
static inline u8 s_paletteOffset = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class PatternDataPadding : public PatternData {
|
class PatternDataPadding : public PatternData {
|
||||||
@ -169,6 +179,7 @@ namespace hex::lang {
|
|||||||
void createEntry(prv::Provider* &provider) override {
|
void createEntry(prv::Provider* &provider) override {
|
||||||
u64 data = 0;
|
u64 data = 0;
|
||||||
provider->read(this->getOffset(), &data, this->getSize());
|
provider->read(this->getOffset(), &data, this->getSize());
|
||||||
|
data = hex::changeEndianess(data, this->getSize(), PatternData::s_endianess);
|
||||||
|
|
||||||
ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
|
ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
@ -215,6 +226,7 @@ namespace hex::lang {
|
|||||||
void createEntry(prv::Provider* &provider) override {
|
void createEntry(prv::Provider* &provider) override {
|
||||||
u64 data = 0;
|
u64 data = 0;
|
||||||
provider->read(this->getOffset(), &data, this->getSize());
|
provider->read(this->getOffset(), &data, this->getSize());
|
||||||
|
data = hex::changeEndianess(data, this->getSize(), PatternData::s_endianess);
|
||||||
|
|
||||||
this->createDefaultEntry(hex::format("%lu (0x%0*lx)", data, this->getSize() * 2, data));
|
this->createDefaultEntry(hex::format("%lu (0x%0*lx)", data, this->getSize() * 2, data));
|
||||||
}
|
}
|
||||||
@ -238,6 +250,7 @@ namespace hex::lang {
|
|||||||
void createEntry(prv::Provider* &provider) override {
|
void createEntry(prv::Provider* &provider) override {
|
||||||
u64 data = 0;
|
u64 data = 0;
|
||||||
provider->read(this->getOffset(), &data, this->getSize());
|
provider->read(this->getOffset(), &data, this->getSize());
|
||||||
|
data = hex::changeEndianess(data, this->getSize(), PatternData::s_endianess);
|
||||||
|
|
||||||
s64 signedData = signedData = hex::signExtend(data, this->getSize(), 64);
|
s64 signedData = signedData = hex::signExtend(data, this->getSize(), 64);
|
||||||
|
|
||||||
@ -265,10 +278,14 @@ namespace hex::lang {
|
|||||||
if (this->getSize() == 4) {
|
if (this->getSize() == 4) {
|
||||||
float data = 0;
|
float data = 0;
|
||||||
provider->read(this->getOffset(), &data, 4);
|
provider->read(this->getOffset(), &data, 4);
|
||||||
|
data = hex::changeEndianess(data, 4, PatternData::s_endianess);
|
||||||
|
|
||||||
formatData = data;
|
formatData = data;
|
||||||
} else if (this->getSize() == 8) {
|
} else if (this->getSize() == 8) {
|
||||||
double data = 0;
|
double data = 0;
|
||||||
provider->read(this->getOffset(), &data, 8);
|
provider->read(this->getOffset(), &data, 8);
|
||||||
|
data = hex::changeEndianess(data, 8, PatternData::s_endianess);
|
||||||
|
|
||||||
formatData = data;
|
formatData = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -488,6 +505,7 @@ namespace hex::lang {
|
|||||||
void createEntry(prv::Provider* &provider) override {
|
void createEntry(prv::Provider* &provider) override {
|
||||||
u64 value = 0;
|
u64 value = 0;
|
||||||
provider->read(this->getOffset(), &value, this->getSize());
|
provider->read(this->getOffset(), &value, this->getSize());
|
||||||
|
value = hex::changeEndianess(value, this->getSize(), PatternData::s_endianess);
|
||||||
|
|
||||||
std::string valueString = this->m_enumName + "::";
|
std::string valueString = this->m_enumName + "::";
|
||||||
|
|
||||||
@ -523,6 +541,7 @@ namespace hex::lang {
|
|||||||
void createEntry(prv::Provider* &provider) override {
|
void createEntry(prv::Provider* &provider) override {
|
||||||
u64 value = 0;
|
u64 value = 0;
|
||||||
provider->read(this->getOffset(), &value, this->getSize());
|
provider->read(this->getOffset(), &value, this->getSize());
|
||||||
|
value = hex::changeEndianess(value, this->getSize(), PatternData::s_endianess);
|
||||||
|
|
||||||
ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
|
ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
|
@ -106,6 +106,23 @@ namespace hex {
|
|||||||
static_assert(always_false<T>::value, "Invalid type provided!");
|
static_assert(always_false<T>::value, "Invalid type provided!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr T changeEndianess(T value, size_t size, std::endian endian) {
|
||||||
|
if (endian == std::endian::native)
|
||||||
|
return value;
|
||||||
|
|
||||||
|
if (size == 1)
|
||||||
|
return value;
|
||||||
|
else if (size == 2)
|
||||||
|
return __builtin_bswap16(value);
|
||||||
|
else if (size == 4)
|
||||||
|
return __builtin_bswap32(value);
|
||||||
|
else if (size == 8)
|
||||||
|
return __builtin_bswap64(value);
|
||||||
|
else
|
||||||
|
throw std::invalid_argument("Invalid value size!");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class ScopeExit {
|
class ScopeExit {
|
||||||
public:
|
public:
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
|
|
||||||
namespace hex::lang {
|
namespace hex::lang {
|
||||||
|
|
||||||
Evaluator::Evaluator(prv::Provider* &provider) : m_provider(provider) {
|
Evaluator::Evaluator(prv::Provider* &provider, std::endian dataEndianess) : m_provider(provider), m_dataEndianess(dataEndianess) {
|
||||||
|
PatternData::setEndianess(dataEndianess);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<PatternData*, size_t> Evaluator::createStructPattern(ASTNodeVariableDecl *varDeclNode, u64 offset) {
|
std::pair<PatternData*, size_t> Evaluator::createStructPattern(ASTNodeVariableDecl *varDeclNode, u64 offset) {
|
||||||
@ -23,8 +23,11 @@ namespace hex::lang {
|
|||||||
|
|
||||||
u64 memberOffset = 0;
|
u64 memberOffset = 0;
|
||||||
|
|
||||||
if (member->getPointerSize().has_value())
|
if (member->getPointerSize().has_value()) {
|
||||||
this->m_provider->read(offset + structSize, &memberOffset, member->getPointerSize().value());
|
this->m_provider->read(offset + structSize, &memberOffset, member->getPointerSize().value());
|
||||||
|
|
||||||
|
memberOffset = hex::changeEndianess(memberOffset, member->getPointerSize().value(), this->m_dataEndianess);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
memberOffset = offset + structSize;
|
memberOffset = offset + structSize;
|
||||||
|
|
||||||
@ -52,6 +55,9 @@ namespace hex::lang {
|
|||||||
if (prevMember->getPatternType() == PatternData::Type::Unsigned && prevMember->getName() == member->getArraySizeVariable()) {
|
if (prevMember->getPatternType() == PatternData::Type::Unsigned && prevMember->getName() == member->getArraySizeVariable()) {
|
||||||
u64 value = 0;
|
u64 value = 0;
|
||||||
this->m_provider->read(prevMember->getOffset(), &value, prevMember->getSize());
|
this->m_provider->read(prevMember->getOffset(), &value, prevMember->getSize());
|
||||||
|
|
||||||
|
value = hex::changeEndianess(value, prevMember->getSize(), this->m_dataEndianess);
|
||||||
|
|
||||||
arraySize = value;
|
arraySize = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -100,8 +106,11 @@ namespace hex::lang {
|
|||||||
|
|
||||||
u64 memberOffset = 0;
|
u64 memberOffset = 0;
|
||||||
|
|
||||||
if (member->getPointerSize().has_value())
|
if (member->getPointerSize().has_value()) {
|
||||||
this->m_provider->read(offset + unionSize, &memberOffset, member->getPointerSize().value());
|
this->m_provider->read(offset + unionSize, &memberOffset, member->getPointerSize().value());
|
||||||
|
|
||||||
|
memberOffset = hex::changeEndianess(memberOffset, member->getPointerSize().value(), this->m_dataEndianess);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
memberOffset = offset;
|
memberOffset = offset;
|
||||||
|
|
||||||
@ -132,6 +141,9 @@ namespace hex::lang {
|
|||||||
if (prevMember->getPatternType() == PatternData::Type::Unsigned && prevMember->getName() == member->getArraySizeVariable()) {
|
if (prevMember->getPatternType() == PatternData::Type::Unsigned && prevMember->getName() == member->getArraySizeVariable()) {
|
||||||
u64 value = 0;
|
u64 value = 0;
|
||||||
this->m_provider->read(prevMember->getOffset(), &value, prevMember->getSize());
|
this->m_provider->read(prevMember->getOffset(), &value, prevMember->getSize());
|
||||||
|
|
||||||
|
value = hex::changeEndianess(value, prevMember->getSize(), this->m_dataEndianess);
|
||||||
|
|
||||||
arraySize = value;
|
arraySize = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -172,6 +172,9 @@ namespace hex::lang {
|
|||||||
this->addPragmaHandler("MIME", [](std::string value) {
|
this->addPragmaHandler("MIME", [](std::string value) {
|
||||||
return !std::all_of(value.begin(), value.end(), isspace) && !value.ends_with('\n') && !value.ends_with('\r');
|
return !std::all_of(value.begin(), value.end(), isspace) && !value.ends_with('\n') && !value.ends_with('\r');
|
||||||
});
|
});
|
||||||
|
this->addPragmaHandler("endian", [](std::string value) {
|
||||||
|
return value == "big" || value == "little" || value == "native";
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -237,26 +237,38 @@ namespace hex {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ViewPattern::parsePattern(char *buffer) {
|
void ViewPattern::parsePattern(char *buffer) {
|
||||||
hex::lang::Preprocessor preprocessor;
|
|
||||||
hex::lang::Lexer lexer;
|
|
||||||
hex::lang::Parser parser;
|
|
||||||
hex::lang::Validator validator;
|
|
||||||
hex::lang::Evaluator evaluator(this->m_dataProvider);
|
|
||||||
|
|
||||||
this->clearPatternData();
|
this->clearPatternData();
|
||||||
this->postEvent(Events::PatternChanged);
|
this->postEvent(Events::PatternChanged);
|
||||||
|
|
||||||
|
hex::lang::Preprocessor preprocessor;
|
||||||
|
std::endian dataEndianess = std::endian::native;
|
||||||
|
|
||||||
|
preprocessor.addPragmaHandler("endian", [&dataEndianess](std::string value) {
|
||||||
|
if (value == "big") {
|
||||||
|
dataEndianess = std::endian::big;
|
||||||
|
return true;
|
||||||
|
} else if (value == "little") {
|
||||||
|
dataEndianess = std::endian::little;
|
||||||
|
return true;
|
||||||
|
} else if (value == "native") {
|
||||||
|
dataEndianess = std::endian::native;
|
||||||
|
return true;
|
||||||
|
} else
|
||||||
|
return false;
|
||||||
|
});
|
||||||
preprocessor.addDefaultPragramHandlers();
|
preprocessor.addDefaultPragramHandlers();
|
||||||
|
|
||||||
auto [preprocessingResult, preprocesedCode] = preprocessor.preprocess(buffer);
|
auto [preprocessingResult, preprocesedCode] = preprocessor.preprocess(buffer);
|
||||||
if (preprocessingResult.failed())
|
if (preprocessingResult.failed())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
hex::lang::Lexer lexer;
|
||||||
auto [lexResult, tokens] = lexer.lex(preprocesedCode);
|
auto [lexResult, tokens] = lexer.lex(preprocesedCode);
|
||||||
if (lexResult.failed()) {
|
if (lexResult.failed()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hex::lang::Parser parser;
|
||||||
auto [parseResult, ast] = parser.parse(tokens);
|
auto [parseResult, ast] = parser.parse(tokens);
|
||||||
if (parseResult.failed()) {
|
if (parseResult.failed()) {
|
||||||
return;
|
return;
|
||||||
@ -264,11 +276,13 @@ namespace hex {
|
|||||||
|
|
||||||
hex::ScopeExit deleteAst([&ast]{ for(auto &node : ast) delete node; });
|
hex::ScopeExit deleteAst([&ast]{ for(auto &node : ast) delete node; });
|
||||||
|
|
||||||
|
hex::lang::Validator validator;
|
||||||
auto validatorResult = validator.validate(ast);
|
auto validatorResult = validator.validate(ast);
|
||||||
if (!validatorResult) {
|
if (!validatorResult) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hex::lang::Evaluator evaluator(this->m_dataProvider, dataEndianess);
|
||||||
auto [evaluateResult, patternData] = evaluator.evaluate(ast);
|
auto [evaluateResult, patternData] = evaluator.evaluate(ast);
|
||||||
if (evaluateResult.failed()) {
|
if (evaluateResult.failed()) {
|
||||||
return;
|
return;
|
||||||
|
Loading…
Reference in New Issue
Block a user