59 c linux macos linker dynamic-linking
我所做的
在为Linux编写共享库时,我倾向于关注重定位,符号可见性,GOT/PLT等.
适用时,我试图避免在同一个库中的函数相互调用时调用PLT存根.例如,让我们说一个共享对象提供了两个公共函数- foo()和bar()(或者那些能够通过用户调用).bar()但是,该功能也会调用foo().所以我在这种情况下做的是:
_foo()和_bar()具有私有可见功能.foo()和bar()弱别名._foo()_bar()这样,共享对象中的代码永远不会使用弱符号.它只直接调用本地函数.例如,在_bar()调用时,它会_foo()直接调用.
但是用户并不知道_*函数,并且总是使用相应的弱别名.
我是怎么做的
在Linux中,这是通过使用以下构造实现的:
extern __typeof (_NAME) NAME __attribute__(weak, alias("_NAME"));
Run Code Online (Sandbox Code Playgroud)
问题
不幸的是,这对OS X不起作用.我对OS X或其二进制格式没有深入的了解,所以我喋喋不休地发现了一些弱函数的例子(比如这个),但是那些并不完全与你可以有一个弱符号相同,但不是一个弱符号,它是DSO本地函数的别名.
可能解决方案
目前,我刚刚禁用了此功能(使用宏实现),因此所有符号都是全局符号并具有默认可见性.我现在想到实现同样目的的唯一方法是让所有_foo函数具有私有可见性,并具有foo默认可见性的相应函数并调用它们的"隐藏"对应物.
更好的方法?
但是,这需要更改大量代码.因此,我宁愿不去那里,除非真的没有别的办法.
那么什么是关闭OS X替代或获得相同语义/行为的最简单方法?
在 OS X 上,库内进行的调用将自动直接调用,不会通过 dyld 存根。事实的证据是,如果您希望能够注入替代函数来为调用提供服务,则需要使用 interposable 来强制间接访问符号并通过 dyld 存根强制执行调用。否则,默认情况下,本地调用将是直接的,不会产生通过 dyld 运行的开销。
因此,您在 Linux 上的优化已经是默认行为,不需要别名。
不过,如果您这样做只是为了使平台兼容的代码更简单,您仍然可以创建别名。您只需使用“weak_import”或“weak”(如果您想要合并)作为属性名称。
extern typeof (_NAME) NAME __attribute (weak_import, alias("_NAME"));
Apple 关于弱链接的参考:标记弱链接的符号
Apple 关于 Mach-O 运行时绑定的参考:符号定义的范围和处理