#pragma module MBX$SDA "X-17" // ************************************************************************* // * * // * © Copyright 2006 Hewlett-Packard Development Company, L.P. * // * * // * Confidential computer software. Valid license from HP and/or * // * its subsidiaries required for possession, use, or copying. * // * * // * Consistent with FAR 12.211 and 12.212, Commercial Computer Software, * // * Computer Software Documentation, and Technical Data for Commercial * // * Items are licensed to the U.S. Government under vendor's standard * // * commercial license. * // * * // * Neither HP nor any of its subsidiaries shall be liable for technical * // * or editorial errors or omissions contained herein. The information * // * in this document is provided "as is" without warranty of any kind and * // * is subject to change without notice. The warranties for HP products * // * are set forth in the express limited warranty statements accompanying * // * such products. Nothing herein should be construed as constituting an * // * additional warranty. * // * * // ************************************************************************* // // FACILITY: // // SDA Extensions // // // ABSTRACT: // // This example program demonstrates the use of SDA extension routines. // This program is compiled and linked as a shareable image (either placed // in SYS$SHARE or pointed to by a logical name) and will be automatically // image activated from within SDA. // // If you type a command FOO at the SDA command prompt "SDA>" which is // unknown to SDA, SDA will try to look for shareable image named FOO$SDA, // and image activate it if found. The main routine entry point must be // called SDA$EXTEND. // // In our case we call our example image MBX$SDA, hence we use the command // MBX at the SDA prompt. You can pass any additional parameters and // qualifiers, and your program will parse and act upon. // // In our example, if you simply say MBX, the example program walks through // all mailbox devices on your system and will display certain information // for them. // You can also pass any virtual address as a parameter, and it will try to // display some information like the symbolization, if it falls within a // known image etc. // // You can run this example program against a dumpfile, or on your running // system, either use ANALYZE/CRASH or ANALYZE/SYSTEM to invoke SDA. // // Note: We ignore condition values returned from calls to SDA$PRINT (except // the first one) and SDA$TYPE. If the first call to SDA$PRINT works, and // the others don't, there's not a lot we can do (we can't rely on SDA$PRINT // to print the condition value!). We also ignore condition values returned // from calls to SDA$REQMEM. Either it works, or the error is signalled and // the command aborted. // // BUILD INSTRUCTIONS: // // $ cc mbx$sda+sys$library:sys$lib_c/lib // $ link/share - // mbx$sda.obj, - // sys$library:vms$volatile_private_interfaces /library, - // sys$input/option // symbol_vector=(sda$extend=procedure) // symbol_vector=(sda$extend_version=data) // $ // $ define mbx$sda sys$disk:[]mbx$sda // $ analyze/system // SDA> mbx // SDA> mbx
// // // AUTHOR: // // Christian Moser, Digital Equipment Corporation // // // REVISION HISTORY: // // X-17 RAB Richard A. Bishop 13-Jan-2006 // Display the environment we're running in // // X-16 CMOS Christian Moser 17-MAY-2005 // UCB$W_UNIT has been promoted to a longword UCB$L_UNIT // field. // // X-15 RAB Richard A. Bishop 09-Feb-2005 // Fix bug displaying image offsets (SDA$GET_IMAGE_OFFSET // example) // // X-14 RAB Richard A. Bishop 11-Jan-2005 // Ensure new page after formatting PCB & PHD. Prevent // use of MBX commands in process dumps // // X-13 RAB Richard A. Bishop 04-Feb-2003 // Allow for IA64 instruction bundles. // // X-12 RAB Richard A. Bishop 02-Oct-2002 // New LDRIMG layout. // // X-11 GHJ Gregory H. Jordan 2-Jan-2002 // The mailbox driver now uses two longword fields in // the mailbox ucb extension. Use these fields to // display the mailbox initial and current buffer // quotas. Also, increase the size that can be // displayed for these fields. // // X-9 RAB Richard A. Bishop 15-Dec-1999 // Give an example of SDA$FAO by splitting up an // existing SDA$PRINT. // // X-8 RAB Richard A. Bishop 5-Apr-1999 // Use !AF instead of !AC for image names in case the // name is corrupted // // X-7 RAB Richard A. Bishop 12-Dec-1997 // Do #include's properly // // X-6 RAB Richard A. Bishop 7-Apr-1997 // Update link instructions to reference the library // ALPHA$LIBRARY:VMS$VOLATILE_PRIVATE_INTERFACES not // the object file ALPHA$LIBRARY:SDA_EXTEND_VECTOR.OBJ. // // X-5 RAB Richard A. Bishop 3-Apr-1997 // Fix SDA$SYMBOL_VALUE definition/call. Now returns // uint64 instead of void. This to ensure users allow // 64-bits for the value. // // X-4 RAB Richard A. Bishop 24-Mar-1997 // Add condition code checking, several new examples, // changes to routine names and definitions // // X-3 CMOS Christian Moser 14-Mar-1997 // Implement version control and minor tweaks in // routine prototypes // // X-2 CMOS Christian Moser 20-Feb-1997 // More examples added // // X-1 CMOS Christian Moser 16-Jan-1997 // Initial version. // // Imported definitions #define __NEW_STARLET 1 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // Global variables int sda$extend_version = SDA_FLAGS$K_VERSION; void mbx$title ( void ) { sda$print ( "Mailbox UCB RefCount Outstanding Initial Remaining Message Read IO Logical" ); sda$print ( " Unit Address Read/Write Messages Quota Quota Queue Queue Name" ); sda$print ( "-------------------------------------------------------------------------------------------------" ); return; } /////////////////////////////////////////////////////////////////////////////// // // This is the main entry point in SDA extension routine called from // within SDA. // // sda$extend transfer_table, cmd_line, sda_flags // // transfer_table - pointer to the routine transfer table // cmd_line - address of descriptor of the command line passed // sda_flags - flags // void sda$extend (int *transfer_table, struct dsc$descriptor_s *cmd_line, SDA_FLAGS sda_flags) { int status; int i; static DDB *ddb; static MB_UCB *ucb; UCB *ucb_addr; int flag; static int sysdef_flag; VOID_PQ ioc$gl_devlist; static LNMB *lnmb; static int lnmb_size; GENERIC_64 longquad; char hw_name[64]; char buffer[128]; char template[16]; // Only used on IA64 char *dyn_tab; int16 *dyn_ptr; LDRIMG *ldrimg; IMCB *imcb; KFERES_SECTION *kferes_section; // Only used on Alpha LDRISD *isd; COMP_IMG_OFF sda_cio; int64 offset; int64 img_info; int64 subimg_info; VOID_PQ queue; VOID_PQ address; void *temp; PCB *current_pcb; PHD *current_phd; DMP *dmp_header; uint32 dmp_header_size; char *errlog_buffer; uint32 errlog_buffer_size; uint32 line_count; uint64 instruction [2]; // IA64 needs entire bundle uint64 *istream = &instruction [0]; CPU *cpu_db; uint32 cpu_id; char faobuf [81]; char *faoptr; // // Initialize the table and establish the condition handler // sda$vector_table = transfer_table; lib$establish ( sda$cond_handler ); // // If invoked with no parameter, display the announcement and exit // if ( cmd_line->dsc$w_length == 0 ) { status = sda$print ( "MBX commands: 'MBX SUMMARY' and 'MBX
'" ); sda$skip_lines (1); status = sda$print ( "Environment: analyzing !AZ!AZ!AZ", sda_flags.sda_flags$v_current ? (sda_flags.sda_flags$v_remote ? "a remote system" : (sda_flags.sda_flags$v_target ? "an SCD target system" : "the current system")) : (sda_flags.sda_flags$v_process ? "a process dump" : (sda_flags.sda_flags$v_target ? "an SDD target dump" : "a system dump")), sda_flags.sda_flags$v_current ? "" : (sda_flags.sda_flags$v_ia64 ? " from an OpenVMS I64 system" : " from an OpenVMS Alpha system"), sda_flags.sda_flags$v_current ? "" : (sda_flags.sda_flags$v_override ? " in override mode" : "")); return; } // // If invoked when analyzing a dump in override mode complain and exit // if ( sda_flags.sda_flags$v_override ) { status = sda$print ( "MBX cannot be used in override mode" ); return; } // // If invoked when analyzing a process dump complain and exit // if ( sda_flags.sda_flags$v_process ) { status = sda$print ( "MBX cannot be used with process dumps" ); return; } // // Allocate buffers for local data structures. We use static pointers // since this routine might be called multiple times and we only want // to allocate the local buffers once per SDA session. // There is no reason to deallocate them at the end of this routine, // because the user might interrupt the SDA output with another // command, hence never finish executing this routine to the end. // Since we don't know how big the LNMB needs to be, we allocate enough // for the header for now, and then allocate more if/when we need to. // if ( ddb == NULL ) sda$allocate (DDB$K_LENGTH, (void *)&ddb ); if ( ucb == NULL ) sda$allocate (UCB$K_MB_UCBLENGTH, (void *)&ucb ); if ( lnmb == NULL ) { sda$allocate (sizeof (LNMB), (void *)&lnmb ); lnmb_size = sizeof (LNMB); } // // Read in the SYSDEF symbol file and suppress the informational // message telling how many symbols were found. // if ( sysdef_flag == FALSE ) { status = sda$read_symfile ( "SDA$READ_DIR:SYSDEF", SDA_OPT$M_READ_NOLOG ); if ( !$VMS_STATUS_SUCCESS (status) ) { sda$print ( "SDA$READ_SYMFILE failed, status = !XL", status); return; } sysdef_flag = TRUE; } // // Check if the input passed along is "summary" // if ( (cmd_line->dsc$w_length <= 8) && (strncmp (cmd_line->dsc$a_pointer, " SUMMARY", cmd_line->dsc$w_length) == 0) ) { // // Set title for each page (exactly one line, automatically // underscored). For the table we use a separate routine to display // the column headers. This routine will be called at each page // break, and we will also start our output on a new page. // sda$format_heading ( "Mailbox Device Information" ); sda$set_heading_routine ( mbx$title ); sda$new_page (); // // In order to find all the mailbox unit control blocks (UCB), we // first need to find the device data block (DDB) of the mailbox // adapter. There is a global symbol pointing to the start of all // device adapters. // After retrieving the value of this symbol, the content of it // points to the start of the loop. // status = sda$symbol_value ( "IOC$GL_DEVLIST", (uint64 *)&ioc$gl_devlist ); if ( !$VMS_STATUS_SUCCESS (status) ) { sda$print ( "SDA$SYMBOL_VALUE (ioc$gl_devlist) failed, status = !XL", status); return; } status = sda$getmem (ioc$gl_devlist, &ddb->ddb$ps_link, 4); if ( !$VMS_STATUS_SUCCESS (status) ) { sda$print ( "SDA$GETMEM (ioc$gl_devlist) failed, status = !XL", status); return; } // // Initialize the flag and the start of the loop through all device // adapters. // flag = FALSE; do { // // Read the DDB into local memory and check for the mailbox // adapter string MBA. // status = sda$trymem (ddb->ddb$ps_link, ddb, DDB$K_LENGTH); if ( !$VMS_STATUS_SUCCESS (status) ) { sda$print ( "SDA$TRYMEM (ddb$ps_link) failed, status = !XL", status); return; } if ( strncmp (ddb->ddb$t_name_str,"MBA",3) == 0 ) { // // Found it, set the flag and quit the loop // flag = TRUE; break; } } // // All DDB's are linked into a zero-terminated single linked list // while ( ddb->ddb$ps_link != NULL ); // // Return if we couldn't locate the mailbox adapter. // if ( flag == FALSE ) { sda$print ( "Could not find Mailbox Adapter" ); return; } // // Initialize the start of the loop through all mailbox UCB's. // ucb->ucb$r_ucb.ucb$l_link = ddb->ddb$ps_ucb; do { // // Save the pointer to the UCB before reading in the unit control // block into local memory. // ucb_addr = ucb->ucb$r_ucb.ucb$l_link; status = sda$trymem (ucb_addr, ucb, UCB$K_MB_UCBLENGTH); if ( !$VMS_STATUS_SUCCESS (status) ) { sda$print ( "SDA$TRYMEM (ucb$l_link) failed, status = !XL", status); return; } // // If the mailbox has a logical name associated with it, read in // the logical name block (LNMB). Since we don't know the exact // size of it upfornt, we read the first octaword which contains // the size, followed by another read of the whole LNMB into local // memory. // if ( ucb->ucb$l_mb_logadr != NULL ) { int new_lnmb_size; status = sda$trymem ( ucb->ucb$l_mb_logadr, lnmb, sizeof (LNMB) ); if ( !$VMS_STATUS_SUCCESS (status) ) { sda$print ( "SDA$TRYMEM (ucb$l_mb_logadr, header) failed, status = !XL", status); return; } new_lnmb_size = lnmb->lnmb$w_size; // // make sure we have a big enough LNMB // if (new_lnmb_size > lnmb_size) { sda$deallocate ( (void *)lnmb, lnmb_size ); sda$allocate ( new_lnmb_size, (void *)&lnmb ); lnmb_size = new_lnmb_size; } status = sda$trymem ( ucb->ucb$l_mb_logadr, lnmb, new_lnmb_size ); if ( !$VMS_STATUS_SUCCESS (status) ) { sda$print ( "SDA$TRYMEM (ucb$l_mb_logadr, body) failed, status = !XL", status); return; } } else lnmb->lnmb$l_namelen = 0; // // Display the results // faoptr = sda$fao ( "!6UL !XL !5UL !5UL", faobuf, sizeof (faobuf), ucb->ucb$r_ucb.ucb$l_unit, ucb_addr, ucb->ucb$l_mb_readerrefc, ucb->ucb$l_mb_writerrefc ); sda$fao ( " !5UL !9UL !9UL !XL", faoptr, sizeof (faobuf) - strlen (faobuf), ucb->ucb$r_ucb.ucb$w_msgcnt, ucb->ucb$l_mb_iniquo, ucb->ucb$l_mb_bufquo, ucb->ucb$r_ucb.ucb$l_mb_msgqfl ); sda$print ( "!AZ !XL !AF", faobuf, ucb->ucb$l_mb_readqfl, lnmb->lnmb$l_namelen, &lnmb->lnmb$t_name ); } // // All UCB's are linked into a zero-terminated single linked list // while ( ucb->ucb$r_ucb.ucb$l_link != NULL ); sda$set_heading_routine ( NULL ); } else { // // The following has really nothing to do with the above mailbox // information display, but uses a variety of SDA extension routines // to demonstrate their use. This is the sole purpose of the potpurri // following below. // // // Check if we are analyzing a running system or a crashdump file. // Also display the hardware name of the system. // sda$get_hw_name ( hw_name, sizeof (hw_name) ); if ( sda_flags.sda_flags$v_current ) sda$format_heading ( "SDA Extension Commands on a !AZ running system", hw_name ); else sda$format_heading ( "SDA Extension Commands on a !AZ from a crashdump file", hw_name ); sda$new_page (); // // The following input should be the address of anything. // We will accept either a longword value (will be sign-extended), a // quadword value or two longwords (separated by a dot '.'). // longquad.gen64$q_quadword = 0; if ( sscanf ( cmd_line->dsc$a_pointer, "%08X.%08X", &longquad.gen64$l_longword[1], &longquad.gen64$l_longword[0] ) != 2 ) { longquad.gen64$q_quadword = 0; if ( sscanf ( cmd_line->dsc$a_pointer, "%016LX", &longquad ) == 1 ) { if ( (longquad.gen64$l_longword[1] == 0) & ((longquad.gen64$l_longword[0] & 0x80000000) > 0) ) longquad.gen64$l_longword[1] = 0xFFFFFFFF; } else lib$signal ( SS$_INVARG ); } // // display the address passed as input // sda$skip_lines (1); sda$print ( "Input address: !@XQ", &longquad ); // // Try to read the first octaword in from this address. // Since we use SDA$GETMEM instead of SDA$TRYMEM, SDA will // signal any errors. // status = sda$getmem ( (VOID_PQ)longquad.gen64$q_quadword, ucb, 16); if ( !$VMS_STATUS_SUCCESS (status) ) { sda$print ( "SDA$GETMEM (!XL.!XL) failed, status = !XL", longquad.gen64$l_longword[1], longquad.gen64$l_longword[0], status); return; } // // See if this address points to a known data structure type. // If there is no named type/subtype for a particular structure, // then an empty string will be returned. This example uses the // UCB offsets for the type and subtype fields: Any structure // type would work just as well. // sda$get_block_name ( ucb->ucb$r_ucb.ucb$b_type, ucb->ucb$r_ucb.ucb$b_flck, buffer, sizeof (buffer) ); if ( strlen (buffer) == 0 ) sda$print ( "Block type: no named type/subtype" ); else sda$print ( "Block type: !AZ", buffer ); // // Now also try to symbolize this address // status = sda$symbolize ( longquad.gen64$q_quadword, buffer, sizeof (buffer) ); if ( status == SS$_NOTRAN ) sda$print ( "Address could not be symbolized" ); else sda$print ( "Address symbolization: !XL.!XL !AZ", longquad.gen64$l_longword[1], longquad.gen64$l_longword[0], buffer ); // // Define a SDA symbol MBX_TEMP containing the address passed // as input and redo the symbolization to show the diff // sda$add_symbol ( "MBX_TEMP", longquad.gen64$q_quadword ); status = sda$symbolize ( longquad.gen64$q_quadword, buffer, sizeof (buffer) ); if ( status == SS$_NOTRAN ) sda$print ( "Address could not be symbolized" ); else sda$print ( "Address symbolization: !XL.!XL !AZ", longquad.gen64$l_longword[1], longquad.gen64$l_longword[0], buffer ); // // Now try and see if it falls within an execlet, process activated // or resident image // sda_cio = sda$get_image_offset ( (VOID_PQ) longquad.gen64$q_quadword, &img_info, &subimg_info, &offset ); if ( sda_cio.sda_cio$v_valid ) { if ( sda_cio.sda_cio$v_process ) { imcb = (IMCB *) img_info; sda$print ( "Process activated image:" ); #if ALPHA if ( sda_cio.sda_cio$v_sliced ) { kferes_section = (KFERES_SECTION *) subimg_info; sda$print ( "Name: !AF Offset: !XL Base: !XL", imcb->imcb$t_image_name [0], &imcb->imcb$t_image_name [1], offset, kferes_section->kferes$l_va ); } else sda$print ( "Name: !AF Offset: !XL Base: !XL", imcb->imcb$t_image_name [0], &imcb->imcb$t_image_name [1], offset, imcb->imcb$l_base_address ); #endif #if IA64 isd = (LDRISD *) subimg_info; sda$print ( "Name: !AF Offset: !XL Base: !XL", imcb->imcb$t_image_name [0], &imcb->imcb$t_image_name [1], offset, isd->ldrisd$p_base ); #endif } else { ldrimg = (LDRIMG *) img_info; isd = (LDRISD *) subimg_info; sda$print ( "System loaded image or resident installed image:" ); #if ALPHA if ( !sda_cio.sda_cio$v_sliced ) sda$print ( "Name: !AF Offset: !XL Base: !XL", ldrimg->ldrimg$l_imgnamlen, ldrimg->ldrimg$ps_imgnam, offset, ldrimg->ldrimg$l_base ); else #endif sda$print ( "Name: !AF Offset: !XL Base: !XL", ldrimg->ldrimg$l_imgnamlen, ldrimg->ldrimg$ps_imgnam, offset, isd->ldrisd$p_base ); } } else sda$print ( "Address does not fall within a known image" ); // // Now throw in a few queue validation commands // sda$new_page (); status = sda$symbol_value ( "IOC$GQ_MOUNTLST", (uint64 *)&address ); if ( !$VMS_STATUS_SUCCESS (status) ) { sda$print ( "SDA$SYMBOL_VALUE (ioc$gq_mountlst) failed, status = !XL", status); return; } sda$reqmem ( address, &temp, 4 ); queue = temp; sda$print ( "*** Validate queue/list ioc$gq_mountlst ***" ); sda$validate_queue ( queue, SDA_OPT$M_QUEUE_LISTQUEUE ); sda$skip_lines (1); status = sda$symbol_value ( "EXE$GQ_PQBIQ", (uint64 *)&queue ); if ( !$VMS_STATUS_SUCCESS (status) ) { sda$print ( "SDA$SYMBOL_VALUE (exe$gq_pqbiq) failed, status = !XL", status); return; } sda$print ( "*** Validate queue/self/list exe$gq_pqbiq ***" ); sda$validate_queue ( queue, SDA_OPT$M_QUEUE_SELF | SDA_OPT$M_QUEUE_LISTQUEUE ); sda$skip_lines (1); status = sda$symbol_value ( "EXE$GL_NONPAGED", (uint64 *)&address ); if ( !$VMS_STATUS_SUCCESS (status) ) { sda$print ( "SDA$SYMBOL_VALUE (exe$gl_nonpaged) failed, status = !XL", status); return; } address = (VOID_PQ)((int64)address + 4); sda$reqmem ( address, &queue, 4 ); sda$print ( "*** Validate queue/single/list exe$gl_nonpaged+4 ***" ); sda$validate_queue ( queue, SDA_OPT$M_QUEUE_SINGLINK ); // // Now some other assorted examples // // First, bugcheck message codes: // sda$skip_lines (1); sda$print ( "*** sda$get_bugcheck_msg ***" ); sda$get_bugcheck_msg ( 0x108, buffer, sizeof (buffer) ); sda$print ( "Bugcheck code 108 (hex) =" ); sda$print ( "!_\"!AZ\"", buffer ); // // Next, sda$ensure & sda$dbg_image_info // sda$skip_lines (1); sda$print ( "*** sda$ensure & sda$dbg_image_info ***" ); sda$ensure (10); sda$dbg_image_info (); // // Demonstrate sda$get_current_pcb and sda$format // sda$new_page (); sda$print ( "*** format pcb & phd ***" ); sda$skip_lines (1); sda$get_current_pcb ( ¤t_pcb ); sda$format ( current_pcb ); sda$reqmem ( (VOID_PQ)¤t_pcb->pcb$l_phd, ¤t_phd, 4 ); sda$skip_lines (1); sda$format ( current_phd, SDA_OPT$M_FORMAT_TYPE, "PHD" ); sda$skip_lines (1); // // Demonstrate sda$get_header // sda$new_page (); sda$print ( "*** sda$get_header ***" ); sda$get_header (&dmp_header, &dmp_header_size, (void **)&errlog_buffer, &errlog_buffer_size); sda$print ("Dump header located at !XL, size !XL bytes", dmp_header, dmp_header_size ); sda$print ("Error log buffer is at !XL, size !XL bytes", errlog_buffer, errlog_buffer_size ); // // Demonstrate sda$get_input // sda$skip_lines (1); sda$print ( "*** sda$get_input ***" ); sda$print ( "Enter any text, it will be echoed until is seen" ); sda$skip_lines (1); while ( $VMS_STATUS_SUCCESS (status) ) { status = sda$get_input ( "MBX> ", buffer, sizeof (buffer) ); if ( (!$VMS_STATUS_SUCCESS (status)) && (status != RMS$_EOF) ) { sda$print ( "SDA$GET_INPUT failed, status = !XL", status); return; } sda$print ( "!AZ", buffer ); } // // Demonstrate sda$get_line_count and sda$set_line_count // sda$skip_lines (1); sda$print ( "*** sda$get_line_count & sda$set_line_count ***" ); sda$get_line_count ( &line_count ); sda$print ( "Line count = !SL. Resetting to zero...", line_count ); sda$set_line_count (0); // // Demonstrate sda$get_address and sda$set_address // sda$skip_lines (1); sda$print ( "*** sda$get_address & sda$set_address ***" ); sda$get_address ( &address ); sda$print ( "SDA current address = !XL.!XL. Resetting to FFFFFFFF.80102030...", (int64)address>>32, (int64)address ); sda$set_address ( (VOID_PQ)0xFFFFFFFF80102030 ); // // Demonstrate sda$parse_command // sda$skip_lines (1); sda$print ( "*** sda$parse_command ***" ); sda$print ( "Executing \"SHOW ADDRESS 80102030\"..." ); sda$parse_command ( "SHOW ADDRESS 80102030" ); // // Demonstrate sda$get_current_cpu, sda$set_cpu and sda$set_process // sda$skip_lines (1); sda$print ( "*** sda$get_current_cpu, sda$set_cpu & sda$set_process ***" ); sda$get_current_cpu ( &cpu_db ); sda$reqmem (&cpu_db->cpu$l_phy_cpuid, &cpu_id, 4); sda$print ( "Current CPU database = !XL. Resetting to CPU ID !XL (no change)...", (int64) cpu_db , cpu_id ); sda$set_cpu ( cpu_id ); sda$print ( "Setting current process to SWAPPER..."); sda$set_process ( "SWAPPER" , 0 , 0 ); sda$parse_command ( "SHOW PROCESS" ); // // Demonstrate sda$get_device_name // sda$skip_lines (1); sda$print ( "*** sda$get_device_name ***" ); sda$parse_command ( "SET OUTPUT NL:" ); sda$parse_command ( "SHOW DEVICE OPA0:" ); sda$parse_command ( "SET OUTPUT TT:" ); sda$symbol_value ( "UCB", (uint64 *)&address ); sda$get_device_name ( (VOID_PQ)address, buffer, 128); sda$print ( "UCB address: !XL = ""!AZ:""", address, buffer); // // Demonstrate sda$type // sda$skip_lines (1); sda$print ( "*** sda$type ***" ); sda$print ( "Redirecting output to MBX$SDA.TMP..." ); sda$parse_command ( "SET OUTPUT /NOINDEX MBX$SDA.TMP" ); sda$type ( "Invoking SHOW SUMMARY to output file..." ); sda$parse_command ( "SHOW SUMMARY" ); sda$type ( "Redirecting output to the terminal..." ); sda$parse_command ( "SET OUTPUT TT:" ); // // Demonstrate sda$instruction_decode // sda$skip_lines (1); sda$print ( "*** sda$instruction_decode ***" ); status = sda$symbol_value ( "EXE_STD$ALLOCATE_C", (uint64 *)&address ); if ( !$VMS_STATUS_SUCCESS (status) ) { sda$print ( "SDA$SYMBOL_VALUE (exe_std$allocate_c) failed, status = !XL", status); return; } if (sda_flags.sda_flags$v_ia64) { // // For IA64, do the entire bundle // sda$reqmem ( address, &instruction, 16); status = sda$instruction_decode ( &istream, buffer, sizeof (buffer), template, sizeof (template) ); if ( !$VMS_STATUS_SUCCESS (status) ) { sda$print ( "SDA$INSTRUCTION_DECODE failed, status = !XL", status); return; } sda$print ( " { !AZ", template ); sda$print ( "EXE_STD$ALLOCATE_C: !AZ", buffer ); while (((int)istream & 7) != 0) // local buffer only guaranteed to be quadword aligned { status = sda$instruction_decode ( &istream, buffer, sizeof (buffer) ); if ( !$VMS_STATUS_SUCCESS (status) ) { sda$print ( "SDA$INSTRUCTION_DECODE failed, status = !XL", status); return; } sda$print ( " !AZ", buffer ); } sda$print ( " }" ); } else { // // For Alpha, do one longword instruction // sda$reqmem ( address, &instruction, 4); status = sda$instruction_decode ( &istream, buffer, sizeof (buffer) ); if ( !$VMS_STATUS_SUCCESS (status) ) { sda$print ( "SDA$INSTRUCTION_DECODE failed, status = !XL", status); return; } sda$print ( "EXE_STD$ALLOCATE_C: !AZ", buffer ); } // // Demonstrate sda$display_help // sda$new_page (); sda$print ( "*** sda$display_help ***" ); sda$print ( "Use to exit help" ); sda$display_help ("SYS$HELP:SDA", "HELP"); sda$skip_lines (1); // // And finally show what the condition handler produces if an error // is signaled // sda$new_page (); sda$print ( "Expect to see %SYSTEM-E-INVARG message, image list, register dump, etc." ); sda$print ( "This is to demonstrate the built-in handler SDA$COND_HANDLER" ); sda$skip_lines (1); lib$signal ( SS$_INVARG ); } return; }