SIGTRAP malgré l’absence de points d’arrêt; point d’arrêt matériel caché?

Je suis en train de déboguer ce logiciel pour un système intégré STM32. Dans l’une des fonctions, mes programmes continuent de bash une sorte de point d’arrêt:

SIGTRAP, Trap / Tracepoint Trap

Cependant, dans GDB, lorsque je donne des info breakpoints je n’ai No breakpoints or watchpoints . Le point d’arrêt correspond en fait à un point d’arrêt que j’avais défini il y a longtemps, dans une autre version de l’exécutable. Lorsque j’ai défini ce point d’arrêt, GDB m’a automatically using a hardware breakpoint on read-only memory indiqué automatically using a hardware breakpoint on read-only memory (ou un message similaire).

Je pense que le point d’arrêt matériel rest sur ma puce, malgré le chargement d’une nouvelle version du logiciel. S’il existe effectivement un point d’arrêt parasite, comment puis-je le localiser et le supprimer?

D’accord. Réponse longue: les points d’arrêt matériels sont généralement définis en écrivant dans des registres spéciaux de la CPU. Ceci est fait par gdb. Si gdb meurt, il peut laisser ceux installés dans la CPU. J’imagine que votre implémentation (de gdb) ne les efface pas ni ne les examine, lorsqu’elle se connecte à votre cible. Pour les localiser, vous devez répertorier le contenu des registres de points d’arrêt matériels sur votre CPU (vous ne savez pas comment procéder de cette manière sur STM32). La solution de contournement serait (conjecture informée) soit la suivante: définissez quelques points de rupture matérielle (généralement, il n’ya que quelques-uns, rarement plus de 8) à l’aide de gdb, puis supprimez-les tous. Cela devrait écraser puis nettoyer ces registres hw. Une fois que vous avez défini ces points d’arrêt (avant de les supprimer), faites “continuer” (juste au cas où, car gdb ne définit des points d’arrêt qu’à ce moment-là).

Ce qui suit m’a aidé:

 # Ones I hit the SIGTRAP: (gdb) f 0 # Show the current stack frame of the current thread. #0 0x4003ed70 in pthread_create@@GLIBC_2.4 () from /opt/CodeSourcery/arm-2011.09/arm-none-linux-gnueabi/libc/lib/libpthread.so.0 # The fragment of interest is the current address: 0x4003ed70. # Set the hardware assisted breakpoint at the current address: (gdb) hbreak *0x4003ed70 # Continue execution (without hitting SIGTRAP): (gdb) c # Continuing. 

SIGTRAP doit être une instruction de point d’arrêt en cours d’exécution.

Déboguer ceci en inspectant votre pointeur d’instruction, il est très probablement pointé sur une adresse qui contient l’instruction BKPT (vous devrez rechercher le code réel).

À partir de là, vous devrez travailler en arrière en vous basant sur le pointeur de stack et d’instructions et voir si vous êtes là où vous vous attendez. Cela pourrait être dû à un certain nombre de choses, notamment l’insertion d’une instruction de point d’arrêt non effacée par GDB, jusqu’à la corruption de la mémoire.

Le code que vous utilisez peut contenir

 int $0x03 ; talking about x86, don't know STM32 mnemo 

qui invoque un SIGTRAP.

Si l’ajout et la suppression de points d’arrêt matériels ne vous aident pas, vérifiez le vecteur d’interruption.

Sur les microcontrôleurs Cortex-M, toutes les entrées de gestionnaire doivent avoir une adresse impaire ( FAQ ARM Cortex-M ). Si ce n’est pas le cas, un UsageFault de type INVSTATE est déclenché et la MCU est arrêtée. GDB interprète cela comme un SIGABRT.

Si l’une des entrées a une adresse paire, vérifiez si la fonction gestionnaire a les directives .thumb_func et .type ( NXP Avoid hardfault , HardFault et .thumb_func ).

Exemple pour un HardFault_Handler:

 .thumb_func .type HardFault_Handler, %function HardFault_Handler: TST LR, #4 ITE EQ MRSEQ R0, MSP MRSNE R0, PSP B hard_fault_handler_c