When invoked in the batch mode, the debugger loads a control file --- a text file containing XD control language statements. Those statements perform various debugging actions: load program, set breakpoint, add watch expression, start program execution, etc.
During control file processing, the debugger creates a log, which may be saved in a file and then analyzed.
There is also a statement that temporarily switches the debugger into the dialog mode. Upon exit from it, control file processing continues.
Each line of a control file may contain a statement or a comment (empty lines are treated as comments). Comments start from the symbol ";".
Statement =
[ label ] name [ parameter {"," parameter}] [";" comment]
A statement consists of a label, a statement name, a comma-separated list of parameters and a comment. All these parts except statement name are optional. Statements may not be broken across two or more lines. Statement names are not case-sensitive.
Control files are often used to prepare a program for debugging in the dialog mode, and usually perform the following actions:
LOAD d:\xds\samples\bench\dry.exe ;1 ;2 MODULE dry ;3 ;4 BREAK P0,ADDR,Proc0,Dialog ;5 BREAK P8,ADDR,Proc8,Dialog ;6 ;7 WATCH Char1Glob,Array1Glob[8] ;8 ;9 START ;10 QUIT ;11 ;12 Dialog DIALOG ;13 STOP ;14
In this sample, comments are used to hold the line numbers referenced below.
Line 1: The LOAD statement loads an executable file, specified as a parameter, into the debugger.
Line 3: The MODULE statement sets the current module to dry, allowing to use unqualified indetifiers in the following statements.
Lines 5 and 6: The BREAK statements establish sticky breakpoints at the entry points of the procedures dry.Proc0 and dry.Proc8. Dialog is the name of a label from which processing of the control file will continue if the breakpoint is hit.
Line 8: The WATCH statement adds expressions dry.Char1Glob and dry.Array1Glob[8] to the list of watch expressions.
Line 10: The START statement starts the debuggee. Processing of this statement finishes when the debuggee terminates or a STOP statement is executed in a break handler.
Line 11: The QUIT statement terminates the debugging session.
Line 13: The label Dialog was specified in the BREAK statements in lines 5 and 6. If either of the breakpoints set by those statements will be encountered during execution, in our case during processing of the START statement in line 10, the debugger will process the control file starting from this line.
The DIALOG statement switches the debugger to dialog mode. Breakpoints and watch expressions remain active. Upon user-initiated exit from the dialog mode, the debugger will return to the batch mode and process the next statement.
Line 14: The STOP statement terminates the debuggee. The debugger will continue control file processing from the line following the START statement.
LOAD Program [ Arguments ]
The LOAD statement loads an executable file Program into the debugger, passing optional command-line Arguments to it. This statement should be executed prior to any statements which perform debugging actions, i.e. set breakpoints, add watch expressions, etc.
If a program fails to load, a message is displayed and control file processing is terminated.
Possible Errors
| 127 | Incorrect program name |
| 165 | Program name expected |
| 700 | Loading <...>: <...> |
LOAD xc =p =a dry LOAD dry
The statements described in this section allow to change the order in which control file is processed,
PAUSE [ Delay ]
The PAUSE statement suspends control file processing for Delay seconds, or until a key is pressed, allowing a user to view the last debugger messages. If Delay is not specified, infinite delay is assumed.
Possible Errors
| 126 | Incorrect parameter |
PAUSE PAUSE 10
GOTO Label
The GOTO statement unconditionally transfers control to the statement associated with Label.
If the specified Label does not exist in the control file, an error message is issued, and control is passed to the next statement.
Possible Errors
| 112 | Incorrect label |
| 114 | Label not found |
| 168 | Label expected |
GOTO Terminate
IF Expression THEN Label
The IF statement evaluates Expression, which has to be of type BOOLEAN, and, if it yields TRUE, passes control to the statement associated with Label. If the result of Expression is FALSE, the next statement is executed.
If the specified Label does not exist in the control file, an error message is issued, and control is passed to the next statement.
Possible Errors
| 128 | THEN expected |
| 134 | Expression expected |
| 168 | Label expected |
| 176 | Incorrect expression |
IF Dry.Char1Glob='A' THEN Write IF (Str.Len=10)AND(Memory.Limit) THEN exit
CALL Label RETURN
The CALL statement transfers control to the statement associated with Label. The RETURN statement returns control to the statement following the last executed CALL statement. Thus, these two statements allow to group the common parts of a control file into subroutines. The procedure calls may be nested.
If the specified Label does not exist in the control file, an error message is issued, and control is passed to the next statement. The same happens if a RETURN statement is encountered. which has no corresponding previously executed CALL statement.
Possible Errors
| 112 | Incorrect label |
| 114 | Label not found |
| 115 | RETURN without CALL |
| 168 | Label expected |
CALL Write . . . Write . . . RETURN
SIGNAL "+" ErrorNumber "," Label SIGNAL "-" ErrorNumber
The SIGNAL statement is used for error trapping. The "+"-form enables trapping of an error ErrorNumber. After execution of a statement caused this error, control is passed to the statement associated with Label. An error is considered handled and the error counter is not incremented.
If the specified Label does not exist in the control file, an error message is issued, and control is passed to the next statement.
The "-"-form disables trapping of a specified error.
The #IMPORT directive and the SIGNAL statement allow to implement reusable handlers for a certain group of errors.
Possible Errors
| 112 | Incorrect label |
| 114 | Label not found |
| 168 | Label expected |
| 208 | Error code expected |
| 209 | Incorrect error list action |
| 210 | Incorrect error code |
| 211 | Handler for error <...> already defined |
| 212 | Handler for error <...> not defined |
SIGNAL +700,ErrorLoadProgram SIGNAL -700
DIALOG [ Message ]
The DIALOG statement switches the debugger to the dialog mode. Message, if specified, is displayed in a message box. All breaks, breakpoints, and watches set in the batch mode remain active.
Control file processing will be resumed upon exit from the dialog mode, unless you select Stop debugging from the File menu.
Possible Errors
| 116 | Program not loaded |
DIALOG
QUIT
The QUIT statement unconditionally terminates control file processing.
Possible Errors
None.
Example
QUIT
Statements of this group are used to establish breaks and breakpoints, and execute the program being debugged.
START STOP
The START statement begins execution of the debuggee. During execution, control may be returned to the debugger, for instance, as a result of a breakpoint hit. The STOP statement may be used in a handler to terminate the debuggee. In this case, control file processing continues from a statement next to the START statement.
The START/STOP statements form a pair similar to CALL/RETURN, except that nesting is not allowed. This means that a program may not be restarted until it is explicitly stopped, so START is not allowed within a handler. Conversely, STOP is not allowed outside a handler.
The STOP statement unwinds the subroutine stack up to the level from which the START statement was issued.
Possible Errors
| 116 | Program not loaded |
| 129 | Program restart not allowed |
START STOP
RESUME
The RESUME statement effectively terminates a handler, causing program execution to continue after a breakpoint hit or a break activation. The CALL stack, however, is not unwound, so issuing RETURN later may cause control to be transferred to the line after the CALL statement which called the subroutine containing the RESUME statement.
Possible Errors
| 116 | Program not loaded |
| 130 | Program was not started |
RESUME
BREAK (Name | Number) "," Event Event = StopByUser | ProgramException | BreakAtAddress | BreakAtLine | BreakAtProc | WriteAccess | ReadAccess | BreakByCondition StopByUser = USER "," Label. ProgramException = XCPT "," Label. BreakAtAddress = ADDR "," Address "," ( Label [ "," Pass] [ ",?," Condition ] ["," "/"] | "*" | "." ). BreakAtLine = LINE "," ModuleName "," Line "," ( Label [ "," Pass] [ ",?," Condition ] ["," "/"] | "*" | "." ). BreakAtProc = PROC "," ProcName "," [ "P" | "B" | "E" | "R" ] "," ( Label [ "," Pass] [ ",?," Condition ] ["," "/"] | "*" | "." ). WriteAccess = WRITE "," Address "," Length "," Label. ReadAccess = READ "," Address "," Length "," Label. BreakByCondition = COND "," BooleanExpression "," Label.
The BREAK statement establishes an event handler. When the specified Event happens during execution of the debuggee, control is returned to XD and control file processing continues from the statement associated with Label. A handler is identified by an unique symbolic Name or Number.
The following types of events may be detected:
For breakpoints, you may optionally specify:
Specify "*", or "."instead of Label to set a watchpoint or a counter respectively.
If the specified Line is not executable, a warning is issued, and the breakpoint is set at the first executable line which number is greater, if such line exists.
In Condition, it is possible to use variables that are not visible in the current context, but they have to be visible at the specified breakpoint location.
Note: It is recommended to remove access breaks from local variables upon return from a procedure.
Possible Errors
| 112 | Incorrect label |
| 114 | Label not found |
| 116 | Program not loaded |
| 131 | Incorrect address |
| 151 | Incorrect breakpoint number |
| 152 | Breakpoint number already in use |
| 153 | Incorrect event identifier |
| 155 | Incorrect length |
| 159 | Line number expected |
| 160 | Incorrect line number |
| 161 | Break already exists |
| 168 | Label expected |
| 169 | Breakpoint number expected |
| 170 | Breakpoint type expected |
| 171 | Breakpoint attributes expected |
| 182 | Incorrect break |
| 213 | Module not found |
| 917 | This break is set but is disabled due to hardware limit |
| 918 | Wrong expression in current context |
BREAK 1,USER,Break BREAK 2,XCPT,Break BREAK 3,ADDR,Dry.Proc8,Break BREAK 4,WRITE,ADR(Dry.Char1Glob),1,Break BREAK 5,READ,ADR(Dry.Char1Glob),1,Break BREAK 6,COND,Dry.Char1Glob='A',Break BREAK 7,LINE,Dry,210,Break
DEL Number { "," Number }
The DEL statement removes a previoulsy installed event handler associated with Number.
Possible Errors
| 151 | Incorrect breakpoint number |
| 162 | Break number <...> not found |
| 169 | Breakpoint number expected |
DEL 1 DEL 3,4,17
The statements described in this section are used to change and display values of CPU registers, variables, and memory areas.
FILL ( Address | Register ) "," Length "," WholeExpression
The FILL statement initializes a memory area or a set of CPU registers by setting all its bytes to a specified value.
Address must be an address expression, so use ADR(v) to initialize a variable v. Length is a number of bytes to fill with result of WholeExpression MOD 100H.
It is also possible to specify CPU Register instead of memory Address. In this case, registers are "mapped" onto a byte array in the following sequence:
EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP
starting from the less significant byte.
Possible Errors
| 107 | Parameter expected |
| 116 | Program not loaded |
| 126 | Incorrect parameter |
| 131 | Incorrect address |
| 157 | Address value expected |
| 203 | Write to address <...> failed, len <...> |
FILL ADR(Dry.Char1Glob),1,0x47 FILL ADR(Dry.Array2Dim),56,0 FILL @EAX,20,0xFA
SET ( Variable | Register ) "," Expression
The SET statement evaluates an Expression and assigns the result to a Variable or loads it into a CPU Register.
See Chapter Expressions for more information about expressions in XD.
Possible Errors
| 116 | Program not loaded |
| 134 | Expression expected |
| 187 | Write to register <...> failed |
| 200 | Variable or register expected |
| 201 | Type incompatibility in assignment |
| 205 | Stuctured variable not allowed in this context |
SET Dry.Char1Glob,'A' SET @ESP,0xFAFBFCFD
MOVE SourceAddress "," DestinationAddress "," Length
The MOVE statement copies Length bytes of memory from SourceAddress to DestinationAddress. Both addresses may be specified as expressions. Overlapped areas are copied unsafely; a warning is issued in this case.
Possible Errors
| 116 | Program not loaded |
| 126 | Incorrect parameter |
| 155 | Incorrect length |
| 157 | Address value expected |
| 203 | Write to address <...> failed, len <...> |
Example
MOVE ADR(Dry.Char1Glob),ADR(Dry.Array1Dim),1
When operating in the batch mode, the debugger forms a log containing executed lines or instructions, messages, etc. The statements described in this section allow to output data to the log, redirect it to a file, toggle log filters, and otherwise control the logging features.
LOG [ FileName [ "." [ FileExt ] ]
The LOG statement allows to redirect log to a file. By default, the log information is written to the standard output. After redirection to a file, only error messages are written to the standard output. If FileExt is not specified, the default extension .XDL will be used. If no file name is specified at all, control file name will be used with extension replaced with the default log file extension.
Possible Errors
| 004 | Error opening log file <...> |
| 117 | Incorrect log file name |
LOG LOG result. LOG result.dat
PRINT Format { ',' Expression }.
Format = '"' { Character | Specifier | ControlSeq } '"'
Character = <any printable character except '%' and '\'>
ControlSeq = '\' ( 'n' | 'r' | 'l' | 'f' |
't' | 'e' | 'g' | '%' | '\' )
Specifier = '%' { Modifier } Base | MemoryRegion
Modifier = '$' | '-' | '+' | '|' | '#' | '0' |
Space | Width | Precision
Base = 'i' | 'd' | 'u' | 'x' | 'o' | 'b' |
'c' | 's' | 'w' | 'f' | 'e' | 'g' |
'X' | 'F' | 'E | 'G' | 'u' | '%'
MemoryRegion = ('M'|'m') "(" "'" Specifier "'"
[',' Const [',' Const ] ] ")"
Width = Digit { Digit }
Precision = '.' Digit { Digit }
The PRINT statement performs formatted output to the log. The format string syntax is similar to used by the printf family of functions available in the C standard library.
Format is a string which may contain ordinary characters, control sequences (starting with '\') and format specifiers (starting with '%'). During execution of a PRINT statement, Format is scanned from left to right. Ordinary characters are sent to the log unchanged, while control sequences are replaced with certain control characters. Upon encountering of a format specifier, result of a corresponding Expression is formatted according to that specifier and output to the log. Therefore, the number of expressions has to match the number of format specifiers. If there is a specifier for which no expression is supplied, an error will be raised. If there are more expressions than specifiers, a warning will be issued. A newline sequence (CR+LF) is output upon completion of a PRINT statement.
Possible Errors
| 134 | Expression expected |
| 143 | Double quotes expected |
| 144 | String not terminated (double quotes expected) |
| 204 | Read from address <...> failed, len <...> |
| 205 | Stuctured variable not allowed in this context |
| 206 | Register is not allowed |
Example
PRINT "Hello, world!"
PRINT "Char1Glob='%c'",Char1Glob
PRINT "------\n\t1 bell\g\n\t2 bell\g\n\t3 bell\g\n------"
PRINT "Array1Glob: [7]=%u, [8]=%u",Array1Glob[7],Array1Glob[8]
PRINT "Memory region: %M('%$4X\n',k4,l20)",ADR(Array1Glob[6])
ControlSeq is a two-character sequence which causes a certain control character to be output:
| Sequence | Replaced with |
| \n | CR+LF (15C 12C) |
| \r | CR (15C) |
| \l | LF (12C) |
| \f | FF (14C) |
| \t | TAB (11C) |
| \e | ESC (33C) |
| \g | BEL (7C) |
| \% | percent sign (45C) |
| \\ | backslash (134C) |
The following format bases are recognized:
| Base | Argument | Output format |
| "c" | CHAR | single character |
| "d", "i" | integer | signed decimal integer |
| "u" | integer | unsigned decimal integer |
| "o" | integer | unsigned octal integer |
| "x", "X" | integer | unsigned hexadecimal integer |
| "f" | real | fixed-point real |
| "e", "E" | real | floating-point real |
| "g", "G" | real | the shorter of "f" and "e" |
| "s" | string | string |
| "w" | boolean | "FALSE" or "TRUE" |
| integer | "FALSE" if zero, "TRUE" otherwise | |
| "n" | any type | default |
| "%" | none | "%" |
Note: Case of hex letters and of a letter used to introduce exponent in a floating point number matches case of the corresponding Base character.
Modifier allow to alter the default data formatting:
| Modifier | Bases | Meaning | Default |
| "+" | difegEG | always print sign | only negative |
| space | difegEG | print space instead of "+" | |
| "-" | all | left-justify the value | right-justify |
| "|" | all | center the value | |
| "0", "$" | numeric | print leading zeroes | spaces |
| "#" | oxX | print a base character | no base character |
Width is an unsigned decimal specifying the minimum number of character positions used for a formatted value. If the output string is shorter than Width, blanks or zeroes are added according to Modifiers. If the number of characters in an output string exceeds Width, or Width is omitted, all characters are printed.
Precision is an unsigned decimal preceded by a period, which specifies the exact number of characters to be printed or the number of decimal places. Unlike Width, Precision may cause the output value to be truncated or floating-point value to be rounded.
Precision value is interpreted depending upon the Base:
| For bases | Precision specifies |
| i d u o x X | The minimum number of digits to output. Shorter values are padded on the left with blanks; longer values are not truncated. Default is 1. |
| f F e E | The number of positions after the decimal point. The last digit output is rounded. If Precision is 0, decimal point is not printed. Default is 6. |
| g G | The maximum number of significant digits to output. By default, all significant digits are printed. |
| c | The number of times the character is to output, default is 1. |
| s | The maximum number of characters to output. By default, characters are output until 0C is reached. |
| {} | Has no effect. |
MODE Mode { "," Mode }
Mode = ADDR | BAT | BREAK | DUMP | PRINT ( "+" | "-" )
TRACE ( "+" | "-" ) [ "," ( CODE | SOURCE | MIX ) ]
DISASM "=" ( SMALL | FULL )
ERRORS "=" number
The MODE statement controls what is written to the log and in which format.
| Mode | Controls |
| ADDR | whether memory dump lines contain addresses |
| BAT | whether executed control file statements are logged |
| BREAK | whether info about breaks is written |
| DISASM | disassembly mode |
| DUMP | whether instruction codes are dumped |
| ERRORS | maximum number of errors |
| whether PRINT statements are executed | |
| TRACE | the way execution trace is logged |
Possible Errors
| 126 | Incorrect parameter |
| 137 | Incorrect mode |
| 138 | Errors limit set to <...> |
| 172 | Mode expected |
MODE TRACE- MODE TRACE+,CODE,DUMP+,DISASM=FULL MODE PRINT+,ADDR- MODE ERRORS=10,BREAK+
MODULE [ ModuleName ]
In the dialog mode, you may use names of program objects belonging to the current module without qualification. Similarly, in the batch mode, when execution of the program stops and control is returned to the debugger, the current component and module are set according to the value of the instruction pointer. The MODULE statement explicitly changes the current module. If ModuleName is not specified, unqualified identifiers recognition is disabled.
Possible Errors
| 116 | Program not loaded |
| 213 | Module not found |
MODULE Dry MODULE
WATCH Expression { "," Expression }
The WATCH statement is used to fill up the list of watch expressions, which is available in the dialog mode. It has no effect in the batch mode, and usually precedes the DIALOG statement.
Each Expression is checked for correctness. If Expression may not be evaluated in the current context, a warning will be issued.
Possible Errors
| 116 | Program not loaded |
| 918 | Wrong expression in current context |
Example
WATCH Dry.Char1Glob WATCH Dry.Array2Glob[1],Memory.Free<=128
#IMPORT ControlFile
XD control files are likely to have some common routines, which perform, for instance, register dump, or heap tracing. It is possible to collect these routines in separate control files and import them into any control file which requires the routines.
The #IMPORT directive causes the debugger to load the specified ControlFile into memory and add its labels to the global table of labels.
After the debugger loads the control file specified on the command line, it scans it for labels and #IMPORT directives, and recursively repeats this procedure for all imported control files.
Note: This directive was intentionally named #IMPORT, not #INCLUDE, in order to emphasis the fact that the contents of the ControlFile are not substituted instead of the directive.
When XD reaches the end of a control file, it terminates regardless of whether that file was imported or specified on the command line. So make sure the imported control files are ended with an explicit control transfer statement, such as RETURN or GOTO.
Possible Errors
| 007 | Batch name missed. |
| 009 | Too many nested packages (16) |
| 010 | Package <...> recursively imported |
| 011 | Incorrect package name <...> |
| 014 | Imported package <...> not found. |
| 018 | Unknown directive <...>. |
| 111 | Label '<...>' already defined |
| 112 | Incorrect label |
| 113 | Label matches reserved word |
#IMPORT PrintRegisters #IMPORT SetBreakpoints #IMPORT ErrorHandler