根据this expert,
动态加载是指在启动后将可执行文件或库映射(或不经常复制)到进程的内存中。 动态链接是指在编译之后解析符号 - 将其名称与地址或偏移相关联。
因此,相应地:静态加载是指在可执行文件或库中启动之前将其映射到内存中,静态链接是指在编译时解析符号。
现在,当您执行库的静态加载和静态链接时,库的二进制代码将附加到您的二进制代码和(函数)和变量)引用您的二进制代码对库进行修补(不确定这是否是正确的术语),以便它们指向正确的位置。
这意味着在静态链接对函数的调用之前
foo()
会给你(在x86 ASM中)以及其他类似的指令:
call 0x00000000
并且在静态链接之后你有类似的东西:
call 0x00001043
其中0x00001043是链接器输出的二进制代码中函数foo的入口点。
现在,当您执行动态加载和动态链接时,您将通过函数指针调用库函数: typedef int(* fun_ptr)(void);
library = dlopen("mylib.so");
fun_ptr foo = dlsym(library, "foo");
foo();
这种机制也是C ++虚拟方法的工作原理。要调用的方法的地址在运行时通过创建一个指向实例的方法部分的函数指针来解析(存储在所谓的vtable中)。
我的问题是:
当您执行共享库的静态加载和动态链接时(对于上下文,让我们在Linux中说一个.so),这个链接补丁吗我的二进制文件引用,如静态加载&链接场景,或通过函数指针工作,如动态加载&链接和C ++虚拟方法?
答案 0 :(得分:1)
进行静态加载和共享库的动态链接时
你不做静态加载'共享库。
即使它将您视为最终用户,例如libc.so.6
已被静态加载'在流程启动时,事实并非如此。相反,内核的静态负载'主二进制文件ld-linux.so
,然后ld-linux
dynamic 加载所有其他共享库。
这个链接修补我的二进制文件的引用,如静态加载&链接场景,或者它是否通过函数指针工作,如动态加载
取决于。
通常共享库是从与位置无关的代码(PIC
)链接的,并且以函数指针的方式工作(指针存储在GOT
- 全局偏移表中)。
但有时共享库与非PIC
代码链接,并且需要"文本重定位",其工作方式类似于"静态链接"。
答案 1 :(得分:0)
我已经能够使用libbfd(位于GNU binutils' ld链接器下面的库)生成运行时静态链接的示例:https://github.com/bloff/runtime-static-linking-with-libbfd