aboutsummaryrefslogtreecommitdiff
path: root/tracing/graph.py
diff options
context:
space:
mode:
authorMark Haines <mark.haines@matrix.org>2015-06-21 18:47:06 +0100
committerMark Haines <mark.haines@matrix.org>2015-06-21 18:47:06 +0100
commitfb980849c4ffc99bca7a2dd5a347e9f0b4b99469 (patch)
treed223e53f304a8fa7dca8df7b8f442af7bd6ff67e /tracing/graph.py
parent0ca3797d2d065e63dc5806ba014bcb742b09c5d7 (diff)
Add gdb script and psuedo-call graph generator python script for tracing calls to crypto primitives
Diffstat (limited to 'tracing/graph.py')
-rwxr-xr-xtracing/graph.py100
1 files changed, 100 insertions, 0 deletions
diff --git a/tracing/graph.py b/tracing/graph.py
new file mode 100755
index 0000000..ac121aa
--- /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")
+