Jump to content United States-English
HP.com Home Products and Services Support and Drivers Solutions How to Buy
» Contact HP
HP.com home

HP OpenVMS Systems

OpenVMS Technical Journal V7
» 

HP OpenVMS Systems

OpenVMS information

» What's new on our site
» Upcoming events
» Configuration and buying assistance
» Send us your comments

HP OpenVMS systems

» OpenVMS software
» Supported Servers
» OpenVMS virtualization
» OpenVMS solutions and partners
» OpenVMS success stories
» OpenVMS service and support
» OpenVMS resources and information
» OpenVMS documentation
» Education and training

Evolving business value

» Business Systems Evolution
» AlphaServer systems transition planning
» Alpha RetainTrust program

Related links

» HP Integrity servers
» HP Alpha systems
» HP storage
» HP software
» HP products and services
» HP solutions
» HP support
2008 HP Worldwide User Advocacy Survey
disaster proof
HP Integrity server animation
Content starts here

Faking it with OpenVMS Shareable Images

John Gillings, HP Customer Support Centre, Sydney Australia

Overview

Shareable images play a key role in OpenVMS. They are largely responsible for the legendary upwards compatibility across all versions by allowing run-time libraries (RTLs) to be updated while remaining binary compatible with existing program images. This mechanism can be exploited to provide a means for intercepting calls into shareable images, allowing black box diagnosis and debugging, selective modification of function, and a variety of other interesting applications.

This article discusses the theory and presents some DCL command procedures for analyzing and manipulating shareable images, and also for generating fake shareable image interfaces.

Caveats

Note that the techniques presented are NOT universal and may not work correctly for all shareable images. They are intended to be used for education, diagnosis and debugging, NOT for production use or in critical applications. For the purposes of this article, only standard call interfaces on OpenVMS Alpha are considered. See the postscript for an enhancement that supports standard call interfaces on OpenVMS I64.

The procedure is user mode and requires no privilege. System shareable images can be faked by unprivileged users; however, the mechanism cannot be used to subvert the function of privileged images.

What is a Shareable Image?

Shareable images are collections of data and code that can be treated as a black box. Among other things, linking a program image involves resolving references to symbols (routines and data). Some references are resolved by including object code directly in the output image. Others are resolved from external libraries, shareable images, which are activated at run time. Thus most images contain a list of shareable images against which it was linked. Those images, in turn may reference other shareable images. A program image may therefore be seen as a hierarchy of shareableimages. Images linked against a shareable image know only about the routines and data exported from the shareable image. They have no knowledge of how the routines are implemented.

How Shareable Images Work

The shareable image interface is controlled by an entity called a symbol vector and a GSMATCH value and condition. These two, plus the image name, completely define the shareable image and control how a calling image can identify the correct shareable image. The symbol vector acts like a plug and socket. Provided the plug in the calling image fits the socket in the shareable image, the shareable image is activated.

The calling image establishes the shapes of the interfaces of referenced shareable images at link time and expects the run-time shareable images to match.

Symbol Vectors and GSMATCH

The symbol vector consists of an ordered list of entries representing objects exported from the shareable image. Entry types considered in this article are PROCEDURE, CONSTANT, DATA CELL and SPARE. There are other types, but they are very rare and beyond the scope of this article. The Global Section MATCH (GSMATCH) is a pair of values and a matching rule that are considered when activating an image. Rules include ALWAYS, EQUAL, LEQUAL and NEVER. The pair of values is major ID and minor ID. When an image is linked, the GSMATCH values and rule of the target image are saved for comparison against a candidate image to be activated at run time. Rule ALWAYS causes the image activator to ignore the GSMATCH and always activate the image. Rule NEVER causes it to never activate an image (naturally this is rarely used in practice!). EQUAL requires both major and minor IDs to match exactly. The LEQUAL rule requires the major ID to match, but the minor ID of the candidate image may be greater than the expected value. The LEQUAL rule is the most commonly used match criterion, because it allows the implementation of upward compatible shareable images.

Image Activation

When an image is activated, the image activator extracts the list of referenced shareable images from the image header. The list gives the image name, the GSMATCH values and match criteria, and the symbol vector size. The name is used to locate the image. By default it is expected to be in directory SYS$SHARE with file type .EXE. The default can be overridden by defining the image name as a logical name with a full file specification. Once the shareable image file is found, the GSMATCH values are checked. If they pass the match criteria, the symbol vector size is compared. The symbol vector of the candidate image must be at least as large as the expected symbol vector size. If all of these tests pass, the shareable image is activated. If the newly activated image itself references shareable images, these are added to the image activator's list and the process of image activation continues.

Upwards Compatibility

