Previous | Contents | Index |
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:
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 () { |
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; |
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); } |
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.
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.
TBK$I64_SYMBOLIZE parameter_block
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.
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_DESC64-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_NUMBER64-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_LINENO64-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_FLAGS64-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_FAULT0 Adjusts the PC value used for symbolization for target frames that suffered a fault exception. All remaining bits Reserved, Must be initialized to zero.
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.
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.
Previous | Next | Contents | Index |