Modern Atari System Software, Appendix B - Object File Formats
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

NOTE: there are probably some typos in this (typed at about midnight),
but there shouldn't be anything so bad that you cannot understand it. 



=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=


This section describes several of the object file formats ("linker formats") 
which are in common use under Atari's TOS.

Lattice
=======

This section describes the Lattice linkable file format. A Lattice object
file is a tag based file format, thus allowing particular fields to be
present or abscent from the file as required by the application. This
also has the major advantage of (almost) limitless expandability.

Each tag is formed by a longword giving the type of the tag, followed by
zero or more longwords giving additional information about the tag. Note
that all items within a Lattice format file are longword size unless noted
otherwise.

A string in a Lattice format file is represented by a longword prefix giving
the length in longwords, followed by the characters forming the string; as
such the string may or may not be NULL terminated.


Module directives
-----------------

The module directives are used to start and terminate object files with
a file. A simple object file will have only one HUNK_UNIT, whereas an
uncompressed library may have many.

HUNK_UNIT          0x3e7 string

A HUNK_UNIT is used to introduce the start of a module within the 
relocatable file. It is followed by a string, giving the name of the module.
If there is more than one section within a module then HUNK_UNIT terminates
the previous module.


Section directives
------------------

The section directives are used to start and end sections within a module.
Each section (HUNK_CODE, HUNK_DATA and HUNK_BSS) may have a HUNK_NAME
associated with it, followed by one or more relocation and/or debugging
directives, terminated by a HUNK_END.

HUNK_NAME          0x3e8 string

HUNK_NAME is used to associate a name with the next HUNK_CODE, HUNK_DATA
or HUNK_BSS directive. It is followed by a string giving the name of the
section. Note that section names are optional, although if present are
used by the linker to coalesce sections of the same name. Unnamed sections
are always coalesced.

HUNK_CODE          0x3e9 long
HUNK_DATA          0x3ea long

HUNK_CODE and HUNK_DATA define a block of code, and a block of data
respectively. They have a long giving the number of longwords of code/data
which follow the tag.

HUNK_BSS           0x3eb long

HUNK_BSS defines a BSS block, containing 'long' longwords of data. Note,
however, that none of the data is actually present, and is implicitly zero.

HUNK_END           0x3f2

A HUNK_END is used to mark the end of the current section. Note however
that the smallest legal module is HUNK_UNIT, HUNK_END.

HUNK_CHIP          0x40000000
HUNK_FAST          0x80000000

HUNK_CHIP and HUNK_FAST are not section directives but section modifiers.
They are bits which may be set in the HUNK_CODE, HUNK_DATA and HUNK_BSS
section types to indicate that the respective section should be exclusively
loaded into system (chip) or alternative (fast) memory respectively. Note
that neither of these bits is supported by Lattice format linkers at the
time of writing.


Relocation/symbol directives
----------------------------

The relocation directives are used to specify fixups which are to be
performed in the current section. They may either be anonymous
(ie not relative to any variable) in the case of the HUNK_RELOC8,
HUNK_RELOC16, HUNK_RELOC32, HUNK_DRELOC8, HUNK_DRELOC1 and HUNK_DRELOC32
directives, or symbol relative in the case of the HUNK_EXT directive.
Note that the HUNK_EXT directive is also used to generate exports of
symbols.

HUNK_RELOC8        0x3ee {long section offsets)
HUNK_RELOC16       0x3ed {long section offsets)
HUNK_RELOC32       0x3ec {long section offsets)

HUNK_RELOC8, HUNK_RELOC16 and HUNK_RELOC32 directives specify 8, 16 and
32 bit relocations, respectively, which are to be performed in the
current section. Each of these directives are followed by a relocation
block consisting of a count of the number of relocations to be performed,
which section the relocations are relative to and finally the relocation
offsets. The list is terminated by a block indicating a zero count.


Each relocation block consists of a long giving the number of items to
be fixed up relative to the section number. Note that the sections
within the module are numbered starting from zero. Following section
are a list of long longword offsets which are to be fixed up.

