7 years agoAdd doc repo as submodule master
Christoph Egger [Mon, 12 Oct 2015 15:41:44 +0000 (17:41 +0200)]
Add doc repo as submodule

7 years agomove doc/ out of the way
Christoph Egger [Mon, 12 Oct 2015 15:46:55 +0000 (17:46 +0200)]
move doc/ out of the way

7 years agoWrap long lines
Christoph Egger [Mon, 12 Oct 2015 06:53:59 +0000 (08:53 +0200)]
Wrap long lines

7 years agoadd InformationManager::getEntryAddress
Christoph Egger [Mon, 12 Oct 2015 06:52:26 +0000 (08:52 +0200)]
add InformationManager::getEntryAddress

wrapps the orresponding Disassembler interface and thereby consistently
allows accessing all information via the InformationManager class. The
sole Interface-responsibility of the Disassembler is now to start work

7 years agoAdd comments
Christoph Egger [Mon, 12 Oct 2015 06:52:05 +0000 (08:52 +0200)]
Add comments

7 years agoWrap long lines
Christoph Egger [Mon, 12 Oct 2015 06:18:39 +0000 (08:18 +0200)]
Wrap long lines

7 years agoRemove unused has* from InformationManager
Christoph Egger [Mon, 12 Oct 2015 06:16:39 +0000 (08:16 +0200)]
Remove unused has* from InformationManager

The only used variant (hasFunction) is used by the disassembler to
determine whether to fall back to unsafe heuristics for finding the
entry. It is not really obvious why such a thing would ever come up for
one of the other types.

7 years agoTemp-fix tests
Christoph Egger [Tue, 2 Jun 2015 21:59:42 +0000 (23:59 +0200)]
Temp-fix tests

We should probably wait for the disassembler to work through the
binary before trying to retrieve the functions. Then however we can't
really decide whether the disassembler failed to find the function or
is just slow.

7 years agoOnly emit resetEvent if binary was succesfully loaded
Christoph Egger [Tue, 2 Jun 2015 21:31:53 +0000 (23:31 +0200)]
Only emit resetEvent if binary was succesfully loaded

7 years agoSilence compiler warnings
Christoph Egger [Tue, 2 Jun 2015 21:23:00 +0000 (23:23 +0200)]
Silence compiler warnings

7 years agoRun the disassembler in it's own thread
Christoph Egger [Tue, 2 Jun 2015 21:16:06 +0000 (23:16 +0200)]
Run the disassembler in it's own thread

Makes the gui responsive while the disassembler is working. Would also
allow for severall worker threads in the disassembler in the future --
and more cool stuff!

7 years agoPass NewFunctionEvents as objects, not pointers
Christoph Egger [Tue, 2 Jun 2015 21:15:15 +0000 (23:15 +0200)]
Pass NewFunctionEvents as objects, not pointers

The current assumption -- emit will only return once all signal
handlers are done -- is false when cross-thread signals
happen. Therefore we can't assume the stack-allocated event is alive
long enough to just pass pointers. We're copying that object now which
should be pretty small and don't get any memory leaks or lifeness

7 years agoRegister types for cross-thread signals
Christoph Egger [Tue, 2 Jun 2015 21:12:16 +0000 (23:12 +0200)]
Register types for cross-thread signals

7 years agoMake LogDock and LogDockAppender communicate by signals
Christoph Egger [Tue, 2 Jun 2015 21:11:18 +0000 (23:11 +0200)]
Make LogDock and LogDockAppender communicate by signals

This way the Appender can work in a different thread from the gui dock
without causing problems. Also we no longer need to make the Appender
a friend of the gui dock and instead make the dock handle it's own

7 years agoMake requestNewFunction pass a signal
Christoph Egger [Tue, 2 Jun 2015 19:31:28 +0000 (21:31 +0200)]
Make requestNewFunction pass a signal

With the Disassembler being assigned to a different thread soon, this
should allow the gui to stay alive while the disassembler is busy

7 years agoActually set frida version
Christoph Egger [Tue, 2 Jun 2015 19:18:41 +0000 (21:18 +0200)]
Actually set frida version

7 years agoAdd freebsd names for llvm-config
Christoph Egger [Tue, 2 Jun 2015 18:50:42 +0000 (20:50 +0200)]
Add freebsd names for llvm-config

Thanks to Ed Maste for the report!

