










               UUssiinngg sshhaarreedd lliibbrraarriieess iinn QQNNXX 44..2211


                    QNX Software Systems Ltd
                 175 Terrence Matthews Crescent
                     Kanata, Ontario Canada.





The  QQNNXX  Operating System Release 4.21 provides an efficient and
flexible mechanism for creating and using shared libraries.   The
mechanism  is  based upon a one in UNIX System V Release 3.2, and
all deviations from this _s_t_a_n_d_a_r_d are mentioned.

     This technical note addresses how to design and build shared
libraries,  and  assumes the reader is familiar the C Programming
Language, the QNX Operating System and  development  system,  and
library design in general.

     The paper is divided into the following sections:

 (1)   Introduction to shared libraries.

 (2)   Designing a shared library.

 (3)   Using the shared library builder mmkksshhlliibb..

11..  IInnttrroodduuccttiioonn ttoo sshhaarreedd lliibbrraarriieess..

     Shared  libraries  are a refinement over static libraries in
that multiple programs share the memory required by the  library.
This  sharing  makes more memory available to other programs, and
reduces the amount of disk and network traffic for  loading  pro-
grams.   Well  designed  shared  libraries  can be upgraded while
maintaining compatability with client applications. 1

     The shared library and any client are separate  binary  pro-
grams  which  join  (or _d_y_n_a_m_i_c_a_l_l_y-link) at runtime.  Before the
client is eexxeecc'd the shared library can be updated, however while
the  program  is  running, the same shared library must remain in
effect.
____________________
   Notice that a _p_o_o_r_l_y designed shared library fairs no worse in
this  respect  than  a static library.  Upgrades require applica-
tions be relinked (or re-compiled).




QQNNXX SSHHAARREEDD LLIIBBRRAARRIIEESS                                            11







22                                            QQNNXX SSHHAARREEDD LLIIBBRRAARRIIEESS


     This section concentrates on  the  basics  of  linking,  and
illustrates a simple mechanism for constructing shared libraries.

11..11..  SSttaattiicc LLiinnkkiinngg

     An object program may contain two types of symbols: resolved
and  unresolved.   A  resolved symbol is a label for some unit of
code or data which: is defined within a given object program; and
is  available  for  other  object programs to use.  An unresolved
symbol is a symbol which is used within an  object  program,  but
not  defined  within  that  program.  This is typically called an
_u_n_r_e_s_o_l_v_e_d _r_e_f_e_r_e_n_c_e.

     When  a  program  is linked2 the linker constructs a list of
unresolved references from the given  object  modules.   It  then
searches  a  set  of  libraries,  extracting object modules which
resolve at least one unresolved reference.  The contents of these
modules  are appended to the program, and any new unresolved ref-
erences are added to the  list.   This  process  continues  until
either

 (1)   The list of unresolved references becomes empty

 (2)   All libraries are scanned without discovering a definition
       for a given symbol.

This processing is ssttaattiicc lliinnkkiinngg , where static implies that all
addresses have been assigned and are immutable.

11..22..  AA ssiimmppllee sshhaarreedd lliibbrraarryy sscchheemmee

     Here  is  a  shared  library scheme which relies only upon a
static linker and some form of shared memory within the operating
system.  There are two parts to this implementation: the hhoosstt and
ttaarrggeett libraries.  The hhoosstt library is a library which is  stati-
cally  linked  with  applications  which  wish  to use the shared
library.  These applications  are  called  _c_l_i_e_n_t_s_.   The  ttaarrggeett
library contains the actual code and data for the shared library.
The target is somehow installed into  the  system  shared  memory
pool;  and the host locates it at program startup.  The steps are
as follows:

 (1)   The shared library implementor chooses a range of  virtual
       addresses  the  target library will occupy.  A simple pro-
       gram is then built which includes all of the  object  pro-
       grams  and  a short mmaaiinn() which allocates a shared memory
____________________
   The terms _l_i_n_k_e_d and _l_i_n_k_e_r are known in other operating  sys-
tems  as  _l_i_n_k_-_e_d_i_t_e_d_, _l_i_n_k_-_e_d_i_t_o_r or _l_o_a_d_e_d_, _l_o_a_d_e_r_.  This tech-
note uses _l_i_n_k_e_d and _l_i_n_k_e_r_.  All such references will be to  the
program //bbiinn//cccc which in turn uses //bbiinn//wwlliinnkk.












