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

时间:2013-10-03 15:07:18

标签: macos dylib dlopen

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

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

1 个答案:

答案 0 :(得分:0)

在Osx上,内联dylib链接器的函数将使用第一个使用的函数。因此,例如,如果首先在主可执行文件中使用内联函数,然后在加载的dylib中使用它,它将使用主可执行文件中的那个。

这通常没问题,除非你的内联引用了一个全局符号,在这种情况下你现在正在使用一个如果你的全局符号用于dylib和你的可执行文件。

这通常很好,因为一致地使用相同的版本。

如果有2个内联函数引用可执行文件和dylib中的全局函数,并且在可执行文件中首先使用了一个函数,而在dylib中首先使用了另一个函数,则会出现问题。然后你有一个不匹配的对。例如:

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

    static RealAllocator gAlloc;
};

假设您在可执行文件中调用MagicAlloc :: Alloc,然后在dylib中调用它,现在对于所有分配,您将在可执行文件中使用gAlloc。然后第一次调用MagicAlloc :: Free发生在dylib中。然后,您将尝试从dylib中释放全局变量中二进制文件中分配的内容。

有两种解决方案:

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

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

    -Wl,-exported_symbols_list,export_file

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