7 years agoReenable Qt Signal keywords
Christoph Egger [Wed, 27 May 2015 11:47:41 +0000 (13:47 +0200)]
Reenable Qt Signal keywords

As we're not using any boost signals any more no need to hide the
special keywords.

7 years agoCleanup documentation
Christoph Egger [Tue, 26 May 2015 19:51:53 +0000 (21:51 +0200)]
Cleanup documentation

7 years agoproperly terminate guile thread v0.2
Christoph Egger [Tue, 26 May 2015 19:23:49 +0000 (21:23 +0200)]
properly terminate guile thread

7 years agoCreate a Settings object in fridatest as well
Christoph Egger [Tue, 26 May 2015 19:23:25 +0000 (21:23 +0200)]
Create a Settings object in fridatest as well

Otherwise it just segfaults!

7 years agoAlways keep log scrolled to the bottom
Christoph Egger [Tue, 26 May 2015 19:23:00 +0000 (21:23 +0200)]
Always keep log scrolled to the bottom

7 years agoAlwas make the first BasicBlock visible
Christoph Egger [Tue, 26 May 2015 18:42:37 +0000 (20:42 +0200)]
Alwas make the first BasicBlock visible

7 years agoFix redraw bug -- call prepareGeometryChange()
Christoph Egger [Tue, 26 May 2015 18:38:47 +0000 (20:38 +0200)]
Fix redraw bug -- call prepareGeometryChange()

"If you want to change the item's bounding rectangle, you must first
call prepareGeometryChange()." -- we are now doing so

7 years agoRemove adjustSize() hack -- doesn't seem to be necessary any more
Christoph Egger [Tue, 26 May 2015 16:06:59 +0000 (18:06 +0200)]
Remove adjustSize() hack -- doesn't seem to be necessary any more

7 years agoin populateWidget create new TextDocument and attach it at the end
Christoph Egger [Tue, 26 May 2015 16:04:24 +0000 (18:04 +0200)]
in populateWidget create new TextDocument and attach it at the end

This is a *huge* performance improvement. Instead of using the
QTextDocument already attached to the QGraphicsTextItem, we create a
new QTextDocument and fill it. Only at the end of populateWidget() we
attach it to the QGraphicsTextItem. This way it will only be layouted
once and not per insert (three times per instruction).

7 years agoMake signals from geiser work
Christoph Egger [Tue, 26 May 2015 13:48:21 +0000 (15:48 +0200)]
Make signals from geiser work

Move geiser to a proper QThread instead of a guile-only thread. This
way it can properly send/receive signals. Also for some obscure reason
the QVector<int> hack is needed for things to work

Closes T24

7 years agoMove to Qt Signal/Slots
Christoph Egger [Mon, 25 May 2015 13:21:38 +0000 (15:21 +0200)]
Move to Qt Signal/Slots

It's actually fun! And was less pain than expected.
Seems receiving commands from geiser is still kind-of broken but we'll

Ref T24

7 years agoLazy layout CFGs
Christoph Egger [Mon, 25 May 2015 11:37:26 +0000 (13:37 +0200)]
Lazy layout CFGs

Wait for the Widget to actually be shown before starting to
layout. Good candidate for a background-worker-thread later!

7 years agoMultiply stepsize by 3
Christoph Egger [Mon, 25 May 2015 11:18:04 +0000 (13:18 +0200)]
Multiply stepsize by 3

As profiling show rather some time spent in that are, cut down number
of iterations to one third. Shouldn't impact quality at all

7 years agoAdd comments on how the graph is drawn
Christoph Egger [Mon, 25 May 2015 11:17:05 +0000 (13:17 +0200)]
Add comments on how the graph is drawn

7 years agoAdd basic Backlog to ScriptingDock
Christoph Egger [Mon, 25 May 2015 09:02:09 +0000 (11:02 +0200)]
Add basic Backlog to ScriptingDock

7 years agoDo proper errorhandling for fileload
Christoph Egger [Mon, 25 May 2015 05:37:00 +0000 (07:37 +0200)]
Do proper errorhandling for fileload

Sharing code with evaluation of strings, now proper error handling is
done and frida won't crash if an invalid scheme file is loaded.

7 years agoUse protected domainsocket for geiser
Christoph Egger [Mon, 25 May 2015 05:23:35 +0000 (07:23 +0200)]
Use protected domainsocket for geiser

