Re: Question on DSO and visibility

2016-09-14 Thread Jonathan Wakely
On 14 September 2016 at 15:26, Paul Smith wrote:
> On Wed, 2016-09-14 at 10:13 +0100, Jonathan Wakely wrote:
>> The real problem is that your library will depend on a newer libstdc++
>> but that's orthogonal to the ABI changes. Statically linking it is one
>> solution, deploying the newer libstdc++.so with your library is
>> another.
>
> Yes, again good point.  So, as long as I don't pass objects of the
> problematic types across the ABI all is fine assuming a sufficient
> libstd++ library is available.

Right. If making the new libstdc++.so available is a problem then your
static linking + -fvisibility=hidden approach should work. I think :-)


> There's one question: what about exceptions?  std::exception::what()
> returns a const char*; I don't know if that's stored internally as a
> std::string which might have problematic types.  If I throw an exception
> from my code (new GCC/ABI) and it's caught by the caller's code (old
> GCC/ABI) is there a problem?  I'm assuming this is not an issue.

The exception classes are the same in the old and new ABIs (except for
std::ios_base::failure, which gains a new base class and data members
in C++11, so had to change anyway). The character data returned by
what() is always stored in a copy-on-write string, even when
std::string is the non-copy-on-write std::__cxx11::string.


Re: Question on DSO and visibility

2016-09-14 Thread Paul Smith
On Wed, 2016-09-14 at 10:13 +0100, Jonathan Wakely wrote:
> On 11 September 2016 at 22:38, Paul Smith wrote:
> > I wonder if someone can comment on this situation: I'll do some testing
> > but I likely can't test everything.
> > 
> > I'm creating DSO's for GNU/Linux with GCC 4.9.2 right now.  I want to
> > upgrade to GCC 6.2.0.  My code is written in C++.  I'm aware of the C++
> > STL ABI break in GCC 5.x.
> 
> Based on the solution you outlined, I'm not sure you've fully
> understood the ABI change in GCC 5.

There's little doubt you're correct about that :)

> See https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html

Thanks.  That is relatively clear.

> >3. Use a linker map to make all symbols in my DSO hidden except the
> >   specific ones I want to be public.  I use a linker map and not just
> >   -fvisibility=hidden, so that all the symbols I've statically linked
> >   from libstdc++.a will also be marked hidden (since libstdc++.a was
> >   not compiled with -fvisibility=hidden).
> 
> The different ABIs coexist automatically. Affected symbols mangle
> differently so they don't collide.

Aha.  Yes, this is the critical point I was glossing over.

> > In other words, I can use std::basic_string and std::list in my library
> > and get the C++11 ABI from GCC 6.2 that I've statically linked, and
> > users can use std::basic_string and std::list in their code and get
> > their version of the libstdc++.so (presumably that is provided by their
> > GNU/Linux distribution) and all will work properly.
> 
> You don't necessarily need two version of libstdc++ in the process.
> The newer libstdc++.so is compatible with the users' code.
> 
> If all you're worried about is the ABI change then just build your
> library with _GLIBCXX_USE_CXX11_ABI defined to 0 (or build your gcc
> with --with-default-libstdcxx-abi=gcc4-compatible)

I could do that.  The problem is: I actually create two different
binaries from my code: one is the shared library which users can link
and the other is a standalone application.  They contain almost all the
same code (the idea is that users may want to embed the application or
run it stand-alone).  I really don't want to have to compile the entire
project twice.

And all things being equal, I'd like to use the newer ABI (since 99% of
my users actually use the stand-alone binary).

But maybe the complexity of both having my cake and eating it is not
worth it.

> The real problem is that your library will depend on a newer libstdc++
> but that's orthogonal to the ABI changes. Statically linking it is one
> solution, deploying the newer libstdc++.so with your library is
> another.

Yes, again good point.  So, as long as I don't pass objects of the
problematic types across the ABI all is fine assuming a sufficient
libstd++ library is available.

There's one question: what about exceptions?  std::exception::what()
returns a const char*; I don't know if that's stored internally as a
std::string which might have problematic types.  If I throw an exception
from my code (new GCC/ABI) and it's caught by the caller's code (old
GCC/ABI) is there a problem?  I'm assuming this is not an issue.

One reason all this came up was that a user was linking with my shared
library and got a crash in their own code, and saw my version of
std::string in the stacktrace (because I linked libstdc++ statically)
even though my code was not involved.  Even though it all was working
fine, seeing this stack trace concerned them.  I was thinking that if I
ensured that my static libstdc++ was marked hidden, they would get their
own dynamically linked libstdc++ and use that from their code and I
could avoid this "appearance of impropriety".

