NAME LIT - linkable and executable format used by TTOOLS SYNOPSIS #include <expr.h> #include <litio.h> GENERAL VIEW LIT format file consists of several areas. The nomencla- ture of areas for linkable (object) and loadable files is different. Linkable file contains the following areas: NAMETABLE, NEEDS, SEGMENTS, DEFINITIONS, and (optional) STABS. A loadable file only contains the SEGMENTS and (optional) STABS areas. At the end of every area there is a marker containing the area identification and size in bytes. Markers have a fixed size (LIT_MARKER_SIZE), which makes it possible to seek to the beginning of any area within the file without having to read all preceding areas, by following the chain of markers starting from the end of the file. Areas consists of records, which in turn consist of basic objects. The following sections describe the records and objects in detail. BASIC OBJECTS The basic structural unit of the file larger than a mere byte is a number, a 32-bit integer specially encoded to save space. The number encoding method is borrowed from the TCOFF object file file format [1]. Numbers in the range [0..240] are represented by a single byte of that value. Larger values may be encoded as 8-, 16-, or 32-bit numbers, stored plain in little-endian order, prefixed by a byte of 251, 252, or 253 respec- tively. Finally, effective encoding of negative numbers is achieved using an additional prefix byte of 255, which tells that the following number should be bitwise-inverted to get the encoded value: number: (byte) value | (byte) 251 (byte) value | (byte) 252 (byte) lsb (byte) msb | (byte) 253 (byte) lsb (byte) b2 (byte) b3 (byte) msb | (byte) 255 (number) ~value Another simple object is a string, stored as a byte sequence with the length number prepended: string: (number) length (byte) byte1 (byte) byte2 ... The most complex basic object in the LIT format is expres- sion, which is an unevaluated arithmetic expression in reverse polish notation. Expressions are composed of leaf expressions and operators. The possible types of leaf expressions are: CONST self-explanatory, stored as a single number; RANGE represent an interval of possible values. Stored as a pair of numbers, lower boundary first, higher boundary next; NAME one of the names from the file's nametable. Stored as a single number, the nametable index; ELEMENT refers to the size of one of the elements in the internal representation of the program. Stored as a single number, the ordinal number of the element in this file; ELSUM represents a sum of a number of ELEMENT expres- sions. Although superfluous at the first sight, expressions of this type allow to save both space and CPU time requred for expression reduction. Stored as a sequence of numbers - ordinal numbers of sum member ELEMENTs, terminated with a number of -1. The set of operators used in expressions is borrowed from C. Every leaf expression type, as well as every operator, is assigned a unique tag; see shared/expr.h for the numeric values of the tags and more details about expres- sions. The end of expression is marked with a LIT_EXPR_END byte. expr: (subexpr) the_expr (byte) LIT_EXPR_END subexpr: leaf_expr | (subexpr) arg (unary_tag) op | (subexpr) larg (subexpr) rarg (binary_tag) op ; leaf_expression: (number) EXPR_CONST (number) const_value | (number) EXPR_RANGE (number) lo (number) hi | (number) EXPR_NAME (number) nametable_index | (number) EXPR_ELEMENT (number) element_index | (number) EXPR_ELSUM (number) element_index1 (number) element_index2 ... (number) -1 unary_tag: (number) EXPR_NEG /* - */ | (number) EXPR_NOT /* ! */ | (number) EXPR_COMPL /* ~ */ ; binary_tag: (number) EXPR_MINUS /* - */ | (number) EXPR_PLUS /* + */ | (number) EXPR_LSH /* << */ | (number) EXPR_RSH /* >> */ | (number) EXPR_MUL /* * */ | (number) EXPR_DIV /* / */ | (number) EXPR_REM /* % */ | (number) EXPR_AND /* & */ | (number) EXPR_XOR /* ^ */ | (number) EXPR_OR /* | */ | (number) EXPR_LT /* < */ | (number) EXPR_LE /* <= */ | (number) EXPR_GT /* > */ | (number) EXPR_GE /* >= */ | (number) EXPR_EQ /* == */ | (number) EXPR_NE /* != */ | (number) EXPR_ANDAND /* && */ | (number) EXPR_OROR /* || */ | (number) EXPR_QUEST /* ? */ | (number) EXPR_COLON /* : */ ; RECORDS LIT file areas consist of records. Every record starts with a record tag number. Positive record tags introduce BLOCK records, zero tag is for DUMMY record, other records use negative tags. NAMETABLE AREA Nametable area consists of NAME type records, each con- taining name identifier and a flag word. NAME: (number) LIT_NAME (string) id (number) flags The flag word may contain the following flags: LIT_NAME_DEFINED says that this name is defined in this file: either there is a fragment with this name in the SEGMENTS area, or a definition for this name is found in the DEFINITIONS area; LIT_NAME_FRAGMENT says that a fragment with this name is defined in this file; LIT_NAME_COMMON says that this is a common name, declared with the .comm in the assembly language source. NEEDS AREA NEEDS area consists of NEED type records. Every NEED record contains a need list for certain name. The list consists of numbers - nametable indices, terminated with the number of -1. NEED: (number) LIT_NEED (number) name (number) need1 (number) need2 ... (number) -1 SEGMENTS AREA The SEGMENTS area is the main area of the file. In fact, its contents is a file version of the internal representa- tion of the program used in ast and lit. Unlike other areas, it consists of records of several types. CMD record corresponds to a CMD element in the internal program representation, and represents a command with unevaluable yet argument. CMD: (number) LIT_CMD (number) opcode (expr) arg (expr) size size is typically a RANGE expression. DATA record corresponds to a DATA element in the inter- nal program representation, and represents data with unevaluable yet value or count. DATA: (number) LIT_CMD (number) width (expr) value (expr) count (expr) size The width parameter may be 1, 2, or 4, for data resulting from .byte, .half, and .word assembler directives respectively. size is typically a RANGE expression. BLOCK record corresponds to a BLOCK element in the inter- nal program representation, and represents a com- pletely translated piece of the program, a sequence of bytes. There is no single LIT_BLOCK tag; instead, every positive tag is considered a tag of a BLOCK record with the length equal to the value of the tag. BLOCK: (number) length (byte) byte1 (byte) byte2 ... (byte) byte[length] FRAGMENT records separate portions of the program belonging to different fragments. The record contains nametable index of the fragment's name, and the alignment required for this this fragment. FRAGMENT: (number) LIT_FRAGMENT (number) name (number) align Any CMD, DATA, and BLOCK records appearing between a segment start and the first FRAGMENT record, are considered to belong to the default fragment of that segment. SEGMENT records separate data belonging to different seg- ments. The record contains a string with the name of this segment (segment names are not in nametable, it's a separate namespace), and the nametable index of the default fragment of this segment. SEGMENT: (number) LIT_SEGMENT (string) ident (number) deffrag Any CMD, DATA, and BLOCK records appearing between the start of the SEGMENTS area and the first SEG- MENT record are considered to belong to the head segment. DEFINITIONS AREA The DEFINITIONS area consists of NAMEDEF records. A NAMEDEF record associates a value with a name. NAMEDEF: (number) LIT_NAMEDEF (number) name (expr) value Records of this kind result from assignments to global names in assembly language source, as well as from non- fragment public labels (see ast(1)). STUBS AREA This area is going to contain symbolic information for use by debuggers. It is not implemented yet. MISCELLANIOUS RECORDS This section discussed the records that may appear in more tahn one area. DUMMY record is a one-byte record with tag equal to zero. This record carries no information and is used as a filler. MARKER records, found at the end of every area, have the following structure: MARKER: (number) LIT_MARKER area_type (number) area_size area_type: (number) LIT_AREA_NAMETABLE | (number) LIT_AREA_NEEDS | (number) LIT_AREA_SEGMENTS | (number) LIT_AREA_DEFINITIONS | (number) LIT_AREA_STABS ; After a MARKER, an appropriate number of DUMMY records are appended to make the total size of the marker and dummies equal to LIT_MARKER_LENGTH bytes. COMMENT record may appear anywhere in the file, and con- sists of the only string of undefined contents. COMMENT: (string) abstract_string This record is intended as means for specifying LIT format version and other pseudocomment information, but is not used by current TTOOLS (although care- fully ignored by LIT format reading routines). LOADABLE LIT FILES Loadable files generated by lit(1) have some differencies from linkable files that lit(1) takes as input. Only the SEGMENTS and (optionally) STABS areas are present in loadable files. The only name references that may appear in a loadable file are references to segment addresses, segment@@start. No nametable is necessary to handle these references; the indices used for the segment@@start names in loadable files are the ordinal numbers of their respective seg- ments. LINK BOOTING As you may have noticed, the format of a small (<= 250 bytes) BLOCK record is identical to the format of the bootrstrap code block that the transputer expects to receive via a link after reset. Since the first record of the head segment apeears at the start of a loadable LIT file, one can code a bootstrap routine in the head seg- ment, and then the output from lit will be a bootable file. One of startup modules that come with TTOOLS, link- boot, uses this technique; see startus/linkboot/crt0.S is you are interested. SEE ALSO ast(1), lit(1), litdump(1), ttools(1) AUTHOR Yury Shevchuk (sizif@botik.ru)