Using GSMATCH=LEQUAL, it is easy to create shareable images that support upwards compatibility. If changes are made to the implementation of a shareable image, the new image will be compatible (plug interchangeable) with the old image provided there are no changes to the symbol vector. However if new entries are added to the end of the symbol vector, the new symbol vector will be longer. So images linked against the old image can execute against old or new shareable images, but images linked against the new shareable image cannot execute against the old version (because they might reference the new symbol vector entries, which do not exist in the older image's symbol vector). By convention, the minor ID of the GSMATCH values for the new image should be incremented, so that the GSMATCH=LEQUAL match criteria detects the difference in the images. For example:

MYSHARE
GSMATCH=LEQUAL,100,5
      SYMBOL_VECTOR=(F1=PROCEDURE,F2=PROCEDURE)

CALLING PROGRAM Shareable image list Name: MYSHARE, match: LEQUAL, Major:100, Minor: 5, vector size:2
Create a new version of the shareable image MYSHARE, adding procedure F3:



MYSHARE GSMATCH=LEQUAL,100,6 SYMBOL_VECTOR=(F1=PROCEDURE,F2=PROCEDURE,F3=PROCEDURE)
A caller linked against the older version of MYSHARE passes the GSMATCH and vector size tests, and therefore, activates the image. A program linked against the new image has a different entry in the shareable image list:


CALLING PROGRAM Shareable image list Name: MYSHARE, match: LEQUAL, Major:100, Minor: 6, vector size:3
If this image attempts to activate the older version of MYSHARE, both the GSMATCH and symbol vector size tests fail, with an error similar to the following:


%DCL-W-ACTIMAGE, error activating image MYSHARE
-CLI-E-IMGNAME, image file DKA100:[SHARE]MYSHARE.EXE;1
-SYSTEM-F-SHRIDMISMAT, ident mismatch with shareable image

If for some reason the GSMATCH comparison succeeds, but the symbol vector is too short, the image fails to activate with an error message similar to the following:


%IMGACT-F-SYMVECMIS, shareable image's symbol vector table mismatch
-IMGACT-F-FIXUPERR, error when CALLPROG referenced MYSHARE

Dynamic Activation

Shareable images can also be activated dynamically under program control. The LIBRTL routine LIB$FIND_IMAGE_SYMBOL (LIB$FIS) accepts an image name, symbol name pair. It activates the image (if necessary) and returns the address of the object represented by the symbol. There are no GSMATCH or symbol vector checks.

Given the above, it is possible to clone the symbol vector and declare the same GSMATCH criteria and values of a given shareable image to create a fake image that can be substituted for the real image at run time. Further, we can implement the routines in the cloned image so they call the real routines in the real image, but we can also insert code at the beginning, at the end, or both to do whatever we like.

Figure 2 - Call Through a Fake Image

The calling image activates a compatible shareable image that intercepts all calls to the real shareable image.

Will the Real Image Please Stand Up?

If the fake image is activated, finding the real image is a problem. To distinguish the images, we need to give the real image a different name, so that the image activator thinks it's a different image. The simplest approach is to take a copy of the image and give it a prefix of REAL_. At run time, a logical name with the REAL_ prefix can be defined to locate the real image.

Because we'd like to be able to activate the fake image either with normal activation or dynamic activation, the symbols in the symbol vector must match those of the real image. Therefore, the fake image cannot call the real image directly, because the linker would detect duplicate symbols. Instead, we can dynamically activate the real image and use LIB$FIND_IMAGE_SYMBOL to locate the real routines. But LIB$FIND_IMAGE_SYMBOL is inside LIBRTL, and it's sometimesdesirable to be able to create a fake LIBRTL, so we can't call LIB$FIND_IMAGE_SYMBOL directly from the fake image. Instead, we can create a FAKE_RTL shareable image in which the calls to other RTLs can be hidden. FAKE_RTL also contains other support routines for tracing argument lists and other functions. It is linked against REAL_LIBRTL to ensure it always calls the real LIB$FIND_IMAGE_SYMBOL.


Figure 3 - FAKE_RTL Support Routines

Use FAKE_RTL to mediate between the fake and real shareable images. Images are located using the logical names as shown.

Resolving Self References

Consider a program calling routine LIB$FIND_IMAGE_SYMBOL in a fake LIBRTL. The image activator follows the logical name LIBRTL finding and activating FAKE_LIBRTL. FAKE_LIBRTL calls FAKE_RTL to find the address of LIB$FIND_IMAGE_SYMBOL in REAL_LIBRTL, using LIB$FIND_IMAGE_SYMBOL itself. FAKE_RTL then calls the real LIB$FIND_IMAGE_SYMBOL on behalf of FAKE_LIBRTL and returns the results to the caller.

But Why Would I Want to Do That?

OK, so it's possible to do this, but why would you want to? The mechanism is general. There are many possibilities. Here are some real world examples:
  • A customer wanted to run COBOL programs with the clock offset arbitrarily forwards or backwards. A FAKE_COBRTL was generated that passed through all COBRTL calls except those dealing with dates and times. These were caught and the dates and times returned were offset according to a logical name.
  • A customer program was apparently triggering a bug in SMGSHR, but attempts to reduce the customer's large program to a manageable reproducer were failing. By tracing the calls and argument lists to SMG$ routines through a FAKE_SMGSHR, it was possible to create a simple program, consisting of a sequence of SMG calls that demonstrated the bug.
  • A suspected AST re-entrancy problem in a customer program was proven by creating a fake RTL for a key (3rd party) shareable image and inserting $SETAST calls before and after each call to block and restore AST interrupts while inside the shareable image. As well as proving the suspicions, this also provided a short term workaround while the shareable image was corrected.
  • When debugging, it's sometimes desirable to set a break point at an RTL routine. If the shareable image containing the routine was not linked with /DEBUG, the symbol is not accessible. A fake image can be compiled and linked with /DEBUG and thereby make symbols available as breakpoints. Moreover, it is possible to break at calls from other code, including OpenVMS RTLs.

This mechanism is applicable for any case where you want to see what's going on inside a shareable image, or want to modify the function of some routines within the image, without having to re-implement the whole thing.

How it's Done

The command procedure FAKE_RTL.COM contains code to create all the necessary components for the FAKE_RTL environment and then analyze a given sharable image, generate a symbol vector and MACRO32 code to implement a template for the fake RTL.

Because the intention is for the user to be able to modify the fake RTL template for specific uses, the procedure is written as a sequence of phases, any of which can be executed independently.

Why MACRO?

Code is generated in MACRO32, because it's necessary to preserve all register values at all times. It's also much easier to manipulate argument lists without having access to the original definitions. MACRO32 doesn't have an RTL of its own, so there's no need to preclude specific RTLs from being candidates of FAKE_RTL (not entirely true, as the MOVC3 and CALLG instructions, both used in FAKE_RTL, are implemented by routines in LIBOTS - FAKE_RTL is therefore linked against REAL_LIBOTS to ensure the "real" routines are always used). The other advantage of MACRO is it is available on all OpenVMS systems without additional licenses.

Vector Entries

As mentioned previously, the four types of vector entries with which we're concerned are SPARE, CONSTANT, PROCEDURE and DATA CELL. For each object, we need to generate a symbol vector reference and some code to implement the object. As a quick overview:
  • SPARE
    Shareable images may declare empty symbol vector slots for a variety of reasons. The existence of spare entries must be inferred from the relative spacing of other entries:
SYMBOL_VECTOR=(SPARE)
No MACRO32 code is necessary:
  • CONSTANT
    This is the simplest case of a real object, the symbol vector entry is:
SYMBOL_VECTOR=(<symbol-name>=DATA)
MACRO32 code is a global symbol definition:
<symbol-name>==<value>
Note that the fake image could export a constant value different from the value exported from the real image. The FAKE_RTL procedure generates the real value in the template source code, but it can easily be modified.
  • PROCEDURE
    The majority of entries are procedure calls. The symbol vector entry is:
SYMBOL_VECTOR=(<symbol-name>=PROCEDURE)
MACRO32 code is a call to a macro:
CallRoutine <symbol-name>
Details of this macro and alternatives are discussed later. In practice, what the macro does depends on why you want to create a fake shareable image. By default FAKE_RTL.COM generates a macro that writes a log file, tracing each call into the shareable image, including argument list and register values.
  • DATA CELL
    Data is hard to deal with, and in some cases intractable. That's because there is no mechanism in OpenVMS to jacket a data reference. Exactly how to implement data depends on how it is used in both the caller and the real shareable image. The symbol vector entry is:
SYMBOL_VECTOR=(<symbol-name>=DATA)
By default, the MACRO32 code generated attempts to declare data cells that match the original in size and location relative to other data cells:
<symbol-name>:: .BLKB <object size>
At run time, the data region containing these declarations is mapped to the corresponding locations in the real shareable image. Although this works for many uses of exported data, it's not universal. Examples of where this might not work, and some potential workarounds are discussed later.

Walkthrough FAKE_RTL.COM

There are seven phases to creating a fake shareable image. They are:
  1. DEF - Define fake RTL environment
  2. COPY - Make a copy of the original shareable image
  3. VECTOR - Analyze the symbol vector
  4. GEN - Generate MACRO code
  5. COMPILE - Compile MACRO code
  6. LINK - Link fake RTL
  7. USE - Define logical names to use image

The procedure is invoked, optionally giving the name of a shareable image, a start phase and options. By default, the named phase and all subsequent phases are executed. If no phase is given, DEF is assumed, but only those phases that appear to have not been executed are performed. If no parameters are given, the environment is defined. For example: $ @FAKE_RTL

  • Defines logical names necessary for running a fake shareable image, including any logical names and symbols for using fake images already created. It also creates FAKE_RTL.EXE if it does not exist.

$ @FAKE_RTL SMGSHR

  • Creates a fake version of SMGSHR if it does not already exist. Defines logical names and symbols for using FAKE_SMGSHR if it already exists.

$ @FAKE_RTL SMGSHR COMPILE

  • Compiles and links FAKE_SMGSHR, then defines logical names and symbols to use it.

$ @FAKE_RTL SMGSHR GENERATE DEBUG

  • Generates MACRO32 code for FAKE_SMGSHR, then compiles and links FAKE_SMGSHR with DEBUG.

$ @FAKE_RTL LIBRTL VECTOR FORCE

  • Analyzes LIBRTL.EXE, generates MACRO32 code, compiles and links FAKE_LIBRTL. The FORCE option causes any existing versions of FAKE_LIBRTL to be overwritten.

FAKE_RTL.COM Phases in Detail

The following list describes FAKE_RTL.COM phases:
  • DEF - Define fake RTL environment

    This phase defines the logical name FAKE_DIR to point to the directory containing FAKE_RTL routines and procedures. If the shareable image FAKE_RTL.EXE does not exist, it is created.

    FAKE_DIR is then scanned for files called REAL_<name>.EXE. A logical name is defined for each one found. COPY - Make a copy of the original shareable image

    The copy is called REAL_<imagename> and placed in the directory containing FAKE_RTL

  • VECTOR - Analyze the symbol vector

    The input image is analyzed using ANALYZE/IMAGE and then filtered using SEARCH to extract the GSMATCH values and symbol vector entries. The GSMATCH information looks like this.

    
    
    image type: shareable (EIHD$K_LIM)
    	global section major id: %X'42', minor id: %X'000017'
    	match control: ISD$K_MATLEQ
    
    

    It would be transformed into a Linker options definition:

GSMATCH=LEQUAL,%X42,%X17

    The three symbol vector entry types look like this:

    
    
    		value: 16 (%X'00000010')
    		symbol vector entry (constant)
    			%X'00000000 00000000'
    			%X'00000000 00358014' (3506196)
    		symbol: "C$_ENOENT"
    
    		value: 1248 (%X'000004E0')
    		symbol vector entry (procedure)
    			%X'00000000 0009BD40'
    			%X'00000000 000D5038'
    		symbol: "LIB$WAIT"
    
    		value: 30272 (%X'00007640')
    		symbol vector entry (data cell)
    			%X'00000000 00000000'
    			%X'00000000 002502C4'
    		symbol: "DECC$GA_TZNAME"
    
    

    The value field is the offset to the entry in the symbol vector. For constants, the second symbol vector entry value is the value of the constant. For procedures, the symbol vector entry is the procedure descriptor. For data cells, the second symbol vector entry value is the offset to the data cell from the start of the shareable image. These entries are parsed and written to a file one line per entry as:

    
    
       <value> <vector value 1> <vector value 2> <symbol> <type>
    
    

    Data cell values are written to a second output file as well:

    
       <vector value 2> <symbol>
    
    

    The output files are then sorted. The vector list is then in symbol vector order. The data list is in allocation order.

  • GEN - Generate MACRO code

    This phase uses the ordered vector and data lists from the VECTOR phase to generate the symbol vector (as a linker options file) and MACRO32 code. For each vector entry we generate a symbol vector declaration and some code. Before writing the symbol vector declaration, we first check for holes. Because all entries are 16 bytes, this is a simple matter of keeping track of the next expected entry value. Any missing entries are filled with SPARE entries. Constants are dealt with as described previously.

    Procedures generate a call to a macro. The default macro generates a memory location to store the symbol name and another to store the symbol address (initialized to 0). These are used in a call to routine FAKE_LOGCALL in FAKE_RTL, passing the name of the real RTL, the name of the symbol, the symbol address and a pointer to the homed argument list.

    FAKE_LOGCALL will check thesymbol address. If zero, it uses LIB$FIND_IMAGE_SYMBOL to locate the routine. The routine is then called, passing the argument list. If the logical name FAKE_DUMPARGS is defined, FAKE_LOGCALL logs the routine name, argument list, and register values to a file called ARGDUMP.LOG.

    In some cases, the shareable image routine should be called using an OpenVMS VAX style JSB mechanism. In these cases, the FAKE_RTL routine FAKE_LOGJSB should be called instead. The OpenVMS naming convention is to name JSB routines with a trailing _Rn, where n is the highest register number used by the routine. FAKE_RTL.COM recognizes this convention and uses a JSB macro instead of a CALL macro. However, this is NOT universal. If your target shareable image has JSB routines, you need to manually modify the generated code to use the correct call semantics.

    When processing vector entries, data cell entries generate a symbol vector declaration, but no code. Once the vector is complete, the data list is processed (if it exists). Data declarations are processed in allocation order. They are placed in a page-aligned PSECT, with the first entry aligned to the same page offset as the entry in the real shareable image. Objects are assumed to be the inferred size of the difference between adjacent declarations.

    However, if a gap between declarations exceeds an Alpha page, a new block of data is started. For each block, the name of the first symbol is saved, and a private routine MapData is generated to be called when the image is activated.

    At run time, MapData calls the FAKE_RTL routine FAKE_MAP_DATA for each data block, given the name of the real shareable image, a generated global section name, the name of the first symbol in the block and the size, and start and end addresses of the block. FAKE_MAP_DATA first deletes the virtual memory for the block, then creates and maps a global section. It then copies the contents of the corresponding memory locations from the real shareable image, deletes the virtual memory in the real shareable image, and maps the locations to the global section. The result is two address ranges that map the same physical data. See Figure 4 for an illustration of this process. This is an imperfect solution. Potential problems are discussed later.


    Figure 4 - Mapping Shared Data

  • COMPILE - Compile MACRO code

    If you make changes to the generated template, you must recompile the MACRO32 source code. The DEBUG option causes the compilation to be /NOOPTIMIZE/DEBUG.

  • LINK - Link fake RTL

    The FAKE_imagename image is linked using the options file generated in the GEN phase. The DEBUG option causes /DEBUG to be added to the LINK command.

  • USE - Define logical names to use image

    A logical name REAL_imagename is defined to point to the image created in the COPY step:

    $ DEFINE REAL_LIBRTL DISK:[DIR]LIBRTL

    You can redefine this point to the original image:

    $ DEFINE REAL_LIBRTL SYS$SHARE:LIBRTL

    However, in the case of installed resident images, especially those with shared address data, this might result in bypassing some defined "fake" images. For most cases, it's best to use the renamed copy created in the COPY phase. Two global symbols are also defined:

    $ FAKE_imagename=="$DEFINE/USER/NAME=CONFINE imagename FAKE_DIR:FAKE_imagename"

    and:

    $ REAL_imagename=="$DEASSIGN imagename"

    These symbols are intended to simplify enabling a fake shareable image. Note that /USER is specified so the definition is automatically cancelled after the next image activation. This is a precaution to prevent surprises. /NAME=CONFINE prevents the logical name from being propagated to subprocesses. This may be necessary, for example, when running an image under DEBUG, as you probably don't want the DEBUG subprocess to run through your fake shareable image.

Does it work?

Well, it does mostly. For shareable images that export only constants and procedures, the only potential problem is JSB routines, which are comparatively rare. The most likely symptom of a JSB routine called incorrectly is when logging argument lists, seeing an obviously incorrect (very high) argument count. It seems that sometimes these high values can upset the argument homing mechanism, resulting in ACCVIOs.

However, images that export data don't always work. In some cases, the data is constant. For example, LIBRTL exports a number of character conversion tables. These work correctly with the remapping mechanism. In other cases the data is used in ways that are incompatible with the mapped section solution implemented by default.

For example, PAS$RTL exports 3 file variables: PAS$FV_INPUT, PAS$FV_OUTPUT and PAS$FV_ERR, being standard input, standard output and standard error. Although the double map mechanism correctly references the variables, PAS$RTL code compares addresses of file variables passed to I/O routines to detect use of the standard files. Because the caller is passing via the fake addresses, the variables aren't recognized.

One way to work around this type of usage is to scan the argument lists of potentially affected routines, looking for addresses in the range of the fake data blocks. If any are found, calculate the offset and adjust it to be in the real address range. This is very ugly, but it works for PAS$RTL (the task is made a bit easier because there's only one potential argument affected, and the I/O routines are easily identified).

Case-sensitive symbol names can't be defined in MACRO32, so any shareable images that export lowercase symbols can cause trouble. For example, DECC$SHR exports each symbol in both uppercase and lowercase forms. Without some modification, this would generate duplicate symbols in MACRO32. The GEN phase identifies lowercase symbols and defines them using a prefix L_, truncating the symbol name if necessary. Because there is no reason to LINK against the FAKE_imagename image, this does not cause any trouble for a caller activating the image normally. But an attempt to activate the image with LIB$FIND_IMAGE_SYMBOL using a lowercase, case-sensitive symbol name fails because the expected symbol does not exist.

Examples

Under OpenVMS V7.3-2 and V8.2, the following OpenVMS RTLs and shareable images can be converted automatically and appear to work as expected:
  • DEC$BASRTL
  • DEC$COBRTL
  • DEC$FORRTL
  • FDLSHR
  • LIBRTL
  • LBRSHR
  • MAILSHR
  • SMGSHR
  • SORTSHR
  • TPUSHR

DECC$SHR seems to work for some simple programs, but fails with more complex programs. This may be a JSB routine issue or a data usage issue. Debugging is rather difficult. Use with extreme care. LIBOTS doesn't work at all. This appears to be some form of recursion trying to call OTS$CALL_PROC using itself, which is even more difficult to debug.

In testing while writing this article, a small bug was found in the MAIL utility. MAIL attempts to find the symbol TPU$_NONANSICRT in TPUSHR to correctly report an attempt to edit from a non-ANSI terminal. A typo in the source code defined the symbol name incorrectly as TPU$_NOANSICRT. As a result, when an attempt was made to use the editor from a non-ANSI terminal, MAIL did not report the error, it just failed to send the message:



MAIL> send/edit
To:     _gillings
Subj:   test
%MAIL-E-SENDABORT, no message sent
MAIL> *EXIT*

To confirm the diagnosis, a FAKE_TPUSHR was created, and the symbol name and definition TPU$_NONANSICRT was changed to TPU$_NOANSICRT so that the call from MAIL would be correct. When running with this modified FAKE_TPUSHR, the behaviour of MAIL changed to the following, as intended:



$ mail

You have 1 new message.

MAIL> send/edit
To:     _gillings
Subj:   test
%TPU-E-NONANSICRT, SYS$INPUT must be supported CRT 
%MAIL-E-SENDABORT, no message sent
MAIL> *EXIT* 

This demonstrates the ability to quickly test and workaround some classes of bug, even when the incorrect source code is unavailable. It also proves that the proposed solution (fixing the symbol name) corrects the problem. (This bug has been reported to OpenVMS engineering, and is now fixed).

Postscript - Port to OpenVMS Integrity Server

Because the routines and mechanisms involved are deeply involved in the calling standard, which has been changed to accommodate the Integrity server platform, it was assumed that porting this utility to OpenVMS Integrity server (I64) would be difficult, hence the caveat about Alpha Only.

Preliminary investigation showed that the FAKE_RTL shareable image worked correctly with no changes. A straight forward "compile and go". All that was necessary was to teach the vector generation phase of FAKE_RTL.COM how to interpret an I64 image analysis. The output of ANALYZE/IMAGE/SECTION=SYMBOL_VECTOR was already much closer to the required format than the Alpha equivalent. Also the I64 qualifier /NOPAGE_BREAK simplified parsing by eliminating page breaks. The I64 implementation lists the symbol vector completely, whereas it needs to be reconstructed by inference from an Alpha image analysis. One consequence of this was the vector listing now contains explicit "SPARE" vector entries, so the GEN phase required extra logic to recognize the entries, rather than inferring them. The only other change required was to change the sanity-check logic to know that I64 vector entries are 8 bytes, and Alpha vector entries are 16 bytes.

In hindsight, the VECTOR phase is almost superfluous given the output of ANALYZE/IMAGE on I64. A better design might be to change the Alpha VECTOR phase to match the I64 format, rather than processing the I64 output to match what was implemented for Alpha.

The port was completed in less than one hour, yielding working FAKE_LIBRTL, FAKE_DECC$SHR, FAKE_MAILSHR, FAKE_SMGSHR and FAKE_UTIL$SHARE images. The command procedure published with this article in Appendix F is the updated Alpha and I64 version. As a minor addition, it also outputs an unsupported error message if executed on any other platform.

The FAKE_RTL command procedure is located at the following URL:

» http://h71000.www7.hp.com/openvms/journal/v7/fake_rtl_com.txt

Appendix A: FAKE_RTL Routines

The following are routines exported by FAKE_RTL:



FAKE_DOCALL(		! dispatch to routine by CALL
	imagename readonly string descriptor,
	symbolname readonly string descriptor,
	routineaddress modify longword reference
	arglist readonly argument vector reference):returns longword

FAKE_LOGCALL(		! log argument list and dispatch by CALL
	imagename readonly string descriptor,
	symbolname readonly string descriptor,
	routineaddress modify longword reference
	arglist readonly argument vector reference):returns longword

FAKE_DOJSB(	          		! dispatch to routine by JSB
	imagename readonly string descriptor,
	symbolname readonly string descriptor,
	routineaddress modify longword reference
	r16,r17,r18,r19,r20,r21 readonly quadword immediate value):returns longword

FAKE_LOGJSB(		! log argument list and dispatch by JSB
	imagename readonly string descriptor,
	symbolname readonly string descriptor,
	routineaddress modify longword reference
	r16,r17,r18,r19,r20,r21 readonly quadword immediate value):returns longword

FAKE_PUT(			! write a string to log file (unconditional)
	string readonly string descriptor)

FAKE_FIS(	          		! jacket for LIB$FIND_IMAGE_SYMBOL
	imagename readonly string descriptor,
	symbolname readonly string descriptor,
	routineaddress modify longword reference)

FAKE_CALL(			! jacket for CALLG (OTS$EMUL_CALL)
	routineaddress readonly longword reference
	arglist readonly argument vector reference):returns longword

 
FAKE_MOVE(			! jacket for MOVC3
	bytes readonly longword immediate value
	source readonly bytearray reference
	destination writeonly bytearracy reference)

FAKE_OUT(	            	! jacket for LIB$PUT_OUTPUT
	string readonly string descriptor)

FAKE_LOG(	            	! write to log file if logging enabled
	string readonly string descriptor)

FAKE_MAP_DATA(		! map data area
	imagename readonly string descriptor,
	sectionname readonly string descriptor,
	symbolname readonly string descriptor,
	pages readonly longword immediate value
	startaddress readonly address immediate value
	endaddress readonly address immediate value):returns address


Appendix B: Logging Argument Lists

Logging calls and argument lists is just one application of this mechanism. As it's of general use, logging is implemented as the default function of a fake RTL. Because there is no information about argument lists available, this implementation of logging is best guess based on the actual arguments. RMS services are used to avoid dependence on language RTLs.

Logging starts with the routine name and a time stamp, followed by a dump of general registers R0 through R11.

The first test is to see if the argument list is readable at all. If not readable, it's considered a zero list. If readable, the argument count is determined and logged.

For each argument, the value is examined. If it's not a readable address, the argument is assumed to have been passed by immediate value and is displayed like arguments 3 and 6 through 10 in Figure 5.



 LIB$CREATE_VM_ZONE at 15:33:46.66
  R0:00000000 R1:010E0009 R2:00B9AA00 R3:00000007 R4 :00124B60 R5: 00090020
  R6:00000000 R7:00BC8024 R8:00000000 R9:00090020 R10:7FFA4F28 R11:7FFCDBE8
  LIB$CREATE_VM_ZONE called with 11 args
     1 00BC8020 => 00000000
     2 7AD496B0 => 00000001
     3 00000000
     4 7AD496B8 => 000000A1
     5 00000000
     6 00000000
     7 00000000
     8 00000000
     9 00000000
    10 00000000
    11 7AD49630 => 010E0009
                   00BA8750 => SMG$_ZONE
  LIB$CREATE_VM_ZONE returning 11 args
     1 00BC8020 => 007D0800
     2 7AD496B0 => 00000001
     3 00000000
     4 7AD496B8 => 000000A1
     5 00000000
     6 00000000
     7 00000000
     8 00000000
     9 00000000
    10 00000000
    11 7AD49630 => 010E0009
                   00BA8750 => SMG$_ZONE
  LIB$CREATE_VM_ZONE returned: 00000001 at 15:33:46.66
  R0:00000001 R1:0000C3A5 R2:00B9AA00 R3:00000007 R4 :00124B60 R5: 00090020
  R6:00000000 R7:00BC8024 R8:00000000 R9:00090020 R10:7FFA4F28 R11:7FFCDBE8

Figure 5 - Sample Logged Call and Argument List

If the argument is a readable address, the value referenced is displayed, like arguments 1, 2 and 4 in Figure 5. The address is also passed to LIB$CVT_DX_DX with a valid output string descriptor. If the argument is a valid scalar descriptor, CVT_DX_DX converts it to a string, which can then be displayed like argument 11 in Figure 4.

If the descriptor test fails, the address is then scanned for printable characters. If any are found, the argument is assumed to be a string by reference or null terminated string, which is displayed, like argument 1 to DECC$GETENV in Figure 6. Obviously, this test has the potential to "run away" on a very long string, so the string is limited to a displayable length (see symbol maxstr in the source code FAKE_RTL.MAR).

When the routine returns, the argument list is logged a second time, the routine name, its return value and a time stamp are logged, and the general registers are dumped again. This shows any changes to arguments resulting from the call, for example, argument 1 in Figure 5.


Figure 6 - Sample Logged Call Showing Nesting

Because logged routines may call other fake RTL routines, logging keeps track of the nesting level and indents nested calls. For example, Figure 6 shows the CRTL routine getenv calls LIB$GET_SYMBOL to obtain the symbol value from DCL. Note that argument 2 to LIB$GET_SYMBOL (the output string) contains junk on input. The descriptor is for a string 1025 characters long, but only the first 48 characters are displayed.

Because this algorithm knows nothing of the actual argument declaration and usage, it's subject to error. It frequently displays an argument as a string, just because the bytes look like printable ASCII characters. The philosophy is to try to show as much as possible. Obviously, the code implemented in FAKE_RTL can be replaced by a more sophisticated algorithm, or one with more direct knowledge of the target shareable image.

Appendix C: Sample Run

The following is a transcript from a terminal session showing initial execution of FAKE_RTL.COM to generate FAKE_RTL.EXE. The procedure is then used to create fake RTLs for SMGSHR, LIBRTL and DECC$SHR.

Note that the warnings listed for LIBRTL and DECC$SHR are normal. They show holes in the symbol vector that are filled with SPARE entries. LIBRTL also contains several JSB routines, identified by the naming convention of suffixing the routine name with _Rn.



$ @fake_rtl
Defining FAKE_RTL environment
%CREATE-I-CREATED, USER$TSC:[GILLINGS.FAKE_RTL]FAKE_RTL.MAR;1 created
%CREATE-I-CREATED, USER$TSC:[GILLINGS.FAKE_RTL]FAKE_RTL.OPT;1 created
Compiling FAKE_RTL.MAR
Linking FAKE_RTL.OBJ
$
$ @fake_rtl smgshr
%COPY-S-COPIED, SYS$COMMON:[SYSLIB]SMGSHR.EXE;1 copied to 
	USER$TSC:[GILLINGS.FAKE_RTL]REAL_SMGSHR.EXE;1 (593 blocks)
Generating symbol vector for SMGSHR
%ANALYZE-I-ERRORS, USER$TSC:[GILLINGS.FAKE_RTL]REAL_SMGSHR.EXE;1 0 errors
Generating MACRO code for SMGSHR
Compiling FAKE_SMGSHR
Linking FAKE_SMGSHR
$
$ @fake_rtl librtl
Generating symbol vector for LIBRTL
%ANALYZE-I-ERRORS, USER$TSC:[GILLINGS.FAKE_RTL]REAL_LIBRTL.EXE;1 0 errors
Generating MACRO code for LIBRTL
Assumed JSB routine LIB$ANALYZE_SDESC_R2
Warning - vector hole before LIB$CVT_DTB. Expecting 272, got 288
Warning - vector hole before LIB$DELETE_FILE. Expecting 336, got 352
Warning - vector hole before LIB$EXTV. Expecting 432, got 448
Warning - vector hole before LIB$GET_COMMAND. Expecting 544, got 576
Warning - vector hole before LIB$INDEX. Expecting 608, got 624
Warning - vector hole before LIB$LOCC. Expecting 656, got 672
Warning - vector hole before LIB$SCANC. Expecting 848, got 864
Assumed JSB routine LIB$SGET1_DD_R6
Warning - vector hole before LIB$TRA_ASC_EBC. Expecting 1168, got 1184
Assumed JSB routine OTS$$CVT_D_T_R8
Assumed JSB routine OTS$$CVT_F_T_R8
Assumed JSB routine OTS$$CVT_G_T_R8
Assumed JSB routine OTS$$CVT_H_T_R8
Assumed JSB routine OTS$MOVE3_R5
Assumed JSB routine OTS$MOVE5_R5
Assumed JSB routine OTS$SGET1_DD_R6
Assumed JSB routine STR$ANALYZE_SDESC_R1
Assumed JSB routine STR$COPY_DX_R8
Assumed JSB routine STR$COPY_R_R8
Assumed JSB routine STR$FREE1_DX_R4
Assumed JSB routine STR$GET1_DX_R4
Assumed JSB routine STR$LEFT_R8
Assumed JSB routine STR$LEN_EXTR_R8
Assumed JSB routine STR$POSITION_R6
Assumed JSB routine STR$POS_EXTR_R8
Assumed JSB routine STR$REPLACE_R8
Assumed JSB routine STR$RIGHT_R8
Assumed JSB routine OTS$$RET_A_CVT_TAB_R1
Warning - vector hole before LIB$EMUL. Expecting 2896, got 2912
Warning - vector hole before LIB$REMQHI. Expecting 3104, got 3120
Warning - vector hole before STR$ADD. Expecting 3392, got 3680
Assumed JSB routine STR$ELEMENT_R8
Warning - vector hole before LIB$TABLE_PARSE. Expecting 4496, got 4576
Warning - vector hole before LIB$FIND_VM_ZONE. Expecting 4608, got 4640
Start of data block 1 00000000000D6EB0 LIB$AB_ASC_EBC
Compiling FAKE_LIBRTL
Linking FAKE_LIBRTL
$
$ @fake_rtl decc$shr
%COPY-S-COPIED, SYS$COMMON:[SYSLIB]DECC$SHR.EXE;1 copied to 
		USER$TSC:[GILLINGS.FAKE_RTL]REAL_DECC$SHR.EXE;1 (4483 blocks)
Generating symbol vector for DECC$SHR
%ANALYZE-I-ERRORS, USER$TSC:[GILLINGS.FAKE_RTL]REAL_DECC$SHR.EXE;1 0 errors
Generating MACRO code for DECC$SHR
Warning - vector hole before decc$bsd__cputchar. Expecting 22784, got 22800
Warning - vector hole before DECC$CONFSTR. Expecting 34736, got 34800
Warning - vector hole before decc$readdir_r. Expecting 46128, got 46224
Warning - vector hole before decc$poll. Expecting 49776, got 50000
Start of data block 1 00000000001F0000 DECC$GA_BSD_AE
Hole in data exceeded threshold at 00000000001F4E18 DECC$$GA_IO_BLOCK
Start of data block 2 00000000001F4E18 DECC$$GA_IO_BLOCK
Compiling FAKE_DECC$SHR
Linking FAKE_DECC$SHR
$

Appendix D: Sample Use

Enable argument logging by defining the logical name fake_dumpargs, then enable the use of the fake DECC$SHR, LIBRTL and SMGSHR and activate the freeware utility DFU.


--------------------------------------------------
$
$ define fake_dumpargs "TRUE"
$ fake_decc$shr
$ fake_librtl
$ fake_smgshr
$ mcr dfu
--------------------------------------------------

+------------------------< DFU V2.7 >-------------------------------+
|                                                                   |                      
|     Disk and File Utilities for OpenVMS DFU V2.7                  |                     
|     Internal Use Only!                                            |                      
|     Copyright Š 2000 COMPAQ Computer Corporation                  |
|     DFU functions are :                                           |
|     DEFRAGMENT : Defragment files or disks                        |                       
|     DELETE     : Delete files by File-ID; delete directory (trees)|                      
|     DIRECTORY  : Manipulate directories                           |
|     INDEXF     : Modify /View INDEXF.SYS                          |                     
|     REPORT     : Generate a complete disk report                  |
|     SEARCH     : Fast file search                                 |                      
|     SET        : Modify file attributes                           |                      
|     UNDELETE   : Recover deleted files                            |                      
|     VERIFY     : Check and repair disk structure                  |
|                                                                   |
|                                                                   |
|                                                                   |
|                                                                   |
|                                                                   |
|                                                                   |
|                                                                   |
|---------------------------Statistics------------------------------|
|                                                                   |
|                                                                   |
|                                                                   |
+-------------------------------------------------------------------+

 DFU>  Exit

								

Appendix E: Sample Output

This (long) listing shows the beginning and end of the argument dump from the activation of DFU. A large chunk is omitted from the middle.


$ type/page argdump.log
Arg tracing started at 17-MAY-2005 15:33:46.62
Mapped Data LIBRTL1_DATA real:004EC000:004EFFFF => fake:00332000:00335FFF               
Mapped Data DECC$SHR1_DATA real:00A5E000:00A5FFFF => fake:00604000:00605FFF
Mapped Data DECC$SHR2_DATA real:00A62000:00A63FFF => fake:00606000:00607FFF

DECC$MAIN at 15:33:46.65
R0:7FFCF87C R1:00002000 R2:00010830 R3:7AF08EB2 R4 :7FFCF814 R5: 7FFCF934
R6:7FF9DEA7 R7:7FFA0ED0 R8:7FF9CDE8 R9:7FF9DDF0 R10:7FFA4F28 R11:7FFCDBE8
DECC$MAIN called with 9 args
   1 7FFCF884 => 00010830
               =/0/
   2 7AE63EC8 => 00303089
   3 7FFCF814 => 00000003
   4 7FFCF934 => 001C0048
               =/H/
   5 00000028
   6 00000000
   7 7AD49B78 => 7AEDB914
   8 7AD49B74 => 00000000
   9 7AD49B70 => 00000000

  LIB$GET_SYMBOL at 15:33:46.65
  R0:00000000 R1:00000001 R2:00A27A18 R3:00A13990 R4 :00000004 R5: 00000001
  R6:00000000 R7:00AFC008 R8:7FF9CDE8 R9:7FF9DDF0 R10:7FFA4F28 R11:7FFCDBE8
  LIB$GET_SYMBOL called with 4 args
     1 7AD48F58 => 010E0004
                   00A13990 => PATH
     2 7AD48F28 => 010E0401
                   7AD48F70 => ĐeM     8       T•G     ĐeM     8’Ôz    ¸ L     
     3 7AD48F60 => 00000000
     4 00000000
  LIB$GET_SYMBOL returning 4 args
     1 7AD48F58 => 010E0004
                   00A13990 => PATH
     2 7AD48F28 => 010E0401
                   7AD48F70 => sys$login                                       
     3 7AD48F60 => 00000009
     4 00000000
  LIB$GET_SYMBOL returned: 00000001 at 15:33:46.66
  R0:00000001 R1:00000009 R2:00A27A18 R3:00A13990 R4 :00000004 R5: 00000001
  R6:00000000 R7:00AFC008 R8:7FF9CDE8 R9:7FF9DDF0 R10:7FFA4F28 R11:7FFCDBE8

  LIB$INSERT_TREE at 15:33:46.66
  R0:00000000 R1:00000001 R2:00A3F2D8 R3:00AFC008 R4 :00000001 R5: 00AA0280
  R6:7AD48F70 R7:00AA0280 R8:7FF9CDE8 R9:7FF9DDF0 R10:7FFA4F28 R11:7FFCDBE8
  LIB$INSERT_TREE called with 7 args
     1 00A67B40 => 00000000
     2 7AD48EC8 => 00A13990
     3 7AD48ED8 => 00000000
     4 00A3F170 => 0116300A
     5 00A3F288 => 00083089
     6 7AD48EE0 => 00A0FF10
     7 00000000

    LIB$VM_MALLOC at 15:33:46.66
    R0:0045C834 R1:7AD48BC8 R2:00A1A260 R3:7AD48EC8 R4 :7AD48B30 R5: 00000000
    R6:00158001 R7:7AD48EE0 R8:00A3F288 R9:00A3F170 R10:7AD48EC8 R11:00000000
    LIB$VM_MALLOC called with 1 arg
       1 0000001C
    LIB$VM_MALLOC returning 1 arg
       1 0000001C
    LIB$VM_MALLOC returned: 00B2C008 at 15:33:46.66
    R0:00B2C008 R1:00000001 R2:00A1A260 R3:7AD48EC8 R4 :7AD48B30 R5: 00000000
    R6:00158001 R7:7AD48EE0 R8:00A3F288 R9:00A3F170 R10:7AD48EC8 R11:00000000

    LIB$VM_MALLOC at 15:33:46.66
    R0:00B2C008 R1:00000001 R2:00A1A260 R3:7AD48EC8 R4 :7AD48B30 R5: 00B2C008
    R6:00158001 R7:7AD48EE0 R8:00A3F288 R9:00A3F170 R10:7AD48EC8 R11:00000000
    LIB$VM_MALLOC called with 1 arg
       1 00000005
    LIB$VM_MALLOC returning 1 arg
       1 00000005
    LIB$VM_MALLOC returned: 00B2C030 at 15:33:46.66
    R0:00B2C030 R1:00000001 R2:00A1A260 R3:7AD48EC8 R4 :7AD48B30 R5: 00B2C008
    R6:00158001 R7:7AD48EE0 R8:00A3F288 R9:00A3F170 R10:7AD48EC8 R11:00000000

    LIB$VM_MALLOC at 15:33:46.66
    R0:00B2C030 R1:00000001 R2:00A1A260 R3:7AD48EC8 R4 :7AD48B30 R5: 00B2C008
    R6:00158001 R7:7AD48EE0 R8:00A3F288 R9:00A3F170 R10:7AD48EC8 R11:00000000
    LIB$VM_MALLOC called with 1 arg
       1 0000000A
    LIB$VM_MALLOC returning 1 arg
       1 0000000A
    LIB$VM_MALLOC returned: 00B2C040 at 15:33:46.66
    R0:00B2C040 R1:00000001 R2:00A1A260 R3:7AD48EC8 R4 :7AD48B30 R5: 00B2C008
    R6:00158001 R7:7AD48EE0 R8:00A3F288 R9:00A3F170 R10:7AD48EC8 R11:00000000

  LIB$INSERT_TREE returning 7 args
     1 00A67B40 => 00B2C008
     2 7AD48EC8 => 00A13990
     3 7AD48ED8 => 00000000
     4 00A3F170 => 0116300A
     5 00A3F288 => 00083089
     6 7AD48EE0 => 00B2C008
     7 00000000
  LIB$INSERT_TREE returned: 00158001 at 15:33:46.66
  R0:00158001 R1:00158214 R2:00A3F2D8 R3:00AFC008 R4 :00000001 R5: 00AA0280
  R6:7AD48F70 R7:00AA0280 R8:7FF9CDE8 R9:7FF9DDF0 R10:7FFA4F28 R11:7FFCDBE8

  LIB$GET_SYMBOL at 15:33:46.66
  R0:00000000 R1:00000001 R2:00A27A18 R3:00A139F0 R4 :00000009 R5: 00000001
  R6:00000000 R7:00AFC008 R8:00A9E2D7 R9:7FF9DDF0 R10:7FFA4F28 R11:7FFCDBE8
  LIB$GET_SYMBOL called with 4 args
     1 7AD48F58 => 010E0009
                   00A139F0 => VAXC$PATH
     2 7AD48F28 => 010E0401
                   7AD48F70 => sys$login                                       
     3 7AD48F60 => 00000000
     4 00000000
  LIB$GET_SYMBOL returning 4 args
     1 7AD48F58 => 010E0009
                   00A139F0 => VAXC$PATH
     2 7AD48F28 => 010E0401
                   7AD48F70 => sys$login                                       
     3 7AD48F60 => 00000000
     4 00000000
  LIB$GET_SYMBOL returned: 00158364 at 15:33:46.66
  R0:00158364 R1:FFFFFFFF R2:00A27A18 R3:00A139F0 R4 :00000009 R5: 00000001
  R6:00000000 R7:00AFC008 R8:00A9E2D7 R9:7FF9DDF0 R10:7FFA4F28 R11:7FFCDBE8

  LIB$INSERT_TREE at 15:33:46.66
  R0:00000000 R1:00000001 R2:00A3F2D8 R3:00AFC008 R4 :00000001 R5: 0000000E
  R6:7AD49030 R7:7FFA0ED0 R8:7FF9CDE8 R9:7FF9DDF0 R10:7FFA4F28 R11:7FFCDBE8
  LIB$INSERT_TREE called with 7 args
     1 00A67B40 => 00B2C008
     2 7AD48F88 => 00A13CF0
     3 7AD48F98 => 00000000
     4 00A3F170 => 0116300A
     5 00A3F288 => 00083089
     6 7AD48FA0 => 20202020
                 =/        ti/
     7 00000000

    LIB$VM_MALLOC at 15:33:46.66
    R0:00000001 R1:0045C520 R2:00A1A260 R3:7AD48F88 R4 :7AD48BD0 R5: 00000000
    R6:00158001 R7:7AD48FA0 R8:00A3F288 R9:00A3F170 R10:7AD48F88 R11:00000000
    LIB$VM_MALLOC called with 1 arg
       1 0000001C
    LIB$VM_MALLOC returning 1 arg
       1 0000001C
    LIB$VM_MALLOC returned: 00B2C058 at 15:33:46.66
    R0:00B2C058 R1:00000001 R2:00A1A260 R3:7AD48F88 R4 :7AD48BD0 R5: 00000000
    R6:00158001 R7:7AD48FA0 R8:00A3F288 R9:00A3F170 R10:7AD48F88 R11:00000000

    LIB$VM_MALLOC at 15:33:46.66
    R0:00B2C058 R1:00000001 R2:00A1A260 R3:7AD48F88 R4 :7AD48BD0 R5: 00B2C058
    R6:00158001 R7:7AD48FA0 R8:00A3F288 R9:00A3F170 R10:7AD48F88 R11:00000000
    LIB$VM_MALLOC called with 1 arg
       1 0000000A
    LIB$VM_MALLOC returning 1 arg
       1 0000000A
    LIB$VM_MALLOC returned: 00B2C080 at 15:33:46.66
    R0:00B2C080 R1:00000001 R2:00A1A260 R3:7AD48F88 R4 :7AD48BD0 R5: 00B2C058
    R6:00158001 R7:7AD48FA0 R8:00A3F288 R9:00A3F170 R10:7AD48F88 R11:00000000

    LIB$VM_MALLOC at 15:33:46.66
    R0:00B2C080 R1:00000001 R2:00A1A260 R3:7AD48F88 R4 :7AD48BD0 R5: 00B2C058
    R6:00158001 R7:7AD48FA0 R8:00A3F288 R9:00A3F170 R10:7AD48F88 R11:00000000
    LIB$VM_MALLOC called with 1 arg
       1 00000020
    LIB$VM_MALLOC returning 1 arg
       1 00000020
    LIB$VM_MALLOC returned: 00B2C098 at 15:33:46.66
    R0:00B2C098 R1:00000001 R2:00A1A260 R3:7AD48F88 R4 :7AD48BD0 R5: 00B2C058
    R6:00158001 R7:7AD48FA0 R8:00A3F288 R9:00A3F170 R10:7AD48F88 R11:00000000

  LIB$INSERT_TREE returning 7 args
     1 00A67B40 => 00B2C008
     2 7AD48F88 => 00A13CF0
     3 7AD48F98 => 00000000
     4 00A3F170 => 0116300A
     5 00A3F288 => 00083089
     6 7AD48FA0 => 00B2C058
                 =/X/
     7 00000000
  LIB$INSERT_TREE returned: 00158001 at 15:33:46.66
  R0:00158001 R1:00000000 R2:00A3F2D8 R3:00AFC008 R4 :00000001 R5: 0000000E
  R6:7AD49030 R7:7FFA0ED0 R8:7FF9CDE8 R9:7FF9DDF0 R10:7FFA4F28 R11:7FFCDBE8

  LIB$VM_CALLOC at 15:33:46.66
  R0:00A65780 R1:00000000 R2:00A1A280 R3:7FFCF934 R4 :00000000 R5: 00A65780
  R6:7FF9DEA7 R7:7FFA0ED0 R8:7FF9CDE8 R9:7FF9DDF0 R10:7FFA4F28 R11:7FFCDBE8
  LIB$VM_CALLOC called with 2 args
     1 00000001
     2 00000204
  LIB$VM_CALLOC returning 2 args
     1 00000001
     2 00000204
  LIB$VM_CALLOC returned: 00B2C0C0 at 15:33:46.66
  R0:00B2C0C0 R1:00000000 R2:00A1A280 R3:7FFCF934 R4 :00000000 R5: 00A65780
  R6:7FF9DEA7 R7:7FFA0ED0 R8:7FF9CDE8 R9:7FF9DDF0 R10:7FFA4F28 R11:7FFCDBE8

  LIB$VM_CALLOC at 15:33:46.66
  R0:00B2C0C0 R1:00000000 R2:00A1A280 R3:7FFCF934 R4 :00000000 R5: 00A65778
  R6:7FF9DEA7 R7:7FFA0ED0 R8:7FF9CDE8 R9:7FF9DDF0 R10:7FFA4F28 R11:7FFCDBE8
  LIB$VM_CALLOC called with 2 args
     1 00000001
     2 00000421
  LIB$VM_CALLOC returning 2 args
     1 00000001
     2 00000421
  LIB$VM_CALLOC returned: 00B2C300 at 15:33:46.66
  R0:00B2C300 R1:00000000 R2:00A1A280 R3:7FFCF934 R4 :00000000 R5: 00A65778
  R6:7FF9DEA7 R7:7FFA0ED0 R8:7FF9CDE8 R9:7FF9DDF0 R10:7FFA4F28 R11:7FFCDBE8

  LIB$VM_CALLOC at 15:33:46.66
  R0:00B2C300 R1:00000000 R2:00A1A280 R3:7FFCF934 R4 :00000000 R5: 00A65778
  R6:00B2C300 R7:7FFA0ED0 R8:7FF9CDE8 R9:7FF9DDF0 R10:7FFA4F28 R11:7FFCDBE8
  LIB$VM_CALLOC called with 2 args
     1 00000001
     2 00000421
  LIB$VM_CALLOC returning 2 args
     1 00000001
     2 00000421
  LIB$VM_CALLOC returned: 00B2C780 at 15:33:46.66
  R0:00B2C780 R1:00000000 R2:00A1A280 R3:7FFCF934 R4 :00000000 R5: 00A65778
  R6:00B2C300 R7:7FFA0ED0 R8:7FF9CDE8 R9:7FF9DDF0 R10:7FFA4F28 R11:7FFCDBE8

  LIB$GET_FOREIGN at 15:33:46.66
  R0:00000000 R1:00000000 R2:00A13DB8 R3:7FFCF934 R4 :00000000 R5: 00A65778
  R6:00B2C300 R7:00B2C780 R8:7FF9CDE8 R9:7FF9DDF0 R10:7FFA4F28 R11:7FFCDBE8
  LIB$GET_FOREIGN called with 3 args
     1 7AD497D8 => 01000421
                 =/!/
     2 00000000
     3 7AD497E0 => 00000000
  LIB$GET_FOREIGN returning 3 args
     1 7AD497D8 => 01000421
                 =/!/
     2 00000000
     3 7AD497E0 => 00000000
  LIB$GET_FOREIGN returned: 00000001 at 15:33:46.66
  R0:00000001 R1:00000000 R2:00A13DB8 R3:7FFCF934 R4 :00000000 R5: 00A65778
  R6:00B2C300 R7:00B2C780 R8:7FF9CDE8 R9:7FF9DDF0 R10:7FFA4F28 R11:7FFCDBE8

  LIB$VM_FREE at 15:33:46.66
  R0:FFFFFFFF R1:00000000 R2:00A1A130 R3:00B2C780 R4 :00000000 R5: 00A65778
  R6:00B2C300 R7:00B2C780 R8:7FF9CDE8 R9:7FF9DDF0 R10:7FFA4F28 R11:7FFCDBE8
  LIB$VM_FREE called with 1 arg
     1 00B2C780 => 20202020
                 =/                                                ...
  LIB$VM_FREE returning 1 arg
     1 00B2C780 => 00000000
  LIB$VM_FREE returned: 00000001 at 15:33:46.66
  R0:00000001 R1:77770000 R2:00A1A130 R3:00B2C780 R4 :00000000 R5: 00A65778
  R6:00B2C300 R7:00B2C780 R8:7FF9CDE8 R9:7FF9DDF0 R10:7FFA4F28 R11:7FFCDBE8

DECC$MAIN returning 9 args
   1 7FFCF884 => 00010830
               =/0/
   2 7AE63EC8 => 00303089
   3 7FFCF814 => 00000003
   4 7FFCF934 => 001C0048
               =/H/
   5 00000028
   6 00000000
   7 7AD49B78 => 00000001
   8 7AD49B74 => 00B2C0C0
   9 7AD49B70 => 00A9E2B0
DECC$MAIN returned: 00A9E2B0 at 15:33:46.66
R0:00A9E2B0 R1:00000001 R2:00010830 R3:7AF08EB2 R4 :7FFCF814 R5: 7FFCF934
R6:7FF9DEA7 R7:7FFA0ED0 R8:7FF9CDE8 R9:7FF9DDF0 R10:7FFA4F28 R11:7FFCDBE8

LIB$GET_FOREIGN at 15:33:46.66
R0:00000001 R1:00B3C000 R2:000106C0 R3:00070248 R4 :00070004 R5: 001262C0
R6:00090020 R7:00124B40 R8:00020000 R9:7FF9DDF0 R10:7FFA4F28 R11:7FFCDBE8
LIB$GET_FOREIGN called with 4 args
   1 7AD49A40 => 010E00FF
                 00070248 =>                                                 
   2 00000000
   3 7AD49A78 => 00000000
   4 00000000
LIB$GET_FOREIGN returning 4 args
   1 7AD49A40 => 010E00FF
                 00070248 =>                                                 
   2 00000000
   3 7AD49A78 => 00000000
   4 00000000
LIB$GET_FOREIGN returned: 00000001 at 15:33:46.66
R0:00000001 R1:00000000 R2:000106C0 R3:00070248 R4 :00070004 R5: 001262C0
R6:00090020 R7:00124B40 R8:00020000 R9:7FF9DDF0 R10:7FFA4F28 R11:7FFCDBE8

SMG$CREATE_PASTEBOARD at 15:33:46.66
R0:00000001 R1:00000000 R2:000106C0 R3:00070248 R4 :00070004 R5: 001262C0
R6:00090020 R7:00124B40 R8:00020000 R9:00090020 R10:7FFA4F28 R11:7FFCDBE8
SMG$CREATE_PASTEBOARD called with 7 args
   1 00124B40 => 00000000
   2 00000000
   3 00124B60 => 00000000
   4 00090020 => 00000050
               =/P/
   5 00020000 => 00000001
   6 7AD49A50 => 00606000
   7 00000000

  LIB$CREATE_VM_ZONE at 15:33:46.66
  R0:00000000 R1:010E0009 R2:00B9AA00 R3:00000007 R4 :00124B60 R5: 00090020
  R6:00000000 R7:00BC8024 R8:00000000 R9:00090020 R10:7FFA4F28 R11:7FFCDBE8
  LIB$CREATE_VM_ZONE called with 11 args
     1 00BC8020 => 00000000
     2 7AD496B0 => 00000001
     3 00000000
     4 7AD496B8 => 000000A1
     5 00000000
     6 00000000
     7 00000000
     8 00000000
     9 00000000
    10 00000000
    11 7AD49630 => 010E0009
                   00BA8750 => SMG$_ZONE
  LIB$CREATE_VM_ZONE returning 11 args
     1 00BC8020 => 007D0800
     2 7AD496B0 => 00000001
     3 00000000
     4 7AD496B8 => 000000A1
     5 00000000
     6 00000000
     7 00000000
     8 00000000
     9 00000000
    10 00000000
    11 7AD49630 => 010E0009
                   00BA8750 => SMG$_ZONE
  LIB$CREATE_VM_ZONE returned: 00000001 at 15:33:46.66
  R0:00000001 R1:0000C3A5 R2:00B9AA00 R3:00000007 R4 :00124B60 R5: 00090020
  R6:00000000 R7:00BC8024 R8:00000000 R9:00090020 R10:7FFA4F28 R11:7FFCDBE8

  LIB$GET_EF at 15:33:46.66
  R0:00010001 R1:00008000 R2:00B9BA80 R3:7AD49628 R4 :00BA8860 R5: 7AD49670
  R6:00010001 R7:00BC80D0 R8:00000000 R9:00BA8750 R10:7FFA4F28 R11:7FFCDBE8
  LIB$GET_EF called with 1 arg
     1 00BC80D0 => 00000000
  LIB$GET_EF returning 1 arg
     1 00BC80D0 => 0000003F
                 =/?/
  LIB$GET_EF returned: 00000001 at 15:33:46.66
  R0:00000001 R1:00008000 R2:00B9BA80 R3:7AD49628 R4 :00BA8860 R5: 7AD49670
  R6:00010001 R7:00BC80D0 R8:00000000 R9:00BA8750 R10:7FFA4F28 R11:7FFCDBE8

  LIB$GET_VM at 15:33:46.66
  R0:00128069 R1:0000014C R2:00B9A500 R3:00BC8020 R4 :00BA8860 R5: 7AD49670
  R6:00128069 R7:00BC80D0 R8:00000000 R9:00BA8750 R10:7FFA4F28 R11:7FFCDBE8
  LIB$GET_VM called with 3 args
     1 7AD492B8 => 0000014C
                 =/L/
     2 7AD49298 => 00000009
     3 00BC8020 => 007D0800
  LIB$GET_VM returning 3 args
     1 7AD492B8 => 0000014C
                 =/L/
     2 7AD49298 => 007D2808
     3 00BC8020 => 007D0800
  LIB$GET_VM returned: 00000001 at 15:33:46.66
  R0:00000001 R1:09110000 R2:00B9A500 R3:00BC8020 R4 :00BA8860 R5: 7AD49670
  R6:00128069 R7:00BC80D0 R8:00000000 R9:00BA8750 R10:7FFA4F28 R11:7FFCDBE8

  LIB$GET_VM at 15:33:46.66
  R0:00000001 R1:09110000 R2:00B9A4E0 R3:7AD493D0 R4 :00BC8020 R5: 7AD49670
  R6:00128069 R7:00BC80D0 R8:00000000 R9:00BA8750 R10:7FFA4F28 R11:7FFCDBE8
  LIB$GET_VM called with 3 args
     1 7AD49250 => 00000038
                 =/8/
     2 7AD49238 => 7AD49260
                 =/`/
     3 00BC8020 => 007D0800
  LIB$GET_VM returning 3 args
     1 7AD49250 => 00000038
                 =/8/
     2 7AD49238 => 007D2960
                 =/`)}/
     3 00BC8020 => 007D0800
  LIB$GET_VM returned: 00000001 at 15:33:46.66
  R0:00000001 R1:09110000 R2:00B9A4E0 R3:7AD493D0 R4 :00BC8020 R5: 7AD49670
  R6:00128069 R7:00BC80D0 R8:00000000 R9:00BA8750 R10:7FFA4F28 R11:7FFCDBE8

  LIB$GET_VM at 15:33:46.66
  R0:00000001 R1:09110000 R2:00B9A4E0 R3:7AD493D0 R4 :00BC8020 R5: 7AD49670
  R6:00128069 R7:00BC80D0 R8:00000000 R9:00BA8750 R10:7FFA4F28 R11:7FFCDBE8
  LIB$GET_VM called with 3 args
     1 7AD49250 => 00004380
     2 007D2968 => 00000000
     3 00BC8020 => 007D0800
  LIB$GET_VM returning 3 args
     1 7AD49250 => 00004380
     2 007D2968 => 007D29A8
     3 00BC8020 => 007D0800
  LIB$GET_VM returned: 00000001 at 15:33:46.66
  R0:00000001 R1:09110000 R2:00B9A4E0 R3:7AD493D0 R4 :00BC8020 R5: 7AD49670
  R6:00128069 R7:00BC80D0 R8:00000000 R9:00BA8750 R10:7FFA4F28 R11:7FFCDBE8

  LIB$GET_VM at 15:33:46.66
  R0:007D2960 R1:0000004A R2:00B9A4E0 R3:7AD493D0 R4 :00BC8020 R5: 0000FFFF
  R6:00128069 R7:00BC80D0 R8:00000000 R9:00BA8750 R10:7FFA4F28 R11:7FFCDBE8
  LIB$GET_VM called with 3 args
     1 7AD49250 => 0000004A
                 =/J/
     2 007D298C => 00000000
     3 00BC8020 => 007D0800
  LIB$GET_VM returning 3 args
     1 7AD49250 => 0000004A
                 =/J/
     2 007D298C => 007D6D38
                 =/8m}/
     3 00BC8020 => 007D0800
  LIB$GET_VM returned: 00000001 at 15:33:46.67
  R0:00000001 R1:09110000 R2:00B9A4E0 R3:7AD493D0 R4 :00BC8020 R5: 0000FFFF
  R6:00128069 R7:00BC80D0 R8:00000000 R9:00BA8750 R10:7FFA4F28 R11:7FFCDBE8

  LIB$GET_VM at 15:33:46.68
  R0:00000001 R1:007D2808 R2:00B9A500 R3:00BC8020 R4 :00BA8860 R5: 7AD49670
  R6:00128069 R7:00BC80D0 R8:00000000 R9:00BA8750 R10:7FFA4F28 R11:7FFCDBE8
  LIB$GET_VM called with 3 args
     1 7AD492A0 => 00000200
     2 007D2878 => 00000000
     3 00BC8020 => 007D0800
  LIB$GET_VM returning 3 args
     1 7AD492A0 => 00000200
     2 007D2878 => 007D6D90
     3 00BC8020 => 007D0800
  LIB$GET_VM returned: 00000001 at 15:33:46.68
  R0:00000001 R1:09110000 R2:00B9A500 R3:00BC8020 R4 :00BA8860 R5: 7AD49670
  R6:00128069 R7:00BC80D0 R8:00000000 R9:00BA8750 R10:7FFA4F28 R11:7FFCDBE8

  LIB$GET_VM at 15:33:46.68
  R0:007D2908 R1:007D290C R2:00B9BA80 R3:007D2808 R4 :00BA8860 R5: 7AD49670
  R6:000000FF R7:007D2908 R8:00000000 R9:00BA8750 R10:7FFA4F28 R11:7FFCDBE8
  LIB$GET_VM called with 3 args
     1 007D2908 => 000000FF
     2 007D290C => 00000000
     3 00BC8020 => 007D0800
  LIB$GET_VM returning 3 args
     1 007D2908 => 000000FF
     2 007D290C => 007D6FA0
     3 00BC8020 => 007D0800
  LIB$GET_VM returned: 00000001 at 15:33:46.68
  R0:00000001 R1:09110000 R2:00B9BA80 R3:007D2808 R4 :00BA8860 R5: 7AD49670
  R6:000000FF R7:007D2908 R8:00000000 R9:00BA8750 R10:7FFA4F28 R11:7FFCDBE8

  LIB$GET_VM at 15:33:46.68
  R0:00000000 R1:00000000 R2:00B9AA00 R3:00000007 R4 :00124B60 R5: 00090020
  R6:0000000A R7:00BC8024 R8:00000000 R9:00BA8750 R10:00000000 R11:7FFCDBE8
  LIB$GET_VM called with 3 args
     1 7AD496B0 => 0000000A
     2 007D28C0 => 00000000
     3 00BC8020 => 007D0800
  LIB$GET_VM returning 3 args
     1 7AD496B0 => 0000000A
     2 007D28C0 => 007D70B0
     3 00BC8020 => 007D0800
  LIB$GET_VM returned: 00000001 at 15:33:46.68
  R0:00000001 R1:09110000 R2:00B9AA00 R3:00000007 R4 :00124B60 R5: 00090020
  R6:0000000A R7:00BC8024 R8:00000000 R9:00BA8750 R10:00000000 R11:7FFCDBE8

