!TITLE Appendix A1. Loader Table Structure !KEY The loader tables are held in a file, T#LOAD, which is created at subsystem start up time. This file is initially 3 pages long but has the capability to expand up to a limit of 1Mb or the maximum file size permitted in the process, whichever is the smaller. After 32 bytes of header information, the remainder of the first page is used for references, the second for permanently loaded entries and the third for temporarily loaded entries. The start address and length of each table is held in a record array SSLOADTAB. There are certain common features in the way each table operates. The first 1008 bytes are used as 252 integers numbered from 0 to 251. These function as listheads from which chains of records are attached. Which particular listhead a given entry or reference is chained to is determined by hashing the entry or reference name. The hash constant for the hashing function is the prime number 251 so that the result of the hash function is an integer in the range 0 - 250. Listhead 251 is not used in the reference table but is used in the entries tables to hold a chain of filenames. This is described at greater length below. Within each table, including the listheads, all links and pointer fields are relative to the start of that table i.e. listhead 0 has relative address 0. Each table is therefore entirely self contained and is independent of the actual address of the start of that table. Thus a table can be moved about as a unit, the only updating required is to the SSLOADTAB record array. This design makes it easy to expand tables when circumstances demand. For example, suppose the permanent entries table, table 2, is full but we need to add more entries to it - a common requirement during a load. The procedure is as follows: CHANGEFILESIZE is called to extend T#LOAD by 1 Epage. Table 3, the table of temporary entries, is moved 1 Epage up the VM and SSLOADTAB(3)_START updated. The page vacated by table 3, which is at the end of table 2, is filled with a 'not used' pattern and assigned to table 2 by incrementing SSLOADTAB(2)_LEN and the load can continue. Each table can expand itself in a similar way as circumstances dictate until T#LOAD reaches the file size limit of the process or 1 Mb, whichever is the smaller. Although there are two tables of entries they should really be regarded as one since they have exactly the same table structure, the difference lying in how they are administered. We are therefore describing two types of table; reference and entry. An entry or reference within each table is uniquely identified by its name and its type, e.g. we could have a code entry called TRIAL and a data entry called TRIAL in the entry tables. These then are the common features of each type of table but to proceed farther it is now necessary to look at each type separately. ! This integer is assigned in the following manner: 2**31 -> if set then the reference is a common reference 2**30 -> if set then the reference is a dynamic reference 2**29 -> if set then the reference is an unsatisfied reference 2**28 - 2**24 -> load level at which the reference was generated 2**23 - 2**0 -> If this is a data reference then the length of the data item else 0 DR1 -> The address of the reference in the gla ADYNR/OFFSET -> If the reference is a dynamic or unresolved code or data reference then the address of the escape table else if the reference is a single word reference then the value of the offset to the address of the entry point else 0. LINK -> Offset of the next information record in the chain relative to the start of the table or -1 if this is the last record in the chain. !> ! name of the reference double word aligned TYPE -> This integer is assigned as follows: 2**31 -> If set then at least one of the information records attached to this basic record is a common reference. 2**30 -> if set then at least one of the information records attached to this basic record is a dynamic reference. 2**29 -> If set then at least one of the information records attached to this basic record is unsatisfied. 2**28 -> If set then ALL the unsatisfied references on the information record chain have been made unresolved; i.e. a complete search for an entry to satisfy this NAME has failed but LOADPARM(LET) was set. Note that this bit and the 2**29 bit cannot both be set. 2**27 - 2**8 -> free 2**7 - 2**0 -> Reference type, 1=data, 2=code, 3=single word i.e code!data FIRST -> Offset relative to the start of the reference table of the first information record associated with this basic record. LAST -> Offset relative to the start of the reference table of the last information record associated with this basic record. LINK -> Offset of the next basic record chained to this listhead or -1 if this is the last record in the chain. The design of the basic record is geared to finding out what we need to know about the information records during loading without the overhead of chaining through them. Thus during a cascade load we can find the next reference that we should search for by inspecting the basic records for ones which have bit 2**29 set in the TYPE field. Similarly when adding a new information record we wish to go directly to the last in the chain rather than follow the chain to the end. More subtly if a reference is currently unresolved then we don't want to add a new unsatisfied reference to the table as this would trigger off a complete search which was bound to fail anyway; we want to make it unresolved right away. !> ! !> ! Name of the entry point single word aligned TYPE -> This integer is assigned as follows: 2**31 - If set then NAME is a main entry point 2**30 - If set then this is a pseudo data entry created by DATASPACE 2**29 - If set then NAME is an alias of some other entry point which is already loaded i.e. created by ALIASENTRY 2**28 - 2**8 Free 2**7 - 2**0 The entry type; 1=data, 2=code (4=macro - not fully implemented as yet) DR0 -> If NAME is a code entry then an appropriate 2900 descriptor else if NAME is a data entry then the length of the data area in BYTES. DR1 -> Address of the entry point LINK -> Offset of the next entry record chained to this listhead or -1 if the record is the chain terminator. However, as well as the entry points from an object file it is also desirable to store other relevant information at the same time. For instance, it may be necessary to create a T#CODE file or a T#GLA file or both. These must be destroyed when the original object file is unloaded. Equally it turns out to be extremely advantageous in diagnosing problems with mismatching data reference/data entry lengths to store the range of gla (and initialised stack, if any) regardless of whether a T#GLA file has been created or not. To achieve these aims, then, after adding the entry points, we add a series of filename records - one for the object file itself and one for each of the other useful pieces of information that we need. In the worst case, therefore, there could be 4 filename records associated with an object file; the object filename, a record describing the gla used by this object file (which would have a T#GLA filename in its NAME field if one had been created or +GL if it hadn't), a record describing its range of initialised stack (which would have +IS in its NAME field) and a T#CODE record. It is not sensible to hash these filename records, instead they are all chained off the extra listhead, listhead 251. This is convenient for providing information to the user and vital in finding out quickly which files to unload at unload time. The information we want to store in a filename record depends on the type of file. The loader recognises four different types - object files, T#CODE files, T#GLA files and character or store mapped files used by DATASPACE. Filename records are the same structure as other entry records; a word aligned name string followed by four integers. We deal with each type in turn. ! Full EMAS 2900 filename TYPE -> 0 MAINEP -> If the object file has one or more main entry points then the address of the first main entry point encountered else 0 DUM1 -> 0 (not used) LINK -> Offset of the next filename record or -1 if the last in the chain. !> ! EMAS 2900 filename i.e. no username TYPE -> 0 DUM2 -> 0 (not used) DUM3 -> 0 (not used) LINK -> Offset of next filename record or -1 if the last in the chain !> ! EMAS 2900 filename i.e. no username/+GL/+IS TYPE -> 0 GLAFROM -> Address of first byte of gla/gla/initialised stack in T#GLA/T#UGLA or T#BGLA/T#USTK GLATO -> Address of last byte of gla/gla/initialised stack in T#GLA/T#UGLA or T#BGLA/T#USTK LINK -> Offset of next filename record or -1 if the last in the chain. !> ! Full EMAS 2900 filename TYPE -> X'40000000' USECOUNT -> Number of separate DATASPACE entry points defined in NAME ACCESSMODE -> Connect mode of NAME, i.e. 1=R, 3=W, 11=WS LINK -> Offset of next filename record or -1 if the last in the chain. !>