Below are preliminary examples of this for both .NET and JVM.
DbgCLR.exe
(graphical) and
CorDBG.exe
(textual) supplied with the
.NET Framework SDK
as well as with the built-in debugger in Visual Studio .NET.
[File->Open Solution...]
.
Files of types: All project files
and navigate to foo.exe
.
Double click foo.exe
.
[Debug->New Breakpoint (Ctrl-B)]
specify
breakpoint in Function program.Do
.
[Debug->Start (F5)]
.
The program will now stop at the do-part of the PROGRAM
fragment.
You can now single step, inspect variables etc. at BETA source
level.
As can be seen, a breakpoint has been set in
program.Do
(as described above) as well as in line 12 and 17. The latter two were
set using the contextual right button menu in the SuperFields.bet
source window.get
method has been
hit, and a single Step-into command has been issued, thus executing
the statement x + y -> z
(the maroon indication of the
statement seems to be off by one - we'll check this later (:-)).
By default Visual Studio will only be able to find source files in the
current directory. This means that when you, e.g., "step into (F11)" a
method residing in a source file outside the current directory, this
will behave as a "step over (F10)"!. To avoid this, you can specify
the Debug Source Files
property:
To access the Debug Source Files
property page,
right-click on your Solution
in Solution
Explorer
and choose Properties
from the shortcut
menu. Expand the Common Properties
folder and click the
Debug Source Files
page.
Additional information can be found on, e.g., Visual Studio: Debugging an Executable That Is Not Part of a Visual Studio Solution
DbgCLR.exe
. It typically resides in
C:\Program Files\Microsoft.Net\FrameworkSDK\GuiDebug\DbgCLR.exe
.
If you installed .NET Framework as part of Visual Studio .NET 2003 it may
reside in
C:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\GuiDebug\DbgCLR.exe
DbgCLR.exe
by double clicking its icon in the Windows Explorer.
foo.bet
has been compiled to foo.exe
, you may now
specify foo.exe
in menu item [Debug->Program to debug]
.
[Debug->New Breakpoint (Ctrl-B)]
specify
breakpoint in Function program.Do
.
[Debug->Start (F5)]
.
The program will now stop at the do-part of the PROGRAM
fragment.
You can now single step, inspect variables etc. at BETA source
level.
Notice that
DbgCLR
will only be able to automatically
open source files in the current directory.
Thus when you "step into (F11)" a file, that does not reside in the
current directory, this will behave as a step over!
This can be avoided by making the other source file "known" by
preopening it. If you accept saving the solution file, when the
current debug session is ended, the next time you debug the same
program, the previously opened source files will be known.
Addition information: CLR Debugger Solution Model.
cordbg.exe
and is normally automatically accessible
from your shell (as the .NET Framework Installer will have included
the path to it in your search path).
If you compiled with nbeta -d
, cordbg
is very useful for debugging
IL code. It automatically breaks a the main entry point when run as
> cordbg foo.exeThe syntax for breaking in the
Do
method of class program is
(cordbg) b program::DoYou may also use cordbg for source level debug, and specify, e.g.,
(cordbg) b foo.bet:16to make it break in line 16 of
foo.bet
. In this case foo should be
compiled without the -d
option. To get more help on using cordbg
type this:
(cordbg) help
If you want to debug at IL level instead of BETA source level, you can compile with:
> nbeta -d fooor (forcing total recompile):
> nbeta -s 12 -d foo
jdb
.
In order to use jdb, a few observations must be made:
<program name>.jar
in a sub directory named jvm
.-classpath jvm/<program name>.jar
beta
.jdb
session must be
prefixed with beta.
main
function resides in class beta.program
).jdb
must be instructed to execute
beta.program
.
jdb
will normally expect the source files to reside
in the same directory as the class files. The class files used when
executing the program all reside in the above mentioned jar file.jdb
to find the source files relative to the
jvm
directory, the jar/class files are placed in, the
-sourcepath
option is used, as shown in the example below.
jdb
supports
reading initial commands from a .jdbrc
file (or
jdb.ini
file on windows). This file can be placed in the
current directory or in your HOME directory.
A good command to put into that file is
stop in beta.program.Dowhich will cause the debugging session to stop at program start up.
Since the invocation of jdb
is a little cumbersom
(especially the setup of the sourcepath
), the BETA
compiler will generate a shell script named <program
name>-jdb
(with .bat
extension on windows),
which invokes jdb
on the program.
Below is a session showing BETA source level debugging using this
script.
tcsh> jbeta SuperFields.bet tcsh> ./SuperFields-jdb Running jdb on SuperFields: To stop at program start issue this command: stop in beta.program.Do Initializing jdb ... > stop in beta.program.Do Deferring breakpoint beta.program.Do. It will be set after the class is loaded. > run run beta.program Set uncaught java.lang.Throwable Set deferred uncaught java.lang.Throwable > VM Started: Set deferred breakpoint beta.program.Do Breakpoint hit: "thread=Thread-1", beta.program.Do(), line=29 bci=0 29 do &SuperFieldsSub[] -> S[]; Thread-1[1] list 25 #) 26 ---program:descriptor--- 27 (# S: ^SuperFieldsSub; 28 N: @integer 29 => do &SuperFieldsSub[] -> S[]; 30 33 -> S.x; 31 44 -> S.y; 32 S.x -> putint; 33 newline; 34 S.y -> putint; Thread-1[1] stop in beta.SuperFieldsSub.get Deferring breakpoint beta.SuperFieldsSub.get. It will be set after the class is loaded. main[1] cont > Set deferred breakpoint beta.SuperFieldsSub.get 33 44 Breakpoint hit: "thread=Thread-1", beta.SuperFieldsSub.get(), line=12 bci=0 12 do x -> z; Thread-1[1] list 8 (# y: @integer; 9 R: ^SuperFieldsSub; 10 get: proc 11 (# z: @integer 12 => do x -> z; 13 z + y -> z; 14 exit z 15 #); 16 call: proc 17 (# N: @integer; P1,P2: ^SuperFieldsSub Thread-1[1] next > Step completed: "thread=main", beta.SuperFieldsSub.get(), line=13 bci=5 13 z + y -> z; Thread-1[1] locals Method arguments: Local variables: z = 33 Thread-1[1] dump this this = { origin: instance of beta.betaenv(id=334) y: 44 R: null beta.SuperFields.origin: instance of beta.betaenv(id=334) beta.SuperFields.x: 33 beta.SuperFields.Q: null beta.BetaObject.comp$: null } Thread-1[1] where [1] beta.SuperFieldsSub.get (SuperFields.bet:13) [2] beta.program.Do (SuperFields.bet:36) [3] beta.Component.run (null) Thread-1[1] clear beta.SuperFieldsSub.get Removed: breakpoint beta.SuperFieldsSub.get Thread-1[1] cont > 77 77 77 77 77 The application exited tcsh>