Possible missing symbol in TGenericClassInfo from Subversion

Hello all,

I’m trying to work with a build of the Subversion trunk (v5.27), and running into some dlopen errors when I try to import some other libraries from our local project.

ROOT 5.27/03 (trunk@33536, May 17 2010, 14:01:07 on linux)

CINT/ROOT C/C++ Interpreter version 5.17.00, Dec 21, 2008
Type ? for help. Commands must be C++ statements.
Enclose multiple statements between { }.
root [0] gSystem->Load("libsvx.so")
Warning in <TClassTable::Add>: class TSQLStatement already in TClassTable
dlopen error: /home/mlockner/local/lib/libRootmessage.so.0: undefined symbol: _ZN4ROOT17TGenericClassInfoC1EPKcS2_iRKSt9type_infoPKNS_13TInitBehaviorEPvPFvvEP16TVirtualIsAProxyii

 *** Break *** segmentation violation
(snip stack trace that follows)

Someone pointed me to a tool called c++filt that can translate the cryptic symbol names. In this case, the _ZN4… symbol translates into:

ROOT::TGenericClassInfo::TGenericClassInfo(char const*, char const*, int, std::type_info const&, ROOT::TInitBehavior const*, void*, void (*)(), TVirtualIsAProxy*, int, int)

This would seem to correspond to a constructor found ca. line 39 of core/meta/src/TGenericClassInfo.cxx:

   TGenericClassInfo::TGenericClassInfo(const char *fullClassname,
                                        const char *declFileName, Int_t declFileLine,
                                        const type_info &info, const TInitBehavior  *action,
                                        ShowMembersFunc_t showmembers, VoidFuncPtr_t dictionary,
                                        TVirtualIsAProxy *isa, Int_t pragmabits, Int_t sizof)
      : fAction(action), fClass(0), fClassName(fullClassname),
        fDeclFileName(declFileName), fDeclFileLine(declFileLine),
        fDictionary(dictionary), fInfo(info),
        fImplFileName(0), fImplFileLine(0),
        fIsA(isa), fShowMembers(showmembers),
        fVersion(1),
        fNew(0),fNewArray(0),fDelete(0),fDeleteArray(0),fDestructor(0), fDirAutoAdd(0), fStreamer(0),
        fCollectionProxy(0), fSizeof(sizof),
        fCollectionProxyInfo(0), fCollectionStreamerInfo(0)
   {
      // Constructor.

      Init(pragmabits);
   }

Now, the lines in the build for this file are:

bin/rmkdepend -R -fcore/meta/src/TGenericClassInfo.d -Y -w 1000 -- -pipe -m32 -Wall -W -Woverloaded-virtual -fPIC -Iinclude -DR__HAVE_CONFIG -pthread -D__cplusplus -- core/meta/src/TGenericClassInfo.cxx
g++ -O2 -pipe -m32 -Wall -W -Woverloaded-virtual -fPIC -Iinclude -DR__HAVE_CONFIG -pthread -o core/meta/src/TGenericClassInfo.o -c core/meta/src/TGenericClassInfo.cxx

However, I cannot establish that the aforementioned constructor is getting compiled into the object file, or thence into libCore.so. I also tried generating the intermediate assembler file, and the symbol doesn’t seem to be there either.

Is there something wrong that is causing no code to be generated for that constructor?

Thanks,
Matthew Lockner

[quote]However, I cannot establish that the aforementioned constructor is getting compiled into the object file, or thence into libCore.so[/quote]You can use ‘nm’ on either the object file or the library to make sure it is there … However it is most certainly there as it is used by almost all dictionaries and hence if it was missing libCore itself should not load.

I suspect that you have an incomplete/mixed up environment where your library has not yet been recompiled against the new version of ROOT and/or there is a problem (another version of ROOT) on your PATH, LD_LIBRARY_PATH and/or ROOTSYS.

Cheers,
Philippe.

[quote=“pcanal”][quote]However, I cannot establish that the aforementioned constructor is getting compiled into the object file, or thence into libCore.so[/quote]You can use ‘nm’ on either the object file or the library to make sure it is there … However it is most certainly there as it is used by almost all dictionaries and hence if it was missing libCore itself should not load.

I suspect that you have an incomplete/mixed up environment where your library has not yet been recompiled against the new version of ROOT and/or there is a problem (another version of ROOT) on your PATH, LD_LIBRARY_PATH and/or ROOTSYS.

Cheers,
Philippe.[/quote]

Hello Philippe,

nm was the tool I was using to check for the presence of the needed symbol. I had also verified (via ldd) that the library I was loading was referencing my freshly built libCore.

[mlockner@goldrush root]$ nm ~/local/lib/root/libCore.so | grep _ZN4ROOT17TGenericClassInfoC1EPKcS2_iRKSt9type_infoPKNS_13TInitBehaviorEPvPFvvEP16TVirtualIsAProxyii
[mlockner@goldrush root]$ nm core/meta/src/TGenericClassInfo.o | grep _ZN4ROOT17TGenericClassInfoC1EPKcS2_iRKSt9type_infoPKNS_13TInitBehaviorEPvPFvvEP16TVirtualIsAProxyii
[mlockner@goldrush root]$ ldd ~/local/lib/libsvx.so | grep libCore
        libCore.so => /home/mlockner/local/lib/root/libCore.so (0xf6567000)

