27

How do I do the equivalent of an x86 software interrupt:

asm( "int $3" )

on an ARM processor (specifically a Cortex A8) to generate an event that will break execution under gdb?

engie
  • 2,569
  • 3
  • 18
  • 13
  • Using the BKPT instruction generates a SIGBUS that seems to mess up the program counter. – engie Jul 05 '12 at 13:30
  • use the swi instruction, I believe svc is another name for that instruction depending on which flavor of arm. – old_timer Jul 05 '12 at 13:49
  • The SWI instruction is OS/debugger dependent. The Angel debugger defines code 0x18 as ReportException, and subcode 0x20020 as breakpoint. It's not portable. http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0058d/BACBEFAA.html – Mark Lakata Jun 26 '13 at 21:48
  • See this posted answer which provides a list of alternatives for both ARM and Intel processors, https://stackoverflow.com/a/49079078/1466970 . – Richard Chambers Apr 07 '23 at 01:43

8 Answers8

27

Using arm-none-eabi-gdb.exe cross compiler, this works great for me (thanks to Igor's answer):

__asm__("BKPT");
benathon
  • 7,455
  • 2
  • 41
  • 70
21

ARM does not define a specific breakpoint instruction. It can be different in different OSes. On ARM Linux it's usually an UND opcode (e.g. FE DE FF E7) in ARM mode and BKPT (BE BE) in Thumb.

With GCC compilers, you can usually use __builtin_trap() intrinsic to generate a platform-specific breakpoint. Another option is raise(SIGTRAP).

Igor Skochinsky
  • 24,629
  • 2
  • 72
  • 109
  • 4
    **GCC/clang assume that code after `__builtin_trap()` is unreachable, even at `-O0`**. On https://godbolt.org/z/RNc7kY, we can see that for ARM, there's nothing after `.inst 0xe7f000f0`, not even a `bx lr` at the end of a function. And on x86, it compiles to `ud2` (illegal instruction), again leaving out code to implement later C statements. Even at `-O0`, ARM gcc8.2 still leaves out function epilogues, although there is code for a later C statement. But that makes it unusable. – Peter Cordes Mar 05 '19 at 10:01
  • @PeterCordes: I'd suggest putting it under a run-time condition then. – Igor Skochinsky Mar 06 '19 at 15:18
  • @yfr24493AzzrggAcom you can ask a new question about it – Igor Skochinsky May 08 '20 at 13:51
  • Hi friend I already did that but didn't get a good answer https://stackoverflow.com/questions/61649711/how-to-put-breakpoint-with-ptrace-by-address – yfr24493AzzrggAcom May 08 '20 at 14:10
8

I have a simple library (scottt/debugbreak) just for this:

#include <debugbreak.h>
...
debug_break();

Just copy the single debugbreak.h header into your code and it'll correctly handle ARM, AArch64, i386, x86-64 and even MSVC.

scottt
  • 7,008
  • 27
  • 37
6

__asm__ __volatile__ ("bkpt #0");

See BKPT man entry.

Benny
  • 4,095
  • 1
  • 26
  • 27
3

For Windows on ARM, the instrinsic __debugbreak() still works which utilizes undefined opcode.

nt!DbgBreakPointWithStatus:
defe     __debugbreak
Thomson
  • 20,586
  • 28
  • 90
  • 134
  • Looks like `__debugbreak()` is an intrinsic available for "x86, x64, ARM, ARM64" and whose use requires the `intrin.h` include file., [topic __debugbreak in Microsoft Learn](https://learn.microsoft.com/en-us/cpp/intrinsics/debugbreak?view=msvc-170). – Richard Chambers Apr 07 '23 at 02:33
3

On my armv7hl (i.MX6q with linux 4.1.15) system, to set a breakpoint in another process, I use :

ptrace(PTRACE_POKETEXT, pid, address, 0xe7f001f0)

I choose that value after strace'ing gdb :)

This works perfectly : I can examine the traced process, restore the original instruction, and restart the process with PTRACE_CONT.

3

Although the original question asked about Cortex-A7 which is ARMv7-A, on ARMv8 GDB uses

brk #0

Olsonist
  • 2,051
  • 1
  • 20
  • 35
2

We can use breakpoint inst:

Or we can use UND pseudo-instruction to generate undefined instruction which will cause exception if processor attempt to execute it.

J1ngB0
  • 41
  • 3