Кортекс руки A9 кросс-компиляция странное поведение с плавающей запятой

Я пытаюсь портировать более крупное приложение с x86 на вооружение cortex a9, но я получаю странные ошибки сегментации с функциями с плавающей запятой, такими как modf, при кросс-компиляции приложения, другие функции libc ++, кажется, просто обрабатывают с плавающей точкой неправильно, но не дают сбоя (увидеть ниже).

Поэтому я попробовал эту небольшую тестовую программу, которая также может вызвать ошибку.
Вывод тестовой программы (см. Ниже) должен продемонстрировать мою проблему.

#include <iostream>
int main(int argc, char *argv[])
{
double x = 80;
double y = 0;
std::cout << x << "\t" << y << std::endl;
return 0;
}

составлено на руку кору а9:

@tegra$ g++ -Wall test.cpp -o test_nativ
@tegra$ ./test_nativ
80      0

кросс составлен

@x86$ arm-cortex_a9-linux-gnueabi-g++ test.cpp  -o test_cc
@tegra$ ./test_cc
0       1.47895e-309

кросс-компилируется с опцией компоновщика -static.

@x86$ arm-cortex_a9-linux-gnueabi-g++ -static test.cpp  -o test_cc_static
@tegra$ ./test_cc_static
80      0

.

@x86$ arm-cortex_a9-linux-gnueabi-objdump -S test_cc
see: http://pastebin.com/3kqHHLgQ

@tegra$ objdump -S test_nativ
see: http://pastebin.com/zK35KL4X

.

Чтобы ответить на некоторые комментарии ниже:
— Кросс-компилятор настроен для little-endian, как и нативный компилятор на машине Tegra.
— Я не верю, что это проблема выравнивания памяти, у меня была их доля при переносе на arm, и они должны были посылать SIGBUS в приложение или регистрироваться в syslog, см. Документацию для / proc / cpu / alignment.

Мой текущий обходной путь — скопировать кросс-скомпилированную цепочку инструментов и использовать ее с LD_LIBRARY_PATH … не очень хорошо, но пока достаточно хорошо.

Редактировать:
Спасибо за ответ.
Тем временем я обнаружил, что дистрибутив linux на устройстве tegra был скомпилирован с помощью ‘-mfloat-abi = softfp’, хотя в документации указано, что требуется цепочка инструментов, скомпилированная с ‘-mfloat-abi = hard’.

Смена набора инструментов принесла успех.

Кажется, что разницу между hard и softfp можно увидеть с помощью ‘readelf -A’ в любом двоичном файле системы:
Если вывод содержит строку: «Tag_ABI_VFP_args: VFP registers», он компилируется с помощью «-mfloat-abi = hard». Если эта строка отсутствует, двоичный файл, скорее всего, компилируется с помощью ‘-mfloat-abi = softfp’.

Строка ‘Tag_ABI_HardFP_use: SP и DP’ не указывает на флаг компилятора ‘-mfloat-abi = hard’.

7

Решение

Глядя на вывод сборки, мы можем увидеть расхождение в двух файлах.

В test_nativ:

86ec:       4602            mov     r2, r0
86ee:       460b            mov     r3, r1
86f0:       f241 0044       movw    r0, #4164       ; 0x1044
86f4:       f2c0 0001       movt    r0, #1
86f8:       f7ff ef5c       blx     85b4 <_init+0x20>

Это прохождение double в r2:r3, а также std::cout в r0,

В test_cc:

86d8:       e28f3068        add     r3, pc, #104    ; 0x68
86dc:       e1c320d0        ldrd    r2, [r3]
86e0:       e14b21f4        strd    r2, [fp, #-20]  ; 0xffffffec
86e4:       e3010040        movw    r0, #4160       ; 0x1040
86e8:       e3400001        movt    r0, #1
86ec:       ed1b0b03        vldr    d0, [fp, #-12]
86f0:       ebffffa5        bl      858c <_init+0x20>

Это проходит double в d0 (регистр VFP) и std::cout в r0, Обратите внимание, что здесь r2:r3 загружен ( ldrd) со значением с плавающей запятой, которое выводится вторым, то есть 0,0. Потому что динамически связанный ostream::operator<<(double val) ожидает своего аргумента в r2:r3, 0 печатается первым.

Я могу объяснить и второй странный вид поплавка. Вот где напечатано второе число:

8708:       e1a03000        mov     r3, r0
870c:       e1a00003        mov     r0, r3
8710:       ed1b0b05        vldr    d0, [fp, #-20]  ; 0xffffffec
8714:       ebffff9c        bl      858c <_init+0x20>

Видеть, что r3 установлен в r0Адрес cout, Сверху, r0 = 0x011040, Таким образом, регистр пары r2:r3 становится 0x0001104000000000, который декодируется в 1.478946186471156e-309 как двойной.

Таким образом, проблема в том, что библиотеки GCC вашего настольного компьютера используют инструкции VFP / NEON, которые не используются динамическими библиотеками на устройстве. Если вы используете -static, вы получаете библиотеки VFP / NEON, и все снова работает.

Мое предложение было бы просто выяснить, почему библиотеки устройств и компиляторов различаются, и разобраться с этим.

4

Другие решения

мой УгадайБез правильных переключателей, указывающих на поддержку аппаратного обеспечения vfp, компилятор будет использовать библиотеки программного обеспечения для выполнения математических операций с плавающей запятой на руке. Если вы компилируете со статической связью, эти библиотеки будут включены в двоичный файл — результат: он работает. Если вы используете нормальный (динамический) режим компоновки, библиотеки не включаются — результат: по какой-то причине он не работает. Библиотеки в вашей системе Tegra каким-то образом несовместимы (вероятно, из-за соглашения о вызовах) с тем, что создает ваш кросс-компилятор.

0