10
votes

Pourquoi ai-je une référence non définie à _Init dans __libc_init_array?

Je tente de construire un projet simple utilisant Yagarto et Eclipse pour une plate-forme de microcontrôleur ARM. Dans mon code de démarrage, j'ai ceci (ce que je crois est assez standard et inintéressant): xxx pré>

sauf si je commente l'appel à __ libc_init_array () code>, je reçois Erreur suivante de la liaison: P>

arm-none-eabi-g++ -nostartfiles -mthumb -mcpu=cortex-m4 -TC:/Users/mark/workspace/stm32_cpp_test/STM32F40x_1024k_192k_flash.ld -gc-sections -Wl,-Map=test_rom.map,--cref,--no-warn-mismatch -o stm32_cpp_test "system\\syscalls.o" "system\\startup_stm32f4xx.o" "system\\mini_cpp.o" "system\\cmsis\\system_stm32f4xx.o" main.o 
d:/utils/yagarto/bin/../lib/gcc/arm-none-eabi/4.7.2/../../../../arm-none-eabi/lib/thumb/v7m\libg.a(lib_a-init.o): In function `__libc_init_array':
C:\msys\1.0\home\yagarto\newlib-build\arm-none-eabi\thumb\v7m\newlib\libc\misc/../../../../../../../newlib-1.20.0/newlib/libc/misc/init.c:37: undefined reference to `_init'
collect2.exe: error: ld returned 1 exit status


0 commentaires

3 Réponses :


5
votes

Je ne suis pas d'expert, mais:

probablement _Init (le point d'entrée d'exécution normal) fait référence au code qui exécute les tables CTOR et DTOR.

Vous utilisez -Nostartfiles, alors évitez le démarrage standard, et probablement que tout le code de départ est éliminé par --gc-sections. L'appel explicite ajoute une référence à nouveau.

Si ometter --gc-sections ne le résout pas, il peut également s'agir d'une instruction Garder () manquante dans votre script de liaison (intégré) qui conserve le code d'entrée à tout moment ou de votre propre code de démarrage. (startup_ *) doit y référoir


5 commentaires

Donc, si j'ajoutez Void _Init (void) {} ​​à mon code de démarrage, il compile bien. Je me demande ce que cette fonction est censée faire?


_Iil est généralement le point dans le binaire que le système d'exploitation saute si un binaire a été chargé. Une étiquette par défaut pour le point d'entrée plus ou moins. Comment résoudre le problème dépend de la configuration de votre système de chargeur embarqué. Pour moi, cela ressemble à ce que cette boîte à outils n'est pas parfaitement portée.


Je n'ai pas de "système de loader intégré", j'ai écrit le code de démarrage moi-même (ou plus précisément je la copie + collé depuis Internet) ... Ceci est un cortex-m4, et le resethandler est le tout premier ( et seulement) chose exécutée.


Qui quoi où quoi que ce soit. Ce code de démarrage et le système de bibliothèque semblent incompatibles.


Dans mon cas, je devais utiliser -nodefaultlibs pour effectuer les codes C ++ pour STM32 Link sans le "manquant _Init ".



6
votes

question oldish, mais j'ai rencontré un problème similaire et la solution était que Marco Van de Voort indiquée, si vous allez utiliser __ libc_init_array Vous devez omettre le -Nostarfiles Option de liaison, pour inclure les fonctions Normal Libc Init. Réponse en double.

Deuxièmement, je vous suggère d'inclure le drapeau - spécifiques = nano.specs lors de la liaison avec GCC-Bras (je crois que Yargarto est une fourchette ou même juste un précompilisation de la GCC-Bras), comme il Réduit Libc, etc. Consommation du code.


0 commentaires

0
votes

La fonction __ libc_init_array de STDLIB prend soin d'appeler tous les initialisateurs ou C ++ constructeurs, enregistrés sur préinit_array et init_array . Inbetween Preinit et Init, il appelle une fonction externe _Init . Le code semble aussi simple que: xxx

Voir aussi: compréhension le __libc_init_array .

Si un code de démarrage personnalisé est implémenté, il est nécessaire d'effectuer cette initialisation, soit en liant ' init.o ' ou en mettant en œuvre quelque chose semblable à la snippet de code ci-dessus.

Si au moins dans la construction de ARM-NON-EAUBI Cible ARMV7E avec newlib-nano spécifications, alors les _Init méthode est liée à partir de crti.o et crtn.o , qui ne fournit que quelques talons vides pour _Init et < em> _fini . J'ai fait des recherches à travers tous les autres objets STDLIB pour ARM-Aucun-EAUBI et n'a trouvé aucun autre objet qui ajoutera des sections à .init , qui serait obsolète de toute façon. Voici quelques démontage de crti.o et crtn.o : xxx

si quelqu'un veut utiliser __ libc_init_array En combinaison avec l'option de liaison Nostartfiles pour cette cible de bras spécifique, il serait acceptable de fournir une méthode de talon _Init pour laisser passer la liaison, comme long Comme aucun autre code d'initialisation n'est émis à la section .init , autre que celui de crti.o et crtn.o . Un talon pourrait ressembler à: xxx

Les fonctions spéciales _Init et _fini sont des constructeurs de gauche historiques aux constructeurs de contrôle et destructeurs. Cependant, ils sont obsolètes et leur utilisation peut entraîner des résultats imprévisibles. Aucune bibliothèque moderne ne devrait utiliser plus ces éléments et utiliser les attributs de la fonction GCC constructeur et destructor , qui ajoutent des méthodes à ces tables à l'intérieur .preinit_array < / em>, .init_array et fini_array sections.

S'il est connu qu'il y avait un code d'initialisation émis à . / em> (même si cela est obsolète aujourd'hui), une fonction _Init (Void) doit être fournie, qui exécutera ce code d'initialisation en appelant l'adresse de démarrage du .init. / em> section.


0 commentaires