链接到.so文件中的特定符号版本

问题描述

在使用符号版本时,显然有一些我做不到的事情,但是我不能指望它是什么。

背景:我正在开发一个需要链接到Python 2.7的应用程序,但它也使用了需要Python 2.6的第三方插件。为我腾出关于Python 2过时的演讲:我知道。但这是该项目不可协商的要求。如果您愿意,可以假装其他库。

我提出的问题的早期版本为here。自该问题的上一次活动以来,我已经做到:

  • 确定Windows中不存在此问题;纯粹是在Linux上,据记录,我目前正在使用CentOS 7。
  • 使用-fno-semantic-interposition编译器标记和--default-symver链接标记重新编译libpython2.7.so.1.0。
  • 验证libpython2.7.so.1.0包含必需的符号版本,即。
> objdump -T libpython2.7.so.1.0 | fgrep Py_
00000000000e8920 g    DF .text  000000000000007a  libpython2.7.so.1.0 _Py_With
00000000000e8490 g    DF .text  000000000000009a  libpython2.7.so.1.0 _Py_ClassDef
0000000000042900 g    DF .text  00000000000000fd  libpython2.7.so.1.0 _Py_addlabel
00000000000e8a60 g    DF .text  000000000000004d  libpython2.7.so.1.0 _Py_TryFinally
00000000000e8b70 g    DF .text  0000000000000059  libpython2.7.so.1.0 _Py_ImportFrom
0000000000412b74 g    DO .bss   0000000000000004  libpython2.7.so.1.0 Py_InteractiveFlag
etc.
  • 验证,在编译和链接后,我自己的可执行文件知道要寻找符号的正确版本
> objdump -T myApplication | fgrep Py_
0000000000000000      DF *UND*  0000000000000000  libpython2.7.so.1.0 Py_Finalize
0000000000000000      DO *UND*  0000000000000000  libpython2.7.so.1.0 Py_NoUserSiteDirectory
0000000000000000      DF *UND*  0000000000000000  libpython2.7.so.1.0 Py_CompileStringFlags
0000000000000000      DF *UND*  0000000000000000  libpython2.7.so.1.0 Py_IsInitialized
0000000000000000      DF *UND*  0000000000000000  libpython2.7.so.1.0 Py_Initialize
0000000000000000      DF *UND*  0000000000000000  libpython2.7.so.1.0 Py_DecRef
0000000000000000      DF *UND*  0000000000000000  libpython2.7.so.1.0 Py_SetPythonHome
0000000000000000      DO *UND*  0000000000000000  libpython2.7.so.1.0 Py_IgnoreEnvironmentFlag

尝试将__asm(“。symver ...”)声明另外插入到我的源文件中,例如建议here

#include <Python.h>

__asm__(".symver Py_NoUserSiteDirectory,Py_NoUserSiteDirectory@libpython2.7.so.1.0");
__asm__(".symver Py_CompileStringFlags,Py_CompileStringFlags@libpython2.7.so.1.0");
__asm__(".symver Py_SetPythonHome,Py_SetPythonHome@libpython2.7.so.1.0");
__asm__(".symver Py_Initialize,Py_Initialize@libpython2.7.so.1.0");
__asm__(".symver Py_IsInitialized,Py_IsInitialized@libpython2.7.so.1.0");
__asm__(".symver Py_DecRef,Py_DecRef@libpython2.7.so.1.0");
__asm__(".symver Py_IgnoreEnvironmentFlag,Py_IgnoreEnvironmentFlag@libpython2.7.so.1.0");
__asm__(".symver Py_Finalize,Py_Finalize@libpython2.7.so.1.0");

但毕竟:

  1. 我必须预加载libpython2.6.so.1.0,否则该插件在被调用时会调用功能的Python 2.7版本并崩溃。
    export LD_PRELOAD=<path to>/libpython2.6.so.1.0
  1. 随后从我自己的代码对Python函数调用导致调用了python 2.6版本:
    import sys
    for p in sys.path:
        print p

    ../lib/python26.zip
    ../lib/python2.6/
    ../lib/python2.6/plat-linux2
    ../lib/python2.6/lib-tk
    ../lib/python2.6/lib-old
    ../lib/python2.6/lib-dynload

那么谁能告诉我我在这里想念的东西吗?

如果所有其他方法都失败了,我将对Python 2.7源代码进行一些更具侵入性的更改,例如对公共函数进行别名化,并依靠-fno-semantic-interposition标志来确保它们调用正确的非别名函数,即。

Python.h
--------

PyAPI_FUNC(void) MyPy_SetPythonHome(char *);  


MyPython.c
----------

PyAPI_FUNC(void) MyPy_SetPythonHome(char * path)
{
    Py_SetPythonHome(path);
}

...但是这闻起来很不好,我宁愿避免。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)