~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to dbug/user.r

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

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