2551 lines
64 KiB
Plaintext
2551 lines
64 KiB
Plaintext
|
.HTML "Acid Manual
|
||
|
.am DS
|
||
|
.ft I
|
||
|
..
|
||
|
.ta 1i 2.3i 4.5i (optional to set tabs)
|
||
|
.TL
|
||
|
Acid Manual
|
||
|
.AU
|
||
|
Phil Winterbottom
|
||
|
philw@plan9.bell-labs.com
|
||
|
.SH
|
||
|
Introduction
|
||
|
.PP
|
||
|
Acid is a general purpose, source level symbolic debugger.
|
||
|
The debugger is built around a simple command language.
|
||
|
The command language, distinct from the language of the program being debugged,
|
||
|
provides a flexible user interface that allows the debugger
|
||
|
interface to be customized for a specific application or architecture.
|
||
|
Moreover, it provides an opportunity to write test and
|
||
|
verification code independently of a program's source code.
|
||
|
Acid is able to debug multiple
|
||
|
processes provided they share a common set of symbols, such as the processes in
|
||
|
a threaded program.
|
||
|
.PP
|
||
|
Like other language-based solutions, Acid presents a poor user interface but
|
||
|
provides a powerful debugging tool.
|
||
|
Application of Acid to hard problems is best approached by writing functions off-line
|
||
|
(perhaps loading them with the
|
||
|
.CW include
|
||
|
function or using the support provided by
|
||
|
.I acme (1)),
|
||
|
rather than by trying to type intricate Acid operations
|
||
|
at the interactive prompt.
|
||
|
.PP
|
||
|
Acid allows the execution of a program to be controlled by operating on its
|
||
|
state while it is stopped and by monitoring and controlling its execution
|
||
|
when it is running. Each program action that causes a change
|
||
|
of execution state is reflected by the execution
|
||
|
of an Acid function, which may be user defined.
|
||
|
A library of default functions provides the functionality of a normal debugger.
|
||
|
.PP
|
||
|
A Plan 9 process is controlled by writing messages to a control file in the
|
||
|
.I proc (3)
|
||
|
file system. Each control message has a corresponding Acid function, which
|
||
|
sends the message to the process. These functions take a process id
|
||
|
.I pid ) (
|
||
|
as an
|
||
|
argument. The memory and text file of the program may be manipulated using
|
||
|
the indirection operators. The symbol table, including source cross reference,
|
||
|
is available to an Acid program. The combination allows complex operations
|
||
|
to be performed both in terms of control flow and data manipulation.
|
||
|
.SH
|
||
|
Input format and \f(CWwhatis\fP
|
||
|
.PP
|
||
|
Comments start with
|
||
|
.CW //
|
||
|
and continue to the end of the line.
|
||
|
Input is a series of statements and expressions separated by semicolons.
|
||
|
At the top level of the interpreter, the builtin function
|
||
|
.CW print
|
||
|
is called automatically to display the result of all expressions except function calls.
|
||
|
A unary
|
||
|
.CW +
|
||
|
may be used as a shorthand to force the result of a function call to be printed.
|
||
|
.PP
|
||
|
Also at the top level, newlines are treated as semicolons
|
||
|
by the parser, so semicolons are unnecessary when evaluating expressions.
|
||
|
.PP
|
||
|
When Acid starts, it loads the default program modules,
|
||
|
enters interactive mode, and prints a prompt. In this state Acid accepts
|
||
|
either function definitions or statements to be evaluated.
|
||
|
In this interactive mode
|
||
|
statements are evaluated immediately, while function definitions are
|
||
|
stored for later invocation.
|
||
|
.PP
|
||
|
The
|
||
|
.CW whatis
|
||
|
operator can be used to report the state of identifiers known to the interpreter.
|
||
|
With no argument,
|
||
|
.CW whatis
|
||
|
reports the name of all defined Acid functions; when supplied with an identifier
|
||
|
as an argument it reports any variable, function, or type definition
|
||
|
associated with the identifier.
|
||
|
Because of the way the interpreter handles semicolons,
|
||
|
the result of a
|
||
|
.CW whatis
|
||
|
statement can be returned directly to Acid without adding semicolons.
|
||
|
A syntax error or interrupt returns Acid to the normal evaluation
|
||
|
mode; any partially evaluated definitions are lost.
|
||
|
.SH
|
||
|
Using the Library Functions
|
||
|
.PP
|
||
|
After loading the program binary, Acid loads the portable and architecture-specific
|
||
|
library functions that form the standard debugging environment.
|
||
|
These files are Acid source code and are human-readable.
|
||
|
The following example uses the standard debugging library to show how
|
||
|
language and program interact:
|
||
|
.P1
|
||
|
% acid /bin/ls
|
||
|
/bin/ls:mips plan 9 executable
|
||
|
|
||
|
/sys/lib/acid/port
|
||
|
/sys/lib/acid/mips
|
||
|
acid: new()
|
||
|
75721: system call _main ADD $-0x14,R29
|
||
|
75721: breakpoint main+0x4 MOVW R31,0x0(R29)
|
||
|
acid: bpset(ls)
|
||
|
acid: cont()
|
||
|
75721: breakpoint ls ADD $-0x16c8,R29
|
||
|
acid: stk()
|
||
|
At pc:0x0000141c:ls /sys/src/cmd/ls.c:87
|
||
|
ls(s=0x0000004d,multi=0x00000000) /sys/src/cmd/ls.c:87
|
||
|
called from main+0xf4 /sys/src/cmd/ls.c:79
|
||
|
main(argc=0x00000000,argv=0x7ffffff0) /sys/src/cmd/ls.c:48
|
||
|
called from _main+0x20 /sys/src/libc/mips/main9.s:10
|
||
|
acid: PC
|
||
|
0xc0000f60
|
||
|
acid: *PC
|
||
|
0x0000141c
|
||
|
acid: ls
|
||
|
0x0000141c
|
||
|
.P2
|
||
|
The function
|
||
|
.CW new()
|
||
|
creates a new process and stops it at the first instruction.
|
||
|
This change in state is reported by a call to the
|
||
|
Acid function
|
||
|
.CW stopped ,
|
||
|
which is called by the interpreter whenever the debugged program stops.
|
||
|
.CW Stopped
|
||
|
prints the status line giving the pid, the reason the program stopped
|
||
|
and the address and instruction at the current PC.
|
||
|
The function
|
||
|
.CW bpset
|
||
|
makes an entry in the breakpoint table and plants a breakpoint in memory.
|
||
|
The
|
||
|
.CW cont
|
||
|
function continues the process, allowing it to run until some condition
|
||
|
causes it to stop. In this case the program hits the breakpoint placed on
|
||
|
the function
|
||
|
.CW ls
|
||
|
in the C program. Once again the
|
||
|
.CW stopped
|
||
|
routine is called to print the status of the program. The function
|
||
|
.CW stk
|
||
|
prints a C stack trace of the current process. It is implemented using
|
||
|
a builtin Acid function that returns the stack trace as a list; the code
|
||
|
that formats the information is all written in Acid.
|
||
|
The Acid variable
|
||
|
.CW PC
|
||
|
holds the address of the
|
||
|
cell where the current value of the processor register
|
||
|
.CW PC
|
||
|
is stored. By indirecting through
|
||
|
the value of
|
||
|
.CW PC
|
||
|
the address where the program is stopped can be found.
|
||
|
All of the processor registers are available by the same mechanism.
|
||
|
.SH
|
||
|
Types
|
||
|
.PP
|
||
|
An Acid variable has one of four types:
|
||
|
.I integer ,
|
||
|
.I float ,
|
||
|
.I list ,
|
||
|
or
|
||
|
.I string .
|
||
|
The type of a variable is inferred from the type of the right-hand
|
||
|
side of the assignment expression which last set its value.
|
||
|
Referencing a variable that has not yet
|
||
|
been assigned draws a "used but not set" error. Many of the operators may
|
||
|
be applied to more than
|
||
|
one type; for these operators the action of the operator is determined by
|
||
|
the types of its operands. The action of each operator is defined in the
|
||
|
.I Expressions
|
||
|
section of this manual.
|
||
|
.SH
|
||
|
Variables
|
||
|
.PP
|
||
|
Acid has three kinds of variables: variables defined by the symbol table
|
||
|
of the debugged program, variables that are defined and maintained
|
||
|
by the interpreter as the debugged program changes state, and variables
|
||
|
defined and used by Acid programs.
|
||
|
.PP
|
||
|
Some examples of variables maintained by the interpreter are the register
|
||
|
pointers listed by name in the Acid list variable
|
||
|
.CW registers ,
|
||
|
and the symbol table listed by name and contents in the Acid variable
|
||
|
.CW symbols .
|
||
|
.PP
|
||
|
The variable
|
||
|
.CW pid
|
||
|
is updated by the interpreter to select the most recently created process
|
||
|
or the process selected by the
|
||
|
.CW setproc
|
||
|
builtin function.
|
||
|
.SH 1
|
||
|
Formats
|
||
|
.PP
|
||
|
In addition to a type, variables have formats. The format is a code
|
||
|
letter that determines the printing style and the effect of some of the
|
||
|
operators on that variable. The format codes are derived from the format
|
||
|
letters used by
|
||
|
.I db (1).
|
||
|
By default, symbol table variables and numeric constants
|
||
|
are assigned the format code
|
||
|
.CW X ,
|
||
|
which specifies 32-bit hexadecimal.
|
||
|
Printing a variable with this code yields the output
|
||
|
.CW 0x00123456 .
|
||
|
The format code of a variable may be changed from the default by using the
|
||
|
builtin function
|
||
|
.CW fmt .
|
||
|
This function takes two arguments, an expression and a format code. After
|
||
|
the expression is evaluated the new format code is attached to the result
|
||
|
and forms the return value from
|
||
|
.CW fmt .
|
||
|
The backslash operator is a short form of
|
||
|
.CW fmt .
|
||
|
The format supplied by the backslash operator must be the format character
|
||
|
rather than an expression.
|
||
|
If the result is assigned to a variable the new format code is maintained
|
||
|
in the variable. For example:
|
||
|
.P1
|
||
|
acid: x=10
|
||
|
acid: print(x)
|
||
|
0x0000000a
|
||
|
acid: x = fmt(x, 'D')
|
||
|
acid: print(x, fmt(x, 'X'))
|
||
|
10 0x0000000a
|
||
|
acid: x
|
||
|
10
|
||
|
acid: x\eo
|
||
|
12
|
||
|
.P2
|
||
|
The supported format characters are:
|
||
|
.RS
|
||
|
.IP \f(CWo\fP
|
||
|
Print two-byte integer in octal.
|
||
|
.IP \f(CWO\fP
|
||
|
Print four-byte integer in octal.
|
||
|
.IP \f(CWq\fP
|
||
|
Print two-byte integer in signed octal.
|
||
|
.IP \f(CWQ\fP
|
||
|
Print four-byte integer in signed octal.
|
||
|
.IP \f(CWB\fP
|
||
|
Print four-byte integer in binary.
|
||
|
.IP \f(CWd\fP
|
||
|
Print two-byte integer in signed decimal.
|
||
|
.IP \f(CWD\fP
|
||
|
Print four-byte integer in signed decimal.
|
||
|
.IP \f(CWV\fP
|
||
|
Print eight-byte integer in signed decimal.
|
||
|
.IP \f(CWZ\fP
|
||
|
Print eight-byte integer in unsigned decimal.
|
||
|
.IP \f(CWx\fP
|
||
|
Print two-byte integer in hexadecimal.
|
||
|
.IP \f(CWX\fP
|
||
|
Print four-byte integer in hexadecimal.
|
||
|
.IP \f(CWY\fP
|
||
|
Print eight-byte integer in hexadecimal.
|
||
|
.IP \f(CWu\fP
|
||
|
Print two-byte integer in unsigned decimal.
|
||
|
.IP \f(CWU\fP
|
||
|
Print four-byte integer in unsigned decimal.
|
||
|
.IP \f(CWf\fP
|
||
|
Print single-precision floating point number.
|
||
|
.IP \f(CWF\fP
|
||
|
Print double-precision floating point number.
|
||
|
.IP \f(CWg\fP
|
||
|
Print a single precision floating point number in string format.
|
||
|
.IP \f(CWG\fP
|
||
|
Print a double precision floating point number in string format.
|
||
|
.IP \f(CWb\fP
|
||
|
Print byte in hexadecimal.
|
||
|
.IP \f(CWc\fP
|
||
|
Print byte as an ASCII character.
|
||
|
.IP \f(CWC\fP
|
||
|
Like
|
||
|
.CW c ,
|
||
|
with
|
||
|
printable ASCII characters represented normally and
|
||
|
others printed in the form \f(CW\ex\fInn\fR.
|
||
|
.IP \f(CWs\fP
|
||
|
Interpret the addressed bytes as UTF characters
|
||
|
and print successive characters until a zero byte is reached.
|
||
|
.IP \f(CWr\fP
|
||
|
Print a two-byte integer as a rune.
|
||
|
.IP \f(CWR\fP
|
||
|
Print successive two-byte integers as runes
|
||
|
until a zero rune is reached.
|
||
|
.IP \f(CWi\fP
|
||
|
Print as machine instructions.
|
||
|
.IP \f(CWI\fP
|
||
|
As
|
||
|
.CW i
|
||
|
above, but print the machine instructions in
|
||
|
an alternate form if possible:
|
||
|
.CW sunsparc
|
||
|
and
|
||
|
.CW mipsco
|
||
|
reproduce the manufacturers' syntax.
|
||
|
.IP \f(CWa\fP
|
||
|
Print the value in symbolic form.
|
||
|
.RE
|
||
|
.SH
|
||
|
Complex types
|
||
|
.PP
|
||
|
Acid permits the definition of the layout of memory.
|
||
|
The usual method is to use the
|
||
|
.CW -a
|
||
|
flag of the compilers to produce Acid-language descriptions of data structures (see
|
||
|
.I 2c (1))
|
||
|
although such definitions can be typed interactively.
|
||
|
The keywords
|
||
|
.CW complex ,
|
||
|
.CW adt ,
|
||
|
.CW aggr ,
|
||
|
and
|
||
|
.CW union
|
||
|
are all equivalent; the compiler uses the synonyms to document the declarations.
|
||
|
A complex type is described as a set of members, each containing a format letter,
|
||
|
an offset in the structure, and a name. For example, the C structure
|
||
|
.P1
|
||
|
struct List {
|
||
|
int type;
|
||
|
struct List *next;
|
||
|
};
|
||
|
.P2
|
||
|
is described by the Acid statement
|
||
|
.P1
|
||
|
complex List {
|
||
|
'D' 0 type;
|
||
|
'X' 4 next;
|
||
|
};
|
||
|
.P2
|
||
|
.SH
|
||
|
Scope
|
||
|
.PP
|
||
|
Variables are global unless they are either parameters to functions
|
||
|
or are declared as
|
||
|
.CW local
|
||
|
in a function body. Parameters and local variables are available only in
|
||
|
the body of the function in which they are instantiated.
|
||
|
Variables are dynamically bound: if a function declares a local variable
|
||
|
with the same name as a global variable, the global variable will be hidden
|
||
|
whenever the function is executing.
|
||
|
For example, if a function
|
||
|
.CW f
|
||
|
has a local called
|
||
|
.CW main ,
|
||
|
any function called below
|
||
|
.CW f
|
||
|
will see the local version of
|
||
|
.CW main ,
|
||
|
not the external symbol.
|
||
|
.SH 1
|
||
|
Addressing
|
||
|
.PP
|
||
|
Since the symbol table specifies addresses,
|
||
|
to access the value of program variables
|
||
|
an extra level of indirection
|
||
|
is required relative to the source code.
|
||
|
For consistency, the registers are maintained as pointers as well; Acid variables with the names
|
||
|
of processor registers point to cells holding the saved registers.
|
||
|
.PP
|
||
|
The location in a file or memory image associated with
|
||
|
an address is calculated from a map
|
||
|
associated with the file.
|
||
|
Each map contains one or more quadruples (\c
|
||
|
.I t ,
|
||
|
.I b ,
|
||
|
.I e ,
|
||
|
.I f \|),
|
||
|
defining a segment named
|
||
|
.I t
|
||
|
(usually
|
||
|
.CW text ,
|
||
|
.CW data ,
|
||
|
.CW regs ,
|
||
|
or
|
||
|
.CW fpregs )
|
||
|
mapping addresses in the range
|
||
|
.I b
|
||
|
through
|
||
|
.I e
|
||
|
to the part of the file
|
||
|
beginning at
|
||
|
offset
|
||
|
.I f .
|
||
|
The memory model of a Plan 9 process assumes
|
||
|
that segments are disjoint. There
|
||
|
can be more than one segment of a given type (e.g., a process
|
||
|
may have more than one text segment) but segments
|
||
|
may not overlap.
|
||
|
An address
|
||
|
.I a
|
||
|
is translated
|
||
|
to a file address
|
||
|
by finding a segment
|
||
|
for which
|
||
|
.I b
|
||
|
+
|
||
|
.I a
|
||
|
<
|
||
|
.I e ;
|
||
|
the location in the file
|
||
|
is then
|
||
|
.I address
|
||
|
+
|
||
|
.I f
|
||
|
\-
|
||
|
.I b .
|
||
|
.PP
|
||
|
Usually,
|
||
|
the text and initialized data of a program
|
||
|
are mapped by segments called
|
||
|
.CW text
|
||
|
and
|
||
|
.CW data .
|
||
|
Since a program file does not contain bss, stack, or register data,
|
||
|
these data are
|
||
|
not mapped by the data segment.
|
||
|
The text segment is mapped similarly in the memory image of
|
||
|
a normal (i.e., non-kernel) process.
|
||
|
However, the segment called
|
||
|
.CW *data
|
||
|
maps memory from the beginning to the end of the program's data space.
|
||
|
This region contains the program's static data, the bss, the
|
||
|
heap and the stack. A segment
|
||
|
called
|
||
|
.CW *regs
|
||
|
maps the registers;
|
||
|
.CW *fpregs
|
||
|
maps the floating point registers.
|
||
|
.PP
|
||
|
Sometimes it is useful to define a map with a single segment
|
||
|
mapping the region from 0 to 0xFFFFFFFF; such a map
|
||
|
allows the entire file to be examined
|
||
|
without address translation. The builtin function
|
||
|
.CW map
|
||
|
examines and modifies Acid's map for a process.
|
||
|
.SH 1
|
||
|
Name Conflicts
|
||
|
.PP
|
||
|
Name conflicts between keywords in the Acid language, symbols in the program,
|
||
|
and previously defined functions are resolved when the interpreter starts up.
|
||
|
Each name is made unique by prefixing enough
|
||
|
.CW $
|
||
|
characters to the front of the name to make it unique. Acid reports
|
||
|
a list of each name change at startup. The report looks like this:
|
||
|
.P1
|
||
|
/bin/sam: mips plan 9 executable
|
||
|
/lib/acid/port
|
||
|
/lib/acid/mips
|
||
|
Symbol renames:
|
||
|
append=$append T/0xa4e40
|
||
|
acid:
|
||
|
.P2
|
||
|
The symbol
|
||
|
.CW append
|
||
|
is both a keyword and a text symbol in the program. The message reports
|
||
|
that the text symbol is now named
|
||
|
.CW $append .
|
||
|
.SH
|
||
|
Expressions
|
||
|
.PP
|
||
|
Operators have the same
|
||
|
binding and precedence as in C.
|
||
|
For operators of equal precedence, expressions are evaluated from left to right.
|
||
|
.SH 1
|
||
|
Boolean expressions
|
||
|
.PP
|
||
|
If an expression is evaluated for a boolean condition the test
|
||
|
performed depends on the type of the result. If the result is of
|
||
|
.I integer
|
||
|
or
|
||
|
.I floating
|
||
|
type the result is true if the value is non-zero. If the expression is a
|
||
|
.I list
|
||
|
the result is true if there are any members in the list.
|
||
|
If the expression is a
|
||
|
.I string
|
||
|
the result is true if there are any characters in the string.
|
||
|
.DS
|
||
|
primary-expression:
|
||
|
identifier
|
||
|
identifier \f(CW:\fP identifier
|
||
|
constant
|
||
|
\f(CW(\fP expression \f(CW)\fP
|
||
|
\f(CW{\fP elist \f(CW}\fP
|
||
|
|
||
|
elist:
|
||
|
expression
|
||
|
elist , expression
|
||
|
.DE
|
||
|
An identifier may be any legal Acid variable. The colon operator returns the
|
||
|
address of parameters or local variables in the current stack of a program.
|
||
|
For example:
|
||
|
.P1
|
||
|
*main:argc
|
||
|
.P2
|
||
|
prints the number of arguments passed into main. Local variables and parameters
|
||
|
can only be referenced after the frame has been established. It may be necessary to
|
||
|
step a program over the first few instructions of a breakpointed function to properly set
|
||
|
the frame.
|
||
|
.PP
|
||
|
Constants follow the same lexical rules as C.
|
||
|
A list of expressions delimited by braces forms a list constructor.
|
||
|
A new list is produced by evaluating each expression when the constructor is executed.
|
||
|
The empty list is formed from
|
||
|
.CW {} .
|
||
|
.P1
|
||
|
acid: x = 10
|
||
|
acid: l = { 1, x, 2\eD }
|
||
|
acid: x = 20
|
||
|
acid: l
|
||
|
{0x00000001 , 0x0000000a , 2 }
|
||
|
.P2
|
||
|
.SH 1
|
||
|
Lists
|
||
|
.PP
|
||
|
Several operators manipulate lists.
|
||
|
.DS
|
||
|
list-expression:
|
||
|
primary-expression
|
||
|
\f(CWhead\fP primary-expression
|
||
|
\f(CWtail\fP primary-expression
|
||
|
\f(CWappend\fP expression \f(CW,\fP primary-expression
|
||
|
\f(CWdelete\fP expression \f(CW,\fP primary-expression
|
||
|
.DE
|
||
|
The
|
||
|
.I primary-expression
|
||
|
for
|
||
|
.CW head
|
||
|
and
|
||
|
.CW tail
|
||
|
must yield a value of type
|
||
|
.I list .
|
||
|
If there are no elements in the list the value of
|
||
|
.CW head
|
||
|
or
|
||
|
.CW tail
|
||
|
will be the empty list. Otherwise
|
||
|
.CW head
|
||
|
evaluates to the first element of the list and
|
||
|
.CW tail
|
||
|
evaluates to the rest.
|
||
|
.P1
|
||
|
acid: head {}
|
||
|
{}
|
||
|
acid: head {1, 2, 3, 4}
|
||
|
0x00000001
|
||
|
acid: tail {1, 2, 3, 4}
|
||
|
{0x00000002 , 0x00000003 , 0x00000004 }
|
||
|
.P2
|
||
|
The first operand of
|
||
|
.CW append
|
||
|
and
|
||
|
.CW delete
|
||
|
must be an expression that yields a
|
||
|
.I list .
|
||
|
.CW Append
|
||
|
places the result of evaluating
|
||
|
.I primary-expression
|
||
|
at the end of the list.
|
||
|
The
|
||
|
.I primary-expression
|
||
|
supplied to
|
||
|
.CW delete
|
||
|
must evaluate to an integer;
|
||
|
.CW delete
|
||
|
removes the
|
||
|
.I n 'th
|
||
|
item from the list, where
|
||
|
.I n
|
||
|
is integral value of
|
||
|
.I primary-expression.
|
||
|
List indices are zero-based.
|
||
|
.P1
|
||
|
acid: append {1, 2}, 3
|
||
|
{0x00000001 , 0x00000002 , 0x00000003 }
|
||
|
acid: delete {1, 2, 3}, 1
|
||
|
{0x00000001 , 0x00000003 }
|
||
|
.P2
|
||
|
.PP
|
||
|
Assigning a list to a variable copies a reference to the list; if a list variable
|
||
|
is copied it still points at the same list. To copy a list, the elements must
|
||
|
be copied piecewise using
|
||
|
.CW head
|
||
|
and
|
||
|
.CW append .
|
||
|
.SH 1
|
||
|
Operators
|
||
|
.PP
|
||
|
.DS
|
||
|
postfix-expression:
|
||
|
list-expression
|
||
|
postfix-expression \f(CW[\fP expression \f(CW]\fP
|
||
|
postfix-expression \f(CW(\fP argument-list \f(CW)\fP
|
||
|
postfix-expression \f(CW.\fP tag
|
||
|
postfix-expression \f(CW->\fP tag
|
||
|
postfix-expression \f(CW++\fP
|
||
|
postfix-expression \f(CW--\fP
|
||
|
|
||
|
argument-list:
|
||
|
expression
|
||
|
argument-list , expression
|
||
|
.DE
|
||
|
The
|
||
|
.CW [
|
||
|
.I expression
|
||
|
.CW ]
|
||
|
operator performs indexing.
|
||
|
The indexing expression must result in an expression of
|
||
|
.I integer
|
||
|
type, say
|
||
|
.I n .
|
||
|
The operation depends on the type of
|
||
|
.I postfix-expression .
|
||
|
If the
|
||
|
.I postfix-expression
|
||
|
yields an
|
||
|
.I integer
|
||
|
it is assumed to be the base address of an array in the memory image.
|
||
|
The index offsets into this array; the size of the array members is
|
||
|
determined by the format associated with the
|
||
|
.I postfix-expression .
|
||
|
If the
|
||
|
.I postfix-expression
|
||
|
yields a
|
||
|
.I string
|
||
|
the index operator fetches the
|
||
|
.I n 'th
|
||
|
character
|
||
|
of the string. If the index points beyond the end
|
||
|
of the string, a zero is returned.
|
||
|
If the
|
||
|
.I postfix-expression
|
||
|
yields a
|
||
|
.I list
|
||
|
then the indexing operation returns the
|
||
|
.I n 'th
|
||
|
item of the list.
|
||
|
If the list contains less than
|
||
|
.I n
|
||
|
items the empty list
|
||
|
.CW {}
|
||
|
is returned.
|
||
|
.PP
|
||
|
The
|
||
|
.CW ++
|
||
|
and
|
||
|
.CW --
|
||
|
operators increment and decrement integer variables.
|
||
|
The amount of increment or decrement depends on the format code. These postfix
|
||
|
operators return the value of the variable before the increment or decrement
|
||
|
has taken place.
|
||
|
.DS
|
||
|
unary-expression:
|
||
|
postfix-expression
|
||
|
\f(CW++\fP unary-expression
|
||
|
\f(CW--\fP unary-expression
|
||
|
|
||
|
unary-operator: one of
|
||
|
\f(CW*\fP \f(CW@\fP \f(CW+\fP \f(CW-\fP ~ \f(CW!\fP
|
||
|
.DE
|
||
|
The operators
|
||
|
.CW *
|
||
|
and
|
||
|
.CW @
|
||
|
are the indirection operators.
|
||
|
.CW @
|
||
|
references a value from the text file of the program being debugged.
|
||
|
The size of the value depends on the format code. The
|
||
|
.CW *
|
||
|
operator fetches a value from the memory image of a process. If either
|
||
|
operator appears on the left-hand side of an assignment statement, either the file
|
||
|
or memory will be written. The file can only be modified when Acid is invoked
|
||
|
with the
|
||
|
.CW -w
|
||
|
option.
|
||
|
The prefix
|
||
|
.CW ++
|
||
|
and
|
||
|
.CW --
|
||
|
operators perform the same operation as their postfix counterparts but
|
||
|
return the value after the increment or decrement has been performed. Since the
|
||
|
.CW ++
|
||
|
and
|
||
|
.CW *
|
||
|
operators fetch and increment the correct amount for the specified format,
|
||
|
the following function prints correct machine instructions on a machine with
|
||
|
variable length instructions, such as the 68020 or 386:
|
||
|
.P1
|
||
|
defn asm(addr)
|
||
|
{
|
||
|
addr = fmt(addr, 'i');
|
||
|
loop 1, 10 do
|
||
|
print(*addr++, "\en");
|
||
|
}
|
||
|
.P2
|
||
|
The operators
|
||
|
.CW ~
|
||
|
and
|
||
|
.CW !
|
||
|
perform bitwise and logical negation respectively. Their operands must be of
|
||
|
.I integer
|
||
|
type.
|
||
|
.DS
|
||
|
cast-expression:
|
||
|
unary-expression
|
||
|
unary-expression \f(CW\e\fP format-char
|
||
|
\f(CW(\fP complex-name \f(CW)\fP unary-expression
|
||
|
.DE
|
||
|
A unary expression may be preceded by a cast. The cast has the effect of
|
||
|
associating the value of
|
||
|
.I unary-expression
|
||
|
with a complex type structure.
|
||
|
The result may then be dereferenced using the
|
||
|
.CW .
|
||
|
and
|
||
|
.CW ->
|
||
|
operators.
|
||
|
.PP
|
||
|
An Acid variable may be associated with a complex type
|
||
|
to enable accessing the type's members:
|
||
|
.P1
|
||
|
acid: complex List {
|
||
|
'D' 0 type;
|
||
|
'X' 4 next;
|
||
|
};
|
||
|
acid: complex List lhead
|
||
|
acid: lhead.type
|
||
|
10
|
||
|
acid: lhead = ((List)lhead).next
|
||
|
acid: lhead.type
|
||
|
-46
|
||
|
.P2
|
||
|
Note that the
|
||
|
.CW next
|
||
|
field cannot be given a complex type automatically.
|
||
|
.PP
|
||
|
When entered at the top level of the interpreter,
|
||
|
an expression of complex type
|
||
|
is treated specially.
|
||
|
If the type is called
|
||
|
.CW T
|
||
|
and an Acid function also called
|
||
|
.CW T
|
||
|
exists,
|
||
|
then that function will be called with the expression as its argument.
|
||
|
The compiler options
|
||
|
.CW -a
|
||
|
and
|
||
|
.CW -aa
|
||
|
will generate Acid source code defining such complex types and functions; see
|
||
|
.I 2c (1).
|
||
|
.PP
|
||
|
A
|
||
|
.I unary-expression
|
||
|
may be qualified with a format specifier using the
|
||
|
.CW \e
|
||
|
operator. This has the same effect as passing the expression to the
|
||
|
.CW fmt
|
||
|
builtin function.
|
||
|
.DS
|
||
|
multiplicative-expression:
|
||
|
cast-expression
|
||
|
multiplicative-expression \f(CW*\fP multiplicative-expression
|
||
|
multiplicative-expression \f(CW/\fP multiplicative-expression
|
||
|
multiplicative-expression \f(CW%\fP multiplicative-expression
|
||
|
.DE
|
||
|
These operate on
|
||
|
.I integer
|
||
|
and
|
||
|
.I float
|
||
|
types and perform the expected operations:
|
||
|
.CW *
|
||
|
multiplication,
|
||
|
.CW /
|
||
|
division,
|
||
|
.CW %
|
||
|
modulus.
|
||
|
.DS
|
||
|
additive-expression:
|
||
|
multiplicative-expression
|
||
|
additive-expression \f(CW+\fP multiplicative-expression
|
||
|
additive-expression \f(CW-\fP multiplicative-expression
|
||
|
.DE
|
||
|
These operators perform as expected for
|
||
|
.I integer
|
||
|
and
|
||
|
.I float
|
||
|
operands.
|
||
|
Unlike in C,
|
||
|
.CW +
|
||
|
and
|
||
|
.CW -
|
||
|
do not scale the addition based on the format of the expression.
|
||
|
This means that
|
||
|
.CW i=i+1
|
||
|
will always add 1 but
|
||
|
.CW i++
|
||
|
will add the size corresponding to the format stored with
|
||
|
.CW i .
|
||
|
If both operands are of either
|
||
|
.I string
|
||
|
or
|
||
|
.I list
|
||
|
type then addition is defined as concatenation.
|
||
|
Adding a string and an integer is treated as concatenation
|
||
|
with the Unicode character corresponding to the integer.
|
||
|
Subtraction is undefined for strings and lists.
|
||
|
.DS
|
||
|
shift-expression:
|
||
|
additive-expression
|
||
|
shift-expression \f(CW<<\fP additive-expression
|
||
|
shift-expression \f(CW>>\fP additive-expression
|
||
|
.DE
|
||
|
The
|
||
|
.CW >>
|
||
|
and
|
||
|
.CW <<
|
||
|
operators perform bitwise right and left shifts respectively. Both
|
||
|
require operands of
|
||
|
.I integer
|
||
|
type.
|
||
|
.DS
|
||
|
relational-expression:
|
||
|
relational-expression \f(CW<\fP shift-expression
|
||
|
relational-expression \f(CW>\fP shift-expression
|
||
|
relational-expression \f(CW<=\fP shift-expression
|
||
|
relational-expression \f(CW>=\fP shift-expression
|
||
|
|
||
|
equality-expression:
|
||
|
relational-expression
|
||
|
relational-expression \f(CW==\fP equality-expression
|
||
|
relational-expression \f(CW!=\fP equality-expression
|
||
|
.DE
|
||
|
The comparison operators are
|
||
|
.CW <
|
||
|
(less than),
|
||
|
.CW >
|
||
|
(greater than),
|
||
|
.CW <=
|
||
|
(less than or equal to),
|
||
|
.CW >=
|
||
|
(greater than or equal to),
|
||
|
.CW ==
|
||
|
(equal to) and
|
||
|
.CW !=
|
||
|
(not equal to). The result of a comparison is 0
|
||
|
if the condition is false, otherwise 1. The relational operators can only be
|
||
|
applied to operands of
|
||
|
.I integer
|
||
|
and
|
||
|
.I float
|
||
|
type. The equality operators apply to all types. Comparing mixed types is legal.
|
||
|
Mixed integer and float compare on the integral value. Other mixtures are always unequal.
|
||
|
Two lists are equal if they
|
||
|
have the same number of members and a pairwise comparison of the members results
|
||
|
in equality.
|
||
|
.DS
|
||
|
AND-expression:
|
||
|
equality-expression
|
||
|
AND-expression \f(CW&\fP equality-expression
|
||
|
|
||
|
XOR-expression:
|
||
|
AND-expression
|
||
|
XOR-expression \f(CW^\fP AND-expression
|
||
|
|
||
|
OR-expression:
|
||
|
XOR-expression
|
||
|
OR-expression \f(CW|\fP XOR-expression
|
||
|
.DE
|
||
|
These operators perform bitwise logical operations and apply only to the
|
||
|
.I integer
|
||
|
type.
|
||
|
The operators are
|
||
|
.CW &
|
||
|
(logical and),
|
||
|
.CW ^
|
||
|
(exclusive or) and
|
||
|
.CW |
|
||
|
(inclusive or).
|
||
|
.DS
|
||
|
logical-AND-expression:
|
||
|
OR-expression
|
||
|
logical-AND-expression \f(CW&&\fP OR-expression
|
||
|
|
||
|
logical-OR-expression:
|
||
|
logical-AND-expression
|
||
|
logical-OR-expression \f(CW||\fP logical-AND-expression
|
||
|
.DE
|
||
|
The
|
||
|
.CW &&
|
||
|
operator returns 1 if both of its operands evaluate to boolean true, otherwise 0.
|
||
|
The
|
||
|
.CW ||
|
||
|
operator returns 1 if either of its operands evaluates to boolean true,
|
||
|
otherwise 0.
|
||
|
.SH
|
||
|
Statements
|
||
|
.PP
|
||
|
.DS
|
||
|
\f(CWif\fP expression \f(CWthen\fP statement \f(CWelse\fP statement
|
||
|
\f(CWif\fP expression \f(CWthen\fP statement
|
||
|
.DE
|
||
|
The
|
||
|
.I expression
|
||
|
is evaluated as a boolean. If its value is true the statement after
|
||
|
the
|
||
|
.CW then
|
||
|
is executed, otherwise the statement after the
|
||
|
.CW else
|
||
|
is executed. The
|
||
|
.CW else
|
||
|
portion may be omitted.
|
||
|
.DS
|
||
|
\f(CWwhile\fP expression \f(CWdo\fP statement
|
||
|
.DE
|
||
|
In a while loop, the
|
||
|
.I statement
|
||
|
is executed while the boolean
|
||
|
.I expression
|
||
|
evaluates
|
||
|
true.
|
||
|
.DS
|
||
|
\f(CWloop\fP startexpr, endexpr \f(CWdo\fP statement
|
||
|
.DE
|
||
|
The two expressions
|
||
|
.I startexpr
|
||
|
and
|
||
|
.I endexpr
|
||
|
are evaluated prior to loop entry.
|
||
|
.I Statement
|
||
|
is evaluated while the value of
|
||
|
.I startexpr
|
||
|
is less than or equal to
|
||
|
.I endexpr .
|
||
|
Both expressions must yield
|
||
|
.I integer
|
||
|
values. The value of
|
||
|
.I startexpr
|
||
|
is
|
||
|
incremented by one for each loop iteration.
|
||
|
Note that there is no explicit loop variable; the
|
||
|
.I expressions
|
||
|
are just values.
|
||
|
.DS
|
||
|
\f(CWreturn\fP expression
|
||
|
.DE
|
||
|
.CW return
|
||
|
terminates execution of the current function and returns to its caller.
|
||
|
The value of the function is given by expression. Since
|
||
|
.CW return
|
||
|
requires an argument, nil-valued functions should return the empty list
|
||
|
.CW {} .
|
||
|
.DS
|
||
|
\f(CWlocal\fP variable
|
||
|
.DE
|
||
|
The
|
||
|
.CW local
|
||
|
statement creates a local instance of
|
||
|
.I variable ,
|
||
|
which exists for the duration
|
||
|
of the instance of the function in which it is declared. Binding is dynamic: the local variable,
|
||
|
rather than the previous value of
|
||
|
.I variable ,
|
||
|
is visible to called functions.
|
||
|
After a return from the current function the previous value of
|
||
|
.I variable
|
||
|
is
|
||
|
restored.
|
||
|
.PP
|
||
|
If Acid is interrupted, the values of all local variables are lost,
|
||
|
as if the function returned.
|
||
|
.DS
|
||
|
\f(CWdefn\fP function-name \f(CW(\fP parameter-list \f(CW)\fP body
|
||
|
|
||
|
parameter-list:
|
||
|
variable
|
||
|
parameter-list , variable
|
||
|
|
||
|
body:
|
||
|
\f(CW{\fP statement \f(CW}\fP
|
||
|
.DE
|
||
|
Functions are introduced by the
|
||
|
.CW defn
|
||
|
statement. The definition of parameter names suppresses any variables
|
||
|
of the same name until the function returns. The body of a function is a list
|
||
|
of statements enclosed by braces.
|
||
|
.SH
|
||
|
Code variables
|
||
|
.PP
|
||
|
Acid permits the delayed evaluation of a parameter to a function. The parameter
|
||
|
may then be evaluated at any time with the
|
||
|
.CW eval
|
||
|
operator. Such parameters are called
|
||
|
.I "code variables
|
||
|
and are defined by prefixing their name with an asterisk in their declaration.
|
||
|
.PP
|
||
|
For example, this function wraps up an expression for later evaluation:
|
||
|
.P1
|
||
|
acid: defn code(*e) { return e; }
|
||
|
acid: x = code(v+atoi("100")\eD)
|
||
|
acid: print(x)
|
||
|
(v+atoi("100"))\eD;
|
||
|
acid: eval x
|
||
|
<stdin>:5: (error) v used but not set
|
||
|
acid: v=5
|
||
|
acid: eval x
|
||
|
105
|
||
|
.P2
|
||
|
.SH
|
||
|
Source Code Management
|
||
|
.PP
|
||
|
Acid provides the means to examine source code. Source code is
|
||
|
represented by lists of strings. Builtin functions provide mapping
|
||
|
from address to lines and vice-versa. The default debugging environment
|
||
|
has the means to load and display source files.
|
||
|
.SH
|
||
|
Builtin Functions
|
||
|
.PP
|
||
|
The Acid interpreter has a number of builtin functions, which cannot be redefined.
|
||
|
These functions perform machine- or operating system-specific functions such as
|
||
|
symbol table and process management.
|
||
|
The following section presents a description of each builtin function.
|
||
|
The notation
|
||
|
.CW {}
|
||
|
is used to denote the empty list, which is the default value of a function that
|
||
|
does not execute a
|
||
|
.CW return
|
||
|
statement.
|
||
|
The type and number of parameters for each function are specified in the
|
||
|
description; where a parameter can be of any type it is specified as type
|
||
|
.I item .
|
||
|
.de Ip
|
||
|
.KS
|
||
|
.in 0
|
||
|
.LP
|
||
|
.ie h \&\f2\\$1\fP\ \ \f(CW\\$2(\f2\\$3\f(CW)\f1\ \ \ \ \ \ \ \ \\$4
|
||
|
.el .tl '\f2\\$1\fP\ \ \f(CW\\$2(\f2\\$3\f(CW)\f1''\\$4'
|
||
|
.IP
|
||
|
..
|
||
|
.de Ex
|
||
|
.KE
|
||
|
.KS
|
||
|
.IP
|
||
|
.ft CW
|
||
|
.ta 4n +4n +4n +4n +4n +4n +4n +4n +4n +4n +4n +4n +4n +4n +4n +4n
|
||
|
.nf
|
||
|
.in +4n
|
||
|
.br
|
||
|
..
|
||
|
.de Ee
|
||
|
.fi
|
||
|
.ft 1
|
||
|
.br
|
||
|
.KE
|
||
|
..
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip integer access string "Check if a file can be read
|
||
|
.CW Access
|
||
|
returns the integer 1 if the file name in
|
||
|
.I string
|
||
|
can be read by the builtin functions
|
||
|
.CW file ,
|
||
|
.CW readfile ,
|
||
|
or
|
||
|
.CW include ,
|
||
|
otherwise 0. A typical use of this function is to follow
|
||
|
a search path looking for a source file; it is used by
|
||
|
.CW findsrc .
|
||
|
.Ex
|
||
|
if access("main.c") then
|
||
|
return file("main.c");
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip float atof string "Convert a string to float
|
||
|
.CW atof
|
||
|
converts the string supplied as its argument into a floating point
|
||
|
number. The function accepts strings in the same format as the C
|
||
|
function of the same name. The value returned has the format code
|
||
|
.CW f .
|
||
|
.CW atof
|
||
|
returns the value 0.0 if it is unable to perform the conversion.
|
||
|
.Ex
|
||
|
acid: +atof("10.4e6")
|
||
|
1.04e+07
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip integer atoi string "Convert a string to an integer
|
||
|
.CW atoi
|
||
|
converts the argument
|
||
|
.i string
|
||
|
to an integer value.
|
||
|
The function accepts strings in the same format as the C function of the
|
||
|
same name. The value returned has the format code
|
||
|
.CW D .
|
||
|
.CW atoi
|
||
|
returns the integer 0 if it is unable to perform a conversion.
|
||
|
.Ex
|
||
|
acid: +atoi("-1255")
|
||
|
-1255
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP error string "Generate an interpreter error
|
||
|
.CW error
|
||
|
generates an error message and returns the interpreter to interactive
|
||
|
mode. If an Acid program is running, it is aborted.
|
||
|
Processes being debugged are not affected. The values of all local variables are lost.
|
||
|
.CW error
|
||
|
is commonly used to stop the debugger when some interesting condition arises
|
||
|
in the debugged program.
|
||
|
.Ex
|
||
|
while 1 do {
|
||
|
step();
|
||
|
if *main != @main then
|
||
|
error("memory corrupted");
|
||
|
}
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip list file string "Read the contents of a file into a list
|
||
|
.CW file
|
||
|
reads the contents of the file specified by
|
||
|
.I string
|
||
|
into a list.
|
||
|
Each element in the list is a string corresponding to a line in the file.
|
||
|
.CW file
|
||
|
breaks lines at the newline character, but the newline
|
||
|
characters are not returned as part each string.
|
||
|
.CW file
|
||
|
returns the empty list if it encounters an error opening or reading the data.
|
||
|
.Ex
|
||
|
acid: print(file("main.c")[0])
|
||
|
#include <u.h>
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip integer filepc string "Convert source address to text address
|
||
|
.CW filepc
|
||
|
interprets its
|
||
|
.I string
|
||
|
argument as a source file address in the form of a file name and line offset.
|
||
|
.CW filepc
|
||
|
uses the symbol table to map the source address into a text address
|
||
|
in the debugged program. The
|
||
|
.I integer
|
||
|
return value has the format
|
||
|
.CW X .
|
||
|
.CW filepc
|
||
|
returns an address of -1 if the source address is invalid.
|
||
|
The source file address uses the same format as
|
||
|
.I acme (1).
|
||
|
This function is commonly used to set breakpoints from the source text.
|
||
|
.Ex
|
||
|
acid: bpset(filepc("main:10"))
|
||
|
acid: bptab()
|
||
|
0x00001020 usage ADD $-0xc,R29
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip item fmt item,fmt "Set print, \f(CW@\fP and \f(CW*\fP formats
|
||
|
.CW fmt
|
||
|
evaluates the expression
|
||
|
.I item
|
||
|
and sets the format of the result to
|
||
|
.I fmt .
|
||
|
The format of a value determines how it will be printed and
|
||
|
what kind of object will be fetched by the
|
||
|
.CW *
|
||
|
and
|
||
|
.CW @
|
||
|
operators. The
|
||
|
.CW \e
|
||
|
operator is a short-hand form of the
|
||
|
.CW fmt
|
||
|
builtin function. The
|
||
|
.CW fmt
|
||
|
function leaves the format of the
|
||
|
.I item
|
||
|
unchanged.
|
||
|
.Ex
|
||
|
acid: main=fmt(main, 'i') // as instructions
|
||
|
acid: print(main\eX, "\et", *main)
|
||
|
0x00001020 ADD $-64,R29
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip fmt fmtof item "Get format
|
||
|
.CW fmtof
|
||
|
evaluates the expression
|
||
|
.I item
|
||
|
and returns the format of the result.
|
||
|
.Ex
|
||
|
acid: +fmtof(33)
|
||
|
W
|
||
|
acid: +fmtof("string")
|
||
|
s
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip integer fmtsize item "Get format size
|
||
|
.CW fmtsize
|
||
|
evaluates the expression
|
||
|
.I item
|
||
|
and returns the size in bytes of a single element of result's format.
|
||
|
.Ex
|
||
|
acid: +fmtsize('c')
|
||
|
8
|
||
|
acid: +fmtsize('c'\ec)
|
||
|
1
|
||
|
acid: +fmtsize(0\eX)
|
||
|
4
|
||
|
acid: +fmtsize('c'\e3)
|
||
|
10
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip list fnbound integer "Find start and end address of a function
|
||
|
.CW fnbound
|
||
|
interprets its
|
||
|
.I integer
|
||
|
argument as an address in the text of the debugged program.
|
||
|
.CW fnbound
|
||
|
returns a list containing two integers corresponding to
|
||
|
the start and end addresses of the function containing the supplied address.
|
||
|
If the
|
||
|
.I integer
|
||
|
address is not in the text segment of the program then the empty list is returned.
|
||
|
.CW fnbound
|
||
|
is used by
|
||
|
.CW next
|
||
|
to detect stepping into new functions.
|
||
|
.Ex
|
||
|
acid: print(fnbound(main))
|
||
|
{0x00001050, 0x000014b8}
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP follow integer "Compute follow set
|
||
|
The follow set is defined as the set of program counter values that could result
|
||
|
from executing an instruction.
|
||
|
.CW follow
|
||
|
interprets its
|
||
|
.I integer
|
||
|
argument as a text address, decodes the instruction at
|
||
|
that address and, with the current register set, builds a list of possible
|
||
|
next program counter values. If the instruction at the specified address
|
||
|
cannot be decoded
|
||
|
.CW follow
|
||
|
raises an error.
|
||
|
.CW follow
|
||
|
is used to plant breakpoints on
|
||
|
all potential paths of execution. The following code fragment
|
||
|
plants breakpoints on top of all potential following instructions.
|
||
|
.Ex
|
||
|
lst = follow(*PC);
|
||
|
while lst do
|
||
|
{
|
||
|
*head lst = bpinst;
|
||
|
lst = tail lst;
|
||
|
}
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP include string "Take input from a new file
|
||
|
.CW include
|
||
|
opens the file specified by
|
||
|
.I string
|
||
|
and uses its contents as command input to the interpreter.
|
||
|
The interpreter restores input to its previous source when it encounters
|
||
|
either an end of file or an error.
|
||
|
.CW include
|
||
|
can be used to incrementally load symbol table information without
|
||
|
leaving the interpreter.
|
||
|
.Ex
|
||
|
acid: include("/sys/src/cmd/acme/syms")
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP interpret string "Take input from a string
|
||
|
.CW interpret
|
||
|
evaluates the
|
||
|
.I string
|
||
|
expression and uses its result as command input for the interpreter.
|
||
|
The interpreter restores input to its previous source when it encounters
|
||
|
either the end of string or an error. The
|
||
|
.CW interpret
|
||
|
function allows Acid programs to write Acid code for later evaluation.
|
||
|
.Ex
|
||
|
acid: interpret("main+10;")
|
||
|
0x0000102a
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip string itoa integer[,string] "Convert integer to string
|
||
|
.CW itoa
|
||
|
takes an integer argument and converts it into an ASCII string
|
||
|
in the
|
||
|
.CW D
|
||
|
format.
|
||
|
an alternate format string
|
||
|
may be provided in the
|
||
|
.CW %
|
||
|
style of
|
||
|
.I print (2).
|
||
|
This function is commonly used to build
|
||
|
.CW rc
|
||
|
command lines.
|
||
|
.Ex
|
||
|
acid: rc("cat /proc/"+itoa(pid)+"/segment")
|
||
|
Stack 7fc00000 80000000 1
|
||
|
Data 00001000 00009000 1
|
||
|
Data 00009000 0000a000 1
|
||
|
Bss 0000a000 0000c000 1
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP kill integer "Kill a process
|
||
|
.CW kill
|
||
|
writes a kill control message into the control file of the process
|
||
|
specified by the
|
||
|
.I integer
|
||
|
pid.
|
||
|
If the process was previously installed by
|
||
|
.CW setproc
|
||
|
it will be removed from the list of active processes.
|
||
|
If the
|
||
|
.I integer
|
||
|
has the same value as
|
||
|
.CW pid ,
|
||
|
then
|
||
|
.CW pid
|
||
|
will be set to 0.
|
||
|
To continue debugging, a new process must be selected using
|
||
|
.CW setproc .
|
||
|
For example, to kill all the active processes:
|
||
|
.Ex
|
||
|
while proclist do {
|
||
|
kill(head proclist);
|
||
|
proclist = tail proclist;
|
||
|
}
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip list map list "Set or retrieve process memory map
|
||
|
.CW map
|
||
|
either retrieves all the mappings associated with a process or sets a single
|
||
|
map entry to a new value.
|
||
|
If the
|
||
|
.I list
|
||
|
argument is omitted then
|
||
|
.CW map
|
||
|
returns a list of lists. Each sublist has four values and describes a
|
||
|
single region of contiguous addresses in the
|
||
|
memory or file image of the debugged program. The first entry is the name of the
|
||
|
mapping. If the name begins with
|
||
|
.CW *
|
||
|
it denotes a map into the memory of an active process.
|
||
|
The second and third values specify the base and end
|
||
|
address of the region and the fourth number specifies the offset in the file
|
||
|
corresponding to the first location of the region.
|
||
|
A map entry may be set by supplying a list in the same format as the sublist
|
||
|
described above. The name of the mapping must match a region already defined
|
||
|
by the current map.
|
||
|
Maps are set automatically for Plan 9 processes and some kernels; they may
|
||
|
need to be set by hand for other kernels and programs that run on bare hardware.
|
||
|
.Ex
|
||
|
acid: map({"text", _start, end, 0x30})
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip integer match item,list "Search list for matching value
|
||
|
.CW match
|
||
|
compares each item in
|
||
|
.I list
|
||
|
using the equality operator
|
||
|
.CW ==
|
||
|
with
|
||
|
.I item .
|
||
|
The
|
||
|
.I item
|
||
|
can be of any type. If the match succeeds the result is the integer index
|
||
|
of the matching value, otherwise -1.
|
||
|
.Ex
|
||
|
acid: list={8,9,10,11}
|
||
|
acid: print(list[match(10, list)]\eD)
|
||
|
10
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP newproc string "Create a new process
|
||
|
.CW newproc
|
||
|
starts a new process with an argument vector constructed from
|
||
|
.I string .
|
||
|
The argument vector excludes the name of the program to execute and
|
||
|
each argument in
|
||
|
.I string
|
||
|
must be space separated. A new process can accept no more
|
||
|
than 512 arguments. The internal variable
|
||
|
.CW pid
|
||
|
is set to the pid of the newly created process. The new pid
|
||
|
is also appended to the list of active processes stored in the variable
|
||
|
.CW proclist .
|
||
|
The new process is created then halted at the first instruction, causing
|
||
|
the debugger to call
|
||
|
.CW stopped .
|
||
|
The library functions
|
||
|
.CW new
|
||
|
and
|
||
|
.CW win
|
||
|
should be used to start processes when using the standard debugging
|
||
|
environment.
|
||
|
.Ex
|
||
|
acid: newproc("-l .")
|
||
|
56720: system call _main ADD $-0x14,R29
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip string pcfile integer "Convert text address to source file name
|
||
|
.CW pcfile
|
||
|
interprets its
|
||
|
.I integer
|
||
|
argument as a text address in the debugged program. The address and symbol table
|
||
|
are used to generate a string containing the name of the source file
|
||
|
corresponding to the text address. If the address does not lie within the
|
||
|
program the string
|
||
|
.CW ?file?
|
||
|
is returned.
|
||
|
.Ex
|
||
|
acid: print("Now at ", pcfile(*PC), ":", pcline(*PC))
|
||
|
Now at ls.c:46
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip integer pcline integer "Convert text address to source line number
|
||
|
.CW pcline
|
||
|
interprets its
|
||
|
.I integer
|
||
|
argument as a text address in the debugged program. The address and symbol table
|
||
|
are used to generate an integer containing the line number in the source file
|
||
|
corresponding to the text address. If the address does not lie within the
|
||
|
program the integer 0 is returned.
|
||
|
.Ex
|
||
|
acid: +file("main.c")[pcline(main)]
|
||
|
main(int argc, char *argv[])
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP print item,item,... "Print expressions
|
||
|
.CW print
|
||
|
evaluates each
|
||
|
.I item
|
||
|
supplied in its argument list and prints it to standard output. Each
|
||
|
argument will be printed according to its associated format character.
|
||
|
When the interpreter is executing, output is buffered and flushed every
|
||
|
5000 statements or when the interpreter returns to interactive mode.
|
||
|
.CW print
|
||
|
accepts a maximum of 512 arguments.
|
||
|
.Ex
|
||
|
acid: print(10, "decimal ", 10\eD, "octal ", 10\eo)
|
||
|
0x0000000a decimal 10 octal 000000000012
|
||
|
acid: print({1, 2, 3})
|
||
|
{0x00000001 , 0x00000002 , 0x00000003 }
|
||
|
acid: print(main, main\ea, "\et", @main\ei)
|
||
|
0x00001020 main ADD $-64,R29
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP printto string,item,item,... "Print expressions to file
|
||
|
.CW printto
|
||
|
offers a limited form of output redirection. The first
|
||
|
.I string
|
||
|
argument is used as the path name of a new file to create.
|
||
|
Each
|
||
|
.I item
|
||
|
is then evaluated and printed to the newly created file. When all items
|
||
|
have been printed the file is closed.
|
||
|
.CW printto
|
||
|
accepts a maximum of 512 arguments.
|
||
|
.Ex
|
||
|
acid: printto("/env/foo", "hello")
|
||
|
acid: rc("echo -n $foo")
|
||
|
hello
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip string rc string "Execute a shell command
|
||
|
.CW rc
|
||
|
evaluates
|
||
|
.I string
|
||
|
to form a shell command. A new command interpreter is started
|
||
|
to execute the command. The Acid interpreter blocks until the command
|
||
|
completes. The return value is the empty string
|
||
|
if the command succeeds, otherwise the exit status of the failed command.
|
||
|
.Ex
|
||
|
acid: rc("B "+itoa(-pcline(addr))+" "+pcfile(addr));
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip string readfile string "Read file contents into a string
|
||
|
.CW readfile
|
||
|
takes the contents of the file specified by
|
||
|
.I string
|
||
|
and returns its contents as a new string.
|
||
|
If
|
||
|
.CW readfile
|
||
|
encounters a zero byte in the file, it terminates.
|
||
|
If
|
||
|
.CW readfile
|
||
|
encounters an error opening or reading the file then the empty list
|
||
|
is returned.
|
||
|
.CW readfile
|
||
|
can be used to read the contents of device files whose lines are not
|
||
|
terminated with newline characters.
|
||
|
.Ex
|
||
|
acid: ""+readfile("/dev/label")
|
||
|
helix
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip string reason integer "Print cause of program stoppage
|
||
|
.CW reason
|
||
|
uses machine-dependent information to generate a string explaining
|
||
|
why a process has stopped. The
|
||
|
.I integer
|
||
|
argument is the value of an architecture dependent status register,
|
||
|
for example
|
||
|
.CW CAUSE
|
||
|
on the MIPS.
|
||
|
.Ex
|
||
|
acid: print(reason(*CAUSE))
|
||
|
system call
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip integer regexp pattern,string "Regular expression match
|
||
|
.CW regexp
|
||
|
matches the
|
||
|
.I pattern
|
||
|
string supplied as its first argument with the
|
||
|
.I string
|
||
|
supplied as its second.
|
||
|
If the pattern matches the result is the value 1, otherwise 0.
|
||
|
.Ex
|
||
|
acid: print(regexp(".*bar", "foobar"))
|
||
|
1
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP setproc integer "Set debugger focus
|
||
|
.CW setproc
|
||
|
selects the default process used for memory and control operations. It effectively
|
||
|
shifts the focus of control between processes. The
|
||
|
.I integer
|
||
|
argument specifies the pid of the process to look at.
|
||
|
The variable
|
||
|
.CW pid
|
||
|
is set to the pid of the selected process. If the process is being
|
||
|
selected for the first time its pid is added to the list of active
|
||
|
processes
|
||
|
.CW proclist .
|
||
|
.Ex
|
||
|
acid: setproc(68382)
|
||
|
acid: procs()
|
||
|
>68382: Stopped at main+0x4 setproc(68382)
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP start integer "Restart execution
|
||
|
.CW start
|
||
|
writes a
|
||
|
.CW start
|
||
|
message to the control file of the process specified by the pid
|
||
|
supplied as its
|
||
|
.I integer
|
||
|
argument.
|
||
|
.CW start
|
||
|
draws an error if the process is not in the
|
||
|
.CW Stopped
|
||
|
state.
|
||
|
.Ex
|
||
|
acid: start(68382)
|
||
|
acid: procs()
|
||
|
>68382: Running at main+0x4 setproc(68382)
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP startstop integer "Restart execution, block until stopped
|
||
|
.CW startstop
|
||
|
performs the same actions as a call to
|
||
|
.CW start
|
||
|
followed by a call to
|
||
|
.CW stop .
|
||
|
The
|
||
|
.I integer
|
||
|
argument specifies the pid of the process to control. The process
|
||
|
must be in the
|
||
|
.CW Stopped
|
||
|
state.
|
||
|
Execution is restarted, the debugger then waits for the process to
|
||
|
return to the
|
||
|
.CW Stopped
|
||
|
state. A process will stop if a startstop message has been written to its control
|
||
|
file and any of the following conditions becomes true: the process executes or returns from
|
||
|
a system call, the process generates a trap or the process receives a note.
|
||
|
.CW startstop
|
||
|
is used to implement single stepping.
|
||
|
.Ex
|
||
|
acid: startstop(pid)
|
||
|
75374: breakpoint ls ADD $-0x16c8,R29
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip string status integer "Return process state
|
||
|
.CW status
|
||
|
uses the pid supplied by its
|
||
|
.I integer
|
||
|
argument to generate a string describing the state of the process.
|
||
|
The string corresponds to the state returned by the
|
||
|
sixth column of the
|
||
|
.I ps (1)
|
||
|
command.
|
||
|
A process must be in the
|
||
|
.CW Stopped
|
||
|
state to modify its memory or registers.
|
||
|
.Ex
|
||
|
acid: ""+status(pid)
|
||
|
Stopped
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP stop integer "Wait for a process to stop
|
||
|
.CW stop
|
||
|
writes a
|
||
|
.CW stop
|
||
|
message to the control file of the process specified by the
|
||
|
pid supplied as its
|
||
|
.I integer
|
||
|
argument.
|
||
|
The interpreter blocks until the debugged process enters the
|
||
|
.CW Stopped
|
||
|
state.
|
||
|
A process will stop if a stop message has been written to its control
|
||
|
file and any of the following conditions becomes true: the process executes or returns from
|
||
|
a system call, the process generates a trap, the process is scheduled or the
|
||
|
process receives a note.
|
||
|
.CW stop
|
||
|
is used to wait for a process to halt before planting a breakpoint since Plan 9
|
||
|
only allows a process's memory to be written while it is in the
|
||
|
.CW Stopped
|
||
|
state.
|
||
|
.Ex
|
||
|
defn bpset(addr) {
|
||
|
if (status(pid)!="Stopped") then {
|
||
|
print("Waiting...\en");
|
||
|
stop(pid);
|
||
|
}
|
||
|
...
|
||
|
}
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip list strace pc,sp,linkreg "Stack trace
|
||
|
.CW strace
|
||
|
generates a list of lists corresponding to procedures called by the debugged
|
||
|
program. Each sublist describes a single stack frame in the active process.
|
||
|
The first element is an
|
||
|
.I integer
|
||
|
of format
|
||
|
.CW X
|
||
|
specifying the address of the called function. The second element is the value
|
||
|
of the program counter when the function was called. The third and fourth elements
|
||
|
contain lists of parameter and automatic variables respectively.
|
||
|
Each element of these lists
|
||
|
contains a string with the name of the variable and an
|
||
|
.I integer
|
||
|
value of format
|
||
|
.CW X
|
||
|
containing the current value of the variable.
|
||
|
The arguments to
|
||
|
.CW strace
|
||
|
are the current value of the program counter, the current value of the
|
||
|
stack pointer, and the address of the link register. All three parameters
|
||
|
must be integers.
|
||
|
The setting of
|
||
|
.I linkreg
|
||
|
is architecture dependent. On the MIPS linkreg is set to the address of saved
|
||
|
.CW R31 ,
|
||
|
on the SPARC to the address of saved
|
||
|
.CW R15 .
|
||
|
For the other architectures
|
||
|
.I linkreg
|
||
|
is not used, but must point to valid memory.
|
||
|
.Ex
|
||
|
acid: print(strace(*PC, *SP, linkreg))
|
||
|
{{0x0000141c, 0xc0000f74,
|
||
|
{{"s", 0x0000004d}, {"multi", 0x00000000}},
|
||
|
{{"db", 0x00000000}, {"fd", 0x000010a4},
|
||
|
{"n", 0x00000001}, {"i", 0x00009824}}}}
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP waitstop integer "Wait for a process to stop
|
||
|
.CW waitstop
|
||
|
writes a waitstop message to the control file of the process specified by the
|
||
|
pid supplied as its
|
||
|
.I integer
|
||
|
argument.
|
||
|
The interpreter will remain blocked until the debugged process enters the
|
||
|
.CW Stopped
|
||
|
state.
|
||
|
A process will stop if a waitstop message has been written to its control
|
||
|
file and any of the following conditions becomes true: the process generates a trap
|
||
|
or receives a note. Unlike
|
||
|
.CW stop ,
|
||
|
the
|
||
|
.CW waitstop
|
||
|
function is passive; it does not itself cause the program to stop.
|
||
|
.Ex
|
||
|
acid: waitstop(pid)
|
||
|
75374: breakpoint ls ADD $-0x16c8,R29
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.SH
|
||
|
Library Functions
|
||
|
.PP
|
||
|
A standard debugging environment is provided by modules automatically
|
||
|
loaded when
|
||
|
Acid is started.
|
||
|
These modules are located in the directory
|
||
|
.CW /sys/lib/acid .
|
||
|
These functions may be overridden, personalized, or added to by code defined in
|
||
|
.CW $home/lib/acid .
|
||
|
The implementation of these functions can be examined using the
|
||
|
.CW whatis
|
||
|
operator and then modified during debugging sessions.
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP Bsrc integer "Load editor with source
|
||
|
.CW Bsrc
|
||
|
interprets the
|
||
|
.I integer
|
||
|
argument as a text address. The text address is used to produce a pathname
|
||
|
and line number suitable for the
|
||
|
.CW B
|
||
|
command
|
||
|
to send to the text editor
|
||
|
.I sam (1)
|
||
|
or
|
||
|
.I acme (1).
|
||
|
.CW Bsrc
|
||
|
builds an
|
||
|
.I rc (1)
|
||
|
command to invoke
|
||
|
.CW B ,
|
||
|
which either selects an existing source file or loads a new source file into the editor.
|
||
|
The line of source corresponding to the text address is then selected.
|
||
|
In the following example
|
||
|
.CW stopped
|
||
|
is redefined so that the editor
|
||
|
follows and displays the source line currently being executed.
|
||
|
.Ex
|
||
|
defn stopped(pid) {
|
||
|
pstop(pid);
|
||
|
Bsrc(*PC);
|
||
|
}
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP Fpr "" "Display double precision floating registers
|
||
|
For machines equipped with floating point,
|
||
|
.CW Fpr
|
||
|
displays the contents of the floating point registers as double precision
|
||
|
values.
|
||
|
.Ex
|
||
|
acid: Fpr()
|
||
|
F0 0. F2 0.
|
||
|
F4 0. F6 0.
|
||
|
F8 0. F10 0.
|
||
|
\&...
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP Ureg integer "Display contents of Ureg structure
|
||
|
.CW Ureg
|
||
|
interprets the integer passed as its first argument as the address of a
|
||
|
kernel
|
||
|
.CW Ureg
|
||
|
structure. Each element of the structure is retrieved and printed.
|
||
|
The size and contents of the
|
||
|
.CW Ureg
|
||
|
structure are architecture dependent.
|
||
|
This function can be used to decode the first argument passed to a
|
||
|
.I notify (2)
|
||
|
function after a process has received a note.
|
||
|
.Ex
|
||
|
acid: Ureg(*notehandler:ur)
|
||
|
status 0x3000f000
|
||
|
pc 0x1020
|
||
|
sp 0x7ffffe00
|
||
|
cause 0x00004002
|
||
|
\&...
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP acidinit "" "Interpreter startup
|
||
|
.CW acidinit
|
||
|
is called by the interpreter after all
|
||
|
modules have been loaded at initialization time.
|
||
|
It is used to set up machine specific variables and the default source path.
|
||
|
.CW acidinit
|
||
|
should not be called by user code.
|
||
|
.KE
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP addsrcdir string "Add element to source search path
|
||
|
.CW addsrcdir
|
||
|
interprets its string argument as a new directory
|
||
|
.CW findsrc
|
||
|
should search when looking for source code files.
|
||
|
.CW addsrcdir
|
||
|
draws an error if the directory is already in the source search path. The search
|
||
|
path may be examined by looking at the variable
|
||
|
.CW srcpath .
|
||
|
.Ex
|
||
|
acid: rc("9fs fornax")
|
||
|
acid: addsrcpath("/n/fornax/sys/src/cmd")
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP asm integer "Disassemble machine instructions
|
||
|
.CW asm
|
||
|
interprets its integer argument as a text address from which to disassemble
|
||
|
machine instructions.
|
||
|
.CW asm
|
||
|
prints the instruction address in symbolic and hexadecimal form, then prints
|
||
|
the instructions with addressing modes. Up to twenty instructions will
|
||
|
be disassembled.
|
||
|
.CW asm
|
||
|
stops disassembling when it reaches the end of the current function.
|
||
|
Instructions are read from the file image using the
|
||
|
.CW @
|
||
|
operator.
|
||
|
.Ex
|
||
|
acid: asm(main)
|
||
|
main 0x00001020 ADD $-0x64,R29
|
||
|
main+0x4 0x00001024 MOVW R31,0x0(R29)
|
||
|
main+0x8 0x00001028 MOVW R1,argc+4(FP)
|
||
|
main+0xc 0x0000102c MOVW $bin(SB),R1
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP bpdel integer "Delete breakpoint
|
||
|
.CW bpdel
|
||
|
removes a previously set breakpoint from memory.
|
||
|
The
|
||
|
.I integer
|
||
|
supplied as its argument must be the address of a previously set breakpoint.
|
||
|
The breakpoint address is deleted from the active breakpoint list
|
||
|
.CW bplist ,
|
||
|
then the original instruction is copied from the file image to the memory
|
||
|
image so that the breakpoint is removed.
|
||
|
.Ex
|
||
|
acid: bpdel(main+4)
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP bpset integer "Set a breakpoint
|
||
|
.CW bpset
|
||
|
places a breakpoint instruction at the address specified
|
||
|
by its
|
||
|
.I integer
|
||
|
argument, which must be in the text segment.
|
||
|
.CW bpset
|
||
|
draws an error if a breakpoint has already been set at the specified address.
|
||
|
A list of current breakpoints is maintained in the variable
|
||
|
.CW bplist .
|
||
|
Unlike in
|
||
|
.I db (1),
|
||
|
breakpoints are left in memory even when a process is stopped, and
|
||
|
the process must exist, perhaps by being
|
||
|
created by either
|
||
|
.CW new
|
||
|
or
|
||
|
.CW win ,
|
||
|
in order to place a breakpoint.
|
||
|
.CW Db "" (
|
||
|
accepts breakpoint commands before the process is started.)
|
||
|
On the
|
||
|
MIPS and SPARC architectures,
|
||
|
breakpoints at function entry points should be set 4 bytes into the function
|
||
|
because the
|
||
|
instruction scheduler may fill
|
||
|
.CW JAL
|
||
|
branch delay slots with the first instruction of the function.
|
||
|
.Ex
|
||
|
acid: bpset(main+4)
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP bptab "" "List active breakpoints
|
||
|
.CW bptab
|
||
|
prints a list of currently installed breakpoints. The list contains the
|
||
|
breakpoint address in symbolic and hexadecimal form as well as the instruction
|
||
|
the breakpoint replaced. Breakpoints are not maintained across process creation
|
||
|
using
|
||
|
.CW new
|
||
|
and
|
||
|
.CW win .
|
||
|
They are maintained across a fork, but care must be taken to keep control of
|
||
|
the child process.
|
||
|
.Ex
|
||
|
acid: bpset(ls+4)
|
||
|
acid: bptab()
|
||
|
0x00001420 ls+0x4 MOVW R31,0x0(R29)
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP casm "" "Continue disassembly
|
||
|
.CW casm
|
||
|
continues to disassemble instructions from where the last
|
||
|
.CW asm
|
||
|
or
|
||
|
.CW casm
|
||
|
command stopped. Like
|
||
|
.CW asm ,
|
||
|
this command stops disassembling at function boundaries.
|
||
|
.Ex
|
||
|
acid: casm()
|
||
|
main+0x10 0x00001030 MOVW $0x1,R3
|
||
|
main+0x14 0x00001034 MOVW R3,0x8(R29)
|
||
|
main+0x18 0x00001038 MOVW $0x1,R5
|
||
|
main+0x1c 0x0000103c JAL Binit(SB)
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP cont "" "Continue program execution
|
||
|
.CW cont
|
||
|
restarts execution of the currently active process.
|
||
|
If the process is stopped on a breakpoint, the breakpoint is first removed,
|
||
|
the program is single stepped, the breakpoint is replaced and the program
|
||
|
is then set executing. This may cause
|
||
|
.CW stopped()
|
||
|
to be called twice.
|
||
|
.CW cont
|
||
|
causes the interpreter to block until the process enters the
|
||
|
.CW Stopped
|
||
|
state.
|
||
|
.Ex
|
||
|
acid: cont()
|
||
|
95197: breakpoint ls+0x4 MOVW R31,0x0(R29)
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP dump integer,integer,string "Formatted memory dump
|
||
|
.CW dump
|
||
|
interprets its first argument as an address, its second argument as a
|
||
|
count and its third as a format string.
|
||
|
.CW dump
|
||
|
fetches an object from memory at the current address and prints it according
|
||
|
to the format. The address is incremented by the number of bytes specified by
|
||
|
the format and the process is repeated count times. The format string is any
|
||
|
combination of format characters, each preceded by an optional count.
|
||
|
For each object,
|
||
|
.CW dump
|
||
|
prints the address in hexadecimal, a colon, the object and then a newline.
|
||
|
.CW dump
|
||
|
uses
|
||
|
.CW mem
|
||
|
to fetch each object.
|
||
|
.Ex
|
||
|
acid: dump(main+35, 4, "X2bi")
|
||
|
0x00001043: 0x0c8fa700 108 143 lwc2 r0,0x528f(R4)
|
||
|
0x0000104d: 0xa9006811 0 0 swc3 r0,0x0(R24)
|
||
|
0x00001057: 0x2724e800 4 37 ADD $-0x51,R23,R31
|
||
|
0x00001061: 0xa200688d 6 0 NOOP
|
||
|
0x0000106b: 0x2710c000 7 0 BREAK
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP findsrc string "Use source path to load source file
|
||
|
.CW findsrc
|
||
|
interprets its
|
||
|
.I string
|
||
|
argument as a source file. Each directory in the source path is searched
|
||
|
in turn for the file. If the file is found, the source text is loaded using
|
||
|
.CW file
|
||
|
and stored in the list of active source files called
|
||
|
.CW srctext .
|
||
|
The name of the file is added to the source file name list
|
||
|
.CW srcfiles .
|
||
|
Users are unlikely to call
|
||
|
.CW findsrc
|
||
|
from the command line, but may use it from scripts to preload source files
|
||
|
for a debugging session. This function is used by
|
||
|
.CW src
|
||
|
and
|
||
|
.CW line
|
||
|
to locate and load source code. The default search path for the MIPS
|
||
|
is
|
||
|
.CW ./ ,
|
||
|
.CW /sys/src/libc/port ,
|
||
|
.CW /sys/src/libc/9sys ,
|
||
|
.CW /sys/src/libc/mips .
|
||
|
.Ex
|
||
|
acid: findsrc(pcfile(main));
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP fpr "" "Display single precision floating registers
|
||
|
For machines equipped with floating point,
|
||
|
.CW fpr
|
||
|
displays the contents of the floating point registers as single precision
|
||
|
values. When the interpreter stores or manipulates floating point values
|
||
|
it converts into double precision values.
|
||
|
.Ex
|
||
|
acid: fpr()
|
||
|
F0 0. F1 0.
|
||
|
F2 0. F3 0.
|
||
|
F4 0. F5 0.
|
||
|
\&...
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP func "" "Step while in function
|
||
|
.CW func
|
||
|
single steps the active process until it leaves the current function
|
||
|
by either calling another function or returning to its caller.
|
||
|
.CW func
|
||
|
will execute a single instruction after leaving the current function.
|
||
|
.Ex
|
||
|
acid: func()
|
||
|
95197: breakpoint ls+0x8 MOVW R1,R8
|
||
|
95197: breakpoint ls+0xc MOVW R8,R1
|
||
|
95197: breakpoint ls+0x10 MOVW R8,s+4(FP)
|
||
|
95197: breakpoint ls+0x14 MOVW $0x2f,R5
|
||
|
95197: breakpoint ls+0x18 JAL utfrrune(SB)
|
||
|
95197: breakpoint utfrrune ADD $-0x18,R29
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP gpr "" "Display general purpose registers
|
||
|
.CW gpr
|
||
|
prints the values of the general purpose processor registers.
|
||
|
.Ex
|
||
|
acid: gpr()
|
||
|
R1 0x00009562 R2 0x000010a4 R3 0x00005d08
|
||
|
R4 0x0000000a R5 0x0000002f R6 0x00000008
|
||
|
\&...
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP labstk integer "Print stack trace from label
|
||
|
.CW labstk
|
||
|
performs a stack trace from a Plan 9
|
||
|
.I label.
|
||
|
The kernel,
|
||
|
C compilers store continuations in a common format. Since the
|
||
|
compilers all use caller save conventions a continuation may be saved by
|
||
|
storing a
|
||
|
.CW PC
|
||
|
and
|
||
|
.CW SP
|
||
|
pair. This data structure is called a label and is used by the
|
||
|
the C function
|
||
|
.CW longjmp
|
||
|
and the kernel to schedule threads and processes.
|
||
|
.CW labstk
|
||
|
interprets its
|
||
|
.I integer
|
||
|
argument as the address of a label and produces a stack trace for
|
||
|
the thread of execution. The value of the function
|
||
|
.CW ALEF_tid
|
||
|
is a suitable argument for
|
||
|
.CW labstk .
|
||
|
.Ex
|
||
|
acid: labstk(*mousetid)
|
||
|
At pc:0x00021a70:Rendez_Sleep+0x178 rendez.l:44
|
||
|
Rendez_Sleep(r=0xcd7d8,bool=0xcd7e0,t=0x0) rendez.l:5
|
||
|
called from ALEF_rcvmem+0x198 recvmem.l:45
|
||
|
ALEF_rcvmem(c=0x000cd764,l=0x00000010) recvmem.l:6
|
||
|
\&...
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP lstk "" "Stack trace with local variables
|
||
|
.CW lstk
|
||
|
produces a long format stack trace.
|
||
|
The stack trace includes each function in the stack,
|
||
|
where it was called from, and the value of the parameters and automatic
|
||
|
variables for each function.
|
||
|
.CW lstk
|
||
|
displays the value rather than the address of each variable and all
|
||
|
variables are assumed to be an integer in format
|
||
|
.CW X .
|
||
|
To print a variable in its correct format use the
|
||
|
.CW :
|
||
|
operator to find the address and apply the appropriate format before indirection
|
||
|
with the
|
||
|
.CW *
|
||
|
operator. It may be necessary to single step a couple of instructions into
|
||
|
a function to get a correct stack trace because the frame pointer adjustment
|
||
|
instruction may get scheduled down into the body of the function.
|
||
|
.Ex
|
||
|
acid: lstk()
|
||
|
At pc:0x00001024:main+0x4 ls.c:48
|
||
|
main(argc=0x00000001,argv=0x7fffefec) ls.c:48
|
||
|
called from _main+0x20 main9.s:10
|
||
|
_argc=0x00000000
|
||
|
_args=0x00000000
|
||
|
fd=0x00000000
|
||
|
buf=0x00000000
|
||
|
i=0x00000000
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP mem integer,string "Print memory object
|
||
|
.CW mem
|
||
|
interprets its first
|
||
|
.I integer
|
||
|
argument as the address of an object to be printed according to the
|
||
|
format supplied in its second
|
||
|
.I string
|
||
|
argument.
|
||
|
The format string can be any combination of format characters, each preceded
|
||
|
by an optional count.
|
||
|
.Ex
|
||
|
acid: mem(bdata+0x326, "2c2Xb")
|
||
|
P = 0xa94bc464 0x3e5ae44d 19
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP new "" "Create new process
|
||
|
.CW new
|
||
|
starts a new copy of the debugged program. The new program is started
|
||
|
with the program arguments set by the variable
|
||
|
.CW progargs .
|
||
|
The new program is stopped in the second instruction of
|
||
|
.CW main .
|
||
|
The breakpoint list is reinitialized.
|
||
|
.CW new
|
||
|
may be used several times to instantiate several copies of a program
|
||
|
simultaneously. The user can rotate between the copies using
|
||
|
.CW setproc .
|
||
|
.Ex
|
||
|
acid: progargs="-l"
|
||
|
acid: new()
|
||
|
60: external interrupt _main ADD $-0x14,R29
|
||
|
60: breakpoint main+0x4 MOVW R31,0x0(R29)
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP next "" "Step through language statement
|
||
|
.CW next
|
||
|
steps through a single language level statement without tracing down
|
||
|
through each statement in a called function. For each statement,
|
||
|
.CW next
|
||
|
prints the machine instructions executed as part of the statement. After
|
||
|
the statement has executed, source lines around the current program
|
||
|
counter are displayed.
|
||
|
.Ex
|
||
|
acid: next()
|
||
|
60: breakpoint Binit+0x4 MOVW R31,0x0(R29)
|
||
|
60: breakpoint Binit+0x8 MOVW f+8(FP),R4
|
||
|
binit.c:93
|
||
|
88
|
||
|
89 int
|
||
|
90 Binit(Biobuf *bp, int f, int mode)
|
||
|
91 {
|
||
|
>92 return Binits(bp, f, mode, bp->b, BSIZE);
|
||
|
93 }
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP notestk integer "Stack trace after receiving a note
|
||
|
.CW notestk
|
||
|
interprets its
|
||
|
.I integer
|
||
|
argument as the address of a
|
||
|
.CW Ureg
|
||
|
structure passed by the kernel to a
|
||
|
.I notify (2)
|
||
|
function during note processing.
|
||
|
.CW notestk
|
||
|
uses the
|
||
|
.CW PC ,
|
||
|
.CW SP ,
|
||
|
and link register from the
|
||
|
.CW Ureg
|
||
|
to print a stack trace corresponding to the point in the program where the note
|
||
|
was received.
|
||
|
To get a valid stack trace on the MIPS and SPARC architectures from a notify
|
||
|
routine, the program must stop in a new function called from the notify routine
|
||
|
so that the link register is valid and the notify routine's parameters are
|
||
|
addressable.
|
||
|
.Ex
|
||
|
acid: notestk(*notify:ur)
|
||
|
Note pc:0x00001024:main+0x4 ls.c:48
|
||
|
main(argc=0x00000001,argv=0x7fffefec) ls.c:48
|
||
|
called from _main+0x20 main9.s:10
|
||
|
_argc=0x00000000
|
||
|
_args=0x00000000
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP pfl integer "Print source file and line
|
||
|
.CW pfl
|
||
|
interprets its argument as a text address and uses it to print
|
||
|
the source file and line number corresponding to the address. The output
|
||
|
has the same format as file addresses in
|
||
|
.I acme (1).
|
||
|
.Ex
|
||
|
acid: pfl(main)
|
||
|
ls.c:48
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP procs "" "Print active process list
|
||
|
.CW procs
|
||
|
prints a list of active process attached to the debugger. Each process
|
||
|
produces a single line of output giving the pid, process state, the address
|
||
|
the process is currently executing, and the
|
||
|
.CW setproc
|
||
|
command required to make that process current.
|
||
|
The current process is marked in the first column with a
|
||
|
.CW >
|
||
|
character. The debugger maintains a list of processes in the variable
|
||
|
.CW proclist .
|
||
|
.Ex
|
||
|
acid: procs()
|
||
|
>62: Stopped at main+0x4 setproc(62)
|
||
|
60: Stopped at Binit+0x8 setproc(60)
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP pstop integer "Print reason process stopped
|
||
|
.CW pstop
|
||
|
prints the status of the process specified by the
|
||
|
.I integer
|
||
|
pid supplied as its argument.
|
||
|
.CW pstop
|
||
|
is usually called from
|
||
|
.CW stopped
|
||
|
every time a process enters the
|
||
|
.CW Stopped
|
||
|
state.
|
||
|
.Ex
|
||
|
acid: pstop(62)
|
||
|
0x0000003e: breakpoint main+0x4 MOVW R31,0x0(R29)
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP regs "" "Print registers
|
||
|
.CW regs
|
||
|
prints the contents of both the general and special purpose registers.
|
||
|
.CW regs
|
||
|
calls
|
||
|
.CW spr
|
||
|
then
|
||
|
.CW gpr
|
||
|
to display the contents of the registers.
|
||
|
.KE
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP source "" "Summarize source data base
|
||
|
.CW source
|
||
|
prints the directory search path followed by a list of currently loaded
|
||
|
source files. The source management functions
|
||
|
.CW src
|
||
|
and
|
||
|
.CW findsrc
|
||
|
use the search path to locate and load source files. Source files are
|
||
|
loaded incrementally into a source data base during debugging. A list
|
||
|
of loaded files is stored in the variable
|
||
|
.CW srcfiles
|
||
|
and the contents of each source file in the variable
|
||
|
.CW srctext .
|
||
|
.Ex
|
||
|
acid: source()
|
||
|
/n/bootes/sys/src/libbio/
|
||
|
./
|
||
|
/sys/src/libc/port/
|
||
|
/sys/src/libc/9sys/
|
||
|
/sys/src/libc/mips/
|
||
|
binit.c
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP spr "" "Print special purpose registers
|
||
|
.CW spr
|
||
|
prints the contents of the processor control and memory management
|
||
|
registers. Where possible, the contents of the registers are decoded
|
||
|
to provide extra information; for example the
|
||
|
.CW CAUSE
|
||
|
register on the MIPS is
|
||
|
printed both in hexadecimal and using the
|
||
|
.CW reason
|
||
|
function.
|
||
|
.Ex
|
||
|
acid: spr()
|
||
|
PC 0x00001024 main+0x4 ls.c:48
|
||
|
SP 0x7fffef68 LINK 0x00006264 _main+0x28 main9.s:12
|
||
|
STATUS 0x0000ff33 CAUSE 0x00000024 breakpoint
|
||
|
TLBVIR 0x000000d3 BADVADR 0x00001020
|
||
|
HI 0x00000004 LO 0x00001ff7
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP src integer "Print lines of source
|
||
|
.CW src
|
||
|
interprets its
|
||
|
.I integer
|
||
|
argument as a text address and uses this address to print 5 lines
|
||
|
of source before and after the address. The current line is marked with a
|
||
|
.CW >
|
||
|
character.
|
||
|
.CW src
|
||
|
uses the source search path maintained by
|
||
|
.CW source
|
||
|
and
|
||
|
.CW addsrcdir
|
||
|
to locate the required source files.
|
||
|
.Ex
|
||
|
acid: src(*PC)
|
||
|
ls.c:47
|
||
|
42 Biobuf bin;
|
||
|
43
|
||
|
44 #define HUNK 50
|
||
|
45
|
||
|
46 void
|
||
|
>47 main(int argc, char *argv[])
|
||
|
48 {
|
||
|
49 int i, fd;
|
||
|
50 char buf[64];
|
||
|
51
|
||
|
52 Binit(&bin, 1, OWRITE);
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP step "" "Single step process
|
||
|
.CW step
|
||
|
causes the debugged process to execute a single machine level instruction.
|
||
|
If the program is stopped on a breakpoint set by
|
||
|
.CW bpset
|
||
|
it is first removed, the single step executed, and the breakpoint replaced.
|
||
|
.CW step
|
||
|
uses
|
||
|
.CW follow
|
||
|
to predict the address of the program counter after the current instruction
|
||
|
has been executed. A breakpoint is placed at each of these predicted addresses
|
||
|
and the process is started. When the process stops the breakpoints are removed.
|
||
|
.Ex
|
||
|
acid: step()
|
||
|
62: breakpoint main+0x8 MOVW R1,argc+4(FP)
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP stk "" "Stack trace
|
||
|
.CW stk
|
||
|
produces a short format stack trace. The stack trace includes each function
|
||
|
in the stack, where it was called from, and the value of the parameters.
|
||
|
The short format omits the values of automatic variables.
|
||
|
Parameters are assumed to be integer values in the format
|
||
|
.CW X ;
|
||
|
to print a parameter in the correct format use the
|
||
|
.CW :
|
||
|
to obtain its address, apply the correct format, and use the
|
||
|
.CW *
|
||
|
indirection operator to find its value.
|
||
|
It may be necessary to single step a couple of instructions into
|
||
|
a function to get a correct stack trace because the frame pointer adjustment
|
||
|
instruction may get scheduled down into the body of the function.
|
||
|
.Ex
|
||
|
acid: stk()
|
||
|
At pc:0x00001028:main+0x8 ls.c:48
|
||
|
main(argc=0x00000002,argv=0x7fffefe4) ls.c:48
|
||
|
called from _main+0x20 main9.s:10
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP stmnt "" "Execute a single statement
|
||
|
.CW stmnt
|
||
|
executes a single language level statement.
|
||
|
.CW stmnt
|
||
|
displays each machine level instruction as it is executed. When the executed
|
||
|
statement is completed the source for the next statement is displayed.
|
||
|
Unlike
|
||
|
.CW next ,
|
||
|
the
|
||
|
.CW stmnt
|
||
|
function will trace down through function calls.
|
||
|
.Ex
|
||
|
acid: stmnt()
|
||
|
62: breakpoint main+0x18 MOVW R5,0xc(R29)
|
||
|
62: breakpoint main+0x1c JAL Binit(SB)
|
||
|
62: breakpoint Binit ADD $-0x18,R29
|
||
|
binit.c:91
|
||
|
89 int
|
||
|
90 Binit(Biobuf *bp, int f, int mode)
|
||
|
>91 {
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP stopped integer "Report status of stopped process
|
||
|
.CW stopped
|
||
|
is called automatically by the interpreter
|
||
|
every time a process enters the
|
||
|
.CW Stopped
|
||
|
state, such as when it hits a breakpoint.
|
||
|
The pid is passed as the
|
||
|
.I integer
|
||
|
argument. The default implementation just calls
|
||
|
.CW pstop ,
|
||
|
but the function may be changed to provide more information or perform fine control
|
||
|
of execution. Note that
|
||
|
.CW stopped
|
||
|
should return; for example, calling
|
||
|
.CW step
|
||
|
in
|
||
|
.CW stopped
|
||
|
will recur until the interpreter runs out of stack space.
|
||
|
.Ex
|
||
|
acid: defn stopped(pid) {
|
||
|
if *lflag != 0 then error("lflag modified");
|
||
|
}
|
||
|
acid: progargs = "-l"
|
||
|
acid: new();
|
||
|
acid: while 1 do step();
|
||
|
<stdin>:7: (error) lflag modified
|
||
|
acid: stk()
|
||
|
At pc:0x00001220:main+0x200 ls.c:54
|
||
|
main(argc=0x00000001,argv=0x7fffffe8) ls.c:48
|
||
|
called from _main+0x20 main9.s:10
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP symbols string "Search symbol table
|
||
|
.CW symbols
|
||
|
uses the regular expression supplied by
|
||
|
.I string
|
||
|
to search the symbol table for symbols whose name matches the
|
||
|
regular expression.
|
||
|
.Ex
|
||
|
acid: symbols("main")
|
||
|
main T 0x00001020
|
||
|
_main T 0x0000623c
|
||
|
.Ee
|
||
|
.\"
|
||
|
.\"
|
||
|
.\"
|
||
|
.Ip \f(CW{}\fP win "" "Start new process in a window
|
||
|
.CW win
|
||
|
performs exactly the same function as
|
||
|
.CW new
|
||
|
but uses the window system to create a new window for the debugged process.
|
||
|
The variable
|
||
|
.CW progargs
|
||
|
supplies arguments to the new process.
|
||
|
The environment variable
|
||
|
.CW $8½srv
|
||
|
must be set to allow the interpreter to locate the mount channel for the
|
||
|
window system.
|
||
|
The window is created in the top left corner of the screen and is
|
||
|
400x600 pixels in size. The
|
||
|
.CW win
|
||
|
function may be modified to alter the geometry.
|
||
|
The window system will not be able to deliver notes in the new window
|
||
|
since the pid of the created process is not passed when the server is
|
||
|
mounted to create a new window.
|
||
|
.Ex
|
||
|
acid: win()
|
||
|
.Ee
|