I am trying to run a cross compiled file with qemu, but get "Permission denied" / "Operation not permitted" erros (even when running with sudo).
I am running Debian 8.7 i386 in a VirtualBox 5.0.22, cross compiling to ARM. The cross-compile setup is described in more detail here http://exploringbeaglebone.com/chapter7.
The cross-compiled file runs fine when copied over to a native ARM device.
#include <stdio.h>
int main()
{
printf("Hello ARM\n";
return 0
}
Build it:
# arm-linux-gnueabihf-gcc testARM.c -o testARM -Wall
# file testARM
# testARM: ELF 32-bit LSB executable, ARM, EABI5 version1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 2.6.32, BuildID[sha1]=...., not stripped
Trying to run directly gives
# ./testARM
# bash: ./testARM: Permission denied
Trying to run via qemu
# qemu-arm ./testARM
# ./testARM: Operation not permitted
Same with sudo
# sudo qemu-arm ./testARM
# ./testARM: Operation not permitted
Running it native on the platform it was cross-compiled for works
beaglebone:~$ ./testARM
Hello ARM
Of course, I also checked the file permissions ( rwxr-xr-x )
Googling showed me someone else with the same issue, but no solution.
My best guess is that running qemu from within VirtualBox is causing the issue, but there are multiple reports that it just works. Host CPU is an Intel Core i7.
What could be the issue? I would like to run automated tests as part of the build process, thats why a working setup with qemu would be nice.
As #TobySpeight supposed, this was just a filesystem mount flag issue. It is described on stackexchange here.
Using the exec flag for mounting resolved the issue: mount -o remount,exec filesystem
Related
Background
I am running the qemu-arm user space emulator inside of a Docker container on Docker for Mac.
I am working on a code base that runs on cortex-m4 processors. I want to be able to cross-compile the code in the docker container to target the cortex-m4 processor and run that code on the qemu-arm user space emulator.
to test this, I have a simple C program (/tmp/program.c):
int main() {
return 0;
}
I use the debian:stable docker image as a base.
I compile the program with the GNU arm toolchain like so:
arm-none-eabi-gcc -mcpu=cortex-m4 --specs=nosys.specs /tmp/program.c
Then I attempt to run this with qemu-arm in the docker container:
qemu-arm -cpu cortex-m4 -strace ./a.out
But I get the following error:
--- SIGSEGV {si_signo=SIGSEGV, si_code=1, si_addr=0x0007fff0} ---
qemu: uncaught target signal 11 (Segmentation fault) - core dumped
Segmentation fault
From what I understand, SIGSEGV occurs in a few scenarios, the only one that makes sense here is that I am accessing memory that I don't have access to when I attempt to run the binary in the qemu-arm user space.
It would seem that the si_addr=0x0007fff0 is the address that I am accessing that I am not supposed to.
Since my program does very little, I am assuming this inaccessible address might be where qemu-arm is attempting to store the binary to run? But I don't see an option in qemu-arm to specify this.
Questions
So my questions are:
how can I verify what is attempting to access that inaccessible address?
if I am correct in my thinking (that this is where qemu-arm is attempting to store the binary to be run), is there a way to change that? I didn't see one in any of the command line options
More information
Docker version 20.10.6, build 370c289
Dockerfile to reproduce:
FROM debian:stable
RUN apt-get update
RUN apt-get install -y gcc-arm-none-eabi qemu-user gcc
RUN echo 'int main() {return 0;}' > /tmp/program.c
# running the program on the docker container exits successfully
RUN gcc /tmp/program.c
RUN ./a.out
# running the program in `qemu-arm` errors
RUN arm-none-eabi-gcc -mcpu=cortex-m4 --specs=nosys.specs /tmp/program.c
RUN qemu-arm -cpu cortex-m4 -strace ./a.out
qemu-arm is an emulator for Linux user-space binaries. The program you're compiling seems to be built with a bare-metal toolchain. It's not impossible to compile a bare-metal binary in such a way that it will run as a Linux user-space program as well, but you have to take specific steps to make it work that way.
You should probably think about whether what you really wanted was:
build a Linux binary targeting Cortex-M4, and run it on qemu-arm
build a bare-metal binary, and run it on qemu-system-arm
something else
For example, how are you expecting your program to produce output? Is the program going to want to talk directly to (emulated) hardware like a serial port, or to other devices? Does the program need to run interrupt handlers?
The best way to debug what's happening is to get QEMU to start its gdbstub, and connect an arm-aware gdb to it. Then you can single step through. (This will probably be a confusing introduction to your toolchain's C runtime startup code...)
I used the
arm-linux-gnueabi-g++ test.cpp -march=armv7-a -mfloat-abi=softfp -mfpu=neon -o test
on ubantu to get an excecutable file on ARM, but when I ran
adb push ./test /data/test
adb shell
cd data
chmod 777 test
./test
I got the following error:
./system/bin/sh: ./test: No such file or directory
I was confused about this.
If you intend to run the executable on Android (as it seems), you should ideally build it using the Android NDK. The problem is that your executable links to glibc which is available on normal linux systems, but not on Android. (In detail, the executable can't start because it requires the dynamic linker /lib/ld-linux.so.3 which isn't available on Android. In addition, it also requires glibc in the form of libc.so.6.)
If you build executables using the Android NDK, it will link to the Bionic libc, which is what is available on Android.
Alternatively, if you add -static when linking (in your case, in your single compile+link command), you'll get a static executable, which should work on both normal linux and Android.
When I try to add it to sources as per debian install instructions I get this error. I'm guessing this means that there are no arm packages for it.
Failed to fetch https://dist.crystal-lang.org/apt/dists/crystal/InRelease Unable to find expected entry 'main/binary-armhf/Packages' in Release file (Wrong sources.list entry or malformed file)
I'm guessing I probably need to install it from source. How would I go about doing that with an arm cpu? When I check it out and run make I get the error:
You need to have a crystal executable in your path! Makefile:113:
recipe for target '.build/crystal' failed make: *** [.build/crystal]
Error 1
Any suggestions would be greatly appreciated.
EDIT: There's now a semi-official repository for crystal on raspbian, check it out here: http://public.portalier.com/raspbian
Crystal doesn't build Debian packages for ARM, and you're correct in that you'll need to build from source.
However, the Crystal compiler is written in Crystal. This presents the obvious problem of how to get a compiler to build the compiler. The answer is cross-compilation: building an arm binary on a x86 desktop computer and copying it across.
Here's a quick step-by-step based on my memory of last time I cross-compiled:
Install Crystal on a x86 desktop PC, and check it works.
Install all required libraries on the desktop and Raspberry Pi. You'll need the same LLVM version on the Raspberry Pi and desktop. This is probably the hardest and longest step. You can install llvm 3.9 from debian testing for ARM, see this stackoverflow post for how to install only LLVM from debian testing.
Check out the sources from git on both computers, and run make deps.
Cross-compile the compiler by running this command in the root of the git repository:
./bin/crystal build src/compiler/crystal.cr --cross-compile --target arm-unknown-linux-gnueabihf --release -s -D without_openssl -D without_zlib
This command will create a crystal.o file in your current directory, and also output a linker command (cc crystal.o -o crystal ...).
Copy crystal.o to the raspberry pi, and run the linker command. Be sure to edit the absolute path to llvm_ext.o so that it points to the Crystal checkout on your Raspberry Pi, not the checkout on your desktop. Also make sure that all references to llvm-config in the command are for the correct LLVM version. For example, changing /usr/local/bin/llvm-config to llvm-config-3.9 on Raspbian.
Run the crystal executable in your current directory (./crystal -v) and make sure it works.
Ensure to set CRYSTAL_PATH environment variable is set to lib:/path/to/crystal/source/checkout/src so that the compiler can find the standard library when compiling applications.
I'm trying to run hello world program on ARM computer with Linux (Debian Wheezy). The libc version on it is 2.13, while my own computer has 2.15 (Ubuntu Precise).
I installed arm-linux-gnueabi-gcc on my computer and compiled the application with static linkage.
All my attempts to run compiled binary result in "cannot execute binary file" message. However, QEMU on my own computer (qemu-arm-static) runs the application succesfully.
I thought that it should be enough to link my app statically. The permissions are 755. What am I missing here?
UPD: I tried to install Arch Linux on that ARM. In that distribution my compiled binaries crash with segfault instead of bash error message. Does stock cross compiler in Ubuntu distribution ever work? :-/
Thanks!
I cross compiled a program on Ubuntu 12.04 running on x86 using gcc-arm-linux-gnueabi and binutils-arm-linux-gnueabi and compiling with arm-linux-gnueabi-gcc instead of gcc with my target architecture being ARM. It compiles fine with no errors or warnings.
When I try to run it on the ARM machine (Pandaboard - also running Ubuntu 12.04) I get:
bash: ./sttyl: No such file or directory
I know the file is there and it has the proper permissions:
-rwxrwxr-x 1 haziz haziz 8.5K Feb 10 10:34 sttyl
The output of file sttyl is
sttyl: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.31,BuildID[sha1]=0x6d504f7d84b93603122223a89e2b5960c840309f, not stripped
When I compile it natively on the Pandaboard it compiles and runs fine. This is the output of file sttyl on the natively compiled copy:
sttyl: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.31,BuildID[sha1]=0x9897c785266c5b7cdf580e08091aba239db84ecf, not stripped
What am I doing wrong? Moreover if I had made a mistake in the cross compilation I would have expected the shell/kernel to tell me effectively that the executable is for the wrong architecture not that it does not exist!
It isn't telling you that ./sttyl doesn't exist.
It's telling you that it spawned a new process, which exited with error No such file or directory. No information is provided about which file or directory was missing.
For example, a shell script starting with #!/bin/specialsh could generate that error if the interpreter /bin/specialsh was missing, even though the script existed and was executable.
Try using strace to find out what call (and path) caused the error.