debugbreak.c 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/COPYING ADDED
@@ -0,0 +1,23 @@
1
+ Copyright (c) 2011-2016, Scott Tsai
2
+
3
+ All rights reserved.
4
+
5
+ Redistribution and use in source and binary forms, with or without modification,
6
+ are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+ 2. Redistributions in binary form must reproduce the above copyright notice,
11
+ this list of conditions and the following disclaimer in the documentation
12
+ and/or other materials provided with the distribution.
13
+
14
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package/GNUmakefile ADDED
@@ -0,0 +1,28 @@
1
+ CFLAGS := -Os -Wall -g
2
+ CXXFLAGS := $(CFLAGS)
3
+
4
+ PROGRAMS := $(basename $(wildcard *.c test/*.c test/*.cc *.S))
5
+
6
+ .PHONY: all clean
7
+ all: $(PROGRAMS)
8
+ clean:
9
+ rm -f $(PROGRAMS) cscope.out tags
10
+
11
+ %: %.S
12
+ $(CC) $(CFLAGS) -nostdlib $< -o $@
13
+
14
+ # Not using builtin rules due to debugbreak.h dependency
15
+ %: %.c
16
+ $(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
17
+
18
+ %: %.cc
19
+ $(CXX) $(CXXFLAGS) $(LDFLAGS) $< -o $@
20
+
21
+ test/%: CFLAGS +=-I.
22
+ test/%: CXXFLAGS +=-I.
23
+ $(PROGRAMS): debugbreak.h
24
+
25
+ GDB ?= gdb
26
+ .PHONY: gdb
27
+ gdb:
28
+ $(GDB) -q -x debugbreak-gdb.py
package/README.md ADDED
@@ -0,0 +1,147 @@
1
+ # Debug Break
2
+
3
+ [debugbreak.h](https://github.com/scottt/debugbreak/blob/master/debugbreak.h), by [Scott Tsai](https://github.com/scottt), allows you to put breakpoints in your C/C++ code with a call to **debug_break()**:
4
+
5
+ ```C
6
+ #include <stdio.h>
7
+ #include "debugbreak.h"
8
+
9
+ int main()
10
+ {
11
+ debug_break(); /* will break into debugger */
12
+ printf("hello world\n");
13
+ return 0;
14
+ }
15
+ ```
16
+ * Include one header file and insert calls to `debug_break()` in the code where you wish to break into the debugger.
17
+ * Supports GCC, Clang and MSVC.
18
+ * Works well on ARM, AArch64, i686, x86-64, POWER and has a fallback code path for other architectures.
19
+ * Works like the **DebugBreak()** fuction provided by [Windows](http://msdn.microsoft.com/en-us/library/ea9yy3ey.aspx) and [QNX](http://www.qnx.com/developers/docs/6.3.0SP3/neutrino/lib_ref/d/debugbreak.html).
20
+
21
+ **License**: the very permissive [2-Clause BSD](https://github.com/scottt/debugbreak/blob/master/COPYING).
22
+
23
+ Known Problem: if continuing execution after a debugbreak breakpoint hit doesn't work (e.g. on ARM or POWER), see [HOW-TO-USE-DEBUGBREAK-GDB-PY.md](HOW-TO-USE-DEBUGBREAK-GDB-PY.md) for a workaround.
24
+
25
+ Installation
26
+ ================================
27
+
28
+ Run:
29
+ ```bash
30
+ $ npm i debugbreak.c
31
+ ```
32
+
33
+ And then include `debugbreak.h` as follows:
34
+ ```c
35
+ #include "node_modules/debugbreak.c/debugbreak.h"
36
+ ```
37
+
38
+ Implementation Notes
39
+ ================================
40
+
41
+ The requirements for the **debug_break()** function are:
42
+ * Act as a compiler code motion barrier
43
+ * Don't cause the compiler optimizers to think the code following it can be removed
44
+ * Trigger a software breakpoint hit when executed (e.g. **SIGTRAP** on Linux)
45
+ * GDB commands like **continue**, **next**, **step**, **stepi** must work after a **debug_break()** hit
46
+
47
+ Ideally, both GCC and Clang would provide a **__builtin_debugtrap()** that satisfies the above on all architectures and operating systems. Unfortunately, that is not the case (yet).
48
+ GCC's [__builtin_trap()](http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html#index-g_t_005f_005fbuiltin_005ftrap-3278) causes the optimizers to think the code follwing can be removed ([test/trap.c](https://github.com/scottt/debugbreak/blob/master/test/trap.c)):
49
+ ```C
50
+ #include <stdio.h>
51
+
52
+ int main()
53
+ {
54
+ __builtin_trap();
55
+ printf("hello world\n");
56
+ return 0;
57
+ }
58
+ ```
59
+ compiles to:
60
+ ```
61
+ main
62
+ 0x0000000000400390 <+0>: 0f 0b ud2
63
+ ```
64
+ Notice how the call to `printf()` is not present in the assembly output.
65
+
66
+ Further, on i386 / x86-64 **__builtin_trap()** generates an **ud2** instruction which triggers **SIGILL** instead of **SIGTRAP**. This makes it necessary to change GDB's default behavior on **SIGILL** to not terminate the process being debugged:
67
+ ```
68
+ (gdb) handle SIGILL stop nopass
69
+ ```
70
+ Even after this, continuing execution in GDB doesn't work well on some GCC, GDB combinations. See [GCC Bugzilla 84595](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84595).
71
+
72
+ On ARM, **__builtin_trap()** generates a call to **abort()**, making it even less suitable.
73
+
74
+ **debug_break()** generates an **int3** instruction on i386 / x86-64 ([test/break.c](https://github.com/scottt/debugbreak/blob/master/test/break.c)):
75
+ ```C
76
+ #include <stdio.h>
77
+ #include "debugbreak.h"
78
+
79
+ int main()
80
+ {
81
+ debug_break();
82
+ printf("hello world\n");
83
+ return 0;
84
+ }
85
+ ```
86
+ compiles to:
87
+ ```
88
+ main
89
+ 0x00000000004003d0 <+0>: 50 push %rax
90
+ 0x00000000004003d1 <+1>: cc int3
91
+ 0x00000000004003d2 <+2>: bf a0 05 40 00 mov $0x4005a0,%edi
92
+ 0x00000000004003d7 <+7>: e8 d4 ff ff ff callq 0x4003b0 <puts@plt>
93
+ 0x00000000004003dc <+12>: 31 c0 xor %eax,%eax
94
+ 0x00000000004003de <+14>: 5a pop %rdx
95
+ 0x00000000004003df <+15>: c3 retq
96
+ ```
97
+ which correctly trigges **SIGTRAP** and single-stepping in GDB after a **debug_break()** hit works well.
98
+
99
+ Clang / LLVM also has a **__builtin_trap()** that generates **ud2** but further provides **__builtin_debugtrap()** that generates **int3** on i386 / x86-64 ([original LLVM intrinsic](http://lists.llvm.org/pipermail/llvm-commits/Week-of-Mon-20120507/142621.html), [further fixes](https://reviews.llvm.org/rL166300#96cef7d3), [Clang builtin support](https://reviews.llvm.org/rL166298)).
100
+
101
+ On ARM, **debug_break()** generates **.inst 0xe7f001f0** in ARM mode and **.inst 0xde01** in Thumb mode which correctly triggers **SIGTRAP** on Linux. Unfortunately, stepping in GDB after a **debug_break()** hit doesn't work and requires a workaround like:
102
+ ```
103
+ (gdb) set $l = 2
104
+ (gdb) tbreak *($pc + $l)
105
+ (gdb) jump *($pc + $l)
106
+ (gdb) # Change $l from 2 to 4 for ARM mode
107
+ ```
108
+ to jump over the instruction.
109
+ A new GDB command, **debugbreak-step**, is defined in [debugbreak-gdb.py](https://github.com/scottt/debugbreak/blob/master/debugbreak-gdb.py) to automate the above. See [HOW-TO-USE-DEBUGBREAK-GDB-PY.md](HOW-TO-USE-DEBUGBREAK-GDB-PY.md) for sample usage.
110
+ ```
111
+ $ arm-none-linux-gnueabi-gdb -x debugbreak-gdb.py test/break-c++
112
+ <...>
113
+ (gdb) run
114
+ Program received signal SIGTRAP, Trace/breakpoint trap.
115
+ main () at test/break-c++.cc:6
116
+ 6 debug_break();
117
+
118
+ (gdb) debugbreak-step
119
+
120
+ 7 std::cout << "hello, world\n";
121
+ ```
122
+
123
+ On AArch64, **debug_break()** generates **.inst 0xd4200000**.
124
+
125
+ See table below for the behavior of **debug_break()** on other architecturs.
126
+
127
+ Behavior on Different Architectures
128
+ ----------------
129
+
130
+ | Architecture | debug_break() |
131
+ | ------------- | ------------- |
132
+ | x86/x86-64 | `int3` |
133
+ | ARM mode, 32-bit | `.inst 0xe7f001f0` |
134
+ | Thumb mode, 32-bit | `.inst 0xde01` |
135
+ | AArch64, ARMv8 | `.inst 0xd4200000` |
136
+ | POWER | `.4byte 0x7d821008` |
137
+ | RISC-V | `.4byte 0x00100073` |
138
+ | MSVC compiler | `__debugbreak` |
139
+ | Apple compiler on AArch64 | `__builtin_trap()` |
140
+ | Otherwise | `raise(SIGTRAP)` |
141
+
142
+ <br>
143
+ <br>
144
+
145
+
146
+ [![ORG](https://img.shields.io/badge/org-nodef-green?logo=Org)](https://nodef.github.io)
147
+ ![](https://ga-beacon.deno.dev/G-RC63DPBH3P:SH3Eq-NoQ9mwgYeHWxu7cw/github.com/nodef/debugbreak.c)
@@ -0,0 +1,183 @@
1
+ # Copyright (c) 2013, Scott Tsai
2
+ #
3
+ # All rights reserved.
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions are met:
7
+ #
8
+ # 1. Redistributions of source code must retain the above copyright notice,
9
+ # this list of conditions and the following disclaimer.
10
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ #
14
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
18
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24
+ # POSSIBILITY OF SUCH DAMAGE.
25
+
26
+
27
+ # Usage: gdb -x debugbreak-gdb.py
28
+ # (gdb) debugbreak-step
29
+ # (gdb) debugbreak-continue
30
+ #
31
+ # To debug:
32
+ # (gdb) set python print-stack full
33
+
34
+ import gdb
35
+ import re
36
+
37
+ def _gdb_show_version_parse(version_str):
38
+ '''
39
+ >>> s0 = 'This GDB was configured as "x86_64-redhat-linux-gnu".'
40
+ >>> s1 = 'This GDB was configured as "--host=i686-build_pc-linux-gnu --target=arm-linux-gnueabihf".'
41
+ >>> s2 = 'This GDB was configured as "x86_64-unknown-linux-gnu".'
42
+ >>> _gdb_show_version_parse(s0) == dict(target='x86_64-redhat-linux-gnu')
43
+ True
44
+ >>> _gdb_show_version_parse(s1) == dict(host='i686-build_pc-linux-gnu', target='arm-linux-gnueabihf')
45
+ True
46
+ >>> _gdb_show_version_parse(s2) == dict(target='x86_64-unknown-linux-gnu')
47
+ True
48
+ '''
49
+
50
+ t = version_str
51
+ msg = 'This GDB was configured as "'
52
+ s = t.find(msg)
53
+ if s == -1:
54
+ raise ValueError
55
+ s += len(msg)
56
+ e = t.find('".', s)
57
+ if e == -1:
58
+ raise ValueError
59
+
60
+ config = t[s:e]
61
+ d = {}
62
+ for i in config.split():
63
+ i = i.strip()
64
+ if i.startswith('--'):
65
+ (k, v) = i[2:].split('=')
66
+ d[k] = v
67
+ else:
68
+ if not i:
69
+ continue
70
+ d['target'] = i
71
+ return d
72
+
73
+ def _target_triplet():
74
+ '''
75
+ -> 'arm-linux-gnueabihf' or 'x86_64-redhat-linux-gnu' or ...
76
+
77
+ >>> import re
78
+ >>> not not re.match(r'\w*-\w*-\w*', target_triplet())
79
+ True
80
+ '''
81
+ t = gdb.execute('show version', to_string=True)
82
+ return _gdb_show_version_parse(t)['target']
83
+
84
+ temp_breakpoint_num = None
85
+
86
+ def on_stop_event(e):
87
+ global temp_breakpoint_num
88
+ if not isinstance(e, gdb.BreakpointEvent):
89
+ return
90
+ for bp in e.breakpoints:
91
+ if bp.number == temp_breakpoint_num:
92
+ bp.delete()
93
+ gdb.events.stop.disconnect(on_stop_event)
94
+ l = gdb.find_pc_line(int(gdb.parse_and_eval('$pc'))).line
95
+ gdb.execute('list %d, %d' % (l, l))
96
+ break
97
+
98
+ def _next_instn_jump_len(gdb_frame):
99
+ '-> None means don\'t jump'
100
+ try:
101
+ arch_name = gdb_frame.architecture().name()
102
+ except AttributeError:
103
+ arch_name = None
104
+
105
+ if arch_name.startswith('powerpc:'):
106
+ # 'powerpc:common64' on ppc64 big endian
107
+ i = bytes(gdb.selected_inferior().read_memory(gdb.parse_and_eval('$pc'), 4))
108
+ if (i == b'\x7d\x82\x10\x08') or (i == b'\x08\x10\x82\x7d'):
109
+ return 4
110
+ else: # not stopped on a breakpoint instruction
111
+ return None
112
+
113
+ triplet = _target_triplet()
114
+ if re.match(r'^arm-', triplet):
115
+ i = bytes(gdb.selected_inferior().read_memory(gdb.parse_and_eval('$pc'), 4))
116
+ if i == b'\xf0\x01\xf0\xe7':
117
+ return 4
118
+ elif i.startswith(b'\x01\xde'):
119
+ return 2
120
+ elif i == b'\xf0\xf7\x00\xa0 ':
121
+ # 'arm_linux_thumb2_le_breakpoint' from arm-linux-tdep.c in GDB
122
+ return 4
123
+ else: # not stopped on a breakpoint instruction
124
+ return None
125
+ return None
126
+
127
+ def _debugbreak_step():
128
+ global temp_breakpoint_num
129
+ try:
130
+ frame = gdb.selected_frame()
131
+ except gdb.error as e:
132
+ # 'No frame is currently selected.'
133
+ gdb.write(e.args[0] + '\n', gdb.STDERR)
134
+ return
135
+ instn_len = _next_instn_jump_len(frame)
136
+
137
+ if instn_len is None:
138
+ gdb.execute('stepi')
139
+ else:
140
+ loc = '*($pc + %d)' % (instn_len,)
141
+ bp = gdb.Breakpoint(loc, gdb.BP_BREAKPOINT, internal=True)
142
+ bp.silent = True
143
+ temp_breakpoint_num = bp.number
144
+ gdb.events.stop.connect(on_stop_event)
145
+ gdb.execute('jump ' + loc)
146
+
147
+ def _debugbreak_continue():
148
+ try:
149
+ frame = gdb.selected_frame()
150
+ except gdb.error as e:
151
+ # 'No frame is currently selected.'
152
+ gdb.write(e.args[0] + '\n', gdb.STDERR)
153
+ return
154
+ instn_len = _next_instn_jump_len(frame)
155
+
156
+ if instn_len is None:
157
+ gdb.execute('continue')
158
+ else:
159
+ loc = '*($pc + %d)' % (instn_len,)
160
+ gdb.execute('jump ' + loc)
161
+
162
+ class _DebugBreakStep(gdb.Command):
163
+ '''Usage: debugbreak-step
164
+ Step one instruction after a debug_break() breakpoint hit'''
165
+
166
+ def __init__(self):
167
+ gdb.Command.__init__(self, 'debugbreak-step', gdb.COMMAND_BREAKPOINTS, gdb.COMPLETE_NONE)
168
+
169
+ def invoke(self, arg, from_tty):
170
+ _debugbreak_step()
171
+
172
+ class _DebugBreakContinue(gdb.Command):
173
+ '''Usage: debugbreak-continue
174
+ Continue execution after a debug_break() breakpoint hit'''
175
+
176
+ def __init__(self):
177
+ gdb.Command.__init__(self, 'debugbreak-continue', gdb.COMMAND_BREAKPOINTS, gdb.COMPLETE_NONE)
178
+
179
+ def invoke(self, arg, from_tty):
180
+ _debugbreak_continue()
181
+
182
+ _DebugBreakStep()
183
+ _DebugBreakContinue()
package/debugbreak.h ADDED
@@ -0,0 +1,174 @@
1
+ /* Copyright (c) 2011-2021, Scott Tsai
2
+ *
3
+ * All rights reserved.
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice,
9
+ * this list of conditions and the following disclaimer.
10
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
11
+ * this list of conditions and the following disclaimer in the documentation
12
+ * and/or other materials provided with the distribution.
13
+ *
14
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
18
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24
+ * POSSIBILITY OF SUCH DAMAGE.
25
+ */
26
+ #ifndef DEBUG_BREAK_H
27
+ #define DEBUG_BREAK_H
28
+
29
+ #ifdef _MSC_VER
30
+
31
+ #define debug_break __debugbreak
32
+
33
+ #else
34
+
35
+ #ifdef __cplusplus
36
+ extern "C" {
37
+ #endif
38
+
39
+ #define DEBUG_BREAK_USE_TRAP_INSTRUCTION 1
40
+ #define DEBUG_BREAK_USE_BULTIN_TRAP 2
41
+ #define DEBUG_BREAK_USE_SIGTRAP 3
42
+
43
+ #if defined(__i386__) || defined(__x86_64__)
44
+ #define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_TRAP_INSTRUCTION
45
+ __inline__ static void trap_instruction(void)
46
+ {
47
+ __asm__ volatile("int $0x03");
48
+ }
49
+ #elif defined(__thumb__)
50
+ #define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_TRAP_INSTRUCTION
51
+ /* FIXME: handle __THUMB_INTERWORK__ */
52
+ __attribute__((always_inline))
53
+ __inline__ static void trap_instruction(void)
54
+ {
55
+ /* See 'arm-linux-tdep.c' in GDB source.
56
+ * Both instruction sequences below work. */
57
+ #if 1
58
+ /* 'eabi_linux_thumb_le_breakpoint' */
59
+ __asm__ volatile(".inst 0xde01");
60
+ #else
61
+ /* 'eabi_linux_thumb2_le_breakpoint' */
62
+ __asm__ volatile(".inst.w 0xf7f0a000");
63
+ #endif
64
+
65
+ /* Known problem:
66
+ * After a breakpoint hit, can't 'stepi', 'step', or 'continue' in GDB.
67
+ * 'step' would keep getting stuck on the same instruction.
68
+ *
69
+ * Workaround: use the new GDB commands 'debugbreak-step' and
70
+ * 'debugbreak-continue' that become available
71
+ * after you source the script from GDB:
72
+ *
73
+ * $ gdb -x debugbreak-gdb.py <... USUAL ARGUMENTS ...>
74
+ *
75
+ * 'debugbreak-step' would jump over the breakpoint instruction with
76
+ * roughly equivalent of:
77
+ * (gdb) set $instruction_len = 2
78
+ * (gdb) tbreak *($pc + $instruction_len)
79
+ * (gdb) jump *($pc + $instruction_len)
80
+ */
81
+ }
82
+ #elif defined(__arm__) && !defined(__thumb__)
83
+ #define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_TRAP_INSTRUCTION
84
+ __attribute__((always_inline))
85
+ __inline__ static void trap_instruction(void)
86
+ {
87
+ /* See 'arm-linux-tdep.c' in GDB source,
88
+ * 'eabi_linux_arm_le_breakpoint' */
89
+ __asm__ volatile(".inst 0xe7f001f0");
90
+ /* Known problem:
91
+ * Same problem and workaround as Thumb mode */
92
+ }
93
+ #elif defined(__aarch64__) && defined(__APPLE__)
94
+ #define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_BULTIN_DEBUGTRAP
95
+ #elif defined(__aarch64__)
96
+ #define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_TRAP_INSTRUCTION
97
+ __attribute__((always_inline))
98
+ __inline__ static void trap_instruction(void)
99
+ {
100
+ /* See 'aarch64-tdep.c' in GDB source,
101
+ * 'aarch64_default_breakpoint' */
102
+ __asm__ volatile(".inst 0xd4200000");
103
+ }
104
+ #elif defined(__powerpc__)
105
+ /* PPC 32 or 64-bit, big or little endian */
106
+ #define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_TRAP_INSTRUCTION
107
+ __attribute__((always_inline))
108
+ __inline__ static void trap_instruction(void)
109
+ {
110
+ /* See 'rs6000-tdep.c' in GDB source,
111
+ * 'rs6000_breakpoint' */
112
+ __asm__ volatile(".4byte 0x7d821008");
113
+
114
+ /* Known problem:
115
+ * After a breakpoint hit, can't 'stepi', 'step', or 'continue' in GDB.
116
+ * 'step' stuck on the same instruction ("twge r2,r2").
117
+ *
118
+ * The workaround is the same as ARM Thumb mode: use debugbreak-gdb.py
119
+ * or manually jump over the instruction. */
120
+ }
121
+ #elif defined(__riscv)
122
+ /* RISC-V 32 or 64-bit, whether the "C" extension
123
+ * for compressed, 16-bit instructions are supported or not */
124
+ #define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_TRAP_INSTRUCTION
125
+ __attribute__((always_inline))
126
+ __inline__ static void trap_instruction(void)
127
+ {
128
+ /* See 'riscv-tdep.c' in GDB source,
129
+ * 'riscv_sw_breakpoint_from_kind' */
130
+ __asm__ volatile(".4byte 0x00100073");
131
+ }
132
+ #else
133
+ #define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_SIGTRAP
134
+ #endif
135
+
136
+
137
+ #ifndef DEBUG_BREAK_IMPL
138
+ #error "debugbreak.h is not supported on this target"
139
+ #elif DEBUG_BREAK_IMPL == DEBUG_BREAK_USE_TRAP_INSTRUCTION
140
+ __attribute__((always_inline))
141
+ __inline__ static void debug_break(void)
142
+ {
143
+ trap_instruction();
144
+ }
145
+ #elif DEBUG_BREAK_IMPL == DEBUG_BREAK_USE_BULTIN_DEBUGTRAP
146
+ __attribute__((always_inline))
147
+ __inline__ static void debug_break(void)
148
+ {
149
+ __builtin_debugtrap();
150
+ }
151
+ #elif DEBUG_BREAK_IMPL == DEBUG_BREAK_USE_BULTIN_TRAP
152
+ __attribute__((always_inline))
153
+ __inline__ static void debug_break(void)
154
+ {
155
+ __builtin_trap();
156
+ }
157
+ #elif DEBUG_BREAK_IMPL == DEBUG_BREAK_USE_SIGTRAP
158
+ #include <signal.h>
159
+ __attribute__((always_inline))
160
+ __inline__ static void debug_break(void)
161
+ {
162
+ raise(SIGTRAP);
163
+ }
164
+ #else
165
+ #error "invalid DEBUG_BREAK_IMPL value"
166
+ #endif
167
+
168
+ #ifdef __cplusplus
169
+ }
170
+ #endif
171
+
172
+ #endif /* ifdef _MSC_VER */
173
+
174
+ #endif /* ifndef DEBUG_BREAK_H */
package/package.json ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "debugbreak.c",
3
+ "version": "1.0.0",
4
+ "description": "Break into the debugger programmatically; Scott Tsai (2011).",
5
+ "keywords": ["c", "library", "mpeg", "video", "writer", "no allocations", "minimalistic"],
6
+ "license": "BSD-2-Clause",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/nodef/debugbreak.c.git"
10
+ },
11
+ "bugs": {
12
+ "url": "https://github.com/nodef/debugbreak.c/issues"
13
+ },
14
+ "homepage": "https://github.com/nodef/debugbreak.c#readme"
15
+ }