├── .clang-format
├── .clang-tidy
├── .clangd
├── .dockerignore
├── .github
├── assets
│ ├── graph1_dark.png
│ ├── graph2_dark.png
│ ├── graph3_dark.png
│ ├── graph4_dark.png
│ ├── graph5_dark.png
│ ├── triskel-gui.png
│ ├── triskel_dark.png
│ ├── triskel_dark.svg
│ ├── triskel_light.png
│ └── triskel_light.svg
└── diagrams
│ └── GithubSteps.drawio
├── .gitignore
├── CMakeLists.txt
├── LICENSE
├── README.md
├── bin
├── CMakeLists.txt
├── bench
│ ├── CMakeLists.txt
│ ├── README.md
│ ├── main.cpp
│ └── src
│ │ └── table.hpp
├── gui
│ ├── CMakeLists.txt
│ ├── README.md
│ ├── assets
│ │ ├── fonts
│ │ │ ├── Lato-Bold.ttf
│ │ │ ├── Lato-Light.ttf
│ │ │ └── Roboto-Medium.ttf
│ │ └── img
│ │ │ └── Triskel.png
│ ├── disas
│ │ ├── CMakeLists.txt
│ │ ├── rec_descent.cpp
│ │ └── rec_descent.hpp
│ ├── external
│ │ ├── CMakeLists.txt
│ │ ├── application.cpp
│ │ ├── application.h
│ │ ├── credit.md
│ │ ├── platform.h
│ │ ├── platform_glw.cpp
│ │ ├── renderer.h
│ │ └── renderer_ogl3.cpp
│ ├── gui
│ │ ├── CMakeLists.txt
│ │ ├── arch
│ │ │ ├── CMakeLists.txt
│ │ │ ├── arch.hpp
│ │ │ ├── arch_binary.cpp
│ │ │ └── arch_llvm.cpp
│ │ ├── triskel.cpp
│ │ └── triskel.hpp
│ └── main.cpp
├── img
│ ├── CMakeLists.txt
│ ├── README.md
│ └── main.cpp
└── wasm
│ ├── CMakeLists.txt
│ └── main.cpp
├── bindings
├── CMakeLists.txt
└── python
│ ├── .gitignore
│ ├── CMakeLists.txt
│ ├── README.md
│ ├── build_wheels.sh
│ ├── pyproject.toml
│ ├── pytriskel.cpp
│ ├── pytriskel
│ ├── __init__.pyi
│ └── pytriskel.pyi
│ └── setup.py
├── cmake
└── FindCairo.cmake
├── docker
├── fedora
│ ├── Dockerfile
│ ├── dependencies.sh
│ └── imgui.CMakeLists.txt
└── manylinux
│ └── Dockerfile
├── lib
├── CMakeLists.txt
├── include
│ └── triskel
│ │ ├── analysis
│ │ ├── dfs.hpp
│ │ ├── lengauer_tarjan.hpp
│ │ ├── patriarchal.hpp
│ │ ├── sese.hpp
│ │ └── udfs.hpp
│ │ ├── datatypes
│ │ ├── rtree.hpp
│ │ └── rtree.ipp
│ │ ├── graph
│ │ ├── graph.hpp
│ │ ├── graph_view.hpp
│ │ ├── igraph.hpp
│ │ └── subgraph.hpp
│ │ ├── internal.hpp
│ │ ├── layout
│ │ ├── ilayout.hpp
│ │ ├── layout.hpp
│ │ ├── phantom_nodes.hpp
│ │ └── sugiyama
│ │ │ ├── layer_assignement.hpp
│ │ │ ├── sugiyama.hpp
│ │ │ └── vertex_ordering.hpp
│ │ ├── llvm
│ │ └── llvm.hpp
│ │ ├── triskel.hpp
│ │ └── utils
│ │ ├── attribute.hpp
│ │ ├── constants.hpp
│ │ ├── point.hpp
│ │ └── tree.hpp
└── src
│ ├── CMakeLists.txt
│ ├── analysis
│ ├── CMakeLists.txt
│ ├── dfs.cpp
│ ├── lengauer_tarjan.cpp
│ ├── patriarchal.cpp
│ ├── sese.cpp
│ └── udfs.cpp
│ ├── graph
│ ├── CMakeLists.txt
│ ├── graph.cpp
│ ├── graph_view.cpp
│ ├── igraph.cpp
│ └── subgraph.cpp
│ ├── layout
│ ├── CMakeLists.txt
│ ├── ilayout.cpp
│ ├── layout.cpp
│ ├── phantom_nodes.cpp
│ └── sugiyama
│ │ ├── CMakeLists.txt
│ │ ├── network_simplex.cpp
│ │ ├── sugiyama.cpp
│ │ ├── tamassia.cpp
│ │ └── vertex_ordering.cpp
│ ├── llvm
│ ├── CMakeLists.txt
│ ├── llvm.cpp
│ └── triskel.cpp
│ ├── renderer
│ ├── CMakeLists.txt
│ ├── cairo.cpp
│ ├── external
│ │ ├── CMakeLists.txt
│ │ ├── credit.md
│ │ ├── imgui_canvas.cpp
│ │ └── imgui_canvas.h
│ └── imgui.cpp
│ └── triskel.cpp
└── test
├── CMakeLists.txt
├── analysis
├── CMakeLists.txt
├── dfs_test.cpp
└── lengauer_tarjan_test.cpp
├── datatypes
├── CMakeLists.txt
└── rtree_test.cpp
├── graph
├── CMakeLists.txt
├── attribute_test.cpp
├── graph_editor_test.cpp
├── graph_test.cpp
└── subgraph_test.cpp
└── triskel_test.cpp
/.clang-format:
--------------------------------------------------------------------------------
1 | ---
2 | Language: Cpp
3 | BasedOnStyle: chromium
4 | IndentWidth: 4
5 | AlignConsecutiveAssignments: true
6 |
--------------------------------------------------------------------------------
/.clang-tidy:
--------------------------------------------------------------------------------
1 | ---
2 | HeaderFilterRegex: include
3 | FormatStyle: google
4 | Checks: >
5 | bugprone-*,
6 | clang-analyzer-*,
7 | google-*,
8 | misc-*,
9 | modernize-*,
10 | performance-*,
11 | portability-*,
12 | readability-*,
13 | -google-readability-todo,
14 | -misc-non-private-member-variables-in-classes,
15 | -modernize-use-emplace,
16 | -readability-identifier-length,
17 | -readability-magic-numbers,
18 | -readability-function-cognitive-complexity,
19 | -bugprone-easily-swappable-parameters,
20 | CheckOptions:
21 | - key: misc-include-cleaner.IgnoreHeaders
22 | value: fmt/printf.h;fmt/chrono.h;bits/ranges_algo.h
23 | - key: modernize-use-ranges.UseReversePipe
24 | value: true
25 |
--------------------------------------------------------------------------------
/.clangd:
--------------------------------------------------------------------------------
1 | CompileFlags:
2 | CompilationDatabase: "build/debug"
3 |
4 | ---
5 | If:
6 | PathMatch: bindings/.*
7 | CompileFlags:
8 | CompilationDatabase: "build/bindings"
9 |
10 | ---
11 | If:
12 | PathMatch: bin/wasm/.*
13 | CompileFlags:
14 | CompilationDatabase: "build/wasm"
15 |
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | .github
2 | .vscode/
3 | .venv/
4 | build/
5 |
6 | makefile
7 |
8 | *.ini
9 |
10 | triskel-bench
11 | triskel-image
12 | triskel-gui
13 |
14 | *.csv
--------------------------------------------------------------------------------
/.github/assets/graph1_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/triskellib/triskel/4b02ad9e162788f4653a404ef47d1b26400ca62d/.github/assets/graph1_dark.png
--------------------------------------------------------------------------------
/.github/assets/graph2_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/triskellib/triskel/4b02ad9e162788f4653a404ef47d1b26400ca62d/.github/assets/graph2_dark.png
--------------------------------------------------------------------------------
/.github/assets/graph3_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/triskellib/triskel/4b02ad9e162788f4653a404ef47d1b26400ca62d/.github/assets/graph3_dark.png
--------------------------------------------------------------------------------
/.github/assets/graph4_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/triskellib/triskel/4b02ad9e162788f4653a404ef47d1b26400ca62d/.github/assets/graph4_dark.png
--------------------------------------------------------------------------------
/.github/assets/graph5_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/triskellib/triskel/4b02ad9e162788f4653a404ef47d1b26400ca62d/.github/assets/graph5_dark.png
--------------------------------------------------------------------------------
/.github/assets/triskel-gui.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/triskellib/triskel/4b02ad9e162788f4653a404ef47d1b26400ca62d/.github/assets/triskel-gui.png
--------------------------------------------------------------------------------
/.github/assets/triskel_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/triskellib/triskel/4b02ad9e162788f4653a404ef47d1b26400ca62d/.github/assets/triskel_dark.png
--------------------------------------------------------------------------------
/.github/assets/triskel_light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/triskellib/triskel/4b02ad9e162788f4653a404ef47d1b26400ca62d/.github/assets/triskel_light.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .venv/
2 | .vscode/
3 |
4 | build/
5 |
6 | makefile
7 |
8 |
9 | triskel-bench
10 | triskel-img
11 | triskel-gui
12 |
13 | *.csv
14 | *.ini
15 | out.*
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.30)
2 |
3 | include(CMakeDependentOption)
4 | include(FetchContent)
5 |
6 | project(Triskel)
7 |
8 | set(CMAKE_CXX_STANDARD 23)
9 | set(CMAKE_CXX_STANDARD_REQUIRED True)
10 |
11 | set(CMAKE_POSITION_INDEPENDENT_CODE ON)
12 |
13 | option(ENABLE_LLVM "Adds utilities to convert LLVM functions to triskel graphs" OFF)
14 | option(ENABLE_IMGUI "Adds utilities to display graphs in imgui" OFF)
15 | option(ENABLE_CAIRO "Adds utilities to create SVG/PNG using cairo" OFF)
16 |
17 | option(ENABLE_LINTING "Linting" OFF)
18 | option(ENABLE_TESTING "Tests" OFF)
19 |
20 | cmake_dependent_option(BUILD_WASM "Builds to wasm" OFF "NOT ENABLE_CAIRO; NOT ENABLE_LLVM; NOT ENABLE_IMGUI" OFF)
21 | cmake_dependent_option(BUILD_BINDINGS "Builds the python bindings" OFF "ENABLE_CAIRO; NOT ENABLE_LLVM; NOT ENABLE_IMGUI" OFF)
22 | cmake_dependent_option(BUILD_BENCH "Builds the binary used for benchmarking" OFF "ENABLE_LLVM" OFF)
23 | cmake_dependent_option(BUILD_GUI "Builds the gui binary" OFF "ENABLE_LLVM; ENABLE_IMGUI" OFF)
24 | cmake_dependent_option(BUILD_IMG "Builds the img binary" OFF "ENABLE_LLVM; ENABLE_CAIRO" OFF)
25 |
26 |
27 | # libfmt
28 | FetchContent_Declare(
29 | fmt
30 | GIT_REPOSITORY https://github.com/fmtlib/fmt
31 | GIT_TAG 11.1.4
32 | FIND_PACKAGE_ARGS
33 | )
34 | FetchContent_MakeAvailable(fmt)
35 | message(STATUS "Found fmt version ${fmt_VERSION}")
36 |
37 | if(ENABLE_TESTING)
38 | message(STATUS "Building tests")
39 | find_package(GTest CONFIG REQUIRED)
40 | add_subdirectory(test)
41 | endif()
42 |
43 | if (ENABLE_CAIRO)
44 | message(STATUS "Building with cairo support")
45 | include(${PROJECT_SOURCE_DIR}/cmake/FindCairo.cmake)
46 | endif()
47 |
48 | if(ENABLE_LLVM)
49 | message(STATUS "Building with LLVM support")
50 | find_package(LLVM CONFIG REQUIRED)
51 | if(LLVM_LINK_LLVM_DYLIB)
52 | set(llvm_libs LLVM)
53 | else()
54 | llvm_map_components_to_libnames(llvm_libs
55 | support core irreader
56 | bitreader bitwriter
57 | passes asmprinter
58 | aarch64info aarch64desc aarch64codegen aarch64asmparser
59 | armcodegen armasmparser
60 | interpreter mcjit
61 | nvptxdesc
62 | x86info x86codegen x86asmparser
63 | sparccodegen sparcasmparser
64 | webassemblydesc)
65 | endif()
66 |
67 | message(STATUS "LLVM Libraries: ${llvm_libs}")
68 | message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
69 | message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
70 |
71 | include_directories(SYSTEM ${LLVM_INCLUDE_DIRS})
72 |
73 | string(REPLACE "." ";" LLVM_VERSION_LIST ${LLVM_PACKAGE_VERSION})
74 | list(GET LLVM_VERSION_LIST 0 LLVM_MAJOR_VERSION)
75 | list(GET LLVM_VERSION_LIST 1 LLVM_MINOR_VERSION)
76 |
77 | set(LLVM_MAJOR_VERSION "${LLVM_MAJOR_VERSION}")
78 | set(LLVM_MINOR_VERSION "${LLVM_MINOR_VERSION}")
79 | endif()
80 |
81 | if (ENABLE_IMGUI)
82 | message(STATUS "Building with ImGui support")
83 | find_package(imgui REQUIRED)
84 | find_package(glfw3 REQUIRED)
85 | find_package(OpenGL REQUIRED)
86 | find_package(GLEW REQUIRED)
87 | endif()
88 |
89 | if(BUILD_BINDINGS)
90 | message(STATUS "Building bindings")
91 | add_subdirectory(bindings)
92 | endif()
93 |
94 | add_subdirectory(bin)
95 | add_subdirectory(lib)
96 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | **Triskel** is a Control Flow Graph (CFG) layout engine. It provides you with
22 | coordinates to draw CFGs in your reverse-engineering tools.
23 |
24 | - CFG specific layout, emphasizing Single Entry Single Exit Regions
25 | - Python bindings
26 | - Export to PNG / SVG (with cairo)
27 | - DearImgui integration
28 | - LLVM integration
29 |
30 |
31 | ## Quick start
32 |
33 | ### Python
34 |
35 | ```
36 | $ pip install pytriskel
37 | ```
38 |
39 | ```python
40 | from pytriskel.pytriskel import *
41 |
42 | builder = make_layout_builder()
43 |
44 | # Build the graph
45 | n1 = builder.make_node("Hello")
46 | n2 = builder.make_node("World")
47 | builder.make_edge(n1, n2)
48 |
49 | # Measure node size using font size
50 | png_renderer = make_png_renderer()
51 | builder.measure_nodes(png_renderer)
52 |
53 | # Export an image
54 | layout = builder.build()
55 | layout.save(png_renderer, "out.png")
56 | ```
57 |
58 | ### C++
59 |
60 | ```cpp
61 | #include
62 |
63 | int main(void) {
64 | auto builder = triskel::make_layout_builder();
65 |
66 | auto n1 = builder->make_node("Hello");
67 | auto n2 = builder->make_node("World");
68 | builder->make_edge(n1, n2)
69 |
70 | auto renderer = triskel::make_svg_renderer();
71 | builder->measure_nodes(renderer)
72 | auto layout = builder->build();
73 |
74 | layout->render_and_save(*renderer, "./out.svg");
75 |
76 | return 1;
77 | }
78 | ```
79 |
80 | ## Theory
81 |
82 | Triskel is the implementation for the paper [Towards better CFG layouts](https://hal.science/hal-04996939).
83 |
84 | The key idea behind Triskel is to split the CFG into Single Entry Single Exit regions.
85 | We are then able to layout each region taking advantage of a divide and conquer approach.
86 |
87 | ## Walkthrough
88 |
89 | Initially we have a directed graph
90 |
91 | 
92 |
93 | The first step involves identifying Single Entry Single Exit (SESE) regions. (See the implementation here: [sese.cpp](https://github.com/triskellib/triskel/blob/master/lib/src/analysis/sese.cpp))
94 | In the diagram, the region is in blue. Notice how a single edge enters and exits the blue border.
95 |
96 | 
97 |
98 | We can then split each region out of the graph. At this step we have multiple smaller directed graphs.
99 | Note that how in the graph of the SESE region, we had to add 2 virtual nodes to represent the entry and exit points.
100 | In the other graph, we added an additional node to represent the region (still in blue).
101 |
102 | 
103 |
104 | The next step involves laying out each SESE region's graph using Sugiyama algorithm (See the implementation here: [sugiyama.cpp](https://github.com/triskellib/triskel/blob/master/lib/src/layout/sugiyama/sugiyama.cpp)).
105 | Note how we have to layout the SESE region first in order to know the coordinates of the blue node.
106 |
107 | 
108 |
109 | Finally, we can superimpose the layouts to obtain the final layout.
110 |
111 | 
112 |
113 | ## Compilation
114 |
115 | Triskel relies on the following dependencies (the provided binaries also have their own dependencies)
116 |
117 | - [fmt](https://github.com/fmtlib/fmt)
118 |
119 | Triskel can then be compiled with cmake
120 |
121 | ```
122 | $ git clone https://github.com/triskeles/triskel
123 | $ cd triskel
124 | $ cmake -B build
125 | $ cmake --build build
126 | ```
127 |
128 | You can then link to Triskel
129 |
130 | ```cmake
131 | target_link_libraries(foo PRIVATE triskel)
132 | ```
133 |
134 | ### CMake options
135 |
136 | To compile with all options and external dependencies check the [dockerfile](https://github.com/triskellib/triskel/tree/master/docker/fedora).
137 |
138 | #### `ENABLE_LLVM`
139 |
140 | Adds [LLVM](https://llvm.org/) integration.
141 |
142 | This also adds `LLVM 19` as a dependency.
143 |
144 | #### `ENABLE_IMGUI`
145 |
146 | Adds [ImGui](https://github.com/ocornut/imgui) integration, used for making GUIs.
147 |
148 | This adds the following dependencies:
149 |
150 | - `imgui` (To use compile imgui with CMake you can use the code in [`docker/fedora/dependencies.sh`](https://github.com/triskellib/triskel/blob/master/docker/fedora/dependencies.sh))
151 | - `glfw3`
152 | - `OpenGL`
153 | - `GLEW`
154 | - `SDL2`
155 | - `stb_image`
156 |
157 | #### `ENABLE_CAIRO`
158 |
159 | Adds [Cairo](https://www.cairographics.org/) integration, used for exporting images.
160 |
161 | ## Binaries
162 |
163 | Triskel comes with many example binaries to help illustrate usage.
164 |
165 | These binaries all require an additional dependency:
166 |
167 | - [gflags](https://gflags.github.io/gflags/)
168 |
169 | ### [triskel-bench](https://github.com/triskellib/triskel/tree/master/bin/bench)
170 |
171 | > Used for testing and evaluation.
172 |
173 | This binary lays out each function in an LLVM module and outputs a CSV containing performance reviews.
174 |
175 | It can also be used on a single function to analyze the lay out with `perf`.
176 |
177 | #### Dependencies
178 |
179 | This binary only requires `triskel` built with `ENABLE_LLVM=ON`.
180 |
181 |
182 |
183 |
184 |
185 | ### [triskel-gui](https://github.com/triskellib/triskel/tree/master/bin/gui)
186 |
187 | An example implementation of a GUI using Dear ImGui.
188 |
189 | This application has a _very limited_ disassembler for x64 binaries.
190 |
191 | #### Dependencies
192 |
193 | This binary requires `triskel` built with `ENABLE_LLVM=ON` and `ENABLE_IMGUI=ON`.
194 |
195 | It also needs [LIEF](https://lief.re/) and [Capstone](http://www.capstone-engine.org/) for the disassembler.
196 |
197 | ### [triskel-img](https://github.com/triskellib/triskel/tree/master/bin/img)
198 |
199 | A binary that generates images for CFGs using cairo.
200 |
201 | #### Dependencies
202 |
203 | This binary requires `triskel` built with `ENABLE_LLVM=ON` and `ENABLE_CAIRO=ON`.
204 |
205 | It also requires [`capstone`](http://www.capstone-engine.org/) and [`LIEF`](https://lief.re/)
206 |
207 | ## Python bindings
208 |
209 | You can download the python bindings using pip:
210 |
211 | ```
212 | $ pip install pytriskel
213 | ```
214 |
215 | ## Contact
216 | - Discord: [Triskel](https://discord.gg/zgBb5VUKKS)
217 |
218 | ## Cite Triskel
219 | ```bibtex
220 | @inproceedings{royer:hal-04996939,
221 | AUTHOR = {Royer, Jack and Tronel, Fr{\'e}d{\'e}ric and Vin{\c c}ont, Ya{\"e}lle},
222 | TITLE = {{Towards Better CFG Layouts}},
223 | BOOKTITLE = {{Workshop on Binary Analysis Research 2025}},
224 | ADDRESS = {San Diego (CA), United States},
225 | MONTH = Feb,
226 | YEAR = {2025},
227 | URL = {https://hal.science/hal-04996939},
228 | DOI = {10.14722/bar.2025.23011},
229 | }
230 | ```
231 |
232 |
--------------------------------------------------------------------------------
/bin/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | if (BUILD_BENCH OR BUILD_IMG OR BUILD_GUI)
2 | find_package(gflags)
3 | endif()
4 |
5 | if(BUILD_BENCH)
6 | message(STATUS "Building triskel-bench")
7 | add_subdirectory(bench)
8 | endif()
9 |
10 | if (BUILD_IMG)
11 | message(STATUS "Building triskel-img")
12 | add_subdirectory(img)
13 | endif()
14 |
15 | if(BUILD_GUI)
16 | message(STATUS "Building triskel-gui")
17 | add_subdirectory(gui)
18 | endif()
19 |
20 | if (BUILD_WASM)
21 | message(STATUS "Building triskel-wasm")
22 | add_subdirectory(wasm)
23 | endif()
24 |
25 |
--------------------------------------------------------------------------------
/bin/bench/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | project(triskel-bench
2 | VERSION 1.0.0
3 | DESCRIPTION "Benchmarking binary for the triskel CFG layout library"
4 | LANGUAGES CXX C
5 | )
6 |
7 | add_executable(triskel-bench main.cpp)
8 |
9 | target_link_libraries(triskel-bench PRIVATE
10 | triskel
11 | fmt::fmt
12 | gflags
13 | )
14 |
15 | if (ENABLE_LINTING)
16 | find_program(CLANG_TIDY NAMES "clang-tidy" REQUIRED)
17 | set_target_properties(triskel-bench PROPERTIES
18 | CXX_CLANG_TIDY ${CLANG_TIDY}
19 | )
20 | endif()
21 |
--------------------------------------------------------------------------------
/bin/bench/README.md:
--------------------------------------------------------------------------------
1 | # triskel-bench
2 |
3 | Lays out CFGs without displaying them. Useful for benchmarking.
4 |
5 | ## Usage
6 |
7 | It can be used on a file, it will lay out each function in the LLVM module and generate a CSV with statistics.
8 |
9 | ```
10 | $ triskel-bench
11 | ```
12 |
13 | It can also be used on a single function.
14 |
15 | ```
16 | $ triskel-bench
17 | ```
--------------------------------------------------------------------------------
/bin/bench/src/table.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | #include
11 | #include
12 |
13 | template
14 | struct Entry {
15 | Entry(std::string name, const T& value, fmt::format_string fmt = "{}")
16 | : name{std::move(name)}, value{value}, fmt{fmt} {}
17 |
18 | std::string name;
19 |
20 | const T& value;
21 |
22 | fmt::format_string fmt;
23 | };
24 |
25 | // NOLINTNEXTLINE(google-build-namespaces)
26 | namespace {
27 |
28 | struct Table {
29 | template
30 | explicit Table(Args... args) {
31 | entries = std::vector>{
32 | {args.name,
33 | fmt::vformat(args.fmt, fmt::make_format_args(args.value))}...};
34 |
35 | column_width = std::ranges::max(
36 | entries | std::ranges::views::transform([](const auto& entry) {
37 | return std::max(entry.first.size(), entry.second.size());
38 | }));
39 |
40 | // For a space on either size
41 | column_width += 2;
42 | }
43 |
44 | auto print_separator() const -> void {
45 | for (size_t i = 0; i < entries.size(); ++i) {
46 | fmt::print("+{:->{}}", "", column_width);
47 | }
48 |
49 | fmt::print("+\n");
50 | }
51 |
52 | template
53 | auto print_content() const -> void {
54 | for (const auto& entry : entries) {
55 | fmt::print("| {:>{}} ", std::get(entry), column_width - 2);
56 | }
57 |
58 | fmt::print("|\n");
59 | }
60 |
61 | auto print() const -> void {
62 | print_separator();
63 | print_content<0>();
64 | print_separator();
65 | print_content<1>();
66 | print_separator();
67 | }
68 |
69 | size_t column_width;
70 |
71 | std::vector> entries;
72 | };
73 |
74 | } // namespace
75 |
76 | template
77 | auto print_table(Args... args) -> void {
78 | const auto table = Table(args...);
79 | table.print();
80 | }
81 |
--------------------------------------------------------------------------------
/bin/gui/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | project(triskel-gui
2 | VERSION 1.0.0
3 | DESCRIPTION "ImGui for the triskel CFG layout library"
4 | LANGUAGES CXX C
5 | )
6 |
7 | add_executable(triskel-gui main.cpp)
8 |
9 | FetchContent_Declare(
10 | LIEF
11 | GIT_REPOSITORY https://github.com/lief-project/LIEF.git
12 | GIT_TAG 7e61aa2e56d67b46a0b055363a4cb4fbe4662ef8 # 0.16.3
13 | FIND_PACKAGE_ARGS
14 | )
15 | FetchContent_MakeAvailable(LIEF)
16 |
17 | target_link_libraries(triskel-gui PRIVATE
18 | triskel
19 | fmt::fmt
20 | gflags
21 | imgui::imgui
22 | imgui::imgui_impl_glfw
23 | imgui::imgui_impl_opengl3
24 | glfw
25 | OpenGL::GL
26 | GLEW::GLEW
27 | LIEF::LIEF
28 | )
29 |
30 | include(FindPkgConfig)
31 | pkg_check_modules(CAPSTONE REQUIRED capstone)
32 | target_include_directories(triskel-gui PRIVATE ${CAPSTONE_INCLUDE_DIRS})
33 | target_link_libraries(triskel-gui PRIVATE ${CAPSTONE_LIBRARIES})
34 |
35 |
36 | add_subdirectory(disas)
37 | add_subdirectory(external)
38 | add_subdirectory(gui)
39 |
40 | add_custom_target(copy_assets
41 | COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_LIST_DIR}/assets ${CMAKE_CURRENT_BINARY_DIR}/assets
42 | )
43 | add_dependencies(triskel-gui copy_assets)
44 | target_compile_definitions(triskel-gui PRIVATE ASSET_PATH="${CMAKE_CURRENT_BINARY_DIR}/assets")
--------------------------------------------------------------------------------
/bin/gui/README.md:
--------------------------------------------------------------------------------
1 | # Triskel GUI
2 |
3 | A sample program using the triskel ImGui widget:
4 |
5 | ```cpp
6 | #include
7 |
8 | imgui_renderer.Begin("##cfg", {42.0F, 10.0F});
9 | layout->render(imgui_renderer);
10 | imgui_renderer.End();
11 | ```
12 |
13 | 
14 |
15 | ## Usage
16 |
17 | ```
18 | $ imgui-gui
19 | ```
20 |
21 | The GUI works with LLVM bytecode (`.ll` and `.bc` files).
22 | There is also limited support for `x64` binaries using a custom _recursive descent_ disassembler.
23 |
24 | In the GUI, functions can be selected on the left.
25 | To modify the canvas viewport
26 | - use the scroll wheel for zoom
27 | - use the right mouse button to pan
28 |
--------------------------------------------------------------------------------
/bin/gui/assets/fonts/Lato-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/triskellib/triskel/4b02ad9e162788f4653a404ef47d1b26400ca62d/bin/gui/assets/fonts/Lato-Bold.ttf
--------------------------------------------------------------------------------
/bin/gui/assets/fonts/Lato-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/triskellib/triskel/4b02ad9e162788f4653a404ef47d1b26400ca62d/bin/gui/assets/fonts/Lato-Light.ttf
--------------------------------------------------------------------------------
/bin/gui/assets/fonts/Roboto-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/triskellib/triskel/4b02ad9e162788f4653a404ef47d1b26400ca62d/bin/gui/assets/fonts/Roboto-Medium.ttf
--------------------------------------------------------------------------------
/bin/gui/assets/img/Triskel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/triskellib/triskel/4b02ad9e162788f4653a404ef47d1b26400ca62d/bin/gui/assets/img/Triskel.png
--------------------------------------------------------------------------------
/bin/gui/disas/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | target_sources(triskel-gui PRIVATE
2 | rec_descent.cpp
3 | )
4 |
--------------------------------------------------------------------------------
/bin/gui/disas/rec_descent.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include