Instead of opening a TCP port on localhost, use a UNIX domainsocket to
listen for connections. This way frida is properly protected against
other users on the same system.

7 years agoAdd settings Class
Christoph Egger [Mon, 25 May 2015 05:20:42 +0000 (07:20 +0200)]
Add settings Class

Singleton class that keeps track of settings. First thing it has a
RuntimeDirectory to place things like sockets into.

7 years agoFix formating of comments. Should not start with a linebreak
Christoph Egger [Mon, 25 May 2015 04:28:32 +0000 (06:28 +0200)]
Fix formating of comments. Should not start with a linebreak

When displaying a comment, an additional linebreak was inserted right
after the ";;" mark and before the first comment. This linebreak is
removed here.

7 years agoAnnotate function address
Christoph Egger [Mon, 25 May 2015 04:14:06 +0000 (06:14 +0200)]
Annotate function address

When the user manually annotates an address from the context menu, add
a special placeholder comment to put the function name there.

7 years agoSome comments
Christoph Egger [Mon, 25 May 2015 04:12:36 +0000 (06:12 +0200)]
Some comments

7 years agoAdd missing Include-Guards to dialogs
Christoph Egger [Sun, 24 May 2015 23:54:16 +0000 (01:54 +0200)]
Add missing Include-Guards to dialogs

7 years agoMove qt.hxx up one directory
Christoph Egger [Sun, 24 May 2015 23:55:52 +0000 (01:55 +0200)]
Move qt.hxx up one directory

We're using Qt now a lot more than only for GUI purposes. Reflect
reality in location of qt.hxx headerfile

Ref T24

7 years agoScript files are not actually binaries but scripts!
Christoph Egger [Sun, 24 May 2015 12:27:55 +0000 (14:27 +0200)]
Script files are not actually binaries but scripts!

7 years agoadd logging to the Guile module
Christoph Egger [Sun, 24 May 2015 12:26:24 +0000 (14:26 +0200)]
add logging to the Guile module

7 years agoFix segfault when loading a sceme file
Christoph Egger [Sun, 24 May 2015 12:26:09 +0000 (14:26 +0200)]
Fix segfault when loading a sceme file

7 years agoColor logmessages according to severity
Christoph Egger [Tue, 19 May 2015 17:55:35 +0000 (19:55 +0200)]
Color logmessages according to severity

Closes T12

7 years agoHighlight jumptargets
Christoph Egger [Tue, 19 May 2015 17:02:13 +0000 (19:02 +0200)]
Highlight jumptargets

 + Properly handle jmps at the right place in the gui
 + Try to center on the relevant BasicBlock
 + Change color of the BasicBlock

Centering needs us to increase the actual Scene size as well so we can
also center on widgets at the rim of the scene. Bug should only be
closed once this is implemented

Ref T31

7 years agoDon't create empty blocks for unconditional jumps out of the text segment
Christoph Egger [Tue, 19 May 2015 15:57:43 +0000 (17:57 +0200)]
Don't create empty blocks for unconditional jumps out of the text segment

These are most likely optimized tail-calls and should be handles as

Ref T34

7 years agoRemove deprecated printEachInstruction function
Christoph Egger [Sat, 16 May 2015 13:59:50 +0000 (15:59 +0200)]
Remove deprecated printEachInstruction function

replaced by getInstructions, no users left

7 years agoMove each widget exactly once per layout iteration
Christoph Egger [Sat, 16 May 2015 12:05:10 +0000 (14:05 +0200)]
Move each widget exactly once per layout iteration

BasicBlocks with many incoming edges were pushed downwards faster than
those with less incoming edges resulting in unnatural graph layouting.

Now we move each widget exactly once (move the widget on collissions,
not its successors) keeping the basic ordering by addresses.

The result is not perfect -- there's quite some room for further
improvements though!

Ref 5

7 years agoAllow Drag-Scrolling in CFG-View
Christoph Egger [Fri, 15 May 2015 23:32:37 +0000 (01:32 +0200)]
Allow Drag-Scrolling in CFG-View

One can now drag the viewpoint on the CFGScene around with the mouse
-- press left mousebutton and drag the canvas.

Closes T32

7 years agoHandle cancel on InterpreterMenu
Christoph Egger [Fri, 15 May 2015 23:25:20 +0000 (01:25 +0200)]
Handle cancel on InterpreterMenu