For HUNK_RELOC32 the relocation is performed by adding the base of the
nominated section to the longwords located at the offsets. Note that
there is no way to perform a 32 bit PC-relative fixup.

For HUNK_RELOC16 and HUNK_RELOC8 a PC-relative fixup is performed by
adding the start of the section, minus the offset of the relocation
point.

HUNK_DRELOC8       0x3f9
HUNK_DRELOC16      0x3f8
HUNK_DRELOC32      0x3f7

HUNK_DRELOC8, HUNK_DRELOC16 and HUNK_DRELOC32 directives specify 8, 16
and 32 bit near data section relocations, respectively, which are to
be performed in the current section. Each of these directives are followed
by a relocation block in the same format as for HUNK_RELOC32.

For all of these directives the relocation is performed by adding the
base of the specified section (ie. the number of bytes from the base of
the __MERGED section to the base of the specified section).

Note the lack of symmetry between HUNK_RELOC16, HUNK_RELOC8 and HUNK_DRELOC16,
HUNK_DRELOC8 directives respectively.


HUNK_EXT           0x3ef { ... }

The HUNK_EXT directive is used to introduce a block specifying both 
definitions for symbols (exports) and references to declared symbols
(imports).

Each symbol block within a HUNK_EXT consists of an initial longword
giving the length of the symbol which follows. The top 8 bits
of the longword are ignored for the length purpose and instead hold a
type. Immediately following this longword there are length longwords
of name, giving the name of the symbol to which this symbol data unit
refers.

EXT_ABS     2
EXT_DEF     1

The EXT_ABS and EXT_DEF types are used to enter absolute and relocatable
definitions, respectively, into the linkers symbol table. Following the
symbol name is a longword value. For an EXT_ABS this is the absolute
value of the symbol. For an EXT_DEF it is an offset from the base of the
current section to the symbol location.

EXT_REF8    132
EXT_REF16   131
EXT_REF32   129

They types EXT_REF8, EXT_REF16 and EXT_REF32 perform 8, 16 and 32 bit
relocations, respectively, in the current section. Each of these is
followed by a count of the number of references and a list of the offsets
to these references.

EXT_REF32 references have the value of the symbol added to the longwords
located at the offsets.

For EXT_REF16 and EXT_REF8 a PC-relative fixup is performed by adding the
value of the symbol, minus the offset of the relocation point.

EXT_DREF8   135
EXT_DREF16  134
EXT_DREF32  133

The types EXT_DREF8, EXT_DREF16 and EXT_DREF32 perform 8, 16 and 32
bit near data section relocations, respectively, which are to be
performed in the current section. Each of these is followed by a count
of the number of references and a list of the offsets to these references.

For all of these types the relocation is performed by adding the offset
of the symbol within the __MERGED.

Note the lack of symmetry between the EXT_REF32 and EXT_DREF32.

EXT_COMMON  130

The EXT_COMMON type is used to enter a reference to a common block.
Following the symbol there is a longword length for the common block.
Note that this gives the length of the common blick in longwords.

A list of references to the common symbol for fixup then follow in the
same manner as used by EXT_REF32. Note that common references are always
32 bit.


Debugging directives
--------------------

The debugging directives supply information which is not directly 
processed by the linker, but instead passed on to the final executable
program for use by a symbolic or source level debugger.

HUNK_SYMBOL    0x3f0

HINK_SYMBOL is used to provide symbol information in the executable
for use by a symbolic debugger.

Each symbol block within a HUNK_SYMBOL block consists of an initial 
longword giving the length of the symbol which follows. The top 8 bits
of this longword are ignored for the length purpose and are always zero.
Immediately following this longword there are length longwords of name,
giving the name of the symbol to be placed in the executable symbol table.
The longword offset from the start of the section immediately follows
the name.

There may be as many of these symbol blocks as required, terminated by
a longword 0 (indicating a zero length string).

HUNK_DEBUG    0x3f1

