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

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

Support for dynamic linking has been added in November 2019
At: https://gem5-review.googlesource.com/c/public/gem5/+/23066
It was working for sure at that point, but then it broke at some point and needs fixing.....
arm 32-bit https://gem5.atlassian.net/browse/GEM5-461
arm 64-bit https://gem5.atlassian.net/browse/GEM5-828
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.
It later broke at https://gem5.atlassian.net/browse/GEM5-430 but was fixed again.
Downsides of dynamic linking
Once I got dynamic linking to work, I noticed that it actually has the following downsides, which might or not be considerable depending on the application:
the dynamic linker has to run some instructions, and if you have a very minimal userland test executable, and are running on a low CPU like O3, then this startup can dominate runtime, so watch out for that
ExecAll does not show symbol names for stdlib functions, you just get offsets from some random nearest symbol e.g. #__end__+274873692728. Maybe something along these lines would work: Debugging shared libraries with gdbserver but not sure
dynamically jumping to a stdlib function for the first time requires going through the dynamic linking machinery, which can create problems if you are trying to control a microbench.
I actually already hit this once: the dynamic version of a program was doing something extra that and that compounded with a gem5 bug broke my experiment, and cost me a few hours of debugging.
Interpreters like Python and Java
Python and Java are just executables, and the script to execute an argument to the executable.
So in theory, you can run them in syscall emulation mode e.g. with:
build/ARM/gem5.opt configs/example/se.py --cmd /usr/bin/python --options='hello.py arg1 arg2'
In practice however hugely complex executable like interpreters are likely to have syscalls that not yet implemented given the current state of gem5 as of November 2019, see also: When to use full system FS vs syscall emulation SE with userland programs in gem5?
Generally it is not hard to implement / ignore uneeded calls though, so give it a shot. Related threads:
Java: Running Java programs in gem5(or any language which is not C)
Python: 3.6.8 aarch64 fails with "fatal: syscall unused#278 (#278) unimplemented.", test setup
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.

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.

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

Related

How does Gem5 accept and decode executables from user?

Eg:
/home/gem5/build/X86/gem5.opt --debug-flags=TLB,Cache
/home/gem5/configs/example/se.py --cpu-type=DerivO3CPU --caches
--mem-type=SimpleMemory -I 10000 -c out --options="1 in_16.txt out.txt" >> test2.txt
The bold part in the SE CLI for Gem5 shows my input to it. How exactly does Gem5 process this and obtain the instructions to be simulated? Which files should I be looking into for this? As far as I know, no tutorials mention this.
out is a regular ELF userland executable, e.g. a C hello world, just like the ones you would run on your Linux host.
Usage of dynamically linked executable is described at: How to run a dynamically linked executable syscall emulation mode se.py in gem5? so generally statically linking is easier.
gem5 parses the ELF format, places memory into the right locations, puts the PC in the right location, and kicks off simulation, just like the exec syscall of the Linux kernel would.
Several runnable examples are available here.

Dynamic Loader of Executable in Valgrind Ignoring LD_LIBRARY_PATH

LD_LIBRARY_PATH=/otherRoot/lib/ valgrind myProg
chroot /otherRoot valgrind myProg
When running the first command, valgrind gives me errors about a stripped dynamic linker because it apparently is not using the one in /otherRoot/lib. Using the second command, it finds my the appropriate .so and works.
For reference, I have valgrind installed in the "normal root" and "otherRoot" as well.
Why does valgrind/myProg not search for the .so in /otherRoot/lib first?
When running the first command, valgrind gives me errors about a stripped dynamic linker because it apparently is not using the one in /otherRoot/lib.
The dynamic loader your program uses doesn't (can't) depend on LD_LIBRARY_PATH, because it is the kernel the loads the dynamic loader (and the kernel generally doesn't care about environment variables). More info here.
Outside of chroot, the "wrong" dynamic loader is used with or without valgrind. You can confirm this by pausing myProg and examining /proc/$PID/maps for it.

importing one ml file into another

I have an interpreter.ml file that contains an interpreter and some type definitions.
I've developed some test batteries to check if the interpreter works well or not.
When I put the functions I use to test the behaviour of the interpreter in the same file of the interpreter all works well, but if I try to use a different file for the tests (let's say tests.ml) it did not load the interpreter functions and definitions.
the interpreter.ml and tests.ml are in the same folder
I tried both with open Interpreter and #use "./interpreter.ml" from inside tests.ml but it wont compile nor shut down the warnings in the IDE (kind of...I'm using Visual Studio Code on MacOs )
I've already tried to follow the official documentation but it won't compile with ocamlopt -c tests.ml
As a result of discussions, the executable is obtained by compiling the 2 files test.ml & interpreter.ml in the right order (test.ml relies on objects defined in interpreter.ml; as a consequence test.ml has to reference to interpreter objects either via the clause open Interpreter or by prefixing all relevant items with Interpreter ):
ocamlc -o exec interpreter.ml test.ml
ocamlbuild is easier as it resolves by itself the dependencies:
The following command:
ocamlbuild test.native
will produce the executable.

Can the object file name be changed from .obj during cmake compiler testing?

Ultimately, I'm trying to build Apache QPID to run in the HPE NonStop OSS environment (a Posix-like environment on the NonStop system). The latest version of QPID uses cmake to build so I first need to get cmake to work for that environment. My earlier attempts tried to build in OSS directly (I needed to build cmake first before trying to build QPID), but I ran into many problems there. So lately I'm trying to build in Windows using a set of cross-development tools (compilers etc.) for NonStop. I've downloaded a Windows version of cmake 2.8 (suggested by the QPID build instructions) and am trying to use that with the X-dev tools to build QPID for OSS.
One big issue I've run into has to do with how cmake does things to test compilers and so forth early on. It will invoke the compiler to create an intermediate object file from C (and/or C++) source file and after that it will invoke the compiler to link an object file from the intermediate file. It seems that cmake prefers to add .obj to file names to create the intermediate object file name. This will work OK with my cross-compiler when creating the file (the name passed with -o to the compiler) but it will not work when passing this name for link purposes. Here is a short bit of the output per the CMakeError.log file (from trying build an OSS version of cmake 2.8 itself):
Determining if the C compiler works failed with the following output:
Change Dir: C:/Source/cmake-2.8.0/bld/CMakeFiles/CMakeTmp
Run Build Command:C:/cygwin/bin/make.exe "cmTryCompileExec/fast"
/usr/bin/make -f CMakeFiles/cmTryCompileExec.dir/build.make CMakeFiles/cmTryCompileExec.dir/build
make[1]: Entering directory '/cygdrive/c/Source/cmake-2.8.0/bld/CMakeFiles/CMakeTmp'
"C:/Program Files (x86)/CMake 2.8/bin/cmake.exe" -E cmake_progress_report C:/Source/cmake-2.8.0/bld/CMakeFiles/CMakeTmp/CMakeFiles 1
Building C object CMakeFiles/cmTryCompileExec.dir/testCCompiler.c.obj
/cygdrive/c/NonStop/tndm_cmplrs-j20/usr/bin/c89.exe -o CMakeFiles/cmTryCompileExec.dir/testCCompiler.c.obj -c C:/Source/cmake-2.8.0/bld/CMakeFiles/CMakeTmp/testCCompiler.c
Linking C executable cmTryCompileExec
/cygdrive/c/NonStop/tndm_cmplrs-j20/usr/bin/c89.exe "CMakeFiles/cmTryCompileExec.dir/testCCompiler.c.obj" -o cmTryCompileExec
c89.exe: error: Invalid input file extension"CMakeFiles/cmTryCompileExec.dir/testCCompiler.c.obj".
The cross-compiler fails because it requires intermediate object files to use .o for the extension, in order to determine they are intermediate object files. There is no way to get the c89 compiler to recognize testCCompiler.c.obj as a file type it knows what to do with.
So I've been searching (trying to find a local expert, but no one in my organization knows cmake; also numerous Google searches but could not find an answer) to see if there is any way to get cmake to change the name of the output file it uses for these type of compiles and tests. I've found info and then set CMAKE_C_OUTPUT_EXTENSION in a toolchain file:
SET(CMAKE_C_OUTPUT_EXTENSION ".o")
but that has made no difference.
If I can find a way to get cmake to create object files with names like testCCompiler.c.o instead of testCCompiler.c.obj, then the c89 cross-compiler would work.
Is it possible to do this?
UPDATE: I've managed to figure out that setting CMAKE_C_OUTPUT_EXTENSION in the toolchain file doesn't help. This gets overwritten in the CMakeCInformation.cmake (depending on whether UNIX is set or not). I also tracked down that UNIX gets set to true in Platform/UnixPaths.cmake, which gets INCLUDEd by various Platform files. So I've created a Modules/Platform/OSS.cmake file which includes it to takes care of that. I'll probably need/want to add other settings there later as I determine more flags for compilers etc that should be set to specific values for the OSS environment.

Build and link µIP library with no OS

I'm relitavely new to embedded development and I have a question, or more of a feedback, on building and linking the µIP library on an embedded device. For what it's worth, the following is using a FOX G20 V board with an ATMEL AT91SAM9G20 processor with no OS.
I have done some research, and the way I see myself building and linking the library on the board is one of the following two options.
Option 1: The first option would be to compile the whole library (the .c files) in order to have a built static library in the form of a .a file. Then, I can link the created static library with my application code, before loading it on the device. Of course, the device driver will have to be programmed in order to allow the library to work on the platform (help was found here). This first option is using a Linux machine. For this first option as well, in order to load the static library linked with my application code, do I do so with an "scp"?
Option 2: The second option would be to compile and link the library to my application code directly without going through an intermediate static library. However, since my platorm does not contain an OS, I would need to install an appropraite GCC compiler in order to compile and link (if anyone has any leads for such an installation, that would be very helpful as well). However I'm quite unfamilier with the second option, but I've been told that it is easier to implement so if anyone as an idea on how to implement it, it would be very helpful.
I would appreciate some feedback along with the answers as to whether these options seem correct to you, and to be sure that I have not mentioned something that is false.
There is no real difference between these options. In any case, the host toolchain is responsible for creating a binary file that contains a fully linked executable with no external dependencies, so you need a cross compiler either way, and it is indeed easiest to just compile uIP along with the rest of the application.
The toolchain will typically have a cross compiler (if you use gcc, it should be named arm-eabi-gcc or arm-none-eabi-gcc), cross linker (arm-eabi-ld), cross archiver (arm-eabi-ar) etc. You would use these instead of the native tools. For Debian, you can find a cross compiler for ARM targets without an OS in testing/unstable.
Whether you build a static library
arm-eabi-gcc -c uip.c
arm-eabi-ar cru uip.a uip.o
arm-eabi-ranlib uip.a
arm-eabi-gcc -o executable application.c uip.a
or directly link
arm-eabi-gcc -c application.c
arm-eabi-gcc -c uip.c
arm-eabi-gcc -o executable application.o uip.o
or directly compile and link
arm-eabi-gcc -o executable application.c uip.c
makes no real difference.
If you use an integrated development environment, it is usually easiest to just add uip.c as a source file.