1.0 CONTENTS ------------- Debugger-------------------------------------- Operation----------------------------------- Memory map---------------------------------- Commands------------------------------------ Breakpoint-------------------------------- Change variable--------------------------- Display variable-------------------------- Entry / exit flag------------------------- Go---------------------------------------- Help-------------------------------------- Line flag--------------------------------- Number------------------------------------ Proceed----------------------------------- Quit-------------------------------------- Remove breakpoint------------------------- Status------------------------------------ Trace------------------------------------- Update command line----------------------- Other uses---------------------------------- External references------------------------- Linkage creator------------------------------- Librarian------------------------------------- 2.0 DEBUGGER ------------- OPERATION The debugger operates in two phases to maximize the amount of memory available for the user program. At the start of phase one the full available memory area is divided into sections by the kernal (refer to the memory map). The debugger table size is defaulted to 10000 bytes or may be specified using the D command line option. If the debugger table size changes, the code area will change by the reverse amount. Making the debugger table smaller will allow more room tobe shared by the user program and the user program heap/data stack. The file specified on the command line is opened and assembled into the code area in one pass. A large disk buffer is used to speed this operation. The assembler is designed to accept the output of the compiler and is not general purpose in nature, therefore inline assembly code should not be used in the pascal program without first referring to the assembler source code to see if it can handle the code you intend to use. After assembly is completed the debugger is loaded on top of what was the assembler and disk buffer and control is passed to it. The first action of the debugger isto display the addresses or values of any external labels defined in the pascal program and to obtain the adresses of any external labels referenced in the pascal program. Both of these are displayed in the format: LABEL EQU $ If the label is defined in the pascal program then the value will be provided by the debugger, if not then you must type in the hex value after the $. This would only occur if variables or procedures are defined as external (detailed later). After all externals are taken care of the debugger enter it's main command processing loop. A description of the commands is provided in this manual and a summary is displayed if the user enters H when in the debugger. MEMORY MAP Phase 1 Phase 2 +----------------------+---------+-----------------------------+ <-- high : program flow table : : user program system stack : +----------------------+ +-----------------------------+ : label table : : user program data stack : +----------------------+ +-----------------------------+ : : : : : : : : : : : user program heap : : : +-----------------------------+ : : : : : : : : : : : : : : : : : code area : : code area : +----------------------+---------+-----------------------------+ : : : : : : : : : debugger table : : debugger table : +----------------------+---------+-----------------------------+ : assembler sys. stack : : debugger system stack : +----------------------+ +-----------------------------+ : : : debugger data stack : : : +-----------------------------+ : : : : : disk buffer : : : +----------------------+ : : : : : : : : : : : assembler : : debugger : +----------------------+---------+-----------------------------+ : : : : : : : : : normal runtime lib. : : normal runtime library : +----------------------+---------+-----------------------------+ : special runtime : : special runtime : +----------------------+---------+-----------------------------+ : kernal : : kernal : +----------------------+---------+-----------------------------+ <-- low : : : : +----------------------+---------+-----------------------------+ <-- $9F : base page variables : : base page variables : +----------------------+---------+-----------------------------+ <-- $20 DEBUGGER COMMANDS Breakpoint Format: B [line #] This command will set a breakpoint or display the current breakpoints. If no number (or zero) is entered, then the current breakpoints are displayed. If a non zero number is entered, then a breakpoint is set at the pascal line if it is an executable line. Executable lines are marked with a '*' (instead of ':') after the line number on the pascal compilation listing. There is a maximum of 16 breakpoints that can be set. If a breakpoint is hit while running the program, the message: Breakpoint encountered at line is displayed and the debugger is entered. The breakpoint is not removed from the table. Change variable Format: C The change command is used to change the previously displayed variable. After entering 'C ', the new variable value is entered. The variable must be entered in the same format as the display command used. The variable is read in the same format as a pascal read statement would use with the following differences. A byte variable is entered as one hex byte. A structure variable is entered as a sequence of hex bytes separated by spaces (only one line may be input). Sets may be entered in the same format as the set display and may be entered on several consecutives lines (input terminated by ']'). The set entry must start with a '[' and blanks are ignored. Display variable Format: Dx {[ or or ] [^] [<+> or <->]} [,length] where x = blank -Default variable type as defined B -Boolean C -Character H -Hex I -Integer R -Real S -String T -Set U -Byte X -Structure This command displays the current value of a variable. The variable may be specified by name, a hex address (prefixed by $), or an integer address. If a variable name is specified, then it must be valid at the current line number and lex level. If no address is specified, then the next location after the address specified in the previous display variable command is used (useful to step through records). The address may be modified by dereferencing (^) it (ie. pointer dereference), or adding/ substracting a variable name, address or offset from it. These modifications may be performed repeatedly. An optional lentgh may be specified which overides the default variable lentgh when displaying structures. When displaying a device (file) the default length is the length of the device descriptor. Dereferencing a device will display the contents of the element buffer. 'x' defines the format of the variable to be displayed. Sets are displayed zero element first (opposite of version 1 debugger) with the entire set enclose in brackets (a 1 means the element is present in the set). For exemple, the set [4..10] is displayed as [00001111 11100000]. The display structure format is similar to a memory dump in many monitors. The start address is displayed followed by a maximum of 16 bytes (in hex) per line, followed by the byte ASCII equivalent characters (non printable characters shown as '.'). This format is normally used to display arrays, records, or devices. Byte variables are displayed in both hex and integer. This form is useful for displaying enumerated types and string or set dynamic lengths. Character and string variables are displayed surrounded by single quotes. Entry / exit flag Format: E or or <+> or <-> This command turn the procedure entry/exit print flag on (ON or +) and off (OFF or -). If the flag is on, then when entering a procedure the following message is printed: Enter Procedure When exiting a procedure the following message is printed: Exit Procedure The enter message is displayed before the first executable line in the procedure, and the exit message is displayed after the last statement (end) in the procedure. The state of this flag is displayed as part of the debugger status message (see status). Go Format: G Go starts execution from the beginning of the program. Help Format: H This command displays the following helpfulness: Debugger command summary General control General display variable display --------------- --------------- ------------------------------- Go Status Dx {[variable name or address] Proceed Help [^][+][-]} [,length] Quit N x can be: Trace one E ON, E OFF, blank -use default type Trace N E+, E- proc or B -boolean func entry or c -character Breakpoints exit display H -hex --------------- L ON, L OFF, I -integer B display all L+, L- line R -real B N set number display S -string R remove all Update Cline T -Set R N remove U -byte X -structure Change last displayed variable Line flag Format: L or or <+> or <-> This commandturns the line number print flag on (ON or +) and off (OFF or -). If the flag is on, then the line number is printed before the line is executed in the following format: Line # The state of this flag is displayed as part of the debugger status message (see status). Number Format: N or This command displays the line number of the specified procedure or program's first executable line (Begin). This is useful when debugging a program using a non-current listing. Proceed Format: P Proceed continues execution of the program from the current line. The program must have previously encountered a breakpoint or a trace completion (ie. must still be in program). Quit Format: Q Quit causes the debugger to exit. Remove breakpoint Format: R [line #] This command removes breakpoints from the breakpoint table. If no number (or zero) is entered, then all breakpoints are removed. If a non zero number is entered, then only the breakpoint at that line is removed. Status Format: S This command displays the status of the program and the debugger. The status of the program is not displayed if the program isn't being executed. The program status contains: Current line number Lex level Trace count Current location Stack Local stack mark Global stack mark heap pointer Current line number (and corresponding current location) is where the program last hit a breakpoint or a trace completion. Lex level is the current lexical level (global is lex level 1). Stack is the current value of the User data stack. Local stack mark is the current base of any local variables, whereas Global variables are referenced from the global stack mark. The trace count is zero if there is not a trace in progress, otherwise it is the number of statements to complete the trace. The debugger status contains: Procedure entry/exit or Line number display or Cline ('contents') 'string' Program start Program end Code area % Debugger table % Procedure entry/exit and line number display reflect the state of the flags set by the entry (E) and line (L) commands. Cline is the current value of the command line (can be modified by the update cline command). Code area is the percentage of the allowable memory used by the user program. The area available is determined by the total system memory size and the size of the debugger table. Normally the heap pointer is set rigth past the end of the program (unless set by the heap command line option). This unused area beyond the actual end of the program is added to the space available for the heap and data stack. Debugger table is the percentage of the allowable memory used by the debugger table. The area available is determined by the debugger table command line option or defaulted to 10000 bytes. Trace Format: T [trace count] This command traces one or more statements of the program and then returns to the debugger. If no trace count (or zero) is entered, then one statement is traced, otherwise the specified trace countis used. The current trace count is displayed as part of the debugger status message (see status). When the end of the trace is reached the following message is displayed and the debugger is entered: Trace finished at line number Update command line Format: U This command changes the current command line. After entering 'U ', the command line is set to the string entered on the next line. The current value of the command line is displayed as part of the debugger status message (see status). This string is accessed when the user program executes the Cline function. OTHER USES Since the debugger has many of the features found in most monitors it is possible to perform operations that are beyond the pascal debugging requirements. Using the Display variable and Change variable commands with a hex address instead of a variable name allows displaying and changing the user program or any other area in memory. For instance in the following example: 5 flag1, flag2 : boolean ; . . 45 flag1 := true ; . . 50 flag2 := line = 'K' ; to change the variable accessed in line 50 to flag1 one could: 1) Set a breakpoint at line 45 et 50. 2) Execute till reaching breakpoint at line 45 3) Display program status noting current location value 4) Display memory: DX $,32 noting stack offset value to access flag1 5) Proceed to line 50. 6) Display program status noting current location value 7) Display memory: DX $,32 noting address of stack offset value to access flag2 8) Display memory: DX $,2 9) Change memory to stack offset value for flag1 This is one of many possibilities, all of which require care in performing to avoid crashing something. To display a base page variable a '<' may preceed the address in the display variable command. EXTERNAL REFERENCES Although the debugger can only operate on pascal programs (not modules) pascal modules or assembly language modules can be accessed from the pascal program being debugged. This is accomplished in the current release by making a loadable object module out of these modules and loading this module above the code area used in the debugger. It is first necessary to determine the ending address of the user program by running the debugger and entering zero for the external references and then using the status command to inspect the ending address. It is wise to leave some room between this ending address and the start of your object module so that if more code must be added to the user program (doesn't it always) you don't have to re-link the other modules. The next step is to link the modules with the runtime library, which can be done in two different ways. The first method is to link it with the runtime library and load the whole mess above the user program. If the modules call a significant portion of the runtime library this would be quite a large file due to the redundant runtime library. The other option is to use part of the linking for the debugger itself exept leave leave off the modules that follow the runtime library, move the location counter in the linker to the desired start of the modules and load the modules. This will result in a fairly large module but many operating systems allow you to easily chop off the unneeded code at the front (anything below your modules). This has the advantage of doing away with any redundant runtime library and also allow errors that occur in those modules to return to the debugger instead of the operating system. To debug this composite program first load the modules into memory then run the debugger using the H command line option to set the heap pointer above the end of your modules. The external references can then be answered using the values on your linker load map. Debugging then proceed as normal. 3.0 LINKAGE CREATOR -------------------- In order to generate a stand alone pascal program it is necessary to set up the stacks and link it with the runtime library. The linkage creator is used to generate the stack setup code and a 'CHAIN' file to: 1) assemblethe output of the compiler 2) assemble the stack setup code 3) link those with the runtime library, any other relocatable files, or other relocatable libraries. A number of files are generated each with the same drive (if used) and name as the pascal compiler output file but each with a different suffixe. Refer to the configuration manual for the suffixes used on your operating system. If the list command line option is specified then a summry will be generated to provide documentation of the parameters used. After the development work is done there will be a number of files left on the disk that can be removed by using the delete command line option. This option will delete all of the files that were generated except for the pascal source file. If the loadable object file is to be preserved it must have its name changed before using the delete option. The linkage creator will prompt for the required information needed for basic operation. If interupt vectors are required for a target system these must be setup by the user (normally by editing the stack setup file and 'CHAIN' file). The first question is the 'pascal compiler output file name' which is the file name (and drive if required) but with no suffix. If the delete command line option was specified this will be the only question asked. The next question is 'pascal program name' which is the identifier used after the pascal reserved word 'program'. In many cases this will be the same as the file name (less drive number) and if so this question can be answered with a carriage return. There are two methods available with the linkage creator to set up the stacks. The first one is 'auto setup' which is normally used for programs that run with the operating system. The details of this vary with the operating system and are covered in the configuration manual. In non 'auto setup' you must provide the addresses for the start and end of system stack, start and end of the data stack, and if used, the start and end of the heap. Note that the heap must always be below the data stack and in most cases you will set them up to use the same area of memory (see runtime environment section of the language handbook). The next question is 'starting load location' which will be passed along to the linker. 'library drive number' specifies the drive to find the runtime library on during the link process. If you have other pascal modules or assembly language modules these may be specified as the answer to 'additional files to load'. The answer is appended to the linker load command. If you have others libraries (either assembly language or pascal) these can be specified as the answer to 'additional library files'. Since it is assumed that some of these may overide the normal runtime routines (custom error handlers, new floating point routines, etc.) this string is put before the normal runtime library in the linker's library command. The next question varies in text but generally refers to the destination for the linker load map. 'map options' allows you to specify the format of the load map if available on the linker being used (see configuration manual). The stack setup code and 'CHAIN' file will now be written along with the summary if enabled in the command ilne. The 'CHAIN' file can now be run (see configuration manual) to complete the operation. 4.0 LIBRARIAN -------------- Most operating system supplied 'merge' commands simply append sectors together, they do not care what is in those sectors. In the pascal runtime library many of the relocatable object files are smaller than a sector, therefore the sectors are zero filled. If sectors are appended together then a great deal of disk space may be wasted. Going through these zero 'areas' also wastes time in the linker. The librarian will append relocatable object records together and skip those zero areas. The command line syntax for the librarian is: LB [S] {} If the S option is not specified then the input file specifications are simply file names to be appended into the output file. The input file names will be printed as they are opened. If the S option is specified then the input file specifications must be in the form of two letters followed by one or two integer digits. This option is used for building the runtime library to save a lot of typing. The one or two digit number is the maximum file number for the series. Since higher numbered runtime routines make use of entries in lower numbered runtime routines it is neccessary to append the files in reverse order, thereby guaranteeing that the linker can determine the modules to be loaded in one pass of the library. To append the files XX3,XX2,XX1 and YY2,YY1 the command line could be: LB XXYY XX3 XX2 XX1 YY2 YY1 or more compactly: LB XXYY XX3 YY1