What determines binary compatibility of shared libraries on Linux?










8















I am building a shared library on Linux, which serves as a "plugin" to some software (to be specific, it extends Mathematica).



I find that if I build on Ubuntu 16.04, the resulting library does not work on RHEL 7.6. However, if I build on RHEL 7.6, the library works both on RHEL and Ubuntu.



By "does not work", I mean that Mathematica refuses to load it, but it only gives a generic and unuseful "failed to load" error message.



I have eliminated a number of factors that could break compatibility, and I cannot find any more. This question is about what else might affect compatibility than what I list below.



The library is written in a mix of C and C++, but it exports a C interface. It is built with -static-libstdc++ and -static-libgcc. If I use ldd on the .so file, the only dependencies it lists are:



linux-vdso.so.1 => (0x00007ffc757b9000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa286e62000)
/lib64/ld-linux-x86-64.so.2 (0x00007fa287854000)


One potential source of incompatibility is the glibc version. I looked at the symbols in the library using nm -gC, and the highest GLIBC version reference I see when I build on Ubuntu is 2.14. RHEL 7.6 has glibc 2.17, i.e. newer than 2.14. Thus I do not believe that the incompatibility is due to glibc.



What else is there that can cause a shared object compiled on Ubuntu 16.04 not to load on RHEL 7.6?




Update: I managed to coax Mathematica to give a more descriptive error (it was a not very well documented feature), so I have a concrete error message. The same could also be seen with @Ctx's suggestion to set LD_DEBUG=all.



The error is:



IGraphM.so: undefined symbol: _ZTVNSt7__cxx1115basic_stringbufIcSt11char_traitsIcESaIcEEE


(IGraphM.so is my library.)



This function would seem to be part of libstdc++ unless I am mistaken. Why does this error occur if I specified -static-libstdc++ and verified that ldd does not list libstdc++?




Update 2:



Per the advice by SergeyA and this QA, I compiled after defining _GLIBCXX_USE_CXX11_ABI=0. This does fix the incompatibility.



But I still do not understand why. The error message complains about a missing symbol. Where is this symbol normally loaded from? I was under the impression that if I use -static-libstdc++, then it should be contained within my library. This seems to be wrong.



While I seem to have a practical solution for the incompatibility for this specific case, I would appreciate some explanations so in the future I can solve similar problems on my own.










share|improve this question
























  • glibc should be fine. I assume both systems are the same platform (say, x86-64). Perhaps Mathematica is a 32-bit application but you're supplying a 64-bit shared object? Have you tried creating an empty "dummy" plugin with no code, and using C only, to see if that works? The result might rule out some possibilities either way.

    – TypeIA
    Nov 13 '18 at 15:33











  • Also look around and see if Mathematica writes a log file that might contain more information. I'd be surprised if it didn't log something useful somewhere.

    – TypeIA
    Nov 13 '18 at 15:34











  • You can try to export LD_DEBUG=all in the console, where you start mathematica. Maybe it yields some debug output which can help you.

    – Ctx
    Nov 13 '18 at 15:44











  • @TypeIA Yes, same architecture (x86-64) and same version of Mathematica, but now that you asked, I started to wonder if the CPUs of the two machines support the same instruction set (e.g. when compiled on one system, gcc emits an instruction that only newer CPUs have). However, that would cause a crash, not a non-fatal failure, no?

    – Szabolcs
    Nov 13 '18 at 15:45






  • 1





    You missing symbol demangles to vtable for std::__cxx11::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> > stackoverflow.com/questions/33394934/… might have some clues.

    – SergeyA
    Nov 13 '18 at 16:24
















8















I am building a shared library on Linux, which serves as a "plugin" to some software (to be specific, it extends Mathematica).



I find that if I build on Ubuntu 16.04, the resulting library does not work on RHEL 7.6. However, if I build on RHEL 7.6, the library works both on RHEL and Ubuntu.



