Skip to content

Triskel

Layouts for Control Flow Graphs

Download plugins:

Theory

Triskel's layout algorithm is based on a divide and conquer approach using SESE regions.

The graph is split into it's SESE regions, then each region is laid out using Sugiyama Layered graph drawing.

This approach yields graphs with significantly less edge crossings and clearer layouts.

These results were presented at the Workshop on Binary Analysis Research 2025 (paper, presentation).

A flow graph split into SESE regions

More theory


Screenshots


Using the API

Triskel includes an easy to use API for drawing flow graphs in your applications.

It's available for:

#include <triskel/triskel.hpp>

int main(void) {
    auto builder  = triskel::make_layout_builder();

    const auto n1 = builder->make_node("Hello");
    const auto n2 = builder->make_node("World");
    builder->make_edge(n1, n2)

    auto renderer = triskel::make_svg_renderer();
    builder->measure_nodes(renderer)
    const auto layout   = builder->build();

    layout->render_and_save(*renderer, "./out.svg");

    return 0;
}
from pytriskel.pytriskel import *

builder = make_layout_builder()

# Build the graph
n1 = builder.make_node("Hello")
n2 = builder.make_node("World")
builder.make_edge(n1, n2)

# Measure node size using font size
png_renderer = make_png_renderer()
builder.measure_nodes(png_renderer)

# Export an image
layout = builder.build()
layout.save(png_renderer, "out.png")
import jtriskel.*;

public class Main {
    static {
        System.loadLibrary("jtriskel");
    }

    public static void main(String[] args) {
        try {
            LayoutBuilder builder = jtriskel.make_layout_builder();
            ExportingRenderer png_renderer = jtriskel.make_png_renderer();

            long n1 = builder.make_node("Hello");
            long n2 = builder.make_node("World");

            long e = builder.make_edge(n1, n2);

            builder.measure_nodes(png_renderer);
            CFGLayout layout = builder.build();
            builder.delete();

            layout.render_and_save_s(png_renderer, "./out.png");
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}

API


Get in touch

Join our discord