动态加载Linux共享库?

Mik*_*wan 10 linux shared

我想创建一个共享库,可以通过两种不同的方式加载到目标中:

  1. LD_PRELOAD
  2. 通过动态加载 dlsym

我的共享库看起来像这样:

#include "stdio.h"

void __attribute__ ((constructor)) my_load(void);

void my_load(void) {
  printf("asdf");
}

void someFunc(void) {
  printf("someFunc called");
}
Run Code Online (Sandbox Code Playgroud)

我正在编译它:

all:
    gcc -fPIC -g -c -Wall MyLib.c
    gcc -shared -W1,-soname,MyLib.so.1 -o MyLib.so.1.0.1 -lc
Run Code Online (Sandbox Code Playgroud)

我不希望用它ldconfig等安装它.目标进程如下所示:

#include <stdio.h>
#include <dlfcn.h>

void func1() {
  printf("%d\n", 1);
}

void func2() {
  printf("%d\n", 2);
}

void func3() {
  printf("%d\n", 3);
}

int main() {
  void* lib_handle = dlopen("/home/mike/Desktop/TargetProcess/MyLib.so.1.0.1",
                         RTLD_NOW|RTLD_GLOBAL);

  if(lib_handle == NULL) {
    printf("Failed loading lib\n");
  } else {
    printf("Loaded lib successfully\n");

    void (*some_func)() = dlsym(lib_handle, "someFunc");
    printf("%p\n", some_func);

    dlclose(lib_handle);
  }

  func1();
  func2();
  func3();

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

目标编译如下:

all:
    gcc TestProg.c -ldl -o TestProg
Run Code Online (Sandbox Code Playgroud)

我的问题是:

  1. dlopen如上所述的动态加载,为什么似乎my_load没有被调用?
  2. 使用相同的方法,为什么dlsym总是返回nil即使dlopen返回非null?同样,nm也不列出.so的符号my_loadsomeFunc.
  3. 是否可以使用LD_PRELOAD加载库?我尝试将.so复制到与目标相同的目录中,然后再调用,LD_PRELOAD="./MyLib.so.1.0.1" ./TestProgmy_load似乎没有被调用.

osg*_*sgx 7

您的目标文件没有链接到您的库:

gcc -shared -W1,-soname,MyLib.so.1 -o MyLib.so.1.0.1 -lc
Run Code Online (Sandbox Code Playgroud)

将其更改为包含您的目标文件MyLib.o:

gcc  MyLib.o -shared -W1,-soname,MyLib.so.1 -o MyLib.so.1.0.1 -lc
Run Code Online (Sandbox Code Playgroud)

更新:只在本地尝试您的命令(没有任何MyLib.c或MyLib.o):

$ gcc -shared -W1,-soname,MyLib.so.1 -o MyLib.so.1.0.1 -lc && echo ok
ok
$ nm MyLib.so.1.0.1
xxxxxxxx a _DYNAMIC
xxxxxxxx a _GLOBAL_OFFSET_TABLE_
         w _Jv_RegisterClasses
xxxxxxxx A __bss_start
         w __cxa_finalize@@xxxxxxxxxxx
xxxxxxxx d __dso_handle
         w __gmon_start__
xxxxxxxx t __i686.get_pc_thunk.bx
xxxxxxxx A _edata
xxxxxxxx A _end
xxxxxxxx T _fini
xxxxxxxx T _init
Run Code Online (Sandbox Code Playgroud)

它是一个空的动态库.