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)