【问题标题】:GCC built from source in different location is incorrectly using same shared libs as native GCC从不同位置的源代码构建的 GCC 错误地使用与本机 GCC 相同的共享库
【发布时间】:2018-04-14 00:54:07
【问题描述】:

我是一名学生,从事涉及扩展 gcc 的 TM 功能的研究。我的目标是更改 gcc 源代码,从修改后的源代码构建 gcc,并以与使用发行版的 vanilla gcc 相同的方式使用新的可执行文件。

我在不同的位置构建并安装了 gcc(不是/usr/bin/gcc),特别是因为修改后的 gcc 会不稳定,而且因为我们的项目目标是比较使用两种不同编译的事务程序版本。

我们对 gcc 源代码的更改会影响 /gcc/libitm。这意味着我们正在对 libitm.so 进行更改,这是已构建的共享库之一。

我的期望:

  • 在编译 myprogram.cpp/usr/bin/g++ 时,将被链接的 libitm.so 版本应该是我的发行版附带的版本;
  • 当使用~/project/install-dir/bin/g++ 编译它时,将被链接的 libitm.so 版本应该是我构建修改后的 gcc 时刚刚构建的版本。

但实际上似乎本地 gcc 和我的都使用相同的 libitm/usr/lib/x86_64-linux-gnu/libitm.so.1

我对 gcc 的内部结构只有粗略的了解,因为它们适用于我们的项目,但这是我的理解:

  • 我们的更改告诉编译器通过有条件地插入我们自己的“内置函数”而不是它通常使用的函数,并且这是 / 成为需要链接到 libitm 的“符号”。
  • 当我使用新的 gcc 编译我的程序时,通过检测这些条件并成功插入符号,但是在运行时我的程序给出了一个“重定位错误”,表明符号未在它正在搜索的文件中定义:./test: relocation error: ./test: symbol _ITM_S1RU4, version LIBITM_1.0 not defined in file libitm.so.1 with link time reference
  • readelf 告诉我/usr/lib/x86_64-linux-gnu/libitm.so.1 不包含我们的新符号,而~/project/install-dir/lib64/libitm.so.1 包含;如果我在简单地将后者 libitm 复制到前者之后重新运行我的程序(当然,首先备份它),它不会再产生重定位错误。但这自然不是永久的解决方案。

所以我希望我构建的 gcc 在链接时使用与它一起构建的共享库。而且我不想每次都告诉它它们在哪里 - 我的感觉是它应该知道在哪里寻找它们,因为我故意在其他地方构建它以表现不同。

这听起来像是任何业余 gcc 开发人员在尝试创建开发环境并且仍然能够使用两个版本的 gcc 时都会遇到的问题,但我很难找到类似的问题。我认为这是在构建之前配置 gcc 时缺少某些配置选项的问题。执行此操作的正确配置是什么?

我对@9​​87654321@ 的小小的了解导致我做了以下事情:

cd ~/project/
mkdir objdir
cd objdir
../source-dir/configure --enable-languages=c,c++ --prefix=/home/myusername/project/install-dir
make -j2
make install

我只有那些配置选项,因为它们似乎与“仅构建我需要的部分”和“不覆盖本机 gcc”最相关,但我可能错了。在初始配置步骤之后,我每次更改代码时都重新运行make -j2make install。所有这些步骤都没有错误地完成,它们会生成~/project/install-dir/bin/ 文件夹,其中包含gccg++,它们的行为与描述的一样。

我使用~/project/install-dir/bin/g++ -fgnu-tm -o myprogram myprogram.cpp 编译事务程序,可能还有其他选项用于线程程序。

(我在 Windows 上的 VirtualBox 中使用 Xubuntu 16.04.3(64 位)。安装的 /usr/bin/gcc 是 5.4.0 版。我们在 ~/project/source-dir/ 的源是 5.3.0 的修改版本。)

【问题讨论】:

  • 你是如何告诉链接器使用~/project/install-dir/lib64/libitm.so.1的?
  • @muru 我没有明确告诉链接器任何事情, 我的问题/问题的一部分是它 not 使用该文件(我希望它自动这样做)。我按照描述构建了 gcc,并用它来编译描述的测试程序。然后当重定位错误告诉我找不到符号时,我基本上使用find / -name "libitm*" 来找出任何libitm.so 文件在哪里(/usr/lib 中的那些是发行版附带的;~/project/install-dir/ 中的那些是来自我的构建)。
  • 链接器不会自动拾取库。您必须使用-L 选项或LD_LIBRARY_PATH,或为ldconfig 添加配置,在链接器使用它之前通知它该目录。
  • @muru 不是我刚刚构建的 gcc 的链接器部分吗?您是说它不会自动搜索靠近安装位置的某些相对路径,它只是使用该环境变量或-L 选项或ldconfig?我会对此进行更多研究。
  • 抱歉,我把链接器和加载器混为一谈了。编译时,链接器必须通过-L 标志告诉 gcc 的位置。运行时错误将来自加载程序,必须在运行时使用ldconfigLD_LIBRARY_PATH 环境变量告知库位置,除非您静态链接该特定库。

标签: gcc shared-libraries


【解决方案1】:

您遇到了构建与运行时链接的差异。当您使用-fgnu-tm 构建时,编译器知道在哪里找到它需要的库,并告诉链接器在哪里找到它;您可以通过将-v 添加到您的g++ 命令来查看这一点。但是,当您运行生成的程序时,动态链接器不知道它应该在某个特殊的地方看起来适合 ITM 库,因此它使用 /usr/lib/x86_64-linux-gnu 中的默认库。

在 Ubuntu 上使用 ITM 变得更加混乱,因为该库安装在系统范围内,但链接脚本安装在 GCC 私有目录中。默认的 GCC 构建不会发生这种情况,因此您自己的 GCC 构建不会这样做,您会在 ~/project/install-dir/lib64 中看到 libitm.so

要在运行时解决此问题,您需要告诉动态链接器在哪里可以找到正确的库。您可以通过设置LD_LIBRARY_PATH(到/home/.../project/install-dir/lib64)来实现这一点,或者在构建时使用-Wl,-rpath=/home/.../project/install-dir/lib64 将路径存储在二进制文件中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-05
    • 1970-01-01
    • 2011-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多