c++ - 如何定义导出符号的地址

标签 c++ c gcc assembly linker

假设我正在编写一个 C++ 库,它必须导出一个变量,一个数据结构,例如称为 ExpData。因此,链接到我的库的程序可以访问此变量(有一个公共(public) header 将其定义为 extern void *ExpData[])。

然而,这个数据结构在内部是一个C++类的vtable。例如,类的名称是 InternalType。因此,在查看生成的汇编代码后,我发现 InternalType 的 vtable 被导出为 _ZTV12InternalType

然后,我需要一种方法使我的库导出变量 ExpData 解析为与 _ZTV12InternalType 相同的地址,这样,当外部程序读取我的库的 ExpData变量,其实就是读取InternalType的vtable。

澄清一下,InternalType 的 vtable 汇编代码是:

    .type   _ZTV12InternalType,@object # @_ZTV12InternalType
    .section    .data.rel.ro._ZTV12InternalType,"aGw",@progbits,_ZTV12InternalType,comdat
    .weak   _ZTV12InternalType
    .align  16
_ZTV12InternalType:
    .quad   0
    .quad   _ZTI12InternalType
    .quad   _ZN12InternalType8vMethodXEi
    .size   _ZTV12InternalType, 24

所以,我需要一种方法来实现这一点(或具有相同效果的其他方法):

    .type   ExpData,@object
    .globl  ExpData

    .type   _ZTV12InternalType,@object
    .section    .data.rel.ro._ZTV12InternalType,"aGw",@progbits,_ZTV12InternalType,comdat
    .weak   _ZTV12InternalType
    .align  16
_ZTV12InternalType:
ExpData:
    .quad   0
    .quad   _ZTI12InternalType
    .quad   _ZN12InternalType8vMethodXEi
    .size   _ZTV12InternalType, 24

在C++端有可能吗?

P.S.:我知道我不应该依赖与实现相关的细节,例如名称修改和 C++ 类内部数据,但只要考虑到我的库将在非常特定的环境中运行。

编辑

我可以通过将 --defsym ExpData=_ZTV12InternalType 传递给链接器来解决我的问题。但是,我不想将实现细节附加到外部资源。假设我决定将类的 vtable 映射为名为 InternalTypeVTable 的 C 结构。因此,我可以将 ExpData 声明为 InternalTypeVTable ExpData;。如果我只需更改源文件而不是 makefile 和链接器脚本,那就太好了。

最佳答案

GCC 的 __attribute__ ((alias())) 正是我需要的。

如果我声明 ExpData 如下:

void *ExpData[0] __attribute__ ((alias("_ZTV12InternalType")));

在我的库的源文件中,我得到以下汇编代码:

    .globl  ExpData
ExpData = _ZTV12InternalType

因此,导出的符号 ExpData 引用与 _ZTV12InternalType 相同的内存地址。

关于c++ - 如何定义导出符号的地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24113044/

相关文章:

c - 特殊字符读取错误 - 文件 I/0

c - 函数调用时的栈结构

c++ - 模板类的类型转换问题

c++ - 时间类构造函数

c - if 跳转 vs 函数跳转

mysql - 在c编程中使用mysql

c++ - 启动时多线程?

c++ - va_start() 修改堆栈

c - linux 终端卡在 bash 脚本上

c++ - C 链接和 C++ 头文件