 |
HP OpenVMS Utility Routines Manual
Chapter 21 Traceback Facility (TBK) Routines
The Traceback facility for HP OpenVMS I64 and Alpha systems is a
debugging tool that provides information (symbolizations) about call
stack PCs. In normal operation, when a process suffers a fatal
unhandled exception, the operating system launches Traceback which
sends to SYS$OUTPUT the complete call stack at the time of the
exception. Applications can also directly use the Traceback facility to
sequentially generate information for an individual call stack PC. In
this case, the Traceback simply returns information to the caller, not
to SYS$OUTPUT. This chapter describes this direct Traceback interface.
21.1 Introduction to TBK Routines
On I64 systems, the Traceback facility can be invoked at any time by
using the TBK$I64_SYMBOLIZE routine. This routine uses a single data
structure for its inputs and outputs. It can be called from User,
Supervisor, or Executive mode.
Similarly, on Alpha systems, the Traceback facility can be invoked at
any time using the TBK$ALPHA_SYMBOLIZE routine. This routine uses a
single data structure for its inputs and outputs and it can be called
from USER, SUPERVISOR, or EXCECUTIVE mode.
Section 21.2 provides sample programs showing how to use the TBK
routines. Section 21.3 is a reference section that provides details
about the TBK routines.
21.2 Using TBK Routines---Example
This section provides an example program containing three small
subroutines to illustrate using the TBK$I64_SYMBOLIZE routine. The
example program runs a test to exercise the I64
librtl
call stack walking routines, the TRACE API,
sys$unwind
, and
sys$unwind_goto_64
. It is presented in three parts with callout information that
describes the processing:
- Part 1 of the example defines the necessary call stack walking
headers, TRACE API headers, local subroutines, and a subroutine
exception handler (see Section 21.2.1).
- Part 2 issues
librtl
call stack walking calls for each of three subroutines, defines a
pointer to a call stack walk invocation context block, defines storage
for the return TRACE symbolizations and information, and defines
storage and initializes the TRACE API parameter block (see
Section 21.2.2).
- Part 3 allocates and initializes the invocation context block and
obtains the the context handler's current context. Subroutine
subc
signals into a frame-based handler,
subc_handler
which walks the stack, calls TBK$I64_SYMBOLIZE to symbolize each
frame's PC, and then prints out the symbolizations (see Section 21.2.3).
21.2.1 TBK$I64_SYMBOLIZE Example---Part 1
The first part of the example defines the necessary call stack walking
headers, TRACE API headers, local subroutines, and a subroutine
exception handler.
| Example 21-1 TBK$I64_SYMBOLIZE Example---Part
1 |
$ run/nodebug unwind4
In subc_handler, ch_cnt = 1
Call stack:
image module routine line PC
UNWIND4 UNWIND4 subc_handler 27271 0000000000030650
DECC$SHR C$SHELL_HANDLER decc$$shell_handler 5566 FFFFF80208613E50
DECC$SHR C$SHELL_HANDLER decc$$shell_handler 0 FFFFFFFF803EC680
DECC$SHR C$SHELL_HANDLER decc$$shell_handler 0 FFFFFFFF803E00B0
UNWIND4 UNWIND4 subc 27409 00000000000310A0
UNWIND4 UNWIND4 subb 27200 0000000000030300
UNWIND4 UNWIND4 suba 27187 0000000000030200
UNWIND4 UNWIND4 main 27175 0000000000030140
UNWIND4 UNWIND4 __main 27171 00000000000300E0
UNWIND4 UNWIND4 __main 0 FFFFFFFF80B72C80
Continue (versus exit)? [Y/N]:
/*
* NOTE: to compile include "/define=(__NEW_STARLET)".
*/
#include <stdio.h> (1)
#include <stdarg.h>
#include <starlet.h>
#include <stddef.h>
#include <ssdef.h>
#include <descrip.h>
/* librtl headers for call stack walking
*/
#include <lib$routines.h> (2)
#include <libicb.h>
/* trace headers for trace api
*/
#include <tbkdef.h> (3)
#include <tbk$routines.h>
/* some local subroutines
*/
void suba (void); (4)
void subb (void);
void subc (void);
/* a subroutine exception handler
*/
int subc_handler (unsigned long int *sigarg, unsigned long int *mecharg); (5)
unsigned long int a_cnt, b_cnt, c_cnt, ch_cnt;
unsigned __int64 a_invo_handle, b_invo_handle, c_invo_handle;
int status;
int main ()
{
suba ();
return 1;
}
void suba ()
{
|
- This program runs a test to exercise the I64
librtl
call stack walking routines, the TRACE API,
sys$unwind
, and
sys$unwind_goto_64
.
- The necessary
librtl
call stack walking headers. LIBICB defines the invocation context
block. LIB$ROUTINES defines the call stack walk function prototypes.
- The necessary TRACE API header files. TBKDEF
defines the TRACE_API call parameter. TBK$ROUTINES defines the TRACE
API function prototype.
- This code defines the local subroutines
suba
,
subb
, and
subc
.
- This code defines a subroutine exception
handler.
21.2.2 TBK$I64_SYMBOLIZE Example---Part 2
The second part of the example issues
librtl
call stack walking calls for each of three subroutines, defines a
pointer to a call stack walk invocation context block, defines storage
for the return TRACE symbolizations and information, and defines
storage and initializes the TRACE API parameter block.
| Example 21-2 TBK$I64_SYMBOLIZE Example---Part
2 |
/* Get routine a's invocation context handle, used in subc_handler
*/
status = lib$i64_get_curr_invo_handle (&a_invo_handle); (1)
a_cnt++;
subb ();
a_cnt++;
subb ();
}
void subb ()
{
/* Get routine b's invocation context handle, used in subc_handler
*/
status = lib$i64_get_curr_invo_handle (&b_invo_handle); (2)
b_cnt++;
subc ();
b_cnt++;
subc ();
b_cnt++;
subc ();
}
void subc ()
{
lib$establish (subc_handler);
/* Get routine c's invocation context handle, used in subc_handler
*/
status = lib$i64_get_curr_invo_handle (&c_invo_handle); (3)
/* Signal into subc_handler
*/
c_cnt++;
lib$signal (c_cnt);
c_cnt++;
lib$signal (c_cnt);
}
int subc_handler (unsigned long int *sigarg, unsigned long int *mecharg)
{
int status, tbk_status=0, callstack_depth = 0;
unsigned int depth;
/* local pointer for the call stack walk invocation context block
*/
INVO_CONTEXT_BLK *myICB; (4)
/* local storage for image, module, routine names, line number, and image
* and module base addresses returned by the trace api
*/
static char image [128], module [128], routine [128], inquire_continue [128];
static struct dsc$descriptor_vs image_dsc = {125, DSC$K_DTYPE_VT, DSC$K_CLASS_VS, &image[0]};
static struct dsc$descriptor_vs module_dsc = {125, DSC$K_DTYPE_VT, DSC$K_CLASS_VS, &module[0]};
static struct dsc$descriptor_vs routine_dsc = {125, DSC$K_DTYPE_VT, DSC$K_CLASS_VS, &routine[0]};
unsigned int list_line;
unsigned __int64 image_base_addr; (5)
unsigned __int64 module_base_addr;
/* Local storage and setup for the trace api parameter block
*/
unsigned __int64 symbolize_flags={0}; (6)
TBK_API_PARAM params = {
TBK$K_LENGTH, /* trace api parameter block length */
0, /* trace api parameter block type, MBZ */
TBK$K_VERSION, /* trace api parameter block length, MBZ */
0, /* reserved, MBZ */
0, /* pc, input */
0, /* fp, input, not used for I64 */
0, /* filename desc, output, not used here */
0, /* library module desc, output, not used here */
0, /* record number, output, not used here */
(struct _descriptor *)&image_dsc, /* image descriptor, output */
(struct _descriptor *)&module_dsc, /* module descriptor, output */
(struct _descriptor *)&routine_dsc, /* routine_descriptor, output */
&list_line, /* compiler listing line number, output */
0, /* relative pc, output, not used here */
&image_base_addr, /* image base address, output */
&module_base_addr, /* module base address, output */
0, /* malloc routine, input */
0, /* free routine, input */
&symbolize_flags, /* symbolize flags, input */
0, /* reserved */
0, /* reserved */
0}; /* reserved */
if (*(sigarg+1) == SS$_UNWIND)
return SS$_CONTINUE;
else
ch_cnt++;
printf ("\nIn subc_handler, ch_cnt = %d\n", ch_cnt);
printf ("Call stack: \n");
status = 1;
|
- A
librtl
call stack walk call to get the
suba
subroutine's invocation context handle used in
subc_handler
.
- A
librtl
call stack walk call to get the
subb
subroutine's invocation context handle used in
subc_handler
.
- A
librtl
call stack walk call to get the
subc
subroutine's invocation context handle used in
subc_handler
.
- A pointer is defined to a call stack walk
invocation context block.
- Storage is defined for the return TRACE
symbolizaions and information, which includes local storage for image,
module, routine names, line number, and image and module base addresses
returned by the TRACE API.
- Local storage is defined for the TRACE API
parameter block, which is initialized.
21.2.3 TBK$I64_SYMBOLIZE Example---Part 3
The third part of the example allocates and initializes the invocation
context block and obtains the the context handler's current context.
Subroutine
subc
signals into a frame-based handler (
subc_handler
), which walks the stack, calls TBK$I64_SYMBOLIZE to symbolize each
frame's PC, and prints out the symbolizations.
| Example 21-3 TBK$I64_SYMBOLIZE Example---Part
3 |
/* Walk the call stack top to bottom, symbolize each frame's PC, and
* print out the symbolizations.
*
* First, create the invocation context block and get my (subc_handler's)
* current context.
*/
myICB = (INVO_CONTEXT_BLK *) lib$i64_create_invo_context (); (1)
lib$i64_get_curr_invo_context (myICB);
printf ("image module routine line PC\n");
while (!(myICB->libicb$v_bottom_of_stack) && (2)
((status & 1) != 0))
{
/* Use the PC from the call stack invocation context block.
*/
params.tbk$q_faulting_pc = (unsigned __int64) myICB->libicb$ih_pc; (3)
/* Call trace to do the symbolizations.
*/
tbk_status = tbk$i64_symbolize (¶ms); (4)
/* And print out results
*/
image [*((short *) image) + 2] = 0;
module [*((short *) module) + 2] = 0;
routine [*((short *) routine) + 2] = 0;
/* Print out the tbk$i64_symbolize info (with formating
* to align columns).
*/
if (*((short *) module) > 8)
{
if (*((short *) routine) > 8)
{
printf ("%s %s %s %ld %16.16LX\n",
&image [2],
&module [2],
&routine [2],
list_line,
(unsigned __int64) myICB->libicb$ih_pc);
}
else
{
printf ("%s %s %s %ld %16.16LX\n",
&image [2],
&module [2],
&routine [2],
list_line,
(unsigned __int64) myICB->libicb$ih_pc);
}
}
else
{
if (*((short *) routine) > 8)
{
printf ("%s %s %s %ld %16.16LX\n",
&image [2],
&module [2],
&routine [2],
list_line,
(unsigned __int64) myICB->libicb$ih_pc);
}
else
{
printf ("%s %s %s %ld %16.16LX\n",
&image [2],
&module [2],
&routine [2],
list_line,
(unsigned __int64) myICB->libicb$ih_pc);
}
}
/* Get the previous call frame.
*/
status = lib$i64_get_prev_invo_context (myICB); (5)
callstack_depth++;
}
/* Terminate the call stack walk and free up the memory that it used.
*/
lib$i64_prev_invo_end (myICB); (6)
lib$i64_free_invo_context (myICB);
/* Set up to unwind if we continue execution.
*/
switch (ch_cnt)
{
/* first, some sys$unwinds (7)
*/
case 1 :
status = sys$unwind (0, 0);
break;
case 2 :
depth = 0;
status = sys$unwind (&depth, 0);
break;
case 3 :
depth = 1;
status = sys$unwind (&depth, 0);
break;
case 4 :
depth = 2;
status = sys$unwind (&depth, 0);
break;
/* now, some sys$goto_unwinds
*/
case 5 :
status = sys$goto_unwind_64 (&c_invo_handle, 0, 0, 0);
break;
case 6 :
status = sys$goto_unwind_64 (&b_invo_handle, 0, 0, 0);
break;
case 7 :
status = sys$goto_unwind_64 (&a_invo_handle, 0, 0, 0);
break;
default :
break;
}
/* Continue (after unwinding) or exit? Let the user decide.
*/
printf ("\nContinue (versus exit)? [Y/N]: ");
gets (inquire_continue);
if ((inquire_continue [0] == 'Y') || (inquire_continue [0] == 'y'))
return SS$_CONTINUE;
else
sys$exit (1);
}
|
- To prepare for walking the call stack, the
invocation context block is allocated and initialized, and the context
handler's (
subc_handler
) current context is obtained.
- The call stack is walked from the current
context,
subc_handler
, to the bottom of the stack.
- The essential call stack PC value is
provided. On I64 systems, all the symbolization is based on a call
stack frame's PC value.
- A call is made to the TRACE symbolize
routine, TBK$I64_SYMBOLIZE, for the call frame's PC. This is the call
to the TRACE API. The information is then printed out.
- The previous call frame context is obtained.
- Cleanup is performed and and memory used by
the call stack walk is deallocated.
- Unwind is set up to continue program
execution.
21.3 TBK Routines
This section describes the TBK routines. The TBK$I64_SYMBOLIZE routine
is for use on I64 systems and the TBK$ALPHA_SYMBOLIZE routine is for
use on Alpha systems.
TBK$I64_SYMBOLIZE
The TBK$I64_SYMBOLIZE routine attempts to symbolize a PC, returning as
much symbolic representation for that location as was requested.
For information about the TBK symbolize routine for Alpha systems, see
the information for TBK$ALPHA_SYMBOLIZE later in TBK$ALPHA_SYMBOLIZE.
Format
TBK$I64_SYMBOLIZE parameter_block
RETURNS
| OpenVMS usage: |
cond_value |
| type: |
longword (unsigned) |
| access: |
write only |
| mechanism: |
by value |
Longword condition value. Most utility routines return a condition
value. Condition values that this routine can return are listed under
Condition Values Returned.
Argument
parmeter_block
| OpenVMS usage: |
TBK_API_PARAM |
| type: |
structure |
| access: |
modify |
| mechanism: |
by reference |
Table 21-1 shows the values for TBK_API_PARAM (defined in TBKDEF).
Table 21-1 Values for TBK_API_PARAM
| Field |
Size |
Description |
|
TBK$W_LENGTH
|
Word
|
Input by value, structure length, must be TBK$K_LENGTH
|
|
TBK$B_TYPE
|
Byte
|
Input, MBZ
|
|
TBK$B_VERSION
|
Byte
|
Input by value, must be TBK$K_VERSION
|
|
TBK$L_RESERVEDA
|
Longword
|
Reserved for future use, MBZ
|
|
TBK$Q_FAULTING_PC
|
Quadword
|
Input by value, call stack frame PC
|
|
TBK$PQ_FILENAME_DESC
|
64-bit pointer
|
Optional output by reference (I64 only), pointer (if not requested,
MBZ) to a fixed-length string text descriptor. The descriptor must be
set up with preallocated adequate buffer space. The descriptor is
filled with the image file name. This can be a dynamic descriptor
(rather than fixed-length), but only if the caller is in user mode.
|
TBK$PQ_
LIBRARY_MODULE_DESC
|
64-bit pointer
|
Optional output, pointer (if not requested, MBZ) to a fixed-length
string text descriptor. The descriptor must be set up with
pre-allocated adequate buffer space. The descriptor is filled in with
library module name
if the image filename (see previous field) is a text library
file. This can be a dynamic descriptor (rather than fixed length) but
only if the caller is in user mode.
|
TBK$PQ_
RECORD_NUMBER
|
64-bit pointer
|
Optional output, pointer (if not requested, MBZ) to a longword to be
filled with the relevant image file record number.
|
|
TBK$PQ_IMAGE_DESC
|
64-bit pointer
|
Optional output, pointer (if not requested, MBZ) to a fixed-length
string text descriptor. The descriptor must be set up with preallocated
adequate buffer space. The descriptor is filled in with the image name.
This can be a dynamic descriptor (rather than fixed length), but only
if the caller is in user mode.
|
|
TBK$PQ_MODULE_DESC
|
64-bit pointer
|
Optional output, pointer (if not requested, MBZ) to a fixed-length
string text descriptor. The descriptor must be set up with preallocated
adequate buffer space. The descriptor is filled in with the module name.
|
|
TBK$PQ_ROUTINE_DESC
|
64-bit pointer
|
Optional output, pointer (if not requested, MBZ) to a fixed-length
string text descriptor. The descriptor must be set up with preallocated
adequate buffer space. The descriptor is filled in with the routine
name.
|
TBK$PQ_
LISTING_LINENO
|
64-bit pointer
|
Optional output, pointer (if not requested, MBZ) to longword to be
filled in with the line number (as show in the modules LIS file).
|
|
TBK$PQ_REL_PC
|
64-bit pointer
|
Optional output, pointer (if not requested, MBZ) to quadword to be
filled in with the relative PC. This can be an image or module relative
PC.
|
|
TBK$PQ_ MALLOC_RTN
|
64-bit pointer
|
Optional input, pointer (if not supplied, MBZ) address to a
user-supplied
malloc
routine. Must be supplied when called from supervisor or executive mode
(kernel mode is not supported).
|
|
TBK$PQ_ FREE_RTN
|
64-bit pointer
|
Optional input, pointer (if not supplied, MBZ) address to a
user-supplied
free
routine. Must be supplied when called from supervisor or executive mode
(kernel mode not supported).
|
TBK$PQ_
SYMBOLIZE_FLAGS
|
64-bit pointer
|
Optional input and output, pointer (if not supplied, MBZ) to
TBK_SYMBOLIZE_FLAGS (quadword, see below). Used to control
symbolization options and to return additional status.
|
|
TBK$Q_RESERVED0
|
Quadword
|
Reserved for future use, MBZ.
|
|
TBK$Q_RESERVED1
|
Quadword
|
Reserved for future use, MBZ.
|
|
TBK$Q_RESERVED2
|
Quadword
|
Reserved for future use, MBZ.
|
TBK$V_
EXCEPTION_IS_FAULT
|
0
|
Adjusts the PC value used for symbolization for target frames that
suffered a fault exception.
|
|
|
All remaining bits
|
Reserved, Must be initialized to zero.
|
Description
The TBK$I64_SYMBOLIZE routine attempts to symbolize a PC, that is,
given a PC, this routine returns as much of the symbolic representation
for that location that has been requested: image name, file name,
module name, routine name, listing line number, file record number, and
so on.
The degree of symbolization depends upon the images symbolic
information. For best results, compile the images source modules with
either traceback (the default) or debug information (/DEBUG) and link
the image with either traceback (/TRACE) or debug (/DEBUG) information.
If no symbolic information records exists within the image for the PC,
then only partial symbolization is possible.
TBK$I64_SYMBOLIZE can be called by programs in user, supervisor, or
executive mode. Calls from kernel mode are not allowed; calls when IPL
is nonzero are not allowed.
Callers in supervisor or executive mode must supply routines that
perform the equivilent of malloc and free operations that are legal for
the given mode. (The C Run Time Library
malloc
and
free
routines are only supported in user mode.) Pointers to these
user-written replacement routines are specified in the
TBK$PQ_MALLOC_RTN and TBK$PQ_FREE_RTN fields.
Condition Values Returned
|
SS$_KERNELINV
|
This API does not support kernel mode calls.
|
|
SS$_BADPARAM
|
Incorrect TBK_API_PARAM length, type, or version.
|
|
SS$_INSFMEM
|
Unable to allocate needed memory.
|
|
SS$_NORMAL
|
Successful completion.
|
|
SS$_ACCVIO
|
Unable to read from the TBK_API_PARAM block.
|
Other conditions indicate TRACE failures such as failure status from
sys$crmpsc_file_64
on an I64 system.
 |
|
|
|