2010-10-05 72 views
3
$ chmod +x libsomelibrary.so 
$ ./libsomelibrary.so 
Segmentation fault 

$ gcc -O2 http://vi-server.org/vi/bin/rundll.c -ldl -o rundll 
$ ./rundll ./libsomelibrary.so main 
(application starts normally) 

为什么我不能只启动libsomelibrary.so,如果它有可用的入口点?为什么我无法在Linux中直接启动共享库?

rundll.c很简单:

void* d = dlopen(argv[1], RTLD_LAZY); 
void* m = dlsym(d, argv[2]); 
return ((int(*)(int,char**,char**))m)(argc-2, argv+2, envp); 

为什么不能在内部使用尝试加载一个二进制文件时?

+0

此功能非常有用:作为一个库是NS插件,但是如果它是“主”开始的,它只是桌面GUI应用程序,它更易于调试。并且不需要有多个项目,静态库和依赖关系。 – 2010-10-05 01:11:43

回答

4

main不是内核或动态链接程序所识别的入口点 - 它在编译时被链接到可执行文件中的启动代码调用(默认情况下此类启动代码未链接到共享库中)。

ELF标题包含起始地址。

3

共享库不能直接运行。它们被设计为链接到另一个代码库。它可能有一个可用的入口点,但可执行需要的不仅仅是具有可用的入口点。 rundll实用程序就是这方面的证明。你的第二个测试表明共享库的确是可执行的,但只有在rundll做了一些工作。如果您对图书馆代码执行之前需要完成的工作感到好奇,请查看rundll的源代码。

+0

“rundll”是我刚写的一个程序。但这是一件微不足道的事情。系统很容易做到这一点(如果我们正在尝试执行该库,请将其删除,dlsym“main”并执行它)。 – 2010-10-05 01:09:20

+0

为什么“可执行”不仅仅意味着“仅仅具有可用的入口点”?请提供一些额外的解释。 – wj32 2010-10-05 01:15:13

+0

这是微不足道的。我见过一些应用程序,其主要可执行文件是一个像这样的小包装器,用于''dlopen''主库并跳转到一个预定义的函数。系统不会自动执行此操作,因为在一般情况下,它不知道入口点在哪里(或者在多个入口点的情况下使用哪个入口点),或者需要先进行什么样的设置跳到那个入口点。 – bta 2010-10-05 01:17:47

3

可以在Linux中启动共享库。

例如,如果你开始/lib/libc.so.6,它会打印出它的版本号:

$ /lib/libc.so.6 
GNU C Library stable release version 2.12, by Roland McGrath et al. 
Copyright (C) 2010 Free Software Foundation, Inc. 
This is free software; see the source for copying conditions. 
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A 
PARTICULAR PURPOSE. 
Compiled by GNU CC version 4.5.0 20100520 (prerelease). 
Compiled on a Linux 2.6.34 system on 2010-05-29. 
Available extensions: 
     crypt add-on version 2.1 by Michael Glad and others 
     GNU Libidn by Simon Josefsson 
     Native POSIX Threads Library by Ulrich Drepper et al 
     BIND-8.2.3-T5B 
libc ABIs: UNIQUE IFUNC 
For bug reporting instructions, please see: 
<http://www.gnu.org/software/libc/bugs.html>. 

一定有什么东西从资料库中失踪。