QQNNXX SSHHAARREEDD LLIIBBRRAARRIIEESS                                            33


       region and copies itself into this region.   The  building
       of this program will need to perform some operation to set
       the base virtual address of the program to lower bound  of
       the  chosen  address range.  In QNX, the //bbiinn//cccc option --@@
       allows the user to specify a base virtual address for  the
       program.

 (2)   Determine  what  symbols  from  the  target should be made
       available to the client.  From this list; examine the tar-
       get library and extract the actual addresses of these sym-
       bols.

 (3)   Build a host library such that the symbols from  step  (2)
       are  assigned  absolute  addresses3  In QNX, the following
       assembly statements can be used  to  give  X  an  absolute
       address of $$0000000011223344:


             ......
            ppuubblliicc XX
            XX eeqquu 0000000011223344hh
             ......



 (4)   Write  a  _b_i_n_d  function which locates and maps the shared
       memory region containing the  target  library.   Add  this
       function to the host library.

 (5)   Change  client  code  to  invoke  the _b_i_n_d function at the
       begining of the program.

 (6)   Rebuild the client program remembering to set  a  compiler
       option to reserve the address range necessary for the tar-
       get library.

     The above scheme, with some refinements,  is  used  for  QNX
shared  libraries.  Most of the _w_o_r_k mentioned above is performed
by shared library builder mmkksshhlliibb..  The designed of  the  library
still has to:

 (1)   Select the address range for the library.

 (2)   Select which symbols should be available to client.

     Some of the refinements in the scheme used in QNX:

 (1)   A  _b_r_a_n_c_h  _t_a_b_l_e  is  employed  to redirect function calls
       within  the  target  library.   That   is,   the   address
____________________
   This is a common facility in assemblers and linkers.












44                                            QQNNXX SSHHAARREEDD LLIIBBRRAARRIIEESS


       associated  with  a  function  symbol  in the host library
       doesn't refer to the actual function address in  the  tar-
       get.   The  address  points  to  one  of a table of _b_r_a_n_c_h
       instructions within the target.  MMkksshhlliibb insures that  the
       address  of this branch table does not accidentally change
       in subsequent revisions of the library.

 (2)   Symbols may be _i_m_p_o_r_t_e_d into the target library  from  the
       client application.

 (3)   An  arrangement  between  mmkksshhlliibb  and  cccc allows the host
       library to specify the virtual address range  occupied  by
       the  target,  thus users of a host library needn't specify
       address ranges, etc...

These aspects are examined in greater detail later in this paper.
There  is  one  golden  rule,  however that bears repeating.  The
branch table  insures  that  function  addresses  within  a  host
library  will  be stable for subsequent revisions of the library.
No such guarantee is made about data; thus  DDOO  NNOOTT  EEXXPPOORRTT  DDAATTAA
FFRROOMM AA SSHHAARREEDD LLIIBBRRAARRYY.  You have been warned.

     The following sub-sections describe the contents of the host
and target libraries produced by mkshlib.

11..22..11..  TThhee hhoosstt sshhaarreedd lliibbrraarryy

     The host library contains a  set  of  object  modules  which
interface to the shared library.  There are three types of inter-
face modules in the QQNNXX version: IInniitt,, CCoonnttrrooll,, and AAddddrreessss..

11..22..11..11..  IInniitt mmoodduulleess

     The init modules contain code  and  data  which  ddyynnaammiiccaallllyy
links  the application to the target library.  This dynamic link-
ing process is very primative.  It has no notion of symbol  names
nor  data types.  It involves a simple name/version number lookup
for the target library as a whole; mapping of memory ranges  with
permissions and sharing modes; copying of tables for pointer ref-
erences.

     The init module  is  custom  build  by  the  shared  library
builder mmkksshhlliibb for each target library.  This processing is per-
formed after the program has started execution, but before either
mmaaiinn  (or static constructors in CC++++) are called.  If the dynamic
link fails, a function is indirectly invoked through the  pointer
____sshhoobbjj__bbiinndd__ffaaiilleedd,  which  takes  a  single pointer to a uu__bbiinndd
structure.  The pointer, by default, points at a function which:

 +o prints the name of the shared library.
 +o prints the string corresponding to the current value of eerrrrnnoo.
 +o invokes __eexxiitt((11))..











QQNNXX SSHHAARREEDD LLIIBBRRAARRIIEESS                                            55


