Multics Technical Bulletin MTB-627
ou_
To: Distribution
From: Benson I. Margulies
Date: 07/07/83
Subject: Subroutines for Generating Object Segments
1 ABSTRACT
create_data_segment_ is capable of generating
only the simplest of object segments. This
MTB describes a new subroutine, ou_, which is
capable of generating any standard object
segments. It can handle arbitrary links,
definitions, and relocation. Rather than
interpreting a single, massive, input
structure, it is called successively to emit
the various parts of an object segment. Thus
translators can generate code and whatnot
directly through ou_ if they so choose.
Comments should be sent to the author:
via Multics Mail:
Margulies.Multics on either MIT Multics or System M.
via US Mail:
Benson I. Margulies
Honeywell Information Systems, inc.
575 Tech Square
Cambridge, Massachusetts 02139
via telephone:
(HVN) 261-9333, or
(617) 492-9333
_________________________________________________________________
Multics project internal working documentation. Not to be
reproduced or distributed outside the Multics project without the
consent of the author or the author's management.
___ ___
ou_ ou_
___ ___
Name: ou_
The ou_ program provides a set of entrypoints for the
construction of Multics standard object segments. The user makes
a series of calls to specify the various components of the object
segment, and then a final call to put the result into an output
segment.
Object segments generated with ou_ are relocatable if
correct relocation bits are provided for the text and symbol
sections. Note, though, that in a multiple-location-counter
segment, or one that is non-seperate-static, a translator that
fails to supply relocation is responsable itself for backpatching
all references to point to the final location of referenced data.
Therefore we STRONGLY RECOMMEND that relocation information be
supplied.
Ou_ provides a standard symbol header, but no other symbol
table information as yet. Translators that wish to construct a
full runtime symbol table must do so themselves.
Ou_ provides no support for obsolete features of the object
segment format, including links type 2 and 6, defs_in_link, and
links_in_text.
The documentation that follows assumes that the reader is
familiar with the object segment format as described in the MPM
reference guide. These should be consulted for definitions of
terms.
Entries in ou_ only supply standard status codes when an
error condition is possible without a logic error on the part of
the caller. For example, the call to ou_ that specifies the
output segment pathname may encounter an access control violation
or null link, which the caller of ou_ could not reliably prevent.
Inconsistent or invalid parameters and other errors, however, are
reported by the sub_err_ mechanism. Callers of ou_ should
establish a handler for the sub_error_ condition, and intercept
signals with a "caller name" of "ou_" if they want to recover
from such errors.
Sections and Classes
Object segments are made up a several sections: Text,
Static, Linkage, Definitions, and Symbol. The Text and Static
sections are unstructured, and ou_ entries simply allow the
translator to supply their contents. While there is a standard
format for the symbol section, ou_ provides no facilities for its
construction, and it is treated like Text and Static. The
___ ___
ou_ ou_
___ ___
Linkage and Definitions sections are structured, and ou_ provides
entries that construct their contents. Translators call ou_ to
generate segnames, definitions, and links, and ou_ constructs the
appropriate structures.
To simplify object segment construction, the translator
may define arbitrary location counters within the unstructured
sections. Location counters are specified in calls to ou_ by
"section indices." One location counter per unstructured section
is provided by default. The indices for these sections are
defined by named constants in the include file ou_info.incl.pl1.
Other sections are defined by calls to ou_$make_section. When a
section is created, its "class" (Text, Static, or Symbol) must be
specified.
___ ___
ou_ ou_
___ ___
Entry: ou_$init
Initializes the ou_ environment, returning a state pointer.
This state pointer identifies a particular object segment and
must be passed in all further calls to ou_ for that segment.
Usage
dcl ou_$init entry (pointer, pointer);
call ou_$init (info_ptr, state_ptr);
where:
info_ptr (Input)
is a pointer to a structure specifying initial
information about the object segment. The structure,
ou_init_info, is found in the include file
ou_info.incl.pl1.
declare 1 ou_init_info aligned based (ou_init_info_ptr),
2 version char (8) aligned,
2 primary_segname character (32) unaligned,
/** this segname is the one that "symbol_table" for
the main segment will be hung off of. */
2 short_translator_name char (8) unaligned,
2 translator_version fixed bin,
2 translator_birthday fixed bin (71),
2 long_translator_version aligned like long_string,
2 translator_comment aligned like long_string;
declare 1 long_string aligned based,
2 s_ptr pointer unaligned,
2 s_length fixed bin (21);
declare long_translator_version_string character
(ou_init_info.long_translator_version.s_length)
based (ou_init_info.long_translator_version.s_ptr);
declare translator_comment_string character
(ou_init_info.translator_comment.s_length)
based (ou_init_info.translator_comment.s_ptr);
declare OU_INIT_INFO_V_1 char (8) aligned internal
static options (constant);
___ ___
ou_ ou_
___ ___
version (Input)
is the version number of this structure, and must be
set to OU_INIT_INFO_V_1.
primary_segname (Input)
This is the first segname of the object segment. The
required definition "symbol_table" will be attached
to this segname. In general, this will be the same
as the file system entryname of the object segment.
All definitions specified for the object segment are
associated with this segname by default.
short_translator_name (Input)
Is a short name of the generating translator.
translator_version (Input)
is an integer version of the translator generating
the object segment.
translator_birthday (Input)
is a standard clock value of the date-time when the
current version of the translator was created.
long_translator_version (Input)
Is a long string (max 255 characters) describing the
translator version. See the description of the
long_string substructure below.
translator_comment (Input)
Is a long string (max 255 characters) describing
compilation options or anything else the translator
wishes to leave as a note.
text_section_mod (Input)
If this value is nonzero, the binder will place the
text section of this segment on a 0 mod
text_section_mod boundary in the bound segment. This
value may not be odd.
static_section_mod (Input)
is the same as text_section_mod, but for the
static_section.
long_string.s_ptr (Input)
is a pointer to a character string of length less
than or equal to 255 characters.
long_string.s_length (Input)
is the length of the character string.
___ ___
ou_ ou_
___ ___
state_ptr (Output)
is a pointer to a state information for the object
segment. The contents of this data structure are not
available to the caller. This pointer must be passed
into all further calls to ou_ for this object
segment.
___ ___
ou_ ou_
___ ___
Entry: ou_$definition
creates a definition in the object segment. The location of
the object defined relative to a location counter must be
supplied.
Usage
dcl ou_$definition entry (ptr, char (), char (), bit (),
fixed bin, fixed bin (18) unsigned returns (fixed bin
(18) unsigned));
definition_loc = ou_$definition (state_ptr, segname,
entrypoint,
flags, section, location);
where:
state_ptr (Input)
is a state pointer obtained from ou_$init.
segname (Input)
is the segname to which this definition will be
attached. If it is "", the primary_segname in the
ou_$init call will be used. This segname must have
been previously defined, either in a call to
ou_$segname, or as the primary segname.
entrypoint (Input)
is the name of this definition. The linker will find
this definition as "segname$entrypoint".
flags (Input)
(Input) are bit flags. Only one is defined:
declare OU_IGNORE_DEFINITION bit (1) init ("1"b)
if this bit is set, the ignore flag will be set on
the definition, causing the linker to ignore it when
searching the object segment.
This constant is defined in ou_info.incl.pl1.
section (Input)
specifies the location counter within which this
definition will point. It must have previously been
defined, either as one of the default sections, or
with a call to ou_$make_section.
location (Input)
is the location within the location counter of the
___ ___
ou_ ou_
___ ___
object defined. It will ordinarily be obtained from
a call to ou_$emit or ou_$reserve.
definition_loc (Output)
is the location, within the definition section, of
the definition. This is useful when defining
entrypoints, which require a pointer to the
definition.
___ ___
ou_ ou_
___ ___
Entry: ou_$segname
defined additional segnames within the object segment, or
synonyms to segnames already defined.
Usage
dcl ou_$segname entry (ptr, char (), char ());
call ou_$segname (state_ptr, segname, syn_to_segname);
where:
state_ptr (Input)
is a state pointer from ou_$init.
segname (Input)
is the segname to be defined. Segnames must be
unique within an object segment. It must be less
than or equal to 32 characters long.
syn_to_segname (Input)
(Input) if this argument is not "", segname will be
associated with syn_to_segname as a synonym.
syn_to_segname must have been previously defined.
___ ___
ou_ ou_
___ ___
Entry: ou_$link
emits an ordinary link. Links are automatically merged --
multiple links to the same external name are combined.
Usage
dcl ou_$link entry (ptr, char (), char (), fixed bin, fixed
bin, bit (6)) returns (fixed bin (18) unsigned));
link_relp = ou_$link (state_ptr, segname, offsetname,
sectionx, expression,
modifier);
where:
state_ptr (Input)
is a state pointer from ou_$init.
segname (Input)
is the symbolic segname. If its first character is a
"*", it is a symbolic reference to a section within
the object segment containing the link. The
following symbolic sections are permitted:
SECTION_TEXT init ("*text")
SECTION_STATIC init ("*static")
SECTION_LINKAGE init ("*link")
SECTION_SYMBOL init ("*symb")
SECTION_DEFINITION init ("*defs")
SECTION_SYSTEM init ("*system")
offsetname (Input)
is the symbolic definition name to which the link
will point. If it is "", the link target is
determined entirely by the segname and the
expression.
sectionx (Input)
if nonzero, specifies a location counter within the
segment being generated to which the link will point.
For example, if a location counter within the text
section is supplied, then the segname will be forced
to "*text". It is an error for segname to be unequal
to "" if this argument is nonzero.
expression (Input)
is a signed offset from the location determined by
the segname and offsetname fields.
___ ___
ou_ ou_
___ ___
modifier (Input)
is the indirect modifier for the snapped link. It
will normally be "n", or ""b. A snapped link is an
ITS pointer, and this becomes the modifier (NOT the
tag) field of that pointer.
code (Input)
is a standard system status code.
link_relp (Output)
is a offset, relative to the base of the linkage
section, of this link. For non-separate static
segments, this value is only meaningful if stored in
this object segment with a relocation code of rc_lp15
or rc_lp18. This is because the actual location of
the link is not known until the static section is
inserted in the object segment. At that time, all
relative pointers to links are relocated
automatically by ou_.
___ ___
ou_ ou_
___ ___
Entry: ou_$link_trap
this entrypoint is identical to ou_$link except that it
associated a link trap with the link. All arguments not listed
are identical to ou_$link.
Usage
dcl ou_$link_trap entry (ptr, char (), char (), fixed bin,
fixed bin, bit (6), fixed bin (18) uns, fixed bin (18)
uns) returns (fixed bin (18) uns));
link_relp = ou_$link_trap (state_ptr, segname,
offsetname, expression,
sectionx, modifier, trap_call_relp, trap_arg_relp,
code);
where:
trap_call_relp (Input)
is a relative pointer in the linkage section to a
link to the procedure to be called when this link is
snapped.
trap_arg_relp (Input)
is a relative pointer in the linkage section to a
link to an argument to the trap procedure. The trap
procedure is called as follows:
call trap_proc (addr (arg_ptr));
so as to avoid snapping the arg link until the trap
procedure referenced through it, if ever.
___ ___
ou_ ou_
___ ___
Entry: ou_$link_init
generates *system links with initialization information.
Any arguments not specified are as documented for ou_$link.
Usage
dcl ou_$link_init entry (ptr, char (), fixed bin, bit (6),
ptr returns (fixed bin (18) uns));
link_relp = ou_$link_init (state_ptr, offsetname,
expression, modifier,
init_info_ptr);
where:
info_ptr (Input)
is a pointer to a structure describing the
initialization to be done with this link. The
structure is found in the include file
ou_info.incl.pl1
declare init_info_ptr pointer;
declare 1 init_info_header aligned based (init_info_ptr),
2 n_words fixed bin,
/* Zero for NO_INIT */
2 init_type fixed bin;
declare 1 init_no_init aligned based (init_info_ptr),
2 header aligned like init_info_header;
/* type = INIT_NO_INIT */
/* or INIT_DEFINE_AREA */
declare init_info_n_words fixed bin;
declare 1 init_copy_data aligned based (init_info_ptr),
2 header aligned like init_info_header,
2 data (init_info_n_words
refer (init_copy_data.header.n_words)) bit (36) aligned;
declare (
NO_INIT init (0), /* No initialization data */
COPY_DATA init (3), /* Template present */
DEFINE_AREA init (4) /* Make an area */
) fixed bin int static options (constant);
These structures are identical to the init structures documents in the
reference guide.
___ ___
ou_ ou_
___ ___
Entry: ou_$emit
supplies data for the unstructured sections of the object segment.
Usage
dcl ou_$emit entry (ptr, ptr, ptr, fixed bin (18) unsigned, fixed bin returns (fixed bin (18) uns));
section_relp = ou_$emit (state_ptr, data_ptr, reloc_ptr, n_words,
sectionx);
where:
state_ptr (Input)
is a state_ptr from ou_$init.
data_ptr (Input)
is a pointer to data to be placed in the specified
section.
reloc_ptr (Input)
is a pointer to an array of relocation information.
If it is null, absolute relocation will be supplied.
The pointer should point to an array structures
unaligned like ou_relocation, of dimension 2 *
n_words.
declare 1 ou_relocation based,
2 reloc_type bit (6) unaligned,
2 sectionx fixed bin (12) unsigned unaligned;
reloc_type (Input)
is a relocation code from relocation_bits.incl.pl1.
n_words (Input)
is the number of words of data to be put in the text
section.
sectionx (Input)
if nonzero, specified a location counter within one
of the unstructured sections.
relp (Output)
is a relative pointer in the section to the beginning
of the data.
___ ___
ou_ ou_
___ ___
Entry: ou_$set_segment_info
specifies the pathname of the object segment to be
generated, and some per-segment information for the object map.
This entrypoint may be called any time before ou_$finish_segment
is called. If it returns an error code, it may be called again
after the error is corrected.
Usage
dcl ou_$set_segment_info entry (ptr, ptr, fixed bin (35));
call ou_$set_segment_info (state_ptr, segment_info_ptr,
code);
where:
state_ptr (Input)
is a state pointer from ou_$init.
info_ptr (Input)
is a pointer to the ou_segment_info structure
declared in ou_info.incl.pl1.
declare ou_segment_info_ptr pointer;
declare 1 ou_segment_info aligned based (segment_info_ptr),
2 version char (8) aligned,
2 dir_name char (168) unaligned,
2 entryname char (32) unaligned,
2 flags aligned,
3 separate_static bit (1) unal,
3 procedure bit (1) unal,
3 perprocess_static bit (1) unal,
3 standard bit (1) unal,
3 relocatable bit (1) unal,
3 bound bit (1) unal,
2 entry_bound fixed bin (18) unsigned,
2 mode bit (3) aligned;
declare OU_SEGMENT_INFO_V_1 char (8) aligned int static
options (constant);
version (Input)
is the version number of this structure. It must be
SEGMENT_INFO_V_1;
___ ___
ou_ ou_
___ ___
dir_name (Input)
is the directory name of the pathname of the object
segment to be generated.
entryname (Input)
is the entryname of the generated segment.
separate_static (Input)
If this is "1"b, the object segment will have a
separate static section. Otherwise, the static
section will be combined with the linkage section.
For a non-seperate-static segment, ou_ automatically
redirects all references to the static section to the
appropriate part of the linkage section.
procedure (Input)
this flag is reflected in the procedure flag of the
object map, and is respected by the linker and binder
when snapping links.
perprocess_static (Input)
this flag is reflected in the preprocess_static flag
of the object map.
standard (Input)
indicates that the object segment is in standard
format. If it is "0"b, most system routines will
refuse to have anything to do with the segment. It
should only be set off if for some reason you wish to
generate a standard object segment that will only be
examined by your own routines, and is not to be
considered an object segment by system routines.
relocatable (Input)
indicates that appropriate relocation information has
been supplied by the translator to allow binding of
the object segment. Note, though, that in a
multiple-location-counter segment, or one that is
non-seperate-static, a translator that fails to
supply relocation is responsable itself for
backpatching all references to point to the final
location of referenced data. Therefore we STRONGLY
RECOMMEND that relocation information be supplied.
bound (Input)
indicates that the segment is a bound segment. This
bit should only be set on if the translator has put a
correct bind_map into the symbol section. The only
effect of the bound bit is to inform display tools
that a segment has a bind map. Duplicate definition
___ ___
ou_ ou_
___ ___
resolution works with or without the bound flag.
entry_bound (Input)
is the segment entry bound. If this is set to a
value other than zero, the entry_bound attribute of
the segment will be set to it, and the file system
entry bound as well.
mode (Input)
is the file system access mode that the calling
process will be given when the object segment is
finished. Values may be obtained from
access_mode_values.incl.pl1.
code (Output)
is a standard system status code, which will be set
if initiate_file_$create is unable to initiate the
segment with write and read access.
___ ___
ou_ ou_
___ ___
Entry: ou_$make_section
defines a new location counter within an unstructured
section.
Usage
dcl ou_$make_section entry (ptr, char (), fixed bin returns
(fixed bin));
sectionx = ou_$make_section (section_name, class);
where:
section_name (Input)
is the name of the new location counter to be
created. Location counters must be uniquely named.
class (Input)
is the section of the object segment into which the
location counter will be put. If may be
OU_CLASS_TEXT, OU_CLASS_STATIC, or OU_CLASS_SYMBOL.
sectionx (Output)
is the index for this location counter that may be
passed to other ou_ entries.
___ ___
ou_ ou_
___ ___
Entry: ou_$reserve
reserves a block of space in a section, to be filled in
later.
Usage
dcl ou_$reserve entry (ptr, fixed bin, fixed bin (18) uns
returns (fixed bin (18) uns));
location = ou_$reserve (state_ptr, sectionx,
size);
where:
state_ptr (Input)
is a state pointer from ou_$init.
sectionx (Input)
identifies the location counter within which the
space will be reserved.
size (Input)
specifes the number of words to reserve.
location (Output)
is the offset, within the section, of the reserved
space. The tuple of (sectionx, location) uniquely
specifies a location.
___ ___
ou_ ou_
___ ___
Entry: ou_$get_backpatch_ptr
obtains a pointer to space that has been either emitted or
reserved previously. Such a pointer is not valid across future
reserve or emit calls within the same segment. This entry,
together with ou_$backpatch_relocation, allow the translator to
backpatch.
Usage
dcl ou_$get_backpatch_ptr entry (ptr, fixed bin, fixed bin
(18) unsigned returns (pointer));
backpatch_ptr = ou_$get_backpatch_ptr (state_ptr,
sectionx,
location);
call ou_$get_backpatch_ptr (IGNORE THIS);
where:
state_ptr (Input)
is a state pointer from ou_$init.
sectionx (Input)
identifies the section withing which backpatching is
needed.
location (Input)
is the location within the section.
backpatch_ptr (Output)
is a pointer to an array of bit (36) aligned words,
which the caller may set as needed. Note that this
pointer MAY NOT be used after ou_$emit or ou_$reserve
has been called for this section.
ou_$get_backpatch_ptr MUST be called again in this
case.
___ ___
ou_ ou_
___ ___
Entry: ou_$backpatch_relocation
changes the relocation for one or more half-words in the
text or static sections after they have been defined with
ou_$emit or ou_$reserve.
Usage
dcl ou_$backpatch_relocation entry (ptr, fixed bin, fixed
bin (18) uns, bit (1) aligned, fixed bin, ptr);
call ou_$backpatch_relocation (state_ptr, sectionx,
location, right, n_halves, relocs_ptr);
where:
state_ptr (Input)
is a state pointer from ou_$init.
sectionx (Input)
identifies the section within which backpatching is
to be done.
location (Input)
identifies the first word for whom relocation will be
changed.
right (Input)
specifies the first half-word to be changed. If it
is "1"b, the right half-word is the first one. If it
is "0"b, the left half-word is used instead.
n_halves (Input)
is the number of half-word for whom relocation
information is changed.
relocs_ptr (Input)
points to an array of unaligned structures like
ou_relocation, from ou_info.incl.pl1.
___ ___
ou_ ou_
___ ___
Entry: ou_$set_mod
advances a location counter so that a subsequent call to
ou_$emit or ou_$reserve emits data on a particular boundary in
the final object segment. The entire location counter will be
placed in the segment on the boundary demanded by the largest mod
called out in any call to ou_$set_mod. Thus data with extreme
alignment requirements (like pages) should be placed in location
counters of their own.
Usage
dcl ou_$set_mod entry (ptr, fixed bin, fixed bin);
call ou_$set_mod (state_ptr, sectionx, mod);
where:
state_ptr (Input)
is a state pointer from ou_$init.
sectionx (Input)
identifies a location counter to be advanced.
mod (Input)
is the modulus that the location counter will be set
to.
___ ___
ou_ ou_
___ ___
Entry: ou_$add_source
adds a source file to the source map of the object segment,
returning its zero-based "file number."
Usage
dcl ou_$add_source entry (pointer, char (), bit (36)
aligned, fixed bin (71) returns (fixed bin));
file_number = ou_$add_source (state_ptr, pathname,
UID, DTCM);
call ou_$add_source (IGNORE THIS);
where:
state_ptr (Input)
is a state pointer from ou_$init.
pathname (Input)
is a source file absolute pathname. No restrictions
are placed upon the content of this string.
UID (Input)
is the file system UID of the source file.
DTCM (Input)
is the file system date-time contents modified of the
source file.
file_number (Output)
is the file number, suitable for use on a source_map,
of this source file. File numbers are assigned
sequentially from zero.
___ ___
ou_ ou_
___ ___
Entry: ou_$fr_trap
adds a first-reference trap to the segment. A segment may
have any number of first-reference traps.
Usage
dcl ou_$fr_trap entry (ptr, fixed bin (18) unsigned, fixed
bin (18) unsigned);
call ou_$fr_trap (state_ptr, call_link_relp, arg_link_relp);
where:
state_ptr (Input)
is a state pointer from ou_$init.
call_link_relp (Input)
is the offset of a link to the procedure to be called
when the generated segment is first referenced in a
process. It should be obtained from ou_$link.
arg_link_relp (Input)
is a link to information to be passed to the
procedure specified by the call link. The procedure
is called as follows:
call trap_proc (addr (arg_ptr));
so the procedure should be coded as follows:
fr_trap_proc: procedure (arg_ptr_ptr);
dcl arg_ptr_ptr pointer;
dcl arg_ptr pointer based (arg_ptr_ptr);
dcl .... arg .... based (arg_ptr) ...
The variable arg_ptr is actually THE arg_link ITSELF.
Thus, until referenced through, it will have a TAG of
"46"b3 rather than "43"b3. This allows the called
procedure to analyze the link without snapping it.
This is only appropriate in ununual circumstances.
___ ___
ou_ ou_
___ ___
Entry: ou_$finish
finishes the process of generating an object segment. The
location counters are packed into the appropriate sections. All
words with relocation information specifying translator defined
location counters are relocated to reflect their placement within
the object segment. All definitions and links are threaded, and
duplicate name information is generated as neccessary. The ACL
of the segment is set as specified in ou_segment_info.mode, and
the entry_bound is set if neccessary. The segment is terminated.
Usage
dcl ou_$finish entry (ptr);
call ou_$finish (state_ptr);
where:
state_ptr (Input/Output)
is a state pointer from ou_$init. It is nulled when
the object segment is complete.
___ ___
ou_ ou_
___ ___
Entry: ou_$cleanup
frees all storage associated with an ou_ state pointer.
This entrypoint should be called in the cleanup handlers of
translators calling ou_.
Usage
dcl ou_$cleanup entry (ptr);
call ou_$cleanup (state_ptr);
where:
state_ptr (Input/Output)
is a state_ptr from ou_$init. It is nulled.