Skip to content

Commit eef36c8

Browse files
committed
Add HLIL structure initializer instructions
1 parent 75dbd2c commit eef36c8

13 files changed

Lines changed: 500 additions & 2 deletions

binaryninjaapi.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16439,6 +16439,9 @@ namespace BinaryNinja {
1643916439
ExprId ArrayIndex(size_t size, ExprId src, ExprId idx, const ILSourceLocation& loc = ILSourceLocation());
1644016440
ExprId ArrayIndexSSA(size_t size, ExprId src, size_t srcMemVersion, ExprId idx,
1644116441
const ILSourceLocation& loc = ILSourceLocation());
16442+
ExprId StructInit(size_t size, const std::vector<ExprId>& fields, const ILSourceLocation& loc = ILSourceLocation());
16443+
ExprId StructInitField(size_t size, uint64_t offset, size_t memberIndex, ExprId src,
16444+
const ILSourceLocation& loc = ILSourceLocation());
1644216445
ExprId Split(size_t size, ExprId high, ExprId low, const ILSourceLocation& loc = ILSourceLocation());
1644316446
ExprId Deref(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation());
1644416447
ExprId DerefField(size_t size, ExprId src, uint64_t offset, size_t memberIndex,

binaryninjacore.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1705,6 +1705,8 @@ extern "C"
17051705
HLIL_UNDEF,
17061706
HLIL_UNIMPL,
17071707
HLIL_UNIMPL_MEM,
1708+
HLIL_STRUCT_INIT,
1709+
HLIL_STRUCT_INIT_FIELD, // Only valid in HLIL_STRUCT_INIT
17081710

17091711
// Floating point
17101712
HLIL_FADD,

highlevelilinstruction.cpp

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ static constexpr std::array s_operandTypeForUsage = {
8989
OperandUsageType{BlockExprsHighLevelOperandUsage, ExprListHighLevelOperand},
9090
OperandUsageType{CasesHighLevelOperandUsage, ExprListHighLevelOperand},
9191
OperandUsageType{ValueExprsHighLevelOperandUsage, ExprListHighLevelOperand},
92+
OperandUsageType{FieldExprsHighLevelOperandUsage, ExprListHighLevelOperand},
9293
OperandUsageType{SourceSSAVariablesHighLevelOperandUsage, SSAVariableListHighLevelOperand},
9394
OperandUsageType{SourceMemoryVersionHighLevelOperandUsage, IndexHighLevelOperand},
9495
OperandUsageType{SourceMemoryVersionsHighLevelOperandUsage, IndexListHighLevelOperand},
@@ -226,6 +227,8 @@ static constexpr std::array s_instructionOperandUsage = {
226227
OperandUsage{HLIL_UNDEF},
227228
OperandUsage{HLIL_UNIMPL},
228229
OperandUsage{HLIL_UNIMPL_MEM, {SourceExprHighLevelOperandUsage}},
230+
OperandUsage{HLIL_STRUCT_INIT, {FieldExprsHighLevelOperandUsage}},
231+
OperandUsage{HLIL_STRUCT_INIT_FIELD, {OffsetHighLevelOperandUsage, MemberIndexHighLevelOperandUsage, SourceExprHighLevelOperandUsage}},
229232
OperandUsage{HLIL_FADD, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
230233
OperandUsage{HLIL_FSUB, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
231234
OperandUsage{HLIL_FMUL, {LeftExprHighLevelOperandUsage, RightExprHighLevelOperandUsage}},
@@ -1249,6 +1252,14 @@ void HighLevelILInstruction::CollectSubExprs(stack<size_t>& toProcess) const
12491252
case HLIL_DEREF_FIELD_SSA:
12501253
toProcess.push(GetSourceExpr<HLIL_DEREF_FIELD_SSA>().exprIndex);
12511254
break;
1255+
case HLIL_STRUCT_INIT:
1256+
exprs = GetFieldExprs<HLIL_STRUCT_INIT>();
1257+
for (auto i = exprs.rbegin(); i != exprs.rend(); ++i)
1258+
toProcess.push(i->exprIndex);
1259+
break;
1260+
case HLIL_STRUCT_INIT_FIELD:
1261+
toProcess.push(GetSourceExpr<HLIL_STRUCT_INIT_FIELD>().exprIndex);
1262+
break;
12521263
case HLIL_CALL:
12531264
toProcess.push(GetDestExpr<HLIL_CALL>().exprIndex);
12541265
exprs = GetParameterExprs<HLIL_CALL>();
@@ -1560,6 +1571,13 @@ ExprId HighLevelILInstruction::CopyTo(
15601571
return dest->ArrayIndexSSA(size, subExprHandler(GetSourceExpr<HLIL_ARRAY_INDEX_SSA>()),
15611572
GetSourceMemoryVersion<HLIL_ARRAY_INDEX_SSA>(), subExprHandler(GetIndexExpr<HLIL_ARRAY_INDEX_SSA>()),
15621573
loc);
1574+
case HLIL_STRUCT_INIT:
1575+
for (auto i : GetFieldExprs<HLIL_STRUCT_INIT>())
1576+
params.push_back(subExprHandler(i));
1577+
return dest->StructInit(size, params, loc);
1578+
case HLIL_STRUCT_INIT_FIELD:
1579+
return dest->StructInitField(size, GetOffset<HLIL_STRUCT_INIT_FIELD>(),
1580+
GetMemberIndex<HLIL_STRUCT_INIT_FIELD>(), subExprHandler(GetSourceExpr<HLIL_STRUCT_INIT_FIELD>()), loc);
15631581
case HLIL_SPLIT:
15641582
return dest->Split(
15651583
size, subExprHandler(GetHighExpr<HLIL_SPLIT>()), subExprHandler(GetLowExpr<HLIL_SPLIT>()), loc);
@@ -1992,6 +2010,26 @@ bool HighLevelILInstruction::operator<(const HighLevelILInstruction& other) cons
19922010
if (other.GetIndexExpr<HLIL_ARRAY_INDEX_SSA>() < GetIndexExpr<HLIL_ARRAY_INDEX_SSA>())
19932011
return false;
19942012
return GetSourceMemoryVersion<HLIL_ARRAY_INDEX_SSA>() < other.GetSourceMemoryVersion<HLIL_ARRAY_INDEX_SSA>();
2013+
case HLIL_STRUCT_INIT:
2014+
if (size < other.size)
2015+
return true;
2016+
if (size > other.size)
2017+
return false;
2018+
return CompareExprList(GetFieldExprs<HLIL_STRUCT_INIT>(), other.GetFieldExprs<HLIL_STRUCT_INIT>());
2019+
case HLIL_STRUCT_INIT_FIELD:
2020+
if (size < other.size)
2021+
return true;
2022+
if (size > other.size)
2023+
return false;
2024+
if (GetOffset<HLIL_STRUCT_INIT_FIELD>() < other.GetOffset<HLIL_STRUCT_INIT_FIELD>())
2025+
return true;
2026+
if (other.GetOffset<HLIL_STRUCT_INIT_FIELD>() < GetOffset<HLIL_STRUCT_INIT_FIELD>())
2027+
return false;
2028+
if (GetMemberIndex<HLIL_STRUCT_INIT_FIELD>() < other.GetMemberIndex<HLIL_STRUCT_INIT_FIELD>())
2029+
return true;
2030+
if (other.GetMemberIndex<HLIL_STRUCT_INIT_FIELD>() < GetMemberIndex<HLIL_STRUCT_INIT_FIELD>())
2031+
return false;
2032+
return GetSourceExpr<HLIL_STRUCT_INIT_FIELD>() < other.GetSourceExpr<HLIL_STRUCT_INIT_FIELD>();
19952033
case HLIL_SPLIT:
19962034
if (size < other.size)
19972035
return true;
@@ -2614,6 +2652,15 @@ HighLevelILInstructionList HighLevelILInstruction::GetValueExprs() const
26142652
}
26152653

26162654

2655+
HighLevelILInstructionList HighLevelILInstruction::GetFieldExprs() const
2656+
{
2657+
size_t operandIndex;
2658+
if (GetOperandIndexForUsage(FieldExprsHighLevelOperandUsage, operandIndex))
2659+
return GetRawOperandAsExprList(operandIndex);
2660+
throw HighLevelILInstructionAccessException();
2661+
}
2662+
2663+
26172664
HighLevelILSSAVariableList HighLevelILInstruction::GetSourceSSAVariables() const
26182665
{
26192666
size_t operandIndex;
@@ -2916,6 +2963,19 @@ ExprId HighLevelILFunction::ArrayIndexSSA(
29162963
}
29172964

29182965

2966+
ExprId HighLevelILFunction::StructInit(size_t size, const vector<ExprId>& fields, const ILSourceLocation& loc)
2967+
{
2968+
return AddExprWithLocation(HLIL_STRUCT_INIT, loc, size, fields.size(), AddOperandList(fields));
2969+
}
2970+
2971+
2972+
ExprId HighLevelILFunction::StructInitField(
2973+
size_t size, uint64_t offset, size_t memberIndex, ExprId src, const ILSourceLocation& loc)
2974+
{
2975+
return AddExprWithLocation(HLIL_STRUCT_INIT_FIELD, loc, size, offset, memberIndex, src);
2976+
}
2977+
2978+
29192979
ExprId HighLevelILFunction::Deref(size_t size, ExprId src, const ILSourceLocation& loc)
29202980
{
29212981
return AddExprWithLocation(HLIL_DEREF, loc, size, src);

highlevelilinstruction.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ namespace BinaryNinja
118118
BlockExprsHighLevelOperandUsage,
119119
CasesHighLevelOperandUsage,
120120
ValueExprsHighLevelOperandUsage,
121+
FieldExprsHighLevelOperandUsage,
121122
SourceSSAVariablesHighLevelOperandUsage,
122123
SourceMemoryVersionHighLevelOperandUsage,
123124
SourceMemoryVersionsHighLevelOperandUsage,
@@ -671,6 +672,11 @@ namespace BinaryNinja
671672
return As<N>().GetValueExprs();
672673
}
673674
template <BNHighLevelILOperation N>
675+
HighLevelILInstructionList GetFieldExprs() const
676+
{
677+
return As<N>().GetFieldExprs();
678+
}
679+
template <BNHighLevelILOperation N>
674680
HighLevelILSSAVariableList GetSourceSSAVariables() const
675681
{
676682
return As<N>().GetSourceSSAVariables();
@@ -820,6 +826,7 @@ namespace BinaryNinja
820826
HighLevelILInstructionList GetBlockExprs() const;
821827
HighLevelILInstructionList GetCases() const;
822828
HighLevelILInstructionList GetValueExprs() const;
829+
HighLevelILInstructionList GetFieldExprs() const;
823830
HighLevelILSSAVariableList GetSourceSSAVariables() const;
824831
size_t GetSourceMemoryVersion() const;
825832
HighLevelILIndexList GetSourceMemoryVersions() const;
@@ -1164,6 +1171,18 @@ namespace BinaryNinja
11641171
HighLevelILInstruction GetHighExpr() const { return GetRawOperandAsExpr(0); }
11651172
HighLevelILInstruction GetLowExpr() const { return GetRawOperandAsExpr(1); }
11661173
};
1174+
template <>
1175+
struct HighLevelILInstructionAccessor<HLIL_STRUCT_INIT> : public HighLevelILInstructionBase
1176+
{
1177+
HighLevelILInstructionList GetFieldExprs() const { return GetRawOperandAsExprList(0); }
1178+
};
1179+
template <>
1180+
struct HighLevelILInstructionAccessor<HLIL_STRUCT_INIT_FIELD> : public HighLevelILInstructionBase
1181+
{
1182+
uint64_t GetOffset() const { return GetRawOperandAsInteger(0); }
1183+
size_t GetMemberIndex() const { return GetRawOperandAsIndex(1); }
1184+
HighLevelILInstruction GetSourceExpr() const { return GetRawOperandAsExpr(2); }
1185+
};
11671186

11681187
template <>
11691188
struct HighLevelILInstructionAccessor<HLIL_VAR> : public HighLevelILInstructionBase

lang/c/pseudoc.cpp

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -697,6 +697,53 @@ void PseudoCFunction::AppendFieldTextTokens(const HighLevelILInstruction& instr,
697697
}
698698

699699

700+
void PseudoCFunction::AppendStructInitFieldTextTokens(const HighLevelILInstruction& init, uint64_t offset,
701+
size_t memberIndex, size_t size, HighLevelILTokenEmitter& tokens)
702+
{
703+
Ref<Type> type = init.GetType().GetValue();
704+
if (type && (type->GetClass() == NamedTypeReferenceClass))
705+
type = GetFunction()->GetView()->GetTypeByRef(type->GetNamedTypeReference());
706+
707+
if (type && (type->GetClass() == StructureTypeClass))
708+
{
709+
std::optional<size_t> memberIndexHint;
710+
if (memberIndex != BN_INVALID_EXPR)
711+
memberIndexHint = memberIndex;
712+
713+
bool hasField = false;
714+
bool correctSize = false;
715+
type->GetStructure()->ResolveMemberOrBaseMember(
716+
GetFunction()->GetView(), offset, 0,
717+
[&](NamedTypeReference*, Structure* s, size_t memberIndex, uint64_t structOffset, uint64_t adjustedOffset,
718+
const StructureMember& member) {
719+
tokens.Append(OperationToken, ".");
720+
721+
vector<string> nameList {member.name};
722+
tokens.AddNamesForOuterStructureMembers(GetFunction()->GetView(), type, init, nameList);
723+
724+
tokens.Append(
725+
FieldNameToken, member.name, structOffset + member.offset, 0, 0, BN_FULL_CONFIDENCE, nameList);
726+
727+
offset = adjustedOffset - member.offset;
728+
hasField = true;
729+
correctSize = member.type.GetValue() && size == member.type->GetWidth();
730+
},
731+
memberIndexHint);
732+
if (hasField && correctSize)
733+
return;
734+
}
735+
736+
char offsetStr[64];
737+
tokens.Append(OperationToken, ".");
738+
snprintf(offsetStr, sizeof(offsetStr), "__offset(0x%" PRIx64 ")", offset);
739+
740+
vector<string> nameList {offsetStr};
741+
tokens.AddNamesForOuterStructureMembers(GetFunction()->GetView(), type, init, nameList);
742+
743+
tokens.Append(StructOffsetToken, offsetStr, offset, size, 0, BN_FULL_CONFIDENCE, nameList);
744+
}
745+
746+
700747
void PseudoCFunction::GetExprText(const HighLevelILInstruction& instr, HighLevelILTokenEmitter& tokens,
701748
DisassemblySettings* settings, BNOperatorPrecedence precedence, bool statement)
702749
{
@@ -3002,6 +3049,59 @@ void PseudoCFunction::GetExprTextInternal(const HighLevelILInstruction& instr, H
30023049
tokens.AppendSemicolon();
30033050
}();
30043051
break;
3052+
3053+
case HLIL_STRUCT_INIT:
3054+
[&]() {
3055+
const auto hlilFunc = GetHighLevelILFunction();
3056+
auto type = instr.GetType();
3057+
if (type.GetValue())
3058+
{
3059+
Ref<Platform> platform;
3060+
if (hlilFunc->GetFunction())
3061+
platform = hlilFunc->GetFunction()->GetPlatform();
3062+
vector<InstructionTextToken> typeTokens = TypePrinter::GetDefault()->GetTypeTokens(
3063+
type.GetValue(), platform, QualifiedName(), type.GetConfidence());
3064+
for (auto& i : typeTokens)
3065+
tokens.Append(i);
3066+
tokens.Append(TextToken, " ");
3067+
}
3068+
else
3069+
{
3070+
tokens.Append(KeywordToken, "struct ");
3071+
}
3072+
tokens.AppendOpenBrace();
3073+
tokens.IncreaseIndent();
3074+
bool first = true;
3075+
for (auto i : instr.GetFieldExprs<HLIL_STRUCT_INIT>())
3076+
{
3077+
if (i.operation != HLIL_STRUCT_INIT_FIELD)
3078+
continue;
3079+
if (!first)
3080+
tokens.Append(OperandSeparatorToken, ",");
3081+
first = false;
3082+
tokens.NewLine();
3083+
tokens.PrependCollapseIndicator();
3084+
AppendStructInitFieldTextTokens(instr, i.GetOffset<HLIL_STRUCT_INIT_FIELD>(),
3085+
i.GetMemberIndex<HLIL_STRUCT_INIT_FIELD>(), i.size, tokens);
3086+
tokens.Append(OperationToken, " = ");
3087+
GetExprText(i.GetSourceExpr<HLIL_STRUCT_INIT_FIELD>(), tokens, settings, AssignmentOperatorPrecedence);
3088+
}
3089+
tokens.DecreaseIndent();
3090+
tokens.NewLine();
3091+
tokens.PrependCollapseIndicator();
3092+
tokens.AppendCloseBrace();
3093+
}();
3094+
break;
3095+
3096+
case HLIL_STRUCT_INIT_FIELD:
3097+
[&]() {
3098+
AppendStructInitFieldTextTokens(instr, instr.GetOffset<HLIL_STRUCT_INIT_FIELD>(),
3099+
instr.GetMemberIndex<HLIL_STRUCT_INIT_FIELD>(), instr.size, tokens);
3100+
tokens.Append(OperationToken, " = ");
3101+
GetExprText(instr.GetSourceExpr<HLIL_STRUCT_INIT_FIELD>(), tokens, settings, AssignmentOperatorPrecedence);
3102+
}();
3103+
break;
3104+
30053105
default:
30063106
[&]() {
30073107
char buf[64]{};

lang/c/pseudoc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ class PseudoCFunction: public BinaryNinja::LanguageRepresentationFunction
5454
void AppendFieldTextTokens(const BinaryNinja::HighLevelILInstruction& instr,
5555
BinaryNinja::HighLevelILTokenEmitter& tokens, BinaryNinja::DisassemblySettings* settings,
5656
std::optional<bool> signedHint, bool addrOf);
57+
void AppendStructInitFieldTextTokens(const BinaryNinja::HighLevelILInstruction& init, uint64_t offset,
58+
size_t memberIndex, size_t size, BinaryNinja::HighLevelILTokenEmitter& tokens);
5759
void AppendDefaultSplitExpr(const BinaryNinja::HighLevelILInstruction& instr, BinaryNinja::HighLevelILTokenEmitter& tokens,
5860
BinaryNinja::DisassemblySettings* settings, BNOperatorPrecedence precedence);
5961
void GetExprTextInternal(const BinaryNinja::HighLevelILInstruction& instr,

0 commit comments

Comments
 (0)