如何编译ELF二进制文件以便它可以作为动态库加载?

Ale*_*kiy 7 c linux elf dlopen dynamic-library

这是一个理论问题.我知道也许最好的做法是使用共享库.但我遇到了这个问题,似乎无法在任何地方找到答案.

如何构建代码并用ELF格式编译一个C/C++程序,以便可以加载dlopen()

例如,如果一个可执行文件包含某个函数的实现,int test()并且我想从我的程序中调用此函数(并且最好得到函数的结果),如果可能的话,我该怎么做呢?

在伪代码中,我可以将其描述如下:

ELF可执行文件来源:

void main() {
    int i = test();
    printf("Returned: %d", i);//Prints "Returned: 5"
}

int test() {
    return 5;
}
Run Code Online (Sandbox Code Playgroud)

外部计划:

// ... Somehow load executable from above
void main() {
    int i = test();
    printf("Returned: %d", i);//Must print "Returned: 5"
}
Run Code Online (Sandbox Code Playgroud)

Ale*_*kiy 1

根据评论和其他答案中提供的链接,这里介绍了如何在不链接这些程序编译时的情况下完成此操作:

测试1.c

#include <stdio.h>

int a(int b)
{
  return b+1;
}

int c(int d)
{
  return a(d)+1;
}

int main()
{
  int b = a(3);
  printf("Calling a(3) gave %d \n", b);
  int d = c(3);
  printf("Calling c(3) gave %d \n", d);
}
Run Code Online (Sandbox Code Playgroud)

测试2.c

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


int (*a_ptr)(int b);
int (*c_ptr)(int d);

int main()
{
  void* lib=dlopen("./test1",RTLD_LAZY);
  a_ptr=dlsym(lib,"a");
  c_ptr=dlsym(lib,"c");
  int d = c_ptr(6);
  int b = a_ptr(5);
  printf("b is %d d is %d\n",b,d);
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译

$ gcc -fPIC  -pie -o test1 test1.c -Wl,-E
$ gcc -o test2 test2.c -ldl
Run Code Online (Sandbox Code Playgroud)

执行结果

$ ./test1
Calling a(3) gave 4 
Calling c(3) gave 5
$ ./test2 
b is 6 d is 8
Run Code Online (Sandbox Code Playgroud)

参考

PS:为了避免符号冲突,导入的符号和它们分配的指针最好具有不同的名称。请参阅此处的评论。