By "does not work", I mean that Mathematica refuses to load it, but it only gives a generic and unuseful "failed to load" error message.



I have eliminated a number of factors that could break compatibility, and I cannot find any more. This question is about what else might affect compatibility than what I list below.



The library is written in a mix of C and C++, but it exports a C interface. It is built with -static-libstdc++ and -static-libgcc. If I use ldd on the .so file, the only dependencies it lists are:



linux-vdso.so.1 => (0x00007ffc757b9000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa286e62000)
/lib64/ld-linux-x86-64.so.2 (0x00007fa287854000)


One potential source of incompatibility is the glibc version. I looked at the symbols in the library using nm -gC, and the highest GLIBC version reference I see when I build on Ubuntu is 2.14. RHEL 7.6 has glibc 2.17, i.e. newer than 2.14. Thus I do not believe that the incompatibility is due to glibc.



What else is there that can cause a shared object compiled on Ubuntu 16.04 not to load on RHEL 7.6?




Update: I managed to coax Mathematica to give a more descriptive error (it was a not very well documented feature), so I have a concrete error message. The same could also be seen with @Ctx's suggestion to set LD_DEBUG=all.



The error is:



IGraphM.so: undefined symbol: _ZTVNSt7__cxx1115basic_stringbufIcSt11char_traitsIcESaIcEEE


(IGraphM.so is my library.)



This function would seem to be part of libstdc++ unless I am mistaken. Why does this error occur if I specified -static-libstdc++ and verified that ldd does not list libstdc++?




Update 2:



Per the advice by SergeyA and this QA, I compiled after defining _GLIBCXX_USE_CXX11_ABI=0. This does fix the incompatibility.



But I still do not understand why. The error message complains about a missing symbol. Where is this symbol normally loaded from? I was under the impression that if I use -static-libstdc++, then it should be contained within my library. This seems to be wrong.



While I seem to have a practical solution for the incompatibility for this specific case, I would appreciate some explanations so in the future I can solve similar problems on my own.










share|improve this question
























  • glibc should be fine. I assume both systems are the same platform (say, x86-64). Perhaps Mathematica is a 32-bit application but you're supplying a 64-bit shared object? Have you tried creating an empty "dummy" plugin with no code, and using C only, to see if that works? The result might rule out some possibilities either way.

    – TypeIA
    Nov 13 '18 at 15:33











  • Also look around and see if Mathematica writes a log file that might contain more information. I'd be surprised if it didn't log something useful somewhere.

    – TypeIA
    Nov 13 '18 at 15:34











  • You can try to export LD_DEBUG=all in the console, where you start mathematica. Maybe it yields some debug output which can help you.

    – Ctx
    Nov 13 '18 at 15:44











  • @TypeIA Yes, same architecture (x86-64) and same version of Mathematica, but now that you asked, I started to wonder if the CPUs of the two machines support the same instruction set (e.g. when compiled on one system, gcc emits an instruction that only newer CPUs have). However, that would cause a crash, not a non-fatal failure, no?

    – Szabolcs
    Nov 13 '18 at 15:45






  • 1





    You missing symbol demangles to vtable for std::__cxx11::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> > stackoverflow.com/questions/33394934/… might have some clues.

    – SergeyA
    Nov 13 '18 at 16:24














8












8








8


1






I am building a shared library on Linux, which serves as a "plugin" to some software (to be specific, it extends Mathematica).



I find that if I build on Ubuntu 16.04, the resulting library does not work on RHEL 7.6. However, if I build on RHEL 7.6, the library works both on RHEL and Ubuntu.



By "does not work", I mean that Mathematica refuses to load it, but it only gives a generic and unuseful "failed to load" error message.



I have eliminated a number of factors that could break compatibility, and I cannot find any more. This question is about what else might affect compatibility than what I list below.



The library is written in a mix of C and C++, but it exports a C interface. It is built with -static-libstdc++ and -static-libgcc. If I use ldd on the .so file, the only dependencies it lists are:



