函数地址由序数Linux?

时间:2015-02-12 06:13:59

标签: c++ linux

Linux是否可以通过共享对象的序数或索引检索函数地址?

我问,因为我正在编写一个OpenGL包装器,我必须为所有300多个函数执行以下操作:

module->AddressOf(funcs[0],"glAccum");
module->AddressOf(funcs[1],"glAlphaFunc");
module->AddressOf(funcs[2],"glAreTexturesResident");
module->AddressOf(funcs[3],"glArrayElement");
module->AddressOf(funcs[4],"glBegin");
module->AddressOf(funcs[5],"glBindTexture");
module->AddressOf(funcs[6],"glBitmap");
module->AddressOf(funcs[7],"glBlendFunc");
module->AddressOf(funcs[8],"glCallList");
module->AddressOf(funcs[9],"glCallLists");
module->AddressOf(funcs[10],"glClear");
module->AddressOf(funcs[11],"glClearAccum");
module->AddressOf(funcs[12],"glClearColor");
module->AddressOf(funcs[13],"glClearDepth");
module->AddressOf(funcs[14],"glClearIndex");
module->AddressOf(funcs[16],"glClearStencil");
module->AddressOf(funcs[17],"glClipPlane");
module->AddressOf(funcs[18],"glColor3b");
module->AddressOf(funcs[19],"glColor3bv");
module->AddressOf(funcs[20],"glColor3d");

依此类推......在Windows上,我可以做到:

for (int i = 0; i < 385; ++i)
   module->AddressOf(funcs[i], (const char*)i);

就是这样!每个函数的地址存储在funcs[I]中。 Linux有与上面类似的内容吗?

注意:

Module->AddressOf相当于:

bool Module::AddressOf(void* &func, const char* name) 
{
    #if defined _WIN32 || defined _WIN64
    func = (void*)GetProcAddress(handle, name);
    #else
    func = dlsym(handle, name);
    #endif

    return func != nullptr;
}

是的,我通过迭代func数组并查看其中是否有NULL来检查错误。

Windows上的序数值示例:

enter image description here

1 个答案:

答案 0 :(得分:1)

在Linux上,您可以使用dlopen(3)dlsym函数。链接主程序时不要忘记传递-rdynamic

当然,您需要知道函数的名称,以便使用dlsym

获取其地址

请注意,您可以通过dlopen在主程序中获取符号 - 将其作为NULL

害怕C ++ name mangling。使用extern "C"将其停用。

BTW,如果你的意思是

 for (int i = 0; i < 385; ++i)
    module->AddressOf(funcs[i], (const char*)i);

(我猜你有一个错字:你的代码混合了Ii)我很惊讶它甚至可以在Windows上可靠地工作:当i为50时,{{1}是(const char*)i,它不太可能是有效的字符串。在Linux上肯定不是(因为地址空间的第一个4K页面没有映射,我想在Windows上也是如此,我不知道。)

但是,GetProcAddress被记录为处理

  

函数的序数值。如果此参数是序数值,则它必须在低位字中;高阶词必须为零。

我不知道函数的序数值是什么(在某些共享库中),而AFAIK Linux没有这样的概念。即使您的代码在Windows上运行,它如何知道(const char*)50对应funcs[5]?您需要在某处将代码提供给您的代码!

在Linux上如果要从其地址获取函数名称,可以使用glBindTexture

如果您需要获取OpenGL函数的地址,您需要处理它们的每个名称!

也许你可以在某些数组中收集许多OpenGL函数的名称。您可以使用一些脚本(可能是一些dladdr脚本处理某些OpenGL标头,或者可能使用GCC自定义MELT编译器来收集它们。

您可能会使用某些ELF读取库(如awk)并扫描ELF符号表。您可以libelf使用popen ...

之类的命令

阅读Drepper's paper: How To Write Shared Libraries;它详细解释了这一切!