SMG$CREATE_PASTEBOARD returning 7 args
   1 00124B40 => 00000000
   2 00000000
   3 00124B60 => 00000024
               =/$/
   4 00090020 => 00000050
               =/P/
   5 00020000 => 00000001
   6 7AD49A50 => 00000006
   7 00000000
SMG$CREATE_PASTEBOARD returned: 00000001 at 15:33:46.68
R0:00000001 R1:00BC8024 R2:000106C0 R3:00070248 R4 :00070004 R5: 001262C0
R6:00090020 R7:00124B40 R8:00020000 R9:00090020 R10:7FFA4F28 R11:7FFCDBE8

DECC$GETENV at 15:33:46.68
R0:00000001 R1:00BC8024 R2:000106C0 R3:00070248 R4 :00070004 R5: 001262C0
R6:00090020 R7:00124B40 R8:00020000 R9:00090020 R10:7FFA4F28 R11:7FFCDBE8
DECC$GETENV called with 1 arg
   1 00010790 => 24554644
               =/DFU$NOSMG/

  LIB$GET_SYMBOL at 15:33:46.68
  R0:00000000 R1:00000001 R2:00A27A18 R3:00010790 R4 :00000009 R5: 00000001
  R6:00000000 R7:00AFC008 R8:00020000 R9:00090020 R10:7FFA4F28 R11:7FFCDBE8
  LIB$GET_SYMBOL called with 4 args
     1 7AD492F8 => 010E0009
                   00010790 => DFU$NOSMG
     2 7AD492C8 => 010E0401
                   7AD49310 =>         D       q               °€˙˙˙˙°Đ‹    
     3 7AD49300 => 00000000
     4 00000000
  LIB$GET_SYMBOL returning 4 args
     1 7AD492F8 => 010E0009
                   00010790 => DFU$NOSMG
     2 7AD492C8 => 010E0401
                   7AD49310 =>         D       q               °€˙˙˙˙°Đ‹    
     3 7AD49300 => 00000000
     4 00000000
  LIB$GET_SYMBOL returned: 00158364 at 15:33:46.68
  R0:00158364 R1:FFFFFFFF R2:00A27A18 R3:00010790 R4 :00000009 R5: 00000001
  R6:00000000 R7:00AFC008 R8:00020000 R9:00090020 R10:7FFA4F28 R11:7FFCDBE8

