Skip to content

Commit 2998855

Browse files
committed
C++ Api for the fancier render layers
1 parent 1628991 commit 2998855

File tree

2 files changed

+281
-11
lines changed

2 files changed

+281
-11
lines changed

binaryninjaapi.h

Lines changed: 141 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19129,20 +19129,156 @@ namespace BinaryNinja {
1912919129
\return Render Layer's name
1913019130
*/
1913119131
std::string GetName() const;
19132+
/*! Apply this Render Layer to a single Basic Block of Disassembly lines.
19133+
Subclasses should modify the input `lines` list to make modifications to
19134+
the presentation of the block.
19135+
19136+
\note This function will only handle Disassembly lines, and not any ILs.
19137+
19138+
\param block Basic Block containing those lines
19139+
\param lines Lines of text for the block, to be modified by this function
19140+
*/
19141+
virtual void ApplyToDisassemblyBlock(
19142+
Ref<BasicBlock> block,
19143+
std::vector<DisassemblyTextLine>& lines
19144+
)
19145+
{
19146+
(void)block;
19147+
(void)lines;
19148+
}
19149+
19150+
/*! Apply this Render Layer to a single Basic Block of Low Level IL lines.
19151+
Subclasses should modify the input `lines` list to make modifications to
19152+
the presentation of the block.
19153+
19154+
\note This function will only handle Lifted IL/LLIL/LLIL(SSA) lines.
19155+
You can use the block's `function_graph_type` property to determine which is being handled.
19156+
19157+
\param block Basic Block containing those lines
19158+
\param lines Lines of text for the block, to be modified by this function
19159+
*/
19160+
virtual void ApplyToLowLevelILBlock(
19161+
Ref<BasicBlock> block,
19162+
std::vector<DisassemblyTextLine>& lines
19163+
)
19164+
{
19165+
(void)block;
19166+
(void)lines;
19167+
}
19168+
19169+
/*! Apply this Render Layer to a single Basic Block of Medium Level IL lines.
19170+
Subclasses should modify the input `lines` list to make modifications to
19171+
the presentation of the block.
19172+
19173+
\note This function will only handle MLIL/MLIL(SSA)/Mapped MLIL/Mapped MLIL(SSA) lines.
19174+
You can use the block's `function_graph_type` property to determine which is being handled.
19175+
19176+
\param block Basic Block containing those lines
19177+
\param lines Lines of text for the block, to be modified by this function
19178+
*/
19179+
virtual void ApplyToMediumLevelILBlock(
19180+
Ref<BasicBlock> block,
19181+
std::vector<DisassemblyTextLine>& lines
19182+
)
19183+
{
19184+
(void)block;
19185+
(void)lines;
19186+
}
19187+
19188+
/*! Apply this Render Layer to a single Basic Block of High Level IL lines.
19189+
Subclasses should modify the input `lines` list to make modifications to
19190+
the presentation of the block.
19191+
19192+
\note This function will only handle HLIL/HLIL(SSA)/Language Representation lines.
19193+
You can use the block's `function_graph_type` property to determine which is being handled.
19194+
19195+
\warning This function will NOT apply to High Level IL bodies as displayed
19196+
in Linear View! Those are handled by `ApplyToHighLevelILBody` instead as they
19197+
do not have a Basic Block associated with them.
19198+
19199+
\param block Basic Block containing those lines
19200+
\param lines Lines of text for the block, to be modified by this function
19201+
*/
19202+
virtual void ApplyToHighLevelILBlock(
19203+
Ref<BasicBlock> block,
19204+
std::vector<DisassemblyTextLine>& lines
19205+
)
19206+
{
19207+
(void)block;
19208+
(void)lines;
19209+
}
19210+
19211+
/*! Apply this Render Layer to the entire body of a High Level IL function.
19212+
Subclasses should modify the input `lines` list to make modifications to
19213+
the presentation of the function.
19214+
19215+
\warning This function only applies to Linear View, and not to Graph View!
19216+
If you want to handle Graph View too, you will need to use `ApplyToHighLevelILBlock`
19217+
and handle the lines one block at a time.
19218+
19219+
\param function Function containing those lines
19220+
\param lines Lines of text for the function, to be modified by this function
19221+
*/
19222+
virtual void ApplyToHighLevelILBody(
19223+
Ref<Function> function,
19224+
std::vector<LinearDisassemblyLine>& lines
19225+
)
19226+
{
19227+
(void)function;
19228+
(void)lines;
19229+
}
19230+
19231+
/*! Apply to lines generated by Linear View that are not part of a function.
19232+
It is up to your implementation to figure out which type of Linear View Object
19233+
lines these are, and what to do with them.
19234+
19235+
\param obj Linear View Object being rendered
19236+
\param prev Linear View Object located directly above this one
19237+
\param next Linear View Object located directly below this one
19238+
\param lines Lines rendered by `obj`, to be modified by this functino
19239+
*/
19240+
virtual void ApplyToMiscLinearLines(
19241+
Ref<LinearViewObject> obj,
19242+
Ref<LinearViewObject> prev,
19243+
Ref<LinearViewObject> next,
19244+
std::vector<LinearDisassemblyLine>& lines
19245+
)
19246+
{
19247+
(void)obj;
19248+
(void)prev;
19249+
(void)next;
19250+
(void)lines;
19251+
}
19252+
19253+
/*! Apply to lines generated by a Basic Block, of any type. If not overridden, this
19254+
function will call the appropriate ApplyToXLevelILBlock function.
19255+
19256+
\param block Basic Block containing those lines
19257+
\param lines Lines of text for the block, to be modified by this function
19258+
*/
19259+
virtual void ApplyToBlock(
19260+
Ref<BasicBlock> block,
19261+
std::vector<DisassemblyTextLine>& lines
19262+
);
1913219263

1913319264
/*! Apply this Render Layer to a Flow Graph, potentially modifying its nodes,
1913419265
their edges, their lines, and their lines' content.
1913519266

19267+
\note If you override this function, you will need to call the parent
19268+
implementation if you want to use the higher level ApplyToXLevelILBlock
19269+
functionality.
19270+
1913619271
\param graph Graph to modify
1913719272
*/
19138-
virtual void ApplyToFlowGraph(Ref<FlowGraph> graph)
19139-
{
19140-
(void)graph;
19141-
}
19273+
virtual void ApplyToFlowGraph(Ref<FlowGraph> graph);
1914219274

1914319275
/*! Apply this Render Layer to the lines produced by a LinearViewObject for rendering
1914419276
in Linear View, potentially modifying the lines and their contents.
1914519277

19278+
\note If you override this function, you will need to call the parent
19279+
implementation if you want to use the higher level ApplyToXLevelILBlock
19280+
functionality.
19281+
1914619282
\param obj Linear View Object being rendered
1914719283
\param prev Linear View Object located directly above this one
1914819284
\param next Linear View Object located directly below this one
@@ -19154,13 +19290,7 @@ namespace BinaryNinja {
1915419290
Ref<LinearViewObject> prev,
1915519291
Ref<LinearViewObject> next,
1915619292
std::vector<LinearDisassemblyLine>& lines
19157-
)
19158-
{
19159-
(void)obj;
19160-
(void)prev;
19161-
(void)next;
19162-
(void)lines;
19163-
}
19293+
);
1916419294
};
1916519295

1916619296
class CoreRenderLayer: public RenderLayer

renderlayer.cpp

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,146 @@ std::string RenderLayer::GetName() const
115115
}
116116

117117

118+
void RenderLayer::ApplyToBlock(
119+
Ref<BasicBlock> block,
120+
std::vector<DisassemblyTextLine>& lines
121+
)
122+
{
123+
if (!block->IsILBlock())
124+
{
125+
ApplyToDisassemblyBlock(block, lines);
126+
}
127+
else if (block->IsLowLevelILBlock())
128+
{
129+
ApplyToLowLevelILBlock(block, lines);
130+
}
131+
else if (block->IsMediumLevelILBlock())
132+
{
133+
ApplyToMediumLevelILBlock(block, lines);
134+
}
135+
else if (block->IsHighLevelILBlock())
136+
{
137+
ApplyToHighLevelILBlock(block, lines);
138+
}
139+
}
140+
141+
142+
void RenderLayer::ApplyToFlowGraph(Ref<FlowGraph> graph)
143+
{
144+
for (auto node: graph->GetNodes())
145+
{
146+
auto lines = node->GetLines();
147+
if (node->GetBasicBlock())
148+
{
149+
ApplyToBlock(node->GetBasicBlock(), lines);
150+
}
151+
node->SetLines(lines);
152+
}
153+
}
154+
155+
156+
void RenderLayer::ApplyToLinearViewObject(
157+
Ref<LinearViewObject> obj,
158+
Ref<LinearViewObject> prev,
159+
Ref<LinearViewObject> next,
160+
std::vector<LinearDisassemblyLine>& lines
161+
)
162+
{
163+
// Hack: HLIL bodies don't have basic blocks
164+
if (!lines.empty() &&
165+
(obj->GetIdentifier().name == "HLIL Function Body"
166+
|| obj->GetIdentifier().name == "HLIL SSA Function Body"
167+
|| obj->GetIdentifier().name == "Language Representation Function Body"))
168+
{
169+
ApplyToHighLevelILBody(lines[0].function, lines);
170+
return;
171+
}
172+
173+
std::vector<LinearDisassemblyLine> blockLines;
174+
std::vector<LinearDisassemblyLine> finalLines;
175+
Ref<BasicBlock> lastBlock;
176+
177+
for (auto& line: lines)
178+
{
179+
// Assume we've finished a block when the line's block changes
180+
if (line.block != lastBlock)
181+
{
182+
if (!blockLines.empty())
183+
{
184+
if (lastBlock)
185+
{
186+
// Convert linear lines to disassembly lines for the apply()
187+
// and then convert back for linear view
188+
std::vector<DisassemblyTextLine> disasmLines;
189+
for (auto& blockLine: blockLines)
190+
{
191+
disasmLines.push_back(blockLine.contents);
192+
}
193+
ApplyToBlock(lastBlock, disasmLines);
194+
195+
Ref<BasicBlock> block = blockLines[0].block;
196+
Ref<Function> func = blockLines[0].function;
197+
blockLines.clear();
198+
for (auto& blockLine: disasmLines)
199+
{
200+
LinearDisassemblyLine newLine;
201+
// todo: losing this information (might not matter)
202+
newLine.type = CodeDisassemblyLineType;
203+
newLine.block = block;
204+
newLine.function = func;
205+
newLine.contents = blockLine;
206+
blockLines.push_back(newLine);
207+
}
208+
}
209+
else
210+
{
211+
ApplyToMiscLinearLines(obj, prev, next, blockLines);
212+
}
213+
}
214+
lastBlock = line.block;
215+
std::move(blockLines.begin(), blockLines.end(), std::back_inserter(finalLines));
216+
}
217+
blockLines.push_back(line);
218+
}
219+
// And we've finished a block when we're done with every line
220+
if (!blockLines.empty())
221+
{
222+
if (lastBlock)
223+
{
224+
// Convert linear lines to disassembly lines for the apply()
225+
// and then convert back for linear view
226+
std::vector<DisassemblyTextLine> disasmLines;
227+
for (auto& blockLine: blockLines)
228+
{
229+
disasmLines.push_back(blockLine.contents);
230+
}
231+
ApplyToBlock(lastBlock, disasmLines);
232+
233+
Ref<BasicBlock> block = blockLines[0].block;
234+
Ref<Function> func = blockLines[0].function;
235+
blockLines.clear();
236+
for (auto& blockLine: disasmLines)
237+
{
238+
LinearDisassemblyLine newLine;
239+
// todo: losing this information (might not matter)
240+
newLine.type = CodeDisassemblyLineType;
241+
newLine.block = block;
242+
newLine.function = func;
243+
newLine.contents = blockLine;
244+
blockLines.push_back(newLine);
245+
}
246+
}
247+
else
248+
{
249+
ApplyToMiscLinearLines(obj, prev, next, blockLines);
250+
}
251+
}
252+
std::move(blockLines.begin(), blockLines.end(), std::back_inserter(finalLines));
253+
254+
lines = finalLines;
255+
}
256+
257+
118258
CoreRenderLayer::CoreRenderLayer(BNRenderLayer* layer): RenderLayer(layer)
119259
{
120260
}

0 commit comments

Comments
 (0)