Macos dlopen和dylib:主应用程序和dylib地址空间

Macos dlopen和dylib:主应用程序和dylib地址空间,macos,dylib,dlopen,Macos,Dylib,Dlopen,我的主应用程序通过函数ABC静态链接到静态库a,我的动态库xyz.dylib也静态链接到具有相同函数ABC的相同静态库a。函数ABC使用全局定义的变量 现在,当主应用程序在运行时使用dlopen加载xyz.dylib时。初始化器在我调用ABC函数的地方被调用。此函数使用ABC和主应用程序地址空间中的全局变量 在Osx上,内嵌在动态库链接器中的函数将使用第一个使用的函数。例如,如果先在主可执行文件中使用内联函数,然后在加载的动态库中使用,它将使用主可执行文件中的内联函数 这通常很好,除非内联引用了

我的主应用程序通过函数ABC静态链接到静态库a,我的动态库xyz.dylib也静态链接到具有相同函数ABC的相同静态库a。函数ABC使用全局定义的变量


现在,当主应用程序在运行时使用dlopen加载xyz.dylib时。初始化器在我调用ABC函数的地方被调用。此函数使用ABC和主应用程序地址空间中的全局变量

在Osx上,内嵌在动态库链接器中的函数将使用第一个使用的函数。例如,如果先在主可执行文件中使用内联函数,然后在加载的动态库中使用,它将使用主可执行文件中的内联函数

这通常很好,除非内联引用了全局符号,在这种情况下,如果全局符号同时用于动态库和可执行文件,那么现在就使用全局符号

同样,这通常是好的,因为相同的版本使用一致

当有两个内联函数引用可执行文件和动态库中的全局函数时,就会出现问题,一个函数首先在可执行文件中使用,另一个函数首先在动态库中使用。那么你有一对不匹配的。例如:

class MagicAlloc
{
    void* Alloc()         { return gAlloc.get(); } 
    void  Free( void* v ) { gAlloc.free( v ); } 

    static RealAllocator gAlloc;
};
假设您在可执行文件中调用MagicAlloc::Alloc,然后在动态库中调用它,现在对于这两种语言中的所有分配,您将在可执行文件中使用gAlloc。然后,对MagicAlloc::Free的第一个调用发生在动态库中。然后,您将尝试从动态库中释放在全局二进制文件中分配的内容

有两种解决方案:

  • 不要使用内联线引用全局/静态。将全局结构和函数定义移动到同一转换单元(对象文件)中。将全局标记为“静态”,以便它们在TLU外部不可见。现在,您的函数将在链接步骤中静态解析,并绑定到正确的全局函数

  • 隐藏可执行文件中除插件api之外的所有符号。正常链接,但链接二进制文件时,将以下内容传递给链接器:

    -Wl,-导出符号列表,导出文件


  • 其中“导出文件”是应导出的链接符号列表。例如,您需要在该文件中至少包含“_main”。现在,当动态库运行时,它将无法动态链接到错误的内联线,因为它们不在动态符号表中。第二种解决方案也更安全,因为恶意插件无法轻松访问全局文件。

    我也有同样的问题。我希望我能找到一种让动态库独立的方法。这也是一个安全问题,因为这意味着有人可以创建一个动态库,您可以使用dlopen打开它,然后在主程序中使用随机golbal数据结构。