Skip to content

Commit e885737

Browse files
committed
Allow nav/search of collapsed regions
1 parent 78f3e20 commit e885737

9 files changed

Lines changed: 61 additions & 24 deletions

File tree

binaryninjaapi.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20684,6 +20684,7 @@ namespace BinaryNinja {
2068420684
bool Previous();
2068520685

2068620686
std::vector<LinearDisassemblyLine> GetLines();
20687+
bool ExpandCollapsedRegionsForLine(size_t lineIndex);
2068720688

2068820689
Ref<LinearViewCursor> Duplicate();
2068920690

@@ -22703,7 +22704,11 @@ namespace BinaryNinja {
2270322704

2270422705
void PrependCollapseIndicator();
2270522706
void PrependCollapseIndicator(Ref<Function> function, const HighLevelILInstruction& instr, uint64_t designator = 0);
22707+
void PrependCollapseIndicator(Ref<Function> function, const HighLevelILInstruction& instr,
22708+
DisassemblySettings* settings, uint64_t designator = 0);
2270622709
void PrependCollapseIndicator(BNInstructionTextTokenContext context, uint64_t hash);
22710+
static bool IsInstructionCollapsed(Ref<Function> function, const HighLevelILInstruction& instr,
22711+
DisassemblySettings* settings, uint64_t designator = 0);
2270722712
bool HasCollapsableRegions();
2270822713
void SetHasCollapsableRegions(bool state);
2270922714

binaryninjacore.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -870,6 +870,7 @@ extern "C"
870870
ShowILTypes = 130,
871871
ShowILOpcodes = 131,
872872
ShowCollapseIndicators = 132,
873+
ShowCollapsedRegions = 133,
873874
};
874875

875876
BN_ENUM(uint32_t, BNDisassemblyAddressMode)
@@ -6071,6 +6072,8 @@ extern "C"
60716072
BINARYNINJACOREAPI bool BNLinearViewCursorNext(BNLinearViewCursor* cursor);
60726073
BINARYNINJACOREAPI bool BNLinearViewCursorPrevious(BNLinearViewCursor* cursor);
60736074
BINARYNINJACOREAPI BNLinearDisassemblyLine* BNGetLinearViewCursorLines(BNLinearViewCursor* cursor, size_t* count);
6075+
BINARYNINJACOREAPI bool BNExpandLinearViewCursorCollapsedRegionsForLine(
6076+
BNLinearViewCursor* cursor, size_t lineIndex);
60746077
BINARYNINJACOREAPI int BNCompareLinearViewCursors(BNLinearViewCursor* a, BNLinearViewCursor* b);
60756078

60766079
BINARYNINJACOREAPI BNRenderLayer** BNGetLinearViewCursorRenderLayers(BNLinearViewCursor* cursor, size_t* count);

highlevelil.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -692,14 +692,21 @@ void HighLevelILTokenEmitter::PrependCollapseIndicator()
692692

693693

694694
void HighLevelILTokenEmitter::PrependCollapseIndicator(Ref<Function> function, const HighLevelILInstruction& instr, uint64_t designator)
695+
{
696+
PrependCollapseIndicator(function, instr, nullptr, designator);
697+
}
698+
699+
void HighLevelILTokenEmitter::PrependCollapseIndicator(
700+
Ref<Function> function, const HighLevelILInstruction& instr, DisassemblySettings* settings, uint64_t designator)
695701
{
696702
if (!HasCollapsableRegions())
697703
return;
698704

699705
// Insert the collapse indicator at the beginning of the line if one isn't already there or the
700706
// one that is there is empty
701707
auto context = HighLevelILInstruction::CanCollapse(instr.operation) ?
702-
(function && function->IsInstructionCollapsed(instr, designator) ? ContentCollapsedContext : ContentExpandedContext) :
708+
(IsInstructionCollapsed(function, instr, settings, designator) ?
709+
ContentCollapsedContext : ContentExpandedContext) :
703710
ContentCollapsiblePadding;
704711

705712
PrependCollapseIndicator(context, instr.GetInstructionHash(designator));
@@ -710,6 +717,14 @@ void HighLevelILTokenEmitter::PrependCollapseIndicator(BNInstructionTextTokenCon
710717
BNHighLevelILTokenPrependCollapseIndicator(m_object, context, hash);
711718
}
712719

720+
bool HighLevelILTokenEmitter::IsInstructionCollapsed(
721+
Ref<Function> function, const HighLevelILInstruction& instr, DisassemblySettings* settings, uint64_t designator)
722+
{
723+
if (settings && settings->IsOptionSet(ShowCollapsedRegions))
724+
return false;
725+
return function && function->IsInstructionCollapsed(instr, designator);
726+
}
727+
713728
bool HighLevelILTokenEmitter::HasCollapsableRegions()
714729
{
715730
return BNHighLevelILTokenEmitterHasCollapsableRegions(m_object);

lang/c/pseudoc.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -734,7 +734,7 @@ void PseudoCFunction::GetExprTextInternal(const HighLevelILInstruction& instr, H
734734

735735
auto function = m_highLevelIL->GetFunction();
736736
if (instr.ast)
737-
tokens.PrependCollapseIndicator(function, instr);
737+
tokens.PrependCollapseIndicator(function, instr, settings);
738738

739739
// ensure we claim the line address for top level instrs on a line
740740
if (instr.operation != HLIL_BLOCK)
@@ -813,7 +813,7 @@ void PseudoCFunction::GetExprTextInternal(const HighLevelILInstruction& instr, H
813813
if (updateExpr.operation != HLIL_NOP)
814814
GetExprTextInternal(updateExpr, tokens, settings);
815815
tokens.AppendCloseParen();
816-
if (function->IsInstructionCollapsed(instr))
816+
if (HighLevelILTokenEmitter::IsInstructionCollapsed(function, instr, settings))
817817
{
818818
tokens.Append(CollapsedInformationToken, " {...}");
819819
}
@@ -854,7 +854,7 @@ void PseudoCFunction::GetExprTextInternal(const HighLevelILInstruction& instr, H
854854
if (!instr.ast)
855855
return;
856856

857-
if (function->IsInstructionCollapsed(instr))
857+
if (HighLevelILTokenEmitter::IsInstructionCollapsed(function, instr, settings))
858858
{
859859
tokens.Append(CollapsedInformationToken, " {...}");
860860
}
@@ -875,9 +875,9 @@ void PseudoCFunction::GetExprTextInternal(const HighLevelILInstruction& instr, H
875875
else if (falseExpr.operation != HLIL_NOP)
876876
{
877877
tokens.ScopeContinuation(false);
878-
tokens.PrependCollapseIndicator(function, instr, 1);
878+
tokens.PrependCollapseIndicator(function, instr, settings, 1);
879879
tokens.Append(KeywordToken, "else");
880-
if (function->IsInstructionCollapsed(instr, 1))
880+
if (HighLevelILTokenEmitter::IsInstructionCollapsed(function, instr, settings, 1))
881881
{
882882
tokens.Append(CollapsedInformationToken, " {...}");
883883
tokens.NewLine();
@@ -910,7 +910,7 @@ void PseudoCFunction::GetExprTextInternal(const HighLevelILInstruction& instr, H
910910
if (!instr.ast)
911911
return;
912912

913-
if (function->IsInstructionCollapsed(instr))
913+
if (HighLevelILTokenEmitter::IsInstructionCollapsed(function, instr, settings))
914914
{
915915
tokens.Append(CollapsedInformationToken, " {...}");
916916
}
@@ -933,7 +933,7 @@ void PseudoCFunction::GetExprTextInternal(const HighLevelILInstruction& instr, H
933933
if (instr.ast)
934934
{
935935
tokens.Append(KeywordToken, "do");
936-
if (function->IsInstructionCollapsed(instr))
936+
if (HighLevelILTokenEmitter::IsInstructionCollapsed(function, instr, settings))
937937
{
938938
tokens.Append(CollapsedInformationToken, " {...}");
939939
tokens.NewLine();
@@ -983,7 +983,7 @@ void PseudoCFunction::GetExprTextInternal(const HighLevelILInstruction& instr, H
983983
if (!instr.ast)
984984
return;
985985

986-
if (function->IsInstructionCollapsed(instr))
986+
if (HighLevelILTokenEmitter::IsInstructionCollapsed(function, instr, settings))
987987
{
988988
tokens.Append(CollapsedInformationToken, " {...}");
989989
}
@@ -998,10 +998,10 @@ void PseudoCFunction::GetExprTextInternal(const HighLevelILInstruction& instr, H
998998

999999
if (defaultExpr.operation != HLIL_NOP && defaultExpr.operation != HLIL_UNREACHABLE)
10001000
{
1001-
tokens.PrependCollapseIndicator(function, instr, 1);
1001+
tokens.PrependCollapseIndicator(function, instr, settings, 1);
10021002
tokens.Append(KeywordToken, "default");
10031003
tokens.Append(TextToken, ":");
1004-
if (function->IsInstructionCollapsed(instr, 1))
1004+
if (HighLevelILTokenEmitter::IsInstructionCollapsed(function, instr, settings, 1))
10051005
{
10061006
tokens.Append(CollapsedInformationToken, " {...}");
10071007
}
@@ -1038,13 +1038,13 @@ void PseudoCFunction::GetExprTextInternal(const HighLevelILInstruction& instr, H
10381038
if (!instr.ast)
10391039
return;
10401040

1041-
if (function->IsInstructionCollapsed(instr))
1041+
if (HighLevelILTokenEmitter::IsInstructionCollapsed(function, instr, settings))
10421042
{
10431043
tokens.Append(CollapsedInformationToken, " {...}");
10441044
}
10451045
else
10461046
{
1047-
tokens.PrependCollapseIndicator(function, instr);
1047+
tokens.PrependCollapseIndicator(function, instr, settings);
10481048
tokens.BeginScope(CaseScopeType);
10491049
GetExprTextInternal(trueExpr, tokens, settings, TopLevelOperatorPrecedence, true);
10501050

lang/rust/pseudorust.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -726,7 +726,7 @@ void PseudoRustFunction::GetExprText(const HighLevelILInstruction& instr, HighLe
726726

727727
auto function = m_highLevelIL->GetFunction();
728728
if (instr.ast)
729-
tokens.PrependCollapseIndicator(function, instr);
729+
tokens.PrependCollapseIndicator(function, instr, settings);
730730
if (instr.operation != HLIL_BLOCK)
731731
tokens.InitLine();
732732
switch (instr.operation)
@@ -846,7 +846,7 @@ void PseudoRustFunction::GetExprText(const HighLevelILInstruction& instr, HighLe
846846
GetExprText(updateExpr, tokens, settings);
847847
}
848848

849-
if (function->IsInstructionCollapsed(instr))
849+
if (HighLevelILTokenEmitter::IsInstructionCollapsed(function, instr, settings))
850850
{
851851
tokens.Append(CollapsedInformationToken, " {...}");
852852
}
@@ -878,7 +878,7 @@ void PseudoRustFunction::GetExprText(const HighLevelILInstruction& instr, HighLe
878878
if (!instr.ast)
879879
return;
880880

881-
if (function->IsInstructionCollapsed(instr))
881+
if (HighLevelILTokenEmitter::IsInstructionCollapsed(function, instr, settings))
882882
{
883883
tokens.Append(CollapsedInformationToken, " {...}");
884884
}
@@ -899,9 +899,9 @@ void PseudoRustFunction::GetExprText(const HighLevelILInstruction& instr, HighLe
899899
else if (falseExpr.operation != HLIL_NOP)
900900
{
901901
tokens.ScopeContinuation(false);
902-
tokens.PrependCollapseIndicator(function, instr, 1);
902+
tokens.PrependCollapseIndicator(function, instr, settings, 1);
903903
tokens.Append(KeywordToken, "else");
904-
if (function->IsInstructionCollapsed(instr, 1))
904+
if (HighLevelILTokenEmitter::IsInstructionCollapsed(function, instr, settings, 1))
905905
{
906906
tokens.Append(CollapsedInformationToken, " {...}");
907907
}
@@ -938,7 +938,7 @@ void PseudoRustFunction::GetExprText(const HighLevelILInstruction& instr, HighLe
938938
if (!instr.ast)
939939
return;
940940

941-
if (function->IsInstructionCollapsed(instr))
941+
if (HighLevelILTokenEmitter::IsInstructionCollapsed(function, instr, settings))
942942
{
943943
tokens.Append(CollapsedInformationToken, " {...}");
944944
}
@@ -960,7 +960,7 @@ void PseudoRustFunction::GetExprText(const HighLevelILInstruction& instr, HighLe
960960
if (instr.ast)
961961
{
962962
tokens.Append(KeywordToken, "do");
963-
if (function->IsInstructionCollapsed(instr))
963+
if (HighLevelILTokenEmitter::IsInstructionCollapsed(function, instr, settings))
964964
{
965965
tokens.Append(CollapsedInformationToken, " {...}");
966966
tokens.NewLine();
@@ -1002,7 +1002,7 @@ void PseudoRustFunction::GetExprText(const HighLevelILInstruction& instr, HighLe
10021002
if (!instr.ast)
10031003
return;
10041004

1005-
if (function->IsInstructionCollapsed(instr))
1005+
if (HighLevelILTokenEmitter::IsInstructionCollapsed(function, instr, settings))
10061006
{
10071007
tokens.Append(CollapsedInformationToken, " {...}");
10081008
}
@@ -1017,9 +1017,9 @@ void PseudoRustFunction::GetExprText(const HighLevelILInstruction& instr, HighLe
10171017
// Check for default case
10181018
if (defaultExpr.operation != HLIL_NOP && defaultExpr.operation != HLIL_UNREACHABLE)
10191019
{
1020-
tokens.PrependCollapseIndicator(function, instr, 1);
1020+
tokens.PrependCollapseIndicator(function, instr, settings, 1);
10211021
tokens.Append(TextToken, "_ =>");
1022-
if (function->IsInstructionCollapsed(instr, 1))
1022+
if (HighLevelILTokenEmitter::IsInstructionCollapsed(function, instr, settings, 1))
10231023
{
10241024
tokens.Append(CollapsedInformationToken, " {...}");
10251025
}
@@ -1056,7 +1056,7 @@ void PseudoRustFunction::GetExprText(const HighLevelILInstruction& instr, HighLe
10561056
if (!instr.ast)
10571057
return;
10581058

1059-
if (function->IsInstructionCollapsed(instr))
1059+
if (HighLevelILTokenEmitter::IsInstructionCollapsed(function, instr, settings))
10601060
{
10611061
tokens.Append(CollapsedInformationToken, " {...}");
10621062
}

linearviewcursor.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,12 @@ vector<LinearDisassemblyLine> LinearViewCursor::GetLines()
207207
}
208208

209209

210+
bool LinearViewCursor::ExpandCollapsedRegionsForLine(size_t lineIndex)
211+
{
212+
return BNExpandLinearViewCursorCollapsedRegionsForLine(m_object, lineIndex);
213+
}
214+
215+
210216
Ref<LinearViewCursor> LinearViewCursor::Duplicate()
211217
{
212218
return new LinearViewCursor(BNDuplicateLinearViewCursor(m_object));

python/lineardisassembly.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,9 @@ def lines(self) -> List['LinearDisassemblyLine']:
657657
count = ctypes.c_ulonglong(0)
658658
return LinearViewCursor._make_lines(core.BNGetLinearViewCursorLines(self.handle, count), count.value, current)
659659

660+
def expand_collapsed_regions_for_line(self, line_index: int) -> bool:
661+
return core.BNExpandLinearViewCursorCollapsedRegionsForLine(self.handle, line_index)
662+
660663
def duplicate(self) -> 'LinearViewCursor':
661664
return LinearViewCursor(None, handle=core.BNDuplicateLinearViewCursor(self.handle))
662665

rust/src/linear_view.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,10 @@ impl LinearViewCursor {
356356
}
357357
}
358358

359+
pub fn expand_collapsed_regions_for_line(&self, line_index: usize) -> bool {
360+
unsafe { BNExpandLinearViewCursorCollapsedRegionsForLine(self.handle, line_index) }
361+
}
362+
359363
/// A list of the currently applied [`CoreRenderLayer`]'s
360364
pub fn render_layers(&self) -> Array<CoreRenderLayer> {
361365
let mut count: usize = 0;

ui/linearview.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,7 @@ class BINARYNINJAUIAPI LinearView : public QAbstractScrollArea, public View, pub
316316

317317
BinaryNinja::Ref<BinaryNinja::LinearViewObject> createLinearViewObject();
318318
LinearViewCursorPosition getPositionForCursor(BinaryNinja::LinearViewCursor* cursor);
319+
bool revealHiddenAddress(uint64_t addr, FunctionRef func, size_t instrIndex);
319320
bool updateCursor(LinearViewCursorPosition& cursorToUpdate, BinaryNinja::LinearViewCursor* matched, bool fullMatch);
320321
bool updateCursor(LinearViewCursorPosition& cursorToUpdate, BinaryNinja::LinearViewCursor* newCursor);
321322
bool updateCursor(LinearViewCursorPosition& cursorToUpdate,

0 commit comments

Comments
 (0)