你如何重新打包gnu gcc标准库stdc ++,gcc和gcc_eh?

时间:2011-10-17 19:46:31

标签: gcc gnu ld std libstdc++

如果不修改和重新编译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没有引入静态定义的所有符号。我也不知道是否有任何其他特殊参数我需要为此工作。

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

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

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

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

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

2 个答案:

答案 0 :(得分:2)

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

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

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

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

答案 1 :(得分:1)

  1. -static可能会解除-shared
  2. 经典地,您从静态库中提取目标文件,然后将这些目标文件打包到共享库中 - 依赖于PIC(位置无关代码)的通用使用,以便静态库中的对象可以安全地转换为共享库。你可能没有那个提取步骤,但我对此表示怀疑。
  3. 您可能想要考虑一下您是否符合许可条款和条件。