Недопустимая инструкция при запуске простого ELLCC-сгенерированного двоичного файла ELF на Raspberry Pi
У меня есть пустая программа в LLVM IR:
define i32 @main(i32 %argc, i8** %argv) nounwind {
entry:
ret i32 0
}
Я кросс-компилирую его на Intel x86-64 Windows для ARM Linux, используя ELLCC, с помощью следующей команды:
ecc++ hw.ll -o hw.o -target arm-linux-engeabihf
Он завершается без ошибок и генерирует двоичный файл ELF.
Когда я беру двоичный файл в Raspberry Pi Model B+ (работает Raspbian), я получаю только следующую ошибку:
Illegal instruction
Я не знаю, как сказать, что не так из разобранного кода. Я пробовал другие цели ARM Linux, но поведение было таким же. В чем дело?
Точно такой же файл строит, связывает и отлично работает для других целей, таких как i386-linux-eng
, x86_64-w64-mingw32
и т. д. (что я мог бы проверить), снова используя цепочку инструментов ELLCC.
Предполагая, что библиотека и код запуска не виноваты, это то, что разборка main
сам выглядит так:
.text:00010188 e24dd008 sub sp, sp, #8
.text:0001018c e3002000 movw r2, #0
.text:00010190 e58d0004 str r0, [sp, #4]
.text:00010194 e1a00002 mov r0, r2
.text:00010198 e58d1000 str r1, [sp]
.text:0001019c e28dd008 add sp, sp, #8
.text:000101a0 e12fff1e bx lr
1 ответ
Я предполагаю, что это задыхается от movw
в 0x0001018c. movw
/ movt
кодировки, которые могут обрабатывать полные 16-битные непосредственные значения, впервые появились в версии архитектуры ARMv6T2 - ARM1176 в оригинальных моделях Pi предшествовал этому, поддерживая только оригинальную ARMv6 *.
Вы должны сказать компилятору генерировать код, соответствующий тому, на чем вы работаете - я не знаю ELLCC, но я предполагаю, что он довольно современный и современный и, следовательно, по умолчанию использует что-то более новое, например ARMv6T2. или ARMv7. В противном случае это сродни генерации кода для Pentium и надежде, что он будет работать на 80486 - вам может повезти, а может и нет. Тем не менее, нет веской причины, по которой он должен был выбрать это кодирование в первую очередь - это не так, как если бы 0 не могло быть закодировано в "классическом" mov
инструкция...
Декадентским вариантом, однако, было бы считать это идеальным оправданием для замены Pi на Pi 2 - Cortex-A7s в том, что это хорошие ядра ARMv7;)
* Ложь для ясности. Я думаю, что 1176 на самом деле может быть v6K, но это не имеет значения здесь. Я не уверен, существует ли что-нибудь на самом деле как простой ARMv6, и все различные расширения архитектуры откровенно отвратительны