You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1129 lines
48 KiB
HTML
1129 lines
48 KiB
HTML
15 years ago
|
<HTML>
|
||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||
|
<!-- Created on March, 27 2008 by texi2html 1.64 -->
|
||
|
<!--
|
||
|
Written by: Lionel Cons <Lionel.Cons@cern.ch> (original author)
|
||
|
Karl Berry <karl@freefriends.org>
|
||
|
Olaf Bachmann <obachman@mathematik.uni-kl.de>
|
||
|
and many others.
|
||
|
Maintained by: Olaf Bachmann <obachman@mathematik.uni-kl.de>
|
||
|
Send bugs and suggestions to <texi2html@mathematik.uni-kl.de>
|
||
|
|
||
|
-->
|
||
|
<HEAD>
|
||
|
<TITLE>Debugging with GDB: Agent Expressions</TITLE>
|
||
|
|
||
|
<META NAME="description" CONTENT="Debugging with GDB: Agent Expressions">
|
||
|
<META NAME="keywords" CONTENT="Debugging with GDB: Agent Expressions">
|
||
|
<META NAME="resource-type" CONTENT="document">
|
||
|
<META NAME="distribution" CONTENT="global">
|
||
|
<META NAME="Generator" CONTENT="texi2html 1.64">
|
||
|
|
||
|
</HEAD>
|
||
|
|
||
|
<BODY LANG="" BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#800080" ALINK="#FF0000">
|
||
|
|
||
|
<A NAME="SEC738"></A>
|
||
|
<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
|
||
|
<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_33.html#SEC737"> < </A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_34.html#SEC739"> > </A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_35.html#SEC745"> << </A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb.html#SEC_Top"> Up </A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_35.html#SEC745"> >> </A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb.html#SEC_Top">Top</A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_toc.html#SEC_Contents">Contents</A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_38.html#SEC764">Index</A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_abt.html#SEC_About"> ? </A>]</TD>
|
||
|
</TR></TABLE>
|
||
|
<H1> E. The GDB Agent Expression Mechanism </H1>
|
||
|
<!--docid::SEC738::-->
|
||
|
<P>
|
||
|
|
||
|
In some applications, it is not feasible for the debugger to interrupt
|
||
|
the program's execution long enough for the developer to learn anything
|
||
|
helpful about its behavior. If the program's correctness depends on its
|
||
|
real-time behavior, delays introduced by a debugger might cause the
|
||
|
program to fail, even when the code itself is correct. It is useful to
|
||
|
be able to observe the program's behavior without interrupting it.
|
||
|
</P><P>
|
||
|
|
||
|
Using GDB's <CODE>trace</CODE> and <CODE>collect</CODE> commands, the user can
|
||
|
specify locations in the program, and arbitrary expressions to evaluate
|
||
|
when those locations are reached. Later, using the <CODE>tfind</CODE>
|
||
|
command, she can examine the values those expressions had when the
|
||
|
program hit the trace points. The expressions may also denote objects
|
||
|
in memory -- structures or arrays, for example -- whose values GDB
|
||
|
should record; while visiting a particular tracepoint, the user may
|
||
|
inspect those objects as if they were in memory at that moment.
|
||
|
However, because GDB records these values without interacting with the
|
||
|
user, it can do so quickly and unobtrusively, hopefully not disturbing
|
||
|
the program's behavior.
|
||
|
</P><P>
|
||
|
|
||
|
When GDB is debugging a remote target, the GDB <EM>agent</EM> code running
|
||
|
on the target computes the values of the expressions itself. To avoid
|
||
|
having a full symbolic expression evaluator on the agent, GDB translates
|
||
|
expressions in the source language into a simpler bytecode language, and
|
||
|
then sends the bytecode to the agent; the agent then executes the
|
||
|
bytecode, and records the values for GDB to retrieve later.
|
||
|
</P><P>
|
||
|
|
||
|
The bytecode language is simple; there are forty-odd opcodes, the bulk
|
||
|
of which are the usual vocabulary of C operands (addition, subtraction,
|
||
|
shifts, and so on) and various sizes of literals and memory reference
|
||
|
operations. The bytecode interpreter operates strictly on machine-level
|
||
|
values -- various sizes of integers and floating point numbers -- and
|
||
|
requires no information about types or symbols; thus, the interpreter's
|
||
|
internal data structures are simple, and each bytecode requires only a
|
||
|
few native machine instructions to implement it. The interpreter is
|
||
|
small, and strict limits on the memory and time required to evaluate an
|
||
|
expression are easy to determine, making it suitable for use by the
|
||
|
debugging agent in real-time applications.
|
||
|
</P><P>
|
||
|
|
||
|
<BLOCKQUOTE><TABLE BORDER=0 CELLSPACING=0>
|
||
|
<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="gdb_34.html#SEC739">E.1 General Bytecode Design</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP">Overview of the interpreter.</TD></TR>
|
||
|
<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="gdb_34.html#SEC740">E.2 Bytecode Descriptions</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP">What each one does.</TD></TR>
|
||
|
<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="gdb_34.html#SEC741">E.3 Using Agent Expressions</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP">How agent expressions fit into the big picture.</TD></TR>
|
||
|
<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="gdb_34.html#SEC742">E.4 Varying Target Capabilities</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP">How to discover what the target can do.</TD></TR>
|
||
|
<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="gdb_34.html#SEC743">E.5 Tracing on Symmetrix</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP">Special info for implementation on EMC's
|
||
|
boxes.</TD></TR>
|
||
|
<TR><TD ALIGN="left" VALIGN="TOP"><A HREF="gdb_34.html#SEC744">E.6 Rationale</A></TD><TD> </TD><TD ALIGN="left" VALIGN="TOP">Why we did it this way.</TD></TR>
|
||
|
</TABLE></BLOCKQUOTE>
|
||
|
<P>
|
||
|
|
||
|
<A NAME="General Bytecode Design"></A>
|
||
|
<HR SIZE="6">
|
||
|
<A NAME="SEC739"></A>
|
||
|
<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
|
||
|
<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_34.html#SEC738"> < </A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_34.html#SEC740"> > </A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_34.html#SEC738"> << </A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_34.html#SEC738"> Up </A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_35.html#SEC745"> >> </A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb.html#SEC_Top">Top</A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_toc.html#SEC_Contents">Contents</A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_38.html#SEC764">Index</A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_abt.html#SEC_About"> ? </A>]</TD>
|
||
|
</TR></TABLE>
|
||
|
<H2> E.1 General Bytecode Design </H2>
|
||
|
<!--docid::SEC739::-->
|
||
|
<P>
|
||
|
|
||
|
The agent represents bytecode expressions as an array of bytes. Each
|
||
|
instruction is one byte long (thus the term <EM>bytecode</EM>). Some
|
||
|
instructions are followed by operand bytes; for example, the <CODE>goto</CODE>
|
||
|
instruction is followed by a destination for the jump.
|
||
|
</P><P>
|
||
|
|
||
|
The bytecode interpreter is a stack-based machine; most instructions pop
|
||
|
their operands off the stack, perform some operation, and push the
|
||
|
result back on the stack for the next instruction to consume. Each
|
||
|
element of the stack may contain either a integer or a floating point
|
||
|
value; these values are as many bits wide as the largest integer that
|
||
|
can be directly manipulated in the source language. Stack elements
|
||
|
carry no record of their type; bytecode could push a value as an
|
||
|
integer, then pop it as a floating point value. However, GDB will not
|
||
|
generate code which does this. In C, one might define the type of a
|
||
|
stack element as follows:
|
||
|
<TABLE><tr><td> </td><td class=example><pre>union agent_val {
|
||
|
LONGEST l;
|
||
|
DOUBLEST d;
|
||
|
};
|
||
|
</pre></td></tr></table>where <CODE>LONGEST</CODE> and <CODE>DOUBLEST</CODE> are <CODE>typedef</CODE> names for
|
||
|
the largest integer and floating point types on the machine.
|
||
|
</P><P>
|
||
|
|
||
|
By the time the bytecode interpreter reaches the end of the expression,
|
||
|
the value of the expression should be the only value left on the stack.
|
||
|
For tracing applications, <CODE>trace</CODE> bytecodes in the expression will
|
||
|
have recorded the necessary data, and the value on the stack may be
|
||
|
discarded. For other applications, like conditional breakpoints, the
|
||
|
value may be useful.
|
||
|
</P><P>
|
||
|
|
||
|
Separate from the stack, the interpreter has two registers:
|
||
|
<DL COMPACT>
|
||
|
<DT><CODE>pc</CODE>
|
||
|
<DD>The address of the next bytecode to execute.
|
||
|
<P>
|
||
|
|
||
|
<DT><CODE>start</CODE>
|
||
|
<DD>The address of the start of the bytecode expression, necessary for
|
||
|
interpreting the <CODE>goto</CODE> and <CODE>if_goto</CODE> instructions.
|
||
|
<P>
|
||
|
|
||
|
</DL>
|
||
|
Neither of these registers is directly visible to the bytecode language
|
||
|
itself, but they are useful for defining the meanings of the bytecode
|
||
|
operations.
|
||
|
<P>
|
||
|
|
||
|
There are no instructions to perform side effects on the running
|
||
|
program, or call the program's functions; we assume that these
|
||
|
expressions are only used for unobtrusive debugging, not for patching
|
||
|
the running code.
|
||
|
</P><P>
|
||
|
|
||
|
Most bytecode instructions do not distinguish between the various sizes
|
||
|
of values, and operate on full-width values; the upper bits of the
|
||
|
values are simply ignored, since they do not usually make a difference
|
||
|
to the value computed. The exceptions to this rule are:
|
||
|
<DL COMPACT>
|
||
|
|
||
|
<DT>memory reference instructions (<CODE>ref</CODE><VAR>n</VAR>)
|
||
|
<DD>There are distinct instructions to fetch different word sizes from
|
||
|
memory. Once on the stack, however, the values are treated as full-size
|
||
|
integers. They may need to be sign-extended; the <CODE>ext</CODE> instruction
|
||
|
exists for this purpose.
|
||
|
<P>
|
||
|
|
||
|
<DT>the sign-extension instruction (<CODE>ext</CODE> <VAR>n</VAR>)
|
||
|
<DD>These clearly need to know which portion of their operand is to be
|
||
|
extended to occupy the full length of the word.
|
||
|
<P>
|
||
|
|
||
|
</DL>
|
||
|
<P>
|
||
|
|
||
|
If the interpreter is unable to evaluate an expression completely for
|
||
|
some reason (a memory location is inaccessible, or a divisor is zero,
|
||
|
for example), we say that interpretation "terminates with an error".
|
||
|
This means that the problem is reported back to the interpreter's caller
|
||
|
in some helpful way. In general, code using agent expressions should
|
||
|
assume that they may attempt to divide by zero, fetch arbitrary memory
|
||
|
locations, and misbehave in other ways.
|
||
|
</P><P>
|
||
|
|
||
|
Even complicated C expressions compile to a few bytecode instructions;
|
||
|
for example, the expression <CODE>x + y * z</CODE> would typically produce
|
||
|
code like the following, assuming that <CODE>x</CODE> and <CODE>y</CODE> live in
|
||
|
registers, and <CODE>z</CODE> is a global variable holding a 32-bit
|
||
|
<CODE>int</CODE>:
|
||
|
<TABLE><tr><td> </td><td class=example><pre>reg 1
|
||
|
reg 2
|
||
|
const32 <I>address of z</I>
|
||
|
ref32
|
||
|
ext 32
|
||
|
mul
|
||
|
add
|
||
|
end
|
||
|
</pre></td></tr></table></P><P>
|
||
|
|
||
|
In detail, these mean:
|
||
|
<DL COMPACT>
|
||
|
|
||
|
<DT><CODE>reg 1</CODE>
|
||
|
<DD>Push the value of register 1 (presumably holding <CODE>x</CODE>) onto the
|
||
|
stack.
|
||
|
<P>
|
||
|
|
||
|
<DT><CODE>reg 2</CODE>
|
||
|
<DD>Push the value of register 2 (holding <CODE>y</CODE>).
|
||
|
<P>
|
||
|
|
||
|
<DT><CODE>const32 <I>address of z</I></CODE>
|
||
|
<DD>Push the address of <CODE>z</CODE> onto the stack.
|
||
|
<P>
|
||
|
|
||
|
<DT><CODE>ref32</CODE>
|
||
|
<DD>Fetch a 32-bit word from the address at the top of the stack; replace
|
||
|
the address on the stack with the value. Thus, we replace the address
|
||
|
of <CODE>z</CODE> with <CODE>z</CODE>'s value.
|
||
|
<P>
|
||
|
|
||
|
<DT><CODE>ext 32</CODE>
|
||
|
<DD>Sign-extend the value on the top of the stack from 32 bits to full
|
||
|
length. This is necessary because <CODE>z</CODE> is a signed integer.
|
||
|
<P>
|
||
|
|
||
|
<DT><CODE>mul</CODE>
|
||
|
<DD>Pop the top two numbers on the stack, multiply them, and push their
|
||
|
product. Now the top of the stack contains the value of the expression
|
||
|
<CODE>y * z</CODE>.
|
||
|
<P>
|
||
|
|
||
|
<DT><CODE>add</CODE>
|
||
|
<DD>Pop the top two numbers, add them, and push the sum. Now the top of the
|
||
|
stack contains the value of <CODE>x + y * z</CODE>.
|
||
|
<P>
|
||
|
|
||
|
<DT><CODE>end</CODE>
|
||
|
<DD>Stop executing; the value left on the stack top is the value to be
|
||
|
recorded.
|
||
|
<P>
|
||
|
|
||
|
</DL>
|
||
|
<P>
|
||
|
|
||
|
<A NAME="Bytecode Descriptions"></A>
|
||
|
<HR SIZE="6">
|
||
|
<A NAME="SEC740"></A>
|
||
|
<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
|
||
|
<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_34.html#SEC739"> < </A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_34.html#SEC741"> > </A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_34.html#SEC741"> << </A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_34.html#SEC738"> Up </A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_35.html#SEC745"> >> </A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb.html#SEC_Top">Top</A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_toc.html#SEC_Contents">Contents</A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_38.html#SEC764">Index</A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_abt.html#SEC_About"> ? </A>]</TD>
|
||
|
</TR></TABLE>
|
||
|
<H2> E.2 Bytecode Descriptions </H2>
|
||
|
<!--docid::SEC740::-->
|
||
|
<P>
|
||
|
|
||
|
Each bytecode description has the following form:
|
||
|
</P><P>
|
||
|
|
||
|
<DL COMPACT>
|
||
|
|
||
|
<DT><CODE>add</CODE> (0x02): <VAR>a</VAR> <VAR>b</VAR> => <VAR>a+b</VAR>
|
||
|
<DD><P>
|
||
|
|
||
|
Pop the top two stack items, <VAR>a</VAR> and <VAR>b</VAR>, as integers; push
|
||
|
their sum, as an integer.
|
||
|
</P><P>
|
||
|
|
||
|
</DL>
|
||
|
<P>
|
||
|
|
||
|
In this example, <CODE>add</CODE> is the name of the bytecode, and
|
||
|
<CODE>(0x02)</CODE> is the one-byte value used to encode the bytecode, in
|
||
|
hexadecimal. The phrase "<VAR>a</VAR> <VAR>b</VAR> => <VAR>a+b</VAR>" shows
|
||
|
the stack before and after the bytecode executes. Beforehand, the stack
|
||
|
must contain at least two values, <VAR>a</VAR> and <VAR>b</VAR>; since the top of
|
||
|
the stack is to the right, <VAR>b</VAR> is on the top of the stack, and
|
||
|
<VAR>a</VAR> is underneath it. After execution, the bytecode will have
|
||
|
popped <VAR>a</VAR> and <VAR>b</VAR> from the stack, and replaced them with a
|
||
|
single value, <VAR>a+b</VAR>. There may be other values on the stack below
|
||
|
those shown, but the bytecode affects only those shown.
|
||
|
</P><P>
|
||
|
|
||
|
Here is another example:
|
||
|
</P><P>
|
||
|
|
||
|
<DL COMPACT>
|
||
|
|
||
|
<DT><CODE>const8</CODE> (0x22) <VAR>n</VAR>: => <VAR>n</VAR>
|
||
|
<DD>Push the 8-bit integer constant <VAR>n</VAR> on the stack, without sign
|
||
|
extension.
|
||
|
<P>
|
||
|
|
||
|
</DL>
|
||
|
<P>
|
||
|
|
||
|
In this example, the bytecode <CODE>const8</CODE> takes an operand <VAR>n</VAR>
|
||
|
directly from the bytecode stream; the operand follows the <CODE>const8</CODE>
|
||
|
bytecode itself. We write any such operands immediately after the name
|
||
|
of the bytecode, before the colon, and describe the exact encoding of
|
||
|
the operand in the bytecode stream in the body of the bytecode
|
||
|
description.
|
||
|
</P><P>
|
||
|
|
||
|
For the <CODE>const8</CODE> bytecode, there are no stack items given before
|
||
|
the =>; this simply means that the bytecode consumes no values
|
||
|
from the stack. If a bytecode consumes no values, or produces no
|
||
|
values, the list on either side of the => may be empty.
|
||
|
</P><P>
|
||
|
|
||
|
If a value is written as <VAR>a</VAR>, <VAR>b</VAR>, or <VAR>n</VAR>, then the bytecode
|
||
|
treats it as an integer. If a value is written is <VAR>addr</VAR>, then the
|
||
|
bytecode treats it as an address.
|
||
|
</P><P>
|
||
|
|
||
|
We do not fully describe the floating point operations here; although
|
||
|
this design can be extended in a clean way to handle floating point
|
||
|
values, they are not of immediate interest to the customer, so we avoid
|
||
|
describing them, to save time.
|
||
|
</P><P>
|
||
|
|
||
|
<DL COMPACT>
|
||
|
|
||
|
<DT><CODE>float</CODE> (0x01): =>
|
||
|
<DD><P>
|
||
|
|
||
|
Prefix for floating-point bytecodes. Not implemented yet.
|
||
|
</P><P>
|
||
|
|
||
|
<DT><CODE>add</CODE> (0x02): <VAR>a</VAR> <VAR>b</VAR> => <VAR>a+b</VAR>
|
||
|
<DD>Pop two integers from the stack, and push their sum, as an integer.
|
||
|
<P>
|
||
|
|
||
|
<DT><CODE>sub</CODE> (0x03): <VAR>a</VAR> <VAR>b</VAR> => <VAR>a-b</VAR>
|
||
|
<DD>Pop two integers from the stack, subtract the top value from the
|
||
|
next-to-top value, and push the difference.
|
||
|
<P>
|
||
|
|
||
|
<DT><CODE>mul</CODE> (0x04): <VAR>a</VAR> <VAR>b</VAR> => <VAR>a*b</VAR>
|
||
|
<DD>Pop two integers from the stack, multiply them, and push the product on
|
||
|
the stack. Note that, when one multiplies two <VAR>n</VAR>-bit numbers
|
||
|
yielding another <VAR>n</VAR>-bit number, it is irrelevant whether the
|
||
|
numbers are signed or not; the results are the same.
|
||
|
<P>
|
||
|
|
||
|
<DT><CODE>div_signed</CODE> (0x05): <VAR>a</VAR> <VAR>b</VAR> => <VAR>a/b</VAR>
|
||
|
<DD>Pop two signed integers from the stack; divide the next-to-top value by
|
||
|
the top value, and push the quotient. If the divisor is zero, terminate
|
||
|
with an error.
|
||
|
<P>
|
||
|
|
||
|
<DT><CODE>div_unsigned</CODE> (0x06): <VAR>a</VAR> <VAR>b</VAR> => <VAR>a/b</VAR>
|
||
|
<DD>Pop two unsigned integers from the stack; divide the next-to-top value
|
||
|
by the top value, and push the quotient. If the divisor is zero,
|
||
|
terminate with an error.
|
||
|
<P>
|
||
|
|
||
|
<DT><CODE>rem_signed</CODE> (0x07): <VAR>a</VAR> <VAR>b</VAR> => <VAR>a modulo b</VAR>
|
||
|
<DD>Pop two signed integers from the stack; divide the next-to-top value by
|
||
|
the top value, and push the remainder. If the divisor is zero,
|
||
|
terminate with an error.
|
||
|
<P>
|
||
|
|
||
|
<DT><CODE>rem_unsigned</CODE> (0x08): <VAR>a</VAR> <VAR>b</VAR> => <VAR>a modulo b</VAR>
|
||
|
<DD>Pop two unsigned integers from the stack; divide the next-to-top value
|
||
|
by the top value, and push the remainder. If the divisor is zero,
|
||
|
terminate with an error.
|
||
|
<P>
|
||
|
|
||
|
<DT><CODE>lsh</CODE> (0x09): <VAR>a</VAR> <VAR>b</VAR> => <VAR>a<<b</VAR>
|
||
|
<DD>Pop two integers from the stack; let <VAR>a</VAR> be the next-to-top value,
|
||
|
and <VAR>b</VAR> be the top value. Shift <VAR>a</VAR> left by <VAR>b</VAR> bits, and
|
||
|
push the result.
|
||
|
<P>
|
||
|
|
||
|
<DT><CODE>rsh_signed</CODE> (0x0a): <VAR>a</VAR> <VAR>b</VAR> => <CODE>(signed)</CODE><VAR>a>>b</VAR>
|
||
|
<DD>Pop two integers from the stack; let <VAR>a</VAR> be the next-to-top value,
|
||
|
and <VAR>b</VAR> be the top value. Shift <VAR>a</VAR> right by <VAR>b</VAR> bits,
|
||
|
inserting copies of the top bit at the high end, and push the result.
|
||
|
<P>
|
||
|
|
||
|
<DT><CODE>rsh_unsigned</CODE> (0x0b): <VAR>a</VAR> <VAR>b</VAR> => <VAR>a>>b</VAR>
|
||
|
<DD>Pop two integers from the stack; let <VAR>a</VAR> be the next-to-top value,
|
||
|
and <VAR>b</VAR> be the top value. Shift <VAR>a</VAR> right by <VAR>b</VAR> bits,
|
||
|
inserting zero bits at the high end, and push the result.
|
||
|
<P>
|
||
|
|
||
|
<DT><CODE>log_not</CODE> (0x0e): <VAR>a</VAR> => <VAR>!a</VAR>
|
||
|
<DD>Pop an integer from the stack; if it is zero, push the value one;
|
||
|
otherwise, push the value zero.
|
||
|
<P>
|
||
|
|
||
|
<DT><CODE>bit_and</CODE> (0x0f): <VAR>a</VAR> <VAR>b</VAR> => <VAR>a&b</VAR>
|
||
|
<DD>Pop two integers from the stack, and push their bitwise <CODE>and</CODE>.
|
||
|
<P>
|
||
|
|
||
|
<DT><CODE>bit_or</CODE> (0x10): <VAR>a</VAR> <VAR>b</VAR> => <VAR>a|b</VAR>
|
||
|
<DD>Pop two integers from the stack, and push their bitwise <CODE>or</CODE>.
|
||
|
<P>
|
||
|
|
||
|
<DT><CODE>bit_xor</CODE> (0x11): <VAR>a</VAR> <VAR>b</VAR> => <VAR>a^b</VAR>
|
||
|
<DD>Pop two integers from the stack, and push their bitwise
|
||
|
exclusive-<CODE>or</CODE>.
|
||
|
<P>
|
||
|
|
||
|
<DT><CODE>bit_not</CODE> (0x12): <VAR>a</VAR> => <VAR>~a</VAR>
|
||
|
<DD>Pop an integer from the stack, and push its bitwise complement.
|
||
|
<P>
|
||
|
|
||
|
<DT><CODE>equal</CODE> (0x13): <VAR>a</VAR> <VAR>b</VAR> => <VAR>a=b</VAR>
|
||
|
<DD>Pop two integers from the stack; if they are equal, push the value one;
|
||
|
otherwise, push the value zero.
|
||
|
<P>
|
||
|
|
||
|
<DT><CODE>less_signed</CODE> (0x14): <VAR>a</VAR> <VAR>b</VAR> => <VAR>a<b</VAR>
|
||
|
<DD>Pop two signed integers from the stack; if the next-to-top value is less
|
||
|
than the top value, push the value one; otherwise, push the value zero.
|
||
|
<P>
|
||
|
|
||
|
<DT><CODE>less_unsigned</CODE> (0x15): <VAR>a</VAR> <VAR>b</VAR> => <VAR>a<b</VAR>
|
||
|
<DD>Pop two unsigned integers from the stack; if the next-to-top value is less
|
||
|
than the top value, push the value one; otherwise, push the value zero.
|
||
|
<P>
|
||
|
|
||
|
<DT><CODE>ext</CODE> (0x16) <VAR>n</VAR>: <VAR>a</VAR> => <VAR>a</VAR>, sign-extended from <VAR>n</VAR> bits
|
||
|
<DD>Pop an unsigned value from the stack; treating it as an <VAR>n</VAR>-bit
|
||
|
twos-complement value, extend it to full length. This means that all
|
||
|
bits to the left of bit <VAR>n-1</VAR> (where the least significant bit is bit
|
||
|
0) are set to the value of bit <VAR>n-1</VAR>. Note that <VAR>n</VAR> may be
|
||
|
larger than or equal to the width of the stack elements of the bytecode
|
||
|
engine; in this case, the bytecode should have no effect.
|
||
|
<P>
|
||
|
|
||
|
The number of source bits to preserve, <VAR>n</VAR>, is encoded as a single
|
||
|
byte unsigned integer following the <CODE>ext</CODE> bytecode.
|
||
|
</P><P>
|
||
|
|
||
|
<DT><CODE>zero_ext</CODE> (0x2a) <VAR>n</VAR>: <VAR>a</VAR> => <VAR>a</VAR>, zero-extended from <VAR>n</VAR> bits
|
||
|
<DD>Pop an unsigned value from the stack; zero all but the bottom <VAR>n</VAR>
|
||
|
bits. This means that all bits to the left of bit <VAR>n-1</VAR> (where the
|
||
|
least significant bit is bit 0) are set to the value of bit <VAR>n-1</VAR>.
|
||
|
<P>
|
||
|
|
||
|
The number of source bits to preserve, <VAR>n</VAR>, is encoded as a single
|
||
|
byte unsigned integer following the <CODE>zero_ext</CODE> bytecode.
|
||
|
</P><P>
|
||
|
|
||
|
<DT><CODE>ref8</CODE> (0x17): <VAR>addr</VAR> => <VAR>a</VAR>
|
||
|
<DD><DT><CODE>ref16</CODE> (0x18): <VAR>addr</VAR> => <VAR>a</VAR>
|
||
|
<DD><DT><CODE>ref32</CODE> (0x19): <VAR>addr</VAR> => <VAR>a</VAR>
|
||
|
<DD><DT><CODE>ref64</CODE> (0x1a): <VAR>addr</VAR> => <VAR>a</VAR>
|
||
|
<DD>Pop an address <VAR>addr</VAR> from the stack. For bytecode
|
||
|
<CODE>ref</CODE><VAR>n</VAR>, fetch an <VAR>n</VAR>-bit value from <VAR>addr</VAR>, using the
|
||
|
natural target endianness. Push the fetched value as an unsigned
|
||
|
integer.
|
||
|
<P>
|
||
|
|
||
|
Note that <VAR>addr</VAR> may not be aligned in any particular way; the
|
||
|
<CODE>ref<VAR>n</VAR></CODE> bytecodes should operate correctly for any address.
|
||
|
</P><P>
|
||
|
|
||
|
If attempting to access memory at <VAR>addr</VAR> would cause a processor
|
||
|
exception of some sort, terminate with an error.
|
||
|
</P><P>
|
||
|
|
||
|
<DT><CODE>ref_float</CODE> (0x1b): <VAR>addr</VAR> => <VAR>d</VAR>
|
||
|
<DD><DT><CODE>ref_double</CODE> (0x1c): <VAR>addr</VAR> => <VAR>d</VAR>
|
||
|
<DD><DT><CODE>ref_long_double</CODE> (0x1d): <VAR>addr</VAR> => <VAR>d</VAR>
|
||
|
<DD><DT><CODE>l_to_d</CODE> (0x1e): <VAR>a</VAR> => <VAR>d</VAR>
|
||
|
<DD><DT><CODE>d_to_l</CODE> (0x1f): <VAR>d</VAR> => <VAR>a</VAR>
|
||
|
<DD>Not implemented yet.
|
||
|
<P>
|
||
|
|
||
|
<DT><CODE>dup</CODE> (0x28): <VAR>a</VAR> => <VAR>a</VAR> <VAR>a</VAR>
|
||
|
<DD>Push another copy of the stack's top element.
|
||
|
<P>
|
||
|
|
||
|
<DT><CODE>swap</CODE> (0x2b): <VAR>a</VAR> <VAR>b</VAR> => <VAR>b</VAR> <VAR>a</VAR>
|
||
|
<DD>Exchange the top two items on the stack.
|
||
|
<P>
|
||
|
|
||
|
<DT><CODE>pop</CODE> (0x29): <VAR>a</VAR> =>
|
||
|
<DD>Discard the top value on the stack.
|
||
|
<P>
|
||
|
|
||
|
<DT><CODE>if_goto</CODE> (0x20) <VAR>offset</VAR>: <VAR>a</VAR> =>
|
||
|
<DD>Pop an integer off the stack; if it is non-zero, branch to the given
|
||
|
offset in the bytecode string. Otherwise, continue to the next
|
||
|
instruction in the bytecode stream. In other words, if <VAR>a</VAR> is
|
||
|
non-zero, set the <CODE>pc</CODE> register to <CODE>start</CODE> + <VAR>offset</VAR>.
|
||
|
Thus, an offset of zero denotes the beginning of the expression.
|
||
|
<P>
|
||
|
|
||
|
The <VAR>offset</VAR> is stored as a sixteen-bit unsigned value, stored
|
||
|
immediately following the <CODE>if_goto</CODE> bytecode. It is always stored
|
||
|
most significant byte first, regardless of the target's normal
|
||
|
endianness. The offset is not guaranteed to fall at any particular
|
||
|
alignment within the bytecode stream; thus, on machines where fetching a
|
||
|
16-bit on an unaligned address raises an exception, you should fetch the
|
||
|
offset one byte at a time.
|
||
|
</P><P>
|
||
|
|
||
|
<DT><CODE>goto</CODE> (0x21) <VAR>offset</VAR>: =>
|
||
|
<DD>Branch unconditionally to <VAR>offset</VAR>; in other words, set the
|
||
|
<CODE>pc</CODE> register to <CODE>start</CODE> + <VAR>offset</VAR>.
|
||
|
<P>
|
||
|
|
||
|
The offset is stored in the same way as for the <CODE>if_goto</CODE> bytecode.
|
||
|
</P><P>
|
||
|
|
||
|
<DT><CODE>const8</CODE> (0x22) <VAR>n</VAR>: => <VAR>n</VAR>
|
||
|
<DD><DT><CODE>const16</CODE> (0x23) <VAR>n</VAR>: => <VAR>n</VAR>
|
||
|
<DD><DT><CODE>const32</CODE> (0x24) <VAR>n</VAR>: => <VAR>n</VAR>
|
||
|
<DD><DT><CODE>const64</CODE> (0x25) <VAR>n</VAR>: => <VAR>n</VAR>
|
||
|
<DD>Push the integer constant <VAR>n</VAR> on the stack, without sign extension.
|
||
|
To produce a small negative value, push a small twos-complement value,
|
||
|
and then sign-extend it using the <CODE>ext</CODE> bytecode.
|
||
|
<P>
|
||
|
|
||
|
The constant <VAR>n</VAR> is stored in the appropriate number of bytes
|
||
|
following the <CODE>const</CODE><VAR>b</VAR> bytecode. The constant <VAR>n</VAR> is
|
||
|
always stored most significant byte first, regardless of the target's
|
||
|
normal endianness. The constant is not guaranteed to fall at any
|
||
|
particular alignment within the bytecode stream; thus, on machines where
|
||
|
fetching a 16-bit on an unaligned address raises an exception, you
|
||
|
should fetch <VAR>n</VAR> one byte at a time.
|
||
|
</P><P>
|
||
|
|
||
|
<DT><CODE>reg</CODE> (0x26) <VAR>n</VAR>: => <VAR>a</VAR>
|
||
|
<DD>Push the value of register number <VAR>n</VAR>, without sign extension. The
|
||
|
registers are numbered following GDB's conventions.
|
||
|
<P>
|
||
|
|
||
|
The register number <VAR>n</VAR> is encoded as a 16-bit unsigned integer
|
||
|
immediately following the <CODE>reg</CODE> bytecode. It is always stored most
|
||
|
significant byte first, regardless of the target's normal endianness.
|
||
|
The register number is not guaranteed to fall at any particular
|
||
|
alignment within the bytecode stream; thus, on machines where fetching a
|
||
|
16-bit on an unaligned address raises an exception, you should fetch the
|
||
|
register number one byte at a time.
|
||
|
</P><P>
|
||
|
|
||
|
<DT><CODE>trace</CODE> (0x0c): <VAR>addr</VAR> <VAR>size</VAR> =>
|
||
|
<DD>Record the contents of the <VAR>size</VAR> bytes at <VAR>addr</VAR> in a trace
|
||
|
buffer, for later retrieval by GDB.
|
||
|
<P>
|
||
|
|
||
|
<DT><CODE>trace_quick</CODE> (0x0d) <VAR>size</VAR>: <VAR>addr</VAR> => <VAR>addr</VAR>
|
||
|
<DD>Record the contents of the <VAR>size</VAR> bytes at <VAR>addr</VAR> in a trace
|
||
|
buffer, for later retrieval by GDB. <VAR>size</VAR> is a single byte
|
||
|
unsigned integer following the <CODE>trace</CODE> opcode.
|
||
|
<P>
|
||
|
|
||
|
This bytecode is equivalent to the sequence <CODE>dup const8 <VAR>size</VAR>
|
||
|
trace</CODE>, but we provide it anyway to save space in bytecode strings.
|
||
|
</P><P>
|
||
|
|
||
|
<DT><CODE>trace16</CODE> (0x30) <VAR>size</VAR>: <VAR>addr</VAR> => <VAR>addr</VAR>
|
||
|
<DD>Identical to trace_quick, except that <VAR>size</VAR> is a 16-bit big-endian
|
||
|
unsigned integer, not a single byte. This should probably have been
|
||
|
named <CODE>trace_quick16</CODE>, for consistency.
|
||
|
<P>
|
||
|
|
||
|
<DT><CODE>end</CODE> (0x27): =>
|
||
|
<DD>Stop executing bytecode; the result should be the top element of the
|
||
|
stack. If the purpose of the expression was to compute an lvalue or a
|
||
|
range of memory, then the next-to-top of the stack is the lvalue's
|
||
|
address, and the top of the stack is the lvalue's size, in bytes.
|
||
|
<P>
|
||
|
|
||
|
</DL>
|
||
|
<P>
|
||
|
|
||
|
<A NAME="Using Agent Expressions"></A>
|
||
|
<HR SIZE="6">
|
||
|
<A NAME="SEC741"></A>
|
||
|
<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
|
||
|
<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_34.html#SEC740"> < </A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_34.html#SEC742"> > </A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_34.html#SEC742"> << </A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_34.html#SEC738"> Up </A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_35.html#SEC745"> >> </A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb.html#SEC_Top">Top</A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_toc.html#SEC_Contents">Contents</A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_38.html#SEC764">Index</A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_abt.html#SEC_About"> ? </A>]</TD>
|
||
|
</TR></TABLE>
|
||
|
<H2> E.3 Using Agent Expressions </H2>
|
||
|
<!--docid::SEC741::-->
|
||
|
<P>
|
||
|
|
||
|
Here is a sketch of a full non-stop debugging cycle, showing how agent
|
||
|
expressions fit into the process.
|
||
|
</P><P>
|
||
|
|
||
|
<UL>
|
||
|
|
||
|
<LI>
|
||
|
The user selects trace points in the program's code at which GDB should
|
||
|
collect data.
|
||
|
<P>
|
||
|
|
||
|
<LI>
|
||
|
The user specifies expressions to evaluate at each trace point. These
|
||
|
expressions may denote objects in memory, in which case those objects'
|
||
|
contents are recorded as the program runs, or computed values, in which
|
||
|
case the values themselves are recorded.
|
||
|
<P>
|
||
|
|
||
|
<LI>
|
||
|
GDB transmits the tracepoints and their associated expressions to the
|
||
|
GDB agent, running on the debugging target.
|
||
|
<P>
|
||
|
|
||
|
<LI>
|
||
|
The agent arranges to be notified when a trace point is hit. Note that,
|
||
|
on some systems, the target operating system is completely responsible
|
||
|
for collecting the data; see <A HREF="gdb_34.html#SEC743">E.5 Tracing on Symmetrix</A>.
|
||
|
<P>
|
||
|
|
||
|
<LI>
|
||
|
When execution on the target reaches a trace point, the agent evaluates
|
||
|
the expressions associated with that trace point, and records the
|
||
|
resulting values and memory ranges.
|
||
|
<P>
|
||
|
|
||
|
<LI>
|
||
|
Later, when the user selects a given trace event and inspects the
|
||
|
objects and expression values recorded, GDB talks to the agent to
|
||
|
retrieve recorded data as necessary to meet the user's requests. If the
|
||
|
user asks to see an object whose contents have not been recorded, GDB
|
||
|
reports an error.
|
||
|
<P>
|
||
|
|
||
|
</UL>
|
||
|
<P>
|
||
|
|
||
|
<A NAME="Varying Target Capabilities"></A>
|
||
|
<HR SIZE="6">
|
||
|
<A NAME="SEC742"></A>
|
||
|
<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
|
||
|
<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_34.html#SEC741"> < </A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_34.html#SEC743"> > </A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_34.html#SEC743"> << </A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_34.html#SEC738"> Up </A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_35.html#SEC745"> >> </A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb.html#SEC_Top">Top</A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_toc.html#SEC_Contents">Contents</A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_38.html#SEC764">Index</A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_abt.html#SEC_About"> ? </A>]</TD>
|
||
|
</TR></TABLE>
|
||
|
<H2> E.4 Varying Target Capabilities </H2>
|
||
|
<!--docid::SEC742::-->
|
||
|
<P>
|
||
|
|
||
|
Some targets don't support floating-point, and some would rather not
|
||
|
have to deal with <CODE>long long</CODE> operations. Also, different targets
|
||
|
will have different stack sizes, and different bytecode buffer lengths.
|
||
|
</P><P>
|
||
|
|
||
|
Thus, GDB needs a way to ask the target about itself. We haven't worked
|
||
|
out the details yet, but in general, GDB should be able to send the
|
||
|
target a packet asking it to describe itself. The reply should be a
|
||
|
packet whose length is explicit, so we can add new information to the
|
||
|
packet in future revisions of the agent, without confusing old versions
|
||
|
of GDB, and it should contain a version number. It should contain at
|
||
|
least the following information:
|
||
|
</P><P>
|
||
|
|
||
|
<UL>
|
||
|
|
||
|
<LI>
|
||
|
whether floating point is supported
|
||
|
<P>
|
||
|
|
||
|
<LI>
|
||
|
whether <CODE>long long</CODE> is supported
|
||
|
<P>
|
||
|
|
||
|
<LI>
|
||
|
maximum acceptable size of bytecode stack
|
||
|
<P>
|
||
|
|
||
|
<LI>
|
||
|
maximum acceptable length of bytecode expressions
|
||
|
<P>
|
||
|
|
||
|
<LI>
|
||
|
which registers are actually available for collection
|
||
|
<P>
|
||
|
|
||
|
<LI>
|
||
|
whether the target supports disabled tracepoints
|
||
|
<P>
|
||
|
|
||
|
</UL>
|
||
|
<P>
|
||
|
|
||
|
<A NAME="Tracing on Symmetrix"></A>
|
||
|
<HR SIZE="6">
|
||
|
<A NAME="SEC743"></A>
|
||
|
<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
|
||
|
<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_34.html#SEC742"> < </A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_34.html#SEC744"> > </A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_34.html#SEC744"> << </A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_34.html#SEC738"> Up </A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_35.html#SEC745"> >> </A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb.html#SEC_Top">Top</A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_toc.html#SEC_Contents">Contents</A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_38.html#SEC764">Index</A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_abt.html#SEC_About"> ? </A>]</TD>
|
||
|
</TR></TABLE>
|
||
|
<H2> E.5 Tracing on Symmetrix </H2>
|
||
|
<!--docid::SEC743::-->
|
||
|
<P>
|
||
|
|
||
|
This section documents the API used by the GDB agent to collect data on
|
||
|
Symmetrix systems.
|
||
|
</P><P>
|
||
|
|
||
|
Cygnus originally implemented these tracing features to help EMC
|
||
|
Corporation debug their Symmetrix high-availability disk drives. The
|
||
|
Symmetrix application code already includes substantial tracing
|
||
|
facilities; the GDB agent for the Symmetrix system uses those facilities
|
||
|
for its own data collection, via the API described here.
|
||
|
</P><P>
|
||
|
|
||
|
<A NAME="IDX1654"></A>
|
||
|
<DL>
|
||
|
<DT><U>Function:</U> DTC_RESPONSE <B>adbg_find_memory_in_frame</B> <I>(FRAME_DEF *<VAR>frame</VAR>, char *<VAR>address</VAR>, char **<VAR>buffer</VAR>, unsigned int *<VAR>size</VAR>)</I>
|
||
|
<DD>Search the trace frame <VAR>frame</VAR> for memory saved from <VAR>address</VAR>.
|
||
|
If the memory is available, provide the address of the buffer holding
|
||
|
it; otherwise, provide the address of the next saved area.
|
||
|
</P><P>
|
||
|
|
||
|
<UL>
|
||
|
|
||
|
<LI>
|
||
|
If the memory at <VAR>address</VAR> was saved in <VAR>frame</VAR>, set
|
||
|
<CODE>*<VAR>buffer</VAR></CODE> to point to the buffer in which that memory was
|
||
|
saved, set <CODE>*<VAR>size</VAR></CODE> to the number of bytes from <VAR>address</VAR>
|
||
|
that are saved at <CODE>*<VAR>buffer</VAR></CODE>, and return
|
||
|
<CODE>OK_TARGET_RESPONSE</CODE>. (Clearly, in this case, the function will
|
||
|
always set <CODE>*<VAR>size</VAR></CODE> to a value greater than zero.)
|
||
|
<P>
|
||
|
|
||
|
<LI>
|
||
|
If <VAR>frame</VAR> does not record any memory at <VAR>address</VAR>, set
|
||
|
<CODE>*<VAR>size</VAR></CODE> to the distance from <VAR>address</VAR> to the start of
|
||
|
the saved region with the lowest address higher than <VAR>address</VAR>. If
|
||
|
there is no memory saved from any higher address, set <CODE>*<VAR>size</VAR></CODE>
|
||
|
to zero. Return <CODE>NOT_FOUND_TARGET_RESPONSE</CODE>.
|
||
|
</UL>
|
||
|
<P>
|
||
|
|
||
|
These two possibilities allow the caller to either retrieve the data, or
|
||
|
walk the address space to the next saved area.
|
||
|
</DL>
|
||
|
</P><P>
|
||
|
|
||
|
This function allows the GDB agent to map the regions of memory saved in
|
||
|
a particular frame, and retrieve their contents efficiently.
|
||
|
</P><P>
|
||
|
|
||
|
This function also provides a clean interface between the GDB agent and
|
||
|
the Symmetrix tracing structures, making it easier to adapt the GDB
|
||
|
agent to future versions of the Symmetrix system, and vice versa. This
|
||
|
function searches all data saved in <VAR>frame</VAR>, whether the data is
|
||
|
there at the request of a bytecode expression, or because it falls in
|
||
|
one of the format's memory ranges, or because it was saved from the top
|
||
|
of the stack. EMC can arbitrarily change and enhance the tracing
|
||
|
mechanism, but as long as this function works properly, all collected
|
||
|
memory is visible to GDB.
|
||
|
</P><P>
|
||
|
|
||
|
The function itself is straightforward to implement. A single pass over
|
||
|
the trace frame's stack area, memory ranges, and expression blocks can
|
||
|
yield the address of the buffer (if the requested address was saved),
|
||
|
and also note the address of the next higher range of memory, to be
|
||
|
returned when the search fails.
|
||
|
</P><P>
|
||
|
|
||
|
As an example, suppose the trace frame <CODE>f</CODE> has saved sixteen bytes
|
||
|
from address <CODE>0x8000</CODE> in a buffer at <CODE>0x1000</CODE>, and thirty-two
|
||
|
bytes from address <CODE>0xc000</CODE> in a buffer at <CODE>0x1010</CODE>. Here are
|
||
|
some sample calls, and the effect each would have:
|
||
|
</P><P>
|
||
|
|
||
|
<DL COMPACT>
|
||
|
|
||
|
<DT><CODE>adbg_find_memory_in_frame (f, (char*) 0x8000, &buffer, &size)</CODE>
|
||
|
<DD>This would set <CODE>buffer</CODE> to <CODE>0x1000</CODE>, set <CODE>size</CODE> to
|
||
|
sixteen, and return <CODE>OK_TARGET_RESPONSE</CODE>, since <CODE>f</CODE> saves
|
||
|
sixteen bytes from <CODE>0x8000</CODE> at <CODE>0x1000</CODE>.
|
||
|
<P>
|
||
|
|
||
|
<DT><CODE>adbg_find_memory_in_frame (f, (char *) 0x8004, &buffer, &size)</CODE>
|
||
|
<DD>This would set <CODE>buffer</CODE> to <CODE>0x1004</CODE>, set <CODE>size</CODE> to
|
||
|
twelve, and return <CODE>OK_TARGET_RESPONSE</CODE>, since <TT>`f'</TT> saves the
|
||
|
twelve bytes from <CODE>0x8004</CODE> starting four bytes into the buffer at
|
||
|
<CODE>0x1000</CODE>. This shows that request addresses may fall in the middle
|
||
|
of saved areas; the function should return the address and size of the
|
||
|
remainder of the buffer.
|
||
|
<P>
|
||
|
|
||
|
<DT><CODE>adbg_find_memory_in_frame (f, (char *) 0x8100, &buffer, &size)</CODE>
|
||
|
<DD>This would set <CODE>size</CODE> to <CODE>0x3f00</CODE> and return
|
||
|
<CODE>NOT_FOUND_TARGET_RESPONSE</CODE>, since there is no memory saved in
|
||
|
<CODE>f</CODE> from the address <CODE>0x8100</CODE>, and the next memory available
|
||
|
is at <CODE>0x8100 + 0x3f00</CODE>, or <CODE>0xc000</CODE>. This shows that request
|
||
|
addresses may fall outside of all saved memory ranges; the function
|
||
|
should indicate the next saved area, if any.
|
||
|
<P>
|
||
|
|
||
|
<DT><CODE>adbg_find_memory_in_frame (f, (char *) 0x7000, &buffer, &size)</CODE>
|
||
|
<DD>This would set <CODE>size</CODE> to <CODE>0x1000</CODE> and return
|
||
|
<CODE>NOT_FOUND_TARGET_RESPONSE</CODE>, since the next saved memory is at
|
||
|
<CODE>0x7000 + 0x1000</CODE>, or <CODE>0x8000</CODE>.
|
||
|
<P>
|
||
|
|
||
|
<DT><CODE>adbg_find_memory_in_frame (f, (char *) 0xf000, &buffer, &size)</CODE>
|
||
|
<DD>This would set <CODE>size</CODE> to zero, and return
|
||
|
<CODE>NOT_FOUND_TARGET_RESPONSE</CODE>. This shows how the function tells the
|
||
|
caller that no further memory ranges have been saved.
|
||
|
<P>
|
||
|
|
||
|
</DL>
|
||
|
<P>
|
||
|
|
||
|
As another example, here is a function which will print out the
|
||
|
addresses of all memory saved in the trace frame <CODE>frame</CODE> on the
|
||
|
Symmetrix INLINES console:
|
||
|
<TABLE><tr><td> </td><td class=example><pre>void
|
||
|
print_frame_addresses (FRAME_DEF *frame)
|
||
|
{
|
||
|
char *addr;
|
||
|
char *buffer;
|
||
|
unsigned long size;
|
||
|
|
||
|
addr = 0;
|
||
|
for (;;)
|
||
|
{
|
||
|
/* Either find out how much memory we have here, or discover
|
||
|
where the next saved region is. */
|
||
|
if (adbg_find_memory_in_frame (frame, addr, &buffer, &size)
|
||
|
== OK_TARGET_RESPONSE)
|
||
|
printp ("saved %x to %x\n", addr, addr + size);
|
||
|
if (size == 0)
|
||
|
break;
|
||
|
addr += size;
|
||
|
}
|
||
|
}
|
||
|
</pre></td></tr></table></P><P>
|
||
|
|
||
|
Note that there is not necessarily any connection between the order in
|
||
|
which the data is saved in the trace frame, and the order in which
|
||
|
<CODE>adbg_find_memory_in_frame</CODE> will return those memory ranges. The
|
||
|
code above will always print the saved memory regions in order of
|
||
|
increasing address, while the underlying frame structure might store the
|
||
|
data in a random order.
|
||
|
</P><P>
|
||
|
|
||
|
[[This section should cover the rest of the Symmetrix functions the stub
|
||
|
relies upon, too.]]
|
||
|
</P><P>
|
||
|
|
||
|
<A NAME="Rationale"></A>
|
||
|
<HR SIZE="6">
|
||
|
<A NAME="SEC744"></A>
|
||
|
<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
|
||
|
<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_34.html#SEC743"> < </A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_35.html#SEC745"> > </A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_34.html#SEC738"> << </A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_34.html#SEC738"> Up </A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_35.html#SEC745"> >> </A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb.html#SEC_Top">Top</A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_toc.html#SEC_Contents">Contents</A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_38.html#SEC764">Index</A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_abt.html#SEC_About"> ? </A>]</TD>
|
||
|
</TR></TABLE>
|
||
|
<H2> E.6 Rationale </H2>
|
||
|
<!--docid::SEC744::-->
|
||
|
<P>
|
||
|
|
||
|
Some of the design decisions apparent above are arguable.
|
||
|
</P><P>
|
||
|
|
||
|
<DL COMPACT>
|
||
|
|
||
|
<DT><B>What about stack overflow/underflow?</B>
|
||
|
<DD>GDB should be able to query the target to discover its stack size.
|
||
|
Given that information, GDB can determine at translation time whether a
|
||
|
given expression will overflow the stack. But this spec isn't about
|
||
|
what kinds of error-checking GDB ought to do.
|
||
|
<P>
|
||
|
|
||
|
<DT><B>Why are you doing everything in LONGEST?</B>
|
||
|
<DD><P>
|
||
|
|
||
|
Speed isn't important, but agent code size is; using LONGEST brings in a
|
||
|
bunch of support code to do things like division, etc. So this is a
|
||
|
serious concern.
|
||
|
</P><P>
|
||
|
|
||
|
First, note that you don't need different bytecodes for different
|
||
|
operand sizes. You can generate code without <EM>knowing</EM> how big the
|
||
|
stack elements actually are on the target. If the target only supports
|
||
|
32-bit ints, and you don't send any 64-bit bytecodes, everything just
|
||
|
works. The observation here is that the MIPS and the Alpha have only
|
||
|
fixed-size registers, and you can still get C's semantics even though
|
||
|
most instructions only operate on full-sized words. You just need to
|
||
|
make sure everything is properly sign-extended at the right times. So
|
||
|
there is no need for 32- and 64-bit variants of the bytecodes. Just
|
||
|
implement everything using the largest size you support.
|
||
|
</P><P>
|
||
|
|
||
|
GDB should certainly check to see what sizes the target supports, so the
|
||
|
user can get an error earlier, rather than later. But this information
|
||
|
is not necessary for correctness.
|
||
|
</P><P>
|
||
|
|
||
|
<DT><B>Why don't you have <CODE>></CODE> or <CODE><=</CODE> operators?</B>
|
||
|
<DD>I want to keep the interpreter small, and we don't need them. We can
|
||
|
combine the <CODE>less_</CODE> opcodes with <CODE>log_not</CODE>, and swap the order
|
||
|
of the operands, yielding all four asymmetrical comparison operators.
|
||
|
For example, <CODE>(x <= y)</CODE> is <CODE>! (x > y)</CODE>, which is <CODE>! (y <
|
||
|
x)</CODE>.
|
||
|
<P>
|
||
|
|
||
|
<DT><B>Why do you have <CODE>log_not</CODE>?</B>
|
||
|
<DD><DT><B>Why do you have <CODE>ext</CODE>?</B>
|
||
|
<DD><DT><B>Why do you have <CODE>zero_ext</CODE>?</B>
|
||
|
<DD>These are all easily synthesized from other instructions, but I expect
|
||
|
them to be used frequently, and they're simple, so I include them to
|
||
|
keep bytecode strings short.
|
||
|
<P>
|
||
|
|
||
|
<CODE>log_not</CODE> is equivalent to <CODE>const8 0 equal</CODE>; it's used in half
|
||
|
the relational operators.
|
||
|
</P><P>
|
||
|
|
||
|
<CODE>ext <VAR>n</VAR></CODE> is equivalent to <CODE>const8 <VAR>s-n</VAR> lsh const8
|
||
|
<VAR>s-n</VAR> rsh_signed</CODE>, where <VAR>s</VAR> is the size of the stack elements;
|
||
|
it follows <CODE>ref<VAR>m</VAR></CODE> and <VAR>reg</VAR> bytecodes when the value
|
||
|
should be signed. See the next bulleted item.
|
||
|
</P><P>
|
||
|
|
||
|
<CODE>zero_ext <VAR>n</VAR></CODE> is equivalent to <CODE>const<VAR>m</VAR> <VAR>mask</VAR>
|
||
|
log_and</CODE>; it's used whenever we push the value of a register, because we
|
||
|
can't assume the upper bits of the register aren't garbage.
|
||
|
</P><P>
|
||
|
|
||
|
<DT><B>Why not have sign-extending variants of the <CODE>ref</CODE> operators?</B>
|
||
|
<DD>Because that would double the number of <CODE>ref</CODE> operators, and we
|
||
|
need the <CODE>ext</CODE> bytecode anyway for accessing bitfields.
|
||
|
<P>
|
||
|
|
||
|
<DT><B>Why not have constant-address variants of the <CODE>ref</CODE> operators?</B>
|
||
|
<DD>Because that would double the number of <CODE>ref</CODE> operators again, and
|
||
|
<CODE>const32 <VAR>address</VAR> ref32</CODE> is only one byte longer.
|
||
|
<P>
|
||
|
|
||
|
<DT><B>Why do the <CODE>ref<VAR>n</VAR></CODE> operators have to support unaligned fetches?</B>
|
||
|
<DD>GDB will generate bytecode that fetches multi-byte values at unaligned
|
||
|
addresses whenever the executable's debugging information tells it to.
|
||
|
Furthermore, GDB does not know the value the pointer will have when GDB
|
||
|
generates the bytecode, so it cannot determine whether a particular
|
||
|
fetch will be aligned or not.
|
||
|
<P>
|
||
|
|
||
|
In particular, structure bitfields may be several bytes long, but follow
|
||
|
no alignment rules; members of packed structures are not necessarily
|
||
|
aligned either.
|
||
|
</P><P>
|
||
|
|
||
|
In general, there are many cases where unaligned references occur in
|
||
|
correct C code, either at the programmer's explicit request, or at the
|
||
|
compiler's discretion. Thus, it is simpler to make the GDB agent
|
||
|
bytecodes work correctly in all circumstances than to make GDB guess in
|
||
|
each case whether the compiler did the usual thing.
|
||
|
</P><P>
|
||
|
|
||
|
<DT><B>Why are there no side-effecting operators?</B>
|
||
|
<DD>Because our current client doesn't want them? That's a cheap answer. I
|
||
|
think the real answer is that I'm afraid of implementing function
|
||
|
calls. We should re-visit this issue after the present contract is
|
||
|
delivered.
|
||
|
<P>
|
||
|
|
||
|
<DT><B>Why aren't the <CODE>goto</CODE> ops PC-relative?</B>
|
||
|
<DD>The interpreter has the base address around anyway for PC bounds
|
||
|
checking, and it seemed simpler.
|
||
|
<P>
|
||
|
|
||
|
<DT><B>Why is there only one offset size for the <CODE>goto</CODE> ops?</B>
|
||
|
<DD>Offsets are currently sixteen bits. I'm not happy with this situation
|
||
|
either:
|
||
|
<P>
|
||
|
|
||
|
Suppose we have multiple branch ops with different offset sizes. As I
|
||
|
generate code left-to-right, all my jumps are forward jumps (there are
|
||
|
no loops in expressions), so I never know the target when I emit the
|
||
|
jump opcode. Thus, I have to either always assume the largest offset
|
||
|
size, or do jump relaxation on the code after I generate it, which seems
|
||
|
like a big waste of time.
|
||
|
</P><P>
|
||
|
|
||
|
I can imagine a reasonable expression being longer than 256 bytes. I
|
||
|
can't imagine one being longer than 64k. Thus, we need 16-bit offsets.
|
||
|
This kind of reasoning is so bogus, but relaxation is pathetic.
|
||
|
</P><P>
|
||
|
|
||
|
The other approach would be to generate code right-to-left. Then I'd
|
||
|
always know my offset size. That might be fun.
|
||
|
</P><P>
|
||
|
|
||
|
<DT><B>Where is the function call bytecode?</B>
|
||
|
<DD><P>
|
||
|
|
||
|
When we add side-effects, we should add this.
|
||
|
</P><P>
|
||
|
|
||
|
<DT><B>Why does the <CODE>reg</CODE> bytecode take a 16-bit register number?</B>
|
||
|
<DD><P>
|
||
|
|
||
|
Intel's IA-64 architecture has 128 general-purpose registers,
|
||
|
and 128 floating-point registers, and I'm sure it has some random
|
||
|
control registers.
|
||
|
</P><P>
|
||
|
|
||
|
<DT><B>Why do we need <CODE>trace</CODE> and <CODE>trace_quick</CODE>?</B>
|
||
|
<DD>Because GDB needs to record all the memory contents and registers an
|
||
|
expression touches. If the user wants to evaluate an expression
|
||
|
<CODE>x->y->z</CODE>, the agent must record the values of <CODE>x</CODE> and
|
||
|
<CODE>x->y</CODE> as well as the value of <CODE>x->y->z</CODE>.
|
||
|
<P>
|
||
|
|
||
|
<DT><B>Don't the <CODE>trace</CODE> bytecodes make the interpreter less general?</B>
|
||
|
<DD>They do mean that the interpreter contains special-purpose code, but
|
||
|
that doesn't mean the interpreter can only be used for that purpose. If
|
||
|
an expression doesn't use the <CODE>trace</CODE> bytecodes, they don't get in
|
||
|
its way.
|
||
|
<P>
|
||
|
|
||
|
<DT><B>Why doesn't <CODE>trace_quick</CODE> consume its arguments the way everything else does?</B>
|
||
|
<DD>In general, you do want your operators to consume their arguments; it's
|
||
|
consistent, and generally reduces the amount of stack rearrangement
|
||
|
necessary. However, <CODE>trace_quick</CODE> is a kludge to save space; it
|
||
|
only exists so we needn't write <CODE>dup const8 <VAR>SIZE</VAR> trace</CODE>
|
||
|
before every memory reference. Therefore, it's okay for it not to
|
||
|
consume its arguments; it's meant for a specific context in which we
|
||
|
know exactly what it should do with the stack. If we're going to have a
|
||
|
kludge, it should be an effective kludge.
|
||
|
<P>
|
||
|
|
||
|
<DT><B>Why does <CODE>trace16</CODE> exist?</B>
|
||
|
<DD>That opcode was added by the customer that contracted Cygnus for the
|
||
|
data tracing work. I personally think it is unnecessary; objects that
|
||
|
large will be quite rare, so it is okay to use <CODE>dup const16
|
||
|
<VAR>size</VAR> trace</CODE> in those cases.
|
||
|
<P>
|
||
|
|
||
|
Whatever we decide to do with <CODE>trace16</CODE>, we should at least leave
|
||
|
opcode 0x30 reserved, to remain compatible with the customer who added
|
||
|
it.
|
||
|
</P><P>
|
||
|
|
||
|
</DL>
|
||
|
<P>
|
||
|
|
||
|
<A NAME="Target Descriptions"></A>
|
||
|
<HR SIZE="6">
|
||
|
<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
|
||
|
<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_34.html#SEC738"> << </A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_35.html#SEC745"> >> </A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb.html#SEC_Top">Top</A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_toc.html#SEC_Contents">Contents</A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_38.html#SEC764">Index</A>]</TD>
|
||
|
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="gdb_abt.html#SEC_About"> ? </A>]</TD>
|
||
|
</TR></TABLE>
|
||
|
<BR>
|
||
|
<FONT SIZE="-1">
|
||
|
|
||
|
<address>
|
||
|
|
||
|
<p>Please send FSF & GNU inquiries & questions to <a
|
||
|
href="mailto:gnu@gnu.org">gnu@gnu.org</a>. There are also <a
|
||
|
href="http://www.gnu.org/home.html#ContactInfo">other ways to
|
||
|
contact</a> the FSF.</p>
|
||
|
|
||
|
<p>These pages are maintained by <a
|
||
|
href="http://www.gnu.org/software/gdb/">the GDB developers</a>.</p>
|
||
|
|
||
|
<p>Copyright Free Software Foundation, Inc., 59 Temple Place - Suite
|
||
|
330, Boston, MA 02111, USA.</p>
|
||
|
|
||
|
<p>Verbatim copying and distribution of this entire article is
|
||
|
permitted in any medium, provided this notice is preserved.</p>
|
||
|
|
||
|
</address>
|
||
|
|
||
|
This document was generated
|
||
|
by <I>GDB Administrator</I> on <I>March, 27 2008</I>
|
||
|
using <A HREF="http://www.mathematik.uni-kl.de/~obachman/Texi2html
|
||
|
"><I>texi2html</I></A>
|
||
|
|
||
|
</BODY>
|
||
|
</HTML>
|