1

在不修改和重新编译 gnu gcc 和 stdc++ 库构建的情况下,我需要能够使用不同的嵌入式 soname 重现这些库的动态加载版本。

我想我会很聪明,使用可用的静态版本并用这样的东西重新打包它们: ld -E -shared -static "-lstdc++" -lgcc -lgcc_eh -o librepackaged_standard.so

librepacked_standard.so 已创建,没有警告或错误,但 ldd 报告它不是动态库,而 readelf 仅报告以下基本符号:

Symbol table '.symtab' contains 4 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000201000     0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start
     2: 0000000000201000     0 NOTYPE  GLOBAL DEFAULT  ABS _edata
     3: 0000000000201000     0 NOTYPE  GLOBAL DEFAULT  ABS _end

我不确定为什么 ld 没有引入所有静态定义的符号。我也不知道是否需要提供任何其他特殊参数才能使其正常工作。

另一种选择是,如果有一种已知的跨平台方式来简单地更改嵌入在原始精灵库中的 soname。我目前只关心精灵格式的二进制文件。我对编写自己的工具来更改现有二进制文件中的 .soname 不感兴趣。

更新:没有符号被编译的原因是因为ld处理静态二进制文件与 .o 文件不同。默认情况下,它不会从 .a 文件中导入任何符号,除非链接行上的另一个库需要它们。我通过提供 --whole-archive 选项解决了这个问题。

但是,这给了我另一个错误,relocation R_X86_64_32S against_ZSt12_S_first_one' 在制作共享对象时不能使用;使用 -fPIC 重新编译and无法读取符号:错误值` 它们都来自 bitset.o 存档中的 libstdc++.a。所以我不能只将 .a 重新编译成动态库,因为默认情况下,GNU GCC 编译器不会使用 PIC 选项编译用于静态库的目标文件。

这让我不得不找到一个精灵工具或重新编译 GNU GCC 并对其构建进行修改。

正如其中一个答案所述,许可问题可能是这些方法中的任何一个都存在的问题。我最好的答案是我们需要改变我们的要求并找到一个不涉及以任何方式更改或重新打包 GCC 标准库的不同解决方案。

4

2 回答 2

2

没有符号被编译到共享库中的原因是ld静态二进制文件的处理方式与 .o 文件不同。默认情况下,它不会从 .a 文件中导入任何符号,除非链接行上的另一个库需要它们。该特定问题的答案是使用 --whole-archive 选项并直接链接 .a 文件通常有效。

但是,要使其正常工作,静态存档中包含的 .o 文件需要在编译时使用 -fPIC 选项进行编译。但是,用于静态库的目标文件未使用可用静态库中的该选项进行编译。

因此,更改 SONAME 的解决方案是使用 ELF 二进制实用程序或重新构建修改为使用不同 SONAME 的 GNU GCC。

由于在这种情况下存在许可问题,因此任何解决方案都不适用于项目,因为它不是开源的,我们不希望要求为我们所有平台重新分发修改后的 GNU GCC 源版本。

于 2011-10-18T20:31:49.113 回答
1
  1. -static大概解开了-shared
  2. 传统上,您将从静态库中提取目标文件,然后将这些目标文件打包到共享库中 - 依赖于 PIC(位置无关代码)的普遍使用,以便静态库中的对象可以安全地转换为一个共享库。你也许可以不用那个提取步骤,但我对此表示怀疑。
  3. 您可能需要考虑是否符合许可条款和条件。
于 2011-10-18T01:55:41.740 回答