Static Linking on AIX

I’ve spent the last several hours trying to link a C++ program statically on our ageing AIX machine. As I’ve come to expect from IBM’s compiler – nothing’s ever that simple. What did I expect? They don’t even provide a man page, and the linker always kicks out thousands of irrelevant warnings by design.

The system is running IBM VisualAge 5 on AIX 5.1. I said it was ageing.

Always finish with -bdynamic

Dynamic linking (-bdynamic) is the default for AIX’s xlC compiler. The documentation says that the -bstatic option turns on static linking. OK, but try using this option and you get dozens of ‘undefined symbol’ errors for symbols that should be defined in libc:

ld: 0711-317 ERROR: Undefined symbol: errno
ld: 0711-317 ERROR: Undefined symbol: _exit
ld: 0711-317 ERROR: Undefined symbol: open

Apparently, you can’t link libc statically. Here’s the relevant quote, hidden away on page 102 of some blasted PDF:

To avoid possible problems with unresolved linker errors when linking the C library, you must add the -bdynamic option to the end of any compilation sections that use the -bstatic option.

Note: Actually the documentation says you can statically link libc, but you might not want to. That said, I’ve not been able to make it work. See below for the secret.

ranlib libz.a

I had trouble with linking Zlib of all things. I got these six severe errors:

ld: 0711-212 SEVERE ERROR: Symbol .__divus, found in the global symbol table
        of archive /lib/libz.a, was not defined in archive member libz.so.1.
ld: 0711-212 SEVERE ERROR: Symbol __divus, found in the global symbol table
        of archive /lib/libz.a, was not defined in archive member libz.so.1.
ld: 0711-212 SEVERE ERROR: Symbol .__mulh, found in the global symbol table
        of archive /lib/libz.a, was not defined in archive member libz.so.1.
ld: 0711-212 SEVERE ERROR: Symbol __mulh, found in the global symbol table
        of archive /lib/libz.a, was not defined in archive member libz.so.1.
ld: 0711-212 SEVERE ERROR: Symbol .__quous, found in the global symbol table
        of archive /lib/libz.a, was not defined in archive member libz.so.1.
ld: 0711-212 SEVERE ERROR: Symbol __quous, found in the global symbol table
        of archive /lib/libz.a, was not defined in archive member libz.so.1.

AIX’s libz.a is at fault. Simply running ranlib on it fixes the problem. You have to make a copy first, since the current one may be in use and therefore locked:

# cd /lib
# cp libz.a libz.a.new
# ranlib libz.a.new
# mv libz.a libz.a.old && mv libz.a.new libz.a

Oracle OCI Library

So how on earth do you link Oracle’s OCI library statically on AIX? Here are the errors:

ld: 0711-317 ERROR: Undefined symbol: pw_wait
ld: 0711-317 ERROR: Undefined symbol: pw_post
ld: 0711-317 ERROR: Undefined symbol: pw_config
ld: 0711-317 ERROR: Undefined symbol: aix_ora_pw_version3_required
ld: 0711-317 ERROR: Undefined symbol: ksmsgl_
ld: 0711-317 ERROR: Undefined symbol: kcbkclx_

Naturally there’s no documentation provided by Oracle, but digging around in the OCI examples reveals the following two options:

  -bI:$(ORACLE_HOME)/lib/pw-syscall.exp
  -bI:$(ORACLE_HOME)/lib/ksms.imp

The -bI option isn’t even mentioned in IBM’s ‘documentation’ for xlC. However, I think it just points to a file that lists symbols to import. I don’t have the inclination to explore that further right now.

UPDATE!!

I’ve belatedly discovered that Oracle provide a (little known) static library: libclntst9.a. (For Oracle 10, the library would be libclntst10.a and so on.) Naturally you’d imagine that you can simply add that to your link line as -lclntst. Well, nearly. You need to include a few other libraries too. On Linux the link line is:

-lclntst9 -lnsl -ldl -lm

For Solaris, you need a few more libraries:

-lclntst9 -lnsl -lsocket -lgen -ldl -laio -lkstat -lm