HUNK_DEBUG is used to provide source level debugging information about
the current section. It consists of the HUNK_DEBUG directive followed
by a longword count of the number of longwords in the remainder of the
HUNK_DEBUG section. The first longword in the debug block is filled in
by the linker, by adding the offset of the start of this section within
the entire coalesced section. The second longword is a type value,
indicating the type of the debugging information contained in this block.

Note that there will typically be as many HUNK_DEBUG blocks within a section
as there are source files which make up the module.

'HEAD'        0x48454144

The HEAD chunk is generated by the linker as the very first HUNK_DEBUG 
directive in an exectuable file (see below for the location of HUNK_DEBUG
information in an executable).

The first longword is the value 'DBGV' (0x44424756), followed by the HEAD
chunk version number. This section describes '01' (0x3031).

The word following the version number gives the linker option flags.
Only two of these bits are committed at present: bit 0 indicates that the
executable is an overlaid program (not supported by current linkers), bit 1
indicates that the file was linked in a case-insensitive manner.

The next two longwords give the number of symbols found in HUNK_DATA 
(or HUNK_BSS) sections and HUNK_CODE sections respectively.

The next longword indicates how many HUNK_DEBUG directives were encountered
during linking (and hence how many follow the head chunk), to improve the
performance of locating these HUNK_DEBUG directives the linker writes an
index of these immediately after the number of the section which the 
HUNK_DEBUG refers to and the remainder of which gives an offset within the 
executable file to the start of the releveant HUNK_DEBUG directive. Note 
that this places a theoretical limit of 16Mb on the size of an executable
plus debigging information.

'HBPR'      0x48425052

The HBPR chunk is generated by Hisoft BASIC for use by the profiler. The
information contained within this chunk is confidential and proprietary.

'HCLN'      0x48434c4e

The HCLN chunk gives inforation about the link numbers of a file from
which the module was generated. The first longword gives the length of
a string giving the name of the file from which the module was generated,
followed by length longwords of the name. Note that up to this point the
format is identical to the LINE chunk.

The next longword gives the number of line number and offset pairs
which are to follow. The remainder of the chunk then consists of signed
line number and offset delta pairs, giving the changes in line numbers
and code offsets, so that line numbers and code offsets may be matched.
The encoding of the deltas is identical to that of the 680x0 BSR in its
short word and long forms. If a non zero byte (note a byte) is read then
this gives the delta, otherwise a word is read which, if non-zero, gives
the delta, finally a longword may be read to give the delta. Note that
the only way of generating a zero delta is via a byte, word and finally
a longword of zero (ie. these should be avoided where possible).

'LINE'    0x4c494e45

The LINE chunk gives information about the line numbers of a file from which
the module was generated. The first longword gives the length of a string
giving the name of the file from which the module was generated, followed
by length longwords of the name.

The remainder of the chunk consists of line numbers and offset pairs, giving]
which offsets within the local code section correspond to which line numbers.

Note that there is no explicit terminator, instead the section ends when
the length longword in the HUNK_DEBUG directive is used up.

'SRC '    0x53524320

The SRC chunk is used by Lattice C for source level debugging information.
The first 8 longwords in the SRC chunk give the module name to which this
HUNK_DEBUG refers (note that this is only the stem of the filename, not the
entire file name). The next three longwords give (in bytes): the size of
the code generated for this module, the size of the line number/offset pair
table and the size of the source level debugging information table.

Next in the chunk a LINE format chunk is generated, comprising a longword
giving the length o a string giving the name of the file from which the
module was generated, followed by length longwords of the name. A link number/
offset pair table then follows, of length given by value retrieved earlier
from the chunk.

The next part of the chunk contains the source level debugging information
table, of a size given earlier in the chunk. The contents of this part of
the chunk are confidential and proprietary.

The final 5 longwords in the hunk are used to hold offsets to the near data,
far data, near BSS, far BSS and chip data (not used under TOS). The values
of these fields are modified by the linker to give the correct offsets
after coalescing.


Library Format
--------------

