arm cortex a9 cross compilant un comportement en virgule flottante

J’essaie de porter une application plus large de x86 à armer cortex a9, mais j’obtiens d’étranges erreurs de segmentation avec des fonctions à virgule flottante telles que modf lors de la compilation croisée de l’application. (voir ci-dessous).

J’ai donc essayé ce petit programme de test, qui peut aussi déclencher l’erreur. La sortie du programme de test (voir ci-dessous) devrait illustrer mon problème.

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

compilé sur le cortex des arm a9:

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

cross compilé

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

cross compilé avec l’option de l’éditeur de liens ‘-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 

.

Pour répondre à certains des commentaires ci-dessous:
– Le compilateur croisé est configuré pour little endian, de même que le compilateur natif sur la machine tegra.
– Je ne crois pas que ce soit un problème d’alignement de mémoire, j’avais ma part de ceux-ci lors du portage sur arm et ceux-ci devraient envoyer SIGBUS à l’application ou se connecter à syslog, voir la documentation de / proc / cpu / alignement.

Ma solution actuelle consiste à copier la chaîne d’outils multi-compilée et à l’utiliser avec LD_LIBRARY_PATH … pas sympa, mais suffisant pour le moment.

Modifier:
Merci pour vos réponses.
Dans l’intervalle, j’ai découvert que la dissortingbution Linux sur le périphérique tegra était compilée avec ‘-mfloat-abi = softfp’ bien que la documentation indique qu’une chaîne d’outils compilée avec ‘-mfloat-abi = hard’ est requirejse.
Changer la chaîne d’outils a apporté le succès

Il semble que la différence entre hard et softfp peut être vue en utilisant ‘readelf-A’ sur n’importe quel binary système:
Si la sortie contient la ligne: ‘Tag_ABI_VFP_args: VFP enregistre’, elle est compilée avec ‘-mfloat-abi = hard’. Si cette ligne manque, le binary est probablement compilé avec ‘-mfloat-abi = softfp’.
La ligne ‘Tag_ABI_HardFP_use: SP et DP’ n’indique pas le drapeau de compilation ‘-mfloat-abi = hard’.

En regardant la sortie de l’assembly, nous pouvons voir une différence dans les deux fichiers.

Dans 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> 

Ceci passe un double dans r2:r3 et std::cout dans r0 .

Dans 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> 

Cela passe un double dans d0 (un registre VFP) et std::cout dans r0 . Observez ici que r2:r3 est chargé (par ldrd ) avec la valeur à virgule flottante imprimée en seconde, soit 0.0. Parce que l’ ostream::operator<<(double val) dynamicment lié ostream::operator<<(double val) attend son argument dans r2:r3 , 0 est imprimé en premier.

Je peux aussi expliquer le deuxième flotteur qui a l'air bizarre. Voici où le deuxième float est imprimé:

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

Voir que r3 est mis à r0 , l'adresse de cout . D'en haut, r0 = 0x011040 . Ainsi, la paire de registres r2:r3 devient 0x0001104000000000, ce qui décode en 1,478946186471156e-309.

Le problème est donc que les bibliothèques de votre bureau GCC utilisent des instructions VFP / NEON, qui ne sont pas utilisées par les bibliothèques dynamics sur le périphérique. Si vous utilisez -static , vous obtenez les bibliothèques VFP / NEON et tout fonctionne à nouveau.

Ma suggestion serait simplement de comprendre pourquoi les bibliothèques de périphériques et de compilateurs diffèrent, et de résoudre ce problème.

Mon hypothèse: sans les commutateurs appropriés indiquant la prise en charge du matériel vfp, le compilateur utilisera des bibliothèques de logiciels pour effectuer des calculs en virgule flottante sur arm. Si vous comstackz avec des liens statiques, ces bibliothèques seront incluses dans le résultat binary: cela fonctionne. Si vous utilisez le mode de liaison normal (dynamic), les bibliothèques ne sont pas incluses – résultat: cela ne fonctionne pas pour une raison quelconque. Les bibliothèques de votre système tegra sont en quelque sorte incompatibles (probablement en raison de conventions d’appel) avec ce que votre compilateur croisé produit.