10
votes

Constructeur mondial de l'appel pas dans la section .Init_array

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: xxx

Je le compile comme ceci: xxx

Quand je regarde la section .init_array avec Objdump, il montre que le .init_section a une taille zéro.

I Obtenir un symbole nommé _z41__static_initialization_and_destruccy_0II . 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.

Pourquoi un pointeur n'est-il pas ajouté à ce symbole dans le fichier .init_section?


2 commentaires

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.


5 Réponses :


3
votes

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.


2 commentaires

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



2
votes

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 (en arracher-nul-nul - à partir de CODESRercery.) Ou une autre fonction ( __ (code) Si vous utilisez Linux G ++). () Cela devrait être appelé au démarrage ou au principal () . Voir aussi Ce lien .


0 commentaires

27
votes

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 .init_array code> Taille de la section de 4: p> xxx pré>

Quand je regarde Le contenu de la section, il contient simplement 0: p> xxx pré>

Cependant, il existe également une section de relocalisation qui la définit correctement vers _global__sub_i_foo code>: p> xxx pré>

en général, .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>

parce que j'utilise code> -NOSTDLIB code> dans ma construction, i Impossible d'utiliser CodeSourcery's __ 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> xxx pré>

__ 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 = .;
}


4 commentaires

Je ne sais pas si les choses ont changé depuis févr. 2013, mais j'ai constaté que je devais traiter __ init_array_start et __ init_array_end 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 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) (); } .


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?



2
votes

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


2 commentaires

Beaucoup de nombreux algorithmes d'élimination naïfe "Code Dead" éliminent non référencées Sections / sections qui ne peuvent pas contribuer à Sortie accessible ... 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 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 ...



4
votes

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


0 commentaires