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