Le symbole faible peut-il être résolu entre les bibliothèques lors de la liaison?

Mon scénario concerne la compilation croisée sur un Arduino Due (cible ARM), mais je suppose que c’est un problème générique de symbole faible C.

Je souhaite diviser mon micrologiciel en 3 parties: 1. La bibliothèque de matériel (CMSIS, Middleware) -> libHardware.a 2. Bibliothèque en temps réel du système d’exploitation -> libOS.a 3. Code de l’application -> Output.elf lié à ci-dessus.

l’implémentation référencée CMSIS a déclaré ce qui suit:

void SysTick_Handler ( void ) __atsortingbute__ ((weak, alias("Dummy_Handler"))); // ...and a few dozen IRQ handler hook skipped for brevity 

L’idée de la conception de CMSIS est de faire en sorte que le code d’application implémente et traite certaines IRQ de manière sélective.

Rapports nm pour libHardware.a

 startup_sam3xa.o: 00000000 W SysTick_Handler ... 

Et dans mon scénario, j’aimerais implémenter ces gestionnaires IRQ dans libOS.a.

J’implémente void SysTick_Handler (void), rapports nm:

 cortex_handlers.o: 00000000 T SysTick_Handler .... 

Ensuite, je les relie, ce qui revient essentiellement à

 g++ -o app.elf -Wl,--start-group app.o libHardware.a libOS.a -Wl,--end-group 

(Le groupement est nécessaire car le système d’exploitation dépend de la fonction matérielle de bas niveau. Et le matériel doit appeler la fonction IRQ / main () fournie par le système d’exploitation.)

rapports nm:

 ... 00080124 W SysTick_Handler ... 

C’est encore faible! Je m’attends à ce qu’il utilise le symbole fort défini dans libOS.a. À la fin, SysTick n’est pas géré, ce qui conduit bien sûr à un échec catastrophique.

D’autre part, si je ne les déclare pas comme étant faibles dans libHardware / startup_sam3xa.c, tout fonctionne correctement. Si je choisis d’implémenter SysTick_Handler dans app / app.c, le lien est également très fort.

Ma question est donc la suivante: comment libOS.a pourrait-il implémenter le gestionnaire faible défini dans libHardware.a? Ou quelle serait la meilleure pratique dans ces scénarios de développement de microprogrammes?

Lorsque vous définissez SysTick_Handler dans cortex_handlers.c, il définit le point d’entrée normal. Mais le symbole faible ne sera écrasé que lorsque l’éditeur de liens obtiendra une demande de liaison du fichier object spécifique (à partir de libOS.a).

LibHardware.a définit généralement la table de vecteurs Interrupt dans laquelle le SysTick_Handler est référencé. C’est le seul pointeur de ce nom. (Pour ARM, il s’agit simplement d’une entrée dans la table des vecteurs.) La même bibliothèque fournit déjà un symbole faible. Par conséquent, l’éditeur de liens ne recherche plus ces symboles. Lorsque vous souhaitez écraser le symbole dans cortex_handlers.c, vous devez référencer tout symbole de ce fichier, ce qui oblige l’éditeur de liens à utiliser cortex_handlers.o . Cela lancera le symbole faible.

 // cortex_handlers.c void SysTick_Handler() { } int link_my_cortex_handlers_file; 

Référencez juste quelque part le symbole link_my_cortex_handlers_file .

Grâce à la réponse de harper ci-dessus, j’ai pu découvrir qu’Arduino avait résolu ce problème sur le Due en déplaçant toutes les définitions faibles de startup_sam3xa.c dans leur fichier cortex_handlers.c, de sorte que les faibles définitions appartenaient à “l’OS” au lieu de le matériel (en utilisant la langue de l’OP).

Une autre solution consiste à garder le source de votre gestionnaire (ou quoi que ce soit) séparé, mais à l’inclure dans un fichier source qui doit toujours être référencé lors de l’utilisation de la bibliothèque (si votre bibliothèque possède une telle fonctionnalité et n’est pas optionnelle.). Si vous utilisez une unité de fichier object .o: si un fichier object contient un symbole qui résout un symbole non résolu lorsque l’éditeur de lien effectue un passage sur les unités .o de l’archive ( et l’éditeur de liens peut effectuer de nombreuses passes), l’éditeur de liens place tous les symboles du fichier object dans le fichier binary lié, en résolvant les symboles non résolus et en remplaçant les définitions faibles. L’ordre des bibliothèques dans la commande de lien est important et vous aurez peut-être besoin qu’une bibliothèque apparaisse deux fois dans la commande de lien. L’ensemble des archives de l’éditeur de liens peut également résoudre le problème. Ma réponse est succincte, mais pourrait être fausse.