dbug (part 3 of 4)
fnf at unisoft.UUCP
fnf at unisoft.UUCP
Thu Dec 12 10:42:27 AEST 1985
#--------CUT---------CUT---------CUT---------CUT--------#
#########################################################
# #
# This is a shell archive file. To extract files: #
# #
# 1) Make a directory for the files. #
# 2) Write a file, such as "file.shar", containing #
# this archive file into the directory. #
# 3) Type "sh file.shar". Do not use csh. #
# #
#########################################################
#
#
echo Extracting user.t:
sed 's/^Z//' >user.t <<\STUNKYFLUFF
Z
Z
Z
Z D B U G
Z
Z C Program Debugging Package
Z
Z by
Z
Z Fred Fish
Z
Z
Z
Z
Z IIIINNNNTTTTRRRROOOODDDDUUUUCCCCTTTTIIIIOOOONNNN
Z
Z
Z Almost every program development environment worthy of
Z the name provides some sort of debugging facility. Usually
Z this takes the form of a program which is capable of
Z controlling execution of other programs and examining the
Z internal state of other executing programs. These types of
Z programs will be referred to as external debuggers since the
Z debugger is not part of the executing program. Examples of
Z this type of debugger include the aaaaddddbbbb and ssssddddbbbb debuggers
Z provided with the UUUUNNNNIIIIXXXX811119 operating system.
Z
Z
Z One of the problems associated with developing programs
Z in an environment with good external debuggers is that
Z developed programs tend to have little or no internal
Z instrumentation. This is usually not a problem for the
Z developer since he is, or at least should be, intimately
Z familiar with the internal organization, data structures,
Z and control flow of the program being debugged. It is a
Z serious problem for maintenance programmers, who are
Z unlikely to have such familiarity with the program being
Z maintained, modified, or ported to another environment. It
Z is also a problem, even for the developer, when the program
Z is moved to an environment with a primitive or unfamiliar
Z debugger, or even no debugger.
Z
Z
Z On the other hand, _d_b_u_g is an example of an internal
Z debugger. Because it requires internal instrumentation of a
Z program, and its usage does not depend on any special
Z capabilities of the execution environment, it is always
Z available and will execute in any environment that the
Z program itself will execute in. In addition, since it is a
Z complete package with a specific user interface, all
Z programs which use it will be provided with similar
Z debugging capabilities. This is in sharp contrast to other
Z
Z
Z __________
Z
Z 1. UNIX is a trademark of AT&T Bell Laboratories.
Z
Z
Z
Z
Z - 1 -
Z
Z
Z
Z
Z
Z
Z
Z DBUG User Manual (preliminary) December 11, 1985
Z
Z
Z
Z forms of internal instrumentation where each developer has
Z their own, usually less capable, form of internal debugger.
Z In summary, because _d_b_u_g is an internal debugger it provides
Z consistency across operating environments, and because it is
Z available to all developers it provides consistency across
Z all programs in the same environment.
Z
Z
Z The _d_b_u_g package imposes only a slight speed penalty on
Z executing programs, typically much less than 10 percent, and
Z a modest size penalty, typically 10 to 20 percent. By
Z defining a specific C preprocessor symbol both of these can
Z be reduced to zero with no changes required to the source
Z code.
Z
Z
Z The following list is a quick summary of the
Z capabilities of the _d_b_u_g package. Each capability can be
Z individually enabled or disabled at the time a program is
Z invoked by specifying the appropriate command line
Z arguments.
Z
Z o Execution trace showing function level control
Z flow in a semi-graphically manner using
Z indentation to indicate nesting depth.
Z
Z o Output the values of all, or any subset of, key
Z internal variables.
Z
Z o Limit actions to a specific set of named
Z functions.
Z
Z o Limit function trace to a specified nesting depth.
Z
Z o Label each output line with source file name and
Z line number.
Z
Z o Label each output line with name of current
Z process.
Z
Z o Push or pop internal debugging state to allow
Z execution with built in debugging defaults.
Z
Z o Redirect the debug output stream to standard
Z output (stdout) or a named file. The default
Z output stream is standard error (stderr). The
Z redirection mechanism is completely independent of
Z normal command line redirection to avoid output
Z conflicts.
Z
Z
Z
Z
Z
Z - 2 -
Z
Z
Z
Z
Z
Z
Z
Z DBUG User Manual (preliminary) December 11, 1985
Z
Z
Z
Z PPPPRRRRIIIIMMMMIIIITTTTIIIIVVVVEEEE DDDDEEEEBBBBUUUUGGGGGGGGIIIINNNNGGGG TTTTEEEECCCCHHHHNNNNIIIIQQQQUUUUEEEESSSS
Z
Z
Z Internal instrumentation is already a familiar concept
Z to most programmers, since it is usually the first debugging
Z technique learned. Typically, "print statements" are
Z inserted in the source code at interesting points, the code
Z is recompiled and executed, and the resulting output is
Z examined in an attempt to determine where the problem is.
Z
Z The procedure is iterative, with each iteration yielding
Z more and more output, and hopefully the source of the
Z problem is discovered before the output becomes too large to
Z deal with or previously inserted statements need to be
Z removed. Figure 1 is an example of this type of primitive
Z debugging technique.
Z
Z
Z
Z #include <stdio.h>
Z
Z main (argc, argv)
Z int argc;
Z char *argv[];
Z {
Z printf ("argv[0] = %d\n", argv[0]);
Z /*
Z * Rest of program
Z */
Z printf ("== done ==\n");
Z }
Z
Z
Z Figure 1
Z Primitive Debugging Technique
Z
Z
Z
Z
Z
Z Eventually, and usually after at least several
Z iterations, the problem will be found and corrected. At
Z this point, the newly inserted print statements must be
Z dealt with. One obvious solution is to simply delete them
Z all. Beginners usually do this a few times until they have
Z to repeat the entire process every time a new bug pops up.
Z The second most obvious solution is to somehow disable the
Z output, either through the source code comment facility,
Z creation of a debug variable to be switched on or off, or by
Z using the C preprocessor. Figure 2 is an example of all
Z three techniques.
Z
Z
Z
Z - 3 -
Z
Z
Z
Z
Z
Z
Z
Z DBUG User Manual (preliminary) December 11, 1985
Z
Z
Z
Z
Z
Z #include <stdio.h>
Z
Z int debug = 0;
Z
Z main (argc, argv)
Z int argc;
Z char *argv[];
Z {
Z /* printf ("argv = %x\n", argv) */
Z if (debug) printf ("argv[0] = %d\n", argv[0]);
Z /*
Z * Rest of program
Z */
Z #ifdef DEBUG
Z printf ("== done ==\n");
Z #endif
Z }
Z
Z
Z Figure 2
Z Debug Disable Techniques
Z
Z
Z
Z
Z
Z Each technique has its advantages and disadvantages
Z with respect to dynamic vs static activation, source code
Z overhead, recompilation requirements, ease of use, program
Z readability, etc. Overuse of the preprocessor solution
Z quickly leads to problems with source code readability and
Z maintainability when multiple ####iiiiffffddddeeeeffff symbols are to be
Z defined or undefined based on specific types of debug
Z desired. The source code can be made slightly more readable
Z by suitable indentation of the ####iiiiffffddddeeeeffff arguments to match the
Z indentation of the code, but not all C preprocessors allow
Z this. The only requirement for the standard UUUUNNNNIIIIXXXX C
Z preprocessor is for the '#' character to appear in the first
Z column, but even this seems like an arbitrary and
Z unreasonable restriction. Figure 3 is an example of this
Z usage.
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z - 4 -
Z
Z
Z
Z
Z
Z
Z
Z DBUG User Manual (preliminary) December 11, 1985
Z
Z
Z
Z
Z
Z #include <stdio.h>
Z
Z main (argc, argv)
Z int argc;
Z char *argv[];
Z {
Z # ifdef DEBUG
Z printf ("argv[0] = %d\n", argv[0]);
Z # endif
Z /*
Z * Rest of program
Z */
Z # ifdef DEBUG
Z printf ("== done ==\n");
Z # endif
Z }
Z
Z
Z Figure 3
Z More Readable Preprocessor Usage
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z - 5 -
Z
Z
Z
Z
Z
Z
Z
Z DBUG User Manual (preliminary) December 11, 1985
Z
Z
Z
Z FFFFUUUUNNNNCCCCTTTTIIIIOOOONNNN TTTTRRRRAAAACCCCEEEE EEEEXXXXAAAAMMMMPPPPLLLLEEEE
Z
Z
Z We will start off learning about the capabilities of
Z the _d_b_u_g package by using a simple minded program which
Z computes the factorial of a number. In order to better
Z demonstrate the function trace mechanism, this program is
Z implemented recursively. Figure 4 is the main function for
Z this factorial program.
Z
Z
Z
Z #include <stdio.h>
Z /* User programs should use <local/dbug.h> */
Z #include "dbug.h"
Z
Z main (argc, argv)
Z int argc;
Z char *argv[];
Z {
Z register int result, ix;
Z extern int factorial (), atoi ();
Z
Z DBUG_ENTER ("main");
Z DBUG_PROCESS (argv[0]);
Z for (ix = 1; ix < argc && argv[ix][0] == '-'; ix++) {
Z switch (argv[ix][1]) {
Z case '#':
Z DBUG_PUSH (&(argv[ix][2]));
Z break;
Z }
Z }
Z for (; ix < argc; ix++) {
Z DBUG_4 ("args", "argv[%d] = %s", ix, argv[ix]);
Z result = factorial (atoi (argv[ix]));
Z printf ("%d\n", result);
Z }
Z DBUG_RETURN (0);
Z }
Z
Z
Z Figure 4
Z Factorial Program Mainline
Z
Z
Z
Z
Z
Z The mmmmaaaaiiiinnnn function is responsible for processing any
Z command line option arguments and then computing and
Z printing the factorial of each non-option argument.
Z
Z
Z
Z - 6 -
Z
Z
Z
Z
Z
Z
Z
Z DBUG User Manual (preliminary) December 11, 1985
Z
Z
Z
Z First of all, notice that all of the debugger functions
Z are implemented via preprocessor macros. This does not
Z detract from the readability of the code and makes disabling
Z all debug compilation trivial (a single preprocessor symbol,
Z DDDDBBBBUUUUGGGG____OOOOFFFFFFFF, forces the macro expansions to be null).
Z
Z Also notice the inclusion of the header file ddddbbbbuuuugggg....hhhh
Z from the local header file directory. (The version included
Z here is the test version in the dbug source distribution
Z directory). This file contains all the definitions for the
Z debugger macros, which all have the form DDDDBBBBUUUUGGGG____XXXXXXXX............XXXXXXXX.
Z
Z
Z The DDDDBBBBUUUUGGGG____EEEENNNNTTTTEEEERRRR macro informs that debugger that we have
Z entered the function named mmmmaaaaiiiinnnn. It must be the very first
Z "executable" line in a function, after all declarations and
Z before any other executable line. The DDDDBBBBUUUUGGGG____PPPPRRRROOOOCCCCEEEESSSSSSSS macro is
Z generally used only once per program to inform the debugger
Z what name the program was invoked with. The DDDDBBBBUUUUGGGG____PPPPUUUUSSSSHHHH macro
Z modifies the current debugger state by saving the previous
Z state and setting a new state based on the control string
Z passed as its argument. The DDDDBBBBUUUUGGGG____4444 macro is used to print
Z the values of each argument for which a factorial is to be
Z computed. The DDDDBBBBUUUUGGGG____RRRREEEETTTTUUUURRRRNNNN macro tells the debugger that the
Z end of the current function has been reached and returns a
Z value to the calling function. All of these macros will be
Z fully explained in subsequent sections.
Z
Z To use the debugger, the factorial program is invoked
Z with a command line of the form:
Z
Z factorial -#d:t 1 2 3
Z
Z The mmmmaaaaiiiinnnn function recognizes the "-#d:t" string as a
Z debugger control string, and passes the debugger arguments
Z ("d:t") to the _d_b_u_g runtime support routines via the
Z DDDDBBBBUUUUGGGG____PPPPUUUUSSSSHHHH macro. This particular string enables output from
Z the DDDDBBBBUUUUGGGG____4444 macro with the 'd' flag and enables function
Z tracing with the 't' flag. The factorial function is then
Z called three times, with the arguments "1", "2", and "3".
Z
Z
Z Debug control strings consist of a header, the "-#",
Z followed by a colon separated list of debugger arguments.
Z Each debugger argument is a single character flag followed
Z by an optional comma separated list of argments specific to
Z the given flag. Some examples are:
Z
Z -#d:t:o
Z -#d,in,out:f,main:F:L
Z
Z
Z
Z
Z - 7 -
Z
Z
Z
Z
Z
Z
Z
Z DBUG User Manual (preliminary) December 11, 1985
Z
Z
Z
Z Note that previously enabled debugger actions can be
Z disabled by the control string "-#".
Z
Z
Z The definition of the factorial function, symbolized as
Z "N!", is given by:
Z
Z N! = N * N-1 * ... 2 * 1
Z
Z Figure 5 is the factorial function which implements this
Z algorithm recursively. Note that this is not necessarily
Z the best way to do factorials and error conditions are
Z ignored completely.
Z
Z
Z
Z #include <stdio.h>
Z /* User programs should use <local/dbug.h> */
Z #include "dbug.h"
Z
Z int factorial (value)
Z register int value;
Z {
Z DBUG_ENTER ("factorial");
Z DBUG_3 ("find", "find %d factorial", value);
Z if (value > 1) {
Z value *= factorial (value - 1);
Z }
Z DBUG_3 ("result", "result is %d", value);
Z DBUG_RETURN (value);
Z }
Z
Z
Z Figure 5
Z Factorial Function
Z
Z
Z
Z
Z
Z One advantage (some may not consider it so) to using
Z the _d_b_u_g package is that it strongly encourages fully
Z structured coding with only one entry and one exit point in
Z each function. Multiple exit points, such as early returns
Z to escape a loop, may be used, but each such point requires
Z the use of an appropriate DDDDBBBBUUUUGGGG____RRRREEEETTTTUUUURRRRNNNN or DDDDBBBBUUUUGGGG____VVVVOOOOIIIIDDDD____RRRREEEETTTTUUUURRRRNNNN
Z macro.
Z
Z
Z To build the factorial program on a UUUUNNNNIIIIXXXX system,
Z compile and link with the command:
Z
Z
Z
Z - 8 -
Z
Z
Z
Z
Z
Z
Z
Z DBUG User Manual (preliminary) December 11, 1985
Z
Z
Z
Z cc -o factorial main.c factorial.c -ldbug
Z
Z The "-ldbug" argument tells the loader to link in the
Z runtime support modules for the _d_b_u_g package. Executing the
Z factorial program with a command of the form:
Z
Z factorial 1 2 3 4 5
Z
Z generates the output shown in figure 6.
Z
Z
Z
Z 1
Z 2
Z 6
Z 24
Z 120
Z
Z
Z Figure 6
Z factorial 1 2 3 4 5
Z
Z
Z
Z
Z
Z Function level tracing is enabled by passing the
Z debugger the 't' flag in the debug control string. Figure 7
Z is the output resulting from the command "factorial -
Z #t:o 3 2".
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z - 9 -
Z
Z
Z
Z
Z
Z
Z
Z DBUG User Manual (preliminary) December 11, 1985
Z
Z
Z
Z
Z
Z | >factorial
Z | | >factorial
Z | | <factorial
Z | <factorial
Z 2
Z | >factorial
Z | | >factorial
Z | | | >factorial
Z | | | <factorial
Z | | <factorial
Z | <factorial
Z 6
Z <main
Z
Z
Z Figure 7
Z factorial -#t:o 3 2
Z
Z
Z
Z
Z
Z Each entry to or return from a function is indicated by
Z '>' for the entry point and '<' for the exit point,
Z connected by vertical bars to allow matching points to be
Z easily found when separated by large distances.
Z
Z
Z This trace output indicates that there was an initial
Z call to factorial from main (to compute 2!), followed by a
Z single recursive call to factorial to compute 1!. The main
Z program then output the result for 2! and called the
Z factorial function again with the second argument, 3.
Z Factorial called itself recursively to compute 2! and 1!,
Z then returned control to main, which output the value for 3!
Z and exited.
Z
Z
Z Note that there is no matching entry point "main>" for
Z the return point "<main" because at the time the DDDDBBBBUUUUGGGG____EEEENNNNTTTTEEEERRRR
Z macro was reached in main, tracing was not enabled yet. It
Z was only after the macro DDDDBBBBUUUUGGGG____PPPPUUUUSSSSHHHH was executing that
Z tracing became enabled. This implies that the argument list
Z should be processed as early as possible since all code
Z preceding the first call to DDDDBBBBUUUUGGGG____PPPPUUUUSSSSHHHH is essentially
Z invisible to ddddbbbbuuuugggg (this can be worked around by inserted a
Z temporary DDDDBBBBUUUUGGGG____PPPPUUUUSSSSHHHH((((aaaarrrrggggvvvv[[[[1111]]]])))) immediately after the
Z DDDDBBBBUUUUGGGG____EEEENNNNTTTTEEEERRRR((((""""mmmmaaaaiiiinnnn"""")))) macro.
Z
Z
Z
Z
Z - 10 -
Z
Z
Z
Z
Z
Z
Z
Z DBUG User Manual (preliminary) December 11, 1985
Z
Z
Z
Z One last note, the trace output normally comes out on
Z the standard error. Since the factorial program prints its
Z result on the standard output, there is the possibility of
Z the output on the terminal being scrambled if the two
Z streams are not synchronized. Thus the debugger is told to
Z write its output on the standard output instead, via the 'o'
Z flag character. Note that no 'o' implies the default
Z (standard error), a 'o' with no arguments means standard
Z output, and a 'o' with an argument means used the named
Z file. I.E, "factorial -#t:o,logfile 3 2" would write the
Z trace output in "logfile". Because of UUUUNNNNIIIIXXXX implementation
Z details, programs usually run faster when writing to stdout
Z rather than stderr, though this is not a prime consideration
Z in this example.
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z - 11 -
Z
Z
Z
Z
Z
Z
Z
Z DBUG User Manual (preliminary) December 11, 1985
Z
Z
Z
Z UUUUSSSSEEEE OOOOFFFF DDDDBBBBUUUUGGGG____NNNN MMMMAAAACCCCRRRROOOOSSSS
Z
Z
Z The mechanism used to produce "printf" style output is
Z the DDDDBBBBUUUUGGGG____NNNN macro, where NNNN is replaced by the matching number
Z of arguments to the macro. Unfortunately, the standard UUUUNNNNIIIIXXXX
Z C preprocessor does not allow macros to have variable number
Z of arguments. If it did, then a single macro (such as
Z DBUG_PRINTF) could replace all the DDDDBBBBUUUUGGGG____NNNN macros.
Z
Z
Z To allow selection of output from specific macros, the
Z first argument to every DDDDBBBBUUUUGGGG____NNNN macro is a _d_b_u_g keyword.
Z When this keyword appears in the argument list of the 'd'
Z flag in a debug control string, as in "-
Z #d,keyword1,keyword2,...:t", output from the corresponding
Z macro is enabled. The default when there is no 'd' flag in
Z the control string is to enable output from all DDDDBBBBUUUUGGGG____NNNN
Z macros.
Z
Z
Z Typically, a program will be run once, with no keywords
Z specified, to determine what keywords are significant for
Z the current problem (the keywords are printed in the macro
Z output line). Then the program will be run again, with the
Z desired keywords, to examine only specific areas of
Z interest.
Z
Z
Z The rest of the argument list to a DDDDBBBBUUUUGGGG____NNNN is a standard
Z printf style format string and one or more arguments to
Z print. Note that no explicit newline is required at the end
Z of the format string. As a matter of style, two or three
Z small DDDDBBBBUUUUGGGG____NNNN macros are preferable to a single macro with a
Z huge format string. Figure 8 shows the output for default
Z tracing and debug.
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z - 12 -
Z
Z
Z
Z
Z
Z
Z
Z DBUG User Manual (preliminary) December 11, 1985
Z
Z
Z
Z
Z
Z | args: argv[2] = 3
Z | >factorial
Z | | find: find 3 factorial
Z | | >factorial
Z | | | find: find 2 factorial
Z | | | >factorial
Z | | | | find: find 1 factorial
Z | | | | result: result is 1
Z | | | <factorial
Z | | | result: result is 2
Z | | <factorial
Z | | result: result is 6
Z | <factorial
Z 6
Z <main
Z
Z
Z Figure 8
Z factorial -#d:t:o 3
Z
Z
Z
Z
Z
Z The output from the DDDDBBBBUUUUGGGG____NNNN macro is indented to match
Z the trace output for the function in which the macro occurs.
Z When debugging is enabled, but not trace, the output starts
Z at the left margin, without indentation.
Z
Z
Z To demonstrate selection of specific macros for output,
Z figure 9 shows the result when the factorial program is
Z invoked with the debug control string "-#d,result:o".
Z
Z
Z
Z factorial: result: result is 1
Z factorial: result: result is 2
Z factorial: result: result is 6
Z factorial: result: result is 24
Z 24
Z
Z
Z Figure 9
Z factorial -#d,result:o 4
Z
Z
Z
Z
Z
Z
Z
Z - 13 -
Z
Z
Z
Z
Z
Z
Z
Z DBUG User Manual (preliminary) December 11, 1985
Z
Z
Z
Z It is sometimes desirable to restrict debugging and
Z trace actions to a specific function or list of functions.
Z This is accomplished with the 'f' flag character in the
Z debug control string. Figure 10 is the output of the
Z factorial program when run with the control string "-
Z #d:f,factorial:F:L:o". The 'F' flag enables printing of the
Z source file name and the 'L' flag enables printing of the
Z source file line number.
Z
Z
Z
Z factorial.c: 9: factorial: find: find 3 factorial
Z factorial.c: 9: factorial: find: find 2 factorial
Z factorial.c: 9: factorial: find: find 1 factorial
Z factorial.c: 13: factorial: result: result is 1
Z factorial.c: 13: factorial: result: result is 2
Z factorial.c: 13: factorial: result: result is 6
Z 6
Z
Z
Z Figure 10
Z factorial -#d:f,factorial:F:L:o 3
Z
Z
Z
Z
Z
Z The output in figure 10 shows that the "find" macro is
Z in file "factorial.c" at source line 8 and the "result"
Z macro is in the same file at source line 12.
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z - 14 -
Z
Z
Z
Z
Z
Z
Z
Z DBUG User Manual (preliminary) December 11, 1985
Z
Z
Z
Z SSSSUUUUMMMMMMMMAAAARRRRYYYY OOOOFFFF MMMMAAAACCCCRRRROOOOSSSS
Z
Z
Z This section summarizes the usage of all currently
Z defined macros in the _d_b_u_g package. The macros definitions
Z are found in the user include file ddddbbbbuuuugggg....hhhh from the standard
Z include directory.
Z
Z
Z
Z DBUG_ENTER Used to tell the runtime support module
Z the name of the function being entered.
Z The argument must be of type "pointer to
Z character". The DBUG_ENTER macro must
Z precede all executable lines in the
Z function just entered, and must come
Z after all local declarations. Each
Z DBUG_ENTER macro must have a matching
Z DBUG_RETURN or DBUG_VOID_RETURN macro at
Z the function exit points. DBUG_ENTER
Z macros used without a matching
Z DBUG_RETURN or DBUG_VOID_RETURN macro
Z will cause warning messages from the
Z _d_b_u_g package runtime support module.
Z
Z EX: DBUG_ENTER ("main");
Z
Z DBUG_RETURN Used at each exit point of a function
Z containing a DBUG_ENTER macro at the
Z entry point. The argument is the value
Z to return. Functions which return no
Z value (void) should use the
Z DBUG_VOID_RETURN macro. It is an error
Z to have a DBUG_RETURN or
Z DBUG_VOID_RETURN macro in a function
Z which has no matching DBUG_ENTER macro,
Z and the compiler will complain if the
Z macros are actually used (expanded).
Z
Z EX: DBUG_RETURN (value);
Z EX: DBUG_VOID_RETURN;
Z
Z DBUG_PROCESS Used to name the current process being
Z executed. A typical argument for this
Z macro is "argv[0]", though it will be
Z perfectly happy with any other string.
Z
Z EX: DBUG_PROCESS (argv[0]);
Z
Z DBUG_PUSH Sets a new debugger state by pushing the
Z current ddddbbbbuuuugggg state onto an internal
Z
Z
Z
Z - 15 -
Z
Z
Z
Z
Z
Z
Z
Z DBUG User Manual (preliminary) December 11, 1985
Z
Z
Z
Z stack and setting up the new state using
Z the debug control string passed as the
Z macro argument. The most common usage
Z is to set the state specified by a debug
Z control string retrieved from the
Z argument list. Note that the leading
Z "-#" in a debug control string specified
Z as a command line argument must nnnnooootttt be
Z passed as part of the macro argument.
Z The proper usage is to pass a pointer to
Z the first character aaaafffftttteeeerrrr the "-#"
Z string.
Z
Z EX: DBUG_PUSH ((argv[i][2]));
Z EX: DBUG_PUSH ("d:t");
Z EX: DBUG_PUSH ("");
Z
Z DBUG_POP Restores the previous debugger state by
Z popping the state stack. Attempting to
Z pop more states than pushed will be
Z ignored and no warning will be given.
Z The DBUG_POP macro has no arguments.
Z
Z EX: DBUG_POP ();
Z
Z DBUG_FILE The DBUG_FILE macro is used to do
Z explicit I/O on the debug output stream.
Z It is used in the same manner as the
Z symbols "stdout" and "stderr" in the
Z standard I/O package.
Z
Z EX: fprintf (DBUG_FILE, "Doing my own
Z I/O!0);
Z
Z DBUG_EXECUTE The DBUG_EXECUTE macro is used to
Z execute any arbitrary C code. The first
Z argument is the debug keyword, used to
Z trigger execution of the code specified
Z as the second argument. This macro must
Z be used cautiously because, like the
Z DBUG_N macros, it is automatically
Z selected by default whenever the 'd'
Z flag has no argument list (I.E., a "-
Z #d:t" control string).
Z
Z EX: DBUG_EXECUTE ("abort", abort ());
Z
Z DBUG_N Used to do printing via the "fprintf"
Z library function on the current debug
Z stream, DBUG_FILE. N may currently be a
Z number in the range 2-5, and specifies
Z
Z
Z
Z - 16 -
Z
Z
Z
Z
Z
Z
Z
Z DBUG User Manual (preliminary) December 11, 1985
Z
Z
Z
Z the number of arguments in the
Z corresponding macro. The first argument
Z is a debug keyword, the second is a
Z format string, and the remaining
Z arguments, if any, are the values to be
Z printed.
Z
Z EX: DBUG_2 ("eof", "end of file found");
Z EX: DBUG_3 ("type","type is %x", type);
Z EX: DBUG_4 ("stp", "%x -> %s", stp,
Z stp -> name);
Z
Z DBUG_SETJMP Used in place of the setjmp() function
Z to first save the current debugger state
Z and then execute the standard setjmp
Z call. This allows to the debugger to
Z restore it's state when the DBUG_LONGJMP
Z macro is used to invoke the standard
Z longjmp() call. Currently all instances
Z of DBUG_SETJMP must occur within the
Z same function and at the same function
Z nesting level.
Z
Z EX: DBUG_SETJMP (env);
Z
Z DBUG_LONGJMP Used in place of the longjmp() function
Z to first restore the previous debugger
Z state at the time of the last
Z DBUG_SETJMP and then execute the
Z standard longjmp() call. Note that
Z currently all DBUG_LONGJMP macros
Z restore the state at the time of the
Z last DBUG_SETJMP. It would be possible
Z to maintain separate DBUG_SETJMP and
Z DBUG_LONGJMP pairs by having the
Z debugger runtime support module use the
Z first argument to differentiate the
Z pairs.
Z
Z EX: DBUG_LONGJMP (env,val);
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z - 17 -
Z
Z
Z
Z
Z
Z
Z
Z DBUG User Manual (preliminary) December 11, 1985
Z
Z
Z
Z DDDDEEEEBBBBUUUUGGGG CCCCOOOONNNNTTTTRRRROOOOLLLL SSSSTTTTRRRRIIIINNNNGGGG
Z
Z
Z The debug control string is used to set the state of
Z the debugger via the DDDDBBBBUUUUGGGG____PPPPUUUUSSSSHHHH macro. This section
Z summarizes the currently available debugger options and the
Z flag characters which enable or disable them. Argument
Z lists enclosed in '[' and ']' are optional.
Z
Z
Z d[,keywords] Enable output from macros with
Z specified keywords. A null list of
Z keywords implies that all keywords are
Z selected.
Z
Z D[,time] Delay for specified time after each
Z output line, to let output drain.
Z Time is given in tenths of a second
Z (value of 10 is one second). Default
Z is zero.
Z
Z f[,functions] Limit debugger actions to the
Z specified list of functions. A null
Z list of functions implies that all
Z functions are selected.
Z
Z F Mark each debugger output line with
Z the name of the source file containing
Z the macro causing the output.
Z
Z L Mark each debugger output line with
Z the source file line number of the
Z macro causing the output.
Z
Z n Mark each debugger output line with
Z the current function nesting depth.
Z
Z N Sequentially number each debugger
Z output line starting at 1. This is
Z useful for reference purposes when
Z debugger output is interspersed with
Z program output.
Z
Z o[,file] Redirect the debugger output stream to
Z the specified file. The default
Z output stream is stderr. A null
Z argument list causes output to be
Z redirected to stdout.
Z
Z p[,processes] Limit debugger actions to the
Z specified processes. A null list
Z
Z
Z
Z - 18 -
Z
Z
Z
Z
Z
Z
Z
Z DBUG User Manual (preliminary) December 11, 1985
Z
Z
Z
Z implies all processes. This is useful
Z for processes which run child
Z processes. Note that each debugger
Z output line can be marked with the
Z name of the current process via the
Z 'P' flag. The process name must match
Z the argument passed to the
Z DDDDBBBBUUUUGGGG____PPPPRRRROOOOCCCCEEEESSSSSSSS macro.
Z
Z P Mark each debugger output line with
Z the name of the current process. Most
Z useful when used with a process which
Z runs child processes that are also
Z being debugged. Note that the parent
Z process must arrange for the debugger
Z control string to be passed to the
Z child processes.
Z
Z r Used in conjunction with the DDDDBBBBUUUUGGGG____PPPPUUUUSSSSHHHH
Z macro to reset the current indentation
Z level back to zero. Most useful with
Z DDDDBBBBUUUUGGGG____PPPPUUUUSSSSHHHH macros used to temporarily
Z alter the debugger state.
Z
Z t[,N] Enable function control flow tracing.
Z The maximum nesting depth is specified
Z by N, and defaults to 200.
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z - 19 -
Z
Z
Z
Z
Z
Z
Z
Z DBUG User Manual (preliminary) December 11, 1985
Z
Z
Z
Z HHHHIIIINNNNTTTTSSSS AAAANNNNDDDD MMMMIIIISSSSCCCCEEEELLLLLLLLAAAANNNNEEEEOOOOUUUUSSSS
Z
Z
Z One of the most useful capabilities of the _d_b_u_g package
Z is to compare the executions of a given program in two
Z different environments. This is typically done by executing
Z the program in the environment where it behaves properly and
Z saving the debugger output in a reference file. The program
Z is then run with identical inputs in the environment where
Z it misbehaves and the output is again captured in a
Z reference file. The two reference files can then be
Z differentially compared to determine exactly where execution
Z of the two processes diverges.
Z
Z
Z A related usage is regression testing where the
Z execution of a current version is compared against
Z executions of previous versions. This is most useful when
Z there are only minor changes.
Z
Z
Z It is not difficult to modify an existing compiler to
Z implement some of the functionality of the _d_b_u_g package
Z automatically, without source code changes to the program
Z being debugged. In fact, such changes were implemented in a
Z version of the Portable C Compiler by the author in less
Z than a day. However, it is strongly encouraged that all
Z newly developed code continue to use the debugger macros for
Z the portability reasons noted earlier. The modified
Z compiler should be used only for testing existing programs.
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z - 20 -
Z
Z
Z
Z
Z
Z
Z
Z DBUG User Manual (preliminary) December 11, 1985
Z
Z
Z
Z CCCCAAAAVVVVEEEEAAAATTTTSSSS
Z
Z
Z The _d_b_u_g package works best with programs which have
Z "line oriented" output, such as text processors, general
Z purpose utilities, etc. It can be interfaced with screen
Z oriented programs such as visual editors by redefining the
Z appropriate macros to call special functions for displaying
Z the debugger results. Of course, this caveat is not
Z applicable if the debugger output is simply dumped into a
Z file for post-execution examination.
Z
Z
Z Programs which use memory allocation functions other
Z than mmmmaaaalllllllloooocccc will usually have problems using the standard
Z _d_b_u_g package. The most common problem is multiply allocated
Z memory.
Z
Z
Z Beware that some of the macros are not context
Z independent. Some of them contain _i_f statements with no
Z _e_l_s_e statements. In particular, the following code segment
Z will not behave as expected:
Z
Z
Z
Z if (something_interesting)
Z DBUG_2 ("ins", "something interesting");
Z else
Z do_normal_processing ();
Z
Z
Z
Z The user code _e_l_s_e will bind to the macro's _i_f to produce
Z code equivalent to:
Z
Z
Z
Z if (something_interesting)
Z if (debugging_on)
Z printf ("something interesting");
Z else
Z do_normal_processing ();
Z
Z
Z
Z The author has received numerous suggestions for changes
Z which would eliminate this danger, most based on obscure
Z features of the language or preprocessor, but has rejected
Z most of these for portability or efficiency reasons. (The
Z author also considers it to be poor programming practice to
Z
Z
Z
Z - 21 -
Z
Z
Z
Z
Z
Z
Z
Z DBUG User Manual (preliminary) December 11, 1985
Z
Z
Z
Z write code with any control flow statements that do not use
Z braces.) However, if you absolutely must prevent this
Z behavior try changing the macro definitions to something of
Z the form:
Z
Z
Z
Z #define DBUG_2(keyword,format) \
Z do { \
Z if (_db_on_) { \
Z _db_printf_ (__LINE__, keyword, format); \
Z } \
Z } while (0)
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z - 22 -
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z D B U G
Z
Z C Program Debugging Package
Z
Z by
Z9
Z Fred Fish
Z9
Z
Z
Z _A_B_S_T_R_A_C_T
Z
Z
Z
Z This document introduces _d_b_u_g, a macro based C debugging
Z package which has proven to be a very flexible and useful
Z tool for debugging, testing, and porting C programs.
Z
Z
Z All of the features of the _d_b_u_g package can be enabled
Z or disabled dynamically at execution time. This means that
Z production programs will run normally when debugging is not
Z enabled, and eliminates the need to maintain two separate
Z versions of a program.
Z
Z
Z Many of the things easily accomplished with
Z conventional debugging tools, such as symbolic debuggers,
Z are difficult or impossible with this package, and vice
Z versa. Thus the _d_b_u_g package should _n_o_t be thought of as a
Z replacement or substitute for other debugging tools, but
Z simply as a useful _a_d_d_i_t_i_o_n to the program development and
Z maintenance environment.
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z
Z99
Z
Z
Z
Z
Z
Z
STUNKYFLUFF
set `sum user.t`
if test 14630 != $1
then
echo user.t: Checksum error. Is: $1, should be: 14630.
fi
echo ALL DONE BUNKY!
exit 0
More information about the Comp.sources.unix
mailing list