Examining program data

This section explains how to examine, test, and modify program data.

Handling signals

The dbx debug program can either trap or ignore signals before they are sent to your program. Each time your program is to receive a signal, the dbx program is notified. If the signal is to be ignored, it is passed to your program; otherwise, the dbx program stops the program and notifies you that a signal has been trapped. The dbx program cannot ignore the SIGTRAP signal if it comes from a process outside of the debug process. In a multithreaded program, a signal can be sent to a particular thread via the pthread_kill subroutine. By default, the dbx program stops and notifies you that a signal has been trapped. If you request a signal be passed on to your program using the ignore subcommand, the dbx program ignores the signal and passes it on to the thread. Use the catch and ignore subcommands to change the default handling.

In the following example, a program uses SIGGRANT and SIGREQUEST to handle allocation of resources. In order for the dbx program to continue each time one of these signals is received, enter:

(dbx) ignore GRANT
(dbx) ignore SIGREQUEST
(dbx) ignore
CONT CLD ALARM KILL GRANT REQUEST

The dbx debug program can block signals to your program if you set the $sigblock variable. By default, signals received through the dbx program are sent to the source program or the object file specified by the dbx ObjectFile parameter. If the $sigblock variable is set using the set subcommand, signals received by the dbx program are not passed to the source program. If you want a signal to be sent to the program, use the cont subcommand and supply the signal as an operand.

You can use this feature to interrupt execution of a program running under the dbx debug program. Program status can be examined before continuing execution as usual. If the $sigblock variable is not set, interrupting execution causes a SIGINT signal to be sent to the program. This causes execution, when continued, to branch to a signal handler if one exists.

The following example program illustrates how execution using the dbx debug program changes when the $sigblock variable is set:

#include <signal.h>
#include <stdio.h>
void inthand( ) {
        printf("\nSIGINT received\n");
        exit(0);
}
main( )
{
        signal(SIGINT, inthand);
        while (1) {
                  printf(".");
                  fflush(stdout);
                sleep(1);
        }
}

The following sample session with the dbx program uses the preceding program as the source file. In the first run of the program, the $sigblock variable is not set. During rerun, the $sigblock variable is set. Comments are placed between angle brackets to the right:

dbx version 3.1.
Type 'help' for help.
reading symbolic information ...
(dbx) run
.........^C                      <User pressed Ctrl-C here!>
interrupt in sleep at 0xd00180bc
0xd00180bc (sleep+0x40) 80410014         1        r2,0x14(r1)
(dbx) cont
SIGINT received
execution completed
(dbx) set $sigblock
(dbx) rerun
[ looper ]
..............^C                  <User pressed Ctrl-C here!>
interrupt in sleep at 0xd00180bc
0xd00180bc (sleep+0x40) 80410014          1        r2,0x14(r1)
(dbx) cont
....^C   <Program did not receive signal, execution continued>
interrupt in sleep at 0xd00180bc
0xd00180bc (sleep+0x40) 80410014          1         r2,0x14(r1)
(dbx) cont 2                     <End program with a signal 2>
SIGINT received
execution completed
(dbx)

Calling procedures

You can call your program procedures from the dbx program to test different arguments. You can also call diagnostic routines that format data to aid in debugging. Use the call subcommand or the print subcommand to call a procedure.

Displaying a stack trace

To list the procedure calls preceding a program halt, use the where command.

In the following example, the executable object file, hello, consists of two source files and three procedures, including the standard procedure main. The program stopped at a breakpoint in procedure sub2.

(dbx) run
[1] stopped in sub2 at line 4 in file "hellosub.c"
(dbx) where
sub2(s = "hello", n = 52), line 4 in "hellosub.c"
sub(s = "hello", a = -1, k = delete), line 31 in "hello.c"
main(), line 19 in "hello.c"

The stack trace shows the calls in reverse order. Starting at the bottom, the following events occurred:

  1. Shell called main.
  2. main called sub procedure at line 19 with values s = "hello", a = -1, and k = delete.
  3. sub called sub2 procedure at line 31 with values s = "hello" and n = 52.
  4. The program stopped in sub2 procedure at line 4.
A portion of the stack trace from frame number 0 to frame number 1 can be displayed using where 0 1.
(dbx)run
[1] stopped in sub2 at line 4 in file "hellosub.c"
(dbx) where 0 1
sub2(s = "hello", n = 52), line 4 in "hellosub.c"
sub(s = "hello", a = -1, k = delete), line 31 in "hello.c"
Note: Set the debug program variable $noargs to turn off the display of arguments passed to procedures. Set the debug program variable $stack_details to display the frame number and the register set for each active function or procedure.