DECC$GETENV returning 1 arg
   1 00010790 => 24554644
               =/DFU$NOSMG/
DECC$GETENV returned: 00000000 at 15:33:46.68
R0:00000000 R1:00000001 R2:000106C0 R3:00070248 R4 :00070004 R5: 001262C0
R6:00090020 R7:00124B40 R8:00020000 R9:00090020 R10:7FFA4F28 R11:7FFCDBE8

SMG$CREATE_VIRTUAL_KEYBOARD at 15:33:46.68
R0:00000006 R1:00000000 R2:000106C0 R3:00070248 R4 :00070004 R5: 001262C0
R6:00090020 R7:00124B40 R8:00020000 R9:00090020 R10:00124270 R11:00090080
SMG$CREATE_VIRTUAL_KEYBOARD called with 5 args
   1 00124270 => 00000000
   2 00000000
   3 00000000
   4 00000000
   5 00000000

  LIB$GET_VM at 15:33:46.68
  R0:00000001 R1:00008000 R2:00B98B18 R3:00000005 R4 :0000000C R5: 7AD495D0
  R6:00000014 R7:00BC8020 R8:00BC8018 R9:00090020 R10:00124270 R11:00090080
  LIB$GET_VM called with 3 args
     1 7AD493B8 => 00000014
     2 7AD492B8 => 020E0000
                   00000000 => 
     3 00BC8020 => 007D0800
  LIB$GET_VM returning 3 args
     1 7AD493B8 => 00000014
     2 7AD492B8 => 007D70C8
     3 00BC8020 => 007D0800
  LIB$GET_VM returned: 00000001 at 15:33:46.68
  R0:00000001 R1:09110000 R2:00B98B18 R3:00000005 R4 :0000000C R5: 7AD495D0
  R6:00000014 R7:00BC8020 R8:00BC8018 R9:00090020 R10:00124270 R11:00090080

  LIB$GET_VM at 15:33:46.68
  R0:00000001 R1:00B1E388 R2:00B98B18 R3:00000005 R4 :0000000C R5: 7AD495D0
  R6:00000014 R7:00BC8020 R8:00BC8018 R9:00090020 R10:00124270 R11:00090080
  LIB$GET_VM called with 3 args
     1 7AD493B8 => 000001C0
     2 7AD49360 => 0000000F
     3 00BC8020 => 007D0800
  LIB$GET_VM returning 3 args
     1 7AD493B8 => 000001C0
     2 7AD49360 => 007D70E8
     3 00BC8020 => 007D0800
  LIB$GET_VM returned: 00000001 at 15:33:46.68
  R0:00000001 R1:09110000 R2:00B98B18 R3:00000005 R4 :0000000C R5: 7AD495D0
  R6:00000014 R7:00BC8020 R8:00BC8018 R9:00090020 R10:00124270 R11:00090080

  LIB$GET_VM at 15:33:46.68
  R0:00000001 R1:09110000 R2:00B98B18 R3:00000005 R4 :0000000C R5: 7AD495D0
  R6:00000014 R7:00BC8020 R8:00BC8018 R9:007D7120 R10:00124270 R11:00090080
  LIB$GET_VM called with 3 args
     1 7AD493B8 => 0000000C
     2 7AD49358 => 7AD49448
                 =/H/
     3 00BC8020 => 007D0800
  LIB$GET_VM returning 3 args
     1 7AD493B8 => 0000000C
     2 7AD49358 => 007D72B8
     3 00BC8020 => 007D0800
  LIB$GET_VM returned: 00000001 at 15:33:46.68
  R0:00000001 R1:09110000 R2:00B98B18 R3:00000005 R4 :0000000C R5: 7AD495D0
  R6:00000014 R7:00BC8020 R8:00BC8018 R9:007D7120 R10:00124270 R11:00090080

  LIB$GET_EF at 15:33:46.68
  R0:00000001 R1:09110000 R2:00B98B18 R3:00000005 R4 :0000000C R5: 7AD495D0
  R6:00000014 R7:00BC8020 R8:00BC8018 R9:007D7120 R10:00124270 R11:00090080
  LIB$GET_EF called with 1 arg
     1 00BC8000 => 00000000
  LIB$GET_EF returning 1 arg
     1 00BC8000 => 0000003E
                 =/>/
  LIB$GET_EF returned: 00000001 at 15:33:46.68
  R0:00000001 R1:09110000 R2:00B98B18 R3:00000005 R4 :0000000C R5: 7AD495D0
  R6:00000014 R7:00BC8020 R8:00BC8018 R9:007D7120 R10:00124270 R11:00090080

  LIB$GET_VM at 15:33:46.68
  R0:00128069 R1:00128069 R2:00B992F0 R3:00000000 R4 :00000050 R5: 000001A0
  R6:00BA855C R7:00BC8020 R8:0000003E R9:007D7120 R10:00124270 R11:00090080
  LIB$GET_VM called with 3 args
     1 7AD49210 => 000001E8
     2 7AD491E0 => 818D55A0
     3 00BC8020 => 007D0800
  LIB$GET_VM returning 3 args
     1 7AD49210 => 000001E8
     2 7AD491E0 => 007D72D0
     3 00BC8020 => 007D0800
  LIB$GET_VM returned: 00000001 at 15:33:46.68
  R0:00000001 R1:09110000 R2:00B992F0 R3:00000000 R4 :00000050 R5: 000001A0
  R6:00BA855C R7:00BC8020 R8:0000003E R9:007D7120 R10:00124270 R11:00090080

  LIB$GET_VM at 15:33:46.68
  R0:00000001 R1:007D72D0 R2:00B992F0 R3:00000000 R4 :00000000 R5: 00000050
  R6:00BA8330 R7:00BC8020 R8:0000003E R9:007D7120 R10:00124270 R11:00090080
  LIB$GET_VM called with 3 args
     1 7AD49208 => 000007A0
     2 7AD491E8 => 00000000
     3 00BC8020 => 007D0800
  LIB$GET_VM returning 3 args
     1 7AD49208 => 000007A0
     2 7AD491E8 => 007D74C8
     3 00BC8020 => 007D0800
  LIB$GET_VM returned: 00000001 at 15:33:46.68
  R0:00000001 R1:09110000 R2:00B992F0 R3:00000000 R4 :00000000 R5: 00000050
  R6:00BA8330 R7:00BC8020 R8:0000003E R9:007D7120 R10:00124270 R11:00090080

  LIB$GET_VM at 15:33:46.68
  R0:00000001 R1:00000000 R2:00B98B18 R3:00000000 R4 :00000050 R5: 000000A0
  R6:00000014 R7:00BC8020 R8:0000003E R9:007D7120 R10:00124270 R11:00090080
  LIB$GET_VM called with 3 args
     1 7AD493B8 => 000000A0
     2 007D729C => 00000000
     3 00BC8020 => 007D0800
  LIB$GET_VM returning 3 args
     1 7AD493B8 => 000000A0
     2 007D729C => 007D7C78
                 =/x|}/
     3 00BC8020 => 007D0800
  LIB$GET_VM returned: 00000001 at 15:33:46.68
  R0:00000001 R1:09110000 R2:00B98B18 R3:00000000 R4 :00000050 R5: 000000A0
  R6:00000014 R7:00BC8020 R8:0000003E R9:007D7120 R10:00124270 R11:00090080

