2017-05-31 1 views
6

Lors du débogage, j'ai récemment remarqué que GDB a la capacité d'évaluer les expressions « complexes » lors du débogage d'un programme, et je me demande comment il le fait. Par exemple, avec le code suivant:Comment GDB évaluer les expressions de C lors de l'exécution

int main() { 
    std::vector<int> v = {1, 2, 3}; 
    int k = 0; 
    std::cin >> k; 
    v.push_back(k); 
    return v.at(0); 
} 

Je suis en mesure de compiler le programme g++ -g myprogram.cpp et le débogage dans GDB ce qui me permet de taper des choses comme print v.at(4); (qui imprime la valeur correcte après k est dynamiquement entré) et print v.at(2) == 3 ce qui évalue à vrai.

Je me demande comment GDB fait cela. This SO question laisse entendre que c'est quelque chose de "compilé en mémoire" mais ne précise pas davantage, alors je me demande s'il utilise une sorte de JIT pour que tout cela fonctionne ou autre chose? Est-ce qu'ils compilent le code en ligne pendant que je le tape et l'exécute? Ont-ils un cadre pour évaluer C++ à la volée dans le contexte de débogage? En substance, je veux reproduire ceci dans un débogueur que j'écris pour évaluer des expressions à des points de rupture, c'est pourquoi je suis curieux de savoir comment GDB le fait.

+1

Je ne sais pas quel genre de réponse vous espérez obtenir. Gdb est capable d'analyser les expressions C et C++ dans le contexte du programme en cours de débogage, à l'aide de l'information de débogage contenue dans le binaire, et éventuellement aussi avec l'utilisation du code source lorsque celui-ci est disponible. Mais vous le saviez déjà, et les détails seraient beaucoup trop longs pour ce lieu. –

+0

@JohnBollinger J'ai pensé que je devrais "utiliser la source", mais ce que je me demande, c'est comment ils évaluent les expressions. Est-ce qu'ils compilent le code en ligne pendant que je le tape et l'exécute? Ont-ils un cadre pour évaluer C++ à la volée dans le contexte de débogage? En substance, je veux reproduire ceci dans un débogueur que j'écris pour évaluer des expressions à des points de rupture, c'est pourquoi je suis curieux de savoir comment GDB le fait. Merci! – llk

+0

Votre question semble être plus axée sur le C++. Je vous recommande de supprimer le tag C. – tambre

Répondre

5

Réponse courte: Il ne compile pas le code.

Réponse longue:

  1. Vous appelez commande print et la procédure se produit dans printcmd.c
  2. Il appelle evaluate_expression, défini dans eval.c, qui évalue une expression en lisant la mémoire cible et le calcul gdb pour opérateurs standard, sinon utilisez call_function_by_hand.
  3. call_function_by_hand est défini dans infcall.c. Lorsqu'elle est appelée, la procédure interrompt l'exécution de la cible (parfois non, il est donc possible de planter un programme multithread avec cette fonctionnalité).
  4. Injecter du code dans le programme en cours de débogage.
  5. Récupérez le résultat en lisant la mémoire et désactivez-la si nécessaire.

Vous pouvez vous concentrer sur le code de call_function_by_hand pour une meilleure compréhension. Remarque: compile est une chose différente de print/call.

Réponse complète:

Dans quelques jours, je peux écrire une analyse détaillée de la façon dont GDB met en œuvre cette fonctionnalité, pour aller plus loin.

6

qui me permet de taper des choses comme print v.at (4); Gdb peut appeler des fonctions compilées dans le binaire.

C'est exactement ce qui se passe ici. gdb appelle std::vector la fonction membre at() et imprime le résultat pour vous, voir documentation.

Notez également que cela est possible parce que vous utilisez v.at(0) dans votre code. Si vous supprimez cette partie du code, v.at() ne sera pas instancié et ne sera pas disponible dans le binaire résultant, ce qui empêchera gdb de l'appeler.

+0

GDB ne compile donc rien, il exécute plutôt des sections du code existant pour évaluer les expressions? Existe-t-il une bibliothèque que GDB utilise pour cela ou est-elle complètement codée de façon autonome? – llk

+1

Oui, dans l'exemple que vous avez posté. Mais il peut également compiler et injecter du code, voir https://sourceware.org/gdb/onlinedocs/gdb/Compiling-and-Injecting-Code.html#Compiling-and-Injection-Code, même si je n'ai pas utilisé cette fonctionnalité. – ks1322