305 | | |
306 | | |
307 | | == A3. Chaîne de compilation |
| 304 | 1. Savez-vous à quoi sert le mot clé `volatile` ? Nous n'en avons pas parlé en cours, mais c'est nécessaire pour les adresses des registres de périphérique, une idée ... ? |
| 305 | {{{#!protected ------------------------------------------------------------------------------------ |
| 306 | ''''''''''''''' |
| 307 | * `volatile` permet de dire à `gcc` que la variable en mémoire peut changer à tout moment, elle est volatile. Ainsi quand le programme demande de lire une variable `volatile` le compilateur doit toujours aller la lire en mémoire. Il ne doit jamais chercher à optimiser en utilisant un registre afin de réduire le nombre de lecture mémoire (load). De même, quand le programme écrit dans une variable `volatile`, cela doit toujours provoquer une écriture dans la mémoire (store). |
| 308 | * Ainsi, les registres de périphériques doivent toujours être directement lus ou écrits à chaque fois que le programme le demande, parce que c'est justement ces lectures et ces écritures qui commandent le périphérique. |
| 309 | ''''''''''''''' |
| 310 | }}} |
| 311 | |
| 312 | |
| 313 | |
| 314 | == A3. Compilation |
| 315 | |
315 | | $ objdump |
316 | | 1. Le fichier « ldscript » décrit l'espace d'adressage et la manière de remplir les sections dans le programme exectutable. Quelle étape dans la chaîne de compilation a besoin de cette description ? |
317 | | Les variables déclarées externes ne sont évidemment pas mise dans la section `.data` du fichier objet en sortie et les appel au fonction sont codés par des `jal ?` puisque le code des fonctions n'est pas là. Ce sera ré |
| 323 | * `objdump -D file.o > file.o.s` ou `objdump -D bin.x > bin.x.s` |
| 324 | - Appel du désassembleur prend les fichiers binaires (`.o` ou `.x`) pour retrouver le code produit par le compilateur à des fins de debug ou de curiosité. |
| 325 | |
| 326 | **Questions** |
| 327 | 1. Le fichier `kernel.ld` décrit l'espace d'adressage et la manière de remplir les sections dans le programme exécutable. |
| 328 | {{{#!c |
| 329 | __tty_regs_map = 0xd0200000 ; |
| 330 | __boot_origin = 0xbfc00000 ; |
| 331 | __boot_length = 0x00001000 ; |
| 332 | __ktext_origin = 0x80000000 ; |
| 333 | __ktext_length = 0x00020000 ; |
| 334 | [... question 1 ...] |
| 335 | __kdata_end = __kdata_origin + __kdata_length ; |
| 336 | |
| 337 | MEMORY { |
| 338 | boot_region : ORIGIN = __boot_origin, LENGTH = __boot_length |
| 339 | ktext_region : ORIGIN = __ktext_origin, LENGTH = __ktext_length |
| 340 | [... question 2 ...] |
| 341 | } |
| 342 | |
| 343 | SECTIONS { |
| 344 | .boot : { |
| 345 | *(.boot) |
| 346 | } > boot_region |
| 347 | [... question 2 ...] |
| 348 | .kdata : { |
| 349 | *(.*data*) |
| 350 | } > kdata_region |
| 351 | } |
| 352 | }}} |
| 353 | 1. ? |
| 354 | {{{#!protected ------------------------------------------------------------------------------------ |
| 355 | ''''''''''''''' |
| 356 | * |
| 357 | ''''''''''''''' |
| 358 | }}} |
| 359 | - Le fichier commence par la déclaration des variables donnant des informations sur les adresses et les tailles des régions de mémoire. Ces symboles n'ont pas de type et ils sont visibles de tous les programmes c, il faut juste leur donner un type pour le compilateur puisse les exploiter, c'est ce que nous avons fait pour `extern volatile struct tty_s __tty_regs_map[NTTYS]` |
| 360 | - Le fichier contient ensuite la déclaration des régions qui vont être remplies par les sections trouvées dans les fichiers objets. |
| 361 | - Enfin le fichier contient comment sont remplies les régions avec les sections |
| 362 | |
| 363 | Les variables déclarées externes ne sont évidemment pas mises dans la section `.data` du fichier objet en sortie et les appels aux fonctions sont codés par des `jal ?` puisque le code des fonctions n'est pas là. Ce sera ré |