You can also display portions of the stack with the up, down, and frame subcommands.

Displaying and modifying variables

To display an expression, use the print subcommand. To print the names and values of variables, use the dump subcommand. If the given procedure is a period, then all active variables are printed. If the PATTERN parameter is specified, then instead of displaying only the specified symbol, all the symbols that match the PATTERN are printed. To modify the value of a variable, use the assign subcommand.

In the following example, a C program has an automatic integer variable x with value 7, and s and n parameters in the sub2 procedure:

(dbx) print x, n
7 52
(dbx) assign x = 3*x
(dbx) print x
21
(dbx) dump
sub2(s = "hello", n = 52)
x = 21

Displaying thread-related information

To display information on user threads, mutexes, conditions, and attribute objects, use the thread, mutex, condition, and attribute subcommands. You can also use the print subcommand on these objects. In the following example, the running thread is thread 1. The user sets the current thread to be thread 2, lists the threads, prints information on thread 1, and finally prints information on several thread-related objects.

(dbx) thread current 2
(dbx) thread
 thread  state-k   wchan state-u   k-tid mode held scope function
*$t1     run             running   12755   u   no   pro  main
>$t2     run             running   12501   k   no   sys  thread_1
(dbx) print $t1
(thread_id = 0x1, state = run, state_u = 0x0, tid = 0x31d3, mode = 0x1, held = 0x0, priority = 0x3c,
    policy = other, scount = 0x1, cursig = 0x5, attributes = 0x200050f8)
(dbx) print $a1,$c1,$m2
(attr_id = 0x1, type = 0x1, state = 0x1, stacksize = 0x0, detachedstate = 0x0, process_shared = 0x0,
 contentionscope = 0x0, priority = 0x0, sched = 0x0, inherit = 0x0, protocol = 0x0, prio_ceiling = 0x0)
(cv_id = 0x1, lock = 0x0, semaphore_queue = 0x200032a0, attributes = 0x20003628)
(mutex_id = 0x2, islock = 0x0, owner = (nil), flags = 0x1, attributes = 0x200035c8)

Scoping of names

Names resolve first using the static scope of the current function. The dynamic scope is used if the name is not defined in the first scope. If static and dynamic searches do not yield a result, an arbitrary symbol is chosen and the message using QualifiedName is printed. You can override the name resolution procedure by qualifying an identifier with a block name (such as Module.Variable). Source files are treated as modules named by the file name without the suffix. For example, the x variable, which is declared in the sub procedure inside the hello.c file, has the fully qualified name hello.sub.x. The program itself has a period for a name.

The which and whereis subcommands can be helpful in determining which symbol is found when multiple symbols with the same name exist.

Using operators and modifiers in expressions

The dbx program can display a wide range of expressions. Specify expressions with a common subset of C syntax, with some FORTRAN extensions.

* (asterisk) or ^ (caret)
Denotes indirection or pointer dereferencing.
[ ] (brackets) or ( ) (parentheses)
Denotes subscript array expressions.
. (period)
Use this field reference operator with pointers and structures. This makes the C operator -> (arrow) unnecessary, although it is allowed.
& (ampersand)
Gets the address of a variable.
.. (two periods)
Separates the upper and lower bounds when specifying a subsection of an array. For example: n[1..4].

The following types of operations are valid in expressions:

Algebraic
=, -, *,/(floating division), div (integral division), mod, exp (exponentiation)
Bitwise
-, I, bitand, xor, ~, <<, >>
Logical
or, and, not, II, &&
Comparison
<, >, <=, >=, <> or !=, = or ==
Other
sizeof

Logical and comparison expressions are allowed as conditions in stop and trace subcommands.

Checking of expression types

