我正在编写一个使用共享库作为插件的Linux C ++应用程序。 (我将在这里使用术语DLL,因为.SO太笨拙了)共享库系统似乎在错误细节方面很弱。每当出现任何问题时,错误都是:没有这样的文件或目录,即使在每种情况下DLL文件都存在并且strace显示我的应用程序打开文件。
Pcap.so is my code and it itself loads various other system DLL files.
open("./tls/x86_64/Pcap.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("./tls/Pcap.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("./x86_64/Pcap.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("./Pcap.so", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\200C\1\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0775, st_size=752011, ...}) = 0
getcwd("/home/woody/projects/wiregrep", 128) = 30
mmap(NULL, 2264832, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fdb8cc88000
mprotect(0x7fdb8ccb0000, 2093056, PROT_NONE) = 0
mmap(0x7fdb8ceaf000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x27000) = 0x7fdb8ceaf000
close(3) = 0
open("./tls/x86_64/libtins.so.1", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("./tls/libtins.so.1", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("./x86_64/libtins.so.1", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("./libtins.so.1", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=95890, ...}) = 0
mmap(NULL, 95890, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fdb8e128000
close(3) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/usr/lib/x86_64-linux-gnu/libtins.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\360~\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0644, st_size=465904, ...}) = 0
mmap(NULL, 2561000, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fdb8ca10000
mprotect(0x7fdb8ca7f000, 2093056, PROT_NONE) = 0
mmap(0x7fdb8cc7e000, 16384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x6e000) = 0x7fdb8cc7e000
close(3) = 0
open("./tls/x86_64/libcrypto.so.1.0.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("./tls/libcrypto.so.1.0.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("./x86_64/libcrypto.so.1.0.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("./libcrypto.so.1.0.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libcrypto.so.1.0.0", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\356\5\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0644, st_size=1930528, ...}) = 0
mmap(NULL, 4040856, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fdb8c630000
mprotect(0x7fdb8c7e2000, 2093056, PROT_NONE) = 0
mmap(0x7fdb8c9e1000, 155648, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b1000) = 0x7fdb8c9e1000
mmap(0x7fdb8ca07000, 14488, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fdb8ca07000
close(3) = 0
open("./tls/x86_64/libpcap.so.0.8", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("./tls/libpcap.so.0.8", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("./x86_64/libpcap.so.0.8", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("./libpcap.so.0.8", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/usr/lib/x86_64-linux-gnu/libpcap.so.0.8", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0 L\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0644, st_size=249096, ...}) = 0
mmap(NULL, 2347480, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fdb8c3f0000
mprotect(0x7fdb8c42b000, 2093056, PROT_NONE) = 0
mmap(0x7fdb8c62a000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x3a000) = 0x7fdb8c62a000
mmap(0x7fdb8c62d000, 472, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fdb8c62d000
close(3) = 0
mprotect(0x7fdb8c62a000, 8192, PROT_READ) = 0
mprotect(0x7fdb8c9e1000, 110592, PROT_READ) = 0
mprotect(0x7fdb8cc7e000, 12288, PROT_READ) = 0
munmap(0x7fdb8e128000, 95890) = 0
munmap(0x7fdb8cc88000, 2264832) = 0
munmap(0x7fdb8ca10000, 2561000) = 0
munmap(0x7fdb8c630000, 4040856) = 0
munmap(0x7fdb8c3f0000, 2347480) = 0
munmap(0x7fdb8ceb8000, 2661832) = 0
write(1, "ERROR:Unable to load shared libr"..., 100ERROR:Unable to load shared library(2): Pcap.so No such file or directory at:Plugin.h_26
) = 100
exit_group(-1) = ?
这表明它正在加载其依赖的DLL,并且在将静态库编译为可执行文件时它确实有效。为什么它最终失败对我来说是不透明的。没有任何迹象表明它为什么会因为内存不足而被淘汰。
我已经解决了导致这种情况的几种类型的错误,它们都是不同的(未解析的外部,在加载插件的主框架代码中没有--export-dynamic等)。我得到的地方是我首先在静态链接中使用DLL代码创建一个简单的应用程序,主要语句只是为了能够在DLL和代码之前查看错误细节。这个Pcap.so可以正常运行,但不会像DLL一样加载。
我这样编译:
VirtualBox-3:~/projects/wiregrep$ make Pcap.so
g++-4.7 -std=c++11 -D__STDC_FORMAT_MACROS -Wno-deprecated -g -I. -fPIC -Wl,--export-dynamic -Wall -c -o Pcap.o Pcap.cc
g++-4.7 -Wl,--export-dynamic -shared -o Pcap.so Pcap.o mylibs/libmm.a -ltins
加载实际DLL的代码如下所示:
void Load(const char* classname)
{
if (classname)
(SharedLibraryFilename = classname) += ".so";
SharedLibraryHandle = ::dlopen(SharedLibraryFilename, RTLD_LAZY|RTLD_GLOBAL);
if (SharedLibraryHandle == NULL) // does strerror implicitly in resultin g message
throw Exception(LOCATION, "Unable to load shared library(%d): %s", errno, SharedLibraryFilename.c_str());
}
我并不关心这种特殊情况,但有更好的方法来调试Linux用来加载DLL的不透明进程。
我有几个其他类似的DLL加载得很好,但我不得不在盲人中调试解决每个问题以使它们工作。