我可以隐藏或删除共享库中的类名吗?

时间:2014-09-04 08:18:13

标签: c++

如果此类是多态的,我发现类名不能隐藏在共享库中。例如,

// example.cpp
#include <stdio.h>
#include <string.h>

// #define virtual 

class Base
{
  public:
    virtual const char* whatiam()
    {
        return "Papa";
    }
};

class Child : public Base
{
  public:
    virtual const char* whatiam()
    {
        return "Son";
    }
};

const char* whatiam(Base* obj)
{
    return obj->whatiam();
}

__attribute__((visibility("default"))) const char* TheAPI(int n)
{
    static char buf[64];
    Child t;
    sprintf(buf, "I'm %s.", whatiam(&t));
    return buf;
}

我在Linux上使用像这样的gcc构建一个共享库

$ g++ -fPIC -shared -fvisibility=hidden ../example.cpp -o libexample.so 
$ strip -R .comment -R .note libexample.so

然后我在Emacs中打开libexample.so作为普通文件进行搜索,找到类名BaseChild

如果我将语句// #define virtual取消注释为#define virtual,也就是说没有虚拟方法make BaseChild,我会找到类名{{1将无法在共享库中找到和Base

编辑时,类名称是否存储在类 vtable 中?或者其他一些原因导致了这个问题?

1 个答案:

答案 0 :(得分:5)

  

如果此类是多态的,我发现类名不能隐藏在共享库中。

不清楚你所指的是什么样的隐藏。

从链接器符号可见性角度来看,隐藏了所有具有内部链接的名称。类根本没有链接,函数和变量都有:

$ nm -C libexample.so
nm: libexample.so: no symbols

$ nm -D -C libexample.so
0000000000201030 B __bss_start
                 w __cxa_finalize
0000000000201030 D _edata
00000000002010a0 B _end
0000000000000944 T _fini
                 w __gmon_start__
0000000000000728 T _init
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 w _Jv_RegisterClasses
                 U sprintf
0000000000000899 T TheAPI(int)
                 U vtable for __cxxabiv1::__class_type_info
                 U vtable for __cxxabiv1::__si_class_type_info


$ strings libexample.so | c++filt 
__gmon_start__
_init
_fini
_ITM_deregisterTMCloneTable
_ITM_registerTMCloneTable
__cxa_finalize
_Jv_RegisterClasses
TheAPI(int)
sprintf
vtable for __cxxabiv1::__si_class_type_info
vtable for __cxxabiv1::__class_type_info
libstdc++.so.6
libm.so.6
libgcc_s.so.1
libc.so.6
_edata
__bss_start
_end
CXXABI_1.3
GLIBC_2.2.5
fffff.
Papa
I'm %s.
5Child
4Base
;*3$"

这些字符串5Child4Basetypeid()返回的typeinfo:

typeinfo name for Child:
    .string "5Child"
    .hidden typeinfo for Child
    .weak   typeinfo for Child
    .section    .data.rel.ro._ZTI5Child,"awG",@progbits,typeinfo for Child,comdat
    .align 16
    .type   typeinfo for Child, @object
    .size   typeinfo for Child, 24
typeinfo name for Base:
    .string "4Base"
    .hidden typeinfo for Base
    .weak   typeinfo for Base
    .section    .data.rel.ro._ZTI4Base,"awG",@progbits,typeinfo for Base,comdat
    .align 16
    .type   typeinfo for Base, @object
    .size   typeinfo for Base, 16

您可以使用-fno-rtti编译器开关禁用typeinfo:

       -fno-rtti
           Disable generation of information about every class with virtual
           functions for use by the C++ run-time type identification features
           (dynamic_cast and typeid).  If you don't use those parts of the
           language, you can save some space by using this flag.  Note that
           exception handling uses the same information, but G++ generates it
           as needed. The dynamic_cast operator can still be used for casts
           that do not require run-time type information, i.e. casts to "void
           *" or to unambiguous base classes.