[freetds] freetds on solaris 11: symbol scope specifies local binding (same problem)

James K. Lowden jklowden at freetds.org
Mon Sep 23 17:47:01 EDT 2013

On Mon, 23 Sep 2013 11:20:33 -0700
Justin T Pryzby <justinp at norchemlab.com> wrote:

> On Mon, Sep 23, 2013 at 01:42:27PM -0400, James K. Lowden wrote:
> > On Mon, 23 Sep 2013 08:53:31 +0100 "Marco A. Ferra"
> > <MAFerra at isq.pt> wrote:
> > 
> > > Regarding Justin Pryzby's question on "freetds on solaris 11:
> > > symbol scope specifies local binding" [1] I'm also having a hard
> > > time compiling FreeTDS 0.91 from source on Solaris 11. The error
> > > is:
> [...]
> > My GNU ld manual doesn't mention options such as those on your
> > command line, e.g. allextract and defaultextract.  Since those
> > options are accepted by the linker, I have to believe you're using
> > the Solaris linker.  Perhaps Solaris's compiler, too?  
> Not sure about Marco, but I wasn't; ./configure gives:
> checking for gcc... gcc
> checking whether we are using the GNU C compiler... yes
> checking if the linker (/usr/bin/ld) is GNU ld... no
> checking whether the gcc linker (/usr/bin/ld) supports shared
> libraries... yes checking whether -lc should be explicitly linked
> in... yes checking dynamic linker characteristics... solaris2.11 ld.so
> checking how to hardcode library paths into programs... immediate
> checking if libtool supports shared libraries... yes
> checking for ld used by GCC... /usr/bin/ld
> checking if the linker (/usr/bin/ld) is GNU ld... no
> There *is* a linker script being used:
> http://lists.ibiblio.org/pipermail/freetds/2013q3/028467.html
> > libtool: link: echo "{ global:" > .libs/libct.so.4.0.0.exp
> > libtool: link: cat .libs/libct.exp | /usr/bin/gsed -e "s/\(.*
> > \)/\1;/" >> .libs/libct.so.4.0.0.exp libtool: link: echo "local:
> > *; };" >> .libs/libct.so.4.0.0.exp libtool: link:  gcc -shared
> > -Wl,-z -Wl,text -Wl,-M -Wl,.libs/libct.so.4.0.0.exp -Wl,-h
> > -Wl,libct.so.4
> > -o .libs/libct.so.4.0.0  .libs/ct.o .libs/cs.o .libs/blk.o .libs/ctutil.o
> > -Wl,-z
> > -Wl,allextract ../tds/.libs/libtds.a ../replacements/.libs/libreplacements.a
> > -Wl,-z -Wl,defaultextract  -lnsl -lsocket -lc  -pthreads
> > -Wl,-Bsymbolic   -pthreads

Hmm.  So you are using solaris's linker:

> checking for ld used by GCC... /usr/bin/ld
> checking if the linker (/usr/bin/ld) is GNU ld... no

I have such a file on my machine, and it's just a list of public
ct-lib symbols:

$ awk -F_  '{print $1}' build/src/ctlib/.libs/libct.exp  | uniq -c 
  19 blk
  23 cs
  32 ct

The effect of the commands

	echo "{ global:" > .libs/libct.so.4.0.0.exp
	cat .libs/libct.exp | /usr/bin/sed -e "s/\(.*\)/\1;/" \
	  >> .libs/libct.so.4.0.0.exp 
	echo "local: *; };" >> .libs/libct.so.4.0.0.exp

is, rather clumsily, to tack a line at the top and at the end, and to
stick a semicolon on the end of every line.  So we would have 

$ head .libs/libct.so.4.0.0.exp 
{ global:

$ tail .libs/libct.so.4.0.0.exp 
local: *; };

What does yours say?  


(Here I am on the FreeTDS list helping someone use an Oracle product.
The future is a weird place.)  

Remove the "-Wl," escapes, your linker command line is 

-z text -M .libs/libct.so.4.0.0.exp -h libct.so.4 \
-o .libs/libct.so.4.0.0 \
.libs/ct.o .libs/cs.o .libs/blk.o .libs/ctutil.o \ 
-z allextract \ 
../tds/.libs/libtds.a ../replacements/.libs/libreplacements.a \
-z defaultextract  -lnsl -lsocket -lc -Bsymbolic

Marco's is similar; I think the -Bsymbolic is impotent: 

-z text -M .libs/libct.so.4.0.0.exp -h libct.so.4  \
-o .libs/libct.so.4.0.0  \
.libs/ct.o .libs/cs.o .libs/blk.o .libs/ctutil.o \
-z allextract \
../tds/.libs/libtds.a ../replacements/.libs/libreplacements.a \
-z defaultextract  -lnsl -lsocket -lc

and the error is 

> Undefined                       first referenced
>  symbol                             in file
> strlen                              .libs/ct.o  
> (symbol scope specifies local binding)

In the Solaris linker, the -M option introduces a map file, *not* a
linker script.  And the last line of that file, 
.libs/libct.so.4.0.0.exp,  is 

	local: *; };

Perhaps there's a connection?  The fine manual says, 

	"However, symbols defined as local or eliminate scope are
reduced to symbols with a local binding within any executable or shared
object file being generated."


	"When in *local* scope, this symbol name can be defined as the
special auto-reduction directive "*". This directive results in all
global symbols, not explicitly defined to be global in the mapfile,
receiving a local binding within any executable or shared object file
being generated."

The intention of "local: *; };" seems to be that no symbols in
the .o files are global except for those explicitly mentioned in the
global section of the mapfile.  

A testable hypothesis: it's not acting as intended.  Perhaps references
to strlen are being "reduced" to local scope.  

If you remove it and make the file to end with

	ct_setparam; };

what effect does that have?  

It's also not perfectly obvious you need any symbol-management
shenanigans.  If I were writing my own Makefile, I'd begin with 

-h libct.so.4 \
-o .libs/libct.so.4.0.0 \
.libs/ct.o .libs/cs.o .libs/blk.o .libs/ctutil.o \ 
../tds/.libs/libtds.a ../replacements/.libs/libreplacements.a \
-lnsl -lsocket -lc  -pthreads 

That might work, too.  There might be too many symbols, but
that's usually better than not enough, as I'm sure you'd agree.  



More information about the FreeTDS mailing list