The Lattice object format supports two library formats. The simple, 
uncompressed version is simply the concatenation of ordinary object modules
(in an identical manner to that done in the GST format). There is a second,
compressed, format recognised by CLink which allows a massive linker
performance improvement.

HUNK_LIB    0x3fa

An HUNK_LIB directive is the first part of a compressed library. It is
followed by a longword giving a count of the total number of longwords in
the remainder of the block.

The data contained within a HUNK_LIB is simply the concatenation of all the
modules which form the library, however all HUNK_UNIT and HUNK_NAME 
directives are removed completely whilst EXT_DEFs and EXT_ABSs are removed
from HUNK_EXTs. Note that EXT_COMMONs (the other 'definition' type) are
not removed, but never-the-less appear within the HUNK_INDEX block.

Because of a restriction in the HUNK_INDEX directive, no section (HUNK_CODE,
HUNK_DATA or HUNK_BSS) in a HUNK_LIB may begin beyond a longword offset of 
65535 (byte offset 262140). If this is required then a library may be 
enlarged by concatenating two or more compressed format libraries in the
same manner as an uncompressed library.

Within the library file, the next directive following a HUNK_LIB must be a
HUNK_INDEX.

HUNK_INDEX  0x3fb

An HUNK_INDEX directive gives the module index for the preceding HUNK_LIB.
It is followed by a longword giving a count of the total number of longwords
in the remainder of the block.

The first item in the HUNK_INDEX is a string table, prefixed by an unsigned
short word giving the number of bytes in the string table. The
entries in the string table are module name (HUNK_UNIT), section names
(HUNK_NAME) and external names (HUNK_EXT). Within the string table
the strings are NULL-terminated (C-style) strings, concatenated
end-to-end. Note that the first string in the table must be the NULL string.
The string table is always padded so that it is an even number of words,
although each string within the table is not padded.

Following the string table are one or more module entries. These give
details of the modules contained within the HUNK_LIB. A module entry
consists of an unsigned short offset to the HUNK_UNIT name within
the string block, an unsigned short offset to the HUNK_UNIT name within
the string block, an unsigned short longword offset to the start of the
module within the preceding HUNK_LIB, and an unsigned short count of
the number of sections in the module (HUNK_CODE, HUNK_DATA and HUNK_BSS).

For each of the sections in the module there is a section entry consisting
of an unsigned short offset to the name of the section within the string
block (note that 0 will indicate the NULL string), an unsigned short
count of the number of longwords in the section within the HUNK_LIB
and a short tpye of the section (HUNK_CODE, HUNK_DATA or HUNK_BSS).

The next unsigned short value indicates the number of references
to external symbols (EXT_REF16, EXT_REF32, EXT_DREF16, EXT_DREF32 and
EXT_COMMON), followed by a list of unsigned short offsets to the strings
referenced within the string block. Note that a 16 bit reference is
indicated by pointing to the zero preceding the string within the block,
whereas a 32 bit reference points at the string itself (an EXT_COMMON is
treated as an EXT_REF32). Note that EXT_REF8 and EXT_DREF8 are not
supported.

The next unsigned short value indicates the number of external
definitions (EXT_DEF, EXT_ABS and EXT_COMMON) within the section. Note
that EXT_DEF and EXT_ABS definitions are deleted from the HUNK_EXT, whereas
EXT_COMMONs are not (and indeed appear both as refences and definitions).
Following the count of references are a series of 6 byte records.

The first unsigned short value gives an offset into the string block for
the name of the symbol followed by two unsigned shorts encoding the value
and type of the symbol.

The encoding used for the value and type of the symbol is rather convoluted,
but permits 25 bits of resolution for values and allows all current HUNK_EXT
types.

The first unsigned short gives the bottom 16 bits of the value of the symbol.
The bottom byte of the next unsigned short excluding bit 6 encodes the
type byte (EXT_DEF, EXT_ABS or EXT_COMMON). The top 8 bits of this short
then encode bits 16-23 of the value, 0 if they are 0x00, or 1 to indicate
0xff. Thus, the type and value of a definition may be decoded in the
following manner:

unsigned short *buffer;
long value;
int type;

value = buffer[0] | ((buffer[1] & 0x0000ff00L) << 8);
if (buffer[1] & (1 << 6))
   value = value | 0xff000000;
type = buffer[1] & -(1 << 6);

Note that there is no explicit terminator, instead the section ends when
the length longword in the HUNK_INDEX directive is used up.



GST
===

This section describes the GST linkable file format. A GST object file is
based around a byte stream which is copied by the linker to the final output
file. Interspersed with the byte stream are directives, introduced using the
code $FB which allow relocation, symbol definition, section and module
definition. If a $FB code is required in the file then one is included using
the sequence $FB $FB.

Within this file symbols and section names are referred to using a word-sized
id number. These numbers are +ive and non-zero for symbols, whilst -ive
values refer to SECTION and COMMON names. The value 0 is reserved for
absolute section references.

A string in GST terminology is a sequence of bytes comprising the string,
prefixed by the length of the string excluding the length byte (aka. a
Pascal string).


Source directives
-----------------

Source directives are used to specify the start and end of modules within
a single file. A GST format object module will have only one such pair of
SOURCE and END directives; a library may have many appearing sequentially
in the file. Note that a SOURCE directive must be the very first item in
a GST format file.

COMMENT  FB 02 string

The COMMENT directive is used to include a comment within the relocatable
file; it has no effect on the executable generated. Many linkers use this
filed type in conjunction with a librarian to improve performance of library
scanning for GST format files.

DEFINE   FB 10 id string

The DEFINE directive is used to introduce id numbers for use by the other
directives. It defines that the string given is associated with the id.

Remember that +ive (non-zero) id values are used for symbols whilst -ive
values refer to SECTION and COMMON names. The id value 0 is reserved for
absolute section references.

END      FB 13

The END directive marks the end of the current module. If there are
further modules in the file then these are introduced using a SOURCE
directive.

SOURCE   FB 01 string

The SOURCE directive is used to indicate which source file the object file
was derived from and as such should only appear at the start of a module.


Section directives
------------------

The section directives allow the specification of various sections
within a single module, eg. a text, data and BSS section.

COMMON   FB 12 id

The COMMON directive is simular to the SECTION directive (see below) but
instead switches to a section which rather than concatenating from module 
to module (as with a SECTION) overlay each other. The size of the
resulting section is then the size of the largest one encountered.

Note that most existing linker implementations permit only non-initialised
COMMON sections, ie. the only valid output directive is OFFSET.

OFFSET   FB 05 long

The OFFSET directive moves the current location pointer within the section.
The parameter gives the absolute offset within the section for the location
pointer. Note that this may cause the section to be expanded as a result.

ORG      FB 03 long

The ORG directive indicats that the bytes following the directive are to
start at the absolute address given in the long paramater. This applies
until the next ORG, SECTION or COMMON directive.1

SECTION  FB 04 id

The SECTION directive switches the current section to that specified by id.
The section should already have been defined via a DEFINE directive. This
applies until the next ORG, SECTION or COMMON directive.


Symbol directives
-----------------

The symbol directives are used to specify symbol definitions and fixups
which should be performed for the relocatable file.

XDEF    FB 06 string long id

The XDEF directive marks symbol as an export. The value of the symbol is
given by long, and is relative to the section defined by id.

XREF    FB 07 long trunc-rule {op id} FB

The XREF is the most complex directive. It is used to include fixup
information in the final file. The final value output is constructed
from the sum of the long parameter and the op id terms.

The trunc-rule parameter is a byte which defines the characteristics
of the item finally written to the file. Six bits of it are used as
follows:

   Bit    Meaning

    0     The result is byte sized
    1     The result is word sized
    2     The result is long sized

          Note that only one of these bits may be set.

    3     The result is signed
    4     The result is unsigned

          Unlike the size bits neither or both of these may
          be set in order to decide the range checking information.

    5     The reference is PC relative, ie. the location counter prior
          to the output of the result is subtracted from the running total.

    6     The result should be relocated at runtime. This is only supported 
          in TOS for longs.

