diff --git a/tracing/README.rst b/tracing/README.rst
new file mode 100644
index 0000000000000000000000000000000000000000..d2846efcdf86d5172df83fd678a9ae681d4eb2df
--- /dev/null
+++ b/tracing/README.rst
@@ -0,0 +1,8 @@
+Tracing
+=======
+
+To see what crypto functions are being called with what input run
+
+.. code:: bash
+
+    gdb --batch -x tracing/trace.gdb ./build/test_ratchet | grep "^[- ]" | tr "{}" "[]" | tracing/graph.py
diff --git a/tracing/graph.py b/tracing/graph.py
new file mode 100755
index 0000000000000000000000000000000000000000..ac121aa0e1c5ae3cfada8b4bfa7c359d17df2945
--- /dev/null
+++ b/tracing/graph.py
@@ -0,0 +1,100 @@
+#! /usr/bin/python
+
+import sys
+import yaml
+import array
+
+class Call(object):
+    def __init__(self, call):
+        self.func, = call
+        args = dict(call[self.func])
+        self.output = array.array("B", args.pop("output")).tostring()
+        self.inputs = {
+            name: array.array("B", args[name]).tostring()
+            for name in args
+            if not name.endswith("_length")
+        }
+        self.bind = {}
+
+    def expr(self, stream, indent="  ", level=""):
+        stream.write(self.func + "(\n")
+        for name, value in self.inputs.items():
+            stream.write(level + indent + name + "=")
+            self.bind.get(name, Literal(value)).expr(
+                stream, indent, level + indent
+            )
+            stream.write(",\n")
+        stream.write(level + ")")
+
+
+class Literal(str):
+    def expr(self, stream, indent, level):
+        stream.write("\"" + self.encode("hex") + "\"")
+
+
+class Slice(object):
+    def __init__(self, thing, start, end):
+        self.thing = thing
+        self.start = start
+        self.end = end
+
+    def expr(self, stream, indent="  ", level=""):
+        self.thing.expr(stream, indent, level)
+        stream.write("[%d:%d]" % (self.start, self.end))
+
+
+class Concat(list):
+    def expr(self, stream, indent="  ", level=""):
+        stream.write("concat(\n")
+        for thing in self:
+            stream.write(level + indent)
+            thing.expr(stream, indent, level + indent)
+            stream.write(",\n")
+        stream.write(level + ")")
+
+
+calls = [Call(c) for c in yaml.load(sys.stdin)]
+
+outputs = {}
+
+for call in calls:
+    for i in range(8, len(call.output)):
+        outputs.setdefault(call.output[i - 8: i], []).append(call)
+
+for call in calls:
+    for name, value in call.inputs.items():
+        for bind in outputs.get(value[:8], ()):
+            if value == bind.output:
+                call.bind[name] = bind
+            else:
+                for end in range(len(value), len(bind.output) + 1):
+                    start = end - len(value)
+                    if value == bind.output[start:end]:
+                        call.bind[name] = Slice(bind, start, end)
+        if not name in call.bind:
+            i = 0
+            j = 1
+            k = 0
+            concat = Concat()
+            while i < len(value):
+                for bind in outputs.get(value[i:i+8], ()):
+                    if value[i:].startswith(bind.output):
+                        if k != i:
+                            concat.append(Literal(value[k:i]))
+                        concat.append(bind)
+                        j = len(bind.output)
+                        k = i + j
+                        break
+                i += j
+                j = 1
+            if concat:
+                if k != i:
+                    concat.append(Literal(value[k:i]))
+                call.bind[name] = concat
+
+for call in calls:
+    if call.func.startswith("h"):
+        sys.stdout.write("\"" + call.output.encode("hex") + "\" = ")
+        call.expr(sys.stdout)
+        sys.stdout.write("\n")
+
diff --git a/tracing/trace.gdb b/tracing/trace.gdb
new file mode 100644
index 0000000000000000000000000000000000000000..bdece2e8e7391bcd96539a7dddbbecfb6f7b6228
--- /dev/null
+++ b/tracing/trace.gdb
@@ -0,0 +1,133 @@
+set print pretty off
+set print repeats unlimited
+set print elements unlimited
+set breakpoint pending on
+
+
+break crypto.cpp:273
+commands
+silent
+printf "- hmac_sha256:\n"
+printf "    key_length: %d\n", key_length
+printf "    input_length: %d\n", input_length
+if key_length > 0
+    printf "    key: "
+    output/x *key@key_length
+    printf "\n"
+else
+    printf "    key: {}\n"
+end
+if input_length > 0
+    printf "    input: "
+    output/x *input@input_length
+    printf "\n"
+else
+    printf "    input: {}\n"
+end
+cont
+end
+
+
+break crypto.cpp:280
+commands
+silent
+printf "    output: "
+output/x *output@32
+printf "\n"
+cont
+end
+
+
+break crypto.cpp:307
+commands
+silent
+set $hkdf_output = output
+cont
+end
+
+
+break crypto.cpp:323
+commands
+silent
+printf "- hkdf_sha256:\n"
+printf "    input_length: %d\n", input_length
+printf "    salt_length: %d\n", salt_length
+printf "    info_length: %d\n", info_length
+printf "    output_length: %d\n", output_length
+if input_length > 0
+    printf "    input: "
+    output/x *input@input_length
+    printf "\n"
+else
+    printf "    input: {}\n"
+end
+if salt_length > 0
+    printf "    salt: "
+    output/x *salt@salt_length
+    printf "\n"
+else
+    printf "    salt: {}\n"
+end
+if info_length > 0
+    printf "    info: "
+    output/x *info@info_length
+    printf "\n"
+else
+    printf "    info: {}\n"
+end
+printf "    output: "
+output/x *$hkdf_output@output_length
+printf "\n"
+cont
+end
+
+
+break crypto.cpp:156
+commands
+silent
+printf "- curve25519:\n"
+printf "    public: "
+output/x *their_key.public_key@32
+printf "\n"
+printf "    private: "
+output/x *our_key.private_key@32
+printf "\n"
+printf "    output: "
+output/x *output@32
+printf "\n"
+cont
+end
+
+break crypto.cpp:156
+commands
+silent
+printf "- curve25519:\n"
+printf "    public: "
+output/x *their_key.public_key@32
+printf "\n"
+printf "    private: "
+output/x *our_key.private_key@32
+printf "\n"
+printf "    output: "
+output/x *output@32
+printf "\n"
+cont
+end
+
+break crypto.cpp:147
+commands
+silent
+printf "- curve25519:\n"
+printf "    public: "
+output/x *CURVE25519_BASEPOINT@32
+printf "\n"
+printf "    private: "
+output/x *key_pair.private_key@32
+printf "\n"
+printf "    output: "
+output/x *key_pair.public_key@32
+printf "\n"
+cont
+end
+
+run