28

I am debugging this piece of software for an STM32 embedded system. In one of the functions my programs keeps hitting some sort of breakpoint:

SIGTRAP, Trace/breakpoint trap

However, in GDB, when I do info breakpoints I get No breakpoints or watchpoints. The breakpoint actually corresponds to a breakpoint I had set quite some time ago, in another version of the executable. When I set that breakpoint, GDB told me automatically using a hardware breakpoint on read-only memory (or a similar message).

I think the hardware breakpoint remains on my chip, despite having loaded a new version of the software. If there is indeed a spurious breakpoint, how can I locate and remove it?

Randomblue
  • 112,777
  • 145
  • 353
  • 547
  • Reset the CPU. :) (hw breakpoints can be left installed, if gdb dies or if it does not delete all existing breakpoints on exit/reconnection). – dbrank0 Mar 23 '12 at 15:03
  • Note that debug registers may persist across some types of resets. A full power-on reset will definitely clear it though. – TJD Mar 23 '12 at 21:37
  • 1
    What do you mean by "full power-on reset"? I've tried unplugging/replugging, but the breakpoint persists. – Randomblue Mar 24 '12 at 13:06
  • So, if I understand, you have cycled power on your embedded system (and there is no back up battery), turned off power on your jtag interface/ICE and breakpoint still gets hit? – dbrank0 Mar 27 '12 at 08:55
  • @dbrank0: Yep. Well at least GDB tells me that I have a SIGTRAP, which I interpret as a breakpoint. – Randomblue Mar 27 '12 at 09:35
  • It can be caused by something else. Have you tried to disassemble instruction at exact address where this happens? You may have a breakpoint instruction itself there (0xdeee, 0xdeeedeee, 0xbeeebeee...), some undefined instruction maybe? – dbrank0 Mar 27 '12 at 12:54
  • You can't be hitting a hardware breakpoint if the CPU is going through a full power cycle. It must be something in the code – mikehabibi Mar 30 '12 at 21:24

5 Answers5

23

Ok. Long answer: Hardware breakpoints are usually set by writing to some special CPU registers. This is done by gdb. If gdb dies, it can left those installed in CPU. I guess your implementation (of gdb) does not either clear or examine those, when it connects to your target. To locate them, you would need to list the contents of hardware breakpoints registers on your CPU (don't know how to do this on STM32). Workaround would be (informed guess) be this: set few HW breakpoints (typically there are only a few, seldom more than 8) using gdb, then remove all of them. This should overwrite and then clean those hw registers. Once you do set those breakpoints (before removing them), do "continue" (just in case, as gdb sets breakpoints only at that time).

dbrank0
  • 9,026
  • 2
  • 37
  • 55
  • 1
    Thanks for the idea of setting many breakpoints, and then removing them. That should solve the problem. A bit annoying that gdb does not clear those breakpoints when it connects to my target. – Randomblue Mar 23 '12 at 16:19
8

The following helped me:

# 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.
Robin Kuzmin
  • 742
  • 4
  • 12
  • 3
    This is the same idea as the accepted answer, but it's good to note that the hbreak command is key. Normal break command will set software breakpoints instead of overwriting previous breakpoints – Samuel Peter Jun 27 '17 at 12:33
  • 1
    This answer needs more upvotes. It works, and it is "cookbook". I was debugging a MinGW-w64 app under Linux/Wine. I kept hitting bizarre `SIGTRAP` breakpoints that I did not set. This answer fixed my issue immediately. – kevinarpe Jan 03 '23 at 06:41
3

SIGTRAP should be a breakpoint instruction that's being run.

Debug this by inspecting your instruction pointer, it's most likely pointed at an address that contains the BKPT instruction (you'll have to look up what the actual code is).

From there you'll have to work backwards based on the stack and instruction pointer and see if you're where you expect to be. There could be a number of things causing this, from GDB inserting a breakpoint instruction that it failed to clear, to memory corruption.

dragonx
  • 14,963
  • 27
  • 44
1

If adding and removing hardware breakpoints does not help, check the interrupt vector.

On Cortex-M microcontrollers all handler entries should have an odd address (ARM Cortex-M FAQ). If they don't, then a UsageFault of type INVSTATE is triggered and the MCU is halted. GDB interprets this as a SIGABRT.

If one of the entries has an even address, then check if the handler function has the .thumb_func and .type directives (NXP Avoid hardfault, HardFault and .thumb_func).

Example for a 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
Sussch
  • 1,117
  • 1
  • 9
  • 15
0

The code you are running may contain

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

which invokes a SIGTRAP.

iehrlich
  • 3,572
  • 4
  • 34
  • 43