ACK.OUT(5)

NAME
ack.out - ACK-assembler and link editor output

SYNOPSIS
#include <out.h>

DESCRIPTION
This manual page discusses the format of object files, as generated by ACK assemblers and the link editor LED. The format is designed to be compact, machine independent, and portable from one machine to another, so that an object file can be produced on one machine, and further processed on another.

In the following discussion, some structures are defined using long and short as type indicators. It is assumed that the size of a short is 2 bytes (chars) and that the size of a long is 4 bytes. However, these types have a machine dependent byte and word order. Therefore, a machine independent representation is chosen for the object format: a long consists of two shorts, of which the least significant one comes first, and a short consists of two bytes, of which the least significant one comes first. There is no alignment between various parts and structures in the object file.

In general, an object file consists of the following parts:

- a file header
- a number of section headers
- the sections themselves
- a number of relocation structures
- a symbol table
- a string area containing the names from the symbol table

The header.
The header of an object file has the following structure:

struct outhead {
	uint16_t oh_magic;	/* magic number */
	uint16_t oh_stamp;	/* version stamp */
	uint16_t oh_flags;	/* several format flags */
	uint16_t oh_nsect;	/* number of outsect structures */
	uint16_t oh_nrelo;	/* number of outrelo structures */
	uint16_t oh_nname;	/* number of outname structures */
	uint32_t oh_nemit;	/* length of sections */
	uint32_t oh_nchar;	/* size of string area */
};

#define HF_LINK	0x0004	/* unresolved references left */

The fields of this structure have the following purpose:

oh_magic
    A magic number, indicating that this is an object file.

oh_stamp
    A version stamp, used to detect obsolete versions of object files.

oh_flags
    Currently only used for the HF_LINK flag. When this flag is set, the object file contains unresolved references.

oh_nsect
    The number of sections and section description structures, later on referred to as outsect structures. Usually, there are only a few sections, f.i. a TEXT section, a ROM section, a DATA section and a BSS section. Notice that neither the assemblers nor LED know more about them than their names.

oh_nrelo
    The number of relocation structures, later on referred to as outrelo structures.

oh_nname
    The number of symbol table structures, later on referred to as outname structures.

oh_nemit
    The total number of bytes in this object file used for the sections themselves. This field is used to find the relocation and symbol table structures fast.

oh_nchar
    The size of the string area (the number of bytes).

The section descriptions.
The next part of an object file contains the outsect-structures. An outsect structure has the following layout:

struct outsect {
	uint32_t os_base;	/* start address in machine */
	uint32_t os_size;	/* section size in machine */
	uint32_t os_foff;	/* start address in file */
	uint32_t os_flen;	/* section size in file */
	uint32_t os_lign;	/* section alignment */
};

The fields in this structure have the following purpose:

os_base
    The start address of this section in the target machine. This address is determined by LED, when producing a non-relocatable object file. It is ignored for relocatable object files.

os_size
    The size of this section on the target machine.

os_foff
    The start address of this section in this file.

os_flen
    The size of this section in this file. This field does not have to have the same value as the os_size field! For instance, an uninitialized data section probably has os_flen set to 0. Notice that the oh_nemit field of the header contains the sum of all the os_flen fields.

os_lign
    The alignment requirement for this section. The requirement is that the loader must leave

    os_base mod os_lign = 0

    in tact.

The sections.
The next part of an object file contains the sections themselves. Usually, the LED program places the sections right behind one another in the target machine, taking the alignment requirements into account. However, the user is allowed to give the start addresses of each section. But if the user gave a start address for say section 2, but not for section 3, section 3 will be put right behind section 2.

The relocation structures.
Relocation information is information that allows a program like LED to combine several object files and produce an executable binary if there are no unresolved references. If relocation information is present, it amounts to 8 bytes per relocatable datum. The information has the following structure:

struct outrelo {
	uint16_t or_type;	/* type of reference */
	uint16_t or_sect;	/* referencing section */
	uint16_t or_nami;	/* referenced symbol index */
	uint32_t or_addr;	/* referencing address */
};

/*
 * relocation type bits
 */
#define RELSZ   0x0fff          /* relocation length */
#define RELO1        1          /* 1 byte */
#define RELO2        2          /* 2 bytes */
#define RELO4        3          /* 4 bytes */
#define RELOPPC      4          /* PowerPC 26-bit address */
#define RELOPPC_LIS  5          /* PowerPC lis */
#define RELOVC4      6  /* VideoCore IV address in 32-bit instruction */
#define RELPC	0x2000		/* pc relative */
#define RELBR	0x4000		/* High order byte lowest address. */
#define RELWR	0x8000		/* High order word lowest address. */

/*
 * section type bits and fields
 */
#define S_TYP	0x007F		/* undefined, absolute or relative */
#define S_EXT	0x0080		/* external flag */
#define S_ETC	0x7F00		/* for symbolic debug, bypassing 'as' */

