-
Notifications
You must be signed in to change notification settings - Fork 1
Debugging Strategies
It's almost universally useful to isolate the bug to the smallest possible case. Try to determine which classes or methods in the subject program are at issue, and create a program containing only them. This will eliminate other potential bugs, improve iteration speed, and allow you to create a test case to verify the correctness of the fix.
- First make sure the bug reporter has followed the steps found on the Reporting a Bug page, referring them to that page if necessary.
- Second, determine if the bug occurs during rewriting or program execution. You can tell this by adding
--save-program
as a command line argument. If the program cannot be successfully rewritten the bug is a rewriting bug, otherwise it's a bug that occurs during execution. * Rewriting bugs will give you an exception trace, see if any information in the exception is useful for debugging. It's helpful to look at theInnerException
property from within Visual Studio's debugger. Bugs of this type probably will be fixed in theILRewriter.cs
file. * For bugs that occur during execution try first verifying the rewritten program. This can be accomplished from the Visual Studio Command Line tools window. Typepeverify [executable-name]
If there are any errors they may reveal what the problem is. Bugs of this type will probably be fixed in theILRewriter.cs
file. - If the program passes the IL verifier but produces invalid output determine what about the output is invalid. Running the .dtrace through Daikon will usually produce useful error messages. See which line is causing the problems, and which variable is being instrumented at that line. Set conditional breakpoints in the
VisitVariable
method inVariableVisitor.cs
orPrintVariable
method inDeclarationPrinter.cs
to get you to break at the time in the code when the bug is occurring.
-
Converting between CCI Metadata types, Assembly Qualified Names, and .NET types is a historically error prone area.
- First, determine what the assembly qualified name of the type should be. This can be done by setting a breakpoint in the source program where a variable of the relevant type is in scope, suppose it's name val.
- Run the source program outside of Celeriac, and when you get to the breakpoint determine
val.GetType().AssemblyQualifiedName
, remember this. - Then set a breakpoint in the
ILRewriter
code that callsTypeManager.ConvertCCITypeToAssemblyQualifiedName()
. There are many callsites, each corresponding to a different variable case. Step through and see if the properAssemblyQualifiedName
is being produced. - If the proper
AssemblyQualifiedName
is being produced then you must check that it is resolved properly when the rewritten program is running. Set a conditional breakpoint in theVisitVariable
method with the name of the variable used from the first step. Watch as theTypeManager.ConvertAssemblyQualifiedNameToType
proceeds, which should point you in the direction of fixing the resolution error.
-
A
StackOverflowException
during program execution breaking in Visual Studio toVariableVisitor.SetInvocationNonce()
, probably means you are re-instrumenting an already instrumented version of your program. -
Getting an error of "Could not load file or assembly 'file:///...' or one of its dependencies. Operation is not supported. (Exception from HRESULT: 0x80131515)" may occur if you get an executable downloaded from the internet or email, in these cases Windows attempts to block the file to prevent virus spread. To fix this problem right click on the executable in Windows Explorer, then click
Properties
. In theGeneral
tab near the bottom there is a button labeledUnblock
, click this, then clickOK
to close the properties window. -
An exception with error message like
System.Runtime.InteropServices.COMException was unhandled HResult=-2147418113 Message=Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED))
may indicate that one of the CCI DLL files in the%CELERIAC_HOME%
folder is not executable.