为什么链接器会改变共享库的名称?

3

通过 'node-gyp' 传递的链接器命令行选项,我指定了程序要连接的库路径和库名称。但是生成的可执行文件没有引用我指定的文件,而是在 /usr/lib 中引用了不同的名称。

我使用 binding.gyp 中的库部分来引用本地的 lib 目录。

      'libraries': [
        '-lao-oboe',
        '-L<(module_root_dir)/lib/',
        '-Wl,-rpath-link,<(module_root_dir)/lib/',
        '-Wl,-rpath,<(module_root_dir)/lib/'
      ],
node-gyp似乎已经正确传递了选项,因为如果我将-L路径更改为不包含libao-oboe.so的路径,则链接器会返回错误:/usr/bin/ld: cannot find -la-oboe。 如果我更改请求的库的名称与lib中的库不同,则链接器也会返回错误。
问题在于本地库在运行时不会被加载。 ldd显示node-gyp输出文件未引用指定的文件-它引用了一个完全不同的名称的库-/usr/lib/liboboe-1.0.so.1。请参见ldd输出的第二行:
linux-vdso.so.1 =>  (0x00007ffee20f5000)
liboboe-1.0.so.1 => /usr/lib/liboboe-1.0.so.1 (0x00007fa476377000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fa475ff5000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa475c2b000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fa475a27000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fa47580a000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fa475501000)
/lib64/ld-linux-x86-64.so.2 (0x00007fa476922000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fa4752eb000)

本地库目录包括:
lrwxrwxrwx  1 bruce bruce      15 Sep  8 02:50 libao-oboe.so -> libao-oboe.so.1`  
-rw-r--r--  2 bruce bruce 1640848 Aug 31 15:01 libao-oboe.so.1

本地库文件libao-oboe.so.1和可执行文件中引用的系统库文件(如ldd所示)/usr/lib/liboboe-1.0.so.1是相同的。

链接器是否通过哈希或某些签名来注意到本地文件与标准位置的库文件相同,并进行替换?

为什么node-gyp的输出文件引用了在构建过程中从未请求的库文件?


1
在.so文件中的'soname'字段最终会替换-l选项中指定的文件名。我不完全明白发生了什么,但如果我让文件名与soname匹配,那么就没有问题了。 - bmacnaughton
1个回答

7
根据wikipedia - soname.so文件中的SONAME字段是“基本兼容版本”。从我在上述问题中发现的行为来看,ld将SONAME插入到链接到共享库的文件中-而不是ld命令中指定的文件名。
重命名.so文件不会更改SONAME,因此链接到重命名文件的可执行文件将尝试加载由SONAME字段命名的库,而不是文件名。
我的解决方案是不要重命名文件。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接