| .TH ACID 1 | 
 | .SH NAME | 
 | acid, acidtypes \- debugger | 
 | .SH SYNOPSIS | 
 | .B acid | 
 | [ | 
 | .BI -l " library | 
 | ] | 
 | [ | 
 | .B -wq | 
 | ] [ | 
 | .B -m | 
 | .I machine | 
 | ] [ | 
 | .I pid | 
 | | | 
 | .I core | 
 | ] | 
 | [ | 
 | .I textfile | 
 | ] | 
 | .PP | 
 | .B acidtypes | 
 | [ | 
 | .B -p | 
 | .I prefix | 
 | ] | 
 | .I file | 
 | \&... | 
 | .\" .PP | 
 | .\" .B acid | 
 | .\" .B -l | 
 | .\" .B truss | 
 | .\" .I textfile | 
 | .\" .PP | 
 | .\" .B acid | 
 | .\" .B -l | 
 | .\" .B trump | 
 | .\" [ | 
 | .\" .I pid | 
 | .\" ] | 
 | .\" [ | 
 | .\" .I textfile | 
 | .\" ] | 
 | .SH DESCRIPTION | 
 | .I Acid | 
 | is a programmable symbolic debugger. | 
 | It can inspect one or more processes that share an address space. | 
 | A program to be debugged may be specified by the process id of | 
 | a running or defunct process, | 
 | or by the name of the program's text file  | 
 | .RB ( a.out | 
 | by default). | 
 | At the prompt, | 
 | .I acid | 
 | will store function definitions or print the value of expressions. | 
 | Options are | 
 | .TP .9i | 
 | .B -w | 
 | Allow the textfile to be modified. | 
 | .TP | 
 | .B -q | 
 | Print variable renamings at startup. | 
 | .TP | 
 | .BI -l " library | 
 | Load from  | 
 | .I library | 
 | at startup; see below. | 
 | .TP | 
 | .BI -m " machine | 
 | Assume instructions are for the given CPU type | 
 | (see | 
 | .IR mach (3)) | 
 | instead of using the executable header to select | 
 | the CPU type. | 
 | .TP | 
 | .BI -k | 
 | Debug the kernel state for the process, rather than the user state. | 
 | .PP | 
 | At startup, | 
 | .I acid | 
 | obtains standard function definitions from the library file | 
 | .BR \*9/acid/port , | 
 | architecture-dependent functions from | 
 | .BR \*9/acid/$objtype , | 
 | user-specified functions from | 
 | .BR $home/lib/acid , | 
 | and further functions from  | 
 | .B -l | 
 | files. | 
 | Definitions in any file may override previously defined functions. | 
 | If the function | 
 | .IR acidinit () | 
 | is defined, it will be invoked after all modules have been loaded. | 
 | Then the function | 
 | .IR acidmap () | 
 | will be invoked if defined. | 
 | .B \*9/acid/port | 
 | provides a definition of | 
 | .I acidmap | 
 | that attaches all the shared libraries being used by the target process | 
 | and then runs | 
 | .I acidtypes | 
 | .RI ( q.v. ) | 
 | to create | 
 | .I acid | 
 | functions for examining data structures. | 
 | .SS Language | 
 | Symbols of the program being debugged become integer  | 
 | variables whose values are addresses. | 
 | Contents of addresses are obtained by indirection. | 
 | Local variables are qualified by | 
 | function name, for example | 
 | .BR main:argv . | 
 | When program symbols conflict with | 
 | .I acid | 
 | words, distinguishing  | 
 | .B $ | 
 | signs are prefixed. | 
 | Such renamings are reported at startup; option | 
 | .B -q | 
 | suppresses them. | 
 | .PP | 
 | Variable types | 
 | .RI ( "integer, float, list, string" ) | 
 | and formats are inferred from assignments. | 
 | Truth values false/true are attributed to zero/nonzero | 
 | integers or floats and to empty/nonempty lists or strings. | 
 | Lists are sequences of expressions surrounded by | 
 | .BR {\^}  | 
 | and separated by commas. | 
 | .PP | 
 | Expressions are much as in C, | 
 | but yield both a value and a format. | 
 | Casts to complex types are allowed. | 
 | Lists admit the following operators, with | 
 | subscripts counted from 0. | 
 | .IP | 
 | .BI head " list | 
 | .br | 
 | .BI tail " list | 
 | .br | 
 | .BI append " list", " element | 
 | .br | 
 | .BI delete " list", " subscript | 
 | .PP | 
 | Format codes are the same as in | 
 | .IR db (1). | 
 | Formats may be attached to (unary) expressions with | 
 | .BR \e , | 
 | e.g. | 
 | .BR (32*7)\eD . | 
 | There are two indirection operators, | 
 | .B * | 
 | to address a core image, | 
 | .B @ | 
 | to address a text file. | 
 | The type and format of the result are determined by the format of the operand, | 
 | whose type must be integer. | 
 | .PP | 
 | Statements are | 
 | .IP | 
 | .BI if " expr " then " statement " "\fR[ \fPelse\fI statement \fR] | 
 | .br | 
 | .BI while " expr " do " statement | 
 | .br | 
 | .BI loop " expr" , " expr " do " statement | 
 | .br | 
 | .BI defn " name" ( args ") {" " statement \fP} | 
 | .br | 
 | .BI defn " name" | 
 | .br | 
 | .IB name ( args ) | 
 | .br | 
 | .BI builtin " name" ( args ) | 
 | .br | 
 | .BI local " name | 
 | .br | 
 | .BI return " expr | 
 | .br | 
 | .BR whatis " [ \fI name \fP] | 
 | .PP | 
 | The statement | 
 | .B defn | 
 | .I name | 
 | clears the definition for | 
 | .IR name . | 
 | A | 
 | .B defn | 
 | may override a built-in function; | 
 | prefixing a function call with | 
 | .B builtin | 
 | ignores any overriding | 
 | .BR defn , | 
 | forcing the use of the built-in function. | 
 | .PP | 
 | Here is a partial list of functions; see the manual for a complete list. | 
 | .TF asm(address) | 
 | .TP | 
 | .B stk() | 
 | Print a stack trace for current process. | 
 | .TP | 
 | .B lstk() | 
 | Print a stack trace with values of local variables. | 
 | .TP | 
 | .B gpr() | 
 | Print general registers. | 
 | Registers can also be accessed by name, for example | 
 | .BR *R0 . | 
 | .TP | 
 | .B spr() | 
 | Print special registers such as program counter and stack pointer. | 
 | .TP | 
 | .B fpr() | 
 | Print floating-point registers. | 
 | .TP | 
 | .B regs() | 
 | Same as | 
 | .BR spr();gpr() . | 
 | .TP | 
 | .BI fmt( expr , format ) | 
 | Expression  | 
 | .I expr | 
 | with format given by the character value of expression | 
 | .IR format . | 
 | .TP | 
 | .BI src( address ) | 
 | Print 10 lines of source around the program address. | 
 | .TP | 
 | .BI Bsrc( address ) | 
 | Get the source line for the program address | 
 | into a window of a running | 
 | .IR sam (1) | 
 | and select it. | 
 | .TP | 
 | .BI line( address ) | 
 | Print source line nearest to the program address. | 
 | .TP | 
 | .B source() | 
 | List current source directories. | 
 | .TP | 
 | .BI addsrcdir( string ) | 
 | Add a source directory to the list. | 
 | .TP | 
 | .BI filepc( where ) | 
 | Convert a string of the form  | 
 | .IB sourcefile : linenumber | 
 | to a machine address. | 
 | .TP | 
 | .BI pcfile( address ) | 
 | Convert a machine address to a source file name. | 
 | .TP | 
 | .BI pcline( address ) | 
 | Convert a machine address to a source line number. | 
 | .TP | 
 | .BI bptab() | 
 | List breakpoints set in the current process. | 
 | .TP | 
 | .BI bpset( address ) | 
 | Set a breakpoint in the current process at the given address. | 
 | (Doesn't work on Unix yet.) | 
 | .TP | 
 | .BI bpdel( address ) | 
 | Delete a breakpoint from the current process. | 
 | .TP | 
 | .B cont() | 
 | Continue execution of current process and wait for it to stop. | 
 | .TP | 
 | .B step() | 
 | Execute a single machine instruction in the current process. | 
 | (Doesn't work on Unix yet.) | 
 | .TP | 
 | .B func() | 
 | Step repeatedly until after a function return. | 
 | .TP | 
 | .BI stopped( pid ) | 
 | This replaceable function is called automatically when the given process | 
 | stops. | 
 | It normally prints the program counter and returns to the prompt. | 
 | .TP | 
 | .BI asm( address ) | 
 | Disassemble 30 machine instructions beginning at the given address. | 
 | .TP | 
 | .BI mem( address , string ) | 
 | Print a block of memory | 
 | interpreted according to a string of format codes. | 
 | .TP | 
 | .BI dump( address , n , string\fP) | 
 | Like | 
 | .BR mem (), | 
 | repeated for  | 
 | .I n | 
 | consecutive blocks. | 
 | .TP | 
 | .BI print( expr , ... ) | 
 | Print the values of the expressions. | 
 | .TP | 
 | .BI newproc( arguments ) | 
 | Start a new process with arguments given as a string | 
 | and halt at the first instruction. | 
 | .TP | 
 | .B new() | 
 | Like  | 
 | .IR newproc (), | 
 | but take arguments (except | 
 | .BR argv[0] ) | 
 | from string variable | 
 | .BR progargs . | 
 | .TP | 
 | .B win() | 
 | Like  | 
 | .IR new (), | 
 | but run the process in a separate window. | 
 | .TP | 
 | .BI start( pid ) | 
 | Start a stopped process. | 
 | .TP | 
 | .BI kill( pid ) | 
 | Kill the given process. | 
 | .TP | 
 | .BI setproc( pid ) | 
 | Make the given process current. | 
 | .TP | 
 | .BI rc( string ) | 
 | Escape to the shell, | 
 | .IR rc (1), | 
 | to execute the command string. | 
 | .TP | 
 | .BI include( string ) | 
 | Read acid commands from the named file. | 
 | .TP | 
 | .BI includepipe( string ) | 
 | Run the command string, reading its standard output as acid commands. | 
 | .PD 0 | 
 | .SS "Shared library segments | 
 | When a pid or core file is specified on the command line, | 
 | .I acid | 
 | will, as part of its startup, determine the set of shared libraries | 
 | in use by the process image and map those at appropriate locations. | 
 | If  | 
 | .I acid | 
 | is started without a pid or core file | 
 | and is subsequently attached to a process via | 
 | .BR setproc , | 
 | the shared library maps can be initialized by calling | 
 | .BR dynamicmap() . | 
 | .SS "Type information | 
 | Unix compilers conventionally include detailed type information | 
 | in the debugging symbol section of binaries. | 
 | The external program | 
 | .B acidtypes | 
 | extracts this information and formats it as | 
 | .I acid | 
 | program text. | 
 | Once the shared libraries have been mapped, the default | 
 | .I acid | 
 | startup invokes | 
 | .B acidtypes | 
 | (via | 
 | .BR includepipe ) | 
 | on the set of currently mapped text files. | 
 | The function | 
 | .B acidtypes() | 
 | can be called to rerun the command after changing | 
 | the set of mapped text files. | 
 | .SS "Acid Libraries | 
 | There are a number of | 
 | .I acid | 
 | `libraries' that provide higher-level debugging facilities.  One notable | 
 | example is | 
 | .IR trump , | 
 | which uses | 
 | .I acid | 
 | to trace memory allocation. | 
 | .I Trump | 
 | requires starting | 
 | .I acid | 
 | on the program, either by attaching to a running process or by | 
 | executing | 
 | .B new() | 
 | on a binary (perhaps after setting | 
 | .BR progargs ), | 
 | stopping the process, and then running | 
 | .B trump() | 
 | to execute the program under the scaffolding. | 
 | The output will be a trace of the memory allocation and free calls | 
 | executed by the program. | 
 | When finished tracing, stop the process and execute | 
 | .B untrump() | 
 | followed by | 
 | .B cont() | 
 | to resume execution. | 
 | .SH EXAMPLES | 
 | Start to debug | 
 | .BR /bin/ls ; | 
 | set some breakpoints; run up to the first one | 
 | (this example doesn't work on Unix yet): | 
 | .IP | 
 | .EX | 
 | % acid /bin/ls | 
 | /bin/ls: mips plan 9 executable | 
 | /sys/lib/acid/port | 
 | /sys/lib/acid/mips | 
 | acid: new() | 
 | 70094: system call	_main	ADD	$-0x14,R29 | 
 | 70094: breakpoint	main+0x4	MOVW	R31,0x0(R29) | 
 | acid: pid | 
 | 70094 | 
 | acid: argv0 = **main:argv\es | 
 | acid: whatis argv0 | 
 | integer variable format s | 
 | acid: *argv0 | 
 | /bin/ls | 
 | acid: bpset(ls) | 
 | acid: cont() | 
 | 70094: breakpoint  ls	ADD	$-0x16c8,R29 | 
 | acid:  | 
 | .EE | 
 | .PP | 
 | Display elements of a linked list of structures: | 
 | .IP | 
 | .EX | 
 | complex Str { 'D' 0 val; 'X' 4 next; }; | 
 | s = *headstr; | 
 | while s != 0 do{ | 
 | 	complex Str s; | 
 | 	print(s.val, "\en"); | 
 | 	s = s.next; | 
 | } | 
 | .EE | 
 | .PP | 
 | Note the use of the | 
 | .B . | 
 | operator instead of | 
 | .BR -> . | 
 | .PP | 
 | Display an array of bytes declared in C as | 
 | .BR "char array[]" . | 
 | .IP | 
 | .EX | 
 | *(array\es) | 
 | .EE | 
 | .PP | 
 | This example gives | 
 | .B array | 
 | string format, then prints the string beginning at the address (in | 
 | .I acid | 
 | notation) | 
 | .BR *array . | 
 | .PP | 
 | Trace the system calls executed by | 
 | .IR ls (1) | 
 | (neither does this one): | 
 | .IP | 
 | .EX | 
 | % acid -l truss /bin/ls | 
 | /bin/ls:386 plan 9 executable | 
 |  | 
 | /sys/lib/acid/port | 
 | /sys/lib/acid/kernel | 
 | /sys/lib/acid/truss | 
 | /sys/lib/acid/386 | 
 | acid: progargs = "-l lib/profile" | 
 | acid: new() | 
 | acid: truss() | 
 | open("#c/pid", 0) | 
 | 	return value: 3 | 
 | pread(3, 0x7fffeeac, 20, -1) | 
 | 	return value: 12 | 
 | 	data: "        166 " | 
 | \&... | 
 | stat("lib/profile", 0x0000f8cc, 113) | 
 | 	return value: 65 | 
 | open("/env/timezone", 0) | 
 | 	return value: 3 | 
 | pread(3, 0x7fffd7c4, 1680, -1) | 
 | 	return value: 1518 | 
 | 	data: "EST -18000 EDT -14400 | 
 |    9943200   25664400   41392800   57718800   73447200   89168400 | 
 |  104896800  ..." | 
 | close(3) | 
 | 	return value: 0 | 
 | pwrite(1, "--rw-rw-r-- M 9 rob rob 2519 Mar 22 10:29 lib/profile | 
 | ", 54, -1) | 
 | --rw-rw-r-- M 9 rob rob 2519 Mar 22 10:29 lib/profile | 
 | 	return value: 54 | 
 | \&... | 
 | 166: breakpoint	_exits+0x5	INTB	$0x40 | 
 | acid: cont() | 
 | .EE | 
 | .SH FILES | 
 | .B \*9/acid/$objtype | 
 | .br | 
 | .B \*9/acid/port | 
 | .br | 
 | .B \*9/acid/kernel | 
 | .br | 
 | .B \*9/acid/trump | 
 | .br | 
 | .B \*9/acid/truss | 
 | .br | 
 | .B $home/lib/acid | 
 | .SH SOURCE | 
 | .B \*9/src/cmd/acid | 
 | .SH "SEE ALSO" | 
 | .IR mk (1), | 
 | .IR db (1) | 
 | .br | 
 | Phil Winterbottom, | 
 | ``Acid Manual''. | 
 | .SH DIAGNOSTICS | 
 | At termination, kill commands are proposed | 
 | for processes that are still active. | 
 | .SH BUGS | 
 | There is no way to redirect the standard input and standard output | 
 | of a new process. | 
 | .PP | 
 | Source line selection near the beginning of a file may pick | 
 | an adjacent file. | 
 | .PP | 
 | With the extant stepping commands, one cannot step through instructions | 
 | outside the text segment and it is hard to debug across process forks. | 
 | .PP | 
 | Breakpoints do not work yet. | 
 | Therefore, commands such as | 
 | .BR step , | 
 | .BR new , | 
 | and | 
 | .B truss | 
 | do not work either. | 
 | .B New | 
 | in particular will need some help to cope with dynamic libraries. |