我的主应用程序静态链接到带有函数ABC的静态库A,我的动态库xyz.dylib也静态链接到具有相同函数ABC的相同静态库A.函数ABC使用全局定义的变量。
现在主应用程序在运行时使用dlopen加载xyz.dylib。调用初始化程序,我调用了ABC函数。此函数ABC使用来自主应用程序地址空间的全局变量。
答案 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中释放全局变量中二进制文件中分配的内容。
有两种解决方案:
不要使用内联来引用全局/静态。将全局结构和函数定义移动到同一个转换单元(目标文件)中。将全局变量标记为“静态”,以便它们在TLU外部甚至不可见。现在,您的功能将在链接步骤中静态解析,并绑定到正确的全局。
隐藏可执行文件中除插件api之外的所有符号。正常链接,但链接二进制文件本身时会将以下内容传递给链接器:
-Wl,-exported_symbols_list,export_file
其中,导出文件是应导出的链接符号列表。例如。你需要在该文件中至少有“_main”。现在,当你的dylib运行时,它将无法动态链接到错误的内联,因为它们不会在动态符号表中。第二种解决方案也更安全,因为恶意插件无法轻易访问全局变量。