C/C++|链接|动态链接库

December 09, 2023
测试
测试
测试
测试
5 分钟阅读

我们经常在游戏目录下看见dll文件,这是windows下的动态链接库。在linux下我们可以使用-shared -fpic生成so文件。

动态链接的好处在于,当我们需要变更函数实现时,不需要重新编译整个可运行文件,只需要修改动态链接库即可,所以破解游戏的时候通常补丁就是一个dll而已。快忘光了,写个随笔复习一下,大一知识简单勿怪。

内存布局

  • GOT(Global offset table) - 动态函数入口,elf中位于.got段,不可执行数据
  • PLT(Procedure linkage table) - 桩函数,elf中位于.got.plt段,可执行代码
  • 动态链接库 - 包含函数和变量,有不可执行数据和可执行代码

原理

下面这个是函数调用原理,如果是变量的话直接获得地址就好。

  • PLT由调用GOT代码+桩代码组成。桩代码用于动态修改GOT表。
  • GOT初始指向桩代码,后来指向动态函数。
  • PLT索引 = 函数索引x+1
  • GOT索引 = 函数索引x+3

初次调用,惰性加载

  • 调用PLT[x+1]
  • 跳转*GOT[x+3](桩代码地址)
  • 传递动态链接函数索引x
  • 跳转PLT[0]
  • 传递动态链接表地址GOT[1]
  • 跳转*GOT[2](动态链接器函数地址)
  • 修改GOT[x+3]为动态函数地址

后续调用,直接跳转

  • 调用PLT[x+1]
  • 跳转*GOT[x+3](动态函数地址)

应用

 #include <dlfcn.h>
 void *dlopen(const char *filename, int flag) ;
			returns: ptr to handle if OK, NULL on error
 void *dlsym(void *handle, char *symbol) ;
			returns: ptr to symbol if OK, NULL on error
 int  dlclose(void *handle) ;
			returns: 0 if OK, -1 on error
 const char dlerror(void) ;
			returns: errormsg if previous call to
 			dlopen, dlysym, or dlclose failed,
 			NULL if previous call was OK

dlopen为mmap+解析符号表

  • RTLD_LAZY/RTLD_NOW决定是否惰性加载
  • RTLD_GLOBAL/RTLD_LOCAL决定符号是否为其他动态链接库可见
  • RTLD_DEEPBIND优先查找动态链接库的符号而非全局符号
  • RTLD_NOLOAD 不加载动态链接库,可用于修改之前的flag
  • RTLD_NODELETE close时不会卸载,因此静态变量在reopen时不会重新初始化

dpsym从符号表中寻址函数、变量

dlclose减少mmap引用计数,为0后munmap

#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
int
main(int argc, char **argv)
{
    void *handle;
    double (*cosine)(double);
    char *error;
   handle = dlopen("libm.so", RTLD_LAZY);
    if (!handle) {
        fprintf(stderr, "%s\n", dlerror());
        exit(EXIT_FAILURE);
    }
   dlerror();
   *(void **) (&cosine) = dlsym(handle, "cos");
   if ((error = dlerror()) != NULL)  {
        fprintf(stderr, "%s\n", error);
        exit(EXIT_FAILURE);
    }
   printf("%f\n", (*cosine)(2.0));
   dlclose(handle);
   exit(EXIT_SUCCESS);
}

引用

  • dlopen(3) - Linux man page
  • http://csapp.cs.cmu.edu/3e/ics3/link/plt2.pdf
  • sjtu,ipads,ics,2-16-dl

继续阅读

更多来自我们博客的帖子

如何安装 BuddyPress
由 测试 December 17, 2023
经过差不多一年的开发,BuddyPress 这个基于 WordPress Mu 的 SNS 插件正式版终于发布了。BuddyPress...
阅读更多
Filter如何工作
由 测试 December 17, 2023
在 web.xml...
阅读更多
如何理解CGAffineTransform
由 测试 December 17, 2023
CGAffineTransform A structure for holding an affine transformation matrix. ...
阅读更多