Skip to content

Commit 16c83ff

Browse files
committed
Add source line render layer plugin
1 parent 7e1eee3 commit 16c83ff

2 files changed

Lines changed: 155 additions & 0 deletions

File tree

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
cmake_minimum_required(VERSION 3.15 FATAL_ERROR)
2+
3+
project(source_line_render_layer)
4+
5+
file(GLOB SOURCES CONFIGURE_DEPENDS
6+
*.cpp
7+
*.c
8+
*.h)
9+
10+
if(DEMO)
11+
add_library(${PROJECT_NAME} STATIC ${SOURCES})
12+
else()
13+
add_library(${PROJECT_NAME} SHARED ${SOURCES})
14+
endif()
15+
16+
if(NOT BN_INTERNAL_BUILD)
17+
# Out-of-tree build
18+
find_path(
19+
BN_API_PATH
20+
NAMES binaryninjaapi.h
21+
HINTS ../../.. binaryninjaapi $ENV{BN_API_PATH}
22+
REQUIRED
23+
)
24+
add_subdirectory(${BN_API_PATH} api)
25+
endif()
26+
27+
target_link_libraries(${PROJECT_NAME} binaryninjaapi)
28+
29+
set_target_properties(${PROJECT_NAME} PROPERTIES
30+
CXX_STANDARD 20
31+
CXX_VISIBILITY_PRESET hidden
32+
CXX_STANDARD_REQUIRED ON
33+
C_STANDARD 99
34+
C_STANDARD_REQUIRED ON
35+
C_VISIBILITY_PRESET hidden
36+
VISIBILITY_INLINES_HIDDEN ON
37+
POSITION_INDEPENDENT_CODE ON)
38+
39+
if(BN_INTERNAL_BUILD)
40+
plugin_rpath(${PROJECT_NAME})
41+
set_target_properties(${PROJECT_NAME} PROPERTIES
42+
LIBRARY_OUTPUT_DIRECTORY ${BN_CORE_PLUGIN_DIR}
43+
RUNTIME_OUTPUT_DIRECTORY ${BN_CORE_PLUGIN_DIR})
44+
else()
45+
bn_install_plugin(${PROJECT_NAME})
46+
endif()
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
#include <binaryninjaapi.h>
2+
3+
using namespace BinaryNinja;
4+
5+
6+
class SourceLineRenderLayer: public RenderLayer
7+
{
8+
static std::string DisplayPath(const std::string& path)
9+
{
10+
size_t pos = path.find_last_of("/\\");
11+
if (pos == std::string::npos)
12+
return path;
13+
return path.substr(pos + 1);
14+
}
15+
16+
static bool HasAddressSeparator(const DisassemblyTextLine& line)
17+
{
18+
for (const auto& token : line.tokens)
19+
{
20+
if (token.type == AddressSeparatorToken)
21+
return true;
22+
}
23+
return false;
24+
}
25+
26+
static void ApplyToLine(Ref<DebugInfo> debugInfo, DisassemblyTextLine& line, bool requireAddressSeparator)
27+
{
28+
if (line.tokens.empty())
29+
return;
30+
31+
if (requireAddressSeparator && !HasAddressSeparator(line))
32+
return;
33+
34+
auto sourceLines = debugInfo->GetSourceLinesByAddress(line.addr);
35+
if (sourceLines.empty())
36+
return;
37+
38+
const auto& sourceLine = std::get<1>(sourceLines.front());
39+
std::string text = " // " + DisplayPath(sourceLine.sourceFile) + ":" + std::to_string(sourceLine.line);
40+
if (sourceLine.column != 0)
41+
text += ":" + std::to_string(sourceLine.column);
42+
43+
line.tokens.emplace_back(CommentToken, text, line.addr);
44+
}
45+
46+
void ApplyToLines(Ref<BasicBlock> block, std::vector<DisassemblyTextLine>& lines, bool requireAddressSeparator = true)
47+
{
48+
Ref<DebugInfo> debugInfo = block->GetFunction()->GetView()->GetDebugInfo();
49+
if (!debugInfo)
50+
return;
51+
52+
for (auto& line : lines)
53+
ApplyToLine(debugInfo, line, requireAddressSeparator);
54+
}
55+
56+
public:
57+
SourceLineRenderLayer(): RenderLayer("Source Line Annotations") {}
58+
59+
void ApplyToDisassemblyBlock(Ref<BasicBlock> block, std::vector<DisassemblyTextLine>& lines) override
60+
{
61+
ApplyToLines(block, lines);
62+
}
63+
64+
void ApplyToLowLevelILBlock(Ref<BasicBlock> block, std::vector<DisassemblyTextLine>& lines) override
65+
{
66+
ApplyToLines(block, lines);
67+
}
68+
69+
void ApplyToMediumLevelILBlock(Ref<BasicBlock> block, std::vector<DisassemblyTextLine>& lines) override
70+
{
71+
ApplyToLines(block, lines);
72+
}
73+
74+
void ApplyToHighLevelILBlock(Ref<BasicBlock> block, std::vector<DisassemblyTextLine>& lines) override
75+
{
76+
ApplyToLines(block, lines, false);
77+
}
78+
79+
void ApplyToHighLevelILBody(Ref<Function> function, std::vector<LinearDisassemblyLine>& lines) override
80+
{
81+
Ref<DebugInfo> debugInfo = function->GetView()->GetDebugInfo();
82+
if (!debugInfo)
83+
return;
84+
85+
for (auto& line : lines)
86+
{
87+
if (line.type != CodeDisassemblyLineType)
88+
continue;
89+
90+
ApplyToLine(debugInfo, line.contents, false);
91+
}
92+
}
93+
};
94+
95+
96+
extern "C" {
97+
BN_DECLARE_CORE_ABI_VERSION
98+
99+
#ifdef DEMO_EDITION
100+
bool SourceLineRenderLayerPluginInit()
101+
#else
102+
BINARYNINJAPLUGIN bool CorePluginInit()
103+
#endif
104+
{
105+
static SourceLineRenderLayer* layer = new SourceLineRenderLayer();
106+
RenderLayer::Register(layer, DisabledByDefaultRenderLayerDefaultEnableState);
107+
return true;
108+
}
109+
}

0 commit comments

Comments
 (0)