J'essaie d'ajouter un support de constructeur mondial sur une cible intégrée (ARM CORTEX-M3).
Disons que j'ai le code suivant: Je le compile comme ceci: p> Quand je regarde la section .init_array avec Objdump, il montre que le .init_section a une taille zéro. p> I Obtenir un symbole nommé Pourquoi un pointeur n'est-il pas ajouté à ce symbole dans le fichier .init_section? P> p> _z41__static_initialization_and_destruccy_0II code>.
Lorsque je désassemblable le fichier d'objet, je vois que la construction globale est effectuée dans le symbole static_initialization_and_d_destructifier. P>
5 Réponses :
Vous avez uniquement produit un fichier d'objet, en raison de l'argument -c à GCC. Pour créer la section .init, je pense que vous devez lier cela .O dans une bibliothèque exécutable ou partagée. Essayez de supprimer l'argument -c et de renommer le fichier de sortie sur "FOO", puis vérifiez l'exécutable résultant avec le désassembleur. P>
Quand je fais que j'ai toujours le même problème.
Ok, donc avec la mise en garde que je connais essentiellement rien sur le bras, je dirais que cela signifie que vous avez une autre étape à effectuer dans la mise en œuvre de la mise en œuvre de la CTOR mondiale et des dtors pour le bras. Le fait que vous obteniez le z41 i> ... Symbole est encourageant, car cela me suggère que le fichier .O est correct. Mais clairement, quelque chose ne se produit pas au temps de liaison. Sur X86 GCC, un processus d'horaire de liaison appelé collect2 gère la fusion de tous les différents constructeurs statiques dans la section .init avant de remettre à LD (ou quelque chose comme ça). Je pense que le support de la liaison est votre prochaine étape.
Si vous regardez soigneusement _z41__static_initialization_and_destruccy_0ii (code> serait appelé à l'intérieur du constructeur mondial. Quelle inturn serait liée dans
.init_array code> (en
arracher-nul-nul - code> à partir de CODESRercery.) Ou une autre fonction (
__ (code) code> Si vous utilisez Linux G ++). () Cela devrait être appelé au démarrage ou au
principal () code>.
Voir aussi Ce lien . P>
Je sais que cela a été presque deux ans que cette question a été posée, mais je devais juste comprendre la mécanique de l'initialisation nue-métal C ++ avec GCC moi-même, j'ai donc pensé partager les détails ici. Il s'avère que beaucoup d'informations obsolètes ou déroutantes sur le Web. Par exemple, l'enveloppe code> Collect2 CODE> OFT ne semble pas être utilisée pour les cibles de l'elfe du bras, car sa prise en charge de la section arbitraire permet l'approche décrite ci-dessous.
Premier, quand je compile le code ci-dessus avec La ligne de commande donnée à l'aide de Sourcery CodeBench Lite 2012.09-63, je vois le bon Quand je regarde Le contenu de la section, il contient simplement 0: p> Cependant, il existe également une section de relocalisation qui la définit correctement vers en général, parce que j'utilise code> -NOSTDLIB code> dans ma construction, i Impossible d'utiliser CodeSourcery's .init_array code> Taille de la section de 4: p>
_global__sub_i_foo code>: p>
.init_array code> points à tous vos
_global__sub_i_xxx code> initialisateur, chacun appelle sa propre copie de
_Z41__STATICTATIC_INITIALIATION_AND_DESTRACUCUN_0III CODE> (Oui, il est multiplié), qui appelle le constructeur avec les arguments appropriés. P>
__ libc_init_array code> à exécuté ute le
.init_array code> pour moi, j'ai donc besoin d'appeler les initialiseurs statiques moi-même: p>
__ init_array_start code> et
et
__ init_array_end code> sont définis par le script de liaison: P>
. = ALIGN(4);
.init_array :
{
__init_array_start = .;
KEEP (*(.init_array*))
__init_array_end = .;
}
Je ne sais pas si les choses ont changé depuis févr. 2013, mais j'ai constaté que je devais traiter __ init_array_start code> et
__ init_array_end code> en tant que pointeurs de fonction, pas des pointeurs à la fonction Pointeurs: TypeDef Void ( initfunc) (vide); externe initfunc __init_array_start; externe initfunc __init_array_end; Initfunc i> pfunc = & __ init_array_start; pour (; pfunc <& __ init_array_end; ++ pfunc) {(* pfunc) (); }
@Timma, il y a quelques erreurs dans votre code. Il compile lorsqu'il est remplacé par Typedef Void (* initfunc) (void); externe initfunc __init_array_start; externe initfunc __init_array_end; Initfunc * pfunc = & __ init_array_start; pour (; pfunc <& __ init_array_end; ++ pfunc) {(* pfunc) (); } code>.
Question Comprendre le __libc_init_array fournit un code plus clair qui utilise un tableau de pointeurs à fonctionner . Et il fonctionne.
@lorcap ressemble à mes astérisques d'interpréter comme marquage. Comme vous pouvez le constater, une partie de mon texte est en italique. Cela se trouve tout à fait être exactement là où j'aurais des astérisques tapé. Désolé pour ça, je ne sais pas comment je ne l'ai pas vu. Peut-être y a-t-il eu une mise à jour pour commenter le formatage?
J'ai eu un problème similaire où mes constructeurs n'étaient pas appelés (NRF51822 Cortex-M0 avec GCC). Le problème s'est avéré être dû à cet indicateur de liaison:
-Wl,--gc-sections
Beaucoup de nombreux algorithmes d'élimination naïfe "Code Dead" éliminent non référencées i> Sections / sections qui ne peuvent pas contribuer à Sortie accessible i> ... même si elles sont nécessaires pour interrompre les gestionnaires, Structures de données globales statiques, etc. Ce n'est peut-être pas suivi de la façon dont GCC travaille, mais c'est un gotha commun. Essayez également l'optimisation du temps de liaison -flto -o4 code> sous GCC et CLIG pour voir ce qui se passe.
Il supprime le code mort. S'il y a un objet global que personne ne se réfère jamais, son constructeur appelle le code mort ou non? Pratiquement personne n'appellerai jamais dans cet objet ...
TIMMMM,
Je viens d'avoir le même problème sur le NRF51822 et je l'ai résolu en ajoutant de la garde () autour de quelques lignes du stock Nordic Fichier: P>
KEEP(*(SORT(.init_array.*))) KEEP(*(.init_array))
Vous ne pensez pas que GCC est suffisamment intelligent pour 1) voir que la valeur est 100, ou 2), voir que la valeur est juste incrémentée mais jamais utilisée?
@Bo Persson: C'est pourquoi j'ai ajouté l'option -O0. GCC n'il peut-il pas optimiser cela.