【问题标题】:C++ RTTI without libstdc++. Is it possible?没有 libstdc++ 的 C++ RTTI。是否可以?
【发布时间】:2013-06-17 07:08:19
【问题描述】:

我想研究如何在没有 libstdc++ 但支持 rtti 的情况下链接 C++ 程序。我尝试按照下面描述的方式编译它。我可以在示例中定义任何必要但不存在的符号,例如函数 strcmp,但是是否可以在没有显式 mangle/demangle 魔术的情况下定义 typeinfo 符号?如果可能的话怎么做?

cd /tmp && cat << 'eof' >rtti.cpp && g++ -nodefaultlibs -lc rtti.cpp

extern "C" int strcmp(const char *s1, const char *s2) { return 0; };
#include "typeinfo"

int main(){
    return typeid(int) == typeid(char);
}

链接器说:

/tmp/cc6rBAef.o:在函数'main'中:

rtti.cpp:(.text+0x18): undefined reference to `typeinfo for char'
rtti.cpp:(.text+0x1d): undefined reference to `typeinfo for int'
collect2: error: ld returned 1 exit status

那么,如何使用 g++ 或 clang++ 在源文件中定义 'typeinfo of char'(_ZTIc@@CXXABI_1.3)?

PS。不要问我为什么需要它。只是好奇。

【问题讨论】:

  • 我不知道“-nostartfiles”选项在这种情况下是否有帮助。
  • 用不用都无所谓。问题是关于精灵符号的。想象一下,如果你愿意,我使用了“g++ ./ti.cc -nodefaultlibs -lc”。
  • 它说找不到_start 函数。也许使用该选项它不会尝试找到它,而是您在应该创建的链接文件中提供的一个。
  • 好的。我编辑了这个问题。谢谢你的评论。
  • 你不应该包括<typeinfo>而不是"typeinfo"吗?

标签: c++ linux rtti libstdc++ abi


【解决方案1】:

由于 RTTI 所需的符号似乎在 libstdc++ 库中,没有它你就不能完全做到。请注意,我是通过运行找到的

readelf -Ws `g++ -print-file-name=libstdc++.so` | awk '{print $8}' | c++filt | grep 'typeinfo for'

然而,你可以做的是静态链接libstdc++

g++ -static-libstdc++ rtti.cpp

通过这种方式,您将不会对libstdc++ 产生任何动态依赖,并且只会将您实际需要的符号拉入可执行文件。 (好吧,目标文件中包含所需符号的所有符号,我想在你的例子中是fundamental_type_info.o。)

【讨论】:

  • 您引用的是 2005 年的一篇博文。现在,您可以通过 -static-libstdc++ 选项。
  • 感谢您的回答,我也找到了 basic_type_info.o。但是文件 gcc-4.8.0/libstdc++-v3/libsupc++/fundamental_type_info.cc 是空的。似乎基本类型是在文件 gcc-4.8.0/gcc/cp/rtti.c 中生成的,但我不确定。我一直在努力。
  • @SpoonwalkerHighwater:嗯,最终哪个.o 文件包含这些符号并不重要,因为当您静态链接时,会自动拉入正确的文件。还是您实际上是在尝试自己实现 RTTI?在这种情况下,请查看Itanium C++ ABI 的相关部分。
  • 真的很想知道编译器是如何定义基础类型信息的。我阅读了 Itanium ABI,但它没有提供理解变量如何实现的关键。用户类的类型信息由 g++ 生成,但基本类型的类型信息位于 libstdc++ 中。就 libstdc++ 被编译和链接为普通库而言,存在一种为用户库中的基本类型生成类型信息的方法。我想找到它。
  • @SpoonwalkerHighwater:我曾经自己创建了一个 RTTI 实现,而我使用的 only 文档是我链接到的 ABI,因此所有必需的“密钥”都应该在那里。如果你愿意,我可以在某处发布我的实现。
【解决方案2】:

感谢gcc community 的提示。

答案是:

“gcc 使用一些魔法将 __fundamental_type_info 的析构函数替换为一组 typeinfo 符号”

替换码放在文件:gcc-4.7.2/gcc/cp/rtti.c,void emit_support_tinfos(void);

rtti.cc:

#include <typeinfo>
namespace __cxxabiv1 {
class __fundamental_type_info:public std::type_info{
public:
     explicit __fundamental_type_info(const char* __n) : std::type_info(_n) { } 
     virtual ~__fundamental_type_info(){}; 
};
}
int main(){
    return typeid(int) == typeid(char);
}

所有基本类型信息都在编译期间插入到目标文件中。

$g++ -c ./rtti.cc;readelf -sW ./rtti.o |c++filt|grep typeinfo|wc -l

$153

所以问题得到了回答。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-09-14
    • 2018-10-04
    • 1970-01-01
    • 2016-07-27
    • 1970-01-01
    • 2022-12-14
    • 1970-01-01
    • 2016-11-05
    相关资源
    最近更新 更多