TacOS-team / tacos

Système d'exploitation / Operating System
GNU General Public License v3.0
9 stars 4 forks source link

[Divers] Compilation avec CLANG #28

Closed MaximeCheramy closed 9 years ago

MaximeCheramy commented 13 years ago

clang fourni de meilleurs messages d'erreurs, et j'imagine qu'être compatible avec 2 compilateurs différents devrait nous permettre de catcher de nouveaux bugs (un peu comme quand on exécute avec des machines virtuelles différentes). C'est donc une bonne chose de pouvoir compiler avec clang.

Le problème est que le binaire généré ne veut pas se charger... !

Ancien ticket : https://www.etud.insa-toulouse.fr/redmine/issues/39

MaximeCheramy commented 10 years ago

À l'aide de mbchk (modifié par mes soins pour étendre la zone de recherche) qui fait une recherche bête du code magique, on voit qu'il trouve le multiboot à la position 0x8004 : The Multiboot header is found at the offset 32772.

Au lieu d'être dans les premiers 8ko analysés par grub... Donc il faudrait arriver à déplacer le multiboot. Mes essais n'ont pas été concluants et je ne sais pas pourquoi.

MaximeCheramy commented 10 years ago

En jouant sur l'alignement dans le fichier linked.ld, j'ai réussi à le faire booter. Par contre le système reboot direct. J'ai commité mes modifs puisque visiblement cela n'affecte pas négativement la version gcc.

MaximeCheramy commented 9 years ago

Profitant d'une petite insomnie, j'ai recompilé avec clang. J'ai peut-être identifié le problème : les plantages se faisaient lors de divisions avec des float. En remplaçant ces calculs par des calculs identiques mais en division entière, j'ai pu aller plus loin dans l'exécution. Mais je plante encore sur une exception Opcode invalide. En regardant le code assembleur, je me suis également aperçu que le code généré par clang utilisait des registres SSE. Or nous ne les gérons pas à ma connaissance.

MaximeCheramy commented 9 years ago

Je pense avoir réglé ce premier problème (j'ai peut être zappé des Makefile), par contre le kprintf foire. J'ai l'impression qu'il n'arrive pas à gérer les arguments variables (adresse du second argument non accessible).

MaximeCheramy commented 9 years ago

Actuellement le handler d'interruption ne marche pas correctement encore une fois à cause de la gestion du passage d'arguments. clang utilise le registre eax pour le passage d'argument ce qui fait que le premier argument pushé manuellement sur eax est écrasé par celui de l'appel de la routine. Alors bon, vu que cet argument n'est pas utilisé, il suffit de pusher le premier argument (au niveau du code asm qui fait le call) et ça semble marcher, mais je maitrise mal les conséquences.

NicolasFloquet commented 9 years ago

Je suis pas sur de comprendre ce que tu propose, mais je sens que ça a effectivement des conséquences :D

MaximeCheramy commented 9 years ago

Actuellement on appelle le handler d'interruption avec son numéro d'interruption alors qu'on en fait rien (on sait bien que la fonction syscall_entry ne sera appelé que pour un certain numéro d'interruption). Et le problème c'est que clang utilise eax pour stocker ce numéro ce qui écrase ce qu'on avait mis dans eax pour le syscall. Donc une solution crado c'est de mettre en premier argument ce qui était dans eax, comme ça il écrase avec la même valeur. Ça semble marcher mais bon... voilà quoi :D. Autre solution : virer l'argument mais tu t'en sers indirectement pour trouver l'adresse de la frame.

NicolasFloquet commented 9 years ago

Alors pour mettre les choses à plat, la façon dont sont appelés les handlers d'interruption est commune à toutes les interruptions, et pas seulement syscall_entry. Du coup si tu veux faire ça, il va falloir soit le faire pour toutes les interruptions ce qui n'est pas souhaitable vu que dans certains cas on peut être amenés à se servir du numero d'interruption, soit faire un cas particulier pour les syscall, mais ça ne me parait pas souhaitable, parce que ça reviendra à dupliquer tout https://github.com/TacOS-team/tacos/blob/master/kernel/interrupts_wrappers.S juste pour contourner un manque de maitrise.

Personnellement, je pencherais plutôt vers l'utilisation d'attribut permettant de maitriser la convention d'appel quand c'est nécessaire (http://clang.llvm.org/docs/AttributeReference.html#calling-conventions)

MaximeCheramy commented 9 years ago

Je suis d'accord, idéalement il faudrait juste que ça se comporte pareil pour les deux, le reste c'est du workaround. J'ai aussi tenté l'attribut mais c'était sans effet (me suis peut être loupé quelque part).

Dans tous les cas, j'avais un peu mis de côté ce ticket là... Je suis content que le kernel boot et arrive à afficher des choses sur la liaison série, c'est le principal :D.

MaximeCheramy commented 9 years ago

Je viens d'y jeter un nouveau coup d'oeil et j'arrive enfin à faire tourner TacOS après une compilation avec clang (et c'est plus rapide à première vue qu'avec gcc). En fait, je crois que je n'avais pas tout à fait compris le problème. Le problème était simplement que clang écrasait eax dans syscall_entry avant que je ne lise son contenu. Du coup j'ai pushé les registres dans le wrapper de l'interruption, le seul endroit où on est sûr de ce qui se fait vraiment.

Je n'ai pas commité sur master pour 2 raisons :

J'ai pushé sur cette branche pour que tu comprennes ce que j'ai fait.

Edit: bon en fait mon commit introduit d'autres bugs. J'ai pété l'accès à la frame mais visiblement ça empêche pas l'OS de tourner, c'est assez magique. De ce que j'en vois, sous clang la frame est jamais bonne ça change rien, sous gcc elle était bonne mais ne l'est plus assez logiquement (j'empile plus de choses et j'ai oublié d'en tenir compte). Je pourrais corriger pour gcc mais la frame resterait mauvaise avec clang donc mauvaise solution.