sh: ./‹file› не найдена ошибка при попытке выполнить файл

Я столкнулся с самой странной проблемой, которую я когда-либо встречал. Я кросс-компилирую приложение для процессора ARM с Linux на борту. Я использую 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

загрузить исполняемый файл в цель; затем выдача на цель:

# ./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

Это еще не все: после сборки с помощью компилятора дистрибутива, такого как arm-linux-gnueabi-g++ -march=armv7-a /tmp/test.cpp -o /tftpboot/hw, приложение работает нормально!

Я сравнивал исполняемые файлы через readelf -a -W /tftpboot/hw, но особой разницы не заметил. Я вставил сюда оба вывода. Единственное, что я заметил, это строки Version5 EABI, soft-float ABI vs Version5 EABI. Я попытался удалить разницу, передав -mfloat-abi=softfp и -mfloat-abi=soft, но компилятор, похоже, игнорирует ее. Я полагаю, однако, что это не имеет большого значения, так как компилятор даже не предупреждает.

Я также подумал, что, возможно, sh выводит эту ошибку, если исполняемый файл каким-то образом несовместим. Но на моем хост-компьютере я вижу другую ошибку в этом случае, например:

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

person Hi-Angel    schedule 07.07.2014    source источник
comment
аналогичная stackoverflow.com/questions/14535897/   -  person Ciro Santilli 新疆再教育营六四事件ۍ    schedule 31.07.2016


Ответы (1)


sh выводит эту странную ошибку, потому что пытается запустить вашу программу как скрипт оболочки!

Ваша ошибка ./hw: not found, вероятно, вызвана тем, что динамический компоновщик (он же интерпретатор ELF) не найден. Попробуйте скомпилировать его как статическую программу с помощью -static или запустить с помощью динамического загрузчика: # /lib/ld-linux.so.2 ./hw или что-то в этом роде.

Если проблема в том, что динамический загрузчик называется по-разному в вашей цепочке инструментов и в вашей среде выполнения, вы можете это исправить:

  • В среде выполнения: с символической ссылкой.
  • В цепочке инструментов: используйте -Wl,--dynamic-linker=/lib/ld-linux.so.2
person rodrigo    schedule 07.07.2014
comment
Да, вариант -static помог! Большое спасибо! Просто любопытно -- если знаете, подскажите, пожалуйста, какую библиотеку надо было туда залинковать, и почему с файлом обращались как со скриптом, пока я не залинковал статически? Разве система не видит подпись ELF в файле? - person Hi-Angel; 07.07.2014
comment
@YagamyLight: проблема не в библиотеке, а в динамическом компоновщике, то есть в программе, которая загружает динамические исполняемые файлы. В Linux это обычно /lib/ld-linux*. Вы можете видеть, что происходит с objdump -s -j /bin/ls, будучи /bin/ls динамическим исполняемым файлом, который действительно работает. - person rodrigo; 07.07.2014
comment
@YagamyLight: файл обрабатывается как скрипт, потому что именно это sh делает со своим первым аргументом: обрабатывает его как скрипт. Чтобы рассматривать это как команду (и, возможно, программу), используйте sh -c ./hw. Но тогда вы можете просто написать ./hw. - person rodrigo; 07.07.2014
comment
Но я так и не понял: sh вызывает динамический загрузчик, верно? Как это можно статически залинковать в файл, если в этом случае для того, чтобы загрузить файл, нам нужен линкер, а линкер остается в файле, поэтому файл не может быть загружен. - person Hi-Angel; 07.07.2014
comment
@YagamyLight: Нет, программа имеет имя динамического компоновщика, заданное параметром компоновщика --dynamic-linker. Настоящий динамический компоновщик находится в файле в вашей системе. И sh не вызывает динамический загрузчик, он вызывает ядро ​​для exec() программы, ядро ​​видит, что это файл ELF (сигнатура), проверяет, есть ли у него интерпретатор или нет (интерпретатор почти всегда является динамическим загрузчиком, если присутствует), и если да, то вместо этого запускает интерпретатор. Если динамический компоновщик, на который ссылается ваша программа, не существует, вы получите ошибку file not found. - person rodrigo; 07.07.2014