linux-vdso.so.1 => (0x00007ffc757b9000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa286e62000)
/lib64/ld-linux-x86-64.so.2 (0x00007fa287854000)


One potential source of incompatibility is the glibc version. I looked at the symbols in the library using nm -gC, and the highest GLIBC version reference I see when I build on Ubuntu is 2.14. RHEL 7.6 has glibc 2.17, i.e. newer than 2.14. Thus I do not believe that the incompatibility is due to glibc.



What else is there that can cause a shared object compiled on Ubuntu 16.04 not to load on RHEL 7.6?




Update: I managed to coax Mathematica to give a more descriptive error (it was a not very well documented feature), so I have a concrete error message. The same could also be seen with @Ctx's suggestion to set LD_DEBUG=all.



The error is:



IGraphM.so: undefined symbol: _ZTVNSt7__cxx1115basic_stringbufIcSt11char_traitsIcESaIcEEE


(IGraphM.so is my library.)



This function would seem to be part of libstdc++ unless I am mistaken. Why does this error occur if I specified -static-libstdc++ and verified that ldd does not list libstdc++?




Update 2:



Per the advice by SergeyA and this QA, I compiled after defining _GLIBCXX_USE_CXX11_ABI=0. This does fix the incompatibility.



But I still do not understand why. The error message complains about a missing symbol. Where is this symbol normally loaded from? I was under the impression that if I use -static-libstdc++, then it should be contained within my library. This seems to be wrong.



While I seem to have a practical solution for the incompatibility for this specific case, I would appreciate some explanations so in the future I can solve similar problems on my own.










share|improve this question
















I am building a shared library on Linux, which serves as a "plugin" to some software (to be specific, it extends Mathematica).



I find that if I build on Ubuntu 16.04, the resulting library does not work on RHEL 7.6. However, if I build on RHEL 7.6, the library works both on RHEL and Ubuntu.



By "does not work", I mean that Mathematica refuses to load it, but it only gives a generic and unuseful "failed to load" error message.



I have eliminated a number of factors that could break compatibility, and I cannot find any more. This question is about what else might affect compatibility than what I list below.



The library is written in a mix of C and C++, but it exports a C interface. It is built with -static-libstdc++ and -static-libgcc. If I use ldd on the .so file, the only dependencies it lists are:



linux-vdso.so.1 => (0x00007ffc757b9000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa286e62000)
/lib64/ld-linux-x86-64.so.2 (0x00007fa287854000)


One potential source of incompatibility is the glibc version. I looked at the symbols in the library using nm -gC, and the highest GLIBC version reference I see when I build on Ubuntu is 2.14. RHEL 7.6 has glibc 2.17, i.e. newer than 2.14. Thus I do not believe that the incompatibility is due to glibc.



What else is there that can cause a shared object compiled on Ubuntu 16.04 not to load on RHEL 7.6?




Update: I managed to coax Mathematica to give a more descriptive error (it was a not very well documented feature), so I have a concrete error message. The same could also be seen with @Ctx's suggestion to set LD_DEBUG=all.



The error is:



IGraphM.so: undefined symbol: _ZTVNSt7__cxx1115basic_stringbufIcSt11char_traitsIcESaIcEEE


(IGraphM.so is my library.)



This function would seem to be part of libstdc++ unless I am mistaken. Why does this error occur if I specified -static-libstdc++ and verified that ldd does not list libstdc++?




Update 2:



Per the advice by SergeyA and this QA, I compiled after defining _GLIBCXX_USE_CXX11_ABI=0. This does fix the incompatibility.



But I still do not understand why. The error message complains about a missing symbol. Where is this symbol normally loaded from? I was under the impression that if I use -static-libstdc++, then it should be contained within my library. This seems to be wrong.



While I seem to have a practical solution for the incompatibility for this specific case, I would appreciate some explanations so in the future I can solve similar problems on my own.







c++ c linux shared-libraries abi






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 13 '18 at 16:43







