{"id":27082044,"url":"https://github.com/triskellib/triskel","last_synced_at":"2025-04-06T02:38:00.199Z","repository":{"id":278051697,"uuid":"924198662","full_name":"triskellib/triskel","owner":"triskellib","description":"A graphing library for Control Flow Graphs","archived":false,"fork":false,"pushed_at":"2025-03-26T10:02:36.000Z","size":604,"stargazers_count":44,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-26T11:22:37.140Z","etag":null,"topics":["cfg","reverse-engineering","visualization"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/triskellib.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-01-29T15:37:14.000Z","updated_at":"2025-03-26T10:02:40.000Z","dependencies_parsed_at":null,"dependency_job_id":"8bb6df64-a336-4e4a-8f67-f7c3af75da2a","html_url":"https://github.com/triskellib/triskel","commit_stats":null,"previous_names":["triskellib/triskel"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/triskellib%2Ftriskel","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/triskellib%2Ftriskel/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/triskellib%2Ftriskel/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/triskellib%2Ftriskel/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/triskellib","download_url":"https://codeload.github.com/triskellib/triskel/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247426997,"owners_count":20937197,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cfg","reverse-engineering","visualization"],"created_at":"2025-04-06T02:37:59.831Z","updated_at":"2025-04-06T02:38:00.192Z","avatar_url":"https://github.com/triskellib.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n\u003cpicture\u003e\n  \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://github.com/triskellib/triskel/blob/master/.github/assets/triskel_dark.png?raw=true\"\u003e\n  \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"https://github.com/triskellib/triskel/blob/master/.github/assets/triskel_light.png?raw=true\"\u003e\n  \u003cimg width=\"50%\" alt=\"Shows a black logo in light color mode and a white one in dark color mode.\" src=\"https://github.com/triskellib/triskel/blob/master/.github/assets/triskel_light.png?raw=true\"\u003e\n\u003c/picture\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n\u003ca href=\"https://pypi.org/project/pytriskel/\"\u003e\n    \u003cimg alt=\"PyPI - Version\" src=\"https://img.shields.io/pypi/v/pytriskel\"\u003e\n\u003c/a\u003e\n\n\u003ca href=\"https://discord.gg/zgBb5VUKKS\"\u003e\n    \u003cimg alt=\"Discord\" src=\"https://img.shields.io/discord/1341034987343970398\"\u003e\n\u003c/a\u003e\n\u003c/p\u003e\n\n\n\n**Triskel** is a Control Flow Graph (CFG) layout engine. It provides you with\ncoordinates to draw CFGs in your reverse-engineering tools.\n\n- CFG specific layout, emphasizing Single Entry Single Exit Regions\n- Python bindings\n- Export to PNG / SVG (with cairo)\n- DearImgui integration\n- LLVM integration\n\n\n## Quick start\n\n### Python\n\n```\n$ pip install pytriskel\n```\n\n```python\nfrom pytriskel.pytriskel import *\n\nbuilder = make_layout_builder()\n\n# Build the graph\nn1 = builder.make_node(\"Hello\")\nn2 = builder.make_node(\"World\")\nbuilder.make_edge(n1, n2)\n\n# Measure node size using font size\npng_renderer = make_png_renderer()\nbuilder.measure_nodes(png_renderer)\n\n# Export an image\nlayout = builder.build()\nlayout.save(png_renderer, \"out.png\")\n```\n\n### C++\n\n```cpp\n#include \u003ctriskel/triskel.hpp\u003e\n\nint main(void) {\n    auto builder  = triskel::make_layout_builder();\n\n    auto n1 = builder-\u003emake_node(\"Hello\");\n    auto n2 = builder-\u003emake_node(\"World\");\n    builder-\u003emake_edge(n1, n2)\n\n    auto renderer = triskel::make_svg_renderer();\n    builder-\u003emeasure_nodes(renderer)\n    auto layout   = builder-\u003ebuild();\n\n    layout-\u003erender_and_save(*renderer, \"./out.svg\");\n\n    return 1;\n}\n```\n\n## Theory\n\nTriskel is the implementation for the paper [Towards better CFG layouts](https://hal.science/hal-04996939).\n\nThe key idea behind Triskel is to split the CFG into Single Entry Single Exit regions.\nWe are then able to layout each region taking advantage of a divide and conquer approach.\n\n## Walkthrough\n\nInitially we have a directed graph\n\n![Directed graph](.github/assets/graph1_dark.png)\n\nThe 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))\nIn the diagram, the region is in blue. Notice how a single edge enters and exits the blue border.\n\n![SESE region identification](.github/assets/graph2_dark.png)\n\nWe can then split each region out of the graph. At this step we have multiple smaller directed graphs.\nNote that how in the graph of the SESE region, we had to add 2 virtual nodes to represent the entry and exit points.\nIn the other graph, we added an additional node to represent the region (still in blue).\n\n![Splitting the graph](.github/assets/graph3_dark.png)\n\nThe 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)).\nNote how we have to layout the SESE region first in order to know the coordinates of the blue node.\n\n![Divide and conquer](.github/assets/graph4_dark.png)\n\nFinally, we can superimpose the layouts to obtain the final layout.\n\n![Final layout](.github/assets/graph5_dark.png)\n\n## Compilation\n\nTriskel relies on the following dependencies (the provided binaries also have their own dependencies)\n\n- [fmt](https://github.com/fmtlib/fmt)\n\nTriskel can then be compiled with cmake\n\n```\n$ git clone https://github.com/triskeles/triskel\n$ cd triskel\n$ cmake -B build\n$ cmake --build build\n```\n\nYou can then link to Triskel\n\n```cmake\ntarget_link_libraries(foo PRIVATE triskel)\n```\n\n### CMake options\n\nTo compile with all options and external dependencies check the [dockerfile](https://github.com/triskellib/triskel/tree/master/docker/fedora).\n\n#### `ENABLE_LLVM`\n\nAdds [LLVM](https://llvm.org/) integration.\n\nThis also adds `LLVM 19` as a dependency.\n\n#### `ENABLE_IMGUI`\n\nAdds [ImGui](https://github.com/ocornut/imgui) integration, used for making GUIs.\n\nThis adds the following dependencies:\n\n- `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))\n- `glfw3`\n- `OpenGL`\n- `GLEW`\n- `SDL2`\n- `stb_image`\n\n#### `ENABLE_CAIRO`\n\nAdds [Cairo](https://www.cairographics.org/) integration, used for exporting images.\n\n## Binaries\n\nTriskel comes with many example binaries to help illustrate usage.\n\nThese binaries all require an additional dependency:\n\n- [gflags](https://gflags.github.io/gflags/)\n\n### [triskel-bench](https://github.com/triskellib/triskel/tree/master/bin/bench)\n\n\u003e Used for testing and evaluation.\n\nThis binary lays out each function in an LLVM module and outputs a CSV containing performance reviews.\n\nIt can also be used on a single function to analyze the lay out with `perf`.\n\n#### Dependencies\n\nThis binary only requires `triskel` built with `ENABLE_LLVM=ON`.\n\n\n\u003c!-- The evaluation pipeline can be found at [triskel-eval](https://github.com/triskeles/triskel-eval). --\u003e\n\n\n###  [triskel-gui](https://github.com/triskellib/triskel/tree/master/bin/gui)\n\nAn example implementation of a GUI using Dear ImGui.\n\nThis application has a _very limited_ disassembler for x64 binaries.\n\n#### Dependencies\n\nThis binary requires `triskel` built with `ENABLE_LLVM=ON` and `ENABLE_IMGUI=ON`.\n\nIt also needs [LIEF](https://lief.re/) and [Capstone](http://www.capstone-engine.org/) for the disassembler.\n\n###  [triskel-img](https://github.com/triskellib/triskel/tree/master/bin/img)\n\nA binary that generates images for CFGs using cairo.\n\n#### Dependencies\n\nThis binary requires `triskel` built with `ENABLE_LLVM=ON` and `ENABLE_CAIRO=ON`.\n\nIt also requires [`capstone`](http://www.capstone-engine.org/) and [`LIEF`](https://lief.re/)\n\n## Python bindings\n\nYou can download the python bindings using pip:\n\n```\n$ pip install pytriskel\n```\n\n## Contact\n- Discord: [Triskel](https://discord.gg/zgBb5VUKKS)\n\n## Cite Triskel\n```bibtex\n@inproceedings{royer:hal-04996939,\n  AUTHOR = {Royer, Jack and Tronel, Fr{\\'e}d{\\'e}ric and Vin{\\c c}ont, Ya{\\\"e}lle},\n  TITLE = {{Towards Better CFG Layouts}},\n  BOOKTITLE = {{Workshop on Binary Analysis Research 2025}},\n  ADDRESS = {San Diego (CA), United States},\n  MONTH = Feb,\n  YEAR = {2025},\n  URL = {https://hal.science/hal-04996939},\n  DOI = {10.14722/bar.2025.23011},\n}\n```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftriskellib%2Ftriskel","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftriskellib%2Ftriskel","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftriskellib%2Ftriskel/lists"}