SMG$CREATE_VIRTUAL_KEYBOARD returning 5 args
   1 00124270 => 007D7120
               =/ q}/
   2 00000000
   3 00000000
   4 00000000
   5 00000000
SMG$CREATE_VIRTUAL_KEYBOARD returned: 00000001 at 15:33:46.68
R0:00000001 R1:00008000 R2:000106C0 R3:00070248 R4 :00070004 R5: 001262C0
R6:00090020 R7:00124B40 R8:00020000 R9:00090020 R10:00124270 R11:00090080

SMG$ERASE_PASTEBOARD at 15:33:46.68
R0:00000001 R1:00000001 R2:000106C0 R3:00070248 R4 :00070004 R5: 001262C0
R6:00090020 R7:00124B40 R8:00020000 R9:00090020 R10:00124270 R11:00090080
SMG$ERASE_PASTEBOARD called with 1 arg
   1 00124B40 => 00000000
SMG$ERASE_PASTEBOARD returning 1 arg
   1 00124B40 => 00000000
SMG$ERASE_PASTEBOARD returned: 00000001 at 15:33:46.68
R0:00000001 R1:FFFFF9F8 R2:000106C0 R3:00070248 R4 :00070004 R5: 001262C0
R6:00090020 R7:00124B40 R8:00020000 R9:00090020 R10:00124270 R11:00090080