getOpenFileName() will return a Null-QString on cancel. Feeding that
filename to guile will die (reasonably) with an exception. Instead, we
now just exit from the handler in the gui if the Null-QString is

Closes T33

7 years agoAdapt Licensing v0.1
Christoph Egger [Tue, 12 May 2015 11:31:12 +0000 (13:31 +0200)]
Adapt Licensing

7 years agoOfficially support LLVM-3.6
Christoph Egger [Sat, 25 Apr 2015 16:47:32 +0000 (18:47 +0200)]
Officially support LLVM-3.6

LLVM-3.6 now passes all the tests and seems to work. Therefore removing
the loud warning message.

7 years agoSome code cleanup
Christoph Egger [Sat, 25 Apr 2015 16:42:18 +0000 (18:42 +0200)]
Some code cleanup

7 years agoFix logic flaw preventing us from handling symbols in the llvm-3.6 path
Christoph Egger [Sat, 25 Apr 2015 16:42:01 +0000 (18:42 +0200)]
Fix logic flaw preventing us from handling symbols in the llvm-3.6 path

7 years agoCreate helper to generate disassembler tests
Christoph Egger [Wed, 1 Apr 2015 15:41:26 +0000 (17:41 +0200)]
Create helper to generate disassembler tests

7 years agoAdd armel testcase
Christoph Egger [Wed, 1 Apr 2015 14:53:50 +0000 (16:53 +0200)]
Add armel testcase

This one doesn't do thumb so it's easy

7 years agoAdd (failing) mipsel test
Christoph Egger [Thu, 26 Mar 2015 16:59:46 +0000 (17:59 +0100)]
Add (failing) mipsel test

7 years agoComments in BasicBlockWidget for the magic
Christoph Egger [Thu, 26 Mar 2015 16:47:10 +0000 (17:47 +0100)]
Comments in BasicBlockWidget for the magic

7 years agoProperly fail if no appropriate Disassembler can be constructed
Christoph Egger [Thu, 26 Mar 2015 16:45:34 +0000 (17:45 +0100)]
Properly fail if no appropriate Disassembler can be constructed

Currently, for mipsel there is no InstructionAnalysis available for some
reason. frida gives now a errormessage and survives instead of just

7 years agoSet Loglevel to ERROR for testcases
Christoph Egger [Thu, 26 Mar 2015 16:44:56 +0000 (17:44 +0100)]
Set Loglevel to ERROR for testcases

Everything lower is just noise for this purpose

7 years agoAdd testcases for disassembler
Christoph Egger [Thu, 26 Mar 2015 16:43:24 +0000 (17:43 +0100)]
Add testcases for disassembler

Testing basic functionality of the LLVM-based disassembler on amd64/elf
and amd64/MachO. More tests will follow as soon as I get reasonable test
binaries, we should at least also cover PE and arm (maybe ppc, mips, ..)

7 years agoProperly add StreamReader class
Christoph Egger [Thu, 26 Mar 2015 13:57:52 +0000 (14:57 +0100)]
Properly add StreamReader class

It already comes in via the inclusion of BasicBlock but Function needs
it on it's own

7 years agoPreliminary LLVM-3.6 support
Christoph Egger [Wed, 25 Mar 2015 17:13:20 +0000 (18:13 +0100)]
Preliminary LLVM-3.6 support

Allows llvm-3.6 in cmake and does compile with 3.6. However it
does *not* work! It will segfault right away. One of the suspects is
different base for addresses used in llvm's getInstruction() and family.

7 years agoAlso allow
Christoph Egger [Wed, 25 Mar 2015 14:26:10 +0000 (15:26 +0100)]
Also allow

Should work if it's already the qt5 version and even if no qt5 version
is available

7 years agoDisable buildModule
Christoph Egger [Wed, 25 Mar 2015 13:55:38 +0000 (14:55 +0100)]
Disable buildModule

seems unneeded for everything frida does and it makes opening arm files
die in an endless loop

7 years agoSet minimum width to prevent endless loop on empty block
Christoph Egger [Wed, 25 Mar 2015 13:54:32 +0000 (14:54 +0100)]
Set minimum width to prevent endless loop on empty block

Fixes an infinite loop when looking at armhf binaries. armhf doesn't
look fully functional but actually does *something*

7 years agoHandle opening of invalid FrIDa file
Christoph Egger [Wed, 25 Mar 2015 13:05:12 +0000 (14:05 +0100)]
Handle opening of invalid FrIDa file

7 years agoProperly handle abort of open dialog
Christoph Egger [Wed, 25 Mar 2015 13:04:21 +0000 (14:04 +0100)]
Properly handle abort of open dialog

7 years agoProper error handling when opening binary
Christoph Egger [Wed, 25 Mar 2015 12:40:51 +0000 (13:40 +0100)]
Proper error handling when opening binary

Fail properly when the supplied file is not a recognized binary

Closes T25

7 years agoFix stupid Qt adjustSize() behavior
Christoph Egger [Tue, 24 Mar 2015 17:27:07 +0000 (18:27 +0100)]
Fix stupid Qt adjustSize() behavior

7 years agoFix last commit
Christoph Egger [Tue, 24 Mar 2015 15:58:37 +0000 (16:58 +0100)]
Fix last commit

Test after doing fancy rewrite foo!

7 years ago(De)serialization of Comments
Christoph Egger [Tue, 24 Mar 2015 15:45:27 +0000 (16:45 +0100)]
(De)serialization of Comments

serialization and deserialization of global comments. Local comments
need to go within the function and are not yet implemented. Also
includes several tests

7 years agoUse QString::arg to construct testcase filenames
Christoph Egger [Tue, 24 Mar 2015 15:31:58 +0000 (16:31 +0100)]
Use QString::arg to construct testcase filenames

7 years agoSave dynamic attribute of functions
Christoph Egger [Fri, 20 Mar 2015 15:25:08 +0000 (16:25 +0100)]
Save dynamic attribute of functions

7 years agoMake GUI Widget move Comments through the backend properly
Christoph Egger [Fri, 20 Mar 2015 14:29:56 +0000 (15:29 +0100)]
Make GUI Widget move Comments through the backend properly

7 years agoBump Cmake compat version
Christoph Egger [Fri, 20 Mar 2015 12:51:56 +0000 (13:51 +0100)]
Bump Cmake compat version

Cmake before 3.0 failed to properly build out-of-tree with SWIG as it
tries to write the generated wrapper to a non-existent directory in the
build folder

7 years agoDon't save the function we're not using
Christoph Egger [Fri, 20 Mar 2015 12:51:31 +0000 (13:51 +0100)]
Don't save the function we're not using

Silences unused variable compiler warnung

7 years agoRemove whitespace around printed instruction
Christoph Egger [Fri, 20 Mar 2015 12:50:28 +0000 (13:50 +0100)]
Remove whitespace around printed instruction

Also fixes display of calls where the whole string was replaced by the
called function name instead of just the address

7 years agoImplement InformationManager / Comment and ChangeCommentEvent
Christoph Egger [Fri, 20 Mar 2015 11:55:09 +0000 (12:55 +0100)]
Implement InformationManager / Comment and ChangeCommentEvent

Comments can now be passed through the InformationManager who will
properly emit events

7 years agoChange from list to vector
Christoph Egger [Fri, 20 Mar 2015 11:46:55 +0000 (12:46 +0100)]
Change from list to vector

We want to index into that array so a vector is the better data structure

7 years agoRework API for getting at instructions
Christoph Egger [Thu, 19 Mar 2015 16:56:49 +0000 (17:56 +0100)]
Rework API for getting at instructions

Now we don't hand a callback to the Disassembler, instead we just get a
list of Instruction objects and use that

7 years agoInclude pointer to changed function in RenameFunctionEvent
Christoph Egger [Thu, 19 Mar 2015 17:01:28 +0000 (18:01 +0100)]
Include pointer to changed function in RenameFunctionEvent

7 years agoRemove unnecessary include for <string>
Christoph Egger [Thu, 19 Mar 2015 14:08:33 +0000 (15:08 +0100)]
Remove unnecessary include for <string>

7 years agoAllow setting loglevel from commandline
Christoph Egger [Thu, 19 Mar 2015 13:58:44 +0000 (14:58 +0100)]
Allow setting loglevel from commandline

7 years agoFix SWIG generation for maps
Christoph Egger [Thu, 19 Mar 2015 11:32:23 +0000 (12:32 +0100)]
Fix SWIG generation for maps

still, we can't do anything with the resulting iterators untill the
%template stuff works

7 years agoInstall the guile-frida-bindings into system library path
Christoph Egger [Wed, 18 Mar 2015 18:31:55 +0000 (19:31 +0100)]
Install the guile-frida-bindings into system library path

Allows using only name in scm_load_module -- can be overwritten for
testing and works with the final binary. Would be even better if we
could hide the module in a private directory but I haven't found a nice
way so far

7 years agoProperly allow plugins to load for testing
Christoph Egger [Wed, 18 Mar 2015 16:57:29 +0000 (17:57 +0100)]
Properly allow plugins to load for testing

Loads stuff from the cmake binary directory for testing -- so tests use
the newly built plugins and not some old installed ones (or fail if none

7 years agoAdd new files missing from previous few commits
Christoph Egger [Wed, 18 Mar 2015 13:59:14 +0000 (14:59 +0100)]
Add new files missing from previous few commits

7 years agoBuild working `make install` target
Christoph Egger [Mon, 16 Mar 2015 16:34:13 +0000 (17:34 +0100)]
Build working `make install` target

Should install the frida binary and the libraries into appropriate
places using the Cmake GNUInstallDirs module. Included is some cleanup
in the guile module.

7 years agoRestructure InformationManager
Christoph Egger [Mon, 16 Mar 2015 15:40:18 +0000 (16:40 +0100)]
Restructure InformationManager

  - Signals now all use Event objects to communicate information and all
    share a common sane interface
  - Organize signals consistently and grup by signal name
  - Dynamic and local functions are now handled almost the same
  - Changes all over the place to fix users for these changes
  - proper iterator access for the maps so one can actually iterate over
    all functions (for example a script)
  - ignore these iterators where they would be most usefuill (scripting)
    untill I figure out how to make SWIG compile them properly

7 years agoBasic MachO Support
Christoph Egger [Fri, 13 Mar 2015 13:51:29 +0000 (14:51 +0100)]
Basic MachO Support

Currently has no way to find the Entrypoint. Doesn't seem to be too easy
-- we probably need to get it out of the cpu_thread_state struct from
the thread_command in the MachO header.

7 years agoMore logging in LLVMDisassembler
Christoph Egger [Fri, 13 Mar 2015 13:08:36 +0000 (14:08 +0100)]
More logging in LLVMDisassembler

7 years ago[BasicBlockWidget] Adjust inner widget size before drawing
Christoph Egger [Thu, 12 Mar 2015 15:46:00 +0000 (16:46 +0100)]
[BasicBlockWidget] Adjust inner widget size before drawing

Adjust size of the innner QGraphicsTextItem before getting it's size for
drawing the outer parts. That way the BasicBlockWidget always has the
correct size matching it's content

Closes: T20
7 years agoMove the interpreters to the core InformationManager
Christoph Egger [Thu, 12 Mar 2015 12:54:15 +0000 (13:54 +0100)]
Move the interpreters to the core InformationManager

7 years agoComplete accessors for InformationManager managed objects
Christoph Egger [Thu, 12 Mar 2015 12:45:41 +0000 (13:45 +0100)]
Complete accessors for InformationManager managed objects

7 years agoRemove unnecessary Interpreter.cxx
Christoph Egger [Wed, 11 Mar 2015 16:08:45 +0000 (17:08 +0100)]
Remove unnecessary Interpreter.cxx

Should make things build again

7 years agoUser proper hirarchial names for loggers
Christoph Egger [Wed, 11 Mar 2015 16:08:10 +0000 (17:08 +0100)]
User proper hirarchial names for loggers

7 years agoActually build Dockstuff
Christoph Egger [Wed, 11 Mar 2015 16:07:16 +0000 (17:07 +0100)]
Actually build Dockstuff

7 years agoAdd log widget to lower dock
Christoph Egger [Wed, 11 Mar 2015 15:47:05 +0000 (16:47 +0100)]
Add log widget to lower dock

Make the lower dock container agnostic the former ScriptingDock now is
just taking care of the content inside one of the tabs and the FridaDock
is managing the Dock and TabWidget stuff.

Add a Logging Tab that outputs messages from the logging system for
inspection. Could well be improved (T12 T13 T14).

Closes T11

7 years agoCleanup
Christoph Egger [Wed, 11 Mar 2015 13:33:20 +0000 (14:33 +0100)]