]> git.lizzy.rs Git - plan9front.git/blob - sys/doc/acidpaper.ms
audio/flacenc
[plan9front.git] / sys / doc / acidpaper.ms
1 .HTML "Acid: A Debugger Built From A Language
2 .TL
3 Acid: A Debugger Built From A Language
4 .AU
5 Phil Winterbottom
6 philw@plan9.bell-labs.com
7 .AB
8 .FS
9 Originally appeared in
10 .I
11 Proc. of the Winter 1994 USENIX Conf.,
12 .R
13 pp. 211-222,
14 San Francisco, CA
15 .FE
16 Acid is an unusual source-level symbolic debugger for Plan 9. It is implemented
17 as a language interpreter with specialized primitives that provide
18 debugger support.  Programs written in the language manipulate
19 one or more target processes; variables in the language represent the
20 symbols, state, and resources of those processes. 
21 This structure allows complex
22 interaction between the debugger and the target program and
23 provides a convenient method of parameterizing differences between
24 machine architectures.
25 Although some effort is required to learn
26 the debugging language, the richness and flexibility of the
27 debugging environment encourages new ways of reasoning about the way
28 programs run and the conditions under which they fail.
29 .AE
30 .NH
31 Introduction
32 .PP
33 The size and complexity
34 of programs have increased in proportion to processor speed and memory but
35 the interface between debugger and programmer has changed little.
36 Graphical user interfaces have eased some of the tedious
37 aspects of the interaction. A graphical interface is a convenient
38 means for navigating through source and data structures but provides
39 little benefit for process control.
40 The introduction of a new concurrent language, Alef [Win93], emphasized the
41 inadequacies of the existing Plan 9 [Pike90] debugger
42 .I db ,
43 a distant relative of
44 .I adb ,
45 and made it clear that a new debugger was required.
46 .PP
47 Current debuggers like
48 .I dbx ,
49 .I sdb ,
50 and
51 .I gdb
52 are limited to answering only the questions their authors
53 envisage.  As a result, they supply a plethora
54 of specialized commands, each attempting to anticipate
55 a specific question a user may ask.
56 When a debugging situation arises that is beyond the scope
57 of the command set, the tool is useless.
58 Further,
59 it is often tedious or impossible to reproduce an anomalous state
60 of the program, especially when
61 the state is embedded in the program's data structures.
62 .PP
63 Acid applies some ideas found in CAD software used for
64 hardware test and simulation.
65 It is based on the notion that the state and resources of a program
66 are best represented and manipulated by a language. The state and resources,
67 such as memory, registers, variables, type information and source code
68 are represented by variables in the language.
69 Expressions provide a computation mechanism and control
70 statements allow repetitive or selective interpretation based
71 on the result of expression evaluation.
72 The heart of the Acid debugger is an interpreter for a small typeless
73 language whose operators mirror the operations
74 of C and Alef, which in turn correspond well to the basic operations of
75 the machine. The interpreter itself knows nothing of the underlying
76 hardware; it deals with the program state and resources
77 in the abstract.
78 Fundamental routines to control
79 processes, read files, and interface to the system are implemented
80 as builtin functions available to the interpreter.
81 The actual debugger functionality is coded
82 in Acid; commands are implemented as Acid functions.
83 .PP
84 This language-based approach has several advantages.
85 Most importantly, programs written in Acid, including most of the
86 debugger itself, are inherently portable.
87 Furthermore, Acid avoids the limitations other debuggers impose when
88 debugging parallel programs.  Instead of embedding a fixed
89 process model in the debugger, Acid allows the
90 programmer to adapt the debugger to handle an
91 arbitrary process partitioning or program structure. 
92 The ability to
93 interact dynamically with an executing process provides clear advantages
94 over debuggers constrained to probe a static image.
95 Finally, the Acid language is a powerful vehicle for expressing
96 assertions about logic, process state, and the contents of data structures.
97 When combined with dynamic interaction it allows a
98 limited form of automated program verification without requiring
99 modification or recompilation of the source code.
100 The language is also an
101 excellent vehicle for preserving a test suite for later regression testing.
102 .PP
103 The debugger may be customized by its users; standard
104 functions may be modified or extended to suit a particular application
105 or preference.
106 For example, the kernel developers in our group require a
107 command set supporting assembler-level debugging while the application
108 programmers prefer source-level functionality.
109 Although the default library is biased toward assembler-level debugging,
110 it is easily modified to provide a convenient source-level interface.
111 The debugger itself does not change; the user combines primitives
112 and existing Acid functions in different ways to
113 implement the desired interface.
114 .NH
115 Related Work
116 .PP
117 DUEL [Gol93], an extension to
118 .I gdb
119 [Stal91], proposes using a high level expression evaluator to solve
120 some of these problems. The evaluator provides iterators to loop over data
121 structures and conditionals to control evaluation of expressions.
122 The author shows that complex state queries can be formulated
123 by combining concise expressions but this only addresses part of the problem.
124 A program is a dynamic entity; questions asked when the program is in
125 a static state are meaningful only after the program has been `caught' in
126 that state. The framework for manipulating the program is still as
127 primitive as the underlying debugger. While DUEL provides a means to
128 probe data structures it entirely neglects the most beneficial aspect
129 of debugging languages: the ability to control processes. Acid is structured
130 around a thread of control that passes between the interpreter and the
131 target program.
132 .PP
133 The NeD debugger [May92] is a set of extensions to TCL [Ous90] that provide
134 debugging primitives. The resulting language, NeDtcl, is used to implement
135 a portable interface between a conventional debugger, pdb [May90], and
136 a server that executes NeDtcl programs operating on the target program.
137 Execution of the NeDtcl programs implements the debugging primitives
138 that pdb expects.
139 NeD is targeted at multi-process debugging across a network,
140 and proves the flexibility of a language as a means of
141 communication between debugging tools. Whereas NeD provides an interface
142 between a conventional debugger and the process it debugs, Acid is the
143 debugger itself. While NeD has some of the ideas
144 found in Acid it is targeted toward a different purpose. Acid seeks to
145 integrate the manipulation of a program's resources into the debugger
146 while NeD provides a flexible interconnect between components of
147 the debugging environment. The choice of TCL is appropriate for its use
148 in NeD but is not suitable for Acid. Acid relies on the coupling of the type
149 system with expression evaluation, which are the root of its design,
150 to provide the debugging primitives.
151 .PP
152 Dalek [Ols90] is an event based language extension to gdb. State transitions
153 in the target program cause events to be queued for processing by the
154 debugging language.
155 .PP
156 Acid has many of the advantages of same process or
157 .I local
158 .I agent
159 debuggers, like Parasight [Aral], without the need for dynamic linking or
160 shared memory.
161 Acid improves on the ideas of these other systems by completely integrating
162 all aspects of the debugging process into the language environment. Of
163 particular importance is the relationship between Acid variables,
164 program symbols, source code, registers and type information. This
165 integration is made possible by the design of the Acid language.
166 .PP
167 Interpreted languages such as Lisp and Smalltalk are able to provide
168 richer debugging environments through more complete information than
169 their compiled counterparts. Acid is a means to gather and represent
170 similar information about compiled programs through cooperation
171 with the compilation tools and library implementers.
172 .NH
173 Acid the Language
174 .PP
175 Acid is a small interpreted language targeted to its debugging task.
176 It focuses on representing program state and addressing data rather than
177 expressing complex computations. Program state is
178 .I addressable
179 from an Acid program.
180 In addition to parsing and executing expressions and providing
181 an architecture-independent interface to the target process,
182 the interpreter supplies a mark-and-scan garbage collector
183 to manage storage.
184 .PP
185 Every Acid session begins with the loading of the Acid libraries.
186 These libraries contain functions, written in Acid, that provide
187 a standard debugging environment including breakpoint management,
188 stepping by instruction or statement, stack tracing, and
189 access to variables, memory, and registers.
190 The library contains 600 lines of Acid code and provides
191 functionality similar to
192 .I dbx .
193 Following the loading of the system library, Acid loads
194 user-specified libraries; this load sequence allows the
195 user to augment or override the standard commands
196 to customize the debugging environment.  When all libraries
197 are loaded, Acid issues an interactive prompt and begins
198 evaluating expressions entered by the user.  The Acid `commands'
199 are actually invocations of builtin primitives or previously defined
200 Acid functions. Acid evaluates each expression as it is entered and
201 prints the result.
202 .NH
203 Types and Variables
204 .PP
205 Acid variables are of four basic types:
206 .I integer ,
207 .I string ,
208 .I float ,
209 and
210 .I list .
211 The type of a variable is inferred by the type of the right-hand side of
212 an assignment expression.
213 Many of the operators can be applied to more than
214 one type; for these operators the action of the operator is determined
215 by the type of its operands.
216 For example,
217 the
218 .CW +
219 operator adds
220 .I integer
221 and
222 .I float
223 operands, and concatenates
224 .I string
225 and
226 .I list
227 operands.
228 Lists are the only complex type in Acid; there are no arrays, structures
229 or pointers. Operators provide
230 .CW head ,
231 .CW tail ,
232 .CW append
233 and
234 .CW delete
235 operations.
236 Lists can also be indexed like arrays.
237 .PP
238 Acid has two levels of scope: global and local.
239 Function parameters and variables declared in a function body
240 using the
241 .CW local
242 keyword are created at entry to the function and
243 exist for the lifetime of a function.
244 Global variables are created by assignment and need not be declared.
245 All variables and functions in the program
246 being debugged are entered in the Acid symbol table as global
247 variables during Acid initialization.
248 Conflicting variable names are resolved by prefixing enough `$' characters
249 to make them unique.
250 Syntactically, Acid variables and target program
251 symbols are referenced identically.
252 However, the variables are managed differently in the Acid
253 symbol table and the user must be aware of this distinction.
254 The value of an Acid variable is stored in the symbol
255 table; a reference returns the value.
256 The symbol table entry for a variable or function in the target
257 program contains the address of that symbol in the image
258 of the program.  Thus, the value of a program variable is
259 accessed by indirect reference through the Acid
260 variable that has the same name; the value of an Acid variable is the
261 address of the corresponding program variable.
262 .NH
263 Control Flow
264 .PP
265 The
266 .CW while
267 and
268 .CW loop
269 statements implement looping.
270 The former
271 is similar to the same statement in C.
272 The latter evaluates starting and ending expressions yielding
273 integers and iterates while an incrementing loop index
274 is within the bounds of those expressions.
275 .P1
276 acid: i = 0; loop 1,5 do print(i=i+1)
277 0x00000001
278 0x00000002
279 0x00000003
280 0x00000004
281 0x00000005
282 acid:
283 .P2
284 The traditional
285 .CW if-then-else 
286 statement implements conditional execution.
287 .NH
288 Addressing
289 .PP
290 Two indirection operators allow Acid to access values in
291 the program being debugged.
292 The
293 .CW *
294 operator fetches a value from the memory image of an
295 executing process;
296 the
297 .CW @
298 operator fetches a value from the text file of the process.
299 When either operator appears on the left side of an assignment, the value
300 is written rather than read.
301 .PP
302 The indirection operator must know the size of the object
303 referenced by a variable.
304 The Plan 9 compilers neglect to include this
305 information in the program symbol table, so Acid cannot
306 derive this information implicitly.
307 Instead Acid variables have formats.
308 The format is a code
309 letter specifying the printing style and the effect of some of the
310 operators on that variable.
311 The indirection operators look at the format code to determine the
312 number of bytes to read or write.
313 The format codes are derived from the format letters used by
314 .I db .
315 By default, symbol table variables and numeric constants
316 are assigned the format code
317 .CW 'X'
318 which specifies 32-bit hexadecimal.
319 Printing such a variable yields output of the form
320 .CW 0x00123456 .
321 An indirect reference through the variable fetches 32 bits
322 of data at the address indicated by the variable.
323 Other formats specify various data types, for example
324 .CW i
325 an instruction,
326 .CW D
327 a signed 32 bit decimal,
328 .CW s
329 a null-terminated string.
330 The
331 .CW fmt
332 function
333 allows the user to change the format code of a variable
334 to control the printing format and
335 operator side effects.
336 This function evaluates the expression supplied as the first
337 argument, attaches the format code supplied as the second
338 argument to the result and returns that value.
339 If the result is assigned to a variable,
340 the new format code applies to
341 that variable.  For convenience, Acid provides the
342 .CW \e
343 operator as a shorthand infix form of
344 .CW fmt .
345 For example:
346 .P1
347 acid: x=10
348 acid: x                          // print x in hex
349 0x0000000a 
350 acid: x = fmt(x, 'D')            // make x type decimal
351 acid: print(x, fmt(x, 'X'), x\eX) // print x in decimal & hex
352 10 0x0000000a 0x0000000a
353 acid: x                          // print x in decimal
354 10
355 acid: x\eo                       // print x in octal
356 000000000012
357 .P2
358 The 
359 .CW ++
360 and
361 .CW --
362 operators increment or decrement a variable by an amount
363 determined by its format code.  Some formats imply a non-fixed size.
364 For example, the
365 .CW i
366 format code disassembles an instruction into a string.
367 On a 68020, which has variable length instructions:
368 .P1
369 acid: p=main\ei                     // p=addr(main), type INST
370 acid: loop 1,5 do print(p\eX, @p++) // disassemble 5 instr's
371 0x0000222e LEA  0xffffe948(A7),A7
372 0x00002232 MOVL s+0x4(A7),A2
373 0x00002236 PEA  0x2f($0)
374 0x0000223a MOVL A2,-(A7)
375 0x0000223c BSR  utfrrune
376 acid:
377 .P2
378 Here,
379 .CW main
380 is the address of the function of the same name in the program under test.
381 The loop retrieves the five instructions beginning at that address and
382 then prints the address and the assembly language representation of each.
383 Notice that the stride of the increment operator varies with the size of
384 the instruction: the
385 .CW MOVL
386 at 
387 .CW 0x0000223a
388 is a two byte instruction while all others are four bytes long.
389 .PP
390 Registers are treated as normal program variables referenced
391 by their symbolic assembler language names.
392 When a
393 process stops, the register set is saved by the kernel
394 at a known virtual address in the process memory map.
395 The Acid variables associated with the registers point
396 to the saved values and the
397 .CW *
398 indirection operator can then be used to read and write the register set.
399 Since the registers are accessed via Acid variables they may
400 be used in arbitrary expressions.
401 .P1
402 acid: PC                            // addr of saved PC
403 0xc0000f60 
404 acid: *PC
405 0x0000623c                          // contents of PC
406 acid: *PC\ea
407 main
408 acid: *R1=10                        // modify R1
409 acid: asm(*PC+4)                    // disassemble @ PC+4
410 main+0x4 0x00006240     MOVW    R31,0x0(R29)
411 main+0x8 0x00006244     MOVW    $setR30(SB),R30
412 main+0x10 0x0000624c    MOVW    R1,_clock(SB)
413 .P2
414 Here, the saved
415 .CW PC
416 is stored at address
417 .CW 0xc0000f60 ;
418 its current content is
419 .CW 0x0000623c .
420 The
421 .CW a ' `
422 format code converts this value to a string specifying
423 the address as an offset beyond the nearest symbol.
424 After setting the value of register
425 .CW 1 ,
426 the example uses the
427 .CW asm
428 command to disassemble a short section of code beginning
429 at four bytes beyond the current value of the
430 .CW PC .
431 .NH
432 Process Interface
433 .PP
434 A program executing under Acid is monitored through the
435 .I proc
436 file system interface provided by Plan 9.
437 Textual messages written to the
438 .CW ctl
439 file control the execution of the process.
440 For example writing
441 .CW waitstop
442 to the control file causes the write to block until the target
443 process enters the kernel and is stopped. When the process is stopped
444 the write completes. The
445 .CW startstop
446 message starts the target process and then does a
447 .CW waitstop
448 action.
449 Synchronization between the debugger and the target process is determined
450 by the actions of the various messages. Some operate asynchronously to the
451 target process and always complete immediately, others block until the
452 action completes. The asynchronous messages allow Acid to control
453 several processes simultaneously.
454 .PP
455 The interpreter has builtin functions named after each of the control
456 messages. The functions take a process id as argument.
457 Any time a control message causes the program to execute instructions 
458 the interpreter performs two actions when the control operation has completed.
459 The Acid variables pointing at the register set are fixed up to point
460 at the saved registers, and then
461 the user defined function
462 .CW stopped
463 is executed.
464 The 
465 .CW stopped
466 function may print the current address,
467 line of source or instruction and return to interactive mode. Alternatively
468 it may traverse a complex data structure, gather statistics and then set
469 the program running again.
470 .PP
471 Several Acid variables are maintained by the debugger rather than the
472 programmer.
473 These variables allow generic Acid code to deal with the current process,
474 architecture specifics or the symbol table.
475 The variable
476 .CW pid
477 is the process id of the current process Acid is debugging.
478 The variable
479 .CW symbols
480 contains a list of lists where each sublist contains the symbol
481 name, its type and the value of the symbol.
482 The variable
483 .CW registers
484 contains a list of the machine-specific register names. Global symbols in the target program
485 can be referenced directly by name from Acid. Local variables
486 are referenced using the colon operator as \f(CWfunction:variable\fP.
487 .NH
488 Source Level Debugging
489 .PP
490 Acid provides several builtin functions to manipulate source code.
491 The
492 .CW file
493 function reads a text file, inserting each line into a list.
494 The
495 .CW pcfile
496 and
497 .CW pcline
498 functions each take an address as an argument.
499 The first
500 returns a string containing the name of the source file
501 and the second returns an integer containing the line number
502 of the source line containing the instruction at the address.
503 .P1
504 acid: pcfile(main)              // file containing main
505 main.c
506 acid: pcline(main)              // line # of main in source
507 11
508 acid: file(pcfile(main))[pcline(main)]  // print that line
509 main(int argc, char *argv[])
510 acid: src(*PC)                  // print statements nearby
511  9
512  10 void
513 >11 main(int argc, char *argv[])
514  12 {
515  13     int a;
516 .P2
517 In this example, the three primitives are combined in an expression to print
518 a line of source code associated with an address.
519 The
520 .CW src
521 function prints a few lines of source
522 around the address supplied as its argument. A companion routine,
523 .CW Bsrc ,
524 communicates with the external editor
525 .CW sam .
526 Given an address, it loads the corresponding source file into the editor
527 and highlights the line containing the address.  This simple interface
528 is easily extended to more complex functions.
529 For example, the
530 .CW step
531 function can select the current file and line in the editor
532 each time the target program stops, giving the user a visual
533 trace of the execution path of the program. A more complete interface
534 allowing two way communication between Acid and the
535 .CW acme
536 user interface [Pike93] is under construction. A filter between the debugger
537 and the user interface provides interpretation of results from both
538 sides of the interface. This allows the programming environment to
539 interact with the debugger and vice-versa, a capability missing from the
540 .CW sam
541 interface.
542 The
543 .CW src
544 and
545 .CW Bsrc
546 functions are both written in Acid code using the file and line primitives.
547 Acid provides library functions to step through source level
548 statements and functions. Furthermore, addresses in Acid expressions can be
549 specified by source file and line.
550 Source code is manipulated in the Acid
551 .I list
552 data type.
553 .NH
554 The Acid Library
555 .PP
556 The following examples define some useful commands and
557 illustrate the interaction of the debugger and the interpreter.
558 .P1
559 defn bpset(addr)                          // set breakpoint
560 {
561         if match(addr, bplist) >= 0 then
562                 print("bkpoint already set:", addr\ea, "\en");
563         else {
564                 *fmt(addr, bpfmt) = bpinst;   // plant it
565                 bplist = append bplist, addr; // add to list
566         }
567 }
568 .P2
569 The
570 .CW bpset
571 function plants a break point in memory. The function starts by
572 using the
573 .CW match
574 builtin to
575 search the breakpoint list to determine if a breakpoint is already
576 set at the address.
577 The indirection operator, controlled by the format code returned
578 by the
579 .CW fmt
580 primitive, is used to plant the breakpoint in memory.
581 The variables
582 .CW bpfmt
583 and
584 .CW bpinst
585 are Acid global variables containing the format code specifying
586 the size of the breakpoint instruction and the breakpoint instruction
587 itself.
588 These
589 variables are set by architecture-dependent library code
590 when the debugger first attaches to the executing image.
591 Finally the address of the breakpoint is
592 appended to the breakpoint list,
593 .CW bplist .
594 .P1
595 defn step()                             // single step
596 {
597         local lst, lpl, addr, bput;
598
599         bput = 0;                       // sitting on bkpoint
600         if match(*PC, bplist) >= 0 then {       
601                 bput = fmt(*PC, bpfmt); // save current addr
602                 *bput = @bput;          // replace it
603         }
604
605         lst = follow(*PC);              // get follow set
606
607         lpl = lst;
608         while lpl do {                  // place breakpoints
609                 *(head lpl) = bpinst;
610                 lpl = tail lpl;
611         }
612
613         startstop(pid);                 // do the step
614
615         while lst do {                  // remove breakpoints
616                 addr = fmt(head lst, bpfmt);
617                 *addr = @addr;          // replace instr.
618                 lst = tail lst;
619         }
620         if bput != 0 then
621                 *bput = bpinst;         // restore breakpoint
622 }
623 .P2
624 The
625 .CW step
626 function executes a single assembler instruction.
627 If the
628 .CW PC
629 is sitting
630 on a breakpoint, the address and size of
631 the breakpoint are saved.
632 The breakpoint instruction
633 is then removed using the
634 .CW @
635 operator to fetch
636 .CW bpfmt
637 bytes from the text file and to place it into the memory
638 of the executing process using the
639 .CW *
640 operator.
641 The
642 .CW follow
643 function is an Acid
644 builtin which returns a follow-set: a list of instruction addresses which
645 could be executed next.
646 If the instruction stored at the
647 .CW PC
648 is a branch instruction, the
649 list contains the addresses of the next instruction and
650 the branch destination; otherwise, it contains only the
651 address of the next instruction.
652 The follow-set is then used to replace each possible following
653 instruction with a breakpoint instruction.  The original
654 instructions need not be saved; they remain
655 in their unaltered state in the text file.
656 The
657 .CW startstop
658 builtin writes the `startstop' message to the
659 .I proc
660 control file for the process named
661 .CW pid .
662 The target process executes until some condition causes it to
663 enter the kernel, in this case, the execution of a breakpoint.
664 When the process blocks, the debugger regains control and invokes the
665 Acid library function
666 .CW stopped
667 which reports the address and cause of the blockage.
668 The
669 .CW startstop
670 function completes and returns to the
671 .CW step
672 function where
673 the follow-set is used to replace the breakpoints placed earlier.
674 Finally, if the address of the original
675 .CW PC
676 contained a breakpoint, it is replaced.
677 .PP
678 Notice that this approach to process control is inherently portable;
679 the Acid code is shared by the debuggers for all architectures.
680 Acid variables and builtin functions provide a transparent interface
681 to architecture-dependent values and functions.  Here the breakpoint
682 value and format are referenced through Acid variables and the
683 .CW follow
684 primitive masks the differences in the underlying instruction set.
685 .PP
686 The
687 .CW next
688 function, similar to the
689 .I dbx
690 command of the same name,
691 is a simpler example.
692 This function steps through
693 a single source statement but steps over function calls.
694 .P1
695 defn next()
696 {
697         local sp, bound;
698
699         sp = *SP;                       // save starting SP
700         bound = fnbound(*PC);           // begin & end of fn.
701         stmnt();                        // step 1 statement
702         pc = *PC;
703         if pc >= bound[0] && pc < bound[1] then
704                 return {};
705
706         while (pc<bound[0] || pc>bound[1]) && sp>=*SP do {
707                 step();
708                 pc = *PC;
709         }
710         src(*PC);
711 }
712 .P2
713 The
714 .CW next
715 function
716 starts by saving the current stack pointer in a local variable.
717 It then uses the Acid library function
718 .CW fnbound
719 to return the addresses of the first and last instructions in
720 the current function in a list.
721 The
722 .CW stmnt
723 function executes a single source statement and then uses
724 .CW src
725 to print a few lines of source around the new
726 .CW PC .
727 If the new value of the
728 .CW PC
729 remains in the current function,
730 .CW next
731 returns.
732 When the executed statement is a function call or a return
733 from a function, the new value of the
734 .CW PC
735 is outside the bounds calculated by
736 .CW fnbound 
737 and the test of the
738 .CW while
739 loop is evaluated.
740 If the statement was a return, the new value of the stack pointer
741 is greater than the original value and the loop completes without
742 execution.
743 Otherwise, the loop is entered and instructions are continually
744 executed until the value of the
745 .CW PC
746 is between the bounds calculated earlier.  At that point, execution
747 ceases and a few lines of source in the vicinity of the
748 .CW PC
749 are printed.
750 .PP
751 Acid provides concise and elegant expression for control and
752 manipulation of target programs. These examples demonstrate how a
753 few well-chosen primitives can be combined to create a rich debugging environment.
754 .NH
755 Dealing With Multiple Architectures
756 .PP
757 A single binary of Acid may be used to debug a program running on any
758 of the five processor architectures supported by Plan 9.  For example,
759 Plan 9 allows a user on a MIPS to import the
760 .I proc
761 file system from an i486-based PC and remotely debug a program executing
762 on that processor.
763 .PP
764 Two levels of abstraction provide this architecture independence.
765 On the lowest level, a Plan 9 library supplies functions to
766 decode the file header of the program being debugged and
767 select a table of system parameters
768 and a jump vector of architecture-dependent
769 functions based on the magic number.
770 Among these functions are byte-order-independent
771 access to memory and text files, stack manipulation, disassembly,
772 and floating point number interpretation.
773 The second level of abstraction is supplied by Acid.
774 It consists of primitives and approximately 200 lines
775 of architecture-dependent Acid library code that interface the
776 interpreter to the architecture-dependent library.
777 This layer performs functions such as mapping register names to
778 memory locations, supplying breakpoint values and sizes,
779 and converting processor specific data to Acid data types.
780 An example of the latter is the stack trace function
781 .CW strace ,
782 which uses the stack traversal functions in the
783 architecture-dependent library to construct a list of lists describing
784 the context of a process.  The first level of list selects
785 each function in the trace; subordinate lists contain the
786 names and values of parameters and local variables of
787 the functions.  Acid commands and library functions that
788 manipulate and display process state information operate
789 on the list representation and are independent of the
790 underlying architecture.
791 .NH
792 Alef Runtime
793 .PP
794 Alef is a concurrent programming language,
795 designed specifically for systems programming, which supports both
796 shared variable and message passing paradigms.
797 Alef borrows the C expression syntax but implements
798 a substantially different type system.
799 The language provides a rich set of 
800 exception handling, process management, and synchronization
801 primitives, which rely on a runtime system.
802 Alef program bugs are often deadlocks, synchronization failures,
803 or non-termination caused by locks being held incorrectly.
804 In such cases, a process stalls deep
805 in the runtime code and it is clearly
806 unreasonable to expect a programmer using the language
807 to understand the detailed
808 internal semantics of the runtime support functions.
809 .PP
810 Instead, there is an Alef support library, coded in Acid, that
811 allows the programmer to interpret the program state in terms of
812 Alef operations.  Consider the example of a multi-process program
813 stalling because of improper synchronization.  A stack trace of
814 the program indicates that it is waiting for an event in some
815 obscure Alef runtime
816 synchronization function.
817 The function itself is irrelevant to the
818 programmer; of greater importance is the identity of the
819 unfulfilled event.
820 Commands in the Alef support library decode
821 the runtime data structures and program state to report the cause
822 of the blockage in terms of the high-level operations available to
823 the Alef programmer.  
824 Here, the Acid language acts
825 as a communications medium between Alef implementer and Alef user.
826 .NH
827 Parallel Debugging
828 .PP
829 The central issue in parallel debugging is how the debugger is
830 multiplexed between the processes comprising
831 the program.
832 Acid has no intrinsic model of process partitioning; it
833 only assumes that parallel programs share a symbol table,
834 though they need not share memory.
835 The
836 .CW setproc
837 primitive attaches the debugger to a running process
838 associated with the process ID supplied as its argument
839 and assigns that value to the global variable
840 .CW pid ,
841 thereby allowing simple rotation among a group of processes.
842 Further, the stack trace primitive is driven by parameters
843 specifying a unique process context, so it is possible to
844 examine the state of cooperating processes without switching
845 the debugger focus from the process of interest.
846 Since Acid is inherently extensible and capable of
847 dynamic interaction with subordinate processes, the
848 programmer can define Acid commands to detect and control
849 complex interactions between processes.
850 In short, the programmer is free to specify how the debugger reacts
851 to events generated in specific threads of the program.
852 .PP
853 The support for parallel debugging in Acid depends on a crucial kernel
854 modification: when the text segment of a program is written (usually to
855 place a breakpoint), the segment is cloned to prevent other threads
856 from encountering the breakpoint.  Although this incurs a slight performance
857 penalty, it is of little importance while debugging.
858 .NH
859 Communication Between Tools
860 .PP
861 The Plan 9 Alef and C compilers do not
862 embed detailed type information in the symbol table of an
863 executable file.
864 However, they do accept a command line option causing them to
865 emit descriptions of complex data types
866 (e.g., aggregates and abstract data types)
867 to an auxiliary file.
868 The vehicle for expressing this information is Acid source code.
869 When an Acid debugging session is 
870 subsequently started, that file is loaded with the other Acid libraries.
871 .PP
872 For each complex object in the program the compiler generates
873 three pieces of Acid code.
874 The first is a table describing the size and offset of each
875 member of the complex data type.  Following is an Acid function,
876 named the same as the object, that formats and prints each member.
877 Finally, Acid declarations associate the
878 Alef or C program variables of a type with the functions
879 to print them.
880 The three forms of declaration are shown in the following example:
881 .P1
882 struct Bitmap {
883         Rectangle    0 r;
884         Rectangle   16 clipr;
885         'D'   32 ldepth;
886         'D'   36 id;
887         'X'   40 cache;
888 };
889 .P2
890 .P1
891 defn
892 Bitmap(addr) {
893         complex Bitmap addr;
894         print("Rectangle r {\en");
895         Rectangle(addr.r);
896         print("}\en");
897         print("Rectangle clipr {\en");
898         Rectangle(addr.clipr);
899         print("}\en");
900         print(" ldepth  ", addr.ldepth, "\en");
901         print(" id      ", addr.id, "\en");
902         print(" cache   ", addr.cache, "\en");
903 };
904
905 complex Bitmap darkgrey;
906 complex Bitmap Window_settag:b;
907 .P2
908 The
909 .CW struct
910 declaration specifies decoding instructions for the complex type named
911 .CW Bitmap .
912 Although the syntax is superficially similar to a C structure declaration,
913 the semantics differ markedly: the C declaration specifies a layout, while
914 the Acid declaration tells how to decode it.
915 The declaration specifies a type, an offset, and name for each
916 member of the complex object. The type is either the name of another
917 complex declaration, for example,
918 .CW Rectangle ,
919 or a format code.
920 The offset is the number of bytes from the start
921 of the object to the member
922 and the name is the member's name in the Alef or C declaration.
923 This type description is a close match for C and Alef, but is simple enough
924 to be language independent.
925 .PP
926 The
927 .CW Bitmap
928 function expects the address of a
929 .CW Bitmap
930 as its only argument.
931 It uses the decoding information contained in the
932 .CW Bitmap
933 structure declaration to extract, format, and print the
934 value of each member of the complex object pointed to by
935 the argument.
936 The Alef compiler emits code to call other Acid functions
937 where a member is another complex type; here,
938 .CW Bitmap
939 calls
940 .CW Rectangle
941 to print its contents.
942 .PP
943 The
944 .CW complex
945 declarations associate Alef variables with complex types.
946 In the example,
947 .CW darkgrey
948 is the name of a global variable of type
949 .CW Bitmap
950 in the program being debugged.
951 Whenever the name
952 .CW darkgrey
953 is evaluated by Acid, it automatically calls the
954 .CW Bitmap
955 function with the address of
956 .CW darkgrey
957 as the argument.
958 The second
959 .CW complex
960 declaration associates a local variable or parameter named
961 .CW b
962 in function
963 .CW Window_settag
964 with the
965 .CW Bitmap
966 complex data type.
967 .PP
968 Acid borrows the C operators
969 .CW .
970 and
971 .CW ->
972 to access the decoding parameters of a member of a complex type.
973 Although this representation is sufficiently general for describing
974 the decoding of both C and Alef complex data types, it may
975 prove too restrictive for target languages with more complicated
976 type systems.
977 Further, the assumption that the compiler can select the proper
978 Acid format code for each basic type in the language is somewhat
979 naive.  For example, when a member of a complex type is a pointer,
980 it is assigned a hexadecimal type code; integer members are always 
981 assigned a decimal type code.
982 This heuristic proves inaccurate when an integer field is a
983 bit mask or set of bit flags which are more appropriately displayed
984 in hexadecimal or octal.
985 .NH
986 Code Verification
987 .PP
988 Acid's ability to interact dynamically with
989 an executing program allows passive test and
990 verification of the target program.  For example,
991 a common concern is leak detection in programs using
992 .CW malloc .
993 Of interest are two items: finding memory that was allocated
994 but never freed and detecting bad pointers passed to
995 .CW free .
996 An auxiliary Acid library contains Acid functions to
997 monitor the execution of a program and detect these
998 faults, either as they happen or in the automated
999 post-mortem analysis of the memory arena.
1000 In the following example, the
1001 .CW sort
1002 command is run under the control of the
1003 Acid memory leak library.
1004 .P1
1005 helix% acid -l malloc /bin/sort
1006 /bin/sort: mips plan 9 executable
1007 /lib/acid/port
1008 /lib/acid/mips
1009 /lib/acid/malloc
1010 acid: go()
1011 now
1012 is
1013 the
1014 time
1015 <ctrl-d>
1016 is
1017 now
1018 the
1019 time
1020 27680 : breakpoint      _exits+0x4      MOVW    $0x8,R1
1021 acid: 
1022 .P2
1023 The
1024 .CW go
1025 command creates a process and plants
1026 breakpoints at the entry to
1027 .CW malloc
1028 and
1029 .CW free .
1030 The program is then started and continues until it
1031 exits or stops.  If the reason for stopping is anything
1032 other than the breakpoints in
1033 .CW malloc
1034 and
1035 .CW free ,
1036 Acid prints the usual status information and returns to the
1037 interactive prompt.
1038 .PP
1039 When the process stops on entering
1040 .CW malloc ,
1041 the debugger must capture and save the address that
1042 .CW malloc
1043 will return.
1044 After saving a stack
1045 trace so the calling routine can be identified, it places
1046 a breakpoint at the return address and restarts the program.
1047 When
1048 .CW malloc
1049 returns, the breakpoint stops the program,
1050 allowing the debugger
1051 to grab the address of the new memory block from the return register.
1052 The address and stack trace are added to the list of outstanding
1053 memory blocks, the breakpoint is removed from the return point, and
1054 the process is restarted.
1055 .PP
1056 When the process stops at the beginning of
1057 .CW free ,
1058 the memory address supplied as the argument is compared to the list
1059 of outstanding memory blocks.  If it is not found an error message
1060 and a stack trace of the call is reported; otherwise, the
1061 address is deleted from the list.
1062 .PP
1063 When the program exits, the list of outstanding memory blocks contains
1064 the addresses of all blocks that were allocated but never freed.
1065 The
1066 .CW leak
1067 library function traverses the list producing a report describing
1068 the allocated blocks.
1069 .P1 1m
1070 acid: leak()
1071 Lost a total of 524288 bytes from:
1072     malloc() malloc.c:32 called from dofile+0xe8 sort.c:217 
1073     dofile() sort.c:190 called from main+0xac sort.c:161 
1074     main() sort.c:128 called from _main+0x20 main9.s:10 
1075 Lost a total of 64 bytes from:
1076     malloc() malloc.c:32 called from newline+0xfc sort.c:280 
1077     newline() sort.c:248 called from dofile+0x110 sort.c:222 
1078     dofile() sort.c:190 called from main+0xac sort.c:161 
1079     main() sort.c:128 called from _main+0x20 main9.s:10 
1080 Lost a total of 64 bytes from:
1081     malloc() malloc.c:32 called from realloc+0x14 malloc.c:129 
1082     realloc() malloc.c:123 called from bldkey+0x358 sort.c:1388 
1083     buildkey() sort.c:1345 called from newline+0x150 sort.c:285 
1084     newline() sort.c:248 called from dofile+0x110 sort.c:222 
1085     dofile() sort.c:190 called from main+0xac sort.c:161 
1086     main() sort.c:128 called from _main+0x20 main9.s:10
1087 acid: refs()
1088 data...bss...stack...
1089 acid: leak()
1090 acid: 
1091 .P2
1092 The presence of a block in the allocation list does not imply
1093 it is there because of a leak; for instance, it may have been
1094 in use when the program terminated.
1095 The
1096 .CW refs()
1097 library function scans the
1098 .I data ,
1099 .I bss ,
1100 and
1101 .I stack
1102 segments of the process looking for pointers
1103 into the allocated blocks.  When one is found, the block is deleted from
1104 the outstanding block list.
1105 The
1106 .CW leak
1107 function is used again to report the
1108 blocks remaining allocated and unreferenced.
1109 This strategy proves effective in detecting
1110 disconnected (but non-circular) data structures.
1111 .PP
1112 The leak detection process is entirely passive.
1113 The program is not
1114 specially compiled and the source code is not required.
1115 As with the Acid support functions for the Alef runtime environment,
1116 the author of the library routines has encapsulated the
1117 functionality of the library interface
1118 in Acid code.
1119 Any programmer may then check a program's use of the
1120 library routines without knowledge of either implementation.
1121 The performance impact of running leak detection is great
1122 (about 10 times slower),
1123 but it has not prevented interactive programs like
1124 .CW sam
1125 and the
1126 .CW 8½
1127 window system from being tested.
1128 .NH
1129 Code Coverage
1130 .PP
1131 Another common component of software test uses 
1132 .I coverage 
1133 analysis.
1134 The purpose of the test is to determine which paths through the code have
1135 not been executed while running the test suite.
1136 This is usually
1137 performed by a combination of compiler support and a reporting tool run
1138 on the output generated by statements compiled into the program.
1139 The compiler emits code that
1140 logs the progress of the program as it executes basic blocks and writes the
1141 results to a file. The file is then processed by the reporting tool 
1142 to determine which basic blocks have not been executed.
1143 .PP
1144 Acid can perform the same function in a language independent manner without
1145 modifying the source, object or binary of the program. The following example
1146 shows
1147 .CW ls
1148 being run under the control of the Acid coverage library.
1149 .P1
1150 philw-helix% acid -l coverage /bin/ls
1151 /bin/ls: mips plan 9 executable
1152 /lib/acid/port
1153 /lib/acid/mips
1154 /lib/acid/coverage
1155 acid: coverage()
1156 acid
1157 newstime
1158 profile
1159 tel
1160 wintool
1161 2: (error) msg: pid=11419 startstop: process exited
1162 acid: analyse(ls)
1163 ls.c:102,105
1164         102:     return 1;
1165         103: }
1166         104: if(db[0].qid.path&CHDIR && dflag==0){
1167         105:     output();
1168 ls.c:122,126
1169         122:     memmove(dirbuf+ndir, db, sizeof(Dir));
1170         123:     dirbuf[ndir].prefix = 0;
1171         124:     p = utfrrune(s, '/');
1172         125:     if(p){
1173         126:         dirbuf[ndir].prefix = s;
1174 .P2
1175 The
1176 .CW coverage
1177 function begins by looping through the text segment placing
1178 breakpoints at the entry to each basic block. The start of each basic
1179 block is found using the Acid builtin function
1180 .CW follow .
1181 If the list generated by
1182 .CW follow 
1183 contains more than one
1184 element, then the addresses mark the start of basic blocks. A breakpoint
1185 is placed at each address to detect entry into the block. If the result
1186 of
1187 .CW follow
1188 is a single address then no action is taken, and the next address is
1189 considered. Acid maintains a list of
1190 breakpoints already in place and avoids placing duplicates (an address may be
1191 the destination of several branches).
1192 .PP
1193 After placing the breakpoints the program is set running.
1194 Each time a breakpoint is encountered
1195 Acid deletes the address from the breakpoint list, removes the breakpoint
1196 from memory and then restarts the program.
1197 At any instant the breakpoint list contains the addresses of basic blocks
1198 which have not been executed. 
1199 The
1200 .CW analyse
1201 function reports the lines of source code bounded by basic blocks
1202 whose addresses are have not been deleted from the breakpoint list.
1203 These are the basic blocks which have not been executed.
1204 Program performance is almost unaffected since each breakpoint is executed
1205 only once and then removed.
1206 .PP
1207 The library contains a total of 128 lines of Acid code.
1208 An obvious extension of this algorithm could be used to provide basic block
1209 profiling.
1210 .NH
1211 Conclusion
1212 .PP
1213 Acid has two areas of weakness. As with
1214 other language-based tools like
1215 .I awk ,
1216 a programmer must learn yet another language to step beyond the normal
1217 debugging functions and use the full power of the debugger.
1218 Second, the command line interface supplied by the
1219 .I yacc
1220 parser is inordinately clumsy.
1221 Part of the problem relates directly to the use of
1222 .I yacc
1223 and could be circumvented with a custom parser.
1224 However, structural problems would remain: Acid often requires
1225 too much typing to execute a simple
1226 command.
1227 A debugger should prostitute itself to its users, doing whatever
1228 is wanted with a minimum of encouragement; commands should be
1229 concise and obvious. The language interface is more consistent than
1230 an ad hoc command interface but is clumsy to use.
1231 Most of these problems are addressed by an Acme interface
1232 which is under construction. This should provide the best of
1233 both worlds: graphical debugging and access to the underlying acid
1234 language when required.
1235 .PP
1236 The name space clash between Acid variables, keywords, program variables,
1237 and functions is unavoidable.
1238 Although it rarely affects a debugging session, it is annoying
1239 when it happens and is sometimes difficult to circumvent.
1240 The current renaming scheme
1241 is too crude; the new names are too hard to remember.
1242 .PP
1243 Acid has proved to be a powerful tool whose applications
1244 have exceeded expectations.
1245 Of its strengths, portability, extensibility and parallel debugging support
1246 were by design and provide the expected utility.
1247 In retrospect,
1248 its use as a tool for code test and verification and as
1249 a medium for communicating type information and encapsulating
1250 interfaces has provided unanticipated benefits and altered our
1251 view of the debugging process.
1252 .NH
1253 Acknowledgments
1254 .PP
1255 Bob Flandrena was the first user and helped prepare the paper.
1256 Rob Pike endured three buggy Alef compilers and a new debugger
1257 in a single sitting.
1258 .NH
1259 References
1260 .LP
1261 [Pike90] R. Pike, D. Presotto, K. Thompson, H. Trickey,
1262 ``Plan 9 from Bell Labs'',
1263 .I
1264 UKUUG Proc. of the Summer 1990 Conf.,
1265 .R
1266 London, England,
1267 1990,
1268 reprinted, in a different form, in this volume.
1269 .LP
1270 [Gol93] M. Golan, D. Hanson,
1271 ``DUEL -- A Very High-Level Debugging Language'',
1272 .I
1273 USENIX Proc. of the Winter 1993 Conf.,
1274 .R
1275 San Diego, CA,
1276 1993.
1277 .LP
1278 [Lin90] M. A. Linton,
1279 ``The Evolution of DBX'',
1280 .I
1281 USENIX Proc. of the Summer 1990 Conf.,
1282 .R
1283 Anaheim, CA,
1284 1990.
1285 .LP
1286 [Stal91] R. M. Stallman, R. H. Pesch,
1287 ``Using GDB: A guide to the GNU source level debugger'',
1288 Technical Report, Free Software Foundation,
1289 Cambridge, MA,
1290 1991.
1291 .LP
1292 [Win93] P. Winterbottom,
1293 ``Alef reference Manual'',
1294 this volume.
1295 .LP
1296 [Pike93] Rob Pike,
1297 ``Acme: A User Interface for Programmers'',
1298 .I
1299 USENIX Proc. of the Winter 1994 Conf.,
1300 .R
1301 San Francisco, CA,
1302 reprinted in this volume.
1303 .LP
1304 [Ols90] Ronald A. Olsson, Richard H. Crawford, and W. Wilson Ho,
1305 ``Dalek: A GNU, improved programmable debugger'',
1306 .I
1307 USENIX Proc. of the Summer 1990 Conf.,
1308 .R
1309 Anaheim, CA.
1310 .LP
1311 [May92] Paul Maybee,
1312 ``NeD: The Network Extensible Debugger''
1313 .I
1314 USENIX Proc. of the Summer 1992 Conf.,
1315 .R
1316 San Antonio, TX.
1317 .LP
1318 [Aral] Ziya Aral, Ilya Gertner, and Greg Schaffer,
1319 ``Efficient debugging primitives for multiprocessors'',
1320 .I
1321 Proceedings of the Third International Conference on Architectural
1322 Support for Programming Languages and Operating Systems,
1323 .R
1324 SIGPLAN notices Nr. 22, May 1989.