Question

Je veux pouvoir détecter le moment où une adresse d'écriture dans la mémoire se produit, par exemple en définissant un rappel associé à une interruption. Est-ce que quelqu'un sait comment?

J'aimerais pouvoir faire cela au moment de l'exécution (éventuellement, gdb a cette fonctionnalité, mais ma l’application provoque le blocage de gdb).

Était-ce utile?

La solution

Si vous souhaitez intercepter des écritures dans une plage d'adresses, vous pouvez utiliser mprotect ( ) pour marquer la mémoire en question comme non inscriptible, et installer un gestionnaire de signaux utilisant sigaction () pour capturer le SIGSEGV résultant, effectuez votre journalisation ou quoi que ce soit et marquez à nouveau la page en écriture.

Autres conseils

Vous avez besoin d'accéder aux registres de débogage X86: http://en.wikipedia.org/wiki / Debug_register

Vous devez définir l'adresse du point d'arrêt dans l'un des DR0 à DR3, puis la condition (écriture des données) dans DR7. L’interruption se produira et vous pourrez exécuter votre code de débogage pour lire DR6 et trouver la cause du point d’arrêt.

Si la GDB ne fonctionne pas, essayez un débogueur plus simple / plus petit, tel que http: // sourceforge. net / projects / minibug / - si cela ne fonctionne pas, vous pouvez au moins consulter le code et comprendre comment utiliser vous-même le matériel de débogage sur le processeur.

Il existe également une excellente ressource de développement IBM sur la maîtrise des techniques de débogage sous Linux, qui devrait fournir des options supplémentaires:

http://www.ibm.com/developerworks/linux/library / l-debug /

Un article assez intéressant sur cette question est que Windows est ici (je sais que vous utilisez Linux, mais d’autres pourraient répondre à cette question et vouloir le faire sous Windows):

http://www.codeproject.com/KB/debug/hardwarebreakpoint.aspx

-Adam

GDB a cette fonctionnalité: elle s’appelle points de contrôle matériels et est très bien supportée sous Linux / x86:

(gdb) watch *(int *)0x12345678

Si votre application plante la GDB, créez la GDB actuelle à partir de Head CVS .

Si cette GDB échoue toujours, créez un bogue .

Il est possible que nous puissions résoudre GDB plus rapidement que vous ne pouvez pirater le gestionnaire SIGSEGV (à condition qu’il s’agisse d’un bon scénario de test), et les correctifs apportés à GDB vous aident également à résoudre les problèmes futurs.

mprotect a un inconvénient: votre mémoire doit être alignée sur les limites de la page. J'avais ma mémoire problématique sur la pile et je ne pouvais pas utiliser mprotect ().

Comme Adam l'a dit, vous voulez manipuler les registres de débogage. Sur Windows, j'ai utilisé ceci: http://www.morearty.com/code/breakpoint/

Le problème avec Linux est qu’il n’a pas de tels équivalents. J'ai trouvé ptrace, mais j'ai pensé, cela ne peut pas être ça, il doit y avoir quelque chose de plus simple. Mais il n'y en a pas. Encore. Je pense qu'ils travaillent sur une API hw_breakpoint pour le noyau et l'espace utilisateur. (voir http://lwn.net/Articles/317153/ )

Mais quand j'ai trouvé ceci: http://blogs.oracle.com/nike/entry / memory_debugger_for_linux J'ai essayé et ce n'était pas si grave. La méthode ptrace fonctionne selon un "processus extérieur". agissant en tant que "débogueur", en vous associant à votre programme, en injectant de nouvelles valeurs pour les registres de débogage et en terminant avec votre programme en continuant avec un nouvel ensemble de points d'arrêt hw. Le fait est que vous pouvez créer ce "processus extérieur". vous-même en utilisant fork () (je n'ai pas eu de succès avec un pthread) et en effectuant ces étapes simples en ligne dans votre code.

Le code addwatchpoint doit être adapté pour fonctionner avec linux 64 bits, mais il ne s'agit que de changer USER_DR7, etc. en offsetof (struct user, u_debugreg [7]). Une autre chose est que, après un PTRACE_ATTACH, vous devez attendre que le débogage soit réellement arrêté. Mais au lieu de réessayer un POKEUSER dans une boucle occupée, la bonne chose à faire serait un waitpid () sur votre pid.

Le seul problème avec la méthode ptrace est que votre programme ne peut avoir qu'un seul "débogueur". attaché à la fois. Donc, une liaison ptrace échouera si votre programme est déjà en cours d'exécution sous le contrôle de gdb. Mais, tout comme l’exemple de code, vous pouvez enregistrer un gestionnaire de signaux pour SIGTRAP, s’exécuter sans gdb et, lorsque vous interceptez le signal, entrer une boucle occupée dans l’attente de l’attachement de gdb. À partir de là, vous pouvez voir qui a essayé d’écrire votre mémoire.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top