Szabolcs

















asked Nov 13 '18 at 14:51









SzabolcsSzabolcs

16k361143




16k361143












  • glibc should be fine. I assume both systems are the same platform (say, x86-64). Perhaps Mathematica is a 32-bit application but you're supplying a 64-bit shared object? Have you tried creating an empty "dummy" plugin with no code, and using C only, to see if that works? The result might rule out some possibilities either way.

    – TypeIA
    Nov 13 '18 at 15:33











  • Also look around and see if Mathematica writes a log file that might contain more information. I'd be surprised if it didn't log something useful somewhere.

    – TypeIA
    Nov 13 '18 at 15:34











  • You can try to export LD_DEBUG=all in the console, where you start mathematica. Maybe it yields some debug output which can help you.

    – Ctx
    Nov 13 '18 at 15:44











  • @TypeIA Yes, same architecture (x86-64) and same version of Mathematica, but now that you asked, I started to wonder if the CPUs of the two machines support the same instruction set (e.g. when compiled on one system, gcc emits an instruction that only newer CPUs have). However, that would cause a crash, not a non-fatal failure, no?

    – Szabolcs
    Nov 13 '18 at 15:45






  • 1





    You missing symbol demangles to vtable for std::__cxx11::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> > stackoverflow.com/questions/33394934/… might have some clues.

    – SergeyA
    Nov 13 '18 at 16:24


















  • glibc should be fine. I assume both systems are the same platform (say, x86-64). Perhaps Mathematica is a 32-bit application but you're supplying a 64-bit shared object? Have you tried creating an empty "dummy" plugin with no code, and using C only, to see if that works? The result might rule out some possibilities either way.

    – TypeIA
    Nov 13 '18 at 15:33











  • Also look around and see if Mathematica writes a log file that might contain more information. I'd be surprised if it didn't log something useful somewhere.

    – TypeIA
    Nov 13 '18 at 15:34











  • You can try to export LD_DEBUG=all in the console, where you start mathematica. Maybe it yields some debug output which can help you.

    – Ctx
    Nov 13 '18 at 15:44











  • @TypeIA Yes, same architecture (x86-64) and same version of Mathematica, but now that you asked, I started to wonder if the CPUs of the two machines support the same instruction set (e.g. when compiled on one system, gcc emits an instruction that only newer CPUs have). However, that would cause a crash, not a non-fatal failure, no?

    – Szabolcs
    Nov 13 '18 at 15:45






  • 1





    You missing symbol demangles to vtable for std::__cxx11::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> > stackoverflow.com/questions/33394934/… might have some clues.

    – SergeyA
    Nov 13 '18 at 16:24

















glibc should be fine. I assume both systems are the same platform (say, x86-64). Perhaps Mathematica is a 32-bit application but you're supplying a 64-bit shared object? Have you tried creating an empty "dummy" plugin with no code, and using C only, to see if that works? The result might rule out some possibilities either way.

– TypeIA
Nov 13 '18 at 15:33





glibc should be fine. I assume both systems are the same platform (say, x86-64). Perhaps Mathematica is a 32-bit application but you're supplying a 64-bit shared object? Have you tried creating an empty "dummy" plugin with no code, and using C only, to see if that works? The result might rule out some possibilities either way.

– TypeIA
Nov 13 '18 at 15:33













Also look around and see if Mathematica writes a log file that might contain more information. I'd be surprised if it didn't log something useful somewhere.

– TypeIA
Nov 13 '18 at 15:34





Also look around and see if Mathematica writes a log file that might contain more information. I'd be surprised if it didn't log something useful somewhere.

– TypeIA
Nov 13 '18 at 15:34













You can try to export LD_DEBUG=all in the console, where you start mathematica. Maybe it yields some debug output which can help you.

– Ctx
Nov 13 '18 at 15:44





You can try to export LD_DEBUG=all in the console, where you start mathematica. Maybe it yields some debug output which can help you.

– Ctx
Nov 13 '18 at 15:44













