summaryrefslogtreecommitdiff
path: root/plugins/stack_render_layer
diff options
context:
space:
mode:
authorGlenn Smith <glenn@vector35.com>2024-12-27 16:14:46 -0500
committerGlenn Smith <glenn@vector35.com>2025-01-30 17:20:05 -0500
commit8862696926173104957729683832591438161557 (patch)
tree78ba6d7dc8144430136086c8dc84726171eec8ab /plugins/stack_render_layer
parent5a5426d030b6be26d4564ba1eba2d8a275533256 (diff)
Render Layers
Diffstat (limited to 'plugins/stack_render_layer')
-rw-r--r--plugins/stack_render_layer/CMakeLists.txt46
-rw-r--r--plugins/stack_render_layer/plugin.cpp124
2 files changed, 170 insertions, 0 deletions
diff --git a/plugins/stack_render_layer/CMakeLists.txt b/plugins/stack_render_layer/CMakeLists.txt
new file mode 100644
index 00000000..3133e63d
--- /dev/null
+++ b/plugins/stack_render_layer/CMakeLists.txt
@@ -0,0 +1,46 @@
+cmake_minimum_required(VERSION 3.9 FATAL_ERROR)
+
+project(stack_render_layer)
+
+file(GLOB SOURCES
+ *.cpp
+ *.c
+ *.h)
+
+if(DEMO)
+ add_library(${PROJECT_NAME} STATIC ${SOURCES})
+else()
+ add_library(${PROJECT_NAME} SHARED ${SOURCES})
+endif()
+
+if(NOT BN_INTERNAL_BUILD)
+ # Out-of-tree build
+ find_path(
+ BN_API_PATH
+ NAMES binaryninjaapi.h
+ HINTS ../../.. binaryninjaapi $ENV{BN_API_PATH}
+ REQUIRED
+ )
+ add_subdirectory(${BN_API_PATH} api)
+endif()
+
+target_link_libraries(${PROJECT_NAME} binaryninjaapi)
+
+set_target_properties(${PROJECT_NAME} PROPERTIES
+ CXX_STANDARD 17
+ CXX_VISIBILITY_PRESET hidden
+ CXX_STANDARD_REQUIRED ON
+ C_STANDARD 99
+ C_STANDARD_REQUIRED ON
+ C_VISIBILITY_PRESET hidden
+ VISIBILITY_INLINES_HIDDEN ON
+ POSITION_INDEPENDENT_CODE ON)
+
+if(BN_INTERNAL_BUILD)
+ plugin_rpath(${PROJECT_NAME})
+ set_target_properties(${PROJECT_NAME} PROPERTIES
+ LIBRARY_OUTPUT_DIRECTORY ${BN_CORE_PLUGIN_DIR}
+ RUNTIME_OUTPUT_DIRECTORY ${BN_CORE_PLUGIN_DIR})
+else()
+ bn_install_plugin(${PROJECT_NAME})
+endif()
diff --git a/plugins/stack_render_layer/plugin.cpp b/plugins/stack_render_layer/plugin.cpp
new file mode 100644
index 00000000..b32ee470
--- /dev/null
+++ b/plugins/stack_render_layer/plugin.cpp
@@ -0,0 +1,124 @@
+
+#include <binaryninjaapi.h>
+#include <thread>
+
+using namespace BinaryNinja;
+
+
+class StackRenderLayer: public RenderLayer
+{
+public:
+ StackRenderLayer(): RenderLayer("Annotate Stack Offset") {}
+
+ void ApplyToLines(
+ Ref<BasicBlock> block,
+ std::vector<DisassemblyTextLine>& lines
+ )
+ {
+ for (auto& line: lines)
+ {
+ // Skip blank lines (block separators)
+ if (line.tokens.empty())
+ {
+ continue;
+ }
+
+ // Insert tokens after the address separator
+ int64_t sep = -1;
+ for (int64_t i = 0; i < line.tokens.size(); i ++)
+ {
+ if (line.tokens[i].type == AddressSeparatorToken)
+ {
+ sep = i;
+ break;
+ }
+ }
+ // Don't annotate lines which don't have an address separator
+ // (these are usually annotations like { Does not return }
+ if (sep == -1)
+ {
+ continue;
+ }
+
+ // Grab stack offset value from function
+ auto stackOffset = block->GetFunction()->GetRegisterValueAtInstruction(
+ block->GetArchitecture(),
+ line.addr,
+ block->GetArchitecture()->GetStackPointerRegister()
+ );
+ auto stackOffsetAfter = block->GetFunction()->GetRegisterValueAfterInstruction(
+ block->GetArchitecture(),
+ line.addr,
+ block->GetArchitecture()->GetStackPointerRegister()
+ );
+ if (stackOffset.state == StackFrameOffset)
+ {
+ // Stack pointer is resolved to an offset: show the offset
+ // (but negative because that is how other tools do it)
+ line.tokens.emplace(
+ line.tokens.begin() + sep + 1,
+ IntegerToken,
+ fmt::format("{:4x}", -stackOffset.value),
+ -stackOffset.value
+ );
+ }
+ else
+ {
+ // Stack pointer is not resolved, show ??
+ line.tokens.emplace(
+ line.tokens.begin() + sep + 1,
+ IntegerToken,
+ " ??",
+ 0
+ );
+ }
+ // And put a spacer after the offset token
+ if (stackOffset != stackOffsetAfter)
+ {
+ line.tokens.emplace(
+ line.tokens.begin() + sep + 2,
+ TextToken,
+ "* "
+ );
+ }
+ else
+ {
+ line.tokens.emplace(
+ line.tokens.begin() + sep + 2,
+ TextToken,
+ " "
+ );
+ }
+ }
+ }
+
+ virtual void ApplyToDisassemblyBlock(
+ Ref<BasicBlock> block,
+ std::vector<DisassemblyTextLine>& lines
+ ) override
+ {
+ // Break this out into a helper so we don't have to write it twice
+ ApplyToLines(block, lines);
+ }
+
+ virtual void ApplyToLowLevelILBlock(
+ Ref<BasicBlock> block,
+ std::vector<DisassemblyTextLine>& lines
+ ) override
+ {
+ // Break this out into a helper so we don't have to write it twice
+ ApplyToLines(block, lines);
+ }
+};
+
+
+extern "C" {
+ BN_DECLARE_CORE_ABI_VERSION
+
+ BINARYNINJAPLUGIN bool CorePluginInit()
+ {
+ static StackRenderLayer* layer = new StackRenderLayer();
+ RenderLayer::Register(layer, DisabledByDefaultRenderLayerDefaultEnableState);
+ return true;
+ }
+} \ No newline at end of file