Understanding the Synergy debugger
The Synergy DBL source-level debugger enables you to run your traditional Synergy programs in debug mode so you can control and examine the execution environment. The debugger supports line numbers, source display, breakpoints, watchpoints, examination by offset, .INCLUDEd routines, dimensioned variables, and named access to fields, including complete variable path specifications.
This topic contains the following information:
- Creating a symbolic access table
- Invoking the debugger
- Using the debugger on Windows
- Indirect command file processing
- Initialization file processing
- Specifying variables
- Debugging remotely on Windows and UNIX
- Debugging remotely on OpenVMS
- Debugger warnings
Creating a symbolic access table
If you want to be able to perform source displays and look up variables by their names, you must create a symbolic access table. If you don’t, you will not have access to the symbolic information when debugging. To create a symbolic access table,
On |
Do this |
---|---|
Windows and UNIX |
Use the -d or -qdebug option when you compile and the -d option when you link. For example: dbl -d source_file dblink -d input_file |
OpenVMS |
Use the /DEBUG option when you compile, and then link normally. For example: dbl /debug source_fileor dibol /debug source_file dblink source_file On OpenVMS, the main routine must also be compiled with the /DEBUG switch for the program to start up in debug mode. |
Invoking the debugger
To invoke the debugger, enter the appropriate command for your operating system,where program is the name of your compiled and linked Synergy program:
On |
Enter |
---|---|
Windows and UNIX |
dbr -d program
or dbr -rd port[:timeout] program (See Debugging remotely on Windows and UNIX for more information about the second format.) |
OpenVMS |
run program
|
Your command line prompt is
DBG>
(or DblDbg> on OpenVMS systems) and you can enter any of the debugger commands described in Synergy debugger commands.
On OpenVMS, if system option #49 is set, the runtime does not enter the debugger when you run programs built with the /DEBUG compiler option.
If you’re running your program in the debugger and a fatal error is encountered, the debugger generates the fatal error message and its traceback and break at the line that caused the fatal error. This feature enables you to investigate the circumstances that surround the error.
Online help for the debugger is available by typing
help [command]
where command is the command for which you want more information. To see a list of commands, just type “help” by itelf.
A system define called _DEBUG is defined when compiling with -d or -qdebug:1. By testing for _DEBUG using .IFDEF and .IFNDEF, you can conditionally include or exclude code based on whether or not a program is compiled in debug mode. |
Using the debugger on Windows
When you are debugging a Synergy application on Windows, the debugger output appears in a separate window. Debugger commands can be entered in this window at the prompt.
You can specify the initial size and placement of the Synergy debugger window in the synergy.ini file using the initialization settings DBG_HEIGHT, DBG_WIDTH, DBG_X, and DBG_Y. If the window fits on the desktop, it appears without scroll bars. If the window is resized to be smaller than the originally created size, it displays scroll bars on the window borders, which you can then move with the mouse to view the rest of the screen.
You can specify the font used in the debugger window using the FONT_DEBUG initialization setting. Refer to Using fonts on Windows for the defaulting hierarchy used when FONT_DEBUG is not specified. We recommend using a fixed font for the debugger.
If you move a source file and a .dbr file from Windows to UNIX or vice versa, you must move the files in binary mode if you want to view the source code correctly in the debugger. If you move the source file in ASCII mode (via FTP), the LF or CR-LF line terminators will not be preserved. |
Indirect command file processing
You can control the debugger indirectly using a command file. If an “at” sign (@) is the first character on an input line, the remainder of the line is assumed to be the name of a text file that contains debug commands to be executed.
When you specify a command file, a new command file level is activated until the last line in the file is executed. If one of the lines executed is another indirect command file specification, another level is activated until the lines in that file are executed. Up to eight levels can be activated in the debugger.
The default filename extension for a command file is .cmd, and full Synergy DBL–style logical name translation occurs.
On OpenVMS, you can use the DBG$INPUT and DBG$OUTPUT logical names to redirect debugger input and output.
Initialization file processing
You can also control the debugger using an initialization file. If you set the environment variable DBG_INIT to the name of your initialization file, the debugger reads the file and executes the debugger commands within it.
The default filename extension for an initialization file is .cmd (.com on OpenVMS).
Specifying variables
A variable specification can be a simple variable, a variable path, or a field belonging to an object instance. In fact, any variable specification that is valid during compilation is valid in the debugger, except that you can only specify a maximum of 12 elements within a given path specification. Like the compiler, the debugger requires that each variable path be unique.
A variable specification has any of the following formats:
- term
- routine:term
- object.field
- record.field
- group.field
where term is any simple variable or path specification, routine is the name of a routine in the current calling chain, object is an object instance variable name, field is a field name, record is a record name, and group is a group name.
For example, the following are all valid variable specifications:
v(1) v(1:3) rout:v(2,5) grp1.fld test:grp1[2].grp2[8].fld myclass.myfield (myclass)x.myfield ns1.ns2.myclass.myfield
To reference arguments, use
@-argnum
To reference an object instance’s field value, specify the object instance variable name and field name. For example,
x.myfield
To reference an object instance’s field value from an ancestor class, you can cast the object instance variable to any of the ancestors of the created class. Only one cast is allowed per EXAMINE command, but the object path can be enclosed in parentheses to clarify the object being cast. Use one of the following syntaxes:
(class_path)handle (class_path)handle.field (class_path)(handle_path).field (class_path)(array_list[entry]).field
where class_path is namespace.class and handle_path is record.group.handle. For example,
(myclass)x.myfield
or
(myclass)(x.y).myfield
or
(myclass)(myarray[0]).myfield
To cast a boxed object, use one of the following syntaxes:
(@structure_path)handle (@structure_path)handle.field (@structure_path)(handle_path) (@structure_path)(handle_path).field (@boxed_type)handle (@boxed_type)(handle_path)
where structure_path is namespace.structure; handle_path is record.group.handle; and boxed_type is a, d, or i.
You can reference a field value for the current object instance from within an instance method by supplying the field name, or you can specify the this keyword. For example,
this.myfield
The path for a static field in a class is made up of two parts: the class path and the field path. The class path is made up of namespace and class identifiers which may be abbreviated on the left side as long as the path is unique, but the specified identifiers must be an exact path without any missing identifiers. The field path must be a path to a static field in the specified class but may have unspecified identifiers as long as it is unique. When in a method, the static field paths may be specified without the class path as long as the static field is a member of the same class as the method. For example,
myclass.myfield
or
ns1.ns2.myclass.myfield
You cannot reference a complex path that includes an indexer, method call, or property.
Debugging remotely on Windows and UNIX
The Synergy DBL debugger can also run in a client/server configuration, where dbr acts as the debug server and the debug client is any program that is capable of acting as a Telnet client. Running the debugger remotely has several benefits:
- It is useful when the runtime is running non-interactively—for example, as a service or scheduled task on Windows, as a detached process on UNIX, under xfServerPlus or with an HTTP server application. (If you are debugging a service or other program that is normally started with dbs or dbssvc, you will need to start it with dbr instead. However, it is still running non-interactively, in that it doesn’t interact with the desktop and it runs under the same user profile as it does in normal [nondebug] mode.)
- It can also be useful in instances where the application is highly user-interactive and using the debugger causes the program you are trying to debug to behave differently. If an application has a problem with the way a field receives focus or if an application is run with input redirected, you probably don’t want the debugger window to pop up and receive focus. Let’s say, for example, that you have an ActiveX event procedure hooked to the OnFocus event for the container. If you break in that routine in the regular debugger, the debugger will steal focus, so that when you continue program execution with GO, the OnFocus event will be invoked again and you will get another break. Running the debugger remotely from a separate workstation will alleviate this problem.
- It can be helpful for cell-based debugging. When debugging a Toolkit application, the window-system displays and the debugger displays get mixed together, and you end up doing a lot of “screen redraw” commands to see what is going on. By running the debugger remotely, you can run the application on one terminal (or terminal emulator) and debug it on another.
Running the debugger remotely requires the following:
- The machines on which the debug client and debug server are running must be capable of communicating via Telnet. (Dbr acts as the Telnet server.) Both debug client and debug server can be on the same machine, or they can be on separate machines.
Telnet is a TCP/IP protocol for accessing remote computers. You can use whatever Telnet application you prefer (for example, the basic telnet.exe program that comes with Windows, the shareware QVT/Term application, or something else).
- TCP/IP must be configured.
- If there is a firewall between the debug client and the debug server, the firewall must be configured to allow Telnet access on the debug port number. (Most firewalls are configured to prohibit Telnet access.)
- You must have access to the machine running the debug server (dbr) as well as access to the external trigger that initiates events within the program (if the program is non-interactive).
To run the debugger remotely, do the following:
1. | (Recommended) Compile and link with the -d option. |
2. | Start the program to be debugged with dbr -rd on the command line: |
dbr -rd port[:timeout] program
where port is the port number on which the debug server will listen as a Telnet server for the debug client (1024 to 65535, inclusive), timeout is the number of seconds the debug server will wait for a connection from the debug client (the default is 100), and program is the name of your compiled and linked Synergy program. If you include the timeout, there cannot be a space on either side of the colon. Make sure timeout is lower than your client connection timeout value.
(Windows) If your program is a detached program or a service that is normally started with dbs or dbssvc, your environment may change, because dbr always reads the synergy.ini file, whereas dbs and dbssvc read it only when SFWINIPATH is set. We recommend that you use SFWINIPATH to point to the location of your synergy.ini file and thereby avoid potential problems. For more information on dbs and dbssvc, see Non-interactive runtimes. |
3. | Start a Telnet session and connect to the debug server. (The Telnet application may be on the same machine as the debug server or on a separate machine.) Specify the IP address or host name of the debug server (or localhost if you are on the same machine as the debug server) and the port number you specified with the -rd option. |
Once a connection is established, the debug session displays in the Telnet session window on the debug client machine.
4. | Debug your program. (Remember that your source files must be accessible by the debug server machine if you want to view source code within the debugger.) |
The debug commands WINDBG (invoke the Toolkit window debugger) and ! (invoke a shell command) are not supported by the debug server. If either command is used, an error is generated.
Most Telnet applications support paging and scrolling in the window. This provides a scrollable debug display and enables you to see more of what you are working on than in the normal Synergy debugger window. |
5. | Once debugging is complete, let the program finish running; the runtime will exit, and the Telnet session will close automatically. Optionally, you can close the session in one of the following ways: |
- Shut down the Telnet session. All breakpoints and watchpoints will be canceled, and the program will continue running in normal mode.
- Use the debugger QUIT or EXIT command to stop the runtime and exit the program. The Telnet session will close automatically.
For more information and specific instructions for debugging when xfServerPlus is involved, see Debugging your remote Synergy routines.
Timeouts or other failures are logged to a file named rd.log, which is created in the TEMP directory when the first entry in the file is logged. This file contains the process ID of the instance of the runtime that logged entries, the date and time entries were logged, and specific messages. If you are having a problem debugging remotely, check this file first.
When using remote debugging with xfServerPlus, we recommend that you explicitly set TEMP in the Synrc node in the Windows registry, or else rsynd will put the log file in a system-determined location (most likely somewhere in the C:\Users path). |
Debugging remotely on OpenVMS
To set remote debugging,
1. | Compile with the /DEBUG option. |
2. | Link the program as usual |
3. | Define the DBG_RMT logical. |
Debugger warnings
When a program is running in debug mode, some warnings are output to the debug window so you can fix potential issues before they cause runtime errors that can break your production system:
file1 file2 duplicate common/gds/static rec record of differing size size1 - size2
Duplicate global common or global data sections exist with different sizes. This fatal error can occur if only part of an application is rebuilt when common and global data section definitions change. Ensure that global common and global data section initializations are defined in only one place via .INCLUDE, preferably in a base ELB/shared image.
Duplicate common/static rec/gds record in ELBs file1 file2 detected - duplicate ignored
Commons and global data sections should never be duplicated in a process. The name lookup algorithm for data variables may cause duplicates to be used concurrently, leading to unexpected program behavior. For example, if a variable called mycommon exists in two places, two different pieces of code may update different mycommon variables. Ensure that global common and global data section INITs are defined in only one place, preferably in a base ELB/shared image.
Casting invalid length length argument as Integer in routine routine line line#
You've passed a variable for ^I() that is not size 1, 2, 4, or 8. Integer data must be one of these lengths; correct your code to pass a variable of the correct size.
Pushing passed integer/object descriptor of declared type argument routine routine line line#
You've passed an integer or object to a routine parameter typed d or d., or to ^D() or ^F(). Fix the call in your code.