~drizzle-trunk/drizzle/development

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