/*
 * S_TYP field values
 */
#define S_UND	0x0000		/* undefined item */
#define S_ABS	0x0001		/* absolute item */
#define S_MIN	0x0002		/* first user section */
#define S_MAX	(S_TYP-1)	/* last user section */
#define S_CRS	S_TYP		/* reference to other namelist item */

The fields of this structure have the following purpose:

or_type
    Contains several flags: One of RELO1, RELO2 and RELO4 is set, indicating the size of the relocatable datum, RELPC is set when the datum is relocated pc relative, RELBR and RELWR indicate byte and word order of the relocatable datum. RELBR and RELWR are needed here. It is not sufficient to have flags for them in the header of the object file, because some machines (NS 32016) use several of the possible combinations in their instruction encoding.

or_sect
    Contains the section number of the referencing section. This is a number that lies between S_MIN and S_MAX. The section indicated with number S_MIN is the first section in the sections-section, etc.

or_addr
    Contains the address of the relocatable datum, in the form of an offset from the base of the section indicated in the or_sect field.

or_nami
    Usually contains the index of the referenced symbol in the symbol table, starting at 0. In this case, the reference is to an undefined external symbol, a common symbol, or a section name. The relocatable datum then contains an offset from the indicated symbol or the start of the indicated section. It may, however, also have the same value as the oh_nname field of the header. In this case the relocatable datum is an absolute number, and the datum is relocated pc relative. The relocatable datum must then be relocated with respect to the base address of its section.

For RELOPPC and RELOVC4, the relocatable datum is a PowerPC or VideoCore IV instruction. The relocation depends on the instruction, and uses an offset encoded in the instruction.

RELOPPC_LIS assembles a PowerPC lis instruction. The relocatable datum is a 4-byte integer. The high bit is set for ha16 or clear for hi16. The next 5 bits are the register RT. The low 26 bits are a signed offset. The relocation replaces the datum with the PowerPC instruction ‘lis RT, ha16[symbol + offset]’.

The symbol table.
This table contains definitions of symbols. It is referred to by outrelo-structures, and can be used by debuggers. Entries in this table have the following structure:

struct outname {
	union {
	  char	*on_ptr;	/* symbol name (in core) */
	  long	on_off;		/* symbol name (in file) */
	}	on_u;
#define on_mptr	on_u.on_ptr
#define on_foff	on_u.on_off
	uint16_t on_type;	/* symbol type */
	uint16_t on_desc;	/* debug info */
	uint32_t on_valu;	/* symbol value */
};

/*
 * S_ETC field values
 */
#define S_SCT	0x0100		/* section names */
#define S_LIN	0x0200		/* hll source line item */
#define S_FIL	0x0300		/* hll source file item */
#define S_MOD	0x0400		/* ass source file item */
#define S_COM	0x1000		/* Common name */

The members of this structure have the following purpose:

on_foff
    Contains the offset of the name from the beginning of the file. The name extends from the offset to the next null byte.

on_type
    The S_TYP field of this member contains the section number of the symbol. Here, this number may be S_ABS for an absolute item, or S_UND, for an undefined item. The S_EXT flag is set in this member if the symbol is external. The S_ETC field has the following flags: S_SCT is set if the symbol represents a section name, S_COM is set if the symbol represents a common name, S_LIN is set if the symbol refers to a high level language source line item, S_FIL is set if the symbol refers to a high level language source file item, and S_MOD is set if the symbol refers to an assembler source file item.

on_desc
    Currently not used.

on_valu
    Is not used if the symbol refers to an undefined item. For absolute items it contains the value, for common names it contains the size, and for anything else it contains the offset from the beginning of the section. In a fully linked binary, the beginning of the section is added.

The string area.
The last part of an object file contains the name list. This is just a sequence of null-terminated strings.

The relocation information, the symbol table, and the name list do not have to be present, but then of course we do not have a relocatable object file.

Miscellaneous defines
The following miscellaneous defines might come in handy when reading object files:

/*
 * structure sizes (bytes in file; add digits in SF_*)
 */
#define SZ_HEAD	20
#define SZ_SECT	20
#define SZ_RELO	10
#define SZ_NAME	12

/*
 * file access macros
 */
#define BADMAGIC(x)	((x).oh_magic!=O_MAGIC)
#define OFF_SECT(x)	SZ_HEAD
#define OFF_EMIT(x)	(OFF_SECT(x) + ((long)(x).oh_nsect * SZ_SECT))
#define OFF_RELO(x)	(OFF_EMIT(x) + (x).oh_nemit)
#define OFF_NAME(x)	(OFF_RELO(x) + ((long)(x).oh_nrelo * SZ_RELO))
#define OFF_CHAR(x)	(OFF_NAME(x) + ((long)(x).oh_nname * SZ_NAME))

SEE ALSO
led(6), object(3)