IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Programmation d'OS Assembleur Discussion :

Triple fault sur implémentation de la GDT


Sujet :

Programmation d'OS Assembleur

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé Avatar de BioKore
    Homme Profil pro
    Dresseur d'Alpaga
    Inscrit en
    Septembre 2016
    Messages
    300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Dresseur d'Alpaga

    Informations forums :
    Inscription : Septembre 2016
    Messages : 300
    Par défaut Triple fault sur implémentation de la GDT
    Bonjour à tous,

    Je suis actuellement, pour raisons ludique et pédagogique, de développer un petit kernel sans autre ambition que d'en savoir plus sur la manière dont fonctionnent ces derniers (et développer un peu mes compétences en programmation). Pour "simplifier" la chose, j'ai choisi de booter avec GRUB dans un premier temps ; je me pencherais sur ce sujet plus tard.
    Je tourne sous Linux, compile avec GCC et AS, link avec LD, le tout dans un makefile approprié. Mes essais se font sous virtual-box.

    Mon code est écrit en C et ASM (GNU/AT&T), et je m'inspire des différentes sources d'infos que je trouve ça et là. Je précise aussi que mes cours d'assembleur et architecture sont assez lointains et se faisaient plutôt sous la forme INTEL (MASM/NASM).

    Mon problème est le suivant : impossible de charger les segments code, data ou encore stack (CS,DS,SS) lors-que je souhaite charger la GDT.
    J'en ai donc déduit que cela venait très certainement de la forme de ma gdt, mais je ne trouve pas mon erreur.

    Code de formation des descripteurs de segment et de la GDT Registres (*.h et *.c) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
     
    #ifndef __GDT_H
    #define __GDT_H
     
    #include "types.h"
     
    #define GDTSIZE 0xFF
    #define GDTBASE 0x0
     
    //typedef struct segDesc segDesc;
    //typedef struct segPtr segPtr;
     
    //segment descriptor
    struct segDesc {
        uint16_t limit_lb;
        uint16_t base_lb;
        uint8_t base_hb;
        uint8_t type;
        uint8_t granul;         //sinon uint8_t limit:4 et uint8_t flags:4
        uint8_t base_vhb;
     
    } __attribute__((packed));
     
    //Global Register Descriptor Table
    struct segPtr {
        uint16_t limit;     //uint32_t limit();
        uint32_t base;      //uint32_t base();
    }__attribute__((packed));
     
    //déclaration des segment descriptors...
    struct segDesc tSeg[3];
     
    //déclaration des seg registers.
    struct segPtr gdtr;
     
    // initialisation des segments (code, data, stack)
    void initSegmentDesc(uint8_t i, uint32_t base, uint32_t limit, uint8_t type, uint8_t flags_hb);
     
    //init de la gdt globale avec registres
    void init_gdt(void);
     
    extern void gdt_load(void);    //fonction présente dans le loader.s
     
     
     
     
    #endif
    ...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
     
    void initSegmentDesc(uint8_t i, uint32_t base, uint32_t limit,
                         uint8_t type, uint8_t flags)
    {
        tSeg[i].limit_lb = (limit & 0xFFFF);
        tSeg[i].base_lb = (base & 0xFFFF);
        tSeg[i].base_hb = (base >> 16) & 0xFF;
        tSeg[i].type = type;
        tSeg[i].granul = (limit >> 16) & 0x0F;          //tSeg[i].limit = (limit >> 16) & 0x0F;
        tSeg[i].granul |= (flags & 0xF0);               //tSeg[i].flags = (flags & 0xF);
        tSeg[i].base_vhb = (base >> 24) & 0xFF;
     
        return;
    }
     
    void init_gdt(void)
    {  
     
        initSegmentDesc(0, 0, 0, 0, 0);                     //null
        initSegmentDesc(1, 0, 0xFFFFFFFF, 0x9A, 0xCF);      //code
        initSegmentDesc(2, 0, 0xFFFFFFFF, 0x92, 0xCF);      //data
        //initSegmentDesc(3, 0x0, 0x0, 0x96, 0x0D);         //stack
     
        gdtr.limit = (sizeof(struct segDesc)*3) - 1;
        gdtr.base = (uint32_t)&tSeg;
     
        //gdtr.limit = GDTSIZE*8;
        //gdtr.base = GDTBASE;
     
        //memcpy((uint8_t*)gdtr.base, (uint8_t*)tSeg, gdtr.limit);
     
        gdt_load();        // <-- bug !!!
    Le sections commentées sont les différents essais que j'ai fait en m'inspirant de ce que j'ai trouvé sur le net.

    loader.s, avec la fonction gdt_load :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
     
    .set MAGIC, 0x1badb002	#adresse où doit commencer le kernel (par grub)
    .set FLAGS, (1<<0 | 1<<1)   #init à 0x0 marche aussi...
    .set CHKSUM, -(MAGIC + FLAGS)
     
    .section .multiboot
        .long MAGIC
        .long FLAGS
        .long CHKSUM
     
    .section .text
        .extern kernelStart
        .extern kerr
        .extern gdtr
        .extern idtP
        .global loader
        .global gdt_load
        .global idt_load
     
        loader:
            mov $kernel_stack , %esp
            push %eax
            push %ebx
            movl %cr0, %eax
            or $1, %eax
            movl %eax, %cr0             #passage ne mode protégé... useless.
            call kernelStart
     
        gdt_load:
            cli                         # <-- ne change rien
            lgdtl (gdtr)
            movw $0x10, %ax
            movw %ax, %ds                #data segment
            movw %ax, %es                #extra segment
            movw %ax, %fs                #gp     -   general purpose
            movw %ax, %gs                #gp     -   general purpose
            ljmp $0x08, $next            #colle le cs à 0x08
        next:
            movw $0x18, %ax
            movw %ax, %ss               #colle le ss à 0x18
            movl $0x20000, %esp
            ret
     
        idt_load:
            lidt (idtP)
            ret
     
        _stop:
            cli
            hlt
            jmp _stop
     
     
    .section .bss
        .space 4096     #Mbi
     
        kernel_stack:
    Vous remarquerez que j'ai essayé de forcer le passage en mode protégé (bien qu'inutile car GRUB passe la main sous ce mode). J'ai aussi essayé de limiter les potentiels interupts lors du chargement de la GDT (cli). Celà fait presque une semaine que je refais mon code dans tous les sens donc je ne peut pas vous faire la liste de ce que j'ai testé.

    Voilà mon "kernel" se lance, m'affiche mes deux lignes de présentations et.. TRIPLE_FAULT....

    Quelqu'un voit d'où vient mon erreur ? Je commence à vraiment sécher...

    Merci beaucoup d'avance !

  2. #2
    Responsable Systèmes


    Homme Profil pro
    Gestion de parcs informatique
    Inscrit en
    Août 2011
    Messages
    18 358
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Gestion de parcs informatique
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Août 2011
    Messages : 18 358
    Par défaut
    Pour commencer : sais tu ce qu'est un triple fault ? ça te donnera une piste pour chercher.

    Il te faut débuguer pour trouver le prob. Je te conseilles l'utilisation de Bochs.
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur le P2V, mon article sur le cloud
    Consultez nos FAQ : Windows, Linux, Virtualisation

  3. #3
    Membre éclairé Avatar de BioKore
    Homme Profil pro
    Dresseur d'Alpaga
    Inscrit en
    Septembre 2016
    Messages
    300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Dresseur d'Alpaga

    Informations forums :
    Inscription : Septembre 2016
    Messages : 300
    Par défaut Merci mais...
    Bonjour, et merci pour cette réponse, mais, cela ne m'aide pas beaucoup plus.

    Le triple Fault intervient en général lors d'un buffer overflow sur l'IDT (ou écriture sur son segment). Ok, mais à mon niveau l'IDT n'est pas encore initialisée donc je ne comprends pas.

    En ce qui concerne l'utilisation de Bochs, j'ai cru voir que les "logs" étaient un peu plus clairs que ce que je retrouve sur VirtualBox effectivement ; je vais essayer d'utiliser cet outil pour voir.

    En ce qui concerne le debugger j'ai bien pensé à GDB mais je ne suis pas sure de voir comment faire avec cet outil pour un "OS". Une idée d'un soft sur lequel je pourrais m'appuyer ?


    Merci !

  4. #4
    Responsable Systèmes


    Homme Profil pro
    Gestion de parcs informatique
    Inscrit en
    Août 2011
    Messages
    18 358
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Gestion de parcs informatique
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Août 2011
    Messages : 18 358
    Par défaut
    Le triple Fault intervient en général lors d'un buffer overflow sur l'IDT (ou écriture sur son segment). Ok, mais à mon niveau l'IDT n'est pas encore initialisée donc je ne comprends pas.
    ça vient aussi sur une exception non gérée

    Bochs intègre un débogueur.
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur le P2V, mon article sur le cloud
    Consultez nos FAQ : Windows, Linux, Virtualisation

  5. #5
    Membre éclairé Avatar de BioKore
    Homme Profil pro
    Dresseur d'Alpaga
    Inscrit en
    Septembre 2016
    Messages
    300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Dresseur d'Alpaga

    Informations forums :
    Inscription : Septembre 2016
    Messages : 300
    Par défaut Ok
    Merci pour ces infos, je vais voir ce que je peux faire... Aussi-tôt que j'aurais réussi à configurer Bochs.

    Je vous tiens au courant.

  6. #6
    Membre éclairé Avatar de BioKore
    Homme Profil pro
    Dresseur d'Alpaga
    Inscrit en
    Septembre 2016
    Messages
    300
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Dresseur d'Alpaga

    Informations forums :
    Inscription : Septembre 2016
    Messages : 300
    Par défaut
    Bon, je viens de faire un premier essai avec Bochs ; voici ce que j'obtiens avec un grep "cpu" (sinon je fais du 2Go de log par seconde) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
     
    00062680563d[CPU0 ] real mode activated
    00062680570d[CPU0 ] inhibit interrupts mask = 3
    00062680571d[CPU0 ] inhibit interrupts mask = 1
    00062680585d[CPU0 ] interrupt(): vector = 10, TYPE = 4, EXT = 0
    00062680649d[CPU0 ] protected mode activated
    00062680656d[CPU0 ] inhibit interrupts mask = 3
    00062681286d[CPU0 ] inhibit interrupts mask = 3
    00062681290d[CPU0 ] real mode activated
    00062681297d[CPU0 ] inhibit interrupts mask = 3
    00062681298d[CPU0 ] inhibit interrupts mask = 1
    00062681312d[CPU0 ] interrupt(): vector = 10, TYPE = 4, EXT = 0
    00062681374d[CPU0 ] protected mode activated
    00062681381d[CPU0 ] inhibit interrupts mask = 3
    00062827919d[CPU0 ] inhibit interrupts mask = 3
    00062831999e[CPU0 ] check_cs(0x0008): conforming code seg descriptor dpl > cpl, dpl=3, cpl=0
    00062831999d[CPU0 ] exception(0x0d): error_code=0008
    00062831999d[CPU0 ] interrupt(): vector = 0d, TYPE = 3, EXT = 1
    00062831999e[CPU0 ] interrupt(): vector must be within IDT table limits, IDT.limit = 0x0
    00062831999d[CPU0 ] exception(0x0d): error_code=006a
    00062831999d[CPU0 ] exception(0x08): error_code=0000
    00062831999d[CPU0 ] interrupt(): vector = 08, TYPE = 3, EXT = 1
    00062831999e[CPU0 ] interrupt(): vector must be within IDT table limits, IDT.limit = 0x0
    00062831999d[CPU0 ] exception(0x0d): error_code=0042
    00062831999i[CPU0 ] CPU is in protected mode (active)
    00062831999i[CPU0 ] CS.mode = 32 bit
    00062831999i[CPU0 ] SS.mode = 32 bit
    00062831999i[CPU0 ] EFER   = 0x00000000
    00062831999i[CPU0 ] | EAX=00100010  EBX=00010000  ECX=00000000  EDX=00000002
    00062831999i[CPU0 ] | ESP=00102fd4  EBP=00102fe0  ESI=00000000  EDI=00000000
    00062831999i[CPU0 ] | IOPL=0 ID vip vif ac vm RF nt of df if tf sf zf af PF cf
    00062831999i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
    00062831999i[CPU0 ] |  CS:0010( 0002| 0|  0) 00000000 ffffffff 1 1
    00062831999i[CPU0 ] |  DS:0010( 0002| 0|  0) ffffffff ffffffff 1 1
    00062831999i[CPU0 ] |  SS:0018( 0003| 0|  0) 00000000 ffffffff 1 1
    00062831999i[CPU0 ] |  ES:0010( 0002| 0|  0) ffffffff ffffffff 1 1
    00062831999i[CPU0 ] |  FS:0010( 0002| 0|  0) ffffffff ffffffff 1 1
    00062831999i[CPU0 ] |  GS:0010( 0002| 0|  0) ffffffff ffffffff 1 1
    00062831999i[CPU0 ] | EIP=00100035 (00100035)
    00062831999i[CPU0 ] | CR0=0x60000011 CR2=0x00000000
    00062831999i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
    00062831999d[CTRL ] searching for component 'cpu' in list 'bochs'
    00062831999d[CTRL ] searching for component 'reset_on_triple_fault' in list 'cpu'
    00062831999e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
    00062831999i[CPU0 ] cpu hardware reset
    Je suis loin de tout comprendre malheureusement, mais ce que je vois bien, c'est que j'ai effectivement des erreurs niveau "exceptions", mais que le log me parle aussi de IDT (qui, je le répète, n'est pas lancé à ce stade). Je vois aussi que mon CS est encore à 0x10 au lieux de 0x08.

    Bref, je n'arrive pas du tout à analyser ce log en fin de compte... Quelqu'un y voit plus clair que moi ?

    Merci encore.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Segmentation fault sur mon serveur
    Par zoullou dans le forum Administration système
    Réponses: 2
    Dernier message: 06/04/2007, 10h17
  2. Segmentation fault sur script PHP
    Par zoullou dans le forum Langage
    Réponses: 1
    Dernier message: 03/04/2007, 09h32
  3. Segmentation fault sur new[] et delete[]
    Par Don ViP dans le forum C++
    Réponses: 4
    Dernier message: 30/04/2006, 00h29
  4. Segmentation Fault sur un fclose
    Par Beush dans le forum C
    Réponses: 9
    Dernier message: 30/11/2005, 19h30
  5. Segmentation fault sur un gethostbyname ?
    Par Mitox dans le forum Réseau
    Réponses: 9
    Dernier message: 25/11/2005, 16h17

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo