This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Crash due to mis-bind of a libstdc++ symbol


On Sun, 17 Apr 2005 21:41:27 +0100, Mike Hearn wrote:
> I haven't fully investigated what is going on here, but for some reason a
> v5 symbol takes precedence over the v6 symbol despite the use of symbol
> versioning. 

I have a small test case. It doesn't crash, but it does show the
mis-bind. What appears to be happening is this.

The STL string + operator overload is defined inline.
Program "yyy", compiled with g++ 3.3, contains this code:

------------------------------------------------------------------
#include <string>
#include <iostream>

extern "C" void go();

int main()
{
    std::string one("one");
    std::string two(" two");

    // force definition of _ZStplIcSt11char_traitsIcESaIcEESbIT_T0_T1_ERKS6_S8_
    // (std::string "+" op override)
    std::string three = one + two;

    std::cout << three << std::endl;
    go();

    return 0;
}

------------------------------------------------------------------

It links against library libxxx.so, compiled using g++ 3.4, 
which contains this code:

------------------------------------------------------------------

#include <stdio.h>
#include <string>

extern "C" void go()
{
    std::string a("a");
    std::string b("b");

    std::string c = a + b;

    printf("%s\n", c.c_str());
}

------------------------------------------------------------------

In other words, both the program "yyy" and "libxxx" contain the a copy of
the std::string + operator. These are both defined as weak symbols,
meaning that they are bound to the first definition in an image. I do not
understand why this is so: I thought methods defined in headers would
be inlined into the code, not emitted into the binary as a symbol. 

Because they were emitted by the compiler, the weak symbol in libxxx.so
is resolved by the dynamic linker. It begins its search from the start 
of the global symbol scope:

5250:	symbol=_ZStplIcSt11char_traitsIcESaIcEESbIT_T0_T1_ERKS6_S8_;  lookup in file=./yyy
5250:	binding file /home/mike/Code/C++/misbind/libxxx.so to ./yyy: normal symbol `_ZStplIcSt11char_traitsIcESaIcEESbIT_T0_T1_ERKS6_S8_'

In this case libxxx.so got bound to the definition in yyy, but that's
just because I forced a definition of std::string operator + in that binary. 

In my original problem case, actually the definition was not in Inkscape
(as Inkscape does not use the STL string but rather Glib::ustring and C
strings) but was nonetheless found in the libstdc++.so.5 binary as that
was loaded into the global scope before libstdc++.so.6 was.

If you can figure out a way (hax0r the binary, whatever) to make 
libstdc++.so.5 the first DT_NEEDED entry before libxxx.so is in yyy, then
you don't need any code except the call to go() in yyy at all.
What matters is which definition takes precedence: it's not too hard
to engineer a situation where an older copy of a symbol comes first
in the search scope, and as the weak definition was not emitted with 
any symbol version, it's bound to the wrong one.

Does this analysis make sense, or am I misunderstanding something?

thanks -mike


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]