【问题标题】:Linker fails in sandbox when running through Bazel but works when sandboxed command is executed from the command line链接器在通过 Bazel 运行时在沙盒中失败,但在从命令行执行沙盒命令时工作
【发布时间】:2018-09-18 12:23:33
【问题描述】:

我正在尝试让我们的跨工具链(标准 Yocto 工具链)与 Bazel 一起使用。我按照https://github.com/bazelbuild/bazel/wiki/Building-with-a-custom-toolchain 上的说明进行操作,但每次我尝试构建一个简单的测试程序时,链接器都会失败。它说

external/toolchain_e6500/sysroots/x86_64-fslsdk-linux/usr/bin/powerpc64-fsl-linux/../../libexec/powerpc64-fsl-linux/gcc/powerpc64-fsl-linux/4.9.2/real-ld: cannot find /lib64/libc.so.6
external/toolchain_e6500/sysroots/x86_64-fslsdk-linux/usr/bin/powerpc64-fsl-linux/../../libexec/powerpc64-fsl-linux/gcc/powerpc64-fsl-linux/4.9.2/real-ld: cannot find /usr/lib64/libc_nonshared.a
external/toolchain_e6500/sysroots/x86_64-fslsdk-linux/usr/bin/powerpc64-fsl-linux/../../libexec/powerpc64-fsl-linux/gcc/powerpc64-fsl-linux/4.9.2/real-ld: cannot find /lib64/ld64.so.1

sysroot 设置正确。在沙箱外运行链接器命令时(例如使用--spawn_strategy=standalone 或手动),它始终有效。奇怪的是,当我使用--debug_sandbox 并从命令行运行发出的命令时,它也可以工作。

我已经调试这个问题两天了,包括straceing Bazel 守护程序和比较real-ld 输入,但我没有发现任何可疑之处。

执行环境之间肯定存在差异,但我现在没有想法。这是--debug_sandbox 打印的失败命令:

(cd /home/sick/.cache/bazel/_bazel_sick/2a7ae5e27644389520091aa03d045c73/execroot/__main__ && \
  exec env - \
    PATH=/home/sick/bin:/home/sick/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/sick/bin \
    PWD=/proc/self/cwd \
    TMPDIR=/tmp \
  /home/sick/.cache/bazel/_bazel_sick/2a7ae5e27644389520091aa03d045c73/execroot/__main__/_bin/linux-sandbox -t 15 -w /home/sick/.cache/bazel/_bazel_sick/2a7ae5e27644389520091aa03d045c73/sandbox/linux-sandbox/2/execroot/__main__ -w /tmp -w /dev/shm -D -- tools/compiler_e6500/e6500_gcc/powerpc64-fsl-linux-gcc -o bazel-out/e6500-fastbuild/bin/test '--sysroot=external/toolchain_e6500/sysroots/ppc64e6500-fsl-linux' -no-canonical-prefixes -pie -Wl,-z,relro,-z,now -Wl,-S -Wl,@bazel-out/e6500-fastbuild/bin/test-2.params)

您可以在这里查看工作区https://github.com/jasal82/bazel-cross-eval

如果需要,我可以提供工具链。


2018 年 9 月 25 日更新

在阅读了下面有关链接描述文件的答案后,我做了更多调查。 this manual 中的第 4.4.2 节说

如果配置了 sysroot 前缀,并且文件名以 / 字符,并且正在处理的脚本位于 sysroot 前缀,文件名将在 sysroot 前缀中查找。 否则,链接器会尝试在当前打开文件 目录。

显然,ld 不认为脚本位于 sysroot 前缀内,因此按字面意思使用(即相对于当前目录解析,可能是沙盒根目录)。这将解释观察到的行为。但是,我仍然不明白为什么当我手动运行命令时它不会发生,即不是通过 Bazel 守护进程。

这可能与 CROSSTOOL 文件中使用的相对 sysroot 路径有关吗?据我了解,由于沙盒,您无法指定 sysroot 的绝对路径。在 Bazel 中处理此问题的推荐方法是什么?我想避免修补工具链。

【问题讨论】:

    标签: gcc cross-compiling bazel toolchain


    【解决方案1】:

    查看系统根目录中的lib.so。它可能看起来像这样:

    /* GNU ld script
       Use the shared library, but some functions are only in
       the static library, so try that secondarily.  */
    OUTPUT_FORMAT(elf64-x86-64)
    GROUP ( /lib/x86_64-linux-gnu/libc.so.6 /usr/lib/x86_64-linux-gnu/libc_nonshared.a  AS_NEEDED ( /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 )
    

    将其中的路径更改为相对于libc.so 所在的目录。您必须对libm.solibpthread.so 执行类似的操作。

    GNU 链接器在评估脚本是否在 sysroot 中之前解析符号链接。当前的 Bazel Linux 沙盒实现为所有操作的输入创建了一个符号链接农场。因此,libc.so.6 链接描述文件被检测为位于沙盒外的 sysroot 中,但不在沙盒内。

    【讨论】:

    • 你是对的,在使这些路径相对后,链接器成功。但是这些路径不应该由 ld 相对于配置的 sysroot 解析吗?在沙盒环境之外,这可以正常工作,因此似乎考虑了 sysroot。
    • 查看我的编辑。不同之处在于沙盒中的所有内容都是符号链接。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-22
    • 1970-01-01
    • 2020-08-21
    • 1970-01-01
    • 2017-01-25
    相关资源
    最近更新 更多