1.\" @(#)user.r 1.13 10/29/86 2.\" 3.\" 2004-10-29: documented features implemented since 10/29/86 4.\" formatting cleanup 5.\" - Sergei Golubchik 6.\" 7.\" DBUG (Macro Debugger Package) nroff source 8.\" 9.\" nroff -mm user.r >user.t 10.\" groff -mm user.r >user.ps 11.\" 12.\" =================================================== 13.\" 14.\" === Some sort of black magic, but I forget... 15.tr ~ 16.\" === Hyphenation control (1 = on) 17.\".nr Hy 1 18.\" === Force all first level headings to start on new page 19.nr Ej 1 20.\" === Set for breaks after headings for levels 1-3 21.nr Hb 3 22.\" === Set for space after headings for levels 1-3 23.nr Hs 3 24.\" === Set standard indent for one/half inch 25.nr Si 10 26.\" === Set page header 27.PH "/DBUG User Manual//\*(DT/" 28.\" === Set page footer 29.PF "// - % - //" 30.\" === Set page offset 31.\".po 0.60i 32.\" === Set line length 33.\".ll 6.5i 34.TL 35.warn 0 36D B U G 37.P 0 38C Program Debugging Package 39.P 0 40by 41.AU "Fred Fish" 42.AF "" 43.SA 1 44.\" === All paragraphs indented. 45.nr Pt 1 46.AS 1 47This document introduces 48.I dbug , 49a macro based C debugging 50package which has proven to be a very flexible and useful tool 51for debugging, testing, and porting C programs. 52 53.P 54All of the features of the 55.I dbug 56package can be enabled or disabled dynamically at execution time. 57This means that production programs will run normally when 58debugging is not enabled, and eliminates the need to maintain two 59separate versions of a program. 60 61.P 62Many of the things easily accomplished with conventional debugging 63tools, such as symbolic debuggers, are difficult or impossible with this 64package, and vice versa. 65Thus the 66.I dbug 67package should 68.I not 69be thought of as a replacement or substitute for 70other debugging tools, but simply as a useful 71.I addition 72to the 73program development and maintenance environment. 74 75.AE 76.MT 4 77.SK 78.B 79INTRODUCTION 80.R 81 82.P 83Almost every program development environment worthy of the name 84provides some sort of debugging facility. 85Usually this takes the form of a program which is capable of 86controlling execution of other programs and examining the internal 87state of other executing programs. 88These types of programs will be referred to as external debuggers 89since the debugger is not part of the executing program. 90Examples of this type of debugger include the 91.B adb 92and 93.B sdb 94debuggers provided with the 95.B UNIX\*F 96.FS 97UNIX is a trademark of AT&T Bell Laboratories. 98.FE 99operating system. 100 101.P 102One of the problems associated with developing programs in an environment 103with good external debuggers is that developed programs tend to have 104little or no internal instrumentation. 105This is usually not a problem for the developer since he is, 106or at least should be, intimately familiar with the internal organization, 107data structures, and control flow of the program being debugged. 108It is a serious problem for maintenance programmers, who 109are unlikely to have such familiarity with the program being 110maintained, modified, or ported to another environment. 111It is also a problem, even for the developer, when the program is 112moved to an environment with a primitive or unfamiliar debugger, 113or even no debugger. 114 115.P 116On the other hand, 117.I dbug 118is an example of an internal debugger. 119Because it requires internal instrumentation of a program, 120and its usage does not depend on any special capabilities of 121the execution environment, it is always available and will 122execute in any environment that the program itself will 123execute in. 124In addition, since it is a complete package with a specific 125user interface, all programs which use it will be provided 126with similar debugging capabilities. 127This is in sharp contrast to other forms of internal instrumentation 128where each developer has their own, usually less capable, form 129of internal debugger. 130In summary, 131because 132.I dbug 133is an internal debugger it provides consistency across operating 134environments, 135and because it is available to all developers it provides 136consistency across all programs in the same environment. 137 138.P 139The 140.I dbug 141package imposes only a slight speed penalty on executing 142programs, typically much less than 10 percent, and a modest size 143penalty, typically 10 to 20 percent. 144By defining a specific C preprocessor symbol both of these 145can be reduced to zero with no changes required to the 146source code. 147 148.P 149The following list is a quick summary of the capabilities 150of the 151.I dbug 152package. 153Each capability can be individually enabled or disabled 154at the time a program is invoked by specifying the appropriate 155command line arguments. 156.SP 1 157.ML o 1i 158.LI 159Execution trace showing function level control flow in a 160semi-graphically manner using indentation to indicate nesting 161depth. 162.LI 163Output the values of all, or any subset of, key internal variables. 164.LI 165Limit actions to a specific set of named functions. 166.LI 167Limit function trace to a specified nesting depth. 168.LI 169Label each output line with source file name and line number. 170.LI 171Label each output line with name of current process. 172.LI 173Push or pop internal debugging state to allow execution with 174built in debugging defaults. 175.LI 176Redirect the debug output stream to standard output (stdout) 177or a named file. 178The default output stream is standard error (stderr). 179The redirection mechanism is completely independent of 180normal command line redirection to avoid output conflicts. 181.LE 182 183.SK 184.B 185PRIMITIVE DEBUGGING TECHNIQUES 186.R 187 188.P 189Internal instrumentation is already a familiar concept 190to most programmers, since it is usually the first debugging 191technique learned. 192Typically, "print\ statements" are inserted in the source 193code at interesting points, the code is recompiled and executed, 194and the resulting output is examined in an attempt to determine 195where the problem is. 196 197The procedure is iterative, with each iteration yielding more 198and more output, and hopefully the source of the problem is 199discovered before the output becomes too large to deal with 200or previously inserted statements need to be removed. 201Figure 1 is an example of this type of primitive debugging 202technique. 203.DS I N 204.SP 2 205\fC 206.so example1.r 207\fR 208.SP 2 209.ll -5 210.ce 211Figure 1 212.ce 213Primitive Debugging Technique 214.ll +5 215.SP 2 216.DE 217 218.P 219Eventually, and usually after at least several iterations, the 220problem will be found and corrected. 221At this point, the newly inserted print statements must be 222dealt with. 223One obvious solution is to simply delete them all. 224Beginners usually do this a few times until they have to 225repeat the entire process every time a new bug pops up. 226The second most obvious solution is to somehow disable 227the output, either through the source code comment facility, 228creation of a debug variable to be switched on or off, or by using the 229C preprocessor. 230Figure 2 is an example of all three techniques. 231.DS I N 232.SP 2 233\fC 234.so example2.r 235\fR 236.SP 2 237.ll -5 238.ce 239Figure 2 240.ce 241Debug Disable Techniques 242.ll +5 243.SP 2 244.DE 245 246.P 247Each technique has its advantages and disadvantages with respect 248to dynamic vs static activation, source code overhead, recompilation 249requirements, ease of use, program readability, etc. 250Overuse of the preprocessor solution quickly leads to problems with 251source code readability and maintainability when multiple 252.B #ifdef 253symbols are to be defined or undefined based on specific types 254of debug desired. 255The source code can be made slightly more readable by suitable indentation 256of the 257.B #ifdef 258arguments to match the indentation of the code, but 259not all C preprocessors allow this. 260The only requirement for the standard 261.B UNIX 262C preprocessor is for the '#' character to appear 263in the first column, but even this seems 264like an arbitrary and unreasonable restriction. 265Figure 3 is an example of this usage. 266.DS I N 267.SP 2 268\fC 269.so example3.r 270\fR 271.SP 2 272.ll -5 273.ce 274Figure 3 275.ce 276More Readable Preprocessor Usage 277.ll +5 278.SP 2 279.DE 280 281.SK 282.B 283FUNCTION TRACE EXAMPLE 284.R 285 286.P 287We will start off learning about the capabilities of the 288.I dbug 289package by using a simple minded program which computes the 290factorial of a number. 291In order to better demonstrate the function trace mechanism, this 292program is implemented recursively. 293Figure 4 is the main function for this factorial program. 294.DS I N 295.SP 2 296\fC 297.so main.r 298\fR 299.SP 2 300.ll -5 301.ce 302Figure 4 303.ce 304Factorial Program Mainline 305.ll +5 306.SP 2 307.DE 308 309.P 310The 311.B main 312function is responsible for processing any command line 313option arguments and then computing and printing the factorial of 314each non-option argument. 315.P 316First of all, notice that all of the debugger functions are implemented 317via preprocessor macros. 318This does not detract from the readability of the code and makes disabling 319all debug compilation trivial (a single preprocessor symbol, 320.B NDEBUG , 321forces the macro expansions to be null). 322.P 323Also notice the inclusion of the header file 324.B dbug.h 325from the local header file directory. 326(The version included here is the test version in the dbug source 327distribution directory). 328This file contains all the definitions for the debugger macros, which 329all have the form 330.B DBUG_XX...XX . 331 332.P 333The 334.B DBUG_ENTER 335macro informs that debugger that we have entered the 336function named 337.B main . 338It must be the very first "executable" line in a function, after 339all declarations and before any other executable line. 340The 341.B DBUG_PROCESS 342macro is generally used only once per program to 343inform the debugger what name the program was invoked with. 344The 345.B DBUG_PUSH 346macro modifies the current debugger state by 347saving the previous state and setting a new state based on the 348control string passed as its argument. 349The 350.B DBUG_PRINT 351macro is used to print the values of each argument 352for which a factorial is to be computed. 353The 354.B DBUG_RETURN 355macro tells the debugger that the end of the current 356function has been reached and returns a value to the calling 357function. 358All of these macros will be fully explained in subsequent sections. 359.P 360To use the debugger, the factorial program is invoked with a command 361line of the form: 362.DS CB N 363\fCfactorial -#d:t 1 2 3 364.DE 365The 366.B main 367function recognizes the "-#d:t" string as a debugger control 368string, and passes the debugger arguments ("d:t") to the 369.I dbug 370runtime support routines via the 371.B DBUG_PUSH 372macro. 373This particular string enables output from the 374.B DBUG_PRINT 375macro with the 'd' flag and enables function tracing with the 't' flag. 376The factorial function is then called three times, with the arguments 377"1", "2", and "3". 378Note that the DBUG_PRINT takes exactly 379.B two 380arguments, with the second argument (a format string and list 381of printable values) enclosed in parentheses. 382.P 383Debug control strings consist of a header, the "-#", followed 384by a colon separated list of debugger arguments. 385Each debugger argument is a single character flag followed 386by an optional comma separated list of arguments specific 387to the given flag. 388Some examples are: 389.DS CB N 390\fC 391-#d:t:o 392-#d,in,out:f,main:F:L 393.DE 394Note that previously enabled debugger actions can be disabled by the 395control string "-#". 396 397.P 398The definition of the factorial function, symbolized as "N!", is 399given by: 400.DS CB N 401N! = N * N-1 * ... 2 * 1 402.DE 403Figure 5 is the factorial function which implements this algorithm 404recursively. 405Note that this is not necessarily the best way to do factorials 406and error conditions are ignored completely. 407.DS I N 408.SP 2 409\fC 410.so factorial.r 411\fR 412.SP 2 413.ll -5 414.ce 415Figure 5 416.ce 417Factorial Function 418.ll +5 419.SP 2 420.DE 421 422.P 423One advantage (some may not consider it so) to using the 424.I dbug 425package is that it strongly encourages fully structured coding 426with only one entry and one exit point in each function. 427Multiple exit points, such as early returns to escape a loop, 428may be used, but each such point requires the use of an 429appropriate 430.B DBUG_RETURN 431or 432.B DBUG_VOID_RETURN 433macro. 434 435.P 436To build the factorial program on a 437.B UNIX 438system, compile and 439link with the command: 440.DS CB N 441\fCcc -o factorial main.c factorial.c -ldbug 442.DE 443The "-ldbug" argument tells the loader to link in the 444runtime support modules for the 445.I dbug 446package. 447Executing the factorial program with a command of the form: 448.DS CB N 449\fCfactorial 1 2 3 4 5 450.DE 451generates the output shown in figure 6. 452.DS I N 453.SP 2 454\fC 455.so output1.r 456\fR 457.SP 2 458.ll -5 459.ce 460Figure 6 461.ce 462\fCfactorial 1 2 3 4 5 463.ll +5 464.SP 2 465.DE 466 467.P 468Function level tracing is enabled by passing the debugger 469the 't' flag in the debug control string. 470Figure 7 is the output resulting from the command 471"factorial\ -#t:o\ 2\ 3". 472.DS I N 473.SP 2 474\fC 475.so output2.r 476\fR 477.SP 2 478.ll -5 479.ce 480Figure 7 481.ce 482\fCfactorial -#t:o 2 3 483.ll +5 484.SP 2 485.DE 486 487.P 488Each entry to or return from a function is indicated by '>' for the 489entry point and '<' for the exit point, connected by 490vertical bars to allow matching points to be easily found 491when separated by large distances. 492 493.P 494This trace output indicates that there was an initial call 495to factorial from main (to compute 2!), followed by 496a single recursive call to factorial to compute 1!. 497The main program then output the result for 2! and called the 498factorial function again with the second argument, 3. 499Factorial called itself recursively to compute 2! and 1!, then 500returned control to main, which output the value for 3! and exited. 501 502.P 503Note that there is no matching entry point "main>" for the 504return point "<main" because at the time the 505.B DBUG_ENTER 506macro was reached in main, tracing was not enabled yet. 507It was only after the macro 508.B DBUG_PUSH 509was executing that tracing became enabled. 510This implies that the argument list should be processed as early as 511possible since all code preceding the first call to 512.B DBUG_PUSH 513is 514essentially invisible to 515.I dbug 516(this can be worked around by 517inserting a temporary 518.B DBUG_PUSH(argv[1]) 519immediately after the 520.B DBUG_ENTER("main") 521macro. 522 523.P 524One last note, 525the trace output normally comes out on the standard error. 526Since the factorial program prints its result on the standard 527output, there is the possibility of the output on the terminal 528being scrambled if the two streams are not synchronized. 529Thus the debugger is told to write its output on the standard 530output instead, via the 'o' flag character. 531Note that no 'o' implies the default (standard error), a 'o' 532with no arguments means standard output, and a 'o' 533with an argument means used the named file. 534i.e, "factorial\ -#t:o,logfile\ 3\ 2" would write the trace 535output in "logfile". 536Because of 537.B UNIX 538implementation details, programs usually run 539faster when writing to stdout rather than stderr, though this 540is not a prime consideration in this example. 541 542.SK 543.B 544USE OF DBUG_PRINT MACRO 545.R 546 547.P 548The mechanism used to produce "printf" style output is the 549.B DBUG_PRINT 550macro. 551 552.P 553To allow selection of output from specific macros, the first argument 554to every 555.B DBUG_PRINT 556macro is a 557.I dbug 558keyword. 559When this keyword appears in the argument list of the 'd' flag in 560a debug control string, as in "-#d,keyword1,keyword2,...:t", 561output from the corresponding macro is enabled. 562The default when there is no 'd' flag in the control string is to 563enable output from all 564.B DBUG_PRINT 565macros. 566 567.P 568Typically, a program will be run once, with no keywords specified, 569to determine what keywords are significant for the current problem 570(the keywords are printed in the macro output line). 571Then the program will be run again, with the desired keywords, 572to examine only specific areas of interest. 573 574.P 575The second argument to a 576.B DBUG_PRINT 577macro is a standard printf style 578format string and one or more arguments to print, all 579enclosed in parentheses so that they collectively become a single macro 580argument. 581This is how variable numbers of printf arguments are supported. 582Also note that no explicit newline is required at the end of the format string. 583As a matter of style, two or three small 584.B DBUG_PRINT 585macros are preferable 586to a single macro with a huge format string. 587Figure 8 shows the output for default tracing and debug. 588.DS I N 589.SP 2 590\fC 591.so output3.r 592\fR 593.SP 2 594.ll -5 595.ce 596Figure 8 597.ce 598\fCfactorial -#d:t:o 3 599.ll +5 600.SP 2 601.DE 602 603.P 604The output from the 605.B DBUG_PRINT 606macro is indented to match the trace output 607for the function in which the macro occurs. 608When debugging is enabled, but not trace, the output starts at the left 609margin, without indentation. 610 611.P 612To demonstrate selection of specific macros for output, figure 6139 shows the result when the factorial program is invoked with 614the debug control string "-#d,result:o". 615.DS I N 616.SP 2 617\fC 618.so output4.r 619\fR 620.SP 2 621.ll -5 622.ce 623Figure 9 624.ce 625\fCfactorial -#d,result:o 4 626.ll +5 627.SP 2 628.DE 629 630.P 631It is sometimes desirable to restrict debugging and trace actions 632to a specific function or list of functions. 633This is accomplished with the 'f' flag character in the debug 634control string. 635Figure 10 is the output of the factorial program when run with the 636control string "-#d:f,factorial:F:L:o". 637The 'F' flag enables printing of the source file name and the 'L' 638flag enables printing of the source file line number. 639.DS I N 640.SP 2 641\fC 642.so output5.r 643\fR 644.SP 2 645.ll -5 646.ce 647Figure 10 648.ce 649\fCfactorial -#d:f,factorial:F:L:o 3 650.ll +5 651.SP 2 652.DE 653 654.P 655The output in figure 10 shows that the "find" macro is in file 656"factorial.c" at source line 8 and the "result" macro is in the same 657file at source line 12. 658 659.SK 660.B 661SUMMARY OF MACROS 662.R 663 664.P 665This section summarizes the usage of all currently defined macros 666in the 667.I dbug 668package. 669The macros definitions are found in the user include file 670.B dbug.h 671from the standard include directory. 672 673.SP 2 674.BL 20 675.LI DBUG_ENTER\ 676Used to tell the runtime support module the name of the function being 677entered. The argument must be of type "pointer to character". The 678DBUG_ENTER macro must precede all executable lines in the function 679just entered, and must come after all local declarations. Each 680DBUG_ENTER macro must have a matching DBUG_RETURN or DBUG_VOID_RETURN 681macro at the function exit points. DBUG_ENTER macros used without a 682matching DBUG_RETURN or DBUG_VOID_RETURN macro will cause warning 683messages from the 684.I dbug 685package runtime support module. 686.SP 1 687EX:\ \fCDBUG_ENTER\ ("main");\fR 688.SP 1 689.LI DBUG_RETURN\ 690Used at each exit point of a function containing a DBUG_ENTER macro at 691the entry point. The argument is the value to return. Functions 692which return no value (void) should use the DBUG_VOID_RETURN macro. 693It is an error to have a DBUG_RETURN or DBUG_VOID_RETURN macro in a 694function which has no matching DBUG_ENTER macro, and the compiler will 695complain if the macros are actually used (expanded). 696.SP 1 697EX:\ \fCDBUG_RETURN\ (value);\fR 698.br 699EX:\ \fCDBUG_VOID_RETURN;\fR 700.SP 1 701.LI DBUG_PROCESS\ 702Used to name the current process being executed. 703A typical argument for this macro is "argv[0]", though 704it will be perfectly happy with any other string. 705Im multi-threaded environment threads may have different names. 706.SP 1 707EX:\ \fCDBUG_PROCESS\ (argv[0]);\fR 708.SP 1 709.LI DBUG_PUSH\ 710Sets a new debugger state by pushing the current 711.I dbug 712state onto an internal stack and setting up the new state using the 713debug control string passed as the macro argument. The most common 714usage is to set the state specified by a debug control string 715retrieved from the argument list. If the control string is 716.I incremental, 717the new state is a copy of the old state, modified by the control 718string. 719.SP 1 720EX:\ \fCDBUG_PUSH\ (\&(argv[i][2]));\fR 721.br 722EX:\ \fCDBUG_PUSH\ ("d:t");\fR 723.br 724EX:\ \fCDBUG_PUSH\ ("");\fR 725.SP 1 726.LI DBUG_POP\ 727Restores the previous debugger state by popping the state stack. 728Attempting to pop more states than pushed will be ignored and no 729warning will be given. The DBUG_POP macro has no arguments. 730.SP 1 731EX:\ \fCDBUG_POP\ ();\fR 732.SP 1 733.LI DBUG_SET\ 734Modifies the current debugger state on top of the stack or pushes 735a new state if the current is set to the initial settings, using 736the debug control string passed as the macro argument. Unless 737.I incremental 738control string is used (see below), it's equivalent to a combination of 739DBUG_POP and DBUG_PUSH. 740.SP 1 741EX:\ \fCDBUG_SET\ ("d:t");\fR 742.br 743EX:\ \fCDBUG_SET\ ("+d,info");\fR 744.br 745EX:\ \fCDBUG_SET\ ("+t:-d");\fR 746.SP 1 747.LI DBUG_FILE\ 748The DBUG_FILE macro is used to do explicit I/O on the debug output 749stream. It is used in the same manner as the symbols "stdout" and 750"stderr" in the standard I/O package. 751.SP 1 752EX:\ \fCfprintf\ (DBUG_FILE,\ "Doing\ my\ own\ I/O!\\n");\fR 753.SP 1 754.LI DBUG_EXECUTE\ 755The DBUG_EXECUTE macro is used to execute any arbitrary C code. The 756first argument is the debug keyword, used to trigger execution of the 757code specified as the second argument. This macro must be used 758cautiously because, like the DBUG_PRINT macro, it is automatically 759selected by default whenever the 'd' flag has no argument list (i.e., 760a "-#d:t" control string). 761.SP 1 762EX:\ \fCDBUG_EXECUTE\ ("status",\ print_status\ ());\fR 763.SP 1 764.LI DBUG_EXECUTE_IF\ 765Works like DBUG_EXECUTE macro, but the code is 766.B not 767executed "by default", if the keyword is not explicitly listed in 768the 'd' flag. Used to conditionally execute "dangerous" actions, e.g 769to crash the program testing how recovery works, or to introduce an 770artificial delay checking for race conditions. 771.SP 1 772EX:\ \fCDBUG_EXECUTE_IF\ ("crashme",\ DBUG_ABORT()\ ());\fR 773.SP 1 774.LI DBUG_EVALUATE\ 775The DBUG_EVALUATE macro is similar to DBUG_EXECUTE, but it can be used in 776the expression context. The first argument is the debug keyword that is used to 777choose whether the second (keyword is enabled) or the third (keyword is not 778enabled) argument is evaluated. When 779.I dbug 780is compiled off, the third argument is evaluated. 781.SP 1 782EX:\fC 783.br 784 printf("Info-debug is %s", 785.br 786 DBUG_EVALUATE\ ("info", "ON", "OFF"));\fR 787.SP 1 788.LI DBUG_EVALUATE_IF\ 789Works like DBUG_EVALUATE macro, but the second argument is 790.B not 791evaluated, if the keyword is not explicitly listed in 792the 'd' flag. Like DBUG_EXECUTE_IF this could be used to conditionally execute 793"dangerous" actions. 794.SP 1 795EX:\fC 796.br 797 if (prepare_transaction () || 798.br 799 DBUG_EVALUATE ("crashme", (DBUG_ABORT(), 0), 0) || 800.br 801 commit_transaction () )\fR 802.SP 1 803.LI DBUG_PRINT\ 804Used to do printing via the "fprintf" library function on the current 805debug stream, DBUG_FILE. The first argument is a debug keyword, the 806second is a format string and the corresponding argument list. Note 807that the format string and argument list are all one macro argument 808and 809.B must 810be enclosed in parentheses. 811.SP 1 812EX:\ \fCDBUG_PRINT\ ("eof",\ ("end\ of\ file\ found"));\fR 813.br 814EX:\ \fCDBUG_PRINT\ ("type",\ ("type\ is\ %x", type));\fR 815.br 816EX:\ \fCDBUG_PRINT\ ("stp",\ ("%x\ ->\ %s", stp, stp\ ->\ name));\fR 817.SP 1 818.LI DBUG_DUMP\ 819Used to dump a memory block in hex via the "fprintf" library function 820on the current debug stream, DBUG_FILE. The first argument is a debug 821keyword, the second is a pointer to a memory to dump, the third is a 822number of bytes to dump. 823.SP 1 824EX: \fCDBUG_DBUG\ ("net",\ packet,\ len);\fR 825.SP 1 826.LI DBUG_SETJMP\ 827Used in place of the setjmp() function to first save the current 828debugger state and then execute the standard setjmp call. 829This allows to the debugger to restore its state when the 830DBUG_LONGJMP macro is used to invoke the standard longjmp() call. 831Currently all instances of DBUG_SETJMP must occur within the 832same function and at the same function nesting level. 833.SP 1 834EX: \fCDBUG_SETJMP\ (env);\fR 835.SP 1 836.LI DBUG_LONGJMP\ 837Used in place of the longjmp() function to first restore the 838previous debugger state at the time of the last DBUG_SETJMP 839and then execute the standard longjmp() call. 840Note that currently all DBUG_LONGJMP macros restore the state 841at the time of the last DBUG_SETJMP. 842It would be possible to maintain separate DBUG_SETJMP and DBUG_LONGJMP 843pairs by having the debugger runtime support module use the first 844argument to differentiate the pairs. 845.SP 1 846EX: \fCDBUG_LONGJMP\ (env,val);\fR 847.SP 1 848.LI DBUG_LOCK_FILE\ 849Used in multi-threaded environment to lock DBUG_FILE stream. 850It can be used, for example, in functions that need to write something to a 851debug stream more than in one fprintf() call and want to ensure that no other 852thread will write something in between. 853.SP 1 854EX:\fC 855.br 856 DBUG_LOCK_FILE; 857.br 858 fprintf (DBUG_FILE, "a=["); 859.br 860 for (int i=0; i < a_length; i++) 861.br 862 fprintf (DBUG_FILE, "0x%03x ", a[i]); 863.br 864 fprintf (DBUG_FILE, "]"); 865.br 866 DBUG_UNLOCK_FILE;\fR 867.SP 1 868.LI DBUG_UNLOCK_FILE\ 869Unlocks DBUG_FILE stream, that was locked with a DBUG_LOCK_FILE. 870.LI DBUG_ABORT\ 871This macro could be used instead of abort(). It flushes DBUG_FILE stream 872to ensure that no 873.I dbug 874output is lost and then calls abort(). 875.SP 1 876.LI DBUG_EXPLAIN\ 877Generates control string corresponding to the current debug state. 878The macro takes two arguments - a buffer to store the result string 879into and its length. The macro (which could be used as a function) 880returns 1 if the control string didn't fit into the buffer and was 881truncated and 0 otherwise. 882.SP 1 883EX:\fC 884.br 885 char buf[256]; 886.br 887 DBUG_EXPLAIN( buf, sizeof(buf) );\fR 888.SP 1 889.LI DBUG_SET_INITIAL\ 890.LI DBUG_EXPLAIN_INITIAL\ 891.br 892These two macros are identical to DBUG_SET and DBUG_EXPLAIN, but they 893operate on the debug state that any new thread starts from. 894Modifying 895.I initial 896value does not affect threads that are already running. Obviously, 897these macros are only useful in the multi-threaded environment. 898.LE 899 900.SK 901.B 902DEBUG CONTROL STRING 903.R 904 905.P 906The debug control string is used to set the state of the debugger 907via the 908.B DBUG_PUSH 909or 910.B DBUG_SET 911macros. Control string consists of colon separated flags. Colons 912that are part of ':\\', ':/', or '::' are not considered flag 913separators. A flag may take an argument or a list of arguments. 914If a control string starts from a '+' sign it works 915.I incrementally, 916that is, it can modify existing state without overriding it. Every 917flag may be preceded by a '+' or '-' to enable or disable a 918corresponding option in the debugger state or to add or remove 919arguments to the list. This section summarizes the currently available 920debugger options and the flag characters which enable or disable them. 921Argument lists enclosed in '[' and ']' are optional. 922.SP 2 923.BL 22 924.LI a[,file] 925Redirect the debugger output stream and append it to the specified 926file. The default output stream is stderr. A null argument list 927causes output to be redirected to stdout. 928.SP 1 929EX: \fCa,C:\\tmp\\log\fR 930.LI A[,file] 931Like 'a[,file]' but ensure that data are written after each write 932(this typically implies flush or close/reopen). It helps to get 933a complete log file in case of crashes. This mode is implicit in 934multi-threaded environment. 935.LI d[,keywords] 936Enable output from macros with specified keywords. 937Every keyword can be a 938.I glob(7) 939pattern. 940An empty list of keywords implies that all keywords are selected. 941.LI D[,time] 942Delay for specified time after each output line, to let output drain. 943Time is given in tenths of a second (value of 10 is one second). 944Default is zero. 945.LI f[,functions] 946Limit debugger actions to the specified list of functions. 947Every function can be a 948.I glob(7) 949pattern. 950An empty list of functions implies that all functions are selected. 951Every function in the list may optionally be followed by a '/' - 952this will implicitly select all the functions down the call stack. 953.SP 1 954EX: \fCf,func1,func2/:-f,func3,func4/\fR 955.SP 1 956This would enable debugger in functions 'func1()', 'func2()' and all 957functions called from it (directly or indirectly). But not in 958functions 'func3()' or 'func4()' and all functions called from 959it. 960.LI F 961Mark each debugger output line with the name of the source file 962containing the macro causing the output. 963.LI i 964Mark each debugger output line with the PID (or thread ID) of the 965current process. 966.LI g,[functions] 967Enable profiling for the specified list of functions. 968Every function can be a 969.I glob(7) 970pattern. 971An empty list of functions enables profiling for all functions. 972See 973.B PROFILING\ WITH\ DBUG 974below. 975.LI L 976Mark each debugger output line with the source file line number of 977the macro causing the output. 978.LI n 979Mark each debugger output line with the current function nesting depth. 980.LI N 981Sequentially number each debugger output line starting at 1. 982This is useful for reference purposes when debugger output is 983interspersed with program output. 984.LI o[,file] 985Like 'a[,file]' but overwrite old file, do not append. 986.LI O[,file] 987Like 'A[,file]' but overwrite old file, do not append. 988.LI p[,processes] 989Limit debugger actions to the specified processes. 990Every name can be a 991.I glob(7) 992pattern. 993An empty list 994implies all processes. This is useful for processes which run child 995processes. Note that each debugger output line can be marked with the 996name of the current process via the 'P' flag. The process name must 997match the argument passed to the 998.B DBUG_PROCESS 999macro. 1000.LI P 1001Mark each debugger output line with the name of the current process. 1002Most useful when used with a process which runs child processes that 1003are also being debugged. Note that the parent process must arrange 1004for the debugger control string to be passed to the child processes. 1005.LI r 1006Used in conjunction with the 1007.B DBUG_PUSH 1008macro to reset the current 1009indentation level back to zero. 1010Most useful with 1011.B DBUG_PUSH 1012macros used to temporarily alter the 1013debugger state. 1014.LI t[,N] 1015Enable function control flow tracing. 1016The maximum nesting depth is specified by N, and defaults to 1017200. 1018.LI T 1019Mark each debugger output line with the current timestamp. 1020The value is printed with microsecond resolution, as returned by 1021.I gettimeofday() 1022system call. The actual resolution is OS- and hardware-dependent. 1023.LE 1024 1025.SK 1026.B 1027MULTI-THREADED DEBUGGING 1028.R 1029 1030.P 1031When 1032.I dbug 1033is used in a multi-threaded environment there are few differences from a single-threaded 1034case to keep in mind. This section tries to summarize them. 1035.SP 2 1036.BL 5 1037.LI 1038Every thread has its own stack of debugger states. 1039.B DBUG_PUSH 1040and 1041.B DBUG_POP 1042affect only the thread that executed them. 1043.LI 1044At the bottom of the stack for all threads there is the common 1045.I initial 1046state. Changes to this state (for example, with 1047.B DBUG_SET_INITIAL 1048macro) affect all new threads and all running threads that didn't 1049.B DBUG_PUSH 1050yet. 1051.LI 1052Every thread can have its own name, that can be set with 1053.B DBUG_PROCESS 1054macro. Thus, "-#p,name1,name2" can be used to limit the output to specific threads. 1055.LI 1056When printing directly to 1057.B DBUG_FILE 1058it may be necessary to prevent other threads from writing something between two parts 1059of logically indivisible output. It is done with 1060.B DBUG_LOCK_FILE 1061and 1062.B DBUG_UNLOCK_FILE 1063macors. See the appropriate section for examples. 1064.LI 1065"-#o,file" and "-#O,file" are treated as "-#a,file" and "-#A,file" respectively. That is 1066all writes to a file are always followed by a flush. 1067.LI 1068"-#i" prints not a PID but a thread id in the form of "T@nnn" 1069.LE 1070 1071.SK 1072.B 1073PROFILING WITH DBUG 1074.R 1075 1076.P 1077With 1078.I dbug 1079one can do profiling in a machine independent fashion, 1080without a need for profiled version of system libraries. 1081For this, 1082.I dbug 1083can write out a file 1084called 1085.B dbugmon.out 1086(by default). This is an ascii file containing lines of the form: 1087.DS CB N 1088\fC<function-name> E <time-entered> 1089<function-name> X <time-exited> 1090.DE 1091 1092.P 1093A second program (\fBanalyze\fR) reads this file, and produces a report on 1094standard output. 1095 1096.P 1097Profiling is enabled through the 1098.B g 1099flag. It can take a list of 1100function names for which profiling is enabled. By default, it 1101profiles all functions. 1102 1103.P 1104The profile file is opened for appending. This 1105is in order that one can run a program several times, and get the 1106sum total of all the times, etc. 1107 1108.P 1109An example of the report generated follows: 1110.DS CB N 1111\fC 1112 Profile of Execution 1113 Execution times are in milliseconds 1114 1115 Calls Time 1116 ----- ---- 1117 Times Percentage Time Spent Percentage 1118Function Called of total in Function of total Importance 1119======== ====== ========== =========== ========== ========== 1120factorial 5 83.33 30 100.00 8333 1121main 1 16.67 0 0.00 0 1122======== ====== ========== =========== ========== 1123Totals 6 100.00 30 100.00 1124.DE 1125.P 1126As you can see, it's quite self-evident. The 1127.B Importance 1128column is a 1129metric obtained by multiplying the percentage of the calls and the percentage 1130of the time. Functions with higher 'importance' benefit the most from 1131being sped up. 1132 1133.P 1134As a limitation - setjmp/longjmp, or child processes, are ignored 1135for the time being. Also, profiling does not work 1136in a multi-threaded environment. 1137 1138.P 1139Profiling code is (c) Binayak Banerjee. 1140 1141.SK 1142.B 1143HINTS AND MISCELLANEOUS 1144.R 1145 1146.P 1147One of the most useful capabilities of the 1148.I dbug 1149package is to compare the executions of a given program in two 1150different environments. 1151This is typically done by executing the program in the environment 1152where it behaves properly and saving the debugger output in a 1153reference file. 1154The program is then run with identical inputs in the environment where 1155it misbehaves and the output is again captured in a reference file. 1156The two reference files can then be differentially compared to 1157determine exactly where execution of the two processes diverges. 1158 1159.P 1160A related usage is regression testing where the execution of a current 1161version is compared against executions of previous versions. 1162This is most useful when there are only minor changes. 1163 1164.P 1165It is not difficult to modify an existing compiler to implement 1166some of the functionality of the 1167.I dbug 1168package automatically, without source code changes to the 1169program being debugged. 1170In fact, such changes were implemented in a version of the 1171Portable C Compiler by the author in less than a day. 1172However, it is strongly encouraged that all newly 1173developed code continue to use the debugger macros 1174for the portability reasons noted earlier. 1175The modified compiler should be used only for testing existing 1176programs. 1177 1178.SK 1179.B 1180CAVEATS 1181.R 1182 1183.P 1184The 1185.I dbug 1186package works best with programs which have "line\ oriented" 1187output, such as text processors, general purpose utilities, etc. 1188It can be interfaced with screen oriented programs such as 1189visual editors by redefining the appropriate macros to call 1190special functions for displaying the debugger results. 1191Of course, this caveat is not applicable if the debugger output 1192is simply dumped into a file for post-execution examination. 1193 1194.P 1195Programs which use memory allocation functions other than 1196.B malloc 1197will usually have problems using the standard 1198.I dbug 1199package. 1200The most common problem is multiply allocated memory. 1201.SP 2 1202.\" .DE nroff dident like this. davida 900108 1203.CS 1204 1205.\" vim:filetype=nroff 1206