SMG$CREATE_KEY_TABLE at 15:33:46.68
R0:00000003 R1:FFFFF9F8 R2:00010530 R3:00070000 R4 :00070004 R5: 001262C0
R6:00090020 R7:00124B40 R8:00020000 R9:00090020 R10:00124270 R11:00090080
SMG$CREATE_KEY_TABLE called with 1 arg
   1 00070000 => 00000000

  LIB$GET_VM at 15:33:46.68
  R0:00BC8020 R1:007D0800 R2:00B99068 R3:00070000 R4 :00070004 R5: 001262C0
  R6:00090020 R7:00124B40 R8:00020000 R9:00090020 R10:00124270 R11:00090080
  LIB$GET_VM called with 3 args
     1 7AD496B0 => 0000005E
                 =/^/
     2 00070000 => 00000000
     3 00BC8020 => 007D0800
  LIB$GET_VM returning 3 args
     1 7AD496B0 => 0000005E
                 =/^/
     2 00070000 => 007D7D28
                 =/(}}/
     3 00BC8020 => 007D0800
  LIB$GET_VM returned: 00000001 at 15:33:46.68
  R0:00000001 R1:09110000 R2:00B99068 R3:00070000 R4 :00070004 R5: 001262C0
  R6:00090020 R7:00124B40 R8:00020000 R9:00090020 R10:00124270 R11:00090080

