diff --git a/tests/system/tools/findUnusedObjects.py b/tests/system/tools/findUnusedObjects.py
index a032960299e8eb54701e763d29a5b0d876424ae0..dfa8d283331834b4e8f7f5c7654a79e271244741 100755
--- a/tests/system/tools/findUnusedObjects.py
+++ b/tests/system/tools/findUnusedObjects.py
@@ -4,6 +4,8 @@ import os
 import sys
 import tokenize
 from optparse import OptionParser
+from toolfunctions import checkDirectory
+from toolfunctions import getFileContent
 
 objMap = None
 
@@ -31,24 +33,6 @@ def parseCommandLine():
     onlyRemovable = options.onlyRemovable
     fileType = options.fileType
 
-def checkDirectory():
-    global directory, objMap
-    if not os.path.exists(directory):
-        print "Given path '%s' does not exist" % directory
-        sys.exit(1)
-    objMap = os.path.join(directory, "objects.map")
-    if not os.path.exists(objMap):
-        print "Given path '%s' does not contain an objects.map file" % directory
-        sys.exit(1)
-
-def getFileContent(filePath):
-    if os.path.isfile(filePath):
-        f = open(filePath, "r")
-        data = f.read()
-        f.close()
-        return data
-    return ""
-
 def collectObjects():
     global objMap
     data = getFileContent(objMap)
@@ -99,8 +83,8 @@ def printResult():
     return None
 
 def main():
-    global useCounts
-    checkDirectory()
+    global useCounts, objMap
+    objMap = checkDirectory(directory)
     useCounts = dict.fromkeys(collectObjects(), 0)
     findUsages()
     atLeastOneRemovable = printResult()
diff --git a/tests/system/tools/objectsToTable.py b/tests/system/tools/objectsToTable.py
new file mode 100755
index 0000000000000000000000000000000000000000..541a4851f750a69e7447fd90841c7a183e3323a7
--- /dev/null
+++ b/tests/system/tools/objectsToTable.py
@@ -0,0 +1,68 @@
+#!/usr/bin/env python
+
+import os
+import sys
+from optparse import OptionParser
+from toolfunctions import checkDirectory
+from toolfunctions import getFileContent
+
+def parseCommandLine():
+    global directory, tsv
+    parser = OptionParser("\n%prog [OPTIONS] [DIRECTORY]")
+    parser.add_option("-t", "--tab-separated", dest="tsv",
+                      action="store_true", default=False,
+                      help="write a tab-separated table")
+    (options, args) = parser.parse_args()
+    if len(args) == 0:
+        directory = os.path.abspath(".")
+    elif len(args) == 1:
+        directory = os.path.abspath(args[0])
+    else:
+        print "\nERROR: Too many arguments\n"
+        parser.print_help()
+        sys.exit(1)
+    tsv = options.tsv
+
+def readProperties(line):
+    def readOneProperty(rawProperties):
+        name, rawProperties = rawProperties.split("=", 1)
+        value, rawProperties = rawProperties.split("'", 2)[1:3]
+        # we want something human-readable so I think
+        # we can live with some imprecision
+        return name.strip(" ~?"), value, rawProperties
+
+    objectName, rawProperties = line.split("\t")
+    rawProperties = rawProperties.strip("{}")
+    properties = {}
+    while len(rawProperties) > 0:
+        name, value, rawProperties = readOneProperty(rawProperties)
+        properties[name] = value
+    return objectName, properties
+
+def main():
+    global directory, tsv
+    objMap = checkDirectory(directory)
+    objects = dict(map(readProperties, getFileContent(objMap).splitlines()))
+
+    # Which properties have been used at least once?
+    eachObjectsProperties = [set(properties.keys()) for properties in objects.values()]
+    usedProperties = list(reduce(lambda x,y: x | y, eachObjectsProperties))
+
+    if tsv:
+        print "\t".join(["Squish internal name"] + usedProperties)
+        for name, properties in objects.items():
+            values = [name] + map(lambda x: properties.setdefault(x, ""), usedProperties)
+            print "\t".join(values)
+    else:
+        maxPropertyLength = max(map(len, usedProperties))
+        for name, properties in objects.items():
+            print "Squish internal name: %s" % name
+            print "Properties:"
+            for key, val in properties.items():
+                print "%s: %s" % (key.rjust(maxPropertyLength + 4), val)
+            print
+    return 0
+
+if __name__ == '__main__':
+    parseCommandLine()
+    sys.exit(main())
diff --git a/tests/system/tools/toolfunctions.py b/tests/system/tools/toolfunctions.py
new file mode 100644
index 0000000000000000000000000000000000000000..3f78454d7c3875969cb0de53608c389beb5e6341
--- /dev/null
+++ b/tests/system/tools/toolfunctions.py
@@ -0,0 +1,22 @@
+#!/usr/bin/env python
+
+import os
+import sys
+
+def checkDirectory(directory):
+    if not os.path.exists(directory):
+        print "Given path '%s' does not exist" % directory
+        sys.exit(1)
+    objMap = os.path.join(directory, "objects.map")
+    if not os.path.exists(objMap):
+        print "Given path '%s' does not contain an objects.map file" % directory
+        sys.exit(1)
+    return objMap
+
+def getFileContent(filePath):
+    if os.path.isfile(filePath):
+        f = open(filePath, "r")
+        data = f.read()
+        f.close()
+        return data
+    return ""