debugbreak.c 1.0.0 → 1.0.1

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/README.md CHANGED
@@ -22,19 +22,51 @@ int main()
22
22
 
23
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
24
 
25
+ <br>
26
+
25
27
  Installation
26
28
  ================================
27
29
 
28
30
  Run:
29
- ```bash
31
+
32
+ ```sh
30
33
  $ npm i debugbreak.c
31
34
  ```
32
35
 
33
36
  And then include `debugbreak.h` as follows:
37
+
34
38
  ```c
39
+ // main.c
35
40
  #include "node_modules/debugbreak.c/debugbreak.h"
41
+
42
+ int main() { /* ... */ }
43
+ ```
44
+
45
+ And then compile with `clang` or `gcc` as usual.
46
+
47
+ ```bash
48
+ $ clang main.c # or, use gcc
49
+ $ gcc main.c
50
+ ```
51
+
52
+ You may also use a simpler approach:
53
+
54
+ ```c
55
+ // main.c
56
+ #include <debugbreak.h>
57
+
58
+ int main() { /* ... */ }
36
59
  ```
37
60
 
61
+ If you add the path `node_modules/debugbreak.c` to your compiler's include paths.
62
+
63
+ ```bash
64
+ $ clang -I./node_modules/debugbreak.c main.c # or, use gcc
65
+ $ gcc -I./node_modules/debugbreak.c main.c
66
+ ```
67
+
68
+ <br>
69
+
38
70
  Implementation Notes
39
71
  ================================
40
72
 
@@ -59,9 +91,9 @@ int main()
59
91
  compiles to:
60
92
  ```
61
93
  main
62
- 0x0000000000400390 <+0>: 0f 0b ud2
94
+ 0x0000000000400390 <+0>: 0f 0b ud2
63
95
  ```
64
- Notice how the call to `printf()` is not present in the assembly output.
96
+ Notice how the call to `printf()` is not present in the assembly output.
65
97
 
66
98
  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
99
  ```
@@ -75,7 +107,7 @@ On ARM, **__builtin_trap()** generates a call to **abort()**, making it even les
75
107
  ```C
76
108
  #include <stdio.h>
77
109
  #include "debugbreak.h"
78
-
110
+
79
111
  int main()
80
112
  {
81
113
  debug_break();
@@ -87,12 +119,12 @@ compiles to:
87
119
  ```
88
120
  main
89
121
  0x00000000004003d0 <+0>: 50 push %rax
90
- 0x00000000004003d1 <+1>: cc int3
122
+ 0x00000000004003d1 <+1>: cc int3
91
123
  0x00000000004003d2 <+2>: bf a0 05 40 00 mov $0x4005a0,%edi
92
124
  0x00000000004003d7 <+7>: e8 d4 ff ff ff callq 0x4003b0 <puts@plt>
93
125
  0x00000000004003dc <+12>: 31 c0 xor %eax,%eax
94
126
  0x00000000004003de <+14>: 5a pop %rdx
95
- 0x00000000004003df <+15>: c3 retq
127
+ 0x00000000004003df <+15>: c3 retq
96
128
  ```
97
129
  which correctly trigges **SIGTRAP** and single-stepping in GDB after a **debug_break()** hit works well.
98
130
 
@@ -143,5 +175,6 @@ Behavior on Different Architectures
143
175
  <br>
144
176
 
145
177
 
178
+ [![SRC](https://img.shields.io/badge/src-repo-green?logo=Org)](https://github.com/scottt/debugbreak)
146
179
  [![ORG](https://img.shields.io/badge/org-nodef-green?logo=Org)](https://nodef.github.io)
147
180
  ![](https://ga-beacon.deno.dev/G-RC63DPBH3P:SH3Eq-NoQ9mwgYeHWxu7cw/github.com/nodef/debugbreak.c)
package/debugbreak.h CHANGED
@@ -1,174 +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 */
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 CHANGED
@@ -1,15 +1,28 @@
1
1
  {
2
2
  "name": "debugbreak.c",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
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",
5
+ "keywords": [
6
+ "c",
7
+ "library",
8
+ "mpeg",
9
+ "video",
10
+ "writer",
11
+ "no allocations",
12
+ "minimalistic"
13
+ ],
14
+ "homepage": "https://github.com/nodef/debugbreak.c#readme",
15
+ "bugs": {
16
+ "url": "https://github.com/nodef/debugbreak.c/issues"
17
+ },
7
18
  "repository": {
8
19
  "type": "git",
9
20
  "url": "git+https://github.com/nodef/debugbreak.c.git"
10
21
  },
11
- "bugs": {
12
- "url": "https://github.com/nodef/debugbreak.c/issues"
13
- },
14
- "homepage": "https://github.com/nodef/debugbreak.c#readme"
22
+ "license": "BSD-2-Clause",
23
+ "author": "wolfram77@gmail.com",
24
+ "main": "debugbreak.h",
25
+ "scripts": {
26
+ "test": "bash build.sh test"
27
+ }
15
28
  }
package/GNUmakefile DELETED
@@ -1,28 +0,0 @@
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/debugbreak-gdb.py DELETED
@@ -1,183 +0,0 @@
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()
File without changes