The OP ID terms are a list of symbols which should be added/subtracted
from the value. OP is the character + for addition  or - for subtraction.
The following ID (previously defined via an id directive) is then add / 
subtracted from the running total. This list is terminated by a single
$FB byte.


Library format
--------------

A GST format library is relocatable object file as described above, but
rather than containing only one SOURCE and END directive it will contain
several. A library is therefore simply the concatenation of several object
files.




DRI
===

This section describes the DRI linkable file format. A DRI obect file
consists of two images of the text and data segments (hence their 
voluminous size), the first giving the code, and the second the reolcation
information. The format is extremely similar to the GEMDOS 
executable format, with the sole difference occurring in the format of the
relocation information. It should be noted that the format is incomplete 
since byte fixups are not possible.

Relocatable format
------------------

A DRI relocatable file starts with a file header in the following format:

struct oheader
  {
   short magic; /* 0x601a */
   long tsize;  /* length of text segment */
   long dsize;  /* length of data segment */
   long bsize;  /* length of BSS segment  */
   long ssize;  /* length of symbol table */
   char reserved[10];     /* must be zero */
  };

Immediately after the header an image of the text section occurs, with
length tsize and then the data section of length dsize. The symbol
table then follows. This is a stream of symbols in the following format:

struct symbol
  {
   char name[8];        /* 8 character name of symbol */
   unsigned short type; /* type of the symbol */
   long value;          /* value assigned to symbol */
  };

Within these structures, name gives the 8 character name of the symbol.
If the original name required more than 8 characters it will be truncated
to 8 characters. Value gives a value which is associated with the symbol.
The type word is used to give a bitmap of the types associated with the
symbol as follows:

Bit    Meaning

15     defined, i.e. the value field gives the value to be assocaited with
       the symbol. Note that any of the other bits may be set to indicate
       a definition relative to that type.
14     equated label
13     global label
12     register equate, i.e. a symbol acting as a register synonym.
       The value field is used to indicate which register the symbol
       refers to; 0-7 indicate D0-D7, 8-15 indicate A0-A7, and 16-23
       indicate FP0-FP7
11     external symbol, i.e. a symbol imported from another module. Note 
       that this means the value field would be unused. Because of this
       the format uses this symbol to indicate a common symbol when the 
       value field is non zero. value then gives the length of the common 
       block to be created.
10     value relative to start of DATA
9      value relative to start of TEXT
8      value relative to start of BSS

The relocation table follows the symbol table. These are the same size
as the section to which they refer and consist of words giving the 
relocation which is to be performed on the data. The top 13 bits of the
relocation word give a symbol index number (note that this gives an 8192
symbol limit per-module), whilst the bottom 3 bits give the relocation
type:

Type   Meaning
0      Absolute reference, no fixup required. Symbol ignored
1      DATA segment relative, add address of local data segment. Symbol 
       ignored.
2      TEXT segment relative, add address of local text segment. Symbol
       ignored.
3      BSS segment relative, add address of local BSS segment. Symbol
       ignored.
4      Absolute address of undefined symbol, add value of the symbol.
5      Referrences the upper word of a long word to be relocated.
       Symbol ignored. Next word determines type of relocation and symbol.
6      PC relative, add symbol-PC
7      References word which is never to be relocated (e.g. an
       instruction). Symbol ignored.

Within this scheme it is possible to general all 16 and 32 bit relocation
types, although most linkers will not permit a short absolute fixup
(relocation type for without a preceding 6). This type of relocation
is used by Lattice C to indicate a near data section reference.


Absolute Format
---------------

A DRI absolute file is identical to the relocatable format, with the
exception of the header. For the absolute format it has the following
structure:

