Chapter Contents |
Previous |
Next |
Using Debugger Commands |
There are several argument types that are common to many commands. You should become familiar with these arguments in order to effectively use the commands that are described in Command Directory. The following common arguments are explained here:
Arguments that can be used only with one command are explained with that command in Command Directory.
SECTION-NAME and FUNCTION-NAME Arguments |
SECTION-NAME (which must be enclosed in parentheses)
is the section name for each source file as specified with the
sname
compiler option (or default). For example, the following drop
command uses a SECTION-NAME argument to drop all requests
for the
comp23
compilation:
drop (comp23) all |
Section names cannot exceed seven characters in length.
Note:
The terms section name and compilation
are used interchangeably in this book.
FUNCTION-NAME is the name of a function. For example,
the following break
command sets a breakpoint
on line 17 of the
main
function:
break main 17 |
break entry |
However, this command issues one breakpoint request
for the entry to function
suba
:
break suba entry |
suba
:
break suba 3:6 | |
break 3:6 |
Breakpoints will be requested at lines 3 through 6 in
suba
only.
HOOK-TYPE Argument |
Hooks are created at each source line in a SAS/C program
at compile time (when the program is compiled with the
debug
option). In addition to these line hooks, the debugger also enables you to
gain control at function calls, function entries, and function returns.
No hooks are generated for blank lines or for lines
that contain only comments. Certain hooks are generated for code that is included
via a
#include
file.
Rules for hook generation Here are some rules for hook generation:
if (a == b) i = 2;
1 for (i = 0; 2 i < 10; 3 i++) 4 { . . . }
In this example, the debugger stops at line 1 as it
falls into the loop. Then, the debugger stops at line 2 before performing
the test. After executing the body of the FOR statement, the debugger stops
at line 3 (
i
is examined before it is incremented) and then
at line 2.
If a function call spans lines, one hook is always generated
on the line in which the parenthesis occurs that closes the function call.
On the other lines, hooks are generated only if code is generated. (Because
a certain amount of optimization is performed even when the
debug
option is used, you cannot always determine which statements cause machine
code to be generated.)
As mentioned in the previous section, you can specify places (hooks) in a program in which you want to interrupt execution. You do this with the HOOK-TYPE argument. Values for the HOOK-TYPE Argument shows values that you use for the HOOK-TYPE argument.
TABLE NOTE 1: Some source lines, such as lines that contain a FOR statement, may actually contain more than one hook, as described in the previous section.
The
following examples of the break
command illustrate
the use of the HOOK-TYPE argument:
break *
break 25
break 18:22
break calls
break entry
break return
break suba *
suba
.
break main 15
main
.
break main 101:135
main
between line 101 and line 135, inclusive.
break (sub1) *
sub1
.
break checkup c
checkup
. The context is that of
checkup
. For each call,
there is a breakpoint at the call from
checkup
at the return to
checkup
.
EXPRESSION Argument |
i i + j i * (a + b) !strcmp(s, d) ((struct xyz *) 0p12345678)->a.b arr[i] .xyz->b strlen(s) == strlen(d) p == &x && q != &y
The expression's order of evaluation follows the operator's rules of precedence and associativity. Operators Supported in Expressions provides a list of the operators that are supported in expressions and operator precedence.
You make an integral constant unsigned by specifying
the
U
suffix. Similarly, use the
L
suffix to make an integral constant long, using
L
either alone, or combined
with
U
.
Constant pointers in an expression must be typed with
leading
0p
. A value such as
0p12345678
behaves the
same as
((char *)0x12345678)
in expressions.
0p12345678
is a short form for
((char *) 0x12345678)
.
Operators Supported in Expressions |
Operators Supported in Expressions lists the operators that you can use in expressions. They are grouped in order of highest to lowest precedence. The associativity is indicated by R-L (right-to-left) or L-R (left-to-right).
For more information about these C operators, see a C language manual.
Functions That Can Be Used in Expressions |
You can use the following functions in expressions:
Casts |
(TAG *) | |
(
struct
TAG *) | |
(
union
TAG *) | |
(
enum
TAG *) | |
(basic-arithmetic-data-type *). |
Zero or more
*
can be specified, as
long as the result is semantically valid. In many cases, the TAG format for
arguments is useful with these commands. Specifying an argument that is an
address, such as
*(struct tag*) address
enables you to refer to storage that starts
at any absolute address (ADDRESS) with the mapping of a structure, union,
or enumeration of the type named by TAG. For example, the following refers
to storage starting at the address in
0p23456789
with the mapping
of
struct listall
:
*(struct listall *) 0p23456789
Note:
The
struct
,
union
, or
enum
keywords can be dropped from the cast if no
ambiguity is introduced.
Structure and Union Members |
You can access a member of a structure by specifying the pointer
and the structure member name. For example, suppose
ptag
is declared to be a pointer to a structure named
TAG0
that has a member
named
mem0
. You can access
mem0
as follows:
ptag->mem0
You can also access memory, using the mapping of a different
structure, by casting the pointer to the appropriate pointer type. For example,
((struct TAG1 *)ptab)
is a pointer to structure
TAG1
.
You can access
mem1
as follows:
((struct TAG1 *) ptab)->mem1
If you are working with absolute addresses, you can
specify an absolute address with a cast to obtain a pointer to a structure.
((struct TAG2 *)0p00123456)
is a pointer to structure
TAG2
.
A member
mem2
of the structure can be accessed as follows:
((struct TAG2 *)0p00123456)->mem2
Macros |
To access macros in your program from the debugger,
you must compile your program with the dbgmacro
option. See Compiler Options.
In addition, except for the debugger whatis
command, in order to do macro substitution in an expression, you must set
the debugger keyword cmacros
. This keyword
is set with the auto
command. By default, cmacros
is not set.
Debugger Variables |
Debugger variables are used to represent the value that is contained in one of the 16 general purpose registers, one of the 4 floating-point registers, or the current instruction address. You can use debugger variables in any command that supports expressions; however, they cannot be modified. Debugger Variables lists the debugger variables along with the type that is assumed by the debugger.
Summary of Types of Expressions |
Types of Expressions That Can Be Used in print and Other Commands shows the types of expressions that you can use in the print
command and other
commands. See also the individual commands
in Command Directory for any restrictions that exist in substitutions for the EXPRESSION argument.
Output Formats |
When
you issue the print
command with only a single
argument (EXPRESSION), the value of the expression that you specify is formatted
according to its type (defined in Types of Expressions That Can Be Used in print and Other Commands).
The output formats are described in Command Directory.
Note: The format that is natural for the value's type is always used.
SCALAR-TYPE-EXPRESSION Argument |
SCALAR-TYPE-EXPRESSION is an expression whose type is arithmetic,
pointer, or bitfield. For example, the following assign
command assigns the address of
int_variable
to a pointer
name
int_ptr
.
assign int_ptr = &int_variable |
In this example,
int_ptr
is a SCALAR-TYPE-EXPRESSION
argument and
int_variable
is a VALUE argument. See VALUE Argument for more information.
AGGREGATE-TYPE-EXPRESSION Argument |
AGGREGATE-TYPE-EXPRESSION is an expression of type structure
or union. (It cannot be an array.) For example, the following assign
command assigns values from a value list to a structure
named
numbers
:
assign numbers = {1,2,3} |
In this example,
numbers
is an AGGREGATE-TYPE-EXPRESSION
argument, and
{1,2,3}
is a VALUE-LIST argument.
VALUE Argument |
VALUE is an expression whose type is one of the following:
You can assign a
value to any scalar expression that
is visible at the point at which you issue the assign
command. To refer to an identifier in an active function that is different
from the function that you are in, precede the identifier by the function
name and a colon. As discussed in Specifying Identifiers Outside the Current Function, the general form of this argument is FUNCTION-NAME:IDENTIFIER.
COUNT Argument |
With the print
command, COUNT is an integer constant that specifies
the number of items to be printed. For example, if
records
is a structure,
the following print
command prints the first
five elements of the structure in the format of the element.
print records 5
You can also use the COUNT argument with the dump
command to specify the number of bytes to dump. For example,
if
ptr
is a pointer, the following dump
command will dump the first ten bytes of storage beginning at the location
pointed to by
ptr
.
dump ptr 10
PTYPE Argument |
A PTYPE argument can be one of the following:
structure
,
union
,
or
enum
type
typedef
PTYPE can be specified for an EXPRESSION argument that belongs to type 1, 2, or 3 in Types of Expressions That Can Be Used in print and Other Commands. You cannot use a PTYPE argument with the other types.
char signed char unsigned char int signed int unsigned int long signed long unsigned long long long signed long long unsigned long long short signed short unsigned short double float
When you specify a PTYPE, the EXPRESSION argument acquires
the type indicated by PTYPE and is displayed using the rules for that type.
If you do not specify a PTYPE, the default is the type that is associated
with the expression in the program. For dereferenced absolute addresses,
the default is
char
.
Note:
One caution is necessary about structure types
and
typedefs
. If you have a structure in your program
and a
typedef
with the same type identifier, then using
the identifier by itself (with no
struct
identifier) refers
to the
typedef
, not the structure. For example, with a
structure type of
buf
and a
typedef
of
buf
,
the following command prints the storage that is referenced by
newvar
with the PTYPE of the
typedef buf
:
print newvar (buf) |
Use
struct
to obtain the PTYPE of the
structure
buf
, as in the following example:
print newvar (struct buf) |
If you specify only a type identifier, the debugger
searches for a
typedef
first. If the identifier is not found in
the list of
typedefs
, the debugger searches the list of structures,
unions, and enumerations next.
FUNCTION-NAME is any function in the calling sequence.
TYPE is a
struct
,
union
, or
enum
type identifier, or a type that is defined with a
typedef
. For example,
the following command prints the value of
x
using the type
XYZ
:
print x (sub1:XYZ) |
XYZ
is a type within the scope of
sub1
.
Example 1 |
int arr[5] ; /* assume arr begins at 0p15880 */
Command | Result |
---|---|
p arr |
arr : 0p00015880 |
- p arr (int) |
LSCD148 Array variable cannot be displayed using a TYPE/cast. |
- p arr (XXX) |
LSCD148 Array variable cannot be displayed using a TYPE/cast. |
Example 2 |
struct XXX int a; short b,c; ; typedef int INTARR[2] int x,y,z; /* assume x begins at 0p10000 */ /* assume x=10; y=20; z=30; */
Command | Result |
---|---|
p x |
x : 10 (0x0000000a) |
- p x (INTARR) |
LSCD148 Casting to an array type (INTARR) is not allowed. |
p x (int *) |
x : 0p0000000a |
- p x (union XXX) |
LSCD148 Invalid TYPE/cast "XXX" specified. |
Example 3 |
struct XXX {int a,b;} x={1,2}; struct YYY {int c,d,e,f;} y=3{,4,5,6};
Command | Result |
---|---|
p x.a |
x.a : 1 (0x00000001) |
p x.a |
x.b : 2 (0x00000002) |
p x (int *) |
x : 0p00000001 |
p y (XXX) |
&y : 0p00015880 y.a : 3 (0x00000003) y.b : 4 (0x00000004) |
Example 4 |
struct ZZZ { int a; double d1; }; struct ZZZ yyy; struct ZZZ *xp = &yyy; /* assume xp-->a = 5 and xp-->d1=3.24} */
Command | Result |
---|---|
p *xp |
&(*xp) : 0p00015880 (*xp) .a : 5 (0x00000005) (*xp) .d1: 3.24 |
p xp--> |
xp-->a : 5 (0x00 000005) |
Example 5 |
enum fruit apple, orange, pear, peach; enum fruit f1, f2; int i = 1, j = 5; f1 = apple; f2 = pear;
Command | Result |
---|---|
p f1 |
f1:0 (apple) |
p f2 |
f2:2 (pear) |
p i (enum fruit) |
i:1 (orange) |
- p j (enum fruit) |
j:5 (constant not in list for enum type fruit) - |
p peach |
peach:3 (enum constant) |
%FMT Argument |
The
%FMT argument is any of the format specifiers that you can use with the
sprintf
function. They include the following:
The format specifier must result in the item being formatted
in 256 characters or fewer. Also, if the EXPRESSION argument in the print
command contains a modulus operator
%
,
you must escape the modulus with a backslash
\
; otherwise, the debugger
interprets the modulus as a format specifier. The only exception to this rule
is modulus operators that are inside parenthesized expressions.
Chapter Contents |
Previous |
Next |
Top of Page |
Copyright © 2001 by SAS Institute Inc., Cary, NC, USA. All rights reserved.