L'utilisation de gdb pour un code d'assemblage en une seule étape en dehors de l'exécutable spécifié provoque l'erreur "Impossible de trouver les limites de la fonction actuelle"

86

Je suis en dehors de l'exécutable cible de gdb et je n'ai même pas de pile correspondant à cette cible. Je veux quand même faire une seule étape, afin de pouvoir vérifier ce qui se passe dans mon code d'assemblage, car je ne suis pas un expert en assemblage x86. Malheureusement, gdb refuse d'effectuer ce simple débogage au niveau de l'assembly. Cela me permet de définir et de m'arrêter sur un point d'arrêt approprié, mais dès que j'essaye d'avancer d'une seule étape, gdb signale l'erreur «Impossible de trouver les limites de la fonction actuelle» et l'EIP ne change pas.

Détails supplémentaires:

Le code machine a été généré par des instructions gcc asm et je l'ai copié dans l'emplacement mémoire du noyau où il s'exécute, à partir de la sortie de objdump -d. Cela ne me dérangerait pas d'utiliser un chargeur pour charger mon code objet à une adresse déplacée, mais gardez à l'esprit que le chargement doit être effectué dans un module du noyau.

Je suppose qu'une autre alternative serait de produire un faux module de noyau ou un fichier d'informations de débogage à donner à gdb, pour lui faire croire que cette zone est dans le code du programme. gdb fonctionne correctement sur l'exécutable du noyau lui-même.

(Pour ceux qui veulent vraiment le savoir, j'insère du code au moment de l'exécution dans l'espace de données du noyau Linux à l'intérieur d'une VM VMware et je le débogue à partir de gdb à distance en déboguant le noyau via le stub gdb intégré de VMware Workstation. Remarque je n'écris pas le noyau exploits; je suis un étudiant diplômé en sécurité qui écrit un prototype.)

(Je peux définir un point d'arrêt sur chaque instruction dans mon assemblage. Cela fonctionne mais deviendrait assez laborieux après un certain temps, car la taille des instructions d'assemblage x86 varie et l'emplacement de l'assemblage changera à chaque redémarrage.)

Paul
la source
Les gens intelligents de ksplice.com injectent des données et du code dans le noyau en assemblant de "faux" modules de noyau et en les chargeant. Et s'ils peuvent le faire, pourquoi pas vous? ;-)
éphémère

Réponses:

116

Vous pouvez utiliser stepiou nexti(qui peut être abrégé en siou ni) pour parcourir le code de votre machine.

R Samuel Klatchko
la source
1
Sensationnel. Rétrospectivement, je ne sais pas comment j'ai oublié stepi. Je suppose que j'ai juste supposé que gdb n'avait pas de code source, cette étape reviendrait aux instructions d'assemblage.
Paul
1
note: vous ne pouvez souvent pas taper "break main", "run" pour les programmes d'assemblage. Tapez "layout asm", "start" à la place. J'ai compris cela en lisant le message ci-dessous, mais quelqu'un d'autre lisant ce message pourrait ne pas être aussi patient.
Dmitry le
1
@Dmitry startéquivaut à tbreak mainsuivi de run(note: tbreakau lieu de break)
Ruslan
151

Au lieu de gdb, courez gdbtui. Ou exécutez gdbavec le -tuicommutateur. Ou appuyez sur C-x C-aaprès avoir entré gdb. Vous êtes maintenant en mode TUI de GDB .

Entrez layout asmpour créer l'assemblage d'affichage de la fenêtre supérieure - cela suivra automatiquement votre pointeur d'instructions, bien que vous puissiez également changer de cadre ou faire défiler pendant le débogage. Appuyez C-x spour passer en mode SingleKey, où run continue up down finishetc. sont abrégés en une seule touche, ce qui vous permet de parcourir votre programme très rapidement.

   + ------------------------------------------------- -------------------------- +
B +> | 0x402670 <main> pousser% r15 |
   | 0x402672 <main + 2> mov% edi,% r15d |
   | 0x402675 <main + 5> pousser% r14 |
   | 0x402677 <main + 7> pousser% r13 |
   | 0x402679 <main + 9> mov% rsi,% r13 |
   | 0x40267c <principal + 12> pousser% r12 |
   | 0x40267e <main + 14> pousser% rbp |
   | 0x40267f <main + 15> pousser% rbx |
   | 0x402680 <main + 16> sous $ 0x438,% rsp |
   | 0x402687 <main + 23> mov (% rsi),% rdi |
   | 0x40268a <main + 26> movq $ 0x402a10,0x400 (% rsp) |
   | 0x402696 <main + 38> movq $ 0x0,0x408 (% rsp) |
   | 0x4026a2 <main + 50> movq $ 0x402510,0x410 (% rsp) |
   + ------------------------------------------------- -------------------------- +
processus fils 21518 Dans: ligne principale: ?? PC: 0x402670
(gdb) fichier / opt / j64-602 / bin / jconsole
Lecture des symboles depuis /opt/j64-602/bin/jconsole...done.
(aucun symbole de débogage trouvé) ... terminé.
(gdb) layout asm
(gdb) démarrer
(gdb)
éphémère
la source
26

La chose la plus utile que vous puissiez faire ici est display/i $pcavant d'utiliser stepicomme déjà suggéré dans la réponse de R Samuel Klatchko. Cela indique à gdb de désassembler l'instruction courante juste avant d'imprimer l'invite à chaque fois; alors vous pouvez simplement continuer à appuyer sur Entrée pour répéter la stepicommande.

(Voir ma réponse à une autre question pour plus de détails - le contexte de cette question était différent, mais le principe est le même.)

Matthew Slattery
la source