~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to dbug/user.r

  • Committer: Brian Aker
  • Date: 2008-07-18 20:10:26 UTC
  • mfrom: (51.3.29 remove-dbug)
  • Revision ID: brian@tangent.org-20080718201026-tto5golt0xhwqe4a
Merging in Jay's final patch on dbug.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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