Thanks to Josh Chu on the Oracle Forums.

static libc

A bit of exploration in the man page for ld reveals the following:

To link a program using the libc.a library as a non-shared library, enter:

cc -o pgm pgm.o -bnso -bI:/lib/syscalls.exp

However this comes with the following warning:

Any application that is statically linked is NOT binary portable from any fix or release level to any other fix or release level.

nso stands for no shared objects, so this sounds promising. However, the file /lib/syscalls.exp is not to be found on my system, so I suppose I’ll never know whether this works or not.

Comment · RSS · TrackBack

  1. michael said,

    19 January, 2006 @ 23:29

    did you ever get/find a copy of /lib/syscalls.exp ???????

  2. alex said,

    24 January, 2006 @ 23:19

    michael: No, I’m afaid not. We looked through all of the system packages, but the file was nowhere to be found. Perhaps it’s only to be found on a more recent version of AIX. I’m still stuck on v5.1.

    Frankly, I wasn’t that bothered about statically linking libc. The calls interface to libc is probably more stable than the OS-level interface, so why would you want to statically link it? My goal was binary portability, which is probably better served by dynamically linked libc.

    I suppose there may be paranoid security reasons for wanting to statically link…

  3. Jonas said,

    26 January, 2006 @ 14:29

    FYI: I just managed to link libc statically using the example above. The system is running AIX 4.3.3.

  4. Sébastien said,

    31 January, 2006 @ 15:51

    On my system, it seems like the /lib/syscalls.exp file comes from the bos.adt.syscalls fileset :

    ls -l /lib/syscalls.exp
    lrwxrwxrwx  1  bin  bin  21 Sep  2 19:52 /lib/syscalls.exp@ -> /usr/lib/syscalls.imp
    
    lslpp -w /usr/lib/syscalls.exp
    File                    Fileset            Type
    -----------------------------------------------------
    /usr/lib/syscalls.exp   bos.adt.syscalls   Symlink
    

    Hope this’ll help

  5. alex said,

    21 February, 2006 @ 16:21

    UPDATE!!

    I’ve added some extra text about Oracle’s libclntst.a static library.

  6. Blaise said,

    16 June, 2006 @ 10:53

    I’ve the same problem. The hint to install bos.adt.syscalls helped!

  7. Yogesh said,

    30 June, 2007 @ 08:40

    Thanks, Nice artical .. i am able to compile static binaries with this informetion.

  8. Ed said,

    22 February, 2012 @ 21:47

    Thanks! Helped me even now trying to build Valgrind on 5.3

  9. ps said,

    20 June, 2013 @ 10:38

    Hi I am getting following error on AIX while linking the executable. There are no compilation errors. ld: 0711-224 WARNING: Duplicate symbol: pxargc ld: 0711-224 WARNING: Duplicate symbol: pxargv ld: 0711-224 WARNING: Duplicate symbol: .main ld: 0711-224 WARNING: Duplicate symbol: .bcopy ld: 0711-224 WARNING: Duplicate symbol: .fsav ld: 0711-224 WARNING: Duplicate symbol: .fres ld: 0711-224 WARNING: Duplicate symbol: std::Tidyfac<std::ctype >::Facsav ld: 0711-224 WARNING: Duplicate symbol: pxrcfg ld: 0711-224 WARNING: Duplicate symbol: pxrc ld: 0711-345 Use the -bloadmap or -bnoquiet option to obtain more information. ld: 0711-317 ERROR: Undefined symbol: .CORBA::ORB::decrrefcount() ld: 0711-317 ERROR: Undefined symbol: .CORBA::ORB::duplicate(CORBA::ORB*) ld: 0711-317 ERROR: Undefined symbol: .CORBA::Object::decrrefcount() ld: 0711-317 ERROR: Undefined symbol: .ACEOS::memset(void*,int,unsigned long) ld: 0711-317 ERROR: Undefined symbol: .CORBA::ORB::nil() ld: 0711-317 ERROR: Undefined symbol: .ACETaskBase::thrmgr() const

Leave a Comment

Sponsors