From d6bcdcdaf7c93299b741ea2cd7e983b9ac5bfef2 Mon Sep 17 00:00:00 2001 From: Roman Telezhynskyi Date: Tue, 18 Dec 2018 16:08:14 +0200 Subject: [PATCH] Update debugbreak for support PowerPC target. --HG-- branch : develop --- src/libs/vmisc/debugbreak.h | 109 +++++++++++++++++++++--------------- 1 file changed, 63 insertions(+), 46 deletions(-) diff --git a/src/libs/vmisc/debugbreak.h b/src/libs/vmisc/debugbreak.h index 6615dda2f..c40850901 100644 --- a/src/libs/vmisc/debugbreak.h +++ b/src/libs/vmisc/debugbreak.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2015, Scott Tsai +/* Copyright (c) 2011-2018, Scott Tsai * * All rights reserved. * @@ -33,27 +33,22 @@ #else -#include - #ifdef __cplusplus extern "C" { #endif -enum { - /* gcc optimizers consider code after __builtin_trap() dead. - * Making __builtin_trap() unsuitable for breaking into the debugger */ - DEBUG_BREAK_PREFER_BUILTIN_TRAP_TO_SIGTRAP = 0 -}; +#define DEBUG_BREAK_USE_TRAP_INSTRUCTION 1 +#define DEBUG_BREAK_USE_BULTIN_TRAP 2 +#define DEBUG_BREAK_USE_SIGTRAP 3 #if defined(__i386__) || defined(__x86_64__) -enum { HAVE_TRAP_INSTRUCTION = 1 }; -__attribute__((gnu_inline, always_inline)) + #define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_TRAP_INSTRUCTION __inline__ static void trap_instruction(void) { __asm__ volatile("int $0x03"); } #elif defined(__thumb__) -enum { HAVE_TRAP_INSTRUCTION = 1, }; + #define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_TRAP_INSTRUCTION /* FIXME: handle __THUMB_INTERWORK__ */ __attribute__((gnu_inline, always_inline)) __inline__ static void trap_instruction(void) @@ -69,30 +64,37 @@ __inline__ static void trap_instruction(void) #endif /* Known problem: - * After a breakpoint hit, can't stepi, step, or continue in GDB. - * 'step' stuck on the same instruction. + * After a breakpoint hit, can't 'stepi', 'step', or 'continue' in GDB. + * 'step' would keep getting stuck on the same instruction. * - * Workaround: a new GDB command, - * 'debugbreak-step' is defined in debugbreak-gdb.py - * that does: + * Workaround: use the new GDB commands 'debugbreak-step' and + * 'debugbreak-continue' that become available + * after you source the script from GDB: + * + * $ gdb -x debugbreak-gdb.py <... USUAL ARGUMENTS ...> + * + * 'debugbreak-step' would jump over the breakpoint instruction with + * roughly equivalent of: * (gdb) set $instruction_len = 2 * (gdb) tbreak *($pc + $instruction_len) * (gdb) jump *($pc + $instruction_len) */ } #elif defined(__arm__) && !defined(__thumb__) -enum { HAVE_TRAP_INSTRUCTION = 1 }; + #define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_TRAP_INSTRUCTION __attribute__((gnu_inline, always_inline)) __inline__ static void trap_instruction(void) { /* See 'arm-linux-tdep.c' in GDB source, * 'eabi_linux_arm_le_breakpoint' */ __asm__ volatile(".inst 0xe7f001f0"); - /* Has same known problem and workaround - * as Thumb mode */ + /* Known problem: + * Same problem and workaround as Thumb mode */ } +#elif defined(__aarch64__) && defined(__APPLE__) + #define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_BULTIN_TRAP #elif defined(__aarch64__) -enum { HAVE_TRAP_INSTRUCTION = 1 }; + #define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_TRAP_INSTRUCTION __attribute__((gnu_inline, always_inline)) __inline__ static void trap_instruction(void) { @@ -100,42 +102,57 @@ __inline__ static void trap_instruction(void) * 'aarch64_default_breakpoint' */ __asm__ volatile(".inst 0xd4200000"); } +#elif defined(__powerpc__) + /* PPC 32 or 64-bit, big or little endian */ + #define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_TRAP_INSTRUCTION +__attribute__((gnu_inline, always_inline)) +__inline__ static void trap_instruction(void) +{ + /* See 'rs6000-tdep.c' in GDB source, + * 'rs6000_breakpoint' */ + __asm__ volatile(".4byte 0x7d821008"); + + /* Known problem: + * After a breakpoint hit, can't 'stepi', 'step', or 'continue' in GDB. + * 'step' stuck on the same instruction ("twge r2,r2"). + * + * The workaround is the same as ARM Thumb mode: use debugbreak-gdb.py + * or manually jump over the instruction. */ +} #else -enum { HAVE_TRAP_INSTRUCTION = 0 }; + #define DEBUG_BREAK_IMPL DEBUG_BREAK_USE_SIGTRAP #endif + +#ifndef DEBUG_BREAK_IMPL +#error "debugbreak.h is not supported on this target" +#elif DEBUG_BREAK_IMPL == DEBUG_BREAK_USE_TRAP_INSTRUCTION __attribute__((gnu_inline, always_inline)) __inline__ static void debug_break(void) { -#if defined(_WIN32) || defined(_WIN64) - /* SIGTRAP available only on POSIX-compliant operating systems - * use builtin trap instead */ - HAVE_TRAP_INSTRUCTION ? trap_instruction() : __builtin_trap(); -#else - // cppcheck-suppress knownConditionTrueFalse - if (HAVE_TRAP_INSTRUCTION) - { - trap_instruction(); - } - // cppcheck-suppress knownConditionTrueFalse - else if (DEBUG_BREAK_PREFER_BUILTIN_TRAP_TO_SIGTRAP) - { - /* raises SIGILL on Linux x86{,-64}, to continue in gdb: - * (gdb) handle SIGILL stop nopass - * */ - __builtin_trap(); - } - else - { - raise(SIGTRAP); - } -#endif + trap_instruction(); } +#elif DEBUG_BREAK_IMPL == DEBUG_BREAK_USE_BULTIN_TRAP +__attribute__((gnu_inline, always_inline)) +__inline__ static void debug_break(void) +{ + __builtin_trap(); +} +#elif DEBUG_BREAK_IMPL == DEBUG_BREAK_USE_SIGTRAP +#include +__attribute__((gnu_inline, always_inline)) +__inline__ static void debug_break(void) +{ + raise(SIGTRAP); +} +#else +#error "invalid DEBUG_BREAK_IMPL value" +#endif #ifdef __cplusplus } #endif -#endif +#endif /* ifdef _MSC_VER */ -#endif +#endif /* ifndef DEBUG_BREAK_H */