AIX 3.1 linker tricks (long)

Paul Amaranth amaranth at vela.acs.oakland.edu
Tue Apr 16 06:47:19 AEST 1991


The linker and binder are rather versatile programs, but it is not always
clear how to make them do what you want them to.  In particular, there are
times when you do not want to use shared libraries, but rather, staticly
bind the required routines into your object.  Or, you may need to use
two version of the same routine (eg, Fortran & C).  Here are the results of my
recent experiments.  I would like to thank Daniel Premer and Brad Hollowbush,
my SE, for hints.  Any mistakes or omissions are my own and I have tended to
interchange the terms "linker" and "binder".  These experiments were
performed on AIX 3.1 3002.  I would expect most of this to be applicable
to 3003 as well.

1)  I have some C programs, I want to bind in the runtime routines.  How
    do I do this?

    You can put the -bnso binder command on the link line.  You should
    also include the -bI:/lib/syscalls.exp control argument:
      cc *.o -bnso -bI:/lib/syscalls.exp -o foo
    This will magically do everything you need.  Note that this will bind
    *ALL* required routines in.  The -bI argument tells the linker that
    these entry points will be resolved dynamically at runtime (these are
    system calls).  If you omit this you will get lots of unresolved 
    reference messages.

2)  I want to staticly bind in the Fortran runtime so a) my customers do
    not need to buy it and b) I don't have to worry about the runtime
    changing on a new release.  Can I use the two binder arguments in
    1) to do this?

    You should be able to do so, but, at least under 3002, if you do
    you will get a linker error referencing getenv.  In addition, there
    are a number of potential conflicts between Fortran and C routines.
    The easy way just does not work.  See the section on
    2 stage linking for C and Fortran on how to do this.  The getenv
    problem is a mess, see the section on Comments & Caveats for more.

3)  I have a mixture of C and Fortran routines, how can I make sure
    that the C routines reference the C getenv, while the Fortran routines
    reference the Fortran getenv (which has different parameters and, if
    called mistakenly by a C routine results in a segmentation fault)?

    You can't.  Only one symbol definition is allowed, and it will be the
    *first* definition on the >last< link.  Here is the quote from the 
    ld info file:

       In this version of ld, the first definition of each symbol in
       the link takes precedence and is used even if the first reference
       follows the definition.

    The only way I can possibly think of to do this is extremely messy:
    Make the C and Fortran routines separate modules.  Staticly bind them
    with their libraries.  Have them dynamicly call each other.  ech.
    I haven't tried this, however.

    If you want to bind everything together, write yourself an interface
    in one language to use the other's routine.  I did this with getenv
    and it works tolerably well.

4)  I have C and Fortran routines.  I want to bind in the xlf library, while
    letting the rest of the libraries be shared.  How do I do this?

    You need to do a 2 stage link.  In the first stage, you bind in the
    xlf library routines, creating an intermediate object file.  The
    second stage resolves the remaining references to the shared libraries.

    This is a general technique that allows you to bind in specific system
    routines, while still referencing the standard shared libraries.

    Specifically, use this command to bind the xlf libraries to the Fortran
    objects:

       ld -bh:4 -T512 -H512 <your objects> -o intermediat.o \
       -bnso -bI:/lib/syscalls.exp -berok -lxlf -bexport:/usr/lib/libg.exp \
       -lg -bexport:<your export file>

    The argument -bexport:<your export file> specifies a file with the
    name of all entry points that are to be visible outside the intermediate 
    module.  Put one entrypoint name on a line.  The -bI:/lib/libg.exp line 
    is required for proper functioning of the program.  The -berok argument 
    tells the binder that it is ok to have unresolved references, at least 
    at this time (you would think -r would work here, but it doesn't seem to).  
    The -bnso argument causes the required modules to be imported
    into the object.  The -lxlf, of course, is the xlf library.

    Then, bind the intermediate object with the other shared libraries in
    the normal fashion:

       ld -bh:4 -T512 -H512 <C or other modules> intermediate.o \
       /lib/crt0.o -lm -lc

    Note the absence of -berok.  After this link, all references should
    be resolved (unless you're doing a multistage link and making another
    intermediate).

    NOTE THE ORDER OF MODULES.  This is extremely important if, for example,
    you had a subroutine named "load" in your Fortran stuff.  Putting the
    C libraries before the intermediate module would make the C "load"
    the operable definition, rather than the Fortran version EVEN THOUGH 
    THE FORTRAN MODULE HAS ALREADY BEEN THROUGH A LINK AND ALL REFERENCES 
    TO THE SYMBOL ARE CONTAINED IN THE FORTRAN MODULE.  This can
    be extremely difficult to find (trust me on this one :-)  Is this
    a bug, a feature, or what?

    The result will be a slightly larger object than normal.  (I say slightly
    because mine went up 5%, but then its a 2 MB object :-)


Comments & Caveats:

   From the documentation the -r argument to the linker should do what
   -berok does.  It does not.  Very strange results come from using the
   -r argument.  I have not been able to make -r work in a sensible manner
   (even for intermediate links which is what it is supposed to be for).
   Note: this is one of the things I gave up on.  I would like to hear
   from anyone with more info on this.

   When binding an intermediate module, use an export file to define the
   entry points you want visible in the later link.  If you don't do this,
   you'll get the dreaded "unresolved reference" error.  Import files name
   entry points that will be dynamically resolved (and possibly where).

   If you are in doubt about what parameters or libraries to link, use the
   -v arg when linking and modify the exec call that shows up into 
   an ld command.  Some thought about the libraries will usually yield an
   idea of when to use what.  If you don't know what an argument is for,
   leave it in.  It's there for a purpose (even if you don't understand it).

   Watch the order of external definitions (ie, libraries) when more than
   one version of a routine may show up, eg "load".  The first one defined
   on the ld command line is the winner.  

   The getenv (and system and signal) problem is a problem that started out
   minor, got somewhat worse in 3003 and, eventually will be correctly fixed.
   Basically, you should extract the 3002 version of these three routines
   from xlf.a before doing the update and save them away, then link these
   routines in if you use these Fortran system services.  

-----------------------------------------------------


Well, there you have it.  If anyone has any other interesting tidbits
concerning the linker, I would appreciate hearing them.
In particular, if anyone has actually done something I said you can't
do, PLEASE let me know.  I have not exhaustively persued all avenues;
when things were not productive, I tried something else.

End of disclaimer, have fun!

-- 
Paul Amaranth  office: (313) 370 4541 (also voicemail) 
(internet)     amaranth at vela.acs.oakland.edu  | WANTED: Clever saying
(bitnet)       amaranth at oakland               | to fill this space. 
(uucp)         ...!uunet!umich!vela!amaranth  | Puns need not apply.



More information about the Comp.unix.aix mailing list