How to run a dynamically linked executable syscall emulation mode se.py in gem5?

六眼飞鱼酱① 提交于 2019-12-01 08:07:41

问题


After How to solve "FATAL: kernel too old" when running gem5 in syscall emulation SE mode? I managed to run a statically linked hello world under certain conditions.

But if I try to run an ARM dynamically linked one against the stdlib with:

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

it fails with:

fatal: Unable to open dynamic executable's interpreter.

How to make it find the interpreter? Hopefully without copying my cross' toolchain's interpreter on my host's root.

For x86_64 it works if I use my native compiler, and as expected strace says that it is using the native interpreter, but it does not work if I use a cross compiler.

The current FAQ says it is not possible to use dynamic executables: http://gem5.org/Frequently_Asked_Questions but I don't trust it, and then these presentations mention it:

  • http://www.gem5.org/wiki/images/0/0c/2015_ws_08_dynamic-linker.pdf
  • http://research.cs.wisc.edu/multifacet/papers/learning_gem5_tutorial.pdf

but not how to actually use it.

QEMU user mode has the -L option for that.

Tested in gem5 49f96e7b77925837aa5bc84d4c3453ab5f07408e

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


回答1:


The cross-compiled binary should have an .interp entry if it's a dynamic executable.

Verify it with readelf:

 readelf -a $bin_name | grep interp

The simulator is setup to find this section in main executable when it loads the executable into the simulated address space. If this sections exists, a c-string is set to point to that text (normally something like /lib64/ld-linux-x86-64.so.2). The simulator then calls glibc's open function with that c-string as the parameter. Effectively, this opens the dynamic linker-loader for the simulator as a normal file. The simulator then maps the file into the simulated address space in phases with mmap and mmap_fixed.

For cross compilation, this code must fail. The error message follows it directly if the simulator cannot open the file. To make this work, you need to debug the opening process and possibly the subsequent pasting of the loader into the address space. There is mechanism to set the program's entry point into the loader rather than directly into the code section of the main binary. (It's done through the auxiliary vector on the stack.) You may need to play around with that as well.

The interesting code is (as of 05/29/19) in src/base/loader/elf_object.cc.




回答2:


Support for dynamic linking has been added in November 2019

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

If you have a root filesystem to use, for example one generated by Buildroot you can do:

./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

Or if you are using an Ubuntu cross compiler toolchain for example in 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

You have to add any paths that might contain dynamic libraries as a separate --redirect as well. Those are enough for C executables.

--interp-dir sets the root directory where the dynamic loader will be searched for, based on ELF metadata which says the path of the loader. For example, buildroot ELF files set that path to /lib/ld-linux-aarch64.so.1, and the loader is a file present at /path/to/build/target/lib/ld-linux-aarch64.so.1. As mentioned by Brandon, this path can be found with:

 readelf -a $bin_name | grep interp

The main difficulty with syscall emulation dynamic linking, is that we want somehow:

  • linker file accesses to go to a magic directory to find libraries there
  • other file accesses from the main application to go to normal paths, e.g. to read an input file in the current working directory

and it is hard to detect if we are in the loader or not, especially because this can happen via dlopen in the middle of a program.

The --redirects option is a simple solution for that.

For example /lib=/path/to/build/target/lib makes it so that if the guest would access the C standard library /lib/libc.so.6, then gem5 sees that this is inside /lib and redirects the path to /path/to/build/target/lib/libc.so.6 instead.

The slight downside is that it becomes impossible to actually access files in the /lib directory of the host, but this is not common, so it works in most cases.

If you miss any --redirect, the dynamic linker will likely complain that the library was not found with a message of type:

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

If that happens, you have to find the libstdc++.so.6 library in the target filesystem / toolchain and add the missing --redirect.

Old answer

I have been told that as of 49f96e7b77925837aa5bc84d4c3453ab5f07408e (May 2018) there is no convenient / well tested way for running dynamically linked cross arch executables in syscall emulation: https://www.mail-archive.com/gem5-users@gem5.org/msg15585.html

I suspect however that it wouldn't be very hard to patch gem5 to support it. QEMU user mode already supports that, you just have to point to the root filesystem with -L.




回答3:


I encountered this problem after I just cross compiled the code. You can try to add "--static" after the command.



来源:https://stackoverflow.com/questions/50542222/how-to-run-a-dynamically-linked-executable-syscall-emulation-mode-se-py-in-gem5

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!