mirror of https://github.com/WerWolv/ImHex.git
patterns: Allow bitfield fields to be accessed as like other members
This commit is contained in:
parent
c75659db82
commit
f8ed89ee2c
|
@ -940,12 +940,77 @@ namespace hex::lang {
|
||||||
std::vector<std::pair<Token::IntegerLiteral, std::string>> m_enumValues;
|
std::vector<std::pair<Token::IntegerLiteral, std::string>> m_enumValues;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class PatternDataBitfieldField : public PatternData {
|
||||||
|
public:
|
||||||
|
PatternDataBitfieldField(u64 offset, u8 bitOffset, u8 bitSize, u32 color = 0)
|
||||||
|
: m_bitOffset(bitOffset), m_bitSize(bitSize), PatternData(offset, 0, color) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
PatternData* clone() override {
|
||||||
|
return new PatternDataBitfieldField(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void createEntry(prv::Provider* &provider) override {
|
||||||
|
std::vector<u8> value(this->getSize(), 0);
|
||||||
|
provider->read(this->getOffset(), &value[0], value.size());
|
||||||
|
|
||||||
|
if (this->m_endian != std::endian::native)
|
||||||
|
std::reverse(value.begin(), value.end());
|
||||||
|
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TreeNodeEx(this->getVariableName().c_str(), ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_AllowItemOverlap);
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("%s", this->getVariableName().c_str());
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::ColorButton("color", ImColor(this->getColor()), ImGuiColorEditFlags_NoTooltip, ImVec2(ImGui::GetColumnWidth(), ImGui::GetTextLineHeight()));
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("0x%08llX : 0x%08llX", this->getOffset() + (this->m_bitOffset >> 3), this->getOffset() + ((this->m_bitOffset + this->m_bitSize) >> 3));
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
if (this->m_bitSize == 1)
|
||||||
|
ImGui::Text("%u bit", this->m_bitSize);
|
||||||
|
else
|
||||||
|
ImGui::Text("%u bits", this->m_bitSize);
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TextColored(ImColor(0xFF9BC64D), "bits");
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
{
|
||||||
|
u128 fieldValue = 0;
|
||||||
|
std::memcpy(&fieldValue, value.data() + (this->m_bitOffset / 8), (this->m_bitSize / 8) + 1);
|
||||||
|
u64 maskedValue = hex::extract((this->m_bitOffset + this->m_bitSize) - 1 - ((this->m_bitOffset / 8) * 8), this->m_bitOffset - ((this->m_bitOffset / 8) * 8), fieldValue);
|
||||||
|
ImGui::Text("%llu (0x%llX)", maskedValue, maskedValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] std::string getFormattedName() const override {
|
||||||
|
return "bits";
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] u8 getBitOffset() const {
|
||||||
|
return this->m_bitOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] u8 getBitSize() const {
|
||||||
|
return this->m_bitSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
u8 m_bitOffset, m_bitSize;
|
||||||
|
};
|
||||||
|
|
||||||
class PatternDataBitfield : public PatternData {
|
class PatternDataBitfield : public PatternData {
|
||||||
public:
|
public:
|
||||||
PatternDataBitfield(u64 offset, size_t size, u32 color = 0) : PatternData(offset, size, color) {
|
PatternDataBitfield(u64 offset, size_t size, u32 color = 0) : PatternData(offset, size, color) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~PatternDataBitfield() override {
|
||||||
|
for (auto field : this->m_fields)
|
||||||
|
delete field;
|
||||||
|
}
|
||||||
|
|
||||||
PatternData* clone() override {
|
PatternData* clone() override {
|
||||||
return new PatternDataBitfield(*this);
|
return new PatternDataBitfield(*this);
|
||||||
}
|
}
|
||||||
|
@ -954,7 +1019,7 @@ namespace hex::lang {
|
||||||
std::vector<u8> value(this->getSize(), 0);
|
std::vector<u8> value(this->getSize(), 0);
|
||||||
provider->read(this->getOffset(), &value[0], value.size());
|
provider->read(this->getOffset(), &value[0], value.size());
|
||||||
|
|
||||||
if (this->m_endian == std::endian::big)
|
if (this->m_endian != std::endian::native)
|
||||||
std::reverse(value.begin(), value.end());
|
std::reverse(value.begin(), value.end());
|
||||||
|
|
||||||
ImGui::TableNextRow();
|
ImGui::TableNextRow();
|
||||||
|
@ -978,31 +1043,9 @@ namespace hex::lang {
|
||||||
ImGui::TextUnformatted(valueString.c_str());
|
ImGui::TextUnformatted(valueString.c_str());
|
||||||
|
|
||||||
if (open) {
|
if (open) {
|
||||||
u16 bitOffset = 0;
|
|
||||||
for (auto &[entryName, entrySize] : this->m_fields) {
|
for (auto &field : this->m_fields)
|
||||||
ImGui::TableNextRow();
|
field->draw(provider);
|
||||||
ImGui::TreeNodeEx(this->getVariableName().c_str(), ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_AllowItemOverlap);
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
ImGui::Text("%s", entryName.c_str());
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
ImGui::ColorButton("color", ImColor(this->getColor()), ImGuiColorEditFlags_NoTooltip, ImVec2(ImGui::GetColumnWidth(), ImGui::GetTextLineHeight()));
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
ImGui::Text("0x%08llX : 0x%08llX", this->getOffset() + (bitOffset >> 3), this->getOffset() + ((bitOffset + entrySize) >> 3));
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
if (entrySize == 1)
|
|
||||||
ImGui::Text("%llu bit", entrySize);
|
|
||||||
else
|
|
||||||
ImGui::Text("%llu bits", entrySize);
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
ImGui::TextColored(ImColor(0xFF9BC64D), "bits");
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
{
|
|
||||||
u128 fieldValue = 0;
|
|
||||||
std::memcpy(&fieldValue, value.data() + (bitOffset / 8), (entrySize / 8) + 1);
|
|
||||||
ImGui::Text("%llX", hex::extract((bitOffset + entrySize) - 1 - ((bitOffset / 8) * 8), bitOffset - ((bitOffset / 8) * 8), fieldValue));
|
|
||||||
}
|
|
||||||
bitOffset += entrySize;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::TreePop();
|
ImGui::TreePop();
|
||||||
}
|
}
|
||||||
|
@ -1017,12 +1060,15 @@ namespace hex::lang {
|
||||||
return this->m_fields;
|
return this->m_fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setFields(const std::vector<std::pair<std::string, size_t>> &fields) {
|
void setFields(const std::vector<PatternData*> &fields) {
|
||||||
this->m_fields = fields;
|
this->m_fields = fields;
|
||||||
|
|
||||||
|
for (auto &field : this->m_fields)
|
||||||
|
field->setSize(this->getSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<std::pair<std::string, size_t>> m_fields;
|
std::vector<PatternData*> m_fields;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
|
@ -56,6 +56,9 @@ namespace hex::lang {
|
||||||
currMembers = structPattern->getMembers();
|
currMembers = structPattern->getMembers();
|
||||||
else if (auto unionPattern = dynamic_cast<PatternDataUnion*>(currPattern); unionPattern != nullptr)
|
else if (auto unionPattern = dynamic_cast<PatternDataUnion*>(currPattern); unionPattern != nullptr)
|
||||||
currMembers = unionPattern->getMembers();
|
currMembers = unionPattern->getMembers();
|
||||||
|
else if (auto bitfieldPattern = dynamic_cast<PatternDataBitfield*>(currPattern); bitfieldPattern != nullptr) {
|
||||||
|
currMembers = bitfieldPattern->getFields();
|
||||||
|
}
|
||||||
else if (auto arrayPattern = dynamic_cast<PatternDataArray*>(currPattern); arrayPattern != nullptr) {
|
else if (auto arrayPattern = dynamic_cast<PatternDataArray*>(currPattern); arrayPattern != nullptr) {
|
||||||
currMembers = arrayPattern->getEntries();
|
currMembers = arrayPattern->getEntries();
|
||||||
continue;
|
continue;
|
||||||
|
@ -201,6 +204,20 @@ namespace hex::lang {
|
||||||
case 16: return new ASTNodeIntegerLiteral(hex::changeEndianess(*reinterpret_cast<u128*>(value), 16, enumPattern->getEndian()));
|
case 16: return new ASTNodeIntegerLiteral(hex::changeEndianess(*reinterpret_cast<u128*>(value), 16, enumPattern->getEndian()));
|
||||||
default: this->getConsole().abortEvaluation("invalid rvalue size");
|
default: this->getConsole().abortEvaluation("invalid rvalue size");
|
||||||
}
|
}
|
||||||
|
} else if (auto bitfieldFieldPattern = dynamic_cast<PatternDataBitfieldField*>(currPattern); bitfieldFieldPattern != nullptr) {
|
||||||
|
u8 value[bitfieldFieldPattern->getSize()];
|
||||||
|
if (currPattern->isLocal())
|
||||||
|
std::memcpy(value, this->m_localStack.data() + bitfieldFieldPattern->getOffset(), bitfieldFieldPattern->getSize());
|
||||||
|
else
|
||||||
|
this->m_provider->read(bitfieldFieldPattern->getOffset(), value, bitfieldFieldPattern->getSize());
|
||||||
|
|
||||||
|
u8 bitOffset = bitfieldFieldPattern->getBitOffset();
|
||||||
|
u8 bitSize = bitfieldFieldPattern->getBitSize();
|
||||||
|
|
||||||
|
u128 fieldValue = 0;
|
||||||
|
std::memcpy(&fieldValue, value + (bitOffset / 8), (bitSize / 8) + 1);
|
||||||
|
|
||||||
|
return new ASTNodeIntegerLiteral(hex::extract((bitOffset + bitSize) - 1 - ((bitOffset / 8) * 8), bitOffset - ((bitOffset / 8) * 8), fieldValue));
|
||||||
} else
|
} else
|
||||||
this->getConsole().abortEvaluation("tried to use non-integer value in numeric expression");
|
this->getConsole().abortEvaluation("tried to use non-integer value in numeric expression");
|
||||||
}
|
}
|
||||||
|
@ -787,7 +804,7 @@ namespace hex::lang {
|
||||||
}
|
}
|
||||||
|
|
||||||
PatternData* Evaluator::evaluateBitfield(ASTNodeBitfield *node) {
|
PatternData* Evaluator::evaluateBitfield(ASTNodeBitfield *node) {
|
||||||
std::vector<std::pair<std::string, size_t>> entryPatterns;
|
std::vector<PatternData*> entryPatterns;
|
||||||
|
|
||||||
auto startOffset = this->m_currOffset;
|
auto startOffset = this->m_currOffset;
|
||||||
size_t bits = 0;
|
size_t bits = 0;
|
||||||
|
@ -809,9 +826,11 @@ namespace hex::lang {
|
||||||
if (fieldBits > 64 || fieldBits <= 0)
|
if (fieldBits > 64 || fieldBits <= 0)
|
||||||
this->getConsole().abortEvaluation("bitfield entry must occupy between 1 and 64 bits");
|
this->getConsole().abortEvaluation("bitfield entry must occupy between 1 and 64 bits");
|
||||||
|
|
||||||
bits += fieldBits;
|
auto fieldPattern = new PatternDataBitfieldField(startOffset, bits, fieldBits);
|
||||||
|
fieldPattern->setVariableName(name);
|
||||||
|
entryPatterns.push_back(fieldPattern);
|
||||||
|
|
||||||
entryPatterns.emplace_back(name, fieldBits);
|
bits += fieldBits;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t size = (bits + 7) / 8;
|
size_t size = (bits + 7) / 8;
|
||||||
|
|
Loading…
Reference in New Issue