When assembling your first programs with AS, and linking it to external libraries like this :
armv7a-hardfloat-linux-gnueabi-as -o test.o test.Sarmv7a-hardfloat-linux-gnueabi-ld.gold --hash-style=sysv -o test test.o -lc
armv7a-hardfloat-linux-gnueabi-as -o test.o test.S
armv7a-hardfloat-linux-gnueabi-ld.gold --hash-style=sysv -o test test.o -lc
You might be confronted to this error when executing your program :
$ ./test-bash: ./test: No such file or directory
$ ./test
-bash: ./test: No such file or directory
Using strace to pinpoint the problem will result to something like this :
execve("./test", ["./test"], [/* 28 vars */]) = -1 ENOENT (No such file or directory)write(2, "strace: exec: No such file or di"..., 40strace: exec: No such file or directory) = 40exit_group(1) = ?+++ exited with 1 +++
execve("./test", ["./test"], [/* 28 vars */]) = -1 ENOENT (No such file or directory)
write(2, "strace: exec: No such file or di"..., 40strace: exec: No such file or directory
) = 40
exit_group(1) = ?
+++ exited with 1 +++
Looking at execve manual page, ENOENT is described like this :
The executable is not a script. The file clearly exists. However, the ELF interpreter ?
When running readelf -l elf_executable you can see which interpreter the executable tries to use. In this case, the output is :
Elf file type is EXEC (Executable file)Entry point 0x81b8There are 5 program headers, starting at offset 52Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align PHDR 0x000034 0x00008034 0x00008034 0x000a0 0x000a0 R 0x4 INTERP 0x0000d4 0x000080d4 0x000080d4 0x00013 0x00013 R 0x1 [Requesting program interpreter: /usr/lib/libc.so.1] LOAD 0x000000 0x00008000 0x00008000 0x00208 0x00208 R E 0x1000 LOAD 0x000208 0x00009208 0x00009208 0x000cc 0x000cc RW 0x1000 DYNAMIC 0x000208 0x00009208 0x00009208 0x000a0 0x000a0 RW 0x4 Section to Segment mapping: Segment Sections... 00 01 .interp 02 .interp .dynsym .dynstr .hash .gnu.version .gnu.version_r .rel.plt .plt .text 03 .dynamic .data .got 04 .dynamic
Elf file type is EXEC (Executable file)
Entry point 0x81b8
There are 5 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x00008034 0x00008034 0x000a0 0x000a0 R 0x4
INTERP 0x0000d4 0x000080d4 0x000080d4 0x00013 0x00013 R 0x1
[Requesting program interpreter: /usr/lib/libc.so.1]
LOAD 0x000000 0x00008000 0x00008000 0x00208 0x00208 R E 0x1000
LOAD 0x000208 0x00009208 0x00009208 0x000cc 0x000cc RW 0x1000
DYNAMIC 0x000208 0x00009208 0x00009208 0x000a0 0x000a0 RW 0x4
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .dynsym .dynstr .hash .gnu.version .gnu.version_r .rel.plt .plt .text
03 .dynamic .data .got
04 .dynamic
The line Requesting program interpreter shows which ELF interpreter the system tries to use. On this system /usr/lib/libc.so.1 does not exist, which is why executing the program returns "File not found".
However, on a Linux system for example, the standard ELF interpreter is not libc but ld.
Define the system dynamic linker as the ELF interpreter using the --dynamic-linker directive when linking the program.
When linking programs for Linux ARM systems :
armv7a-hardfloat-linux-gnueabi-ld.gold --hash-style=sysv --dynamic-linker=/lib/ld-linux-armhf.so.3 -o test test.o -lc
When linking programs for Android ARM systems :
armv7a-hardfloat-linux-gnueabi-ld.gold --hash-style=sysv --dynamic-linker=/system/bin/linker -o test test.o -lc
I just encountered the same issue while trying to cross-compile a C program from a system using GlibC and execute it on a system using Musl.
Musl dynamic linker is located at : /lib/ld-musl-armhf.so.1 on ARMv7 with Hardware FPU.
So you'll have to pass -Wl,--dynamic-linker=/lib/ld-musl-armhf.so.1 to GCC, when linking an executable, to be able to execute the program correctly on the Musl system.
Example :
arm-linux-gnueabihf-gcc -o test test.c -Wl,--dynamic-linker=/lib/ld-musl-armhf.so.1