The following types of elements generated by the compiler itself or from the compiler output have been supported in POSIX hitherto:
| executable file (type X) |
| object generated by the compiler (type O) |
| ar library (type AR; normally containing types X and O) |
We now introduce another object, called a “shared object”. The name “shared object” is derived from UNIX. Other names for shared objects that we also use in certain contexts are “dynamic library” or “shared library” as in UNIX.
In POSIX, a shared object always has the following structure:
| so element (type SO; built from types X, O, AR and SO itself, and from PLAM libraries) |
While generating a shared object, libraries (of type SO and AR) and files with .o extensions can be specified. To use executable files (type X) while generating a shared object, these files must be renamed (see page 14).
Supporting shared objects in POSIX
Shared objects can be reloaded in POSIX while running using an overlay technique (program controlled reloading). The functions dlopen(), dlclose(), dlsym(), dlerror(), and dladdr() are provided for reloading (see "genso - generate a shared object").
In POSIX automatic reloading (like classic BS2000) is only possible for modules of the runtime system CRTE.
Unlike UNIX, POSIX does not support the automatic binding of objects during runtime and the shared coding can not be used by several programs in a shared memory.
Organization (Structure) of a shared object
Physically, a shared object is an ar library which contains object modules that are part of the shared object and a description of the shared object itself. The description of the shared object takes the form of a text file in the ar library. This text file is generated during the generation of the shared object (with the genso command).
The processing of this file is processed during dlopen() is done in the following way:
If no dependent libraries are found, the o files are loaded in reverse order as specified in the file.
If a dependent shared object exists, then a new list is generated. The dependent shared object is appended to the end of this list.
Another search is then made for the first dependent object in the new list. This may be a dependent object of the first dependent object.
This is repeated until all dependent objects (and dependent objects of these objects, ...) are replaced by listed o files. Checks are made to avoid recursion. Finally, this results in a list containing only o files which will then be loaded as specified in the list. This resolution of an so file is what is described as dependency ordering in the description of dlopen().
The handling of ar files is the same as for o files; an ar file is considered as an ordered set of o files.
Example
Here is a typical example of such a description. This is the description of the example 1 of the genso command (see "genso - generate a shared object").
Shared object description for file libtest21.so:
DLL? /posix315/bachmann/sharedlib/examples/libtest21.so ofile_GM_.o ##### /posix315/bachmann/sharedlib/examples/test21.o ###SO### /posix315/bachmann/sharedlib/examples/libtest22.so libtest22.so ###SO### /posix315/bachmann/sharedlib/examples/libtest23.so libtest23.so -X lang=c
Shared object description for file libtest22.so:
DLL? /posix315/bachmann/sharedlib/examples/libtest22.so ofile_GM_.o ##### /posix315/bachmann/sharedlib/examples/test22.o ###SO### /posix315/bachmann/sharedlib/examples/libtest24.so libtest24.so -X lang=c
Shared object description for file libtest23.so:
DLL? /posix315/bachmann/sharedlib/examples/libtest23.so ofile_GM_.o ##### /posix315/bachmann/sharedlib/examples/test23.o -X lang=c
Shared object description for file libtest24.so:
DLL? /posix315/bachmann/sharedlib/examples/libtest24.so ofile_GM_.o ##### /posix315/bachmann/sharedlib/examples/test24.o -X lang=c
The elements of this shared object have the following appearance when they are processed by dlopen().
Object libtest21.so:
ofile_GM_.o (libtest21.so) libtest22.so libtest23.so
Object libtest22.so:
ofile_GM_.o (libtest22.so) libtest24.so
Object libtest23.so:
ofile_GM_.o (libtest23.so)
Object libtest24.so:
ofile_GM_.o (libtest24.so)
The reference to libtest22.so in the description of libtest21.so is replaced by the description of libtest22.so in a first step. This produces the following arrangement:
ofile_GM_.o (libtest21.so) ofile_GM_.o (libtest22.so) libtest24.so libtest23.so
This procedure is repeated until finally the following is produced.
ofile_GM_.o (libtest21.so) ofile_GM_.o (libtest22.so) ofile_GM_.o (libtest24.so) ofile_GM_.o (libtest23.so)
The elements are then loaded in this order.