[Python-Dev] Dynamic linking problem on Solaris

Greg Ward gward@mems-exchange.org
Fri, 19 May 2000 13:03:18 -0400

Hi all --

interesting problem with building Robin Dunn's extension for BSD DB 2.x
as a shared object on Solaris 2.6 for Python 1.5.2 with GCC 2.8.1 and
Sun's linker.  (Yes, all of those things seem to matter.)

DB 2.x (well, at least 2.7.7) contains this line of C code:

    *mbytesp = sb.st_size / MEGABYTE;

where 'sb' is a 'struct stat' -- ie. 'sb.st_size' is a long long, which
I believe is 64 bits on Solaris.  Anyways, GCC compiles this division
into a subroutine call -- I guess the SPARC doesn't have a 64-bit
divide, or if it does then GCC doesn't know about it.

Of course, the subroutine in question -- '__cmpdi2' -- is defined in
libgcc.a.  So if you write a C application that uses BSD DB 2.x, and
compile and link it with GCC, no problem -- everything is controlled by
GCC, so libgcc.a gets linked in at the appropriate time, the linker
finds '__cmpdi2' and includes it in your binary executable, and
everything works.

However, if you're building a Python extension that uses BSD DB 2.x,
there's a problem: the default command for creating a shared extension
on Solaris is "ld -G" -- this is in Python's Makefile, so it affects
extension building with either Makefile.pre.in or the Distutils.

However, since "ld" is Sun's "ld", it doesn't know anything about
libgcc.a.  And, since presumably no 64-bit division is done in Python
itself, '__cmpdi2' isn't already present in the Python binary.  The
result: when you attempt to load the extension, you die:

  $ python -c "import dbc"
  Traceback (innermost last):
    File "<string>", line 1, in ?
  ImportError: ld.so.1: python: fatal: relocation error: file ./dbcmodule.so: symbol __cmpdi2: referenced symbol not found

The workaround turns out to be fairly easy, and there are actually two
of them.  First, add libgcc.a to the link command, ie. instead of

  ld -G  db_wrap.o  -L/usr/local/BerkeleyDB/lib -ldb -o dbcmodule.so


  ld -G  db_wrap.o  -L/usr/local/BerkeleyDB/lib -ldb \
    /depot/gnu/plat/lib/gcc-lib/sparc-sun-solaris2.6/2.8.1/libgcc.a \
    -o dbcmodule.so

(where the location of libgcc.a is variable, but invariably hairy).  Or,
it turns out that you can just use "gcc -G" to create the extension:

  gcc -G db_wrap.o -ldb -o dbcmodule.so

Seems to me that the latter is a no-brainer.

So the question arises: why is the default command for building
extensions on Solaris "ld -G" instead of "gcc -G"?  I'm inclined to go
edit my installed Makefile to make this permanent... what will that

Greg Ward - software developer                gward@mems-exchange.org
MEMS Exchange / CNRI                           voice: +1-703-262-5376
Reston, Virginia, USA                            fax: +1-703-262-5367