PR# 14804 All symbols exported in shared libraries on GNU/Linux/ELF platform

Problem Report Summary
Submitter: paul.cohen
Category: C Compilation
Priority: High
Date: 2008/09/19
Class: Bug
Severity: Serious
Number: 14804
Release: 6.2.7.3753
Confidential: No
Status: Analyzed
Responsible: manus_eiffel
Environment: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.1) Gecko/2008072820 Firefox/3.0.1
Synopsis: All symbols exported in shared libraries on GNU/Linux/ELF platform

Description
Compiling a shared library on the GNU/Linux/ELF platform results in all exported symbols becoming exported. 

This means that all "C mangled" Eiffel feature names like " F424_3664" as well as Eiffel system specific "C" names like "eif_gc_run" are exported.

This in turn means that you can't link an Eiffel application with an Eiffel shared library or any application with more than one Eiffel shared library, since you will get symbol clashes.

SOLUTION
========

For GNU/Eiffel/ELF systems you should use the "--version-script" flag of the GNU linker ld to specify the symbols to export. These symbols are explicitly listed in the .def file for the system. For more info on the "--version-script" flag see the documentation on the version command in the ld manual.

To check that EiffelStudio is being run on an ELF system you can do something like this:

if echo __ELF__ | ${CC:-cc} -E - | grep -q __ELF__
then echo "Not ELF"
else echo "It is an ELF system"
fi

The "--version-script" flag should be used when performing the final linking of object files, eg:

ld --version-script=foo.ver -shared -o sum.so   C5/Cobj5.o C4/Cobj4.o C3/Cobj3.o C2/Cobj2.o C1/Cobj1.o E2/Eobj2.o E1/eoption.o E1/eref.o E1/epoly.o E1/esize.o E1/eplug.o E1/eskelet.o E1/evisib.o E1/ececil.o E1/einit.o E1/eparents.o E1/edynlib.o E1/egc_dynlib.o    "/usr/lib/eiffelstudio-6.2/libfinalized.a" -lm 

This means 1) making sure that the "../F_code/Makefile" contains:

LDSHAREDFLAGS =  --version-script=foo.ver -shared -o

and 2) that a version-script file "foo.ver" is generated when compiling a system to a shared library and that the file "foo.ver" explicitly lists the features that are to be global, which are all features from the system's .def file, and also lists all other features '*' as local!
To Reproduce
1. Finalize an Eiffel shared library system "foo.so".

2. Run the following command to list the exported global symbols:

   ../F_code$ nm -g foo.so

3. Create a version-script file "../F_code/foo.ver" with the following contents:

   VERS_1 {
       global:
           feature1_from_def_file_for_foo_system;
           feature2_from_def_file_for_foo_system;
       local:
           *; 
    };

4. Edit the "../F_code/Makefile" and change the line:

   LDSHAREDFLAGS = -shared -o

   to

   LDSHAREDFLAGS =  --version-script=foo.ver -shared -o

5. Run:

   ../F_code$ make

6. Run the following command to list the exported global symbols:

   ../F_code$ nm -g foo.so
Problem Report Interactions
From:larryl    Date:2009/08/10    Status: Analyzed    Download   
This bug is still reproducible in Eiffel Studio 6.5 (6.5.7.9743 GPL Edition - linux-x86) on Ubuntu 8.10.

The way Paul suggested works indeed.