The EQATEC Tracer for .NET apps

Quick guide to tracing

The tracer works by injecting tracing code in every function and property in your assemblies. Every time a function is called this piece of code checks to see if the trace is enabled. If so a trace is generated and send to the viewer. The trace contains information on the functions called and a result of ToString() on every parameter.

How to trace your assemblies

You will use the tracer in four steps:

  1. Drop your assemblies somewhere in the window
  2. Start instrumentation to inject tracing code into the assemblies
  3. Run the modified application on your PC or device
  4. View and control your trace from the viewer section

That's it. That is all you need to do. You can try it out now on the demo-app, "Bubbles", or on any full .NET application you have installed.

The next sections will describe these four steps.


Step 1: Drop your assemblies somewhere in the window

Select your application folder and drop it in the window. The .Net assemblies present in the folder structure will be added to the assembly list. If there is any signed assemblies you will prompted to deal with them either by providing a key for resigning or simply by skipping them all together

You deselect any assemblies you do not want to instrument. It will then only be copied to the output folder and used as is.


Step 2: Start instrumentation to inject tracing code into the assemblies

The Instrumentator tab is explained below:

Trace your application

A traced assembly is typically slightly larger than the original and runs slightly slower. The more trace enabled the larger the performance penalty will be. The performance penalty will vary greatly depending on your application structure. Normally you will just trace all of your assembly-files, but sometimes you would like to be more particular - for instance, if

  • your device has no room for that extra code
  • an assembly-file is highly time-critical and cannot stand the extra runtime-overhead


Step 3: Run the modified application on your PC or device

When the instrumentation has finished you simply click on the flash icon to launch your application. If you have several executables you will be prompted to choose which one you want to execute. When the application is launched the view will change to the Viewer tab.

When running on a device the launch of the application will have to be done by hand. Go to the "YourApp (Traced)" folder (you can find the exact path in the instrumentation messages). Copy the contents to the device and launch from the device.


Step 4: View and control your trace from the viewer section

Now we're ready to see some output from the application. Below is the Viewer tab functionality shown

Trace your application

On the left hand side is the Control Tree. This is where you control which members you want to see output from. On the right hand side is the Trace Viewer. This is where the the trace is shown when it has been generated by the application

Control tree

  • The control tree toolbar holds undo and redo buttons for used for control tree actions. It holds a target IP box defaulting to LocalHost. If you need to trace an application running on a device type the device IP and connect. The play button attempts to connect to the target
  • The control tree holds all the assemblies in your application. You can expland the tree down to the individual methods on every type. When you check an item in the tree it enables all sub nodes in the tree. Be carefull when enabling on a assembly level this can generate a lot of output. If your selection seems to generate to much output simply deselect or undo your action.
  • When your at a method level there is a context menu giving you the following options

    Tree context menu

    This enables you to not only enable this particular method, but also to enable its callers five levels up. This is usefull when you are unaware of how exactly a particular method is called.

Trace viewer

  • The toolbar in the Trace viewer section gives you a selection of tools to control the flow information. These are for the most part self explanatory, however some of them needs some explanation. The pause button will pause the traceviewer and no new lines will enter the viewer. This means that trace arriving at the viewer will be dumped and lost. The save button will save all present trace to a text file. The close parameter window button will close all open parameter windows. Parameter windows can be opened by double clicking on a trace line
  • The trace output itself is generated with like so timestamp (threadid) methodname (parametervalue1, ...). Left clicking on a line will bring up additional information in the parameter window below. Double clicking on a line will open a seperate parameter window. Right clicking on a line will bring up the same context menu as in the control tree.

    Trace context menu

    This will enable you to control the trace directly from the trace window itself. This is usefull for disabling trace that is of no interest in your present debugging scenario
  • Below the trace output is the buffer management section.

    Buffer management

    The bar shows you how much trace is currently accumulated in the target application. The time shown is the time difference between the oldest and the newest trace in the buffer. The bar can jump in size in scenarios where there are bursts of trace at longer intervals. If the buffer still holds old trace being send, new trace added will make the bar grow suddenly.
  • The Max allowed delay slider will set the maximum allowed delay in the trace buffer. If the delay is exceeded the buffer will be flushed. Flushing events will be signaled in the trace window with a line describing how many lines where removed. If you generate a lot of trace and you are experiencing flushing events increase the delay. If you don't want old trace to appear in the trace window or have limited space for buffering in your target application decrease the delay
  • If you enable a lot of trace you can encounter scenarios where the tracer is unable to cope with the amounts of data. The trace line queue in the target application is limited to 30000 lines. If this amount is exceeded it will start dumping lines. Every time dumping occurs this will be signaled in the trace output.

Appendix A: Debug boot crashes

Debugging application boot crashes is a normal debugging scenario. As you read previously the tracer have to connected to show trace. This is not possible when your application crashes on boot. This shows how you can still find the reason for the crash using the EQATEC Tracer

  • Instrument your application as usual but do not start it from the instrumentation view.
  • Switch to the viewer tab manually and press the connect button. The following window will appear.

    Waiting for connection

    This means that the viewer is waiting for the application to start and when it does it will connect immediatly.
  • Start your application. Your instrumented application will then detect that the viewer have connected and will block in its first called method (usually Main()) until it has exchanged assembly info. It will then continue to boot and crash
  • The viewer is now in offline mode. This is signaled by the play button in the control tree side is enabled. The tree is however still active. You now enable whatever you need to debug the crash and press play again. The viewer will again wait for the target to start
  • Start the target application again. It will again wait in the first called method to exchange assembly information, but this time it will also exchange info on the function you enabled in offline mode. When it has finished the target application will continue to boot but this time it will trace whatever you enabled hopefully giving you enough information to solve the problem

Known limitations

This is a list of known limitations.

  • Only defined methods are currently traced, not referenced ones. So all the methods that your application itself defines will be traced, but not System.* etc.
  • Only outputs ToString() If there are no ToString() method the type will be the result of the output. You can enhance the output by overriding ToString() in your types.

Contact

The tracer is a work in progress. Your input is most welcome: if you have any problems or suggestions then please let us know.

Visit our forum at http://www.eqatec.com/forum
Send us an email at tools@eqatec.com

If you experience a bug, such as your traced program not working or throwing an exception, then maybe we can help:

  1. First of all, check if there's maybe a newer tracer version available
  2. If not then please report the problem in our forum, or by mail
  3. Next, see if you can reproduce the problem on a smaller scale and send us a source example
  4. Or, submit as much info about the problem as possible; call-stack, types involved etc
  5. Or, submit the offending assembly-files to us
  6. Or, submit your entire offending source code project to us

If you'd like professional assistance in performance-tuning or improving your .NET CF application then don't hesitate to contact us, either. Because after all, doing hardcore embedded programming for clients is what we do for a living here at EQATEC.

Best regards,
the EQATEC tools team