Mp debug 02-JAN-81 Mp debug The debugger for mp is envoked by the following two actions: 1. One must compile the file to be debugged using the debug switch (/da). This implies that modules that are not built this way will by considered atomic by the debugger. The first debugger routine entered will get an automatic breakpoint. 2. The debugger module (debug.obj) must be included in the task build stream with the /da switch on it. First the things that can go wrong using the debugger. Don't place any absolute data (like .word, .blkb etc.) statements after the first function statement. After this statement occurs Mp places before EVERY line a bpt instruction so it can get control. Sure this adds up and its slow (like an interpreter), but its better than nothing and it works like a charm on overlaid tasks since it need not modify the code (works on r/o code too!). If you have a rather long loop, turn off the /da switch from the source module across the loop. However, it ran 30000 statements in 20 seconds. Of course this method has some good features too. Like dynamic profiling and checking for variables that change their values. Remember this ain't a Vax. Wild ass'd branches out of a function (like for error recovery) can cause problems since the dynamic traceback chain won't get released (poped). Now the good news: All statements to the debugger are of the following form: cmd op1 op2 op3 ... where there are separators between the operands. These may be commas or spaces. Here are the statements: Facts statements: f facts about current function fa facts about all functions ft facts about current trace back chain ftv like ft but more info -1- Mp debug 02-JAN-81 Mp debug Listing of variables l quick list all vars in local funcion l var [from [to]] treats var as beginning of array to dump lb var [from [to]] dump array as bytes The output of an l or lb dump contains: var(index) @address octal decimal. ascii Tracing t display current trace settings t l/f on/off trace line (l) or function (f) on or off ct var [g] check trace var in local or (g) globally Breakpoints b list breakpoints (0-7) b line [function] set break at line in current or function bd number delete breakpoint numer n (0-7) bd delete all breakpoints bl also a breakpoint list c var [g] set breakpoint on var change of value c clears any check variable (trace or break) start, stop, continue, and pause p proceed from current breakpoint single step control-z exits (does not close files) !any mcr command spawn and stop-for completion (i.e. wait). modify memory m var val1 [val2] modify var to val1 or var[val1] to val2 mb var val1 [val2] modify var to val1 or var[val1] to val2 Notes: Where a variable name is required (var) an absolute machine address may be specified (in octal if it starts with `0' else decimal). Also, @var or @xxx (xxx is a machine address) may be specified. @@var etc is also acceptable. The last accessed location either via l, m, or c type commands can be refered to as `.' (dot). It may be referenced as @. also. Note that the entrys for val1, val2 as well as from and to in the l commands may be variables (or @var). They may not be machine addresses (any numerical value is considered as a constant). Only where a var is required can a machine address be specified. And, only in this case will dot be updated. The c and ct commands constantly check for a variable whose value is changing and either break or just trace. The g means do it everywhere (global variable) else it must be in the same function where you are now (at a breakpoint). This value may be a register if you put registers into the symbol table with value of 10+register number. E.g. r0 is 10, r1 is 11 etc. The way to do this is: -2- Mp debug 02-JAN-81 Mp debug e%s r0 10 e%s r1 11 etc. Place these between autos and the function statement. There must be an auto statment for this to work otherwise the symbol table will be cleared by the function statement. The registers are saved in a single save area so the debugger can locate them easily. However, they get reused in all routines so one should not declare them global. Global (or static) variables can be entered like the above registers by a statement: Extern var1,var2,...,varN This puts these in with type 3. Also, if one wants to find out where in a dynamic chain of routines a location is getting clobbered, then specify global on the c command. Note also that when the routine in which a local check variable is declared exits, the check variable disapears, so the debugger disengages the checking of that variable. Of course it really does not verify the globalness of a variable and one could probably do meaningful stuff by declaring a local variable as global for the debugging process. (In the debugger not in the program!!) One sometimes useful technique is to set a variable trap on some absolute location on the stack where you suspect you might be getting to. This allows one to trap in the event of stack under flow. The function enter routine will do this also but when it traps on underflow it arbitrarily sets sp to 1000 and then can only be used to look around - any p or step will cause an exit. Since I could not come up with an elegant way of handling control o since the user program can attach the terminal on us, the following method is used. First, it requires typeahead as we have patched it into rsx (does not need an attach). Before each line printed in the various dump commands, a call to the routine `interupt' is made which reads the current typeahead count. If non zero, then it first flushes the type ahead and then breaks out of the dump loop. Works pretty well too. Note that spawning does not detach the terminal so if the user program has it attached, this will not work too well. I suggest that all code regarding attaching the terminal be implemented after all else has been debugged. One last non-documented command is `debug'. This prints out the address of some internal locations. A clever user can figure out how to make use of this stuff. The only use I have thought of is to do a global check of fcur or dcur the two pointers which change on every change from one function to another (exit or entry). Note that proceed counters have not yet been implemented. -3-