xref: /plan9-contrib/sys/doc/acidpaper.ms (revision 426d2b71458df9b491ba6c167f699b3f1f7b0428)
1*426d2b71SDavid du Colombier.HTML "Acid: A Debugger Built From A Language
2219b2ee8SDavid du Colombier.TL
3219b2ee8SDavid du ColombierAcid: A Debugger Built From A Language
4219b2ee8SDavid du Colombier.AU
5219b2ee8SDavid du ColombierPhil Winterbottom
67dd7cddfSDavid du Colombierphilw@plan9.bell-labs.com
7219b2ee8SDavid du Colombier.AB
8219b2ee8SDavid du Colombier.FS
9219b2ee8SDavid du ColombierOriginally appeared in
10219b2ee8SDavid du Colombier.I
11219b2ee8SDavid du ColombierProc. of the Winter 1994 USENIX Conf.,
12219b2ee8SDavid du Colombier.R
13219b2ee8SDavid du Colombierpp. 211-222,
14219b2ee8SDavid du ColombierSan Francisco, CA
15219b2ee8SDavid du Colombier.FE
16219b2ee8SDavid du ColombierAcid is an unusual source-level symbolic debugger for Plan 9. It is implemented
17219b2ee8SDavid du Colombieras a language interpreter with specialized primitives that provide
18219b2ee8SDavid du Colombierdebugger support.  Programs written in the language manipulate
19219b2ee8SDavid du Colombierone or more target processes; variables in the language represent the
20219b2ee8SDavid du Colombiersymbols, state, and resources of those processes.
21219b2ee8SDavid du ColombierThis structure allows complex
22219b2ee8SDavid du Colombierinteraction between the debugger and the target program and
23219b2ee8SDavid du Colombierprovides a convenient method of parameterizing differences between
24219b2ee8SDavid du Colombiermachine architectures.
25219b2ee8SDavid du ColombierAlthough some effort is required to learn
26219b2ee8SDavid du Colombierthe debugging language, the richness and flexibility of the
27219b2ee8SDavid du Colombierdebugging environment encourages new ways of reasoning about the way
28219b2ee8SDavid du Colombierprograms run and the conditions under which they fail.
29219b2ee8SDavid du Colombier.AE
30219b2ee8SDavid du Colombier.NH
31219b2ee8SDavid du ColombierIntroduction
32219b2ee8SDavid du Colombier.PP
33219b2ee8SDavid du ColombierThe size and complexity
34219b2ee8SDavid du Colombierof programs have increased in proportion to processor speed and memory but
35219b2ee8SDavid du Colombierthe interface between debugger and programmer has changed little.
36219b2ee8SDavid du ColombierGraphical user interfaces have eased some of the tedious
37219b2ee8SDavid du Colombieraspects of the interaction. A graphical interface is a convenient
38219b2ee8SDavid du Colombiermeans for navigating through source and data structures but provides
39219b2ee8SDavid du Colombierlittle benefit for process control.
40219b2ee8SDavid du ColombierThe introduction of a new concurrent language, Alef [Win93], emphasized the
41219b2ee8SDavid du Colombierinadequacies of the existing Plan 9 [Pike90] debugger
42219b2ee8SDavid du Colombier.I db ,
43219b2ee8SDavid du Colombiera distant relative of
44219b2ee8SDavid du Colombier.I adb ,
45219b2ee8SDavid du Colombierand made it clear that a new debugger was required.
46219b2ee8SDavid du Colombier.PP
47219b2ee8SDavid du ColombierCurrent debuggers like
48219b2ee8SDavid du Colombier.I dbx ,
49219b2ee8SDavid du Colombier.I sdb ,
50219b2ee8SDavid du Colombierand
51219b2ee8SDavid du Colombier.I gdb
52219b2ee8SDavid du Colombierare limited to answering only the questions their authors
53219b2ee8SDavid du Colombierenvisage.  As a result, they supply a plethora
54219b2ee8SDavid du Colombierof specialized commands, each attempting to anticipate
55219b2ee8SDavid du Colombiera specific question a user may ask.
56219b2ee8SDavid du ColombierWhen a debugging situation arises that is beyond the scope
57219b2ee8SDavid du Colombierof the command set, the tool is useless.
58219b2ee8SDavid du ColombierFurther,
59219b2ee8SDavid du Colombierit is often tedious or impossible to reproduce an anomalous state
60219b2ee8SDavid du Colombierof the program, especially when
61219b2ee8SDavid du Colombierthe state is embedded in the program's data structures.
62219b2ee8SDavid du Colombier.PP
63219b2ee8SDavid du ColombierAcid applies some ideas found in CAD software used for
64219b2ee8SDavid du Colombierhardware test and simulation.
65219b2ee8SDavid du ColombierIt is based on the notion that the state and resources of a program
66219b2ee8SDavid du Colombierare best represented and manipulated by a language. The state and resources,
67219b2ee8SDavid du Colombiersuch as memory, registers, variables, type information and source code
68219b2ee8SDavid du Colombierare represented by variables in the language.
69219b2ee8SDavid du ColombierExpressions provide a computation mechanism and control
70219b2ee8SDavid du Colombierstatements allow repetitive or selective interpretation based
71219b2ee8SDavid du Colombieron the result of expression evaluation.
72219b2ee8SDavid du ColombierThe heart of the Acid debugger is an interpreter for a small typeless
73219b2ee8SDavid du Colombierlanguage whose operators mirror the operations
74219b2ee8SDavid du Colombierof C and Alef, which in turn correspond well to the basic operations of
75219b2ee8SDavid du Colombierthe machine. The interpreter itself knows nothing of the underlying
76219b2ee8SDavid du Colombierhardware; it deals with the program state and resources
77219b2ee8SDavid du Colombierin the abstract.
78219b2ee8SDavid du ColombierFundamental routines to control
79219b2ee8SDavid du Colombierprocesses, read files, and interface to the system are implemented
80219b2ee8SDavid du Colombieras builtin functions available to the interpreter.
81219b2ee8SDavid du ColombierThe actual debugger functionality is coded
82219b2ee8SDavid du Colombierin Acid; commands are implemented as Acid functions.
83219b2ee8SDavid du Colombier.PP
84219b2ee8SDavid du ColombierThis language-based approach has several advantages.
85219b2ee8SDavid du ColombierMost importantly, programs written in Acid, including most of the
86219b2ee8SDavid du Colombierdebugger itself, are inherently portable.
87219b2ee8SDavid du ColombierFurthermore, Acid avoids the limitations other debuggers impose when
88219b2ee8SDavid du Colombierdebugging parallel programs.  Instead of embedding a fixed
89219b2ee8SDavid du Colombierprocess model in the debugger, Acid allows the
90219b2ee8SDavid du Colombierprogrammer to adapt the debugger to handle an
91219b2ee8SDavid du Colombierarbitrary process partitioning or program structure.
92219b2ee8SDavid du ColombierThe ability to
93219b2ee8SDavid du Colombierinteract dynamically with an executing process provides clear advantages
94219b2ee8SDavid du Colombierover debuggers constrained to probe a static image.
95219b2ee8SDavid du ColombierFinally, the Acid language is a powerful vehicle for expressing
96219b2ee8SDavid du Colombierassertions about logic, process state, and the contents of data structures.
97219b2ee8SDavid du ColombierWhen combined with dynamic interaction it allows a
98219b2ee8SDavid du Colombierlimited form of automated program verification without requiring
99219b2ee8SDavid du Colombiermodification or recompilation of the source code.
100219b2ee8SDavid du ColombierThe language is also an
101219b2ee8SDavid du Colombierexcellent vehicle for preserving a test suite for later regression testing.
102219b2ee8SDavid du Colombier.PP
103219b2ee8SDavid du ColombierThe debugger may be customized by its users; standard
104219b2ee8SDavid du Colombierfunctions may be modified or extended to suit a particular application
105219b2ee8SDavid du Colombieror preference.
106219b2ee8SDavid du ColombierFor example, the kernel developers in our group require a
107219b2ee8SDavid du Colombiercommand set supporting assembler-level debugging while the application
108219b2ee8SDavid du Colombierprogrammers prefer source-level functionality.
109219b2ee8SDavid du ColombierAlthough the default library is biased toward assembler-level debugging,
110219b2ee8SDavid du Colombierit is easily modified to provide a convenient source-level interface.
111219b2ee8SDavid du ColombierThe debugger itself does not change; the user combines primitives
112219b2ee8SDavid du Colombierand existing Acid functions in different ways to
113219b2ee8SDavid du Colombierimplement the desired interface.
114219b2ee8SDavid du Colombier.NH
115219b2ee8SDavid du ColombierRelated Work
116219b2ee8SDavid du Colombier.PP
117219b2ee8SDavid du ColombierDUEL [Gol93], an extension to
118219b2ee8SDavid du Colombier.I gdb
119219b2ee8SDavid du Colombier[Stal91], proposes using a high level expression evaluator to solve
120219b2ee8SDavid du Colombiersome of these problems. The evaluator provides iterators to loop over data
121219b2ee8SDavid du Colombierstructures and conditionals to control evaluation of expressions.
122219b2ee8SDavid du ColombierThe author shows that complex state queries can be formulated
123219b2ee8SDavid du Colombierby combining concise expressions but this only addresses part of the problem.
124219b2ee8SDavid du ColombierA program is a dynamic entity; questions asked when the program is in
125219b2ee8SDavid du Colombiera static state are meaningful only after the program has been `caught' in
126219b2ee8SDavid du Colombierthat state. The framework for manipulating the program is still as
127219b2ee8SDavid du Colombierprimitive as the underlying debugger. While DUEL provides a means to
128219b2ee8SDavid du Colombierprobe data structures it entirely neglects the most beneficial aspect
129219b2ee8SDavid du Colombierof debugging languages: the ability to control processes. Acid is structured
130219b2ee8SDavid du Colombieraround a thread of control that passes between the interpreter and the
131219b2ee8SDavid du Colombiertarget program.
132219b2ee8SDavid du Colombier.PP
133219b2ee8SDavid du ColombierThe NeD debugger [May92] is a set of extensions to TCL [Ous90] that provide
134219b2ee8SDavid du Colombierdebugging primitives. The resulting language, NeDtcl, is used to implement
135219b2ee8SDavid du Colombiera portable interface between a conventional debugger, pdb [May90], and
136219b2ee8SDavid du Colombiera server that executes NeDtcl programs operating on the target program.
137219b2ee8SDavid du ColombierExecution of the NeDtcl programs implements the debugging primitives
138219b2ee8SDavid du Colombierthat pdb expects.
139219b2ee8SDavid du ColombierNeD is targeted at multi-process debugging across a network,
140219b2ee8SDavid du Colombierand proves the flexibility of a language as a means of
141219b2ee8SDavid du Colombiercommunication between debugging tools. Whereas NeD provides an interface
142219b2ee8SDavid du Colombierbetween a conventional debugger and the process it debugs, Acid is the
143219b2ee8SDavid du Colombierdebugger itself. While NeD has some of the ideas
144219b2ee8SDavid du Colombierfound in Acid it is targeted toward a different purpose. Acid seeks to
145219b2ee8SDavid du Colombierintegrate the manipulation of a program's resources into the debugger
146219b2ee8SDavid du Colombierwhile NeD provides a flexible interconnect between components of
147219b2ee8SDavid du Colombierthe debugging environment. The choice of TCL is appropriate for its use
148219b2ee8SDavid du Colombierin NeD but is not suitable for Acid. Acid relies on the coupling of the type
149219b2ee8SDavid du Colombiersystem with expression evaluation, which are the root of its design,
150219b2ee8SDavid du Colombierto provide the debugging primitives.
151219b2ee8SDavid du Colombier.PP
152219b2ee8SDavid du ColombierDalek [Ols90] is an event based language extension to gdb. State transitions
153219b2ee8SDavid du Colombierin the target program cause events to be queued for processing by the
154219b2ee8SDavid du Colombierdebugging language.
155219b2ee8SDavid du Colombier.PP
156219b2ee8SDavid du ColombierAcid has many of the advantages of same process or
157219b2ee8SDavid du Colombier.I local
158219b2ee8SDavid du Colombier.I agent
159219b2ee8SDavid du Colombierdebuggers, like Parasight [Aral], without the need for dynamic linking or
160219b2ee8SDavid du Colombiershared memory.
161219b2ee8SDavid du ColombierAcid improves on the ideas of these other systems by completely integrating
162219b2ee8SDavid du Colombierall aspects of the debugging process into the language environment. Of
163219b2ee8SDavid du Colombierparticular importance is the relationship between Acid variables,
164219b2ee8SDavid du Colombierprogram symbols, source code, registers and type information. This
165219b2ee8SDavid du Colombierintegration is made possible by the design of the Acid language.
166219b2ee8SDavid du Colombier.PP
167219b2ee8SDavid du ColombierInterpreted languages such as Lisp and Smalltalk are able to provide
168219b2ee8SDavid du Colombierricher debugging environments through more complete information than
169219b2ee8SDavid du Colombiertheir compiled counterparts. Acid is a means to gather and represent
170219b2ee8SDavid du Colombiersimilar information about compiled programs through cooperation
171219b2ee8SDavid du Colombierwith the compilation tools and library implementers.
172219b2ee8SDavid du Colombier.NH
173219b2ee8SDavid du ColombierAcid the Language
174219b2ee8SDavid du Colombier.PP
175219b2ee8SDavid du ColombierAcid is a small interpreted language targeted to its debugging task.
176219b2ee8SDavid du ColombierIt focuses on representing program state and addressing data rather than
177219b2ee8SDavid du Colombierexpressing complex computations. Program state is
178219b2ee8SDavid du Colombier.I addressable
179219b2ee8SDavid du Colombierfrom an Acid program.
180219b2ee8SDavid du ColombierIn addition to parsing and executing expressions and providing
181219b2ee8SDavid du Colombieran architecture-independent interface to the target process,
182219b2ee8SDavid du Colombierthe interpreter supplies a mark-and-scan garbage collector
183219b2ee8SDavid du Colombierto manage storage.
184219b2ee8SDavid du Colombier.PP
185219b2ee8SDavid du ColombierEvery Acid session begins with the loading of the Acid libraries.
186219b2ee8SDavid du ColombierThese libraries contain functions, written in Acid, that provide
187219b2ee8SDavid du Colombiera standard debugging environment including breakpoint management,
188219b2ee8SDavid du Colombierstepping by instruction or statement, stack tracing, and
189219b2ee8SDavid du Colombieraccess to variables, memory, and registers.
190219b2ee8SDavid du ColombierThe library contains 600 lines of Acid code and provides
191219b2ee8SDavid du Colombierfunctionality similar to
192219b2ee8SDavid du Colombier.I dbx .
193219b2ee8SDavid du ColombierFollowing the loading of the system library, Acid loads
194219b2ee8SDavid du Colombieruser-specified libraries; this load sequence allows the
195219b2ee8SDavid du Colombieruser to augment or override the standard commands
196219b2ee8SDavid du Colombierto customize the debugging environment.  When all libraries
197219b2ee8SDavid du Colombierare loaded, Acid issues an interactive prompt and begins
198219b2ee8SDavid du Colombierevaluating expressions entered by the user.  The Acid `commands'
199219b2ee8SDavid du Colombierare actually invocations of builtin primitives or previously defined
200219b2ee8SDavid du ColombierAcid functions. Acid evaluates each expression as it is entered and
201219b2ee8SDavid du Colombierprints the result.
202219b2ee8SDavid du Colombier.NH
203219b2ee8SDavid du ColombierTypes and Variables
204219b2ee8SDavid du Colombier.PP
205219b2ee8SDavid du ColombierAcid variables are of four basic types:
206219b2ee8SDavid du Colombier.I integer ,
207219b2ee8SDavid du Colombier.I string ,
208219b2ee8SDavid du Colombier.I float ,
209219b2ee8SDavid du Colombierand
210219b2ee8SDavid du Colombier.I list .
211219b2ee8SDavid du ColombierThe type of a variable is inferred by the type of the right-hand side of
212219b2ee8SDavid du Colombieran assignment expression.
213219b2ee8SDavid du ColombierMany of the operators can be applied to more than
214219b2ee8SDavid du Colombierone type; for these operators the action of the operator is determined
215219b2ee8SDavid du Colombierby the type of its operands.
216219b2ee8SDavid du ColombierFor example,
217219b2ee8SDavid du Colombierthe
218219b2ee8SDavid du Colombier.CW +
219219b2ee8SDavid du Colombieroperator adds
220219b2ee8SDavid du Colombier.I integer
221219b2ee8SDavid du Colombierand
222219b2ee8SDavid du Colombier.I float
223219b2ee8SDavid du Colombieroperands, and concatenates
224219b2ee8SDavid du Colombier.I string
225219b2ee8SDavid du Colombierand
226219b2ee8SDavid du Colombier.I list
227219b2ee8SDavid du Colombieroperands.
228219b2ee8SDavid du ColombierLists are the only complex type in Acid; there are no arrays, structures
229219b2ee8SDavid du Colombieror pointers. Operators provide
230219b2ee8SDavid du Colombier.CW head ,
231219b2ee8SDavid du Colombier.CW tail ,
232219b2ee8SDavid du Colombier.CW append
233219b2ee8SDavid du Colombierand
234219b2ee8SDavid du Colombier.CW delete
235219b2ee8SDavid du Colombieroperations.
236219b2ee8SDavid du ColombierLists can also be indexed like arrays.
237219b2ee8SDavid du Colombier.PP
238219b2ee8SDavid du ColombierAcid has two levels of scope: global and local.
239219b2ee8SDavid du ColombierFunction parameters and variables declared in a function body
240219b2ee8SDavid du Colombierusing the
241219b2ee8SDavid du Colombier.CW local
242219b2ee8SDavid du Colombierkeyword are created at entry to the function and
243219b2ee8SDavid du Colombierexist for the lifetime of a function.
244219b2ee8SDavid du ColombierGlobal variables are created by assignment and need not be declared.
245219b2ee8SDavid du ColombierAll variables and functions in the program
246219b2ee8SDavid du Colombierbeing debugged are entered in the Acid symbol table as global
247219b2ee8SDavid du Colombiervariables during Acid initialization.
248219b2ee8SDavid du ColombierConflicting variable names are resolved by prefixing enough `$' characters
249219b2ee8SDavid du Colombierto make them unique.
250219b2ee8SDavid du ColombierSyntactically, Acid variables and target program
251219b2ee8SDavid du Colombiersymbols are referenced identically.
252219b2ee8SDavid du ColombierHowever, the variables are managed differently in the Acid
253219b2ee8SDavid du Colombiersymbol table and the user must be aware of this distinction.
254219b2ee8SDavid du ColombierThe value of an Acid variable is stored in the symbol
255219b2ee8SDavid du Colombiertable; a reference returns the value.
256219b2ee8SDavid du ColombierThe symbol table entry for a variable or function in the target
257219b2ee8SDavid du Colombierprogram contains the address of that symbol in the image
258219b2ee8SDavid du Colombierof the program.  Thus, the value of a program variable is
259219b2ee8SDavid du Colombieraccessed by indirect reference through the Acid
260219b2ee8SDavid du Colombiervariable that has the same name; the value of an Acid variable is the
261219b2ee8SDavid du Colombieraddress of the corresponding program variable.
262219b2ee8SDavid du Colombier.NH
263219b2ee8SDavid du ColombierControl Flow
264219b2ee8SDavid du Colombier.PP
265219b2ee8SDavid du ColombierThe
266219b2ee8SDavid du Colombier.CW while
267219b2ee8SDavid du Colombierand
268219b2ee8SDavid du Colombier.CW loop
269219b2ee8SDavid du Colombierstatements implement looping.
270219b2ee8SDavid du ColombierThe former
271219b2ee8SDavid du Colombieris similar to the same statement in C.
272219b2ee8SDavid du ColombierThe latter evaluates starting and ending expressions yielding
273219b2ee8SDavid du Colombierintegers and iterates while an incrementing loop index
274219b2ee8SDavid du Colombieris within the bounds of those expressions.
275219b2ee8SDavid du Colombier.P1
276219b2ee8SDavid du Colombieracid: i = 0; loop 1,5 do print(i=i+1)
277219b2ee8SDavid du Colombier0x00000001
278219b2ee8SDavid du Colombier0x00000002
279219b2ee8SDavid du Colombier0x00000003
280219b2ee8SDavid du Colombier0x00000004
281219b2ee8SDavid du Colombier0x00000005
282219b2ee8SDavid du Colombieracid:
283219b2ee8SDavid du Colombier.P2
284219b2ee8SDavid du ColombierThe traditional
285219b2ee8SDavid du Colombier.CW if-then-else
286219b2ee8SDavid du Colombierstatement implements conditional execution.
287219b2ee8SDavid du Colombier.NH
288219b2ee8SDavid du ColombierAddressing
289219b2ee8SDavid du Colombier.PP
290219b2ee8SDavid du ColombierTwo indirection operators allow Acid to access values in
291219b2ee8SDavid du Colombierthe program being debugged.
292219b2ee8SDavid du ColombierThe
293219b2ee8SDavid du Colombier.CW *
294219b2ee8SDavid du Colombieroperator fetches a value from the memory image of an
295219b2ee8SDavid du Colombierexecuting process;
296219b2ee8SDavid du Colombierthe
297219b2ee8SDavid du Colombier.CW @
298219b2ee8SDavid du Colombieroperator fetches a value from the text file of the process.
299219b2ee8SDavid du ColombierWhen either operator appears on the left side of an assignment, the value
300219b2ee8SDavid du Colombieris written rather than read.
301219b2ee8SDavid du Colombier.PP
302219b2ee8SDavid du ColombierThe indirection operator must know the size of the object
303219b2ee8SDavid du Colombierreferenced by a variable.
304219b2ee8SDavid du ColombierThe Plan 9 compilers neglect to include this
305219b2ee8SDavid du Colombierinformation in the program symbol table, so Acid cannot
306219b2ee8SDavid du Colombierderive this information implicitly.
307219b2ee8SDavid du ColombierInstead Acid variables have formats.
308219b2ee8SDavid du ColombierThe format is a code
309219b2ee8SDavid du Colombierletter specifying the printing style and the effect of some of the
310219b2ee8SDavid du Colombieroperators on that variable.
311219b2ee8SDavid du ColombierThe indirection operators look at the format code to determine the
312219b2ee8SDavid du Colombiernumber of bytes to read or write.
313219b2ee8SDavid du ColombierThe format codes are derived from the format letters used by
314219b2ee8SDavid du Colombier.I db .
315219b2ee8SDavid du ColombierBy default, symbol table variables and numeric constants
316219b2ee8SDavid du Colombierare assigned the format code
317219b2ee8SDavid du Colombier.CW 'X'
318219b2ee8SDavid du Colombierwhich specifies 32-bit hexadecimal.
319219b2ee8SDavid du ColombierPrinting such a variable yields output of the form
320219b2ee8SDavid du Colombier.CW 0x00123456 .
321219b2ee8SDavid du ColombierAn indirect reference through the variable fetches 32 bits
322219b2ee8SDavid du Colombierof data at the address indicated by the variable.
323219b2ee8SDavid du ColombierOther formats specify various data types, for example
324219b2ee8SDavid du Colombier.CW i
325219b2ee8SDavid du Colombieran instruction,
326219b2ee8SDavid du Colombier.CW D
327219b2ee8SDavid du Colombiera signed 32 bit decimal,
328219b2ee8SDavid du Colombier.CW s
329219b2ee8SDavid du Colombiera null-terminated string.
330219b2ee8SDavid du ColombierThe
331219b2ee8SDavid du Colombier.CW fmt
332219b2ee8SDavid du Colombierfunction
333219b2ee8SDavid du Colombierallows the user to change the format code of a variable
334219b2ee8SDavid du Colombierto control the printing format and
335219b2ee8SDavid du Colombieroperator side effects.
336219b2ee8SDavid du ColombierThis function evaluates the expression supplied as the first
337219b2ee8SDavid du Colombierargument, attaches the format code supplied as the second
338219b2ee8SDavid du Colombierargument to the result and returns that value.
339219b2ee8SDavid du ColombierIf the result is assigned to a variable,
340219b2ee8SDavid du Colombierthe new format code applies to
341219b2ee8SDavid du Colombierthat variable.  For convenience, Acid provides the
342219b2ee8SDavid du Colombier.CW \e
343219b2ee8SDavid du Colombieroperator as a shorthand infix form of
344219b2ee8SDavid du Colombier.CW fmt .
345219b2ee8SDavid du ColombierFor example:
346219b2ee8SDavid du Colombier.P1
347219b2ee8SDavid du Colombieracid: x=10
348219b2ee8SDavid du Colombieracid: x				 // print x in hex
349219b2ee8SDavid du Colombier0x0000000a
350219b2ee8SDavid du Colombieracid: x = fmt(x, 'D')		 // make x type decimal
351219b2ee8SDavid du Colombieracid: print(x, fmt(x, 'X'), x\eX) // print x in decimal & hex
352219b2ee8SDavid du Colombier10 0x0000000a 0x0000000a
353219b2ee8SDavid du Colombieracid: x				 // print x in decimal
354219b2ee8SDavid du Colombier10
355219b2ee8SDavid du Colombieracid: x\eo			 // print x in octal
356219b2ee8SDavid du Colombier000000000012
357219b2ee8SDavid du Colombier.P2
358219b2ee8SDavid du ColombierThe
359219b2ee8SDavid du Colombier.CW ++
360219b2ee8SDavid du Colombierand
361219b2ee8SDavid du Colombier.CW --
362219b2ee8SDavid du Colombieroperators increment or decrement a variable by an amount
363219b2ee8SDavid du Colombierdetermined by its format code.  Some formats imply a non-fixed size.
364219b2ee8SDavid du ColombierFor example, the
365219b2ee8SDavid du Colombier.CW i
366219b2ee8SDavid du Colombierformat code disassembles an instruction into a string.
367219b2ee8SDavid du ColombierOn a 68020, which has variable length instructions:
368219b2ee8SDavid du Colombier.P1
369219b2ee8SDavid du Colombieracid: p=main\ei                     // p=addr(main), type INST
370219b2ee8SDavid du Colombieracid: loop 1,5 do print(p\eX, @p++) // disassemble 5 instr's
371219b2ee8SDavid du Colombier0x0000222e LEA	0xffffe948(A7),A7
372219b2ee8SDavid du Colombier0x00002232 MOVL	s+0x4(A7),A2
373219b2ee8SDavid du Colombier0x00002236 PEA	0x2f($0)
374219b2ee8SDavid du Colombier0x0000223a MOVL	A2,-(A7)
375219b2ee8SDavid du Colombier0x0000223c BSR	utfrrune
376219b2ee8SDavid du Colombieracid:
377219b2ee8SDavid du Colombier.P2
378219b2ee8SDavid du ColombierHere,
379219b2ee8SDavid du Colombier.CW main
380219b2ee8SDavid du Colombieris the address of the function of the same name in the program under test.
381219b2ee8SDavid du ColombierThe loop retrieves the five instructions beginning at that address and
382219b2ee8SDavid du Colombierthen prints the address and the assembly language representation of each.
383219b2ee8SDavid du ColombierNotice that the stride of the increment operator varies with the size of
384219b2ee8SDavid du Colombierthe instruction: the
385219b2ee8SDavid du Colombier.CW MOVL
386219b2ee8SDavid du Colombierat
387219b2ee8SDavid du Colombier.CW 0x0000223a
388219b2ee8SDavid du Colombieris a two byte instruction while all others are four bytes long.
389219b2ee8SDavid du Colombier.PP
390219b2ee8SDavid du ColombierRegisters are treated as normal program variables referenced
391219b2ee8SDavid du Colombierby their symbolic assembler language names.
392219b2ee8SDavid du ColombierWhen a
393219b2ee8SDavid du Colombierprocess stops, the register set is saved by the kernel
394219b2ee8SDavid du Colombierat a known virtual address in the process memory map.
395219b2ee8SDavid du ColombierThe Acid variables associated with the registers point
396219b2ee8SDavid du Colombierto the saved values and the
397219b2ee8SDavid du Colombier.CW *
398219b2ee8SDavid du Colombierindirection operator can then be used to read and write the register set.
399219b2ee8SDavid du ColombierSince the registers are accessed via Acid variables they may
400219b2ee8SDavid du Colombierbe used in arbitrary expressions.
401219b2ee8SDavid du Colombier.P1
402219b2ee8SDavid du Colombieracid: PC                            // addr of saved PC
403219b2ee8SDavid du Colombier0xc0000f60
404219b2ee8SDavid du Colombieracid: *PC
405219b2ee8SDavid du Colombier0x0000623c                          // contents of PC
406219b2ee8SDavid du Colombieracid: *PC\ea
407219b2ee8SDavid du Colombiermain
408219b2ee8SDavid du Colombieracid: *R1=10                        // modify R1
409219b2ee8SDavid du Colombieracid: asm(*PC+4)                    // disassemble @ PC+4
410219b2ee8SDavid du Colombiermain+0x4 0x00006240 	MOVW	R31,0x0(R29)
411219b2ee8SDavid du Colombiermain+0x8 0x00006244 	MOVW	$setR30(SB),R30
412219b2ee8SDavid du Colombiermain+0x10 0x0000624c 	MOVW	R1,_clock(SB)
413219b2ee8SDavid du Colombier.P2
414219b2ee8SDavid du ColombierHere, the saved
415219b2ee8SDavid du Colombier.CW PC
416219b2ee8SDavid du Colombieris stored at address
417219b2ee8SDavid du Colombier.CW 0xc0000f60 ;
418219b2ee8SDavid du Colombierits current content is
419219b2ee8SDavid du Colombier.CW 0x0000623c .
420219b2ee8SDavid du ColombierThe
421219b2ee8SDavid du Colombier.CW a ' `
422219b2ee8SDavid du Colombierformat code converts this value to a string specifying
423219b2ee8SDavid du Colombierthe address as an offset beyond the nearest symbol.
424219b2ee8SDavid du ColombierAfter setting the value of register
425219b2ee8SDavid du Colombier.CW 1 ,
426219b2ee8SDavid du Colombierthe example uses the
427219b2ee8SDavid du Colombier.CW asm
428219b2ee8SDavid du Colombiercommand to disassemble a short section of code beginning
429219b2ee8SDavid du Colombierat four bytes beyond the current value of the
430219b2ee8SDavid du Colombier.CW PC .
431219b2ee8SDavid du Colombier.NH
432219b2ee8SDavid du ColombierProcess Interface
433219b2ee8SDavid du Colombier.PP
434219b2ee8SDavid du ColombierA program executing under Acid is monitored through the
435219b2ee8SDavid du Colombier.I proc
436219b2ee8SDavid du Colombierfile system interface provided by Plan 9.
437219b2ee8SDavid du ColombierTextual messages written to the
438219b2ee8SDavid du Colombier.CW ctl
439219b2ee8SDavid du Colombierfile control the execution of the process.
440219b2ee8SDavid du ColombierFor example writing
441219b2ee8SDavid du Colombier.CW waitstop
442219b2ee8SDavid du Colombierto the control file causes the write to block until the target
443219b2ee8SDavid du Colombierprocess enters the kernel and is stopped. When the process is stopped
444219b2ee8SDavid du Colombierthe write completes. The
445219b2ee8SDavid du Colombier.CW startstop
446219b2ee8SDavid du Colombiermessage starts the target process and then does a
447219b2ee8SDavid du Colombier.CW waitstop
448219b2ee8SDavid du Colombieraction.
449219b2ee8SDavid du ColombierSynchronization between the debugger and the target process is determined
450219b2ee8SDavid du Colombierby the actions of the various messages. Some operate asynchronously to the
451219b2ee8SDavid du Colombiertarget process and always complete immediately, others block until the
452219b2ee8SDavid du Colombieraction completes. The asynchronous messages allow Acid to control
453219b2ee8SDavid du Colombierseveral processes simultaneously.
454219b2ee8SDavid du Colombier.PP
455219b2ee8SDavid du ColombierThe interpreter has builtin functions named after each of the control
456219b2ee8SDavid du Colombiermessages. The functions take a process id as argument.
457219b2ee8SDavid du ColombierAny time a control message causes the program to execute instructions
458219b2ee8SDavid du Colombierthe interpreter performs two actions when the control operation has completed.
459219b2ee8SDavid du ColombierThe Acid variables pointing at the register set are fixed up to point
460219b2ee8SDavid du Colombierat the saved registers, and then
461219b2ee8SDavid du Colombierthe user defined function
462219b2ee8SDavid du Colombier.CW stopped
463219b2ee8SDavid du Colombieris executed.
464219b2ee8SDavid du ColombierThe
465219b2ee8SDavid du Colombier.CW stopped
466219b2ee8SDavid du Colombierfunction may print the current address,
467219b2ee8SDavid du Colombierline of source or instruction and return to interactive mode. Alternatively
468219b2ee8SDavid du Colombierit may traverse a complex data structure, gather statistics and then set
469219b2ee8SDavid du Colombierthe program running again.
470219b2ee8SDavid du Colombier.PP
471219b2ee8SDavid du ColombierSeveral Acid variables are maintained by the debugger rather than the
472219b2ee8SDavid du Colombierprogrammer.
473219b2ee8SDavid du ColombierThese variables allow generic Acid code to deal with the current process,
474219b2ee8SDavid du Colombierarchitecture specifics or the symbol table.
475219b2ee8SDavid du ColombierThe variable
476219b2ee8SDavid du Colombier.CW pid
477219b2ee8SDavid du Colombieris the process id of the current process Acid is debugging.
478219b2ee8SDavid du ColombierThe variable
479219b2ee8SDavid du Colombier.CW symbols
480219b2ee8SDavid du Colombiercontains a list of lists where each sublist contains the symbol
481219b2ee8SDavid du Colombiername, its type and the value of the symbol.
482219b2ee8SDavid du ColombierThe variable
483219b2ee8SDavid du Colombier.CW registers
484219b2ee8SDavid du Colombiercontains a list of the machine-specific register names. Global symbols in the target program
485219b2ee8SDavid du Colombiercan be referenced directly by name from Acid. Local variables
486219b2ee8SDavid du Colombierare referenced using the colon operator as \f(CWfunction:variable\fP.
487219b2ee8SDavid du Colombier.NH
488219b2ee8SDavid du ColombierSource Level Debugging
489219b2ee8SDavid du Colombier.PP
490219b2ee8SDavid du ColombierAcid provides several builtin functions to manipulate source code.
491219b2ee8SDavid du ColombierThe
492219b2ee8SDavid du Colombier.CW file
493219b2ee8SDavid du Colombierfunction reads a text file, inserting each line into a list.
494219b2ee8SDavid du ColombierThe
495219b2ee8SDavid du Colombier.CW pcfile
496219b2ee8SDavid du Colombierand
497219b2ee8SDavid du Colombier.CW pcline
498219b2ee8SDavid du Colombierfunctions each take an address as an argument.
499219b2ee8SDavid du ColombierThe first
500219b2ee8SDavid du Colombierreturns a string containing the name of the source file
501219b2ee8SDavid du Colombierand the second returns an integer containing the line number
502219b2ee8SDavid du Colombierof the source line containing the instruction at the address.
503219b2ee8SDavid du Colombier.P1
504219b2ee8SDavid du Colombieracid: pcfile(main)		// file containing main
505219b2ee8SDavid du Colombiermain.c
506219b2ee8SDavid du Colombieracid: pcline(main)		// line # of main in source
507219b2ee8SDavid du Colombier11
508219b2ee8SDavid du Colombieracid: file(pcfile(main))[pcline(main)]	// print that line
509219b2ee8SDavid du Colombiermain(int argc, char *argv[])
510219b2ee8SDavid du Colombieracid: src(*PC)			// print statements nearby
511219b2ee8SDavid du Colombier 9
512219b2ee8SDavid du Colombier 10 void
513219b2ee8SDavid du Colombier>11 main(int argc, char *argv[])
514219b2ee8SDavid du Colombier 12 {
515219b2ee8SDavid du Colombier 13	int a;
516219b2ee8SDavid du Colombier.P2
517219b2ee8SDavid du ColombierIn this example, the three primitives are combined in an expression to print
518219b2ee8SDavid du Colombiera line of source code associated with an address.
519219b2ee8SDavid du ColombierThe
520219b2ee8SDavid du Colombier.CW src
521219b2ee8SDavid du Colombierfunction prints a few lines of source
522219b2ee8SDavid du Colombieraround the address supplied as its argument. A companion routine,
523219b2ee8SDavid du Colombier.CW Bsrc ,
524219b2ee8SDavid du Colombiercommunicates with the external editor
525219b2ee8SDavid du Colombier.CW sam .
526219b2ee8SDavid du ColombierGiven an address, it loads the corresponding source file into the editor
527219b2ee8SDavid du Colombierand highlights the line containing the address.  This simple interface
528219b2ee8SDavid du Colombieris easily extended to more complex functions.
529219b2ee8SDavid du ColombierFor example, the
530219b2ee8SDavid du Colombier.CW step
531219b2ee8SDavid du Colombierfunction can select the current file and line in the editor
532219b2ee8SDavid du Colombiereach time the target program stops, giving the user a visual
533219b2ee8SDavid du Colombiertrace of the execution path of the program. A more complete interface
534219b2ee8SDavid du Colombierallowing two way communication between Acid and the
535219b2ee8SDavid du Colombier.CW acme
536219b2ee8SDavid du Colombieruser interface [Pike93] is under construction. A filter between the debugger
537219b2ee8SDavid du Colombierand the user interface provides interpretation of results from both
538219b2ee8SDavid du Colombiersides of the interface. This allows the programming environment to
539219b2ee8SDavid du Colombierinteract with the debugger and vice-versa, a capability missing from the
540219b2ee8SDavid du Colombier.CW sam
541219b2ee8SDavid du Colombierinterface.
542219b2ee8SDavid du ColombierThe
543219b2ee8SDavid du Colombier.CW src
544219b2ee8SDavid du Colombierand
545219b2ee8SDavid du Colombier.CW Bsrc
546219b2ee8SDavid du Colombierfunctions are both written in Acid code using the file and line primitives.
547219b2ee8SDavid du ColombierAcid provides library functions to step through source level
548219b2ee8SDavid du Colombierstatements and functions. Furthermore, addresses in Acid expressions can be
549219b2ee8SDavid du Colombierspecified by source file and line.
550219b2ee8SDavid du ColombierSource code is manipulated in the Acid
551219b2ee8SDavid du Colombier.I list
552219b2ee8SDavid du Colombierdata type.
553219b2ee8SDavid du Colombier.NH
554219b2ee8SDavid du ColombierThe Acid Library
555219b2ee8SDavid du Colombier.PP
556219b2ee8SDavid du ColombierThe following examples define some useful commands and
557219b2ee8SDavid du Colombierillustrate the interaction of the debugger and the interpreter.
558219b2ee8SDavid du Colombier.P1
559219b2ee8SDavid du Colombierdefn bpset(addr)                          // set breakpoint
560219b2ee8SDavid du Colombier{
561219b2ee8SDavid du Colombier	if match(addr, bplist) >= 0 then
562219b2ee8SDavid du Colombier		print("bkpoint already set:", addr\ea, "\en");
563219b2ee8SDavid du Colombier	else {
564219b2ee8SDavid du Colombier		*fmt(addr, bpfmt) = bpinst;   // plant it
565219b2ee8SDavid du Colombier		bplist = append bplist, addr; // add to list
566219b2ee8SDavid du Colombier	}
567219b2ee8SDavid du Colombier}
568219b2ee8SDavid du Colombier.P2
569219b2ee8SDavid du ColombierThe
570219b2ee8SDavid du Colombier.CW bpset
571219b2ee8SDavid du Colombierfunction plants a break point in memory. The function starts by
572219b2ee8SDavid du Colombierusing the
573219b2ee8SDavid du Colombier.CW match
574219b2ee8SDavid du Colombierbuiltin to
575219b2ee8SDavid du Colombiersearch the breakpoint list to determine if a breakpoint is already
576219b2ee8SDavid du Colombierset at the address.
577219b2ee8SDavid du ColombierThe indirection operator, controlled by the format code returned
578219b2ee8SDavid du Colombierby the
579219b2ee8SDavid du Colombier.CW fmt
580219b2ee8SDavid du Colombierprimitive, is used to plant the breakpoint in memory.
581219b2ee8SDavid du ColombierThe variables
582219b2ee8SDavid du Colombier.CW bpfmt
583219b2ee8SDavid du Colombierand
584219b2ee8SDavid du Colombier.CW bpinst
585219b2ee8SDavid du Colombierare Acid global variables containing the format code specifying
586219b2ee8SDavid du Colombierthe size of the breakpoint instruction and the breakpoint instruction
587219b2ee8SDavid du Colombieritself.
588219b2ee8SDavid du ColombierThese
589219b2ee8SDavid du Colombiervariables are set by architecture-dependent library code
590219b2ee8SDavid du Colombierwhen the debugger first attaches to the executing image.
591219b2ee8SDavid du ColombierFinally the address of the breakpoint is
592219b2ee8SDavid du Colombierappended to the breakpoint list,
593219b2ee8SDavid du Colombier.CW bplist .
594219b2ee8SDavid du Colombier.P1
595219b2ee8SDavid du Colombierdefn step()				// single step
596219b2ee8SDavid du Colombier{
597219b2ee8SDavid du Colombier	local lst, lpl, addr, bput;
598219b2ee8SDavid du Colombier
599219b2ee8SDavid du Colombier	bput = 0;			// sitting on bkpoint
600219b2ee8SDavid du Colombier	if match(*PC, bplist) >= 0 then {
601219b2ee8SDavid du Colombier		bput = fmt(*PC, bpfmt);	// save current addr
602219b2ee8SDavid du Colombier		*bput = @bput;		// replace it
603219b2ee8SDavid du Colombier	}
604219b2ee8SDavid du Colombier
605219b2ee8SDavid du Colombier	lst = follow(*PC);		// get follow set
606219b2ee8SDavid du Colombier
607219b2ee8SDavid du Colombier	lpl = lst;
608219b2ee8SDavid du Colombier	while lpl do {			// place breakpoints
609219b2ee8SDavid du Colombier		*(head lpl) = bpinst;
610219b2ee8SDavid du Colombier		lpl = tail lpl;
611219b2ee8SDavid du Colombier	}
612219b2ee8SDavid du Colombier
613219b2ee8SDavid du Colombier	startstop(pid);			// do the step
614219b2ee8SDavid du Colombier
615219b2ee8SDavid du Colombier	while lst do {			// remove breakpoints
616219b2ee8SDavid du Colombier		addr = fmt(head lst, bpfmt);
617219b2ee8SDavid du Colombier		*addr = @addr;		// replace instr.
618219b2ee8SDavid du Colombier		lst = tail lst;
619219b2ee8SDavid du Colombier	}
620219b2ee8SDavid du Colombier	if bput != 0 then
621219b2ee8SDavid du Colombier		*bput = bpinst;		// restore breakpoint
622219b2ee8SDavid du Colombier}
623219b2ee8SDavid du Colombier.P2
624219b2ee8SDavid du ColombierThe
625219b2ee8SDavid du Colombier.CW step
626219b2ee8SDavid du Colombierfunction executes a single assembler instruction.
627219b2ee8SDavid du ColombierIf the
628219b2ee8SDavid du Colombier.CW PC
629219b2ee8SDavid du Colombieris sitting
630219b2ee8SDavid du Colombieron a breakpoint, the address and size of
631219b2ee8SDavid du Colombierthe breakpoint are saved.
632219b2ee8SDavid du ColombierThe breakpoint instruction
633219b2ee8SDavid du Colombieris then removed using the
634219b2ee8SDavid du Colombier.CW @
635219b2ee8SDavid du Colombieroperator to fetch
636219b2ee8SDavid du Colombier.CW bpfmt
637219b2ee8SDavid du Colombierbytes from the text file and to place it into the memory
638219b2ee8SDavid du Colombierof the executing process using the
639219b2ee8SDavid du Colombier.CW *
640219b2ee8SDavid du Colombieroperator.
641219b2ee8SDavid du ColombierThe
642219b2ee8SDavid du Colombier.CW follow
643219b2ee8SDavid du Colombierfunction is an Acid
644219b2ee8SDavid du Colombierbuiltin which returns a follow-set: a list of instruction addresses which
645219b2ee8SDavid du Colombiercould be executed next.
646219b2ee8SDavid du ColombierIf the instruction stored at the
647219b2ee8SDavid du Colombier.CW PC
648219b2ee8SDavid du Colombieris a branch instruction, the
649219b2ee8SDavid du Colombierlist contains the addresses of the next instruction and
650219b2ee8SDavid du Colombierthe branch destination; otherwise, it contains only the
651219b2ee8SDavid du Colombieraddress of the next instruction.
652219b2ee8SDavid du ColombierThe follow-set is then used to replace each possible following
653219b2ee8SDavid du Colombierinstruction with a breakpoint instruction.  The original
654219b2ee8SDavid du Colombierinstructions need not be saved; they remain
655219b2ee8SDavid du Colombierin their unaltered state in the text file.
656219b2ee8SDavid du ColombierThe
657219b2ee8SDavid du Colombier.CW startstop
658219b2ee8SDavid du Colombierbuiltin writes the `startstop' message to the
659219b2ee8SDavid du Colombier.I proc
660219b2ee8SDavid du Colombiercontrol file for the process named
661219b2ee8SDavid du Colombier.CW pid .
662219b2ee8SDavid du ColombierThe target process executes until some condition causes it to
663219b2ee8SDavid du Colombierenter the kernel, in this case, the execution of a breakpoint.
664219b2ee8SDavid du ColombierWhen the process blocks, the debugger regains control and invokes the
665219b2ee8SDavid du ColombierAcid library function
666219b2ee8SDavid du Colombier.CW stopped
667219b2ee8SDavid du Colombierwhich reports the address and cause of the blockage.
668219b2ee8SDavid du ColombierThe
669219b2ee8SDavid du Colombier.CW startstop
670219b2ee8SDavid du Colombierfunction completes and returns to the
671219b2ee8SDavid du Colombier.CW step
672219b2ee8SDavid du Colombierfunction where
673219b2ee8SDavid du Colombierthe follow-set is used to replace the breakpoints placed earlier.
674219b2ee8SDavid du ColombierFinally, if the address of the original
675219b2ee8SDavid du Colombier.CW PC
676219b2ee8SDavid du Colombiercontained a breakpoint, it is replaced.
677219b2ee8SDavid du Colombier.PP
678219b2ee8SDavid du ColombierNotice that this approach to process control is inherently portable;
679219b2ee8SDavid du Colombierthe Acid code is shared by the debuggers for all architectures.
680219b2ee8SDavid du ColombierAcid variables and builtin functions provide a transparent interface
681219b2ee8SDavid du Colombierto architecture-dependent values and functions.  Here the breakpoint
682219b2ee8SDavid du Colombiervalue and format are referenced through Acid variables and the
683219b2ee8SDavid du Colombier.CW follow
684219b2ee8SDavid du Colombierprimitive masks the differences in the underlying instruction set.
685219b2ee8SDavid du Colombier.PP
686219b2ee8SDavid du ColombierThe
687219b2ee8SDavid du Colombier.CW next
688219b2ee8SDavid du Colombierfunction, similar to the
689219b2ee8SDavid du Colombier.I dbx
690219b2ee8SDavid du Colombiercommand of the same name,
691219b2ee8SDavid du Colombieris a simpler example.
692219b2ee8SDavid du ColombierThis function steps through
693219b2ee8SDavid du Colombiera single source statement but steps over function calls.
694219b2ee8SDavid du Colombier.P1
695219b2ee8SDavid du Colombierdefn next()
696219b2ee8SDavid du Colombier{
697219b2ee8SDavid du Colombier	local sp, bound;
698219b2ee8SDavid du Colombier
699219b2ee8SDavid du Colombier	sp = *SP;			// save starting SP
700219b2ee8SDavid du Colombier	bound = fnbound(*PC);		// begin & end of fn.
701219b2ee8SDavid du Colombier	stmnt();			// step 1 statement
702219b2ee8SDavid du Colombier	pc = *PC;
703219b2ee8SDavid du Colombier	if pc >= bound[0] && pc < bound[1] then
704219b2ee8SDavid du Colombier		return {};
705219b2ee8SDavid du Colombier
706219b2ee8SDavid du Colombier	while (pc<bound[0] || pc>bound[1]) && sp>=*SP do {
707219b2ee8SDavid du Colombier		step();
708219b2ee8SDavid du Colombier		pc = *PC;
709219b2ee8SDavid du Colombier	}
710219b2ee8SDavid du Colombier	src(*PC);
711219b2ee8SDavid du Colombier}
712219b2ee8SDavid du Colombier.P2
713219b2ee8SDavid du ColombierThe
714219b2ee8SDavid du Colombier.CW next
715219b2ee8SDavid du Colombierfunction
716219b2ee8SDavid du Colombierstarts by saving the current stack pointer in a local variable.
717219b2ee8SDavid du ColombierIt then uses the Acid library function
718219b2ee8SDavid du Colombier.CW fnbound
719219b2ee8SDavid du Colombierto return the addresses of the first and last instructions in
720219b2ee8SDavid du Colombierthe current function in a list.
721219b2ee8SDavid du ColombierThe
722219b2ee8SDavid du Colombier.CW stmnt
723219b2ee8SDavid du Colombierfunction executes a single source statement and then uses
724219b2ee8SDavid du Colombier.CW src
725219b2ee8SDavid du Colombierto print a few lines of source around the new
726219b2ee8SDavid du Colombier.CW PC .
727219b2ee8SDavid du ColombierIf the new value of the
728219b2ee8SDavid du Colombier.CW PC
729219b2ee8SDavid du Colombierremains in the current function,
730219b2ee8SDavid du Colombier.CW next
731219b2ee8SDavid du Colombierreturns.
732219b2ee8SDavid du ColombierWhen the executed statement is a function call or a return
733219b2ee8SDavid du Colombierfrom a function, the new value of the
734219b2ee8SDavid du Colombier.CW PC
735219b2ee8SDavid du Colombieris outside the bounds calculated by
736219b2ee8SDavid du Colombier.CW fnbound
737219b2ee8SDavid du Colombierand the test of the
738219b2ee8SDavid du Colombier.CW while
739219b2ee8SDavid du Colombierloop is evaluated.
740219b2ee8SDavid du ColombierIf the statement was a return, the new value of the stack pointer
741219b2ee8SDavid du Colombieris greater than the original value and the loop completes without
742219b2ee8SDavid du Colombierexecution.
743219b2ee8SDavid du ColombierOtherwise, the loop is entered and instructions are continually
744219b2ee8SDavid du Colombierexecuted until the value of the
745219b2ee8SDavid du Colombier.CW PC
746219b2ee8SDavid du Colombieris between the bounds calculated earlier.  At that point, execution
747219b2ee8SDavid du Colombierceases and a few lines of source in the vicinity of the
748219b2ee8SDavid du Colombier.CW PC
749219b2ee8SDavid du Colombierare printed.
750219b2ee8SDavid du Colombier.PP
751219b2ee8SDavid du ColombierAcid provides concise and elegant expression for control and
752219b2ee8SDavid du Colombiermanipulation of target programs. These examples demonstrate how a
753219b2ee8SDavid du Colombierfew well-chosen primitives can be combined to create a rich debugging environment.
754219b2ee8SDavid du Colombier.NH
755219b2ee8SDavid du ColombierDealing With Multiple Architectures
756219b2ee8SDavid du Colombier.PP
757219b2ee8SDavid du ColombierA single binary of Acid may be used to debug a program running on any
758219b2ee8SDavid du Colombierof the five processor architectures supported by Plan 9.  For example,
759219b2ee8SDavid du ColombierPlan 9 allows a user on a MIPS to import the
760219b2ee8SDavid du Colombier.I proc
761219b2ee8SDavid du Colombierfile system from an i486-based PC and remotely debug a program executing
762219b2ee8SDavid du Colombieron that processor.
763219b2ee8SDavid du Colombier.PP
764219b2ee8SDavid du ColombierTwo levels of abstraction provide this architecture independence.
765219b2ee8SDavid du ColombierOn the lowest level, a Plan 9 library supplies functions to
766219b2ee8SDavid du Colombierdecode the file header of the program being debugged and
767219b2ee8SDavid du Colombierselect a table of system parameters
768219b2ee8SDavid du Colombierand a jump vector of architecture-dependent
769219b2ee8SDavid du Colombierfunctions based on the magic number.
770219b2ee8SDavid du ColombierAmong these functions are byte-order-independent
771219b2ee8SDavid du Colombieraccess to memory and text files, stack manipulation, disassembly,
772219b2ee8SDavid du Colombierand floating point number interpretation.
773219b2ee8SDavid du ColombierThe second level of abstraction is supplied by Acid.
774219b2ee8SDavid du ColombierIt consists of primitives and approximately 200 lines
775219b2ee8SDavid du Colombierof architecture-dependent Acid library code that interface the
776219b2ee8SDavid du Colombierinterpreter to the architecture-dependent library.
777219b2ee8SDavid du ColombierThis layer performs functions such as mapping register names to
778219b2ee8SDavid du Colombiermemory locations, supplying breakpoint values and sizes,
779219b2ee8SDavid du Colombierand converting processor specific data to Acid data types.
780219b2ee8SDavid du ColombierAn example of the latter is the stack trace function
781219b2ee8SDavid du Colombier.CW strace ,
782219b2ee8SDavid du Colombierwhich uses the stack traversal functions in the
783219b2ee8SDavid du Colombierarchitecture-dependent library to construct a list of lists describing
784219b2ee8SDavid du Colombierthe context of a process.  The first level of list selects
785219b2ee8SDavid du Colombiereach function in the trace; subordinate lists contain the
786219b2ee8SDavid du Colombiernames and values of parameters and local variables of
787219b2ee8SDavid du Colombierthe functions.  Acid commands and library functions that
788219b2ee8SDavid du Colombiermanipulate and display process state information operate
789219b2ee8SDavid du Colombieron the list representation and are independent of the
790219b2ee8SDavid du Colombierunderlying architecture.
791219b2ee8SDavid du Colombier.NH
792219b2ee8SDavid du ColombierAlef Runtime
793219b2ee8SDavid du Colombier.PP
794219b2ee8SDavid du ColombierAlef is a concurrent programming language,
795219b2ee8SDavid du Colombierdesigned specifically for systems programming, which supports both
796219b2ee8SDavid du Colombiershared variable and message passing paradigms.
797219b2ee8SDavid du ColombierAlef borrows the C expression syntax but implements
798219b2ee8SDavid du Colombiera substantially different type system.
799219b2ee8SDavid du ColombierThe language provides a rich set of
800219b2ee8SDavid du Colombierexception handling, process management, and synchronization
801219b2ee8SDavid du Colombierprimitives, which rely on a runtime system.
802219b2ee8SDavid du ColombierAlef program bugs are often deadlocks, synchronization failures,
803219b2ee8SDavid du Colombieror non-termination caused by locks being held incorrectly.
804219b2ee8SDavid du ColombierIn such cases, a process stalls deep
805219b2ee8SDavid du Colombierin the runtime code and it is clearly
806219b2ee8SDavid du Colombierunreasonable to expect a programmer using the language
807219b2ee8SDavid du Colombierto understand the detailed
808219b2ee8SDavid du Colombierinternal semantics of the runtime support functions.
809219b2ee8SDavid du Colombier.PP
810219b2ee8SDavid du ColombierInstead, there is an Alef support library, coded in Acid, that
811219b2ee8SDavid du Colombierallows the programmer to interpret the program state in terms of
812219b2ee8SDavid du ColombierAlef operations.  Consider the example of a multi-process program
813219b2ee8SDavid du Colombierstalling because of improper synchronization.  A stack trace of
814219b2ee8SDavid du Colombierthe program indicates that it is waiting for an event in some
815219b2ee8SDavid du Colombierobscure Alef runtime
816219b2ee8SDavid du Colombiersynchronization function.
817219b2ee8SDavid du ColombierThe function itself is irrelevant to the
818219b2ee8SDavid du Colombierprogrammer; of greater importance is the identity of the
819219b2ee8SDavid du Colombierunfulfilled event.
820219b2ee8SDavid du ColombierCommands in the Alef support library decode
821219b2ee8SDavid du Colombierthe runtime data structures and program state to report the cause
822219b2ee8SDavid du Colombierof the blockage in terms of the high-level operations available to
823219b2ee8SDavid du Colombierthe Alef programmer.
824219b2ee8SDavid du ColombierHere, the Acid language acts
825219b2ee8SDavid du Colombieras a communications medium between Alef implementer and Alef user.
826219b2ee8SDavid du Colombier.NH
827219b2ee8SDavid du ColombierParallel Debugging
828219b2ee8SDavid du Colombier.PP
829219b2ee8SDavid du ColombierThe central issue in parallel debugging is how the debugger is
830219b2ee8SDavid du Colombiermultiplexed between the processes comprising
831219b2ee8SDavid du Colombierthe program.
832219b2ee8SDavid du ColombierAcid has no intrinsic model of process partitioning; it
833219b2ee8SDavid du Colombieronly assumes that parallel programs share a symbol table,
834219b2ee8SDavid du Colombierthough they need not share memory.
835219b2ee8SDavid du ColombierThe
836219b2ee8SDavid du Colombier.CW setproc
837219b2ee8SDavid du Colombierprimitive attaches the debugger to a running process
838219b2ee8SDavid du Colombierassociated with the process ID supplied as its argument
839219b2ee8SDavid du Colombierand assigns that value to the global variable
840219b2ee8SDavid du Colombier.CW pid ,
841219b2ee8SDavid du Colombierthereby allowing simple rotation among a group of processes.
842219b2ee8SDavid du ColombierFurther, the stack trace primitive is driven by parameters
843219b2ee8SDavid du Colombierspecifying a unique process context, so it is possible to
844219b2ee8SDavid du Colombierexamine the state of cooperating processes without switching
845219b2ee8SDavid du Colombierthe debugger focus from the process of interest.
846219b2ee8SDavid du ColombierSince Acid is inherently extensible and capable of
847219b2ee8SDavid du Colombierdynamic interaction with subordinate processes, the
848219b2ee8SDavid du Colombierprogrammer can define Acid commands to detect and control
849219b2ee8SDavid du Colombiercomplex interactions between processes.
850219b2ee8SDavid du ColombierIn short, the programmer is free to specify how the debugger reacts
851219b2ee8SDavid du Colombierto events generated in specific threads of the program.
852219b2ee8SDavid du Colombier.PP
853219b2ee8SDavid du ColombierThe support for parallel debugging in Acid depends on a crucial kernel
854219b2ee8SDavid du Colombiermodification: when the text segment of a program is written (usually to
855219b2ee8SDavid du Colombierplace a breakpoint), the segment is cloned to prevent other threads
856219b2ee8SDavid du Colombierfrom encountering the breakpoint.  Although this incurs a slight performance
857219b2ee8SDavid du Colombierpenalty, it is of little importance while debugging.
858219b2ee8SDavid du Colombier.NH
859219b2ee8SDavid du ColombierCommunication Between Tools
860219b2ee8SDavid du Colombier.PP
861219b2ee8SDavid du ColombierThe Plan 9 Alef and C compilers do not
862219b2ee8SDavid du Colombierembed detailed type information in the symbol table of an
863219b2ee8SDavid du Colombierexecutable file.
864219b2ee8SDavid du ColombierHowever, they do accept a command line option causing them to
865219b2ee8SDavid du Colombieremit descriptions of complex data types
866219b2ee8SDavid du Colombier(e.g., aggregates and abstract data types)
867219b2ee8SDavid du Colombierto an auxiliary file.
868219b2ee8SDavid du ColombierThe vehicle for expressing this information is Acid source code.
869219b2ee8SDavid du ColombierWhen an Acid debugging session is
870219b2ee8SDavid du Colombiersubsequently started, that file is loaded with the other Acid libraries.
871219b2ee8SDavid du Colombier.PP
872219b2ee8SDavid du ColombierFor each complex object in the program the compiler generates
873219b2ee8SDavid du Colombierthree pieces of Acid code.
874219b2ee8SDavid du ColombierThe first is a table describing the size and offset of each
875219b2ee8SDavid du Colombiermember of the complex data type.  Following is an Acid function,
876219b2ee8SDavid du Colombiernamed the same as the object, that formats and prints each member.
877219b2ee8SDavid du ColombierFinally, Acid declarations associate the
878219b2ee8SDavid du ColombierAlef or C program variables of a type with the functions
879219b2ee8SDavid du Colombierto print them.
880219b2ee8SDavid du ColombierThe three forms of declaration are shown in the following example:
881219b2ee8SDavid du Colombier.P1
882219b2ee8SDavid du Colombierstruct Bitmap {
883219b2ee8SDavid du Colombier	Rectangle    0 r;
884219b2ee8SDavid du Colombier	Rectangle   16 clipr;
885219b2ee8SDavid du Colombier	'D'   32 ldepth;
886219b2ee8SDavid du Colombier	'D'   36 id;
887219b2ee8SDavid du Colombier	'X'   40 cache;
888219b2ee8SDavid du Colombier};
889219b2ee8SDavid du Colombier.P2
890219b2ee8SDavid du Colombier.P1
891219b2ee8SDavid du Colombierdefn
892219b2ee8SDavid du ColombierBitmap(addr) {
893219b2ee8SDavid du Colombier	complex Bitmap addr;
894219b2ee8SDavid du Colombier	print("Rectangle r {\en");
895219b2ee8SDavid du Colombier	Rectangle(addr.r);
896219b2ee8SDavid du Colombier	print("}\en");
897219b2ee8SDavid du Colombier	print("Rectangle clipr {\en");
898219b2ee8SDavid du Colombier	Rectangle(addr.clipr);
899219b2ee8SDavid du Colombier	print("}\en");
900219b2ee8SDavid du Colombier	print("	ldepth	", addr.ldepth, "\en");
901219b2ee8SDavid du Colombier	print("	id	", addr.id, "\en");
902219b2ee8SDavid du Colombier	print("	cache	", addr.cache, "\en");
903219b2ee8SDavid du Colombier};
904219b2ee8SDavid du Colombier
905219b2ee8SDavid du Colombiercomplex Bitmap darkgrey;
906219b2ee8SDavid du Colombiercomplex Bitmap Window_settag:b;
907219b2ee8SDavid du Colombier.P2
908219b2ee8SDavid du ColombierThe
909219b2ee8SDavid du Colombier.CW struct
910219b2ee8SDavid du Colombierdeclaration specifies decoding instructions for the complex type named
911219b2ee8SDavid du Colombier.CW Bitmap .
912219b2ee8SDavid du ColombierAlthough the syntax is superficially similar to a C structure declaration,
913219b2ee8SDavid du Colombierthe semantics differ markedly: the C declaration specifies a layout, while
914219b2ee8SDavid du Colombierthe Acid declaration tells how to decode it.
915219b2ee8SDavid du ColombierThe declaration specifies a type, an offset, and name for each
916219b2ee8SDavid du Colombiermember of the complex object. The type is either the name of another
917219b2ee8SDavid du Colombiercomplex declaration, for example,
918219b2ee8SDavid du Colombier.CW Rectangle ,
919219b2ee8SDavid du Colombieror a format code.
920219b2ee8SDavid du ColombierThe offset is the number of bytes from the start
921219b2ee8SDavid du Colombierof the object to the member
922219b2ee8SDavid du Colombierand the name is the member's name in the Alef or C declaration.
923219b2ee8SDavid du ColombierThis type description is a close match for C and Alef, but is simple enough
924219b2ee8SDavid du Colombierto be language independent.
925219b2ee8SDavid du Colombier.PP
926219b2ee8SDavid du ColombierThe
927219b2ee8SDavid du Colombier.CW Bitmap
928219b2ee8SDavid du Colombierfunction expects the address of a
929219b2ee8SDavid du Colombier.CW Bitmap
930219b2ee8SDavid du Colombieras its only argument.
931219b2ee8SDavid du ColombierIt uses the decoding information contained in the
932219b2ee8SDavid du Colombier.CW Bitmap
933219b2ee8SDavid du Colombierstructure declaration to extract, format, and print the
934219b2ee8SDavid du Colombiervalue of each member of the complex object pointed to by
935219b2ee8SDavid du Colombierthe argument.
936219b2ee8SDavid du ColombierThe Alef compiler emits code to call other Acid functions
937219b2ee8SDavid du Colombierwhere a member is another complex type; here,
938219b2ee8SDavid du Colombier.CW Bitmap
939219b2ee8SDavid du Colombiercalls
940219b2ee8SDavid du Colombier.CW Rectangle
941219b2ee8SDavid du Colombierto print its contents.
942219b2ee8SDavid du Colombier.PP
943219b2ee8SDavid du ColombierThe
944219b2ee8SDavid du Colombier.CW complex
945219b2ee8SDavid du Colombierdeclarations associate Alef variables with complex types.
946219b2ee8SDavid du ColombierIn the example,
947219b2ee8SDavid du Colombier.CW darkgrey
948219b2ee8SDavid du Colombieris the name of a global variable of type
949219b2ee8SDavid du Colombier.CW Bitmap
950219b2ee8SDavid du Colombierin the program being debugged.
951219b2ee8SDavid du ColombierWhenever the name
952219b2ee8SDavid du Colombier.CW darkgrey
953219b2ee8SDavid du Colombieris evaluated by Acid, it automatically calls the
954219b2ee8SDavid du Colombier.CW Bitmap
955219b2ee8SDavid du Colombierfunction with the address of
956219b2ee8SDavid du Colombier.CW darkgrey
957219b2ee8SDavid du Colombieras the argument.
958219b2ee8SDavid du ColombierThe second
959219b2ee8SDavid du Colombier.CW complex
960219b2ee8SDavid du Colombierdeclaration associates a local variable or parameter named
961219b2ee8SDavid du Colombier.CW b
962219b2ee8SDavid du Colombierin function
963219b2ee8SDavid du Colombier.CW Window_settag
964219b2ee8SDavid du Colombierwith the
965219b2ee8SDavid du Colombier.CW Bitmap
966219b2ee8SDavid du Colombiercomplex data type.
967219b2ee8SDavid du Colombier.PP
968219b2ee8SDavid du ColombierAcid borrows the C operators
969219b2ee8SDavid du Colombier.CW .
970219b2ee8SDavid du Colombierand
971219b2ee8SDavid du Colombier.CW ->
972219b2ee8SDavid du Colombierto access the decoding parameters of a member of a complex type.
973219b2ee8SDavid du ColombierAlthough this representation is sufficiently general for describing
974219b2ee8SDavid du Colombierthe decoding of both C and Alef complex data types, it may
975219b2ee8SDavid du Colombierprove too restrictive for target languages with more complicated
976219b2ee8SDavid du Colombiertype systems.
977219b2ee8SDavid du ColombierFurther, the assumption that the compiler can select the proper
978219b2ee8SDavid du ColombierAcid format code for each basic type in the language is somewhat
979219b2ee8SDavid du Colombiernaive.  For example, when a member of a complex type is a pointer,
980219b2ee8SDavid du Colombierit is assigned a hexadecimal type code; integer members are always
981219b2ee8SDavid du Colombierassigned a decimal type code.
982219b2ee8SDavid du ColombierThis heuristic proves inaccurate when an integer field is a
983219b2ee8SDavid du Colombierbit mask or set of bit flags which are more appropriately displayed
984219b2ee8SDavid du Colombierin hexadecimal or octal.
985219b2ee8SDavid du Colombier.NH
986219b2ee8SDavid du ColombierCode Verification
987219b2ee8SDavid du Colombier.PP
988219b2ee8SDavid du ColombierAcid's ability to interact dynamically with
989219b2ee8SDavid du Colombieran executing program allows passive test and
990219b2ee8SDavid du Colombierverification of the target program.  For example,
991219b2ee8SDavid du Colombiera common concern is leak detection in programs using
992219b2ee8SDavid du Colombier.CW malloc .
993219b2ee8SDavid du ColombierOf interest are two items: finding memory that was allocated
994219b2ee8SDavid du Colombierbut never freed and detecting bad pointers passed to
995219b2ee8SDavid du Colombier.CW free .
996219b2ee8SDavid du ColombierAn auxiliary Acid library contains Acid functions to
997219b2ee8SDavid du Colombiermonitor the execution of a program and detect these
998219b2ee8SDavid du Colombierfaults, either as they happen or in the automated
999219b2ee8SDavid du Colombierpost-mortem analysis of the memory arena.
1000219b2ee8SDavid du ColombierIn the following example, the
1001219b2ee8SDavid du Colombier.CW sort
1002219b2ee8SDavid du Colombiercommand is run under the control of the
1003219b2ee8SDavid du ColombierAcid memory leak library.
1004219b2ee8SDavid du Colombier.P1
1005219b2ee8SDavid du Colombierhelix% acid -l malloc /bin/sort
1006219b2ee8SDavid du Colombier/bin/sort: mips plan 9 executable
1007219b2ee8SDavid du Colombier/lib/acid/port
1008219b2ee8SDavid du Colombier/lib/acid/mips
1009219b2ee8SDavid du Colombier/lib/acid/malloc
1010219b2ee8SDavid du Colombieracid: go()
1011219b2ee8SDavid du Colombiernow
1012219b2ee8SDavid du Colombieris
1013219b2ee8SDavid du Colombierthe
1014219b2ee8SDavid du Colombiertime
1015219b2ee8SDavid du Colombier<ctrl-d>
1016219b2ee8SDavid du Colombieris
1017219b2ee8SDavid du Colombiernow
1018219b2ee8SDavid du Colombierthe
1019219b2ee8SDavid du Colombiertime
1020219b2ee8SDavid du Colombier27680 : breakpoint	_exits+0x4	MOVW	$0x8,R1
1021219b2ee8SDavid du Colombieracid:
1022219b2ee8SDavid du Colombier.P2
1023219b2ee8SDavid du ColombierThe
1024219b2ee8SDavid du Colombier.CW go
1025219b2ee8SDavid du Colombiercommand creates a process and plants
1026219b2ee8SDavid du Colombierbreakpoints at the entry to
1027219b2ee8SDavid du Colombier.CW malloc
1028219b2ee8SDavid du Colombierand
1029219b2ee8SDavid du Colombier.CW free .
1030219b2ee8SDavid du ColombierThe program is then started and continues until it
1031219b2ee8SDavid du Colombierexits or stops.  If the reason for stopping is anything
1032219b2ee8SDavid du Colombierother than the breakpoints in
1033219b2ee8SDavid du Colombier.CW malloc
1034219b2ee8SDavid du Colombierand
1035219b2ee8SDavid du Colombier.CW free ,
1036219b2ee8SDavid du ColombierAcid prints the usual status information and returns to the
1037219b2ee8SDavid du Colombierinteractive prompt.
1038219b2ee8SDavid du Colombier.PP
1039219b2ee8SDavid du ColombierWhen the process stops on entering
1040219b2ee8SDavid du Colombier.CW malloc ,
1041219b2ee8SDavid du Colombierthe debugger must capture and save the address that
1042219b2ee8SDavid du Colombier.CW malloc
1043219b2ee8SDavid du Colombierwill return.
1044219b2ee8SDavid du ColombierAfter saving a stack
1045219b2ee8SDavid du Colombiertrace so the calling routine can be identified, it places
1046219b2ee8SDavid du Colombiera breakpoint at the return address and restarts the program.
1047219b2ee8SDavid du ColombierWhen
1048219b2ee8SDavid du Colombier.CW malloc
1049219b2ee8SDavid du Colombierreturns, the breakpoint stops the program,
1050219b2ee8SDavid du Colombierallowing the debugger
1051219b2ee8SDavid du Colombierto grab the address of the new memory block from the return register.
1052219b2ee8SDavid du ColombierThe address and stack trace are added to the list of outstanding
1053219b2ee8SDavid du Colombiermemory blocks, the breakpoint is removed from the return point, and
1054219b2ee8SDavid du Colombierthe process is restarted.
1055219b2ee8SDavid du Colombier.PP
1056219b2ee8SDavid du ColombierWhen the process stops at the beginning of
1057219b2ee8SDavid du Colombier.CW free ,
1058219b2ee8SDavid du Colombierthe memory address supplied as the argument is compared to the list
1059219b2ee8SDavid du Colombierof outstanding memory blocks.  If it is not found an error message
1060219b2ee8SDavid du Colombierand a stack trace of the call is reported; otherwise, the
1061219b2ee8SDavid du Colombieraddress is deleted from the list.
1062219b2ee8SDavid du Colombier.PP
1063219b2ee8SDavid du ColombierWhen the program exits, the list of outstanding memory blocks contains
1064219b2ee8SDavid du Colombierthe addresses of all blocks that were allocated but never freed.
1065219b2ee8SDavid du ColombierThe
1066219b2ee8SDavid du Colombier.CW leak
1067219b2ee8SDavid du Colombierlibrary function traverses the list producing a report describing
1068219b2ee8SDavid du Colombierthe allocated blocks.
1069219b2ee8SDavid du Colombier.P1 1m
1070219b2ee8SDavid du Colombieracid: leak()
1071219b2ee8SDavid du ColombierLost a total of 524288 bytes from:
1072219b2ee8SDavid du Colombier    malloc() malloc.c:32 called from dofile+0xe8 sort.c:217
1073219b2ee8SDavid du Colombier    dofile() sort.c:190 called from main+0xac sort.c:161
1074219b2ee8SDavid du Colombier    main() sort.c:128 called from _main+0x20 main9.s:10
1075219b2ee8SDavid du ColombierLost a total of 64 bytes from:
1076219b2ee8SDavid du Colombier    malloc() malloc.c:32 called from newline+0xfc sort.c:280
1077219b2ee8SDavid du Colombier    newline() sort.c:248 called from dofile+0x110 sort.c:222
1078219b2ee8SDavid du Colombier    dofile() sort.c:190 called from main+0xac sort.c:161
1079219b2ee8SDavid du Colombier    main() sort.c:128 called from _main+0x20 main9.s:10
1080219b2ee8SDavid du ColombierLost a total of 64 bytes from:
1081219b2ee8SDavid du Colombier    malloc() malloc.c:32 called from realloc+0x14 malloc.c:129
1082219b2ee8SDavid du Colombier    realloc() malloc.c:123 called from bldkey+0x358 sort.c:1388
1083219b2ee8SDavid du Colombier    buildkey() sort.c:1345 called from newline+0x150 sort.c:285
1084219b2ee8SDavid du Colombier    newline() sort.c:248 called from dofile+0x110 sort.c:222
1085219b2ee8SDavid du Colombier    dofile() sort.c:190 called from main+0xac sort.c:161
1086219b2ee8SDavid du Colombier    main() sort.c:128 called from _main+0x20 main9.s:10
1087219b2ee8SDavid du Colombieracid: refs()
1088219b2ee8SDavid du Colombierdata...bss...stack...
1089219b2ee8SDavid du Colombieracid: leak()
1090219b2ee8SDavid du Colombieracid:
1091219b2ee8SDavid du Colombier.P2
1092219b2ee8SDavid du ColombierThe presence of a block in the allocation list does not imply
1093219b2ee8SDavid du Colombierit is there because of a leak; for instance, it may have been
1094219b2ee8SDavid du Colombierin use when the program terminated.
1095219b2ee8SDavid du ColombierThe
1096219b2ee8SDavid du Colombier.CW refs()
1097219b2ee8SDavid du Colombierlibrary function scans the
1098219b2ee8SDavid du Colombier.I data ,
1099219b2ee8SDavid du Colombier.I bss ,
1100219b2ee8SDavid du Colombierand
1101219b2ee8SDavid du Colombier.I stack
1102219b2ee8SDavid du Colombiersegments of the process looking for pointers
1103219b2ee8SDavid du Colombierinto the allocated blocks.  When one is found, the block is deleted from
1104219b2ee8SDavid du Colombierthe outstanding block list.
1105219b2ee8SDavid du ColombierThe
1106219b2ee8SDavid du Colombier.CW leak
1107219b2ee8SDavid du Colombierfunction is used again to report the
1108219b2ee8SDavid du Colombierblocks remaining allocated and unreferenced.
1109219b2ee8SDavid du ColombierThis strategy proves effective in detecting
1110219b2ee8SDavid du Colombierdisconnected (but non-circular) data structures.
1111219b2ee8SDavid du Colombier.PP
1112219b2ee8SDavid du ColombierThe leak detection process is entirely passive.
1113219b2ee8SDavid du ColombierThe program is not
1114219b2ee8SDavid du Colombierspecially compiled and the source code is not required.
1115219b2ee8SDavid du ColombierAs with the Acid support functions for the Alef runtime environment,
1116219b2ee8SDavid du Colombierthe author of the library routines has encapsulated the
1117219b2ee8SDavid du Colombierfunctionality of the library interface
1118219b2ee8SDavid du Colombierin Acid code.
1119219b2ee8SDavid du ColombierAny programmer may then check a program's use of the
1120219b2ee8SDavid du Colombierlibrary routines without knowledge of either implementation.
1121219b2ee8SDavid du ColombierThe performance impact of running leak detection is great
1122219b2ee8SDavid du Colombier(about 10 times slower),
1123219b2ee8SDavid du Colombierbut it has not prevented interactive programs like
1124219b2ee8SDavid du Colombier.CW sam
1125219b2ee8SDavid du Colombierand the
1126219b2ee8SDavid du Colombier.CW 8½
1127219b2ee8SDavid du Colombierwindow system from being tested.
1128219b2ee8SDavid du Colombier.NH
1129219b2ee8SDavid du ColombierCode Coverage
1130219b2ee8SDavid du Colombier.PP
1131219b2ee8SDavid du ColombierAnother common component of software test uses
1132219b2ee8SDavid du Colombier.I coverage
1133219b2ee8SDavid du Colombieranalysis.
1134219b2ee8SDavid du ColombierThe purpose of the test is to determine which paths through the code have
1135219b2ee8SDavid du Colombiernot been executed while running the test suite.
1136219b2ee8SDavid du ColombierThis is usually
1137219b2ee8SDavid du Colombierperformed by a combination of compiler support and a reporting tool run
1138219b2ee8SDavid du Colombieron the output generated by statements compiled into the program.
1139219b2ee8SDavid du ColombierThe compiler emits code that
1140219b2ee8SDavid du Colombierlogs the progress of the program as it executes basic blocks and writes the
1141219b2ee8SDavid du Colombierresults to a file. The file is then processed by the reporting tool
1142219b2ee8SDavid du Colombierto determine which basic blocks have not been executed.
1143219b2ee8SDavid du Colombier.PP
1144219b2ee8SDavid du ColombierAcid can perform the same function in a language independent manner without
1145219b2ee8SDavid du Colombiermodifying the source, object or binary of the program. The following example
1146219b2ee8SDavid du Colombiershows
1147219b2ee8SDavid du Colombier.CW ls
1148219b2ee8SDavid du Colombierbeing run under the control of the Acid coverage library.
1149219b2ee8SDavid du Colombier.P1
1150219b2ee8SDavid du Colombierphilw-helix% acid -l coverage /bin/ls
1151219b2ee8SDavid du Colombier/bin/ls: mips plan 9 executable
1152219b2ee8SDavid du Colombier/lib/acid/port
1153219b2ee8SDavid du Colombier/lib/acid/mips
1154219b2ee8SDavid du Colombier/lib/acid/coverage
1155219b2ee8SDavid du Colombieracid: coverage()
1156219b2ee8SDavid du Colombieracid
1157219b2ee8SDavid du Colombiernewstime
1158219b2ee8SDavid du Colombierprofile
1159219b2ee8SDavid du Colombiertel
1160219b2ee8SDavid du Colombierwintool
1161219b2ee8SDavid du Colombier2: (error) msg: pid=11419 startstop: process exited
1162219b2ee8SDavid du Colombieracid: analyse(ls)
1163219b2ee8SDavid du Colombierls.c:102,105
1164219b2ee8SDavid du Colombier	102:     return 1;
1165219b2ee8SDavid du Colombier	103: }
1166219b2ee8SDavid du Colombier	104: if(db[0].qid.path&CHDIR && dflag==0){
1167219b2ee8SDavid du Colombier	105:     output();
1168219b2ee8SDavid du Colombierls.c:122,126
1169219b2ee8SDavid du Colombier	122:     memmove(dirbuf+ndir, db, sizeof(Dir));
1170219b2ee8SDavid du Colombier	123:     dirbuf[ndir].prefix = 0;
1171219b2ee8SDavid du Colombier	124:     p = utfrrune(s, '/');
1172219b2ee8SDavid du Colombier	125:     if(p){
1173219b2ee8SDavid du Colombier	126:         dirbuf[ndir].prefix = s;
1174219b2ee8SDavid du Colombier.P2
1175219b2ee8SDavid du ColombierThe
1176219b2ee8SDavid du Colombier.CW coverage
1177219b2ee8SDavid du Colombierfunction begins by looping through the text segment placing
1178219b2ee8SDavid du Colombierbreakpoints at the entry to each basic block. The start of each basic
1179219b2ee8SDavid du Colombierblock is found using the Acid builtin function
1180219b2ee8SDavid du Colombier.CW follow .
1181219b2ee8SDavid du ColombierIf the list generated by
1182219b2ee8SDavid du Colombier.CW follow
1183219b2ee8SDavid du Colombiercontains more than one
1184219b2ee8SDavid du Colombierelement, then the addresses mark the start of basic blocks. A breakpoint
1185219b2ee8SDavid du Colombieris placed at each address to detect entry into the block. If the result
1186219b2ee8SDavid du Colombierof
1187219b2ee8SDavid du Colombier.CW follow
1188219b2ee8SDavid du Colombieris a single address then no action is taken, and the next address is
1189219b2ee8SDavid du Colombierconsidered. Acid maintains a list of
1190219b2ee8SDavid du Colombierbreakpoints already in place and avoids placing duplicates (an address may be
1191219b2ee8SDavid du Colombierthe destination of several branches).
1192219b2ee8SDavid du Colombier.PP
1193219b2ee8SDavid du ColombierAfter placing the breakpoints the program is set running.
1194219b2ee8SDavid du ColombierEach time a breakpoint is encountered
1195219b2ee8SDavid du ColombierAcid deletes the address from the breakpoint list, removes the breakpoint
1196219b2ee8SDavid du Colombierfrom memory and then restarts the program.
1197219b2ee8SDavid du ColombierAt any instant the breakpoint list contains the addresses of basic blocks
1198219b2ee8SDavid du Colombierwhich have not been executed.
1199219b2ee8SDavid du ColombierThe
1200219b2ee8SDavid du Colombier.CW analyse
1201219b2ee8SDavid du Colombierfunction reports the lines of source code bounded by basic blocks
1202219b2ee8SDavid du Colombierwhose addresses are have not been deleted from the breakpoint list.
1203219b2ee8SDavid du ColombierThese are the basic blocks which have not been executed.
1204219b2ee8SDavid du ColombierProgram performance is almost unaffected since each breakpoint is executed
1205219b2ee8SDavid du Colombieronly once and then removed.
1206219b2ee8SDavid du Colombier.PP
1207219b2ee8SDavid du ColombierThe library contains a total of 128 lines of Acid code.
1208219b2ee8SDavid du ColombierAn obvious extension of this algorithm could be used to provide basic block
1209219b2ee8SDavid du Colombierprofiling.
1210219b2ee8SDavid du Colombier.NH
1211219b2ee8SDavid du ColombierConclusion
1212219b2ee8SDavid du Colombier.PP
1213219b2ee8SDavid du ColombierAcid has two areas of weakness. As with
1214219b2ee8SDavid du Colombierother language-based tools like
1215219b2ee8SDavid du Colombier.I awk ,
1216219b2ee8SDavid du Colombiera programmer must learn yet another language to step beyond the normal
1217219b2ee8SDavid du Colombierdebugging functions and use the full power of the debugger.
1218219b2ee8SDavid du ColombierSecond, the command line interface supplied by the
1219219b2ee8SDavid du Colombier.I yacc
1220219b2ee8SDavid du Colombierparser is inordinately clumsy.
1221219b2ee8SDavid du ColombierPart of the problem relates directly to the use of
1222219b2ee8SDavid du Colombier.I yacc
1223219b2ee8SDavid du Colombierand could be circumvented with a custom parser.
1224219b2ee8SDavid du ColombierHowever, structural problems would remain: Acid often requires
1225219b2ee8SDavid du Colombiertoo much typing to execute a simple
1226219b2ee8SDavid du Colombiercommand.
1227219b2ee8SDavid du ColombierA debugger should prostitute itself to its users, doing whatever
1228219b2ee8SDavid du Colombieris wanted with a minimum of encouragement; commands should be
1229219b2ee8SDavid du Colombierconcise and obvious. The language interface is more consistent than
1230219b2ee8SDavid du Colombieran ad hoc command interface but is clumsy to use.
1231219b2ee8SDavid du ColombierMost of these problems are addressed by an Acme interface
1232219b2ee8SDavid du Colombierwhich is under construction. This should provide the best of
1233219b2ee8SDavid du Colombierboth worlds: graphical debugging and access to the underlying acid
1234219b2ee8SDavid du Colombierlanguage when required.
1235219b2ee8SDavid du Colombier.PP
1236219b2ee8SDavid du ColombierThe name space clash between Acid variables, keywords, program variables,
1237219b2ee8SDavid du Colombierand functions is unavoidable.
1238219b2ee8SDavid du ColombierAlthough it rarely affects a debugging session, it is annoying
1239219b2ee8SDavid du Colombierwhen it happens and is sometimes difficult to circumvent.
1240219b2ee8SDavid du ColombierThe current renaming scheme
1241219b2ee8SDavid du Colombieris too crude; the new names are too hard to remember.
1242219b2ee8SDavid du Colombier.PP
1243219b2ee8SDavid du ColombierAcid has proved to be a powerful tool whose applications
1244219b2ee8SDavid du Colombierhave exceeded expectations.
1245219b2ee8SDavid du ColombierOf its strengths, portability, extensibility and parallel debugging support
1246219b2ee8SDavid du Colombierwere by design and provide the expected utility.
1247219b2ee8SDavid du ColombierIn retrospect,
1248219b2ee8SDavid du Colombierits use as a tool for code test and verification and as
1249219b2ee8SDavid du Colombiera medium for communicating type information and encapsulating
1250219b2ee8SDavid du Colombierinterfaces has provided unanticipated benefits and altered our
1251219b2ee8SDavid du Colombierview of the debugging process.
1252219b2ee8SDavid du Colombier.NH
1253219b2ee8SDavid du ColombierAcknowledgments
1254219b2ee8SDavid du Colombier.PP
1255219b2ee8SDavid du ColombierBob Flandrena was the first user and helped prepare the paper.
1256219b2ee8SDavid du ColombierRob Pike endured three buggy Alef compilers and a new debugger
1257219b2ee8SDavid du Colombierin a single sitting.
1258219b2ee8SDavid du Colombier.NH
1259219b2ee8SDavid du ColombierReferences
1260219b2ee8SDavid du Colombier.LP
1261219b2ee8SDavid du Colombier[Pike90] R. Pike, D. Presotto, K. Thompson, H. Trickey,
1262219b2ee8SDavid du Colombier``Plan 9 from Bell Labs'',
1263219b2ee8SDavid du Colombier.I
1264219b2ee8SDavid du ColombierUKUUG Proc. of the Summer 1990 Conf.,
1265219b2ee8SDavid du Colombier.R
1266219b2ee8SDavid du ColombierLondon, England,
1267219b2ee8SDavid du Colombier1990,
1268219b2ee8SDavid du Colombierreprinted, in a different form, in this volume.
1269219b2ee8SDavid du Colombier.LP
1270219b2ee8SDavid du Colombier[Gol93] M. Golan, D. Hanson,
1271219b2ee8SDavid du Colombier``DUEL -- A Very High-Level Debugging Language'',
1272219b2ee8SDavid du Colombier.I
1273219b2ee8SDavid du ColombierUSENIX Proc. of the Winter 1993 Conf.,
1274219b2ee8SDavid du Colombier.R
1275219b2ee8SDavid du ColombierSan Diego, CA,
1276219b2ee8SDavid du Colombier1993.
1277219b2ee8SDavid du Colombier.LP
1278219b2ee8SDavid du Colombier[Lin90] M. A. Linton,
1279219b2ee8SDavid du Colombier``The Evolution of DBX'',
1280219b2ee8SDavid du Colombier.I
1281219b2ee8SDavid du ColombierUSENIX Proc. of the Summer 1990 Conf.,
1282219b2ee8SDavid du Colombier.R
1283219b2ee8SDavid du ColombierAnaheim, CA,
1284219b2ee8SDavid du Colombier1990.
1285219b2ee8SDavid du Colombier.LP
1286219b2ee8SDavid du Colombier[Stal91] R. M. Stallman, R. H. Pesch,
1287219b2ee8SDavid du Colombier``Using GDB: A guide to the GNU source level debugger'',
1288219b2ee8SDavid du ColombierTechnical Report, Free Software Foundation,
1289219b2ee8SDavid du ColombierCambridge, MA,
1290219b2ee8SDavid du Colombier1991.
1291219b2ee8SDavid du Colombier.LP
1292219b2ee8SDavid du Colombier[Win93] P. Winterbottom,
1293219b2ee8SDavid du Colombier``Alef reference Manual'',
1294219b2ee8SDavid du Colombierthis volume.
1295219b2ee8SDavid du Colombier.LP
1296219b2ee8SDavid du Colombier[Pike93] Rob Pike,
1297219b2ee8SDavid du Colombier``Acme: A User Interface for Programmers'',
1298219b2ee8SDavid du Colombier.I
1299219b2ee8SDavid du ColombierUSENIX Proc. of the Winter 1994 Conf.,
1300219b2ee8SDavid du Colombier.R
1301219b2ee8SDavid du ColombierSan Francisco, CA,
1302219b2ee8SDavid du Colombierreprinted in this volume.
1303219b2ee8SDavid du Colombier.LP
1304219b2ee8SDavid du Colombier[Ols90] Ronald A. Olsson, Richard H. Crawford, and W. Wilson Ho,
1305219b2ee8SDavid du Colombier``Dalek: A GNU, improved programmable debugger'',
1306219b2ee8SDavid du Colombier.I
1307219b2ee8SDavid du ColombierUSENIX Proc. of the Summer 1990 Conf.,
1308219b2ee8SDavid du Colombier.R
1309219b2ee8SDavid du ColombierAnaheim, CA.
1310219b2ee8SDavid du Colombier.LP
1311219b2ee8SDavid du Colombier[May92] Paul Maybee,
1312219b2ee8SDavid du Colombier``NeD: The Network Extensible Debugger''
1313219b2ee8SDavid du Colombier.I
1314219b2ee8SDavid du ColombierUSENIX Proc. of the Summer 1992 Conf.,
1315219b2ee8SDavid du Colombier.R
1316219b2ee8SDavid du ColombierSan Antonio, TX.
1317219b2ee8SDavid du Colombier.LP
1318219b2ee8SDavid du Colombier[Aral] Ziya Aral, Ilya Gertner, and Greg Schaffer,
1319219b2ee8SDavid du Colombier``Efficient debugging primitives for multiprocessors'',
1320219b2ee8SDavid du Colombier.I
1321219b2ee8SDavid du ColombierProceedings of the Third International Conference on Architectural
1322219b2ee8SDavid du ColombierSupport for Programming Languages and Operating Systems,
1323219b2ee8SDavid du Colombier.R
1324219b2ee8SDavid du ColombierSIGPLAN notices Nr. 22, May 1989.
1325