Ubuntu 17.10, C program:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
puts("hello");
return EXIT_SUCCESS;
}
gem5 version: da79d6c6cde0fbe5473ce868c9be4771160a003b dec 2017
GCC version:
$ sudo apt-get install gcc-arm-linux-gnueabi
$ arm-linux-gnueabi-gcc --version
arm-linux-gnueabi-gcc (Ubuntu/Linaro 7.2.0-6ubuntu1) 7.2.0
Compile and run:
./gem5/gem5/build/ARM/gem5.opt ./gem5/gem5/configs/example/se.py -c ./a.out
arm-linux-gnueabi-gcc -static kernel_module/user/hello.c
Outcome:
gem5 Simulator System. http://gem5.org
gem5 is copyrighted software; use the --copyright option for details.
gem5 compiled Feb 23 2018 05:25:49
gem5 started Feb 24 2018 04:10:38
gem5 executing on ciro-p51, pid 3092
command line: ./gem5/gem5/build/ARM/gem5.opt ./gem5/gem5/configs/example/se.py -c ./a.out
Global frequency set at 1000000000000 ticks per second
warn: DRAM device capacity (8192 Mbytes) does not match the address range assigned (512 Mbytes)
0: system.remote_gdb.listener: listening for remote gdb #0 on port 7000
**** REAL SIMULATION ****
info: Entering event queue @ 0. Starting simulation...
FATAL: kernel too old
warn: ignoring syscall rt_sigprocmask(...)
(further warnings will be suppressed)
fatal: syscall gettid (#224) unimplemented.
Memory Usage: 659680 KBytes
Analogous on X86.
This has been asked over and over on the mailing lists, so let's centralize the discussion here and determine the best solution.
- https://www.mail-archive.com/gem5-users@gem5.org/msg13772.html
- https://www.mail-archive.com/gem5-users@gem5.org/msg12385.html
- https://www.mail-archive.com/gem5-users@gem5.org/msg12383.html
- https://www.mail-archive.com/gem5-users@gem5.org/msg05538.html
https://www.mail-archive.com/gem5-users@gem5.org/msg12385.html provides a good problem description:
Shortly after the beginning of _start(), the C library issues the uname() syscall to verify for the minimum kernel version. If you look at gem5/src/arch/arm/linux/process.cchttp://process.cc, you will see that in 32-bit mode the emulated syscall returns "3.0.0" and in 64, "3.7.0+". When you configured the toolchain in crosstool-ng, there is an option "CT_LIBC_GLIBC_MIN_KERNEL_VERSION". If that's greater than what the emulated uname() reports, glibc will fatal().
I have noticed that if I use the magic in-tree blob:
tests/test-progs/hello/bin/arm/linux/hello
so what is special about that blob, and how was it generated?
Allowed source version on the source code
823d9d177fded16af07114d70b5c26caaec6aa00 teaches us that the x86 point where the fake kernel version is defined is src/arch/x86/linux/process.cc
.
unameFunc(SyscallDesc *desc, int callnum, Process *process,
...
strcpy(name->release, "3.2.0");
Analogous grepping tells us that arm 32 was at 3.0 and 64 at 3.7.0.
crosstool-ng
attempts
One promising possibility is to use crosstool-ng https://github.com/crosstool-ng/crosstool-ng to generate the compiler, which makes things more controlled.
As of ab3c204aee88f08481f1f63825d0e94b082ef84e I tried both of the following configs:
./ct-ng arm-cortex_a15-linux-gnueabihf
./ct-ng aarch64-unknown-linux-gnu
which compile for kernel 4.16 with GCC 8.1, and then static compilation fails on gem5 49f96e7b77925837aa5bc84d4c3453ab5f07408e respectively with:
fatal: syscall openat (#322) unimplemented.
and:
panic: Attempted to execute unimplemented instruction 'mrs' (inst 0x4d5380000)
but I don't really understand any of the failures:
openat
was introduced in much older kernel 2.6.16, and it does not seem so exotic so why wouldn't it be implemented yet?We then can see on the source that it is implemented for 64 bit but is not implemented for 32 bit for some reason.
I also tried to set the arm minimum kernel version to 3.2, but unsurprisingly it did not help.
why an instruction
mrs
wouldn't be implemented? The ARM reference says this instruction encoding ends in:1 1 0 1 0 1 0 1 0 0 1 1
which is:
d 5 2
so maybe it matches the
0x4d5380000
, but I'm not sure.
It would also be interesting to play around with different crosstool-ng settings, in particular the target kernel version, which at that revision defaults to the latest v4.16 to see if it solves the syscall problem.
Tested on gem5 49f96e7b77925837aa5bc84d4c3453ab5f07408e May 2018.
Ubuntu 18.04 with gem5 Oct 2018
After a few recent gem5 updates, a C hello world for all of x86, arm, aarch64 works with the pre-packaged Ubuntu toolchains. This is described in detail at: How to compile and run an executable in gem5 syscall emulation mode with se.py?
crosstool-ng x86_64-unknown-linux-gnu
Worked with gem5 49f96e7b77925837aa5bc84d4c3453ab5f07408e, ct-ng ab3c204aee88f08481f1f63825d0e94b082ef84e. Generates executables for old Linux kernel 3.2 according to
file
for some reason.uclibc
This is likely a bad idea, but if we use crosstool-ng with uclibc instead of glibc:
then that implementation does not have a kernel check, and the hello world works for all archs.
Also for some reason
mrs
was not used, so it must be a part of the glibc itself.Of course, other unimplemented syscalls on more complex programs are bound to fail.