struct abshdr {
  {
   short magic; /* 0x601b */
   long tsize;  /* length of text section */
   long dsize;  /* length of data section */
   long bsize;  /* length of bss section */
   long ssize;  /* length of symbol table */
   long reserved;   /* zero */
   long textbase;   /* absolute base of text section */
   short relocflag; /* zero if relocation present */
   long database;   /* absolute base of data section */
   long bssbase;    /* absolute base of bss section */
  };

Following the header the format is identical to the relocatable format.

Note that GEMDOS cannot execute absolute format programs.


Executable Format
-----------------

A GEMDOS executable file starts with a file header in the following
format (note the similarity to the DRI relocatable module format):

struct abshdr {
  {
   short magic; /* 0x601a */
   long tsize;  /* length of text segment */
   long dsize;  /* length of data segment */
   long bsize;  /* length of BSS segment  */
   long ssize;  /* length of symbol table */
   long reserved; /* zero */
   long flags;  /* program load flags */
   short relocflag; /* zero if relocation present */
  };

The bottom 28 bits of the flags longword are used to control the loading
characteristics of the program. The bits are assigned as follows:

Bit    Meaning when set
0      Only clear the BSS of the program cf. the entire TPA
1      Load the program into alternative (TT/Fast) RAM
2      Allow Malloc to take memory from alternative (TT/Fast) RAM
4-5    Memory protection mode (MiNT):
       $00 - Private (no reads or writes)
       $10 - Global (any reads or writes)
       $20 - Supervisor (supervisor mode reads and writes only)
       $30 - Shared (any reads, no writes)
11     Shared text segment (MiNT)

The top 4 bits of the flags longword are used in conjunction with the
alternative RAM load bit. If this bit is set then TOS checks the amount
of alternative memory against the value in the top 4 bits of flags*128+128, 
if more alternative RAM is available than this minimum TPA size then the
program is loaded into alternative RAM, otherwise it is loaded into 
system RAM.

Note that prior to TOS 1.04, setting the relocaflag word causes Pexec()
to leave the file open after loading it; this behaviour usually
results in two or more files with the same name appearing.

Immediately after the header an image of the text section occurs,
with length tsize and then the data section of length dsize. The symbol
table then follows, in almost the same format as the relocatable symbol
format.

Note that within the symbol table all symbols are considered relative
to the text section regardless of the type field.

As extensions to the standard format some utilities allow various
extensions to the symol types present in the executable symbol table:

Value   Meaning

0x??48  HiSoft extended symbol... [details omitted]
0x0280  file symbol... [details omitted]
0x02c0  library symbol... [details omitted]


The relocation information differs completely from the DRI relocatablle
format. The relocation starts with a long word giving he first longword 
to be relocated. The byte stream that follows gives the offset to the next
longword to be fixed. The values used are:

Value   Meaning
0       end of relocation information
1       add 254 to the current location counter and then decode the 
        next fixup byte
2..255  add the value to location counter and fixup longword at
        that location.

Beyond the end of the relocation information there may be additional
debugging information for use by symbol and source level debuggers.
There is no standard representation for this information, although
for Hisoft products this information (if present) is in the format of
Lattice HUNK_DEBUG hunks, aligned to a word boundary.


Library Format
--------------

A DRI format library is formed by concatenating several DRI format
object modules together with a header added at the front of each
module. The initial word in the file is the magic number 0xff65 to 
indicate that the file is a library file. The header pre-pended to each
module is as follows:

struct arheader {
   {
    char a_fname[14]; /* modules file name */
    long a_modtim; /* last modified time of module */
    char a_userid; /* user ID (not used) */
    char a_gid;    /* group ID (not used) */
    short a_fimod; /* file mode of module */
    long a_fsize;  /* size of module in bytes */
    short reserved; /* zero */

Within this structure, a_fname gives the name of the module, with any
directory information removed. a_modtime gives the UNIX format
time stamp of the module (i.e. seconds since 00:00:00 GMT, jan 1, 1970).
a_fimode gives the UNIX file mode bits; under TOS only one of these
bits is used; bit 7 is set if write permission is available for the
file, cleared otherwise. a_fsize gives the size of the module which 
follows in bytes. Note that this size includes the header pre-pended 
to the DRI format module, but excludes the archive header size.