How can I check if a library was compiled with -fno-rtti?
Asked Answered
P

2

8

Assume a simple file bla.cpp:

struct MyClass {
  virtual int foo(int x);
  virtual ~MyClass();
};


int MyClass::foo(int x) { return x + 23; }
MyClass::~MyClass() {}

Build into a shared library with

g++ -c -fPIC bla.cpp
g++ -shared -o bla.so bla.o

will usually contain some type_info symbol because RTTI is enabled by default on gcc. However, if I build with

g++ -c -fPIC -fno-rtti bla.cpp

the type_info will be missing.

Is there a simple, reliable way (on gcc or clang) to check if a library has been built with -fno-rtti or -frtti? I ask because today I stared at the infamous undefined reference to type_info and it took me a moment to understand that this was cause by a library I was linking against being built with -fno-rtti.

Propel answered 3/3, 2014 at 15:34 Comment(4)
Well why don't you use <dynamic_cast> and see if you get a compilation error? Or do you need to conduct this test during runtime?Chafee
@barakmanos This is not going to work. If I use dynamic_cast my code breaks depending on my setting of f(no)rtti. I'm wondering about a library I'm linking against (here inheritance is usually enough to break compilation). I really want to know this during configure time to set up parts of my build correctly or perhaps warn about it.Propel
If you need this for configuration, do as GNU autoconf does: Write a minimal proggie that does the checking and build that one. If the build (or perhaps run) fails or not tells you what you need to know.Wean
@Wean Yes, that sounds good. Could you add it as an answer?Propel
D
11

If a class has virtual. functions, it should have type info. Do nm -C libname.so and watch for "vtable for", "typeinfo for", and "typeinfo name for". Example:

00000000 b .bss
00000000 d .data
00000000 r .eh_frame
00000000 r .rdata$_ZTI3Foo
00000000 r .rdata$_ZTS3Foo
00000000 r .rdata$_ZTV3Foo
00000000 r .rdata$zzz
00000000 t .text
00000000 T Foo::foo()
00000000 R typeinfo for Foo
00000000 R typeinfo name for Foo
00000000 R vtable for Foo
         U vtable for __cxxabiv1::__class_type_info

If you have vtable but not typeinfo, this is compiled with -fno-rtti. Example:

00000000 b .bss
00000000 d .data
00000000 r .eh_frame
00000000 r .rdata$_ZTV3Foo
00000000 r .rdata$zzz
00000000 t .text
00000000 T Foo::foo()
00000000 R vtable for Foo

If you don't have any virtual functions, you cannot tell (and should not care).

Dado answered 3/3, 2014 at 16:33 Comment(7)
if you strip symbols, do you still get this information in the library?Cult
Can I assume this to be the same across different compilers? I wouldn't think so, but maybe I'm wrong.Propel
@BЈовић You cannot link with a stripped library, but you can try nm -D.Dado
@Propel no, but I think the microsoft compiler has similar symbols for vtable and typeinfo.Dado
After some thought, I realized that my comment was a nonsense. Of course, this info is there even after stripping the library. I am not sure what you meant with "can't link", but I was thinking of just stripping debug symbols.Cult
@BЈовић no, it's not nonsense. Stripping removes info necessary for ld so linking will fail; but symbols necessary for ld.so remain so you can still dlopen and load it.Dado
Great answer and to the point. I guess that all those C++ ABI changes eventually resulted in library dependencies issues being easier to debug :)Bedrail
W
3

If you need this for configuration, do as GNU autoconf does: Write a minimal proggie that does the checking and build that one. Whether the build (or perhaps a run) fails or not tells you what you need to know.

Wean answered 3/3, 2014 at 19:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.