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