Itanium和MSVC abi中跨模块边界的RTTI

RTTI across module boundaries in Itanium and MSVC ABIs

本文关键字:模块 边界 RTTI MSVC abi Itanium      更新时间:2023-10-16

我正在阅读Itanium ABI,它说

当且仅当两个type_info指针相等时,它们指向相同的类型描述。实现必须满足此约束,例如,通过使用符号抢占、COMDAT节或其他机制。

有谁知道在流行的平台上,比如Linux使用GCC和GNU binutils,当使用动态加载的库时,是如何实现的?它有多可靠?

另外,我的印象是,MSVC中的typeid比较是(曾经是?)使用运行时字符串比较来实现的,正是因为这个要求不能保证得到满足。现在还是这样吗?是否存在阻止MSVC使用Itanium ABI平台上使用的相同技术的技术平台限制?

EDIT还有一个问题:跨模块边界(在任何ABI中)的异常捕获是否也依赖于RTTI信息,或者除了等效运行时dynamic_cast之外是否还有其他机制?

MSVC首先使用指针比较,如果失败,则比较字符串。您可以在VS2012的CRT源代码中看到实现:

extern "C" _CRTIMP int __cdecl __TypeMatch(
    HandlerType *pCatch,                // Type of the 'catch' clause
    CatchableType *pCatchable,          // Type conversion under consideration
    ThrowInfo *pThrow                   // General information about the thrown
                                        //   type.
) {
    // First, check for match with ellipsis:
    if (HT_IS_TYPE_ELLIPSIS(*pCatch)) {
        return TRUE;
    }
    // Not ellipsis; the basic types match if it's the same record *or* the
    // names are identical.
    if (HT_PTD(*pCatch) != CT_PTD(*pCatchable)
      && strcmp(HT_NAME(*pCatch), CT_NAME(*pCatchable)) != 0) {
        return FALSE;
    }
    ...

Itanium ABI总是只使用指针比较。与dll一起工作的方式是,动态加载器应该确保在程序的地址空间中,对于每个异常都有一个typeinfo对象的实例。

如果您对异常RTTI的实际实现和捕获信息感兴趣,请查看我的OpenRCE文章(MSVC)和Recon 2012演示文稿(GCC, MSVC x64)。