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

C++ Discussion :

Problème de linker avec ld


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Inscrit en
    Juin 2008
    Messages
    85
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 85
    Par défaut Problème de linker avec ld
    Bonjour,

    J'essaye de compiler un programme mais j'ai une erreur d'édition de liens. J'ai 4 fichiers : Screen.h, Screen.cpp, type.h, main.cpp. Je compile main.cpp et screen.cpp sans erreur ni warning (avec gcc). Je fais ensuite la commande ld pour indiquer que mon code commence à l'adresse 0x10000. Voici mes lignes de compilation :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    gcc -c main.cpp 
    gcc -c screen.cpp
    ld --oformat binary -Ttext 10000 main.o screen.o -o kernel
    Voici les erreurs lors de la commande ld :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    ld: AVERTISSEMENT: ne peut trouver le symbole d'entrée _start; utilise par défaut 0000000000010000
    main.o: dans la fonction "main":
    main.cpp:(.text+0x6b): référence indéfinie vers "_Unwind_Resume"
    main.o:(.eh_frame+0x12): référence indéfinie vers "__gxx_personality_v0"
    Merci d'avance

  2. #2
    Membre expérimenté
    Profil pro
    Inscrit en
    Août 2007
    Messages
    190
    Détails du profil
    Informations personnelles :
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations forums :
    Inscription : Août 2007
    Messages : 190
    Par défaut
    Salut,

    Première chose : Il faut que tu utilises g++ pour compiler et non gcc.
    Si tu ne précises pas le point d'entrée (la première instruction qui sera exécutée au lancement de ton programme) ld prend par défaut _start. Pour modifier ce comportement il suffit d'utiliser l'option -e (--entry). Un petit :
    t'en diras plus.

  3. #3
    Membre confirmé
    Inscrit en
    Juin 2008
    Messages
    85
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 85
    Par défaut
    Mon point d'entrée est bien _start c'est pour ça que je ne le redéfini pas. De plus avec g++ la même erreur survient.

  4. #4
    Membre expérimenté
    Profil pro
    Inscrit en
    Août 2007
    Messages
    190
    Détails du profil
    Informations personnelles :
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations forums :
    Inscription : Août 2007
    Messages : 190
    Par défaut
    Dans ce cas, peux tu montrer le code ?

  5. #5
    Membre confirmé
    Inscrit en
    Juin 2008
    Messages
    85
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 85
    Par défaut
    Bien sur le voici,

    type.h :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #ifndef _I386_TYPE_
    #define _I386_TYPE_
    #define NULL 0
     
    typedef unsigned char u8;
    typedef unsigned short u16;
    typedef unsigned int u32;
    typedef unsigned char uchar;
     
    #endif
    screen.h :

    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
    #include "type.h"
     
    class Cscreen
    {
    	private: //attribut
    		unsigned char m_x; //position du curseur en x
    		unsigned char m_y; //position du curseur en y
    		unsigned char m_attr; //attribut du caractère a afficher
     
    	private: //fonctions
    		void putChar(unsigned char); //affiche le charactere passer en parametre à l'ecran
     
    	public: //fonctions
    		Cscreen(void); //constructeur par défault
    		void clearScreen(void); //efface les données de l'ecran
    		void print(unsigned char*); // affiche la ligne à l'ecran
    		void movScrollRight(unsigned char); //déplace le scroll en x du nombre passer en parametre
    		void movScrollDown(unsigned char); //déplace le scroll en y du nombre passer en parametre
    		void movScrollUp(void); //efface la premiere ligne et met la derniere ligne libre
    		~Cscreen(); //destructeur
    };
    screen.cpp :

    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
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    #define RAMSCREEN 0xB8000       /* debut de la memoire video */
    #define SIZESCREEN 0xFA0        /* 4000, nombres d'octets d'une page texte */
    #define SCREENLIM 0xB8FA0	/* fin de la mémoire video */
     
    #include "screen.h"
     
    Cscreen::Cscreen() //constructeur par défault
    {
    	m_x = 0;
    	m_y = 0;
    	m_attr = 0x0E;
    }
     
    void Cscreen::putChar(unsigned char p_char)//affiche le charactere passer en parametre à l'ecran
    {
    	unsigned char* chardisplay = NULL;//pointe sur la zone mémoire qui contient le mappage de la mémoire vidéo
    	switch (p_char)
    	{
    		case 10 : m_y++; break; //New line
    		case 13 : m_x = 0; break; //Cariot return
    		case 9 : m_x = (m_x+8) - (m_x%8); break; //tab
    		default :  // caractere normal
    			chardisplay = (unsigned char*) (RAMSCREEN+2*m_x+m_y*160); //zone mémoire ou ecrire le char
    			*chardisplay = p_char;
    			*(chardisplay+1) = m_attr;
    			m_x++;
    			if (m_x == 80) //si on arrive a la derniere colonne
    			{
    				m_x = 0;
    				m_y++; //nouvelle ligne
    			}
    			if (m_y == 25) // si derniere ligne
    			{
    				movScrollUp(); //met la derniere ligne libre et remonte toutes les lignes
    			}
    			break;
    	}
    }
     
    void Cscreen::clearScreen() //efface les données de l'ecran
    {
    	for (unsigned char* videoram = (unsigned char*) RAMSCREEN; // debut mémoire video
    	     videoram != (unsigned char*) SCREENLIM; //jusqu a fin memoire video
    	     videoram = videoram+2) // mémoire video + 2 octets
    	{
    		// efface l'ecran
    		*videoram = 0;
    		*(videoram+1) = 0;
    	}
    	m_x = 0;
    	m_y = 0;
    }
     
    void Cscreen::print(unsigned char* p_chaine) // affiche la ligne à l'ecran
    {
    	int i = 0;
    	while (*(p_chaine+i) != '\0') //tant que pas caractere fin de chaine
    	{
    		putChar(*(p_chaine+i)); //affiche le caractere
    		i++; //passe au caractere suivant
    	}
    }
     
    void Cscreen::movScrollRight(unsigned char p_dep) //déplace le scroll en x du nombre passer en parametre
    {
    	if (p_dep<(80-m_x)) //si le déplacement ne deborde pas sur la ligne suivante
    		m_x+=p_dep; //ajoute p_dep a x (abscisse)
    }	
     
    void Cscreen::movScrollDown(unsigned char p_dep) //déplace le scroll en y du nombre passer en parametre
    {
    	if (p_dep<(25-m_y)) //si le deplacement ne deborde pas en y(ordonnée)
    		m_y+=p_dep; //ajoute p_dep en ordonnées(y)
    }	
     
    void Cscreen::movScrollUp() //efface la premiere ligne et met la derniere ligne libre
    {
    	unsigned char rowsav[4000]; // sauvegarde la zone memoire video
    	int i = 0;
     
    	// sauvegarde la memoire video
    	for (unsigned char* videoram = (unsigned char*) RAMSCREEN; // debut mémoire video
    	     videoram != (unsigned char*) SCREENLIM; //jusqu a fin memoire video
    	     videoram = videoram+2) // mémoire video + 2 octets
    	{
    		rowsav[i] = *videoram; //sauvegarde la ram
    		rowsav[i+1] = *(videoram+1); //sauvegarde la ram
    		i+=2;
    	}
     
    	i = 0;
    	//remplace la memoire video (monte tous d'une ligne)
    	for (unsigned char* videoram = (unsigned char*) RAMSCREEN; // debut mémoire video
    	     videoram != (unsigned char*) SCREENLIM; //jusqu a fin memoire video
    	     videoram = videoram+2) // mémoire video + 2 octets
    	{
    		if (i <= 3838) //si pas derniere ligne copier les données enregistrer dans la ram
    		{
    			*videoram = rowsav[i+160]; //remplace la ram
    			*(videoram+1) = rowsav[i+161]; //remplace la ram
    			i+=2;
    		}
    		else //sinon mettre 0 (ligne vide)
    		{
    			*videoram = 0; //remplace la ram
    			*(videoram+1) = 0x07; //remplace la ram
    		}
    	}
    }
     
    Cscreen::~Cscreen()//destructeur
    {
    }
    main.cpp :

    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
    #include "screen.h"
     
    int main();
     
    void _start(void)
    {
            main();
    }
     
    int main(void)
    {
    	Cscreen screen; //initialise l'ecran
    	screen.clearScreen(); //efface l'ecran
    	for (int i = 0; i != 5; i++)
    		screen.print((unsigned char*) "Bonjour");
    	while (1);
    }
    Merci de l'aide

  6. #6
    Membre expérimenté
    Profil pro
    Inscrit en
    Août 2007
    Messages
    190
    Détails du profil
    Informations personnelles :
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations forums :
    Inscription : Août 2007
    Messages : 190
    Par défaut
    Le problème du _start vient du fait que le compilateur C++ décore le nom des fonctions ce qui permet entre autre la surcharge. Pour ne pas qu'il décore le nom de la fonction tu peux utiliser :
    Dans ton cas ca donne :
    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
    #include "screen.h"
     
    int main();
     
    extern "C" {
      void _start(void)
      {
        main();
      }
    }
     
    int main(void)
    {
      Cscreen screen; //initialise l'ecran
      screen.clearScreen(); //efface l'ecran
      for (int i = 0; i != 5; i++)
        screen.print((unsigned char*) "Bonjour");
      while (1);
    }
    Tu informes ainsi le compilateur que ta fonction à un "linkage C" et donc qu'il doit garder intact le nom de la fonction.

  7. #7
    screetch
    Invité(e)
    Par défaut
    g++ pour linker aussi. si tu veux passer des commandes a ld, utilise l'option -Wl,

    par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    g++ -c main.cpp 
    g++ -c screen.cpp
    g++ -Wl,--oformat,binary -Wl,-Ttext,10000 main.o screen.o -o kernel

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

Discussions similaires

  1. Problème de linker avec SDL_Image
    Par Shugo78 dans le forum SDL
    Réponses: 7
    Dernier message: 25/03/2012, 23h10
  2. problème de linker avec bibliothèque PTHREAD
    Par krossark dans le forum Bibliothèques
    Réponses: 1
    Dernier message: 28/01/2010, 14h58
  3. Réponses: 10
    Dernier message: 17/08/2009, 12h39
  4. Problèmes de versions avec Xalan, Xerces et Java
    Par honeyz dans le forum XML/XSL et SOAP
    Réponses: 4
    Dernier message: 05/06/2003, 10h18
  5. [Debutant] Problème du linker [Dev-c++4]
    Par Macdir dans le forum Dev-C++
    Réponses: 3
    Dernier message: 30/05/2003, 20h50

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