debugbreak.h 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  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. #ifdef _MSC_VER
  29. #define debug_break __debugbreak
  30. #else
  31. #ifdef __cplusplus
  32. extern "C" {
  33. #endif
  34. #define DEBUG_BREAK_USE_TRAP_INSTRUCTION 1
  35. #define DEBUG_BREAK_USE_BULTIN_TRAP 2
  36. #define DEBUG_BREAK_USE_SIGTRAP 3
  37. #if defined(__i386__) || defined(__x86_64__)
  38. #define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_TRAP_INSTRUCTION
  39. __inline__ static void trap_instruction(void)
  40. {
  41. __asm__ volatile("int $0x03");
  42. }
  43. #elif defined(__thumb__)
  44. #define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_TRAP_INSTRUCTION
  45. /* FIXME: handle __THUMB_INTERWORK__ */
  46. __attribute__((always_inline))
  47. __inline__ static void trap_instruction(void)
  48. {
  49. /* See 'arm-linux-tdep.c' in GDB source.
  50. * Both instruction sequences below work. */
  51. #if 1
  52. /* 'eabi_linux_thumb_le_breakpoint' */
  53. __asm__ volatile(".inst 0xde01");
  54. #else
  55. /* 'eabi_linux_thumb2_le_breakpoint' */
  56. __asm__ volatile(".inst.w 0xf7f0a000");
  57. #endif
  58. /* Known problem:
  59. * After a breakpoint hit, can't 'stepi', 'step', or 'continue' in GDB.
  60. * 'step' would keep getting stuck on the same instruction.
  61. *
  62. * Workaround: use the new GDB commands 'debugbreak-step' and
  63. * 'debugbreak-continue' that become available
  64. * after you source the script from GDB:
  65. *
  66. * $ gdb -x debugbreak-gdb.py <... USUAL ARGUMENTS ...>
  67. *
  68. * 'debugbreak-step' would jump over the breakpoint instruction with
  69. * roughly equivalent of:
  70. * (gdb) set $instruction_len = 2
  71. * (gdb) tbreak *($pc + $instruction_len)
  72. * (gdb) jump *($pc + $instruction_len)
  73. */
  74. }
  75. #elif defined(__arm__) && !defined(__thumb__)
  76. #define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_TRAP_INSTRUCTION
  77. __attribute__((always_inline))
  78. __inline__ static void trap_instruction(void)
  79. {
  80. /* See 'arm-linux-tdep.c' in GDB source,
  81. * 'eabi_linux_arm_le_breakpoint' */
  82. __asm__ volatile(".inst 0xe7f001f0");
  83. /* Known problem:
  84. * Same problem and workaround as Thumb mode */
  85. }
  86. #elif defined(__aarch64__) && defined(__APPLE__)
  87. #define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_BULTIN_DEBUGTRAP
  88. #elif defined(__aarch64__)
  89. #define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_TRAP_INSTRUCTION
  90. __attribute__((always_inline))
  91. __inline__ static void trap_instruction(void)
  92. {
  93. /* See 'aarch64-tdep.c' in GDB source,
  94. * 'aarch64_default_breakpoint' */
  95. __asm__ volatile(".inst 0xd4200000");
  96. }
  97. #elif defined(__powerpc__)
  98. /* PPC 32 or 64-bit, big or little endian */
  99. #define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_TRAP_INSTRUCTION
  100. __attribute__((always_inline))
  101. __inline__ static void trap_instruction(void)
  102. {
  103. /* See 'rs6000-tdep.c' in GDB source,
  104. * 'rs6000_breakpoint' */
  105. __asm__ volatile(".4byte 0x7d821008");
  106. /* Known problem:
  107. * After a breakpoint hit, can't 'stepi', 'step', or 'continue' in GDB.
  108. * 'step' stuck on the same instruction ("twge r2,r2").
  109. *
  110. * The workaround is the same as ARM Thumb mode: use debugbreak-gdb.py
  111. * or manually jump over the instruction. */
  112. }
  113. #elif defined(__riscv)
  114. /* RISC-V 32 or 64-bit, whether the "C" extension
  115. * for compressed, 16-bit instructions are supported or not */
  116. #define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_TRAP_INSTRUCTION
  117. __attribute__((always_inline))
  118. __inline__ static void trap_instruction(void)
  119. {
  120. /* See 'riscv-tdep.c' in GDB source,
  121. * 'riscv_sw_breakpoint_from_kind' */
  122. __asm__ volatile(".4byte 0x00100073");
  123. }
  124. #else
  125. #define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_SIGTRAP
  126. #endif
  127. #ifndef DEBUG_BREAK_IMPL
  128. #error "debugbreak.h is not supported on this target"
  129. #elif DEBUG_BREAK_IMPL == DEBUG_BREAK_USE_TRAP_INSTRUCTION
  130. __attribute__((always_inline))
  131. __inline__ static void debug_break(void)
  132. {
  133. trap_instruction();
  134. }
  135. #elif DEBUG_BREAK_IMPL == DEBUG_BREAK_USE_BULTIN_DEBUGTRAP
  136. __attribute__((always_inline))
  137. __inline__ static void debug_break(void)
  138. {
  139. __builtin_debugtrap();
  140. }
  141. #elif DEBUG_BREAK_IMPL == DEBUG_BREAK_USE_BULTIN_TRAP
  142. __attribute__((always_inline))
  143. __inline__ static void debug_break(void)
  144. {
  145. __builtin_trap();
  146. }
  147. #elif DEBUG_BREAK_IMPL == DEBUG_BREAK_USE_SIGTRAP
  148. #include <signal.h>
  149. __attribute__((always_inline))
  150. __inline__ static void debug_break(void)
  151. {
  152. raise(SIGTRAP);
  153. }
  154. #else
  155. #error "invalid DEBUG_BREAK_IMPL value"
  156. #endif
  157. #ifdef __cplusplus
  158. }
  159. #endif
  160. #endif /* ifdef _MSC_VER */
  161. #endif /* ifndef DEBUG_BREAK_H */