There are, however, other similar symbols; the ones not containing “MemberInspector” appear to correspond to the other constructors in TGenericClassInfo:

[mlockner@goldrush root]$ nm ~/local/lib/root/libCore.so | grep TGenericClassInfo | grep TVirtualIsAProxy
00000000001fa0b0 T _ZN4ROOT17TGenericClassInfoC1EPKcS2_iRKSt9type_infoPKNS_13TInitBehaviorEPFvPvR16TMemberInspectorPcEPFvvEP16TVirtualIsAProxyii
00000000001f9e90 T _ZN4ROOT17TGenericClassInfoC1EPKciS2_iRKSt9type_infoPKNS_13TInitBehaviorEPFvPvR16TMemberInspectorPcEPFvvEP16TVirtualIsAProxyii
00000000001f9c50 T _ZN4ROOT17TGenericClassInfoC1EPKciS2_iRKSt9type_infoPKNS_13TInitBehaviorEPFvvEP16TVirtualIsAProxyii
00000000001fa1d0 T _ZN4ROOT17TGenericClassInfoC2EPKcS2_iRKSt9type_infoPKNS_13TInitBehaviorEPFvPvR16TMemberInspectorPcEPFvvEP16TVirtualIsAProxyii
00000000001f9fa0 T _ZN4ROOT17TGenericClassInfoC2EPKciS2_iRKSt9type_infoPKNS_13TInitBehaviorEPFvPvR16TMemberInspectorPcEPFvvEP16TVirtualIsAProxyii
00000000001f9d70 T _ZN4ROOT17TGenericClassInfoC2EPKciS2_iRKSt9type_infoPKNS_13TInitBehaviorEPFvvEP16TVirtualIsAProxyii

I have also very carefully rechecked the environment variables you mentioned to ensure my local paths are first and the ROOT I built is the one being run. It still appears, as best as I can tell, that my libCore has missing symbols.

Can you think of anything else I might try to help track down the problem?

Thanks,
Matthew Lockner

Hi,

Taking another look I noticed that indeed: ROOT::TGenericClassInfo::TGenericClassInfo(char const*, char const*, int, std::type_info const&, ROOT::TInitBehavior const*, void*, void (*)(), TVirtualIsAProxy*, int, int) is a signature that was explicitly removed in 5.27 (namely the void* was replace with a function pointer.

And accordingly to your logs the library that was not rebuild is:dlopen error: /home/mlockner/local/lib/libRootmessage.so.0: undefined symbol:

Cheers,
Philippe.

Thanks, that was the vital info I was missing. I presume there is no plan to implement reverse compatibility in this instance?

Cheers,
M. Lockner

[quote]I presume there is no plan to implement reverse compatibility in this instance?[/quote]This actually would be quite restrictive as it would (essentially) freeze not only the public interfaces but also the (semi) private interfaces used in dictionary (i.e. the one you encountered) and I don’t think that we are yet at the point where the benefit (allowing you to use older code with newer version of ROOT without even recompiling it) outweigh the many costs (extreme limitation in the type of interface improvement, run-time cost incurred by the technique needed to support binary backward compatibility, very large increase in the amount and type of testing required to insure correctness, etc.).

Cheers,
Philippe.

My problem is that I am ending up having to recompile half the experiment’s software base because of this one change. I recompile one library, and then it just fails trying to load another. They are entrenched in version 5.17 for reasons I don’t completely understand, but I am writing an EVE application, and 5.17 won’t do for that.

I can’t seriously suggest the whole of ROOT be hacked up for my one issue - but is there some sort of means by which I could patch just my copy of the ROOT sources to provide the removed functionality?

Thanks,
Matthew Lockner

[quote] but is there some sort of means by which I could patch just my copy of the ROOT sources to provide the removed functionality?[/quote]Sure there is, however this probably would be more harmful than anything else. This one case had a link time consequence that is easy to spot but similar change (for example if we added a data member to one of the class that is used in one of your experiment’s software) would have very hard to track consequence (usually resulting in random (wrong) behavior) ; tracking all the necessary changes would be much work than recompiling your whole experiment framework.

Philippe.

An additional thought - I am running into cases where completely fresh checkouts of CVS sources of ours will fail to link because of the same missing constructor problem. After some grepping, it looks like there are no explicit references to TGenericClassInfo in our sources - except in the generated dictionaries (*_Dict.C).

Is it possible that the dictionary source files are being generated by rootcint with the old constructor prototype?

(My apologies if I’m not using the correct ROOT terminology for things; I can attempt to elaborate further if the above didn’t make sense).

[quote]After some grepping, it looks like there are no explicit references to TGenericClassInfo in our sources - except in the generated dictionaries (*_Dict.C).[/quote]Indeed this is the only place they should occur.

[quote]Is it possible that the dictionary source files are being generated by rootcint with the old constructor prototype?[/quote]In that respect the code generated has not changed, the only thing that changed is the header file of TGenericClassInfo where the signature become more restrictive. So if you indeed already re-run rootcint and recompile the library I mentioned then this means that during its compilation its used the wrong set of header files (i.e. the compiler saw the older header files).

Cheers,
Philippe.