Thanks for the response Jonathan!


Re: Question on DSO and visibility

2016-09-14 Thread Jonathan Wakely
On 11 September 2016 at 22:38, Paul Smith wrote:
> I wonder if someone can comment on this situation: I'll do some testing
> but I likely can't test everything.
>
> I'm creating DSO's for GNU/Linux with GCC 4.9.2 right now.  I want to
> upgrade to GCC 6.2.0.  My code is written in C++.  I'm aware of the C++
> STL ABI break in GCC 5.x.

Based on the solution you outlined, I'm not sure you've fully
understood the ABI change in GCC 5.

See https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html

> I have users who will be using my library who are also writing C++ code
> and they will be using older versions of GCC (I build my own GCC and I
> use a specific sysroot for an older version of libc etc. so I know my
> code will run properly on their system: they'll use their distribution's
> version of GCC).
>
> What I was thinking of doing was this:
>1. Link my DSO with -static-libstdc++ and -static-libgcc
>2. Ensure that no STL typed objects are passed across the ABI between my
>   library and its callers; also that no memory I allocate is freed by
>   the user and no memory the user allocates is freed by me (my library
>   also runs on Windows as a DLL so I already have this restriction).

On GNU/Linux there's no reason for the restriction on allocation,
there's only a single malloc. You might need to do that for Windows,
but not GNU/Linux.

>3. Use a linker map to make all symbols in my DSO hidden except the
>   specific ones I want to be public.  I use a linker map and not just
>   -fvisibility=hidden, so that all the symbols I've statically linked
>   from libstdc++.a will also be marked hidden (since libstdc++.a was
>   not compiled with -fvisibility=hidden).
>
> Is this plan sufficient to allow people to link with my library and not
> have their version of GCC's libstdc++.so interfere with my library's
> version, so the different ABI's can coexist in the same program without
> interfering with each other?

The different ABIs coexist automatically. Affected symbols mangle
differently so they don't collide.

> In other words, I can use std::basic_string and std::list in my library
> and get the C++11 ABI from GCC 6.2 that I've statically linked, and
> users can use std::basic_string and std::list in their code and get
> their version of the libstdc++.so (presumably that is provided by their
> GNU/Linux distribution) and all will work properly.

You don't necessarily need two version of libstdc++ in the process.
The newer libstdc++.so is compatible with the users' code.

If all you're worried about is the ABI change then just build your
library with _GLIBCXX_USE_CXX11_ABI defined to 0 (or build your gcc
with --with-default-libstdcxx-abi=gcc4-compatible)

The real problem is that your library will depend on a newer libstdc++
but that's orthogonal to the ABI changes. Statically linking it is one
solution, deploying the newer libstdc++.so with your library is
another.


Question on DSO and visibility

2016-09-11 Thread Paul Smith
I wonder if someone can comment on this situation: I'll do some testing
but I likely can't test everything.

I'm creating DSO's for GNU/Linux with GCC 4.9.2 right now.  I want to
upgrade to GCC 6.2.0.  My code is written in C++.  I'm aware of the C++
STL ABI break in GCC 5.x.

I have users who will be using my library who are also writing C++ code
and they will be using older versions of GCC (I build my own GCC and I
use a specific sysroot for an older version of libc etc. so I know my
code will run properly on their system: they'll use their distribution's
version of GCC).

What I was thinking of doing was this:
   1. Link my DSO with -static-libstdc++ and -static-libgcc
   2. Ensure that no STL typed objects are passed across the ABI between my
  library and its callers; also that no memory I allocate is freed by
  the user and no memory the user allocates is freed by me (my library
  also runs on Windows as a DLL so I already have this restriction).
   3. Use a linker map to make all symbols in my DSO hidden except the
  specific ones I want to be public.  I use a linker map and not just
  -fvisibility=hidden, so that all the symbols I've statically linked
  from libstdc++.a will also be marked hidden (since libstdc++.a was
  not compiled with -fvisibility=hidden).

Is this plan sufficient to allow people to link with my library and not
have their version of GCC's libstdc++.so interfere with my library's
version, so the different ABI's can coexist in the same program without
interfering with each other?

In other words, I can use std::basic_string and std::list in my library
and get the C++11 ABI from GCC 6.2 that I've statically linked, and
users can use std::basic_string and std::list in their code and get
their version of the libstdc++.so (presumably that is provided by their
GNU/Linux distribution) and all will work properly.