Comment récupérer l’adresse de fin de mon code

J’écris un système d’exploitation en temps réel à partir de zéro pour un projet de cours. Je souhaite connaître l’adresse de fin de mon code après l’avoir téléchargée sur la puce, car je prévois d’utiliser la mémoire disponible pour l’espace de stack et je dois m’assurer de ne pas écraser le code existant.

J’ai entendu parler de la variable __end fournie par GCC, c’est la fin du code, mais je ne sais pas du tout ce que signifie __end et comment l’utiliser dans mon code. Quelqu’un pourrait-il expliquer un peu ou fournir des liens vers certains documents, parce que je ne pouvais pas google __end?

Merci beaucoup.

Comme Adam Rosenfeld le fait remarquer, vous devez utiliser le fichier de contrôle de l’éditeur de liens pour définir un ou plusieurs symboles situés précisément au bon endroit.

Pour gcc et binutils, vous utiliserez la syntaxe de script de l’éditeur de liens de ld. Reportez-vous au manuel de LD pour tous les détails que je laisse ici. C’est un peu opaque, mais vous devriez y consacrer un peu de temps si vous souhaitez consacrer beaucoup d’efforts au monde intégré. Cela vous rapportera.

Dans le script de l’éditeur de liens, vous souhaitez définir un symbole avant votre segment .text et un après.

Adam mentionne la syntaxe PROVIDE() , qui fonctionnera. Mais vous n’avez peut-être pas besoin d’envelopper la définition dans PROVIDE si vous pouvez garantir que votre nom est unique. Notez que c’est une garantie que vous devez pouvoir faire, sinon vous risquez beaucoup de confusion par la suite.

Dans mon script, j’utilise simplement quelque chose comme:

 __SDRAM_CS1 = 0x10000000; 

pour définir le symbole avec une adresse constante qui renvoie (dans ce cas) à l’emplacement, nous avons décidé que le contrôleur SDRAM mappera la mémoire SDRAM et le déclarera comme suit dans le CI:

 extern unsigned char __SDRAM_CS1[]; 

afin qu’il puisse être utilisé dans un code qui a besoin de savoir où se trouve réellement la SDRAM.

Pour un symbole localisant la fin du segment .text, vous auriez quelque chose comme ceci dans le script de l’éditeur de liens

 SECTIONS { ... .text { _start_text = .; *(.text); ... _end_text = .; } ... } 

et déclarer les symboles de début et de fin comme

 extern unsigned char _start_text[]; extern unsigned char _end_text[]; 

en C. Ensuite, l’adresse de début est simplement _start_text et la longueur en octets du segment de texte est _end_text - _start_text .

Notez que j’ai omis beaucoup de détails. Vous avez probablement des sections nommées autres choses que .text qui doivent être traitées comme si elles se trouvaient dans le segment de texte. Un bon exemple est celui des données en lecture seule qui peuvent souvent être localisées dans le segment de texte en toute sécurité car elles sont connues pour être const et dans un système intégré, vous préféreriez ne pas les copier dans de la RAM précieuse si vous n’y êtes pas obligé. En outre, les initialiseurs du segment de données et les listes de constructeurs d’objects globaux générées en interne sont tous situés près du segment de texte.

Que vous intégriez de telles choses dans la taille de votre image est une décision de conception à prendre après avoir compris à quoi elles servent.

Vous pouvez utiliser un script de l’éditeur de liens. Dans votre code C, déclarez:

 // call this whatever you want; the linker will fill this in with the address // of the end of code extern uint32_t endOfCode; 

Ensuite, dans votre script de l’éditeur de liens, ajoutez ce qui suit immédiatement après la définition de la section .text :

 PROVIDE(endOfCode = .); 

Je ne connais pas très bien les scripts de l’éditeur de liens et je ne peux donc pas fournir un exemple complet et fonctionnel. Vous devrez prendre le script de l’éditeur de liens par défaut (que je ne sais pas comment l’obtenir) et le modifier comme ci-dessus, puis utilisez l’option -T de l’éditeur de liens pour le spécifier. Bonne chance!

Au lieu de le mettre à la fin, pourriez-vous simplement déclarer un grand tableau statique et ne pas l’utiliser, sans compilateur ni astuce de l’éditeur de liens?

Eh bien, je ne connais pas très bien GCC, mais vous pouvez peut-être faire quelque chose comme ceci:

 long foo() { int anything[0]; return *(&anything - 1); } long endOfProgram() { return stackPointer(); } 

Ce que j’essaie de faire ici est:

  1. Appelez endOfProgram ()
  2. endOfProgram appelle foo, l’adresse de endOfProgram est donc poussée dans la stack.
  3. Poussez n’importe quoi [0] sur la stack de foo.
  4. Saisissez l’emplacement de l’élément juste avant l’adresse de quoi que ce soit, qui devrait être l’emplacement de mémoire de endOfProgram.

Certaines de mes syntaxes sont peut-être fausses, mais j’espère que vous pourrez comprendre l’essentiel de ce que j’essaie de faire.

MODIFIER:

… ou saisissez simplement la valeur d’un pointeur de fonction sur endOfProgram. Je suppose que cela fonctionnerait aussi.