Hi-Angel Hi-Angel - 4 months ago 9
Linux Question

"sh: ./<file> not found" error when trying to execute a file

I've come across a weirdest problem I ever met. I am trying to cross-compile an app for the ARM CPU with a linux on-board. I am using the buildroot, and all goes just fine, until I load an application to the target. When I am trying to launch an application, I getting an error like

-sh: ./hw: not found
. Let's consider an example

$ cat /tmp/test.cpp
#include <cstdio>
#include <vector>

int main(int argc, char** argv){
printf("Hello Kitty!\n");
return 0;
}
$ ./arm-linux-g++ -march=armv7-a /tmp/test.cpp -o /tftpboot/hw


load the executable to the target; next in the target issuing:

# ./hw
-sh: ./hw: Permission denied
# chmod +x ./hw
# ./hw
-sh: ./hw: not found
# ls -l ./hw
-rwxr-xr-x 1 root root 6103 Jan 1 03:40 ./hw


But yet it isn't all. If I compile by the distro compiler, like this
arm-linux-gnueabi-g++ -march=armv7-a /tmp/test.cpp -o /tftpboot/hw
, the application runs just fine!

I tried to compare the files through the
readelf -a -W /tftpboot/hw
, but haven't noticed any big defferences. I pasted both the outputs here. The only thing I had noticed is the lines
Version5 EABI, soft-float ABI
vs
Version5 EABI
. I tried to remove this line too, by passing either of the options
-mfloat-abi=softfp
and
-mfloat-abi=soft
, but compiler seems just ignore it. But, I suppose, this doesn't really matter, as the compiler doesn't even warn me.

One more thing: at first I thought that the sh writes this weird error if the executable file somehow incompatible. But this is not true! On my host PC the sh gives another error in this cases, i.e.:

$ sh /tftpboot/hw
/tftpboot/hw: 1: /tftpboot/hw: Syntax error: word unexpected (expecting ")")

Answer

sh prints this weird error because it is trying to run your program as a shell script!

Your error ./hw: not found is probably caused by the dynamic linker (AKA ELF interpreter) not being found. Try compiling it as a static program with -static or running it with your dynamic loader: # /lib/ld-linux.so.2 ./hw or something like that.

If the problem is that the dynamic loader is named differently in your tool-chain and in your runtime environment you can fix it:

  • In the runtime environment: with a symbolic link.
  • In the tool-chain: use -Wl,--dynamic-linker=/lib/ld-linux.so.2