使用asmjit库通过汇编调用C++非静态成员函数的问题咨询
非静态成员函数asmjit调用方案
能否通过名称直接调用?
不建议通过名称调用非静态成员函数。你观察到的_ZNK3Foo5printEv是clang遵循Itanium C++ ABI生成的修饰名,命名规则和类名、函数签名、const/volatile修饰、命名空间层级强绑定,只要类结构、函数参数或修饰符有变动,修饰名就会变更,硬编码修饰名的稳定性极差,维护成本非常高。
获取非静态成员函数地址的可行方案
直接在宿主代码中取成员函数指针并提取入口地址是最优方案,完全绕开名称修饰问题:
- 对于非虚成员函数,直接通过C++语法取函数指针,提取实际入口地址即可:
你拿到class Foo { public: void print() const; }; // 取非静态成员函数指针 void (Foo::*memberFunc)() const = &Foo::print; // Itanium ABI下非虚成员函数指针的前8字节即为实际函数入口地址 uint64_t funcEntry = *reinterpret_cast<uint64_t*>(&memberFunc);funcEntry之后直接作为asmjit中call指令的目标地址即可,调用时按x86_64 System V ABI将实例地址传入rdi寄存器,和你之前调用全局函数的逻辑完全一致。 - 对于虚成员函数,不要直接取类的成员函数指针,要通过实例的虚表动态查询地址:
Foo* fooInstance = new Foo(); // 实例首地址存储虚表指针 uintptr_t* vtable = *reinterpret_cast<uintptr_t**>(fooInstance); // 按虚函数在类中的声明顺序取对应索引的地址,比如print是第一个虚函数就取索引0 uint64_t funcEntry = vtable[0];
如果你确实有动态按名称查找的需求,可以在编译宿主程序时添加-rdynamic参数导出符号表,再通过dlsym接口查找对应修饰名的地址,但该方案稳定性低,除非必要不建议使用。
内容的提问来源于stack exchange,提问作者jagemue
相关产品推荐
相关产品推荐

