首页 > 解决方案 > 如何在 gem5 中运行动态链接的可执行系统调用仿真模式 se.py?

问题描述

系统调用仿真 SE 模式下运行 gem5 时如何解决“致命:内核太旧”?我设法在某些条件下运行了一个静态链接的 hello world。

但是,如果我尝试针对 stdlib 运行一个 ARM 动态链接:

./out/common/gem5/build/ARM/gem5.opt ./gem5/gem5/configs/example/se.py -c ./a.out

它失败了:

fatal: Unable to open dynamic executable's interpreter.

如何让它找到解释器?希望不要在主机的根目录上复制我的交叉工具链的解释器。

对于 x86_64,如果我使用本机编译器,它可以工作,并且正如预期的strace那样,它正在使用本机解释器,但如果我使用交叉编译器,它就不起作用。

当前的常见问题解答说不可能使用动态可执行文件:http: //gem5.org/Frequently_Asked_Questions但我不相信它,然后这些演示文稿提到了它:

但不是如何实际使用它。

QEMU 用户模式有这个-L选项。

在 gem5 49f96e7b77925837aa5bc84d4c3453ab5f07408e 中测试

https://www.mail-archive.com/gem5-users@gem5.org/msg15582.html

标签: gem5

解决方案


2019 年 11 月增加了对动态链接的支持

在:https ://gem5-review.googlesource.com/c/public/gem5/+/23066

那时它肯定可以工作,但后来它在某个时候坏了,需要修复.....

如果您有要使用的根文件系统,例如由 Buildroot 生成的文件系统,您可以执行以下操作:

./build/ARM/gem5.opt configs/example/se.py \
  --redirects /lib=/path/to/build/target/lib \
  --redirects /lib64=/path/to/build/target/lib64 \
  --redirects /usr/lib=/path/to/build/target/usr/lib \
  --redirects /usr/lib64=/path/to/build/target/usr/lib64 \
  --interp-dir /path/to/build/target \
  --cmd /path/to/build/target/bin/hello

或者,如果您使用的是 Ubuntu 交叉编译器工具链,例如在 Ubuntu 18.04 中:

sudo apt install gcc-aarch64-linux-gnu
aarch64-linux-gnu-gcc -o hello.out hello.c
./build/ARM/gem5.opt configs/example/se.py \
  --interp-dir /usr/aarch64-linux-gnu \
  --redirects /lib=/usr/aarch64-linux-gnu/lib \
  --cmd hello.out

您还必须单独添加任何可能包含动态库的路径--redirect。这些对于 C 可执行文件来说已经足够了。

--interp-dir根据表示加载程序路径的 ELF 元数据设置将在其中搜索动态加载程序的根目录。例如, buildroot ELF 文件将该路径设置为/lib/ld-linux-aarch64.so.1,并且加载程序是存在于/path/to/build/target/lib/ld-linux-aarch64.so.1. 正如布兰登所提到的,这条路径可以通过以下方式找到:

 readelf -a $bin_name | grep interp

系统调用仿真动态链接的主要困难是我们想要以某种方式:

  • 链接器文件访问到一个魔法目录以在那里找到库
  • 从主应用程序访问其他文件以转到正常路径,例如读取当前工作目录中的输入文件

并且很难检测我们是否在加载程序中,特别是因为这可能发生dlopen在程序中间。

--redirects选项是一个简单的解决方案。

例如/lib=/path/to/build/target/lib,如果来宾将访问 C 标准库/lib/libc.so.6,则 gem5 会看到它在里面/lib,并将路径重定向到/path/to/build/target/lib/libc.so.6

轻微的缺点是无法实际访问/lib主机目录中的文件,但这并不常见,因此在大多数情况下都可以使用。

如果你错过了 any --redirect,动态链接器可能会抱怨找不到库并带有以下类型的消息:

hello.out: error while loading shared libraries: libstdc++.so.6: cannot open shared object file: No such file or directory

如果发生这种情况,您必须在目标文件系统/工具链中找到该libstdc++.so.6库并添加缺少的--redirect.

它后来在https://gem5.atlassian.net/browse/GEM5-430上中断,但又被修复了。

动态链接的缺点

一旦我得到动态链接来工作,我注意到它实际上有以下缺点,根据应用程序的不同,这些缺点可能会很大,也可能不会:

  • 动态链接器必须运行一些指令,如果你有一个非常小的用户态测试可执行文件,并且运行在像 O3 这样的低 CPU 上,那么这个启动可以支配运行时,所以要小心

  • ExecAll不显示 stdlib 函数的符号名称,您只需从一些随机最近的符号(例如@__end__+274873692728. 也许这些方面的东西会起作用:Debugging shared libraries with gdbserver but not sure

  • 第一次动态跳转到 stdlib 函数需要通过动态链接机制,如果您试图控制 microbench,这可能会产生问题。

    实际上,我已经遇到过一次:程序的动态版本做了一些额外的事情,再加上 gem5 错误破坏了我的实验,并花费了我几个小时的调试时间。

像 Python 和 Java 这样的解释器

Python 和 Java 只是可执行文件,以及执行可执行文件参数的脚本。

所以理论上,你可以在系统调用仿真模式下运行它们,例如:

build/ARM/gem5.opt configs/example/se.py --cmd /usr/bin/python --options='hello.py arg1 arg2'

然而,在实践中,考虑到截至 2019 年 11 月 gem5 的当前状态,非常复杂的可执行文件(如解释器)可能具有尚未实现的系统调用,另请参阅:何时在 gem5 中将完整系统 FS 与系统调用仿真 SE 与用户态程序一起使用?

一般来说,实现/忽略不需要的调用并不难,所以试一试。相关话题:

旧答案

有人告诉我,截至 49f96e7b77925837aa5bc84d4c3453ab5f07408e(2018 年 5 月),在系统调用仿真中运行动态链接的跨拱可执行文件没有方便/经过良好测试的方法:https ://www.mail-archive.com/gem5-users@gem5.org /msg15585.html

然而,我怀疑修补 gem5 来支持它并不难。QEMU 用户模式已经支持这一点,您只需使用-L.


推荐阅读