Bug 9728

Summary: libtool --mode=link g++ -export-symbols-regex does not work as expected
Product: Sisyphus Reporter: at <at>
Component: libtool_1.5Assignee: Dmitry V. Levin <ldv>
Status: NEW --- QA Contact: qa-sisyphus
Severity: normal    
Priority: P2 CC: jackie.rosen
Version: unstable   
Hardware: all   
OS: Linux   

Description at@altlinux.org 2006-06-26 10:12:00 MSD
when using g++, -export-symbols does not work as expected.

$ cat test.c
extern "C"
void _test()
{
        return;
}
extern "C"
void test()
{
        return;
}
$

-- created sample file.

$ libtool --tag=CXX --mode=compile g++ -c test.c -o test.lo
 g++ -c test.c  -fPIC -DPIC -o .libs/test.o
 g++ -c test.c -o test.o >/dev/null 2>&1
$

-- complited sample file.

$ libtool --mode=link gcc -o libtest.la -rpath /usr/lib -version-info 0:0:0
-export-symbols-regex '^test' test.lo
rm -fr  .libs/libtest.a .libs/libtest.exp .libs/libtest.la .libs/libtest.lai
.libs/libtest.so .libs/libtest.so.0 .libs/libtest.so.0.0.0 .libs/libtest.ver
generating symbol list for `libtest.la'
/usr/bin/nm -B  .libs/test.o  | sed -n -e 's/^.*[      
]\([ABCDGIRSTW][ABCDGIRSTW]*\)[         ][      ]*\([_A-Za-z][_A-Za-z0-9]*\)$/\1
\2 \2/p' | /bin/sed 's/.* //' | sort | uniq > .libs/libtest.exp
grep -E -e "^test" ".libs/libtest.exp" > ".libs/libtest.expT"
mv -f ".libs/libtest.expT" ".libs/libtest.exp"
echo "{ global:" > .libs/libtest.ver
 cat .libs/libtest.exp | sed -e "s/\(.*\)/\1;/" >> .libs/libtest.ver
 echo "local: *; };" >> .libs/libtest.ver
 gcc -shared  .libs/test.o   -Wl,-soname -Wl,libtest.so.0 -Wl,-version-script
-Wl,.libs/libtest.ver -o .libs/libtest.so.0.0.0
(cd .libs && rm -f libtest.so.0 && ln -s libtest.so.0.0.0 libtest.so.0)
(cd .libs && rm -f libtest.so && ln -s libtest.so.0.0.0 libtest.so)
ar cru .libs/libtest.a  test.o
ranlib .libs/libtest.a
creating libtest.la
(cd .libs && rm -f libtest.la && ln -s ../libtest.la libtest.la)
$ 

-- linked with gcc, and it worked ok.  Note: .libs/libtest.ver file is created
and
-version-script -Wl,.libs/libtest.ver is passed to the linker.

Now I am going to link with g++:

$ libtool --mode=link g++ -o libtest.la -rpath /usr/lib -version-info 0:0:0
-export-symbols-regex '^test' test.lo
rm -fr  .libs/libtest.a .libs/libtest.exp .libs/libtest.la .libs/libtest.lai
.libs/libtest.so .libs/libtest.so.0 .libs/libtest.so.0.0.0 .libs/libtest.ver
generating symbol list for `libtest.la'
/usr/bin/nm -B  .libs/test.o  | sed -n -e 's/^.*[      
]\([ABCDGIRSTW][ABCDGIRSTW]*\)[         ][      ]*\([_A-Za-z][_A-Za-z0-9]*\)$/\1
\2 \2/p' | /bin/sed 's/.* //' | sort | uniq > .libs/libtest.exp
grep -E -e "^test" ".libs/libtest.exp" > ".libs/libtest.expT"
mv -f ".libs/libtest.expT" ".libs/libtest.exp"
g++ -shared -nostdlib /usr/lib/gcc/i586-alt-linux/3.4.4/../../../crti.o
/usr/lib/gcc/i586-alt-linux/3.4.4/crtbeginS.o  .libs/test.o 
-L/usr/lib/gcc/i586-alt-linux/3.4.4 -L/usr/lib/gcc/i586-alt-linux/3.4.4/../../..
-lstdc++ -lm -lc -lgcc_s /usr/lib/gcc/i586-alt-linux/3.4.4/crtendS.o
/usr/lib/gcc/i586-alt-linux/3.4.4/../../../crtn.o  -Wl,-soname -Wl,libtest.so.0
-Wl,-retain-symbols-file -Wl,.libs/libtest.exp -o .libs/libtest.so.0.0.0
i586-alt-linux-g++: /usr/lib/gcc/i586-alt-linux/3.4.4/../../../crti.o: No such
file or directory
i586-alt-linux-g++: /usr/lib/gcc/i586-alt-linux/3.4.4/crtbeginS.o: No such file
or directory
i586-alt-linux-g++: /usr/lib/gcc/i586-alt-linux/3.4.4/crtendS.o: No such file or
directory
i586-alt-linux-g++: /usr/lib/gcc/i586-alt-linux/3.4.4/../../../crtn.o: No such
file or directory
$

-- it failed, but it does not really matter for now.  Note two things:
.libs/libtest.ver is not created;
and -version-script is not passed to the linker.  -Wl,-retain-symbols-file
-Wl,.libs/libtest.exp is used instead.

Now see what happens if I fix the command and use -Wl,-retain-symbols-file:

$ cat .libs/libtest.exp
test
$ g++ -shared -nostdlib .libs/test.o -Wl,-soname -Wl,libtest.so.0
-Wl,-retain-symbols-file -Wl,.libs/libtest.exp -o .libs/libtest.so.0.0.0
$ nm -D .libs/libtest.so.0.0.0
00001244 A __bss_start
         U __gxx_personality_v0
00001244 A _edata
00001244 A _end
000001cc T _test
000001d2 T test
$

You see "_test" is still exported!  However, what I was trying to achieve with
-export-symbols-regex '^test'
is exactly the opposite: "_test" must not be exported.  Thus I infer that
-export-symbols does not work as expected.
Comment 1 Dmitry V. Levin 2008-01-13 21:00:47 MSK
Retested with libtool_1.5-1.5.24-alt3:
The libtool --mode=link g++ command now works, but
-export-symbols-regex option still works strange.
Comment 2 Dmitry V. Levin 2008-01-13 21:29:12 MSK
According to discussion in
http://sourceware.org/ml/binutils/2001-12/msg00143.html thread,
libtool should use -version-script instead of -retain-symbols-file.
Comment 3 Dmitry V. Levin 2019-04-10 20:26:11 MSK
There is a famous rant in the DSO howto on this subject:

"there is hope libtool will learn about converting the
export lists into the anonymous version maps we have
seen in the previous section when the GNU linker is used.
At that point libtool will become useful. Until then
relying on its -export-symbols option is misleading
at best."