Headers serve as a cover page and table of contents for the object file. They contain size descriptions, magic numbers, and pointers to other sections.
The object file components covered in this chapter are the file header, a.out
header, and section headers:
a.out
header provides the size, location, and addresses of the object's segments.
An object file may contain other header sections that are used to navigate the symbol table and dynamic loading information. The symbolic header and dynamic header are discussed in Chapter 5 and Chapter 6 respectively.
Version 3.13 of the object file format does not introduce any new header features.
filehdr.h
)struct filehdr { coff_ushort f_magic; coff_ushort f_nscns; coff_int f_timdat; coff_off f_symptr; coff_int f_nsyms; coff_ushort f_opthdr; coff_ushort f_flags; };
SIZE - 24 bytes, ALIGNMENT - 8 bytes
File Header Fields
f_magic
f_nscns
f_timdat
f_symptr
f_nsyms
f_opthdr
a.out
header (in bytes). f_flags
Symbol |
Value |
Description |
|
|
Object file. |
|
|
Compressed object file. |
|
|
Ucode object file. Obsolete. |
Symbol |
Value |
Description |
|
|
File does not contain relocation information. This flag applies to actual relocations only, not compact relocations. |
|
|
File is executable (has no unresolved external references). |
|
|
Line numbers are stripped from file. |
|
|
Local symbols are stripped from file. |
|
|
Currently unused. |
|
|
Object file cannot be used to create a |
|
|
Allows a static executable file to be loaded at an address less than |
|
|
Shared library. |
|
|
Dynamic executable file. |
|
|
Tells object consumer not to reorder sections. |
|
|
Tells object consumer not to remove |
aouthdr.h
)The a.out
header is also referred to as the "optional header". Note that "optional" is a misnomer because the header is actually mandatory.
typedef struct aouthdr { coff_ushort magic; coff_ushort vstamp; coff_ushort bldrev; coff_ushort padcell; coff_long tsize; coff_long dsize; coff_long size; coff_addr entry; coff_addr text_start; coff_addr data_start; coff_addr bss_start; coff_uint gprmask; coff_word fprmask; coff_long gp_value; } AOUTHDR;
SIZE - 80 bytes, ALIGNMENT - 8 bytes
a.out
Header Fields
magic
vstamp
stamp.h
header file:
|
3 |
High byte |
|
13 |
Low byte |
bldrev
stamp.h
and is updated for each major release of the operating system. The values for Tru64 UNIX releases to date are shown below. This field is not meaningful to users.
Release |
1.2 |
1.3 |
2.0 |
3.0 |
3.2 |
4.0 |
5.0 |
bldrev |
- |
2 |
4 |
6 |
8 |
10 |
12 |
tsize
ZMAGIC
object files, this value includes the size of the header sections (file header, a.out
header, and all section headers). See Section 2.3.2 for more information.dsize
bsize
entry
text_start, data_start, bss_start
gprmask
fprmask
gp_value
entry
field will load its GP value into the GP register, which may or may not be different than the value in this field for objects with multiple GP ranges. See Section 2.3.4. This value is also used by the linker as a basis for relocation adjustments in objects. See Section 4.3.3.2.a.out
Header Magic Numbers
Symbol |
Value |
Description |
|
0407 |
Impure format. The text segment is not write-protected or shareable; the data segment is contiguous with the text segment. An |
|
0410 |
Shared text format. |
|
0413 |
Demand-paged format. The text and data segments are separated and the text segment is write-protected and shareable. The object can be a dynamic or static executable, or a shared library. All shared objects use a |
scnhdr.h
)struct scnhdr { char s_name[8]; coff_addr s_paddr; coff_addr s_vaddr; coff_long s_size; coff_off s_scnptr; coff_off s_relptr; coff_ulong s_lnnoptr; coff_ushort s_nreloc; coff_ushort s_nlnno; coff_uint s_flags; };
SIZE - 64 bytes, ALIGNMENT - 8 bytes
Section Header Fields
s_name
s_paddr
s_vaddr
, normally s_vaddr
is used and s_paddr
is ignored. s_vaddr
.comment
..tlsdata
and .tlsbss
, this field contains an offset from the beginning of the object's dynamically allocated TLS region. s_size
s_scnptr
s_size
field, is mapped at s_vaddr
(if non-zero) in the process image. .bss
, this field is set to zero.s_relptr
s_lnnoptr
.lita
section header, indicates number of GP ranges used for the object:
Value |
Meaning |
0 |
Object has one GP range. |
1 |
Invalid value. |
2 or higher |
Object has this number of GP ranges. |
R_GPVALUE
relocation entries for that section. In .pdata
this field contains the number of runtime procedure descriptors.V3.13
and greater.s_nreloc
0xffff
if number of entries overflows size of this field (see Table 2-5). s_nlnno
s_flags
Symbol |
Field Contents |
Description |
|
|
Text section |
|
|
Initialization text section |
|
|
Termination (clean-up) text section |
|
. |
Read-only constant section |
|
|
Read-only data section |
|
|
Large data section |
|
|
Literal address pool section |
|
|
8-byte literal pool section |
|
|
4-byte literal pool section |
|
|
Small data section |
|
|
Large bss section |
|
|
Small bss section |
|
|
Ucode section (obsolete) |
|
|
Global offset table |
|
|
Dynamic linking information |
|
|
Dynamic linking symbol table |
|
|
Relocation information |
|
|
Dynamic linking strings |
|
|
Dynamic symbol hash table |
|
|
Additional dynamic linking symbol table |
|
|
Shared library dependency list |
|
|
Additional dynamic linking information |
|
|
Exception scope table |
|
|
Exception procedure table |
|
|
Initialized TLS data |
|
|
Uninitialized TLS data |
|
|
Initialization for TLS data |
|
|
Comment section |
Table Notes:
xdata
and .pdata
sections respectively contain the run-time procedure descriptors and code range descriptors that enable exception-handling. See the Calling Standard for Alpha Systems for details. Other sections are described in Chapter 3. s_flags
field)
Symbol |
Value |
Description |
|
|
Regular section: allocated, relocated, loaded. User section flags have this setting. |
|
|
Text only |
|
|
Data only |
|
|
Bss only |
|
|
Read-only data only |
|
|
Small data only |
|
|
Small bss only |
|
|
Obsolete |
|
|
Global offset table |
|
|
Dynamic linking information |
|
|
Dynamic linking symbol table |
|
|
Dynamic relocation information |
|
|
Dynamic linking symbol table |
|
|
Dynamic symbol hash table |
|
|
Shared library dependency list |
|
|
Additional dynamic linking symbol table |
|
|
Additional dynamic linking information |
|
|
Termination text only |
|
|
Comment section |
|
|
Read-only constants |
|
|
Exception scope table |
|
|
Initialized TLS data |
|
|
Uninitialized TLS data |
|
|
Initialization for TLS data |
|
|
Exception procedure table |
|
|
Address literals only |
|
|
8-byte literals only |
|
|
Identifies bits used for multiple bit flag values. |
|
|
4-byte literals only |
|
|
Indicates that section header field |
|
|
Initialization text only |
Table Notes:
S_NRELOC_OVFL
flag is used when the number of relocation entries in a section overflows the s_nreloc
field in the section header. In this case, s_nreloc
contains the value 0xffff
and the s_flags
field has the S_NRELOC_OVFL
flag set. The actual relocation count is in the first relocation entry for the section. General Notes:
The system linker uses the s_flags
field instead of s_name
to determine the section type. User-defined sections (see Section 3.3.10) constitute an exception; they are identified exclusively by section name.
Each section header must be unique within the object file. For system-defined sections, both the section name and flags must be unique. For user-defined sections, the name must be unique.
Object file consumers use the file header to recognize an input file as an object file. Other tools that do not support objects may use the file header to determine that they cannot process the file. The file
tool can also identify an object by means of the file and a.out
headers.
A file is identified as an object in its first 16 bits. These bits correspond to the magic number field in the file header. Objects built for the Alpha architecture are identified by the magic number ALPHAMAGIC
; equivalent compressed objects are identified by ALPHAMAGICZ
. Foreign objects, which are objects built for other architectures, may also be positively identified. However, once a foreign object is recognized, it is not considered to be a linkable or executable object file on the Alpha system.
In addition to providing basic identification, the file header also provides a high-level description of the object file through its flags
field. File header flags store the following information: whether the object is executable, whether symbol table sections have been stripped, whether the file is suitable for creation of a shared library, and more. See Table 2-2 for a list of all flags.
The a.out
header magic numbers also contribute important information about the file format. The magic numbers signify different organizations of object file sections and indicate where the image will be mapped into memory (see Section 2.3.2).
The a.out
header stores run-time information about the object. Its magic number field indicates how the file is to be organized in virtual memory. Note that the contents and ordering of the sections of the image can be affected by compilation options and program contents in addition to the MAGIC
classification.
The possible image formats are:
OMAGIC
) OMAGIC
files are typically relocatable object files. They are referred to as "impure" because the text segment is writable.
NMAGIC
) NMAGIC
files are static executables that use a different organization from the default ZMAGIC
layout. The NMAGIC
format is historical and offers no special advantages. This format can be selected by using the linker option -n
or -nN
in conjunction with -non_shared
. In an NMAGIC
file, the text segment is shared.
ZMAGIC
) ZMAGIC
files are executable files or shared libraries. This format is referred to as demand-paged because its segments are blocked on page boundaries, allowing the operating system to page in text and data as needed by the running process. By default, the linker aligns ZMAGIC
segments on 64K boundaries, the maximum possible page size on Alpha systems.
The ordering of sections within segments is flexible. Diagrams in this section depict the default ordering as laid out by the linker.
The default segment ordering, which places the text segment before the data segment, is flexible. However, the bss segment is required to contiguously follow the data segment, wherever the data segment is located.
All three formats are constrained by the following restrictions:
bss
segment must follow the data segment.
0x7fff8000
) of all data addresses in the file. The OMAGIC
format typically has the following layout and characteristics:
OMAGIC
Layout0x7fff8000
) of all data addresses in the file.
OMAGIC
objects are zero-based, with the data segment contiguous to the text segment. The default text segment address for partially linked objects is 0x10000000
, and the data segment follows the text segment.
Starting addresses can be specified for the text and data segments using -T
and -D
options. These addresses can be anywhere in the virtual address space but must be aligned on a 16-byte boundary.
OMAGIC
layout is most commonly used for pre-link object files produced by compilers. Post-link OMAGIC
files tend to be used for special purposes such as loadable device drivers or om input objects.
Loadable device drivers must be built as OMAGIC
files because the kernel loader kloadsrv
relies upon relocation information in order to link objects into the kernel image.
OMAGIC
files can also be executable. An important example of an OMAGIC
executable file is the kernel, /vmunix
. A programmer might also choose to use an OMAGIC
format for self-modifying programs or for any other application that has a reason to write to the text segment.
The NMAGIC
file format is of historical interest only.
The NMAGIC
format typically has the following layout and characteristics:
NMAGIC
Layout0x7fff8000
) of all data addresses in the file.
0x20000000
and the starting address of the data segment is 0x40000000
.
Addresses can be specified for the start of the text and data segments using -T
and -D
options. These addresses may be anywhere in the virtual address space but must be a multiple of the page size.
The ZMAGIC
format typically has the following layout and characteristics:
ZMAGIC
Layout for Shared ObjectZMAGIC
Layout for Static Executable ObjectsThe .rdata
and .tlsinit
sections are shown as part of the text segment. However, it is possible that one or both of those sections might be in the data segment. They are placed in the data segment only if they contain dynamic relocations.
0x7fff8000
) of all data addresses in the file.
0x120000000
and the starting address of the data segment is 0x140000000
. The bss segment follows the data segment.
Addresses can be specified for the start of the text and data segments using -T
and -D
options. Those addresses can be anywhere in the virtual address space but must be a multiple of the page size.
At load time, an executable object is mapped into the system's virtual memory using one of the formats detailed in Section 2.3.2. The user can choose where the object, transformed into the program image, will be loaded, but system-specific constraints exist. This section discusses the general layout of the address space and the various considerations involved in choosing memory locations for object file segments.
Figure 2-5 shows the default memory scheme for a dynamic image.
The stack is used for storing local variables. It grows toward zero. The stack pointer (stored in register $sp
) points to the top of the stack at all times. In generated code, items on the stack are often referenced relative to the stack pointer.
The program heap is reserved for system memory-allocation calls (brk()
and sbrk()
). TLS sections are allocated from the heap. The heap begins where the bss segment of the program ends, and the special symbol _end
indicates the start of the heap. The heap's placement can also be calculated using the starting addresses and sizes of segments in the a.out
header. The mapping of shared libraries may impose an upper bound on the heap's size. Some programs do not have a heap.
The dynamic loader and shared libraries reside in memory during program execution. See Section 6.3.2 for details.
User programs can request additional memory space that is dynamically allocated. One way to request space is through an anonymous mmap()
call. This system call creates a new memory region belonging to the process. The user can attempt to specify the address where the region will be placed. However, if it is not possible to accomodate that placement, the system will rely on environment variables to dictate placement. See the mmap(2)
man page for details.
The usable address range for user mode addresses is 0x0 - 0x800000000000
. Attempts to map object file segments outside this range will fail, and the defaults will be invoked or execution aborted.
Several mechanisms permit the user to select addresses for loadable objects or assist the user in choosing viable addresses. Unless there is a good reason to do otherwise, it is preferable to rely on system defaults, which are designed to enhance performance and reduce conflicts.
The linker's -T
and -D
options may be used to specify the starting addresses for the text and data segments of an executable, respectively. Use of these options may be appropriate for large applications with dependencies on many shared libraries that need to explicitly manage their address space. Programs relying in any way on fixed addresses may also need to control the segment placement.
Another use of the address selection options is to place an application in the lowest 31 bits of the address space. To restrict an application to this part of the address space, the -T
and -D
switches may be used in conjunction with the -taso
option (see Section 2.3.3.2) or separately.
The default placement of the text and data segments at 0x120000000
and 0x140000000
for executables means the default maximum size of the text segment is 0x20000000
bytes, or approximately 500MB. If this space is insufficient, the -D
option can be used to enlarge it by specifying a higher starting address for the data segment.
The -T
and -D
options can also be used to change the segment ordering. Some applications, such as those ported from other platforms onto the Alpha platform, may rely upon the data segment being mapped in lower addresses than the text segment.
If only -T
or only -D
is specified on the link line, system defaults are used for the nonspecified address. If a given address is not properly aligned, the linker rounds the value to the applicable boundary. If inappropriate addresses are chosen, such as addresses for the text and data segments that are too far apart, linking may fail. Alternatively, linking may succeed, but execution can abnormally terminate if addresses are incompatible with the system memory configuration.
The linker option -B
, which specifies a placement for the bss segment, is available for partial links only. For executable objects, the bss segment should be contiguous with the data segment, which is the system default. As a general rule, the -B
option should not be used.
Another mechanism permits address selection for shared libraries. A registry file, by default named so_locations
, stores shared library segment addresses and sizes. The so_locations
directives, described in the Programmer's Guide, can be used to control the linker's address selection for shared libraries.
The TASO (Truncated Address Space Option) address space is a 32-bit address-space emulation that is useful for porting 32-bit applications to 64-bit Alpha systems. Selection of the -taso
linker option causes object file segments to be loaded into the lower 31 bits of the memory space. This can also be accomplished, in part, by using -T
and -D
. If the -taso
option is used in conjunction with the -T
or -D
options, the addresses specified with -T
and -D
take precedence.
Use of the -taso
option also causes shared libraries linked outside the 31-bit address space to be appropriately relocated by the loader. All executable objects and shared libraries will be mapped to the address range 0x0 - 0x7fffffff
.
The default segment addresses for a TASO executable are 0x12000000
for the text segment and 0x14000000
for the data segment, with the bss segment directly following the data segment. The -T
and -D
options can be used to alter the segment placement if necessary.
Figure 2-6 is a diagram of the TASO address space layout.
A TASO shared object is marked as such with the RHF_USE_31BIT_ADDRESSES
flag in the DT_FLAGS
entry in the dynamic header. The loader recognizes dynamic executable objects marked with the TASO flag and maps their shared library dependencies to the TASO address space. A TASO static executable is not explicitly identified.
Programs running on Tru64 UNIX obtain the addresses of procedures and global data by means of a GP (Global Pointer) and an address table. Address ranges and address-table sections (.lita
and .got
) are described further in Section 3.3.2 and Section 6.3.3. However, several important pieces of information concerning GP-relative addressing are contained in the headers.
During program execution, the global pointer register ($gp
) contains the active GP value. This value is used to access run-time addresses stored in the image's address-table section. Addresses are specified in generated code as an offset to the GP.
There are several reasons for using this GP-relative addressing technique:
A GP range is the set of addresses reachable from a given GP. The size of this range is approximately 64KB, or 8K 64-bit addresses.
Although only one GP value is active at any time, a program can use several GP values. A program's text can be divided into ranges of addresses with a different GP value for each range. The linker will start a new GP range at a boundary between two input object file's section contributions. As a result, a GP range will rarely be filled before a new GP range is started. Regardless of how much of a GP range is actually used, the linker always sets the GP value associated with that range as follows:
GP value = GP range start address + 32752
Figure 2-7 is a depiction of the use of GP values and ranges.
Objects can share a GP range, as shown in Figure 2-7, or use more than one GP range, depending on the amount of program data. However, the Calling Standard for Alpha Systems specifies that a single procedure can use only one GP value. The a.out
header's gp_value
field contains either the GP value of the object (if there is only one) or the first one the program should use (if there are multiple GP ranges).
How the number of GP ranges is represented in an object depends on the object's type:
.lita
section, the section header field s_nlnnoptr
indicates the number of GP ranges, as explained in Section 2.2.3.
OMAGIC
file), a new GP range is signalled by a R_GPVALUE
relocation entry. See Section 4.3.4.18 for details.
.dynamic
), which are described in Section 6.2.1. Alignment is an architectural issue that must be dealt with in the object file at several levels: object file segments, object file sections, and program variables all have alignment requirements.
Data alignment refers to the rounding that must be applied to a data item's address. For natural alignment, a data item's address must be a multiple of its size. For example, the natural alignment of a character variable is one byte, and the natural alignment of a double-precision floating-point variable is 8 bytes.
On Alpha systems, all data should be aligned on proper boundaries. Unaligned references can result in substantially slower access times or cause fatal errors. The compiler and the user have some control over the alignments through the use of assembler directives and compilation flags (see the Programmer's Guide and Assembly Language Programmer's Guide). When designing alignment attributes, however, the architectural cost of loading unaligned values should be considered.
Object file segments are, by default, aligned as indicated in Section 2.3.2. Segment alignment can be impacted by section alignment. The segment alignment must be evenly divisible by the highest sectional alignment factor for sections contained in that segment.
Object file sections may have a power-of-two alignment factor specified in their section headers (see Section 2.2.3). The default sectional alignment is 16 bytes.
The default alignment boundary for raw data is 16 bytes. Smaller alignments can be applied to invidual data items allocated in raw section data. If a data item must be aligned with greater than 16 byte alignment, the section in which it is allocated must be aligned with a power-of-two alignment factor that is greater than or equal to the data item's required alignment.
Individual data items should meet the following minimum requirements. Structure members and array elements are aligned according to the minimum requirements in order to minimize pad bytes between members. Other data items are typically aligned with 8 or 16 byte rounding due to alignment requirements imposed by the generated code used to access data addresses.
value
field for a common storage class symbol indicates its size and determines which section it will be allocated in (.bss
or .sbss
). All common storage class symbols with a size of 16-bytes or greater are aligned to octaword (16-byte) boundaries. All other common storage class symbols are aligned to quadword (8-byte) boundaries. Sections are padded wherever necessary to maintain proper alignment. Padding is done with zero bytes in the data and bss sections. In the text segment, each routine is padded with NOP
instructions to a 16-byte boundary. The section sizes reported in the section headers and the segment sizes reported in the a.out
header reflect this padding.
The primary unit of an object file is a section, and the sections in an object are identified, located, and broadly characterized by means of the section headers. Object files are organized into sections primarily to enable the linker to combine multiple input objects into an executable image. At link time, sections of the same type are concatenated or merged. The sectional breakdown also provides the linker flexibility in segment mapping; the linker has a choice in assigning sections to segments for memory-mapping and loading.
Section headers include flags that describe the section type. These flags identify the section type and attributes. See Table 2-5 for a complete listing of section flags. Note that the s_flags
field cannot be treated as a simple bit vector when testing or accessing section types because some of the flag values are overloaded. The algorithm below illustrates how to test for a particular section type using the s_flags
field.
if (type & STYP_EXTMASK) FOUND = ((SHDR.s_flags & STYP_EXTMASK) == type) else FOUND = (SHDR.s_flags & type)
Sections can be mapped or unmapped. A mapped section is one that is part of the process image as well as the object file. An unmapped section is present only in the on-disk object file.
Raw data, organized by section and segment, is part of the process image. For a ZMAGIC
file, all header sections in the object are also mapped into memory as part of the text segment. However, the .comment
section is never loaded with a program.
Some special symbol names are reserved for use by the linker or loader. The majority of these special symbols correspond to locations in the image layout.
Table 2-6 describes the special symbols and indicates whether they are reserved for the linker or the loader. Additional special symbols for debug information are described in Section 5.3.9.
Linker Reserved Symbols |
||
Symbol |
Description |
|
|
Base address of text segment. |
|
|
First COBOL main symbol; undefined if not a COBOL program. |
|
|
Starting address of |
|
|
Value is 1 if a dynamic executable file; otherwise, zero. |
|
|
End of bss segment. |
|
|
End of data segment. |
|
|
Weak symbol for end of data segment. |
|
|
End of bss segment. |
|
|
Weak symbol for end of bss segment. |
|
|
End of text segment. |
|
|
Weak symbol for end of text segment. |
|
|
First location of bss data. Usually the virtual address of either the |
|
|
First location of initialized data. Usually the virtual address of the |
|
|
Start of |
|
|
Number of entries in |
|
|
Start of |
|
|
First location of executable text. Usually the virtual address of the |
|
|
The address of the |
|
|
Starting address of |
|
|
GP value stored in |
|
|
Table of GP ranges used exclusively by exception handling code. |
|
|
Start of |
|
|
String table for run-time procedures |
|
|
Run-time procedure table. |
|
|
Number of entries in run-time procedure table. |
|
|
Size of the |
|
|
Size of the |
|
|
The value of this symbol is the address of the GOT or |
|
|
Offset in the TSD array of the TLS pointer for a particular object. For static executables, this value is set at link time. For shared objects, the value is set to 0 at link time and filled in at run time. |
|
|
The number of TLS regions (TSD entries) that are used by an executable or library. |
|
Loader Reserved Symbols |
||
|
Points to loader's data structures. |
|
|
Weak symbol pointing to loader's data structures. |
|
|
The generic loader entry point servicing all loader function calls. |
Table Notes:
RPDR
stuctures (their declaration is in the header file sym.h
). The table is a subset of the procedure descriptor table portion of the symbol table with one additional field, exception_info
. When the procedure table entry is for an external procedure and an external symbol table exists, the linker fills in exception_info
with the address of the external symbol. Otherwise, it fills in exception_info
with zeros. The linker defines special symbols only if they are referenced.
The majority of these symbols have local binding in a shared object's dynamic symbol table. Consequently, a shared object can only reference its own definition of these symbols. However, several special symbols have global scope. The linker-defined symbols end
, _end
, __istart
, and _cobol_main
are global, which implies that each has a unique value process-wide. The symbol _end
and its weak counterpart end
are used by libc.so
to identify the start of the heap in memory. The symbol _cobol_main
gives a COBOL program's main entry point.
Special symbols in addition to those listed in Table 2-1 are defined by the linker to represent object file section addresses:
.bss .comment .data .fini .init .lit4 .lit8 .lita .pdata .rconst .rdata .sbss .sdata .text .xdata
The value of the symbol is the starting address of the corresponding section. These symbols generally are not referenced by user code. For shared objects, they may appear in the dynamic symbol table.
A user program can reference, but not define, reserved symbols. An error message is generated if a user program attempts to define a symbol reserved for system use.
A special symbol is a label, and thus its value is its address. Interpreting a label's contents as its value may lead to an access violation, particularly for those linker-defined symbols that are not address locations within the image (for example, _DYNAMIC_LINK
or _procedure_table_size
).
The following example shows how linker-defined labels are referenced in code:
$ cat proctab.c #include <stdio.h> extern _procedure_table_size; extern _procedure_string_table; main(){ int i; void *tempsize=&_procedure_table_size; void *tempstring=&_procedure_string_table; long size=(long) tempsize char *string=(char *) tempstring; printf("\n Procedure Table Size=%d\n\n",size); for (i=0;i < size;i++){ printf("%d: %s\n",i+1,string); string+=strlen(string)+1; } } $ a.out Procedure Table Size=11 1: static procedure (no name) 2: main 3: __start 4: exit 5: _mcount 6: __eprol 7: eprol 8: printf 9: strlen 10: __exc_add_pc_range_table 11: __exc_add_gp_range $
This example prints out the names stored in the run-time procedure string table. The string table consists of character strings of varying lengths separated by null characters.
The linker-defined symbol _cobol_main
is set to the symbol value of the first external symbol encountered by the linker with its cobol_main
flag set. COBOL programs use this symbol to determine the program entry point.