The dbx debug program checks expression types. You can override the expression type by using a renaming or casting operator. There are three forms of type renaming:

  • Typename (Expression
  • Expression \ Typename 
  • (Typename) Expression

Note: When you cast to or from a structure, union, or class, the casting is left-justified. However, when casting from a class to a base class, C++ syntax rules are followed.

For example, to rename the x variable where x is an integer with a value of 97, enter:

(dbx) print char (x), x \ char, (char) x, x,
'a' 'a' 'a' 97

The following examples show how you can use the (Typename) Expression form of type renaming:

print (float) i
print ((struct qq *) void_pointer)->first_element

The following restrictions apply to C-style typecasting for the dbx debug program:

  • The Fortran types (integer*1, integer*2, integer*4, logical*1, logical*2, logical*4, and so on) are not supported as cast operators.
  • If an active variable has the same name as one of the base types or user-defined types, the type cannot be used as a cast operator for C-style typecasting.

The whatis subcommand prints the declaration of an identifier, which you can then qualify with block names.

Use the $$TagName construct to print the declaration of an enumeration, structure, or union tag.

The type of the assign subcommand expression must match the variable type you assigned. If the types do not match, an error message is displayed. Change the expression type using a type renaming. Disable type checking by setting a special dbx debug program $unsafeassign variable.

Folding variables to lowercase and uppercase

By default, the dbx program folds symbols based on the current language. If the current language is C, C++, or undefined, the symbols are not folded. If the current language is Fortran, the symbols are folded to lowercase. The current language is undefined if the program is in a section of code that has not been compiled with the debug flag. You can override default handling with the case subcommand.

Using the case subcommand without arguments displays the current case mode.

The Fortran compiler converts all program symbols to lowercase; the C compiler does not. However, some Fortran compilers might not always generate lowercase symbols. For example, given a procedure named proc1 inside a module named mod2, the XLF Fortran compiler generates the __mod2_MOD_proc1 symbol, which is mixed case. In such situations, you must change the case in the dbx program to mixed case.

Changing print output with special debug program variables

Use the set subcommand to set the following special dbx debug program variables to get different results from the print subcommand:

$hexints
Prints integer expressions in hexadecimal.
$hexchars
Prints character expressions in hexadecimal.
$hexstrings
Prints the address of the character string, not the string itself.
$octints
Prints integer expressions in octal.
$expandunions
Prints fields within a union.
$pretty
Displays complex C and C++ types in pretty format.
$print_dynamic
Prints the dynamic type of the C++ objects.
$show_vft
Prints Virtual Function Table while printing C++ objects.

Set and unset the debug program variables to get the desired results. For example:

(dbx) whatis x; whatis i; whatis s
int x;
char i;
char *s;
(dbx) print x, i, s
375 'c' "hello"
(dbx) set $hexstrings; set $hexints; set $hexchars
(dbx) print x, i, s
0x177 0x63 0x3fffe460
(dbx) unset $hexchars; set $octints
(dbx) print x, i
0567 'c'
(dbx) whatis p
struct info p;
(dbx) whatis struct info
struct info {
    int x;
    double position[3];
    unsigned char c;
    struct vector force;
};
(dbx) whatis struct vector
struct vector {
    int a;
    int b;
    int c;
};
(dbx) print p
(x = 4, position = (1.3262493258532527e-315, 0.0, 0.0), 
c = '\0', force = (a = 0, b = 9, c = 1))(dbx) set $pretty="on"
(dbx) print p
{
    x = 4
    position[0] = 1.3262493258532527e-315
    position[1] = 0.0
    position[2] = 0.0
    c = '\0'
    force = {
        a = 0
        b = 9
        c = 1
    }
}
(dbx) set $pretty="verbose"
(dbx) print p
x = 4
position[0] = 1.3262493258532527e-315
position[1] = 0.0
position[2] = 0.0
c = '\0'
force.a = 0
force.b = 9
force.c = 1

When show_vft is not set and an object is printed using print sub command, the Virtual Function Table (VFT) is not printed. If it is set VFT is displayed. For example:

(dbx) p *d
    B1:(int_in_b1 = 91)
    B2:(int_in_b2 = 92)
(int_in_d = 93)
(dbx) p *b2
(int_in_b2 = 20)
(dbx)set $show_vft
(dbx) p *d
    B1:(B1::f1(), int_in_b1 = 91)
    B2:(D::f2(), int_in_b2 = 92)
(int_in_d = 93)
(dbx) p *b2
(B2::f2(), int_in_b2 = 20)
(dbx)  

When print_dynamic is not set the object is displayed as per the static type’s (what is defined in the source code) template. Otherwise it will be displayed as per the dynamic type’s (what an object was before any casts were made to it) template. For example:

(dbx) r
[1] stopped in main at line 57
   57   A *obj1 = new A();
(dbx) n
stopped in main at line 58
   58   A *obj2 = new B();
(dbx) n
stopped in main at line 59
   59   cout<<" a = "<<obj2->a<<" b = "<<obj2->b<<endl; 
(dbx) p *obj2
(a = 1, b = 2)
(dbx)set $print_dynamic
(dbx) print *obj2
    A:(a = 1, b = 2)
(c = 3, d = 4)
(dbx)