SMG$CREATE_KEY_TABLE returning 1 arg
   1 00070000 => 007D7D28
               =/(}}/
SMG$CREATE_KEY_TABLE returned: 00000001 at 15:33:46.68
R0:00000001 R1:007D7D28 R2:00010530 R3:00070000 R4 :00070004 R5: 001262C0
R6:00090020 R7:00124B40 R8:00020000 R9:00090020 R10:00124270 R11:00090080

SMG$ADD_KEY_DEF at 15:33:46.68
R0:00000001 R1:007D7D28 R2:00010530 R3:00070000 R4 :00070004 R5: 001262C0
R6:00090020 R7:00124B40 R8:00020000 R9:00090020 R10:00124270 R11:00090080
SMG$ADD_KEY_DEF called with 6 args
   1 00070000 => 007D7D28
               =/(}}/
   2 7AD49998 => 010E0002
                 00010570 => DO
   3 00000000
   4 7AD499A0 => 00000003
   5 7AD49998 => 010E0002
                 00010570 => DO
   6 00000000

  LIB$INSERT_TREE at 15:33:46.68
  R0:00000001 R1:007D7D6C R2:00B98D28 R3:00000006 R4 :007D7D28 R5: 001262C0
  R6:00090020 R7:00124B40 R8:00020000 R9:00090020 R10:00124270 R11:00090080
  LIB$INSERT_TREE called with 7 args
     1 007D7D28 => 00000000
     2 007D7D58 => 010E000A
                   007D7D64 => DEFAULT  (
     3 7AD49668 => 00000000
     4 00B98F60 => 00183089
     5 00B99028 => 00283089
     6 7AD49658 => 00000000
     7 00000000

    LIB$GET_VM at 15:33:46.68
    R0:0045C834 R1:00000054 R2:004C6FB0 R3:004C6F78 R4 :00000000 R5: 00000000
    R6:00158001 R7:7AD49658 R8:00B99028 R9:00B98F60 R10:007D7D58 R11:00000000
    LIB$GET_VM called with 3 args
       1 7AD49250 => 00000054
                   =/T/
       2 7AD49270 => 00000000
       3 00BC8020 => 007D0800
    LIB$GET_VM returning 3 args
       1 7AD49250 => 00000054
                   =/T/
       2 7AD49270 => 007D7D98
       3 00BC8020 => 007D0800
    LIB$GET_VM returned: 00000001 at 15:33:46.68
    R0:00000001 R1:09110000 R2:004C6FB0 R3:004C6F78 R4 :00000000 R5: 00000000
    R6:00158001 R7:7AD49658 R8:00B99028 R9:00B98F60 R10:007D7D58 R11:00000000

  LIB$INSERT_TREE returning 7 args
     1 007D7D28 => 007D7D98
     2 007D7D58 => 010E000A
                   007D7D64 => DEFAULT  (
     3 7AD49668 => 00000000
     4 00B98F60 => 00183089
     5 00B99028 => 00283089
     6 7AD49658 => 007D7D98
     7 00000000
  LIB$INSERT_TREE returned: 00158001 at 15:33:46.68
  R0:00158001 R1:00158214 R2:00B98D28 R3:00000006 R4 :007D7D28 R5: 001262C0
  R6:00090020 R7:00124B40 R8:00020000 R9:00090020 R10:00124270 R11:00090080

  LIB$SCOPY_R_DX at 15:33:46.68
  R0:00128412 R1:007D7D98 R2:00B98D28 R3:00000006 R4 :007D7D28 R5: 007D7D98
  R6:00090020 R7:00124B40 R8:00020000 R9:00090020 R10:00124270 R11:00090080
  LIB$SCOPY_R_DX called with 3 args
     1 7AD49670 => 0000000A
     2 007D7D64 => 41464544
                 =/DEFAULT/
     3 007D7DA4 => 020E0000
                   00000000 => 
  LIB$SCOPY_R_DX returning 3 args
     1 7AD49670 => 0000000A
     2 007D7D64 => 41464544
                 =/DEFAULT/
     3 007D7DA4 => 020E000A
                   007CED2C => DEFAULT  (
  LIB$SCOPY_R_DX returned: 00000001 at 15:33:46.68
  R0:00000001 R1:FFFFFFFF R2:00B98D28 R3:00000006 R4 :007D7D28 R5: 007D7D98
  R6:00090020 R7:00124B40 R8:00020000 R9:00090020 R10:00124270 R11:00090080

…
---Many lines omitted---
…
DECC$GXVSPRINTF at 15:33:46.96
R0:00000031 R1:7AD49998 R2:00010EC0 R3:00124930 R4 :00070004 R5: 001262C0
R6:00090020 R7:00124B40 R8:00020000 R9:00090020 R10:00124270 R11:00000001
DECC$GXVSPRINTF called with 3 args
   1 00124930 => 20202020
               =/     UNDELETE   : Recover deleted files/
   2 00013D78 => 20202020
               =/     VERIFY     : Check and repair disk structur...
   3 7AD499B0 => 00000004
DECC$GXVSPRINTF returning 3 args
   1 00124930 => 20202020
               =/     VERIFY     : Check and repair disk structur...
   2 00013D78 => 20202020
               =/     VERIFY     : Check and repair disk structur...
   3 7AD499B0 => 00000004
DECC$GXVSPRINTF returned: 00000031 at 15:33:46.96
R0:00000031 R1:00000001 R2:00010EC0 R3:00124930 R4 :00070004 R5: 001262C0
R6:00090020 R7:00124B40 R8:00020000 R9:00090020 R10:00124270 R11:00000001

DECC$STRLEN at 15:33:46.96
R0:00000001 R1:00000001 R2:00010EC0 R3:00124930 R4 :00070004 R5: 001262C0
R6:00090020 R7:00124B40 R8:00020000 R9:00090020 R10:00124270 R11:00000001
DECC$STRLEN called with 1 arg
   1 00124930 => 20202020
               =/     VERIFY     : Check and repair disk structur...
DECC$STRLEN returning 1 arg
   1 00124930 => 20202020
               =/     VERIFY     : Check and repair disk structur...
DECC$STRLEN returned: 00000031 at 15:33:46.96
R0:00000031 R1:00000001 R2:00010EC0 R3:00124930 R4 :00070004 R5: 001262C0
R6:00090020 R7:00124B40 R8:00020000 R9:00090020 R10:00124270 R11:00000001

SMG$PUT_LINE at 15:33:46.96
R0:00000001 R1:010E01FF R2:00010EC0 R3:00124930 R4 :00070004 R5: 001262C0
R6:00090020 R7:00124B40 R8:00020000 R9:00090020 R10:00124270 R11:00000001
SMG$PUT_LINE called with 8 args
   1 00090080 => 007D80F8
   2 7AD49968 => 010E0031
                 00124930 =>      VERIFY     : Check and repair disk structur
   3 00000000
   4 00000000
   5 00000000
   6 000201C8 => 00000001
   7 00000000
   8 00000000

  LIB$SCANC at 15:33:46.96
  R0:00000000 R1:010E0031 R2:00B99660 R3:00000007 R4 :007D80F8 R5: 00000000
  R6:00000031 R7:00124930 R8:00000000 R9:00000000 R10:00000000 R11:00000000
  LIB$SCANC called with 3 args
     1 7AD49520 => 010E0031
                   00124930 =>      VERIFY     : Check and repair disk structur
     2 00BA8594 => 01010101
     3 00BA8590 => 000000FF
  LIB$SCANC returning 3 args
     1 7AD49520 => 010E0031
                   00124930 =>      VERIFY     : Check and repair disk structur
     2 00BA8594 => 01010101
     3 00BA8590 => 000000FF
  LIB$SCANC returned: 00000000 at 15:33:46.96
  R0:00000000 R1:00124961 R2:00B99660 R3:00000007 R4 :007D80F8 R5: 00000000
  R6:00000031 R7:00124930 R8:00000000 R9:00000000 R10:00000000 R11:00000000

SMG$PUT_LINE returning 8 args
   1 00090080 => 007D80F8
   2 7AD49968 => 010E0031
                 00124930 =>      VERIFY     : Check and repair disk structur
   3 00000000
   4 00000000
   5 00000000
   6 000201C8 => 00000001
   7 00000000
   8 00000000
SMG$PUT_LINE returned: 00000001 at 15:33:46.96
R0:00000001 R1:00000000 R2:00010EC0 R3:00124930 R4 :00070004 R5: 001262C0
R6:00090020 R7:00124B40 R8:00020000 R9:00090020 R10:00124270 R11:00000001

SMG$END_PASTEBOARD_UPDATE at 15:33:46.96
R0:00000000 R1:000900F0 R2:000106C0 R3:00070248 R4 :00070004 R5: 001262C0
R6:00090020 R7:00124B40 R8:00020000 R9:00090020 R10:00124270 R11:00000001
SMG$END_PASTEBOARD_UPDATE called with 1 arg
   1 00124B40 => 00000000
SMG$END_PASTEBOARD_UPDATE returning 1 arg
   1 00124B40 => 00000000
SMG$END_PASTEBOARD_UPDATE returned: 00000001 at 15:33:46.97
R0:00000001 R1:00000001 R2:000106C0 R3:00070248 R4 :00070004 R5: 001262C0
R6:00090020 R7:00124B40 R8:00020000 R9:00090020 R10:00124270 R11:00000001

DECC$GETENV at 15:33:46.97
R0:00000001 R1:00000001 R2:000106C0 R3:00070248 R4 :00070004 R5: 001262C0
R6:00090020 R7:00124B40 R8:00020000 R9:00090020 R10:00124270 R11:00126380
DECC$GETENV called with 1 arg
   1 000105B0 => 24554644
               =/DFU$TRACE/

  LIB$GET_SYMBOL at 15:33:46.97
  R0:00000000 R1:00000001 R2:00A27A18 R3:000105B0 R4 :00000009 R5: 00000001
  R6:00000000 R7:00AFC008 R8:00020000 R9:00090020 R10:00124270 R11:00126380
  LIB$GET_SYMBOL called with 4 args
     1 7AD492F8 => 010E0009
                   000105B0 => DFU$TRACE
     2 7AD492C8 => 010E0401
                   7AD49310 =>         a       q               °€˙˙˙˙°Đ‹    
     3 7AD49300 => 00000000
     4 00000000
  LIB$GET_SYMBOL returning 4 args
     1 7AD492F8 => 010E0009
                   000105B0 => DFU$TRACE
     2 7AD492C8 => 010E0401
                   7AD49310 =>         a       q               °€˙˙˙˙°Đ‹    
     3 7AD49300 => 00000000
     4 00000000
  LIB$GET_SYMBOL returned: 00158364 at 15:33:46.97
  R0:00158364 R1:FFFFFFFF R2:00A27A18 R3:000105B0 R4 :00000009 R5: 00000001
  R6:00000000 R7:00AFC008 R8:00020000 R9:00090020 R10:00124270 R11:00126380

DECC$GETENV returning 1 arg
   1 000105B0 => 24554644
               =/DFU$TRACE/
DECC$GETENV returned: 00000000 at 15:33:46.97
R0:00000000 R1:00000001 R2:000106C0 R3:00070248 R4 :00070004 R5: 001262C0
R6:00090020 R7:00124B40 R8:00020000 R9:00090020 R10:00124270 R11:00126380

LIB$CREATE_VM_ZONE at 15:33:46.97
R0:00126400 R1:000204A0 R2:00010E00 R3:00070248 R4 :00070004 R5: 001262C0
R6:00090020 R7:00124B40 R8:00020000 R9:00090020 R10:00124270 R11:00126380
LIB$CREATE_VM_ZONE called with 13 args
   1 000204A0 => 00000000
   2 7AD499A8 => 00000002
   3 7AD499A0 => 00000080
   4 7AD49998 => 00000028
               =/(/
   5 7AD49990 => 00000008
   6 00000000
   7 00000000
   8 00000000
   9 00000000
  10 00000000
  11 7AD49988 => 010E0008
                 00010E30 => dfu_zone
  12 00000000
  13 00000000
LIB$CREATE_VM_ZONE returning 13 args
   1 000204A0 => 007D0858
               =/X/
   2 7AD499A8 => 00000002
   3 7AD499A0 => 00000080
   4 7AD49998 => 00000028
               =/(/
   5 7AD49990 => 00000008
   6 00000000
   7 00000000
   8 00000000
   9 00000000
  10 00000000
  11 7AD49988 => 010E0008
                 00010E30 => dfu_zone
  12 00000000
  13 00000000
LIB$CREATE_VM_ZONE returned: 00000001 at 15:33:46.97
R0:00000001 R1:0000C3A5 R2:00010E00 R3:00070248 R4 :00070004 R5: 001262C0
R6:00090020 R7:00124B40 R8:00020000 R9:00090020 R10:00124270 R11:00126380

DECC$GETENV at 15:33:46.97
R0:00000000 R1:000001D5 R2:000106C0 R3:00070248 R4 :00070004 R5: 001262C0
R6:00090020 R7:00124B40 R8:00020000 R9:00090020 R10:00124270 R11:00126380
DECC$GETENV called with 1 arg
   1 00013D40 => 24554644
               =/DFU$DISABLE_CHECK/

  LIB$GET_SYMBOL at 15:33:46.97
  R0:00000000 R1:00000001 R2:00A27A18 R3:00013D40 R4 :00000011 R5: 00000001
  R6:00000000 R7:00AFC008 R8:00020000 R9:00090020 R10:00124270 R11:00126380
  LIB$GET_SYMBOL called with 4 args
     1 7AD492F8 => 010E0011
                   00013D40 => DFU$DISABLE_CHECK
     2 7AD492C8 => 010E0401
                   7AD49310 =>         a       q               °€˙˙˙˙°Đ‹    
     3 7AD49300 => 00000000
     4 00000000
  LIB$GET_SYMBOL returning 4 args
     1 7AD492F8 => 010E0011
                   00013D40 => DFU$DISABLE_CHECK
     2 7AD492C8 => 010E0401
                   7AD49310 =>         a       q               °€˙˙˙˙°Đ‹    
     3 7AD49300 => 00000000
     4 00000000
  LIB$GET_SYMBOL returned: 00158364 at 15:33:46.97
  R0:00158364 R1:FFFFFFFF R2:00A27A18 R3:00013D40 R4 :00000011 R5: 00000001
  R6:00000000 R7:00AFC008 R8:00020000 R9:00090020 R10:00124270 R11:00126380

DECC$GETENV returning 1 arg
   1 00013D40 => 24554644
               =/DFU$DISABLE_CHECK/
DECC$GETENV returned: 00000000 at 15:33:46.97
R0:00000000 R1:00000001 R2:000106C0 R3:00070248 R4 :00070004 R5: 001262C0
R6:00090020 R7:00124B40 R8:00020000 R9:00090020 R10:00124270 R11:00126380

LIB$GET_VM at 15:33:46.97
R0:00000001 R1:001263F0 R2:00010DC0 R3:7AD49A70 R4 :00070140 R5: 00070004
R6:00000005 R7:00124B40 R8:00020000 R9:00090020 R10:00124270 R11:00126380
LIB$GET_VM called with 3 args
   1 7AD498E8 => 00000028
               =/(/
   2 7AD49968 => 00000000
   3 000204A0 => 007D0858
               =/X/
LIB$GET_VM returning 3 args
   1 7AD498E8 => 00000028
               =/(/
   2 7AD49968 => 007DA800
   3 000204A0 => 007D0858
               =/X/
LIB$GET_VM returned: 00000001 at 15:33:46.97
R0:00000001 R1:01140000 R2:00010DC0 R3:7AD49A70 R4 :00070140 R5: 00070004
R6:00000005 R7:00124B40 R8:00020000 R9:00090020 R10:00124270 R11:00126380

DECC$STRNCMP at 15:33:46.98
R0:00000001 R1:7AD40008 R2:00010468 R3:7AD49A70 R4 :00070140 R5: 00070004
R6:00000005 R7:007DA800 R8:00000001 R9:00000000 R10:FFFFFFFF R11:00126380
DECC$STRNCMP called with 3 args
   1 00070140 => 4C4C4947
               =/GILLINGS                                        ...
   2 000104E0 => 5F554644
               =/DFU_ALLPRIV/
   3 00000008
DECC$STRNCMP returning 3 args
   1 00070140 => 4C4C4947
               =/GILLINGS                                        ...
   2 000104E0 => 5F554644
               =/DFU_ALLPRIV/
   3 00000008
DECC$STRNCMP returned: 00000001 at 15:33:46.98
R0:00000001 R1:00000000 R2:00010468 R3:7AD49A70 R4 :00070140 R5: 00070004
R6:00000005 R7:007DA800 R8:00000001 R9:00000000 R10:FFFFFFFF R11:00126380

DECC$STRNCMP at 15:33:46.98
R0:00000001 R1:7AD4000B R2:00010468 R3:7AD49A70 R4 :00070140 R5: 00070004
R6:00000005 R7:007DA808 R8:00000002 R9:00000000 R10:FFFFFFFF R11:00126380
DECC$STRNCMP called with 3 args
   1 00070140 => 45544E49
               =/INTERACTIVE                                     ...
   2 000104E0 => 5F554644
               =/DFU_ALLPRIV/
   3 0000000B
DECC$STRNCMP returning 3 args
   1 00070140 => 45544E49
               =/INTERACTIVE                                     ...
   2 000104E0 => 5F554644
               =/DFU_ALLPRIV/
   3 0000000B
DECC$STRNCMP returned: 00000001 at 15:33:46.98
R0:00000001 R1:00000000 R2:00010468 R3:7AD49A70 R4 :00070140 R5: 00070004
R6:00000005 R7:007DA808 R8:00000002 R9:00000000 R10:FFFFFFFF R11:00126380

DECC$STRNCMP at 15:33:46.98
R0:00000001 R1:7AD40005 R2:00010468 R3:7AD49A70 R4 :00070140 R5: 00070004
R6:00000005 R7:007DA810 R8:00000003 R9:00000000 R10:FFFFFFFF R11:00126380
DECC$STRNCMP called with 3 args
   1 00070140 => 41434F4C
               =/LOCAL                                           ...
   2 000104E0 => 5F554644
               =/DFU_ALLPRIV/
   3 00000005
DECC$STRNCMP returning 3 args
   1 00070140 => 41434F4C
               =/LOCAL                                           ...
   2 000104E0 => 5F554644
               =/DFU_ALLPRIV/
   3 00000005
DECC$STRNCMP returned: 00000008 at 15:33:46.98
R0:00000008 R1:00000007 R2:00010468 R3:7AD49A70 R4 :00070140 R5: 00070004
R6:00000005 R7:007DA810 R8:00000003 R9:00000000 R10:FFFFFFFF R11:00126380

DECC$STRNCMP at 15:33:46.98
R0:00002224 R1:7AD40005 R2:00010468 R3:7AD49A70 R4 :00070140 R5: 00070004
R6:00000005 R7:007DA818 R8:00000004 R9:00000000 R10:FFFFFFFF R11:00126380
DECC$STRNCMP called with 3 args
   1 00070140 => 41434F4C
               =/LOCAL                                           ...
   2 000104E0 => 5F554644
               =/DFU_ALLPRIV/
   3 00000005
DECC$STRNCMP returning 3 args
   1 00070140 => 41434F4C
               =/LOCAL                                           ...
   2 000104E0 => 5F554644
               =/DFU_ALLPRIV/
   3 00000005
DECC$STRNCMP returned: 00000008 at 15:33:46.98
R0:00000008 R1:00000007 R2:00010468 R3:7AD49A70 R4 :00070140 R5: 00070004
R6:00000005 R7:007DA818 R8:00000004 R9:00000000 R10:FFFFFFFF R11:00126380

DECC$STRNCMP at 15:33:46.98
R0:00002224 R1:7AD40005 R2:00010468 R3:7AD49A70 R4 :00070140 R5: 00070004
R6:00000005 R7:007DA820 R8:00000005 R9:00000000 R10:FFFFFFFF R11:00126380
DECC$STRNCMP called with 3 args
   1 00070140 => 41434F4C
               =/LOCAL                                           ...
   2 000104E0 => 5F554644
               =/DFU_ALLPRIV/
   3 00000005
DECC$STRNCMP returning 3 args
   1 00070140 => 41434F4C
               =/LOCAL                                           ...
   2 000104E0 => 5F554644
               =/DFU_ALLPRIV/
   3 00000005
DECC$STRNCMP returned: 00000008 at 15:33:46.98
R0:00000008 R1:00000007 R2:00010468 R3:7AD49A70 R4 :00070140 R5: 00070004
R6:00000005 R7:007DA820 R8:0000000