@TypeIA Yes, same architecture (x86-64) and same version of Mathematica, but now that you asked, I started to wonder if the CPUs of the two machines support the same instruction set (e.g. when compiled on one system, gcc emits an instruction that only newer CPUs have). However, that would cause a crash, not a non-fatal failure, no?

– Szabolcs
Nov 13 '18 at 15:45





@TypeIA Yes, same architecture (x86-64) and same version of Mathematica, but now that you asked, I started to wonder if the CPUs of the two machines support the same instruction set (e.g. when compiled on one system, gcc emits an instruction that only newer CPUs have). However, that would cause a crash, not a non-fatal failure, no?

– Szabolcs
Nov 13 '18 at 15:45




1




1





You missing symbol demangles to vtable for std::__cxx11::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> > stackoverflow.com/questions/33394934/… might have some clues.

– SergeyA
Nov 13 '18 at 16:24






You missing symbol demangles to vtable for std::__cxx11::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> > stackoverflow.com/questions/33394934/… might have some clues.

– SergeyA
Nov 13 '18 at 16:24













1 Answer
1






active

oldest

votes


















4














I can't explain why your .so library doesn't link all the used symbols statically (and instead leaves them as undefined), but I can offer practical suggestion on how to fix the issue at hand.



You can stop linking libstdc++ statically into your plugin, and instead use the one available to host system. This doesn't work for you because of ABI incompatibility between build and target platforms. You can downgrade an ABI in use for your plugin by specifying macro _GLIBCXX_USE_CXX11_ABI=0.






share|improve this answer
























    Your Answer






    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53283649%2fwhat-determines-binary-compatibility-of-shared-libraries-on-linux%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    4














    I can't explain why your .so library doesn't link all the used symbols statically (and instead leaves them as undefined), but I can offer practical suggestion on how to fix the issue at hand.



    You can stop linking libstdc++ statically into your plugin, and instead use the one available to host system. This doesn't work for you because of ABI incompatibility between build and target platforms. You can downgrade an ABI in use for your plugin by specifying macro _GLIBCXX_USE_CXX11_ABI=0.






    share|improve this answer





























      4














      I can't explain why your .so library doesn't link all the used symbols statically (and instead leaves them as undefined), but I can offer practical suggestion on how to fix the issue at hand.



      You can stop linking libstdc++ statically into your plugin, and instead use the one available to host system. This doesn't work for you because of ABI incompatibility between build and target platforms. You can downgrade an ABI in use for your plugin by specifying macro _GLIBCXX_USE_CXX11_ABI=0.






      share|improve this answer



























        4












        4








        4







        I can't explain why your .so library doesn't link all the used symbols statically (and instead leaves them as undefined), but I can offer practical suggestion on how to fix the issue at hand.



        You can stop linking libstdc++ statically into your plugin, and instead use the one available to host system. This doesn't work for you because of ABI incompatibility between build and target platforms. You can downgrade an ABI in use for your plugin by specifying macro _GLIBCXX_USE_CXX11_ABI=0.






        share|improve this answer















        I can't explain why your .so library doesn't link all the used symbols statically (and instead leaves them as undefined), but I can offer practical suggestion on how to fix the issue at hand.



        You can stop linking libstdc++ statically into your plugin, and instead use the one available to host system. This doesn't work for you because of ABI incompatibility between build and target platforms. You can downgrade an ABI in use for your plugin by specifying macro _GLIBCXX_USE_CXX11_ABI=0.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Nov 13 '18 at 17:16

























        answered Nov 13 '18 at 17:08









        SergeyASergeyA

        42.2k53785




        42.2k53785



























            draft saved

            draft discarded
















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53283649%2fwhat-determines-binary-compatibility-of-shared-libraries-on-linux%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            這個網誌中的熱門文章

            Barbados

            How to read a connectionString WITH PROVIDER in .NET Core?

            Node.js Script on GitHub Pages or Amazon S3