The     source     for     the     default    handler    is    in
//uussrr//lliibb//sshhlliibb//mmkksshhlliibb..sskkeell.

     If the target library requires floating point support, mmkksshh--
lliibb  builds  the  init  module  such that the linker will include
floating point support in the program.

11..22..11..22..  CCoonnttrrooll mmoodduulleess

     There is  a  convention  in  the  program  //bbiinn//cccc  to  scan
libraries  for  files  with the name prefix --@@..  Rather than link
these files into the executable, these filenames are used to con-
trol  the  link  process.  For example the filename --@@1100000000,,6600000000
within a host library would instruct the linker to  reserve  hex-
adecimal  address  range  10000..6ffff  for  the  target library.
These modules  are  custom  build  by  mmkksshhlliibb  for  each  target
library.

     It  is  important  not  to use the _#_p_r_a_g_m_a _l_i_b_r_a_r_y directive
when using shared libraries.  If the //bbiinn//cccc command does not _s_e_e
the  library  name;  it  cannot  know to generate the appropriate
linker directives.

11..22..11..33..  AAddddrreessss mmoodduulleess

     These modules contain _a_b_s_o_l_u_t_e addresses of  symbols  within
the  target  library.  When a program references a symbol defined
by the shared library; one of these modules provides  the  appro-
priate  address.  Each module contains a reference to a symbol in
the iinniitt module for this target (which ensures the  init  process
will  be performed).  This forces the inclusion of the init code;
which in turn dynamically links the target library.

11..22..22..  TThhee ttaarrggeett lliibbrraarryy

     The target library4 contains all of the object code and data
necessary to provide the library service.  It contains some addi-
tional  code to install itself; which is accomplished by allocat-
ing an area of shared memory and copying portions of it's  ..tteexxtt,
..ddaattaa and ..bbssss sections into the shared area; then exitting.

     This  technote  uses  the UNIX convention for naming program
     segments to keep the terminlogy inline  with  the  usage  of
     mmkksshhlliibb..   The  code  and  constants  area  of  a program is
     referred to as it's ..tteexxtt..  Data which has been assigned  an
     initial  value  is  referred to as ..ddaattaa..  Data which has no
____________________
   The terminology is inherited from UNIX where the target is  an
'actual'  library  loaded by the processing in the eexxeecc((22)) system
call.  The fact that it is a stand-alone program in QQNNXX is irrel-
evant.












66                                            QQNNXX SSHHAARREEDD LLIIBBRRAARRIIEESS


     initial value is referred to as ..bbssss..

This operation is performed by  the  function  __sshhoo__ccrreeaattee(())  and
driven  by the structure ss__bbiinndd is defined in <<ssyyss//sshhoobbjj..hh>>..  The
ss__bbiinndd structure is created by mmkksshhlliibb..

     There is a corresponding structure uu__bbiinndd which  is  created
in the host library; and drives the dynamic linking in __sshhoo__ooppeenn..

22..  BBuuiillddiinngg aa sshhaarreedd lliibbrraarryy

     This section describes the steps involved in making a shared
library;  and  the  operation of the shared library tool mmkksshhlliibb..
At the end of this section; there is a small example source for a
shared  library.   This example is referenced throughout the sec-
tion.

     To build a shared library; you must perform the following:

 (1)   select the library contents.

 (2)   modify existing library code to be included in the  shared
       library.

 (3)   write the library specification file.

 (4)   use mmkksshhlliibb to generate the host and target libraries.

22..11..  SSeelleeccttiinngg tthhee lliibbrraarryy ccoonntteennttss

     Selecting  the contents is the most important step in build-
ing the shared library.  Both the contents and the interface must
be  carefully considered, and there are no fixed rules about bet-
ter.  During this step, you will have to decide what the  exports
and imports of the shared library will be.

22..22..  MMooddiiffyyiinngg tthhee lliibbrraarryy ssoouurrccee ccooddee

     Only minimal changes are required to library source code for
use in the target library.  The changes are for  imported  items,
and are best illustrated with an example:

strdup.c

     cchhaarr **ssttrrdduupp((ccoonnsstt cchhaarr **ssttrr))
     {{
        eexxtteerrnn vvooiidd **mmaalllloocc((iinntt lleenn));;
        cchhaarr        **pp == mmaalllloocc((ssttrrlleenn((ssttrr))++11));;
        rreettuurrnn ssttrrccppyy((pp,, ssttrr));;
     }}













