链接器的输出为可执行文件。可以在链接器上做事情,加载器是运行前置,加载器也可以做很多事情。
动态链接,在加载器加载可执行文件时,先加载和运行动态链接器,然后动态链接器动态链接共享库。用于解决静态库的缺点,即全量加载库,浪费内存。依赖库更新后,需要重新编译打包发版,非常麻烦。
Linux操作系统提供dlopen,dlsym,dlclose,dlerror系统函数,用于动态链接。动态链接器调用了dlopen从磁盘加载共享库,调用dlsym,从共享库找到引用的符号并返回符号指针,即全局变量和全局函数。
JNI,java本地接口,就是动态链接共享库。
库打桩的基本思想是:允许你截获共享库函数的调用,取而代之执行自己的代码。基本做法是给定一个目标函数,创建一个包装函数,原型与目标函数完全一致。
编译器链接器提供了用户代码的打桩机制。
打桩机制有三种:
1,编译时打桩;需要能够访问包装函数的源代码;
2,链接时打桩;需要能够访问可重定位目标文件。linux静态链接器支持用--wrap f标志进行链接时打桩。
3,运行时打桩;只需要能够访问可执行目标文件。
运行时打桩机制是:基于动态链接器的LD_PRELOAD环境变量,如果LD_PRELOAD环境变量被设置为一个共享库路径名的以分号或空格分割的列表时,当你加载和执行一个程序,需要解析未定义的引用时,动态链接器(LD-LINUX.SO)会先搜索LD_PRELOAD库,然后再搜索其他库。
java运行时,指定javaagent的路径,其实就是利用了运行时库打桩机制。