尝试执行文件时出现"sh:./ <file> not found"错误

Hi-*_*gel 6 c++ linux arm sh buildroot

我遇到过一个我见过的最奇怪的问题.我正在为Linux上的Linux CPU交叉编译应用程序.我正在使用buildroot,一切顺利,直到我试图在目标上运行应用程序:我得到了-sh: ./hw: not found.例如:

$ 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
Run Code Online (Sandbox Code Playgroud)

将可执行文件加载到目标; 然后发布目标:

# ./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
Run Code Online (Sandbox Code Playgroud)

还有更多:在使用发行版编译器构建时arm-linux-gnueabi-g++ -march=armv7-a /tmp/test.cpp -o /tftpboot/hw,应用运行正常!

我比较了可执行文件readelf -a -W /tftpboot/hw,但没有发现太多的差异.我在这里粘贴了两个输出.我注意到的唯一一件事就是线Version5 EABI, soft-float ABI对战Version5 EABI.我试图通过传递要么删除的差别-mfloat-abi=softfp-mfloat-abi=soft,但似乎编译器忽略它.我想,这并不重要,因为编译器甚至没有警告过.

我也想过,也许SH输出此错误,如果一个可执行文件在某种程度上是不兼容的.但是在我的主机PC上,我看到了这种情况下的另一个错误,例如:

$ sh /tftpboot/hw
/tftpboot/hw: 1: /tftpboot/hw: Syntax error: word unexpected (expecting ")")
Run Code Online (Sandbox Code Playgroud)

rod*_*igo 9

sh打印这个奇怪的错误,因为它试图将您的程序作为shell脚本运行!

您的错误./hw: not found可能是由未找到动态链接器(AKA ELF解释器)引起的.尝试将其编译为静态程序,-static或者使用动态加载程序运行它:# /lib/ld-linux.so.2 ./hw或类似的东西.

如果问题是动态加载程序在工具链和运行时环境中的命名方式不同,则可以修复它:

  • 在运行时环境中:使用符号链接.
  • 在工具链中:使用 -Wl,--dynamic-linker=/lib/ld-linux.so.2

  • @YagamyLight:不,程序具有动态链接器的_name_,由`--dynamic-linker`链接器选项设置.真正的动态链接器位于系统中的文件中.并且`sh`不调用动态加载器,它调用内核到`exec()`程序,内核看到它是一个ELF文件(签名),检查它是否有解释器(解释器是几乎总是动态加载器,如果存在的话),如果是这样,则运行解释器.如果程序引用的动态链接器不存在,则会出现"找不到文件"错误. (4认同)
  • 是的,`-static`选项就行了!非常感谢你!只是很好奇 - 如果你知道的话,请告诉我:库应该链接到哪里,以及为什么文件被描述为脚本,直到我静态链接?系统是否在文件中看到"ELF"签名? (2认同)
  • @YagamyLight:问题不是库,而是动态链接器,即加载动态可执行文件的程序.在Linux中,它通常是`/ lib/ld-linux*`.您可以使用`objdump -s -j/bin/ls`查看它是什么,是`/ bin/ls`是一个可行的动态可执行文件. (2认同)
  • @YagamyLight:该文件被视为一个脚本,因为这是`sh`对其第一个参数的作用:将其视为脚本.要将其视为命令(以及可能的程序),请使用`sh -c./ hw`.但是,你可以简单地写一下`./hw`. (2认同)