QQNNXX SSHHAARREEDD LLIIBBRRAARRIIEESS                                            77


To  use  this function in a target library; we want to invoke the
_m_a_l_l_o_c function defined by the user.  This will (necessarily)  be
an  indirect  invocation;  so we will change our use of malloc to
call via a function pointer _s_l_i_b___m_a_l_l_o_c.  So  the  example  above
becomes:

strdup-2.c

     cchhaarr **ssttrrdduupp((ccoonnsstt cchhaarr **ssttrr))
     {{
        eexxtteerrnn vvooiidd **((**sslliibb__mmaalllloocc))((iinntt lleenn));;
        cchhaarr          **pp == ((**sslliibb__mmaalllloocc))((ssttrrlleenn((ssttrr))++11));;
        rreettuurrnn ssttrrccppyy((pp,, ssttrr));;
     }}



Somehow,  early  in  the  execution  of  the process, the pointer
_s_l_i_b___m_a_l_l_o_c will be assigned the address  of  the  user's  _m_a_l_l_o_c
function.  One should notice from the above example that the con-
version was nearly mechanical,malloc = (*slib_malloc)), and  that
should suggest using the C pre-processor.  So, another re-write:

strdup-3.c

     ##ddeeffiinnee mmaalllloocc ((**sslliibb__mmaalllloocc))
     cchhaarr **ssttrrdduupp((ccoonnsstt cchhaarr **ssttrr))
     {{
        eexxtteerrnn vvooiidd **mmaalllloocc((iinntt lleenn));;
        cchhaarr        **pp == mmaalllloocc((ssttrrlleenn((ssttrr))++11));;
        rreettuurrnn ssttrrccppyy((pp,, ssttrr));;
     }}



This  transformation is much simpler as no source lines had to be
modified.  One line was added at the beginning of the module; and
the changes were reflected automatically.  It is decidedly better
form still to have all of the modules which comprise  the  target
library  include  a  common header file (import.h is a good name)
which contains the definitions for the imported symbols.  So, the
final version would be:





















88                                            QQNNXX SSHHAARREEDD LLIIBBRRAARRIIEESS


strdup-4.c

     ##iinncclluuddee      ""iimmppoorrtt..hh""

     cchhaarr **ssttrrdduupp((ccoonnsstt cchhaarr **ssttrr))
     {{
        eexxtteerrnn vvooiidd **mmaalllloocc((iinntt lleenn));;
        cchhaarr        **pp == mmaalllloocc((ssttrrlleenn((ssttrr))++11));;
        rreettuurrnn ssttrrccppyy((pp,, ssttrr));;
     }}



This  approach allows the user to furthur use the preprocessor to
define a symbol indicating whether the module is  being  compiled
for a target library or not.

     It  is important to note that this pre-processor trick works
oonnllyy if all  declarations  contain  the  storage-class  specifier
eexxtteerrnn..   All declarations in header files supplied with QNX have
the appropriate extern specifier.

22..33..  WWrriittiinngg tthhee ssppeecciiffiiccaattiioonn ffiillee

     Applications and shared libraries are coupled by the follow-
ing mechanisms:

22..33..11..  TThhee BBrraanncchh ttaabbllee..

     MMkksshhlliibb constructs a branch table based upon a specification
     file which provides  a  level  of  indirection  between  the
     application  and  the  target  library.   The address of the
     branch table is fixed and each entry contains a jump to  the
     corresponding function within the target.

22..33..22..  EExxtteerrnnaallss

     MMkksshhlliibb  constructs  absolute  symbols  in  the host library
     which correspond to symbols in the target library.  There is
     no  level  of indirection with these symbols; thus should be
     used with extreme care; or preferrably not at all.

22..33..33..  IImmppoorrttss

     MMkksshhlliibb provides an iimmppoorrtt or lliinnkkaaggee mechanism  which  per-
     mits  the  shared  library to use symbols defined within the
     application using the library.  These definitions  are  made
     in  the  _#_i_n_i_t section of the specification file.  This type
     of linkage is important where the target  library  needs  to
     use  some  state  dependant  function (such as mmaalllloocc(())) and
     thus must use the one defined by the calling application.












QQNNXX SSHHAARREEDD LLIIBBRRAARRIIEESS                                            99


     Note that these imports are not limited to functions;  datum
are perfectly acceptable; and this interface is much preferred to
the export one.


22..44..  GGuuiiddeelliinneess ffoorr SShhaarreedd LLiibbrraarryy CCooddee

     As much as possible, program source should not  have  to  be
altered  for use in a shared library.  There are, however, excep-
tions to this.

22..44..11..  EExxtteerrnnaall ssyymmbboollss hhaavvee ffiixxeedd aaddddrreesssseess..

     If an external symbol moves;  all  programs  which  use  the
shared  library  must  be  re-linked  to use the new one.  BBrraanncchh
table entries are not affected by this; as the branch table  pro-
vides the necessary level of indirection.

     External  symbols  can  move  because of changes in the com-
piler, linker or options to the  code-generator  when  an  object
module  is  generated.  If you mmuusstt use external symbols, you can
minimize the risk of generating an incompatible library by:

 (1)   Place the definition of all external definitions in a sin-
       gle module.

 (2)   Ensure that aallll external symbols are initialized.

 (3)   Do  not  place  aannyy code nor non exported data in the same
       module as this one.

 (4)   In the specification file; place the module with  exported
       data at the head of the list.


22..44..22..  AAddddrreessss rraannggeess mmuusstt bbee rreesseerrvveedd iinn aaddvvaannccee..

     The  address  space  required for the shared library must be
reserved in all programs using the library.  The designer  should
carefully  choose  values  for  ..tteexxtt  and  ..ddaattaa addresses which
reflect this limitation and allow for  future  enhancements.   Be
generous  with reserving space in the ..tteexxtt area, there is virtu-
ally no cost for doing so.


22..44..33..  IImmppoorrtteedd ssyymmbboollss ccaannnnoott bbee rreeffeerreenncceedd ddiirreeccttllyy..

     The addresses of imported symbols are  not  known  when  the
     target library is built; thus each reference must be subject
     to a level of indirection.  A high degree of source indepen-
     dence  can  be achieved by using a single ##iinncclluuddee file with
     macroes to define these.  An example might be for the CC LLaann--
     gguuaaggee ffuunnccttiioonn mmaalllloocc(()), which could be conveniently defined










1100                                           QQNNXX SSHHAARREEDD LLIIBBRRAARRIIEESS


     as:

         #define malloc (*_mylib_malloc)


when a declaration of the function malloc (such as in  <<ssttddlliibb..hh>>
) is encountered, it will be translated into:


extern void *(*_mylib_malloc)(size_t __size);


And an invocation such as

         if ((s=malloc(32)) == 0)


will be translated into

         if ((s=(*_mylib_malloc)(32)) == 0).


     Provided  all  declarations of mmaalllloocc have the storage class
specifier eexxtteerrnn; and the symbol mmaalllloocc  is  not  ##uunnddeeff'd,  this
mechanism can be implemented transparently in the source.

33..  UUssiinngg MMkksshhlliibb

     MMkksshhlliibb  builds  the host and target shared libraries from a
specification file and a set of command line options.  This  sec-
tion details the command arguments and the syntax of the specifi-
cation file.

33..11..  CCoommmmaanndd AArrgguummeennttss

    mmkksshhlliibb [[ooppttiioonnss]] --ss ssppeeccffiillee --tt ttaarrggeett



where:

-s _s_p_e_c_f_i_l_e
     use _s_p_e_c_f_i_l_e as the shared library  specification.   (-  for
     standard input).

-t _t_a_r_g_e_t
     set the name of the target shared library to _t_a_r_g_e_t.

and _o_p_t_i_o_n_s:

-q   Run quietly, only output (fatal) errors.












QQNNXX SSHHAARREEDD LLIIBBRRAARRIIEESS                                           1111


-n   Do not generate a new target library.

-h host
     Set host library name.

-L libpath
     Add _l_i_b_p_a_t_h to the directories scanned for libraries.

and the following are QNX only extensions:

-D   Set default object type to "data".

-C   Set default object type to "code".

-T   Do not load target.

-W[lL],_o_p_t_i_o_n
     Add linker option _o_p_t_i_o_n.

-d _f_i_l_e
     Generate diagnostic information in _f_i_l_e.

-S skeleton
     Use  _s_k_e_l_e_t_o_n for code genereration; rather than the default
     //uussrr//lliibb//sshhlliibb//mmkklliibb..sskkeell.  Use this option cautiously.

-U   Do not unlink intermediate files.  This is useful for debug-
     ging.

FFIILLEESS

    /bin/cc
    /bin/wlib
    /usr/include/sys/shobj.h
    /usr/lib/shlib/mklib.skel


33..22..  SSppeecciiffiiccaattiioonn FFiillee SSyynnttaaxx

     The  specification  file (given by argument _-_s) contains all
of the information necessary to build both libraries.  This spec-
ification file consists of a series of sseeccttiioonnss listed below:

##aaddddrreessss _s_e_c_t_i_o_n_-_n_a_m_e _a_d_d_r_e_s_s

     Specifies  the  starting address of the given section.  This
     _s_e_c_t_i_o_n_-_n_a_m_e can only be ..tteexxtt or ..ddaattaa A ##aaddddrreessss  must  be
     given for at least the ib .text section.

##ttaarrggeett _p_a_t_h

     Sets  the  name  of the ttaarrggeett library to _p_a_t_h_.  This can be
     over-ridden by the command line option --tt..










1122                                           QQNNXX SSHHAARREEDD LLIIBBRRAARRIIEESS


##bbrraanncchh

     This section contains one or more lines of the form:

         function-name _<_w_h_i_t_e_-_s_p_a_c_e_> position1 [-position2]

     which identifies _f_u_n_c_t_i_o_n_-_n_a_m_e with the range of integers  [
     _p_o_s_i_t_i_o_n_1 _p_o_s_i_t_i_o_n_2 ] in the branch table.

     It  is  an error to specify a number less than 1 for a posi-
     tion; or to attempt to assign the same position to more than
     one function.

##oobbjjeeccttss

     This section contains one or more lines, each containing the
     name of an object file to be included in the target library.
     Each file should be listed only once.

##oobbjjeeccttss nnoollooaadd

     This section contains one or more lines, each containing the
     name of a  library  the  target  library  should  be  linked
     against.   In UNIX this option takes on a slightly different
     meaning.

##hhiiddee lliinnkkeerr _[_*_]

     This section contains zero or more lines of regular  expres-
     sions.   These expressions are applied against the name list
     of the shared library to hide target names from the host.

     This has not been implemented in QQNNXX.  By default; all names
     are  hidden  from  the  host  library.   To  have  any  name
     exported; it must be explicitly mentioned in  the  following
     section.

##eexxppoorrtt lliinnkkeerr _[_*_]

     This  section contains zero or more lines of regular expres-
     sions.  These expressions are applied against the name  list
     of  the  target  library and names matching any of the given
     patterns are exported into the host library.

     This has not been implemented in  QQNNXX.   In  QQNNXX,  you  must
     specify eexxaaccttllyy which symbols you want to be made available.

##iinniitt _o_b_j_e_c_t

     This section contains one or more lines of the form:

         _p_t_r _<_w_h_i_t_e _s_p_a_c_e_> _i_m_p_o_r_t











QQNNXX SSHHAARREEDD LLIIBBRRAARRIIEESS                                           1133


     where _p_t_r is a symbol defined in the  target  to  indirectly
     reference _i_m_p_o_r_t , which is a symbol defined by the applica-
     tion.  It is a gross error to export the symbol _p_t_r_.

     This mechanism allows the target shared library to use func-
     tions  and  datum  defined by the application.  A common use
     for this is to access the mmaalllloocc(()) family of functions.

     In SVr3, the _o_b_j_e_c_t specifies which object file the _p_t_r_s are
     defined  in.   In  QQNNXX,  the object file is ignored, and the
     ptrs are defined within an internally generated module.

##iiddeenntt _s_t_r_i_n_g

     This is ignored in QQNNXX.

####

     is a comment.  Everything after the #### is ignored.

33..33..  MMkksshhlliibb OOppeerraattiioonn

     MMkksshhlliibb prepares target and host libraries from a specifica-
tion  file;  and  a  set  of  object modules and libraries.  This
preparation involves three principal operations:

[1]. Preparing the bbrraanncchh ttaabbllee.

[2]. Making eexxppoorrtteedd ssyymmbboollss available to the host library.

[3]. Preparing the linkage section.

Each of these operations is described in this section; concluding
with  examples of the generated source code.  Note that this sec-
tion (necessarily) contains some assembly  code  examples.   This
code is demonstrative; and is not valid input to any known assem-
bler.

33..33..11..  TThhee BBrraanncchh TTaabbllee

     The _b_r_a_n_c_h _t_a_b_l_e is constructed from ##bbrraanncchh section of  the
specification  file.  The term _b_r_a_n_c_h _t_a_b_l_e refers to the organi-
zation of function entry-points in the  shared  library.   Rather
that have the application _k_n_o_w the exact address of a given func-
tion; the application _k_n_o_w_s the address of a machine  instruction
(branch)  which  transfers  control  to the actual function.  For
example; assume the function ff(()) is defined in the  ##bbrraanncchh  sec-
tion of a shared library; The application may have the code:


     00xx110000000000    ccaallll     00xxAA11003388 ;; ff__












1144                                           QQNNXX SSHHAARREEDD LLIIBBRRAARRIIEESS


at 0xA1038, we would find


     00xx00AA11003388    jjmmpp      00xxAA22334455 ;; ((aaccttuuaall ff__))



Since the branch table is not _p_a_r_t of the application; subsequent
revisions of the shared library do not  affect  the  address  the
application uses to invoke function ff(()).

     MMkksshhlliibb  generates  the  branch  table  as a table of 8 byte
entries which have the form:


            lljjmmpp     ffuunncc   ;; ((44 bbyyttee ooffffsseett))
            nnoopp
            nnoopp
            nnoopp



In the example below; the ..tteexxtt address is set  to  0xA0000,  and
function ff(()) is listed as index #7, thus an application using the
host library will _s_e_e ff(()) at address 0xA1038.  That is 0xA0000  +
0x1000  +  7 * 8.  The offset of 0x1000 is necessary to align the
jump table on a page boundary of the processor.

     MMkksshhlliibb generates an _a_b_s_o_l_u_t_e _s_y_m_b_o_l  in the  host  library.
An  _a_b_s_o_l_u_t_e _s_y_m_b_o_l tells the linker to use the value provided as
is.

33..33..22..  EExxppoorrtteedd SSyymmbboollss

     The branch table mechanism discussed  above  provides  ready
access  to  functions within the shared library, but no provision
for data.  In general, _e_x_p_o_r_t_i_n_g data symbols from any library is
a  design  flaw.   If  you  are  in  control  of the API for your
library; you will be much happier if you  enforce  some  form  of
protocol,  even for constant data.  If you have performance prob-
lems with calling some sort of protocol function for each access;
you  could  consider providing a function which returns a pointer
to the data (structure) and hiding the name from applications.

     Mostly for supporting historical implementations;  there  is
support for exporting data by name from the shared library.  This
mechanism is provided  by  the  ##eexxppoorrtt  lliinnkkeerr  section  of  the
specification.5 The symbols  are  exported  by  placing  _a_b_s_o_l_u_t_e
____________________
   In  UNIX  System  V  Release 3.2, every public symbol which is
bound to the shared library is, by default,  exported.   The  QQNNXX
implementation chose to by default ##hhiiddee all symbols not declared
in the ##bbrraanncchh section.  This decision is motivated  by  ease  of










QQNNXX SSHHAARREEDD LLIIBBRRAARRIIEESS                                           1155


_s_y_m_b_o_l_s  in  the host library corresponding to the address of the
symbol in the target shared library.  Unlike branch entries, how-
ever,  there  is  no  level  of indirection; thus these addresses
could potentially change in subsequent revisions  of  the  shared
library.   The following rules minimize the opportunities of such
changes.

[1]  -Use the ##aaddddrreessss definition  for  the  ..ddaattaa  section;  and
     allow  sufficient  room  between  the  end  of the ..tteexxtt and
     beginning of ..ddaattaa for future additions to the library.

[2]  -Object modules are placed into the shared  library  in  the
     order  encounted.  Put objects which define exported symbols
     at the beginning of this list.

[3]  -Allways initialize any data which  is  exported.   In  UNIX
     only  initialized  data  is permitted in the shared library.
     In QQNNXX this rule was loosened,  but  one  should  understand
     that:


          iinntt           aa;;
          aanndd
          iinntt           aa==00;;



     will cause a to be assigned to different locations; the for-
     mer in the

[4]  -Avoid placing code or static data in  the  same  module  as
     exported  data.  The code may cause the compiler to generate
     data (switch tables, strings) which can _m_o_v_e  the  locations
     of  your  data.  Similiarly, the compiler will re-order data
     definitions in object modules for  alignment  and  to  avoid
     _h_o_l_e_s.

33..33..33..  LLiinnkkaaggee SSeeccttiioonn

     The  lliinnkkaaggee  sseeccttiioonn  consists  of two corresponding tables
within the host and target libraries.  In the target library; the
linkage section is a table of entry pointers, each index of which
is labelled with the symbol appearing on the left-hand side of an
init line.   The table below illustrates:




____________________
implementation, and to minimize the hazard of unintentionally ex-
porting symbols.












1166                                           QQNNXX SSHHAARREEDD LLIIBBRRAARRIIEESS



     ##iinniitt  xx..oo
        nnaammee      ttlliibb__nnaammee
        aaggee       ttlliibb__aaggee

     ;; ggeenneerraatteedd ffiillee xx..ss
     ppuubblliicc __ttlliibb__nnaammee
     ppuubblliicc __ttlliibb__aaggee
     ppuubblliicc __lliinnkkaaggee__sseeccttiioonn__bbeeggiinn
     ppuubblliicc __lliinnkkaaggee__sseeccttiioonn__eenndd
     __lliinnkkaaggee__sseeccttiioonn__bbeeggiinn llaabbeell bbyyttee
     __ttlliibb__nnaammee           dddd          00
     __ttlliibb__aaggee            dddd          00
     __lliinnkkaaggee__sseeccttiioonn__eenndd   llaabbeell bbyyttee




     When  an application binds to the target library (at process
startup), a similiar table is copied from  the  client  into  the
target  library.  Continuing the example above; the module in the
client might look like:


     eexxttrrnn __nnaammee
     eexxttrrnn __aaggee
     ppuubblliicc __lliinnkkaaggee__sseeccttiioonn__bbeeggiinn
     ppuubblliicc __lliinnkkaaggee__sseeccttiioonn__eenndd
     __lliinnkkaaggee__sseeccttiioonn__bbeeggiinn llaabbeell bbyyttee
           dddd          ooffffsseett __nnaammee
           dddd          ooffffsseett __aaggee
     __lliinnkkaaggee__sseeccttiioonn__eenndd   llaabbeell bbyyttee



     Via this process the target library code  will  use  defini-
tions of data and code provided by the client.

33..33..33..11..  NNaammiinngg pprroobblleemmss

     A  relatively new trend in CC compilers is name mangling.  In
CC++++, for example, names are modified  to  provide  the  types  of
parameters  and  return values; thus providing _t_y_p_e _s_a_f_e _l_i_n_k_a_g_e.
In WWAATTCCOOMM CC, to accomodate development tools from  other  vendors
and  languages;  chooses  to  make a small modification to symbol
names.  Code symbols (function names) have  a  single  underscore
(_)  appended  to  the  name; thus a function ff(()) is labelled ff__.
Data symbols have a single underscore prepended to the name; thus
a data item dd is labelled __dd.

     This  name transformation causes a problem in the ##iinniitt sec-
tions of mmkksshhlliibb - the init entries do not  specify  whether  the
symbol  is  code  or data.  To resolve this; mmkksshhlliibb enforces the










QQNNXX SSHHAARREEDD LLIIBBRRAARRIIEESS                                           1177


following rules:

1.   - All symbols identified in the ##bbrraanncchh  section  are  ..tteexxtt
     symbols.

2.   -  All  symbols  appearing  on the _l_e_f_t _h_a_n_d _s_i_d_e of an init
     line are ..ddaattaa symbols.

2.   - All other symbols default to ..ddaattaa.  This  option  may  be
     over-ridden with a command switch.

3.   -  A  symbols  which  is not a ##bbrraanncchh or the lhs of an init
     line may be specified in any of the following ways:

[a]  Append the characters (()) to the symbol name  defines  it  as
     ..tteexxtt.

[b]  Append  the  characters  [[]] to the symbol name defines it as
     ..ddaattaa.

[c]  A comment at the end of the line where the symbol is defined
     which is literally ####ddaattaa defines the symbol as ..ddaattaa.

[d]  A comment at the end of the line where the symbol is defined
     which is literally ####ffuunncc defines the symbol as ..tteexxtt.

     The reason for providing two equivalent methods is for  com-
     patability  with UNIX mkshlib.  The last two will be ignored
     by UNIX mkshlib, however are less instructive than the first
     two.

     In  the  future; primarily to support CC++++, mmkksshhlliibb will sup-
port full declarations of symbols; perhaps with a ##ttyyppeess section.

44..  MMkksshhlliibb eexxaammpplleess
























