From patchwork Fri Sep 11 12:13:19 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antoine Tremblay X-Patchwork-Id: 8632 Received: (qmail 130791 invoked by alias); 11 Sep 2015 12:14:08 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 130778 invoked by uid 89); 11 Sep 2015 12:14:08 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.3 required=5.0 tests=AWL, BAYES_50, SPF_PASS autolearn=ham version=3.3.2 X-HELO: usevmg21.ericsson.net Received: from usevmg21.ericsson.net (HELO usevmg21.ericsson.net) (198.24.6.65) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-SHA encrypted) ESMTPS; Fri, 11 Sep 2015 12:13:52 +0000 Received: from EUSAAHC003.ericsson.se (Unknown_Domain [147.117.188.81]) by usevmg21.ericsson.net (Symantec Mail Security) with SMTP id 10.5D.26730.6CA52F55; Fri, 11 Sep 2015 06:38:31 +0200 (CEST) Received: from elxa4wqvvz1.dyn.mo.ca.am.ericsson.se (147.117.188.8) by smtps-am.internal.ericsson.com (147.117.188.81) with Microsoft SMTP Server (TLS) id 14.3.248.2; Fri, 11 Sep 2015 08:13:35 -0400 From: Antoine Tremblay To: CC: Antoine Tremblay Subject: [PATCH 3/7] Support multiple breakpoint types per target in GDBServer. Date: Fri, 11 Sep 2015 08:13:19 -0400 Message-ID: <1441973603-15247-4-git-send-email-antoine.tremblay@ericsson.com> In-Reply-To: <1441973603-15247-1-git-send-email-antoine.tremblay@ericsson.com> References: <1441973603-15247-1-git-send-email-antoine.tremblay@ericsson.com> MIME-Version: 1.0 X-IsSubscribed: yes This patch is in preparation for software single stepping on ARM aarch32-linux. It refactors breakpoint and breakpoint_len into breakpoint_from_pc to prepare the case where we have multiple types of breakpoints. breakpoint_from_pc returns the breakpoint for this PC as a string of bytes, the length of the breakpoint and ajusts the PC to the real memory location in case a flag was present in the PC. No regressions, tested on Ubuntu 14.04 on ARMv7 and x86 Also since the target_ops have been changed compilation was tested on all affected archs namely : aarch64, arm, bfin, cris, crisv32, m32r, m68k, mips, nios2, ppc, s390, sh, sparc, tic6x, tile, x86, xtensa gdbserver/ChangeLog: * linux-aarch64-low.c (aarch64_breakpoint_from_pc): New function. * linux-arm-low.c (arm_breakpoint_from_pc): Likewise. * linux-bfin-low.c (bfin_breakpoint_from_pc): Likewise. * linux-cris-low.c (cris_breakpoint_from_pc): Likewise. * linux-crisv32-low.c: (cris_breakpoint_from_pc): Likewise. * linux-low.c (linux_wait_1): Add call to breakpoint_from_pc. (linux_breakpoint_from_pc): New function. (initialize_low): Add call to breakpoint_from_pc. * linux-low.h: Add breakpoint_from_pc operation. * linux-m32r-low.c (m32r_breakpoint_from_pc): New function. * linux-m68k-low.c (m68k_breakpoint_from_pc): Likewise. * linux-mips-low.c (mips_breakpoint_from_pc): Likewise. * linux-nios2-low.c (nios2_breakpoint_from_pc): Likewise. * linux-ppc-low.c (ppc_breakpoint_from_pc): Likewise. * linux-s390-low.c (s390_breakpoint_from_pc): Likewise. * linux-sh-low.c (sh_breakpoint_from_pc): Likewise. * linux-sparc-low.c (sparc_breakpoint_from_pc): Likewise. * linux-tic6x-low.c (tic6x_breakpoint_from_pc): Likewise. * linux-tile-low.c (tile_breakpoint_from_pc): Likewise. * linux-x86-low.c (x86_breakpoint_from_pc): Likewise. * linux-xtensa-low.c(xtensa_breakpoint_from_pc): Likewise. * target.h (struct target_ops): Add breakpoint_from_pc operation. * win32-arm-low.c (arm_wince_breakpoint_from_pc): New Function. * win32-i386-low.c(i386_win32_breakpoint_from_pc): Likewise. --- gdb/gdbserver/linux-aarch64-low.c | 10 ++++++++-- gdb/gdbserver/linux-arm-low.c | 28 ++++++++++++++++------------ gdb/gdbserver/linux-bfin-low.c | 10 ++++++++-- gdb/gdbserver/linux-cris-low.c | 12 +++++++++--- gdb/gdbserver/linux-crisv32-low.c | 10 ++++++++-- gdb/gdbserver/linux-low.c | 28 +++++++++++++++++++++++++--- gdb/gdbserver/linux-low.h | 9 +++++++-- gdb/gdbserver/linux-m32r-low.c | 10 ++++++++-- gdb/gdbserver/linux-m68k-low.c | 10 ++++++++-- gdb/gdbserver/linux-mips-low.c | 10 ++++++++-- gdb/gdbserver/linux-nios2-low.c | 22 +++++++++++++--------- gdb/gdbserver/linux-ppc-low.c | 10 ++++++++-- gdb/gdbserver/linux-s390-low.c | 10 ++++++++-- gdb/gdbserver/linux-sh-low.c | 10 ++++++++-- gdb/gdbserver/linux-sparc-low.c | 9 +++++++-- gdb/gdbserver/linux-tic6x-low.c | 13 +++++++++---- gdb/gdbserver/linux-tile-low.c | 10 ++++++++-- gdb/gdbserver/linux-x86-low.c | 10 ++++++++-- gdb/gdbserver/linux-xtensa-low.c | 10 ++++++++-- gdb/gdbserver/target.h | 5 +++++ gdb/gdbserver/win32-arm-low.c | 10 ++++++++-- gdb/gdbserver/win32-i386-low.c | 10 ++++++++-- 22 files changed, 203 insertions(+), 63 deletions(-) diff --git a/gdb/gdbserver/linux-aarch64-low.c b/gdb/gdbserver/linux-aarch64-low.c index aebf1e3..0b2c5f1 100644 --- a/gdb/gdbserver/linux-aarch64-low.c +++ b/gdb/gdbserver/linux-aarch64-low.c @@ -200,6 +200,13 @@ aarch64_set_pc (struct regcache *regcache, CORE_ADDR pc) (aarch64_default_breakpoint). */ static const gdb_byte aarch64_breakpoint[] = {0x00, 0x00, 0x20, 0xd4}; +static const unsigned char * +aarch64_breakpoint_from_pc (CORE_ADDR *pcptr, int *len) +{ + *len = aarch64_breakpoint_len; + return (const unsigned char *) &aarch64_breakpoint; +} + /* Implementation of linux_target_ops method "breakpoint_at". */ static int @@ -569,8 +576,7 @@ struct linux_target_ops the_low_target = NULL, /* fetch_register */ aarch64_get_pc, aarch64_set_pc, - (const unsigned char *) &aarch64_breakpoint, - aarch64_breakpoint_len, + aarch64_breakpoint_from_pc, NULL, /* breakpoint_reinsert_addr */ 0, /* decr_pc_after_break */ aarch64_breakpoint_at, diff --git a/gdb/gdbserver/linux-arm-low.c b/gdb/gdbserver/linux-arm-low.c index a277bb6..367c704 100644 --- a/gdb/gdbserver/linux-arm-low.c +++ b/gdb/gdbserver/linux-arm-low.c @@ -913,6 +913,21 @@ arm_regs_info (void) return ®s_info_arm; } +static const unsigned char * +arm_breakpoint_from_pc (CORE_ADDR *pcptr, int *len) +{ + *len = arm_breakpoint_len; + /* Define an ARM-mode breakpoint; we only set breakpoints in the C + library, which is most likely to be ARM. If the kernel supports + clone events, we will never insert a breakpoint, so even a Thumb + C library will work; so will mixing EABI/non-EABI gdbserver and + application. */ +#ifndef __ARM_EABI__ + return (const unsigned char *) &arm_breakpoint; +#else + return (const unsigned char *) &arm_eabi_breakpoint; +#endif +} struct linux_target_ops the_low_target = { arm_arch_setup, arm_regs_info, @@ -921,18 +936,7 @@ struct linux_target_ops the_low_target = { NULL, /* fetch_register */ arm_get_pc, arm_set_pc, - - /* Define an ARM-mode breakpoint; we only set breakpoints in the C - library, which is most likely to be ARM. If the kernel supports - clone events, we will never insert a breakpoint, so even a Thumb - C library will work; so will mixing EABI/non-EABI gdbserver and - application. */ -#ifndef __ARM_EABI__ - (const unsigned char *) &arm_breakpoint, -#else - (const unsigned char *) &arm_eabi_breakpoint, -#endif - arm_breakpoint_len, + arm_breakpoint_from_pc, arm_reinsert_addr, 0, arm_breakpoint_at, diff --git a/gdb/gdbserver/linux-bfin-low.c b/gdb/gdbserver/linux-bfin-low.c index 4002f22..1c0e1e9 100644 --- a/gdb/gdbserver/linux-bfin-low.c +++ b/gdb/gdbserver/linux-bfin-low.c @@ -75,6 +75,13 @@ bfin_set_pc (struct regcache *regcache, CORE_ADDR pc) #define bfin_breakpoint_len 2 static const unsigned char bfin_breakpoint[bfin_breakpoint_len] = {0xa1, 0x00}; +static const unsigned char * +bfin_breakpoint_from_pc (CORE_ADDR *pcptr, int *len) +{ + *len = bfin_breakpoint_len; + return (const unsigned char *) &bfin_breakpoint; +} + static int bfin_breakpoint_at (CORE_ADDR where) { @@ -122,8 +129,7 @@ struct linux_target_ops the_low_target = { NULL, /* fetch_register */ bfin_get_pc, bfin_set_pc, - bfin_breakpoint, - bfin_breakpoint_len, + bfin_breakpoint_from_pc, NULL, /* breakpoint_reinsert_addr */ 2, bfin_breakpoint_at, diff --git a/gdb/gdbserver/linux-cris-low.c b/gdb/gdbserver/linux-cris-low.c index e0bfa1a..da5876d 100644 --- a/gdb/gdbserver/linux-cris-low.c +++ b/gdb/gdbserver/linux-cris-low.c @@ -62,7 +62,7 @@ cris_cannot_fetch_register (int regno) extern int debug_threads; static CORE_ADDR -cris_get_pc (struct regcache *regcache, void) +cris_get_pc (struct regcache *regcache) { unsigned long pc; collect_register_by_name (regcache, "pc", &pc); @@ -81,6 +81,13 @@ cris_set_pc (struct regcache *regcache, CORE_ADDR pc) static const unsigned short cris_breakpoint = 0xe938; #define cris_breakpoint_len 2 +static const unsigned char * +cris_breakpoint_from_pc (CORE_ADDR *pcptr, int *len) +{ + *len = cris_breakpoint_len; + return (const unsigned char *) &cris_breakpoint; +} + static int cris_breakpoint_at (CORE_ADDR where) { @@ -140,8 +147,7 @@ struct linux_target_ops the_low_target = { NULL, /* fetch_register */ cris_get_pc, cris_set_pc, - (const unsigned char *) &cris_breakpoint, - cris_breakpoint_len, + cris_breakpoint_from_pc, cris_reinsert_addr, 0, cris_breakpoint_at, diff --git a/gdb/gdbserver/linux-crisv32-low.c b/gdb/gdbserver/linux-crisv32-low.c index 5120863..d2dba91 100644 --- a/gdb/gdbserver/linux-crisv32-low.c +++ b/gdb/gdbserver/linux-crisv32-low.c @@ -77,6 +77,13 @@ cris_set_pc (struct regcache *regcache, CORE_ADDR pc) static const unsigned short cris_breakpoint = 0xe938; #define cris_breakpoint_len 2 +static const unsigned char * +cris_breakpoint_from_pc (CORE_ADDR *pcptr, int *len) +{ + *len = cris_breakpoint_len; + return (const unsigned char *) &cris_breakpoint; +} + static int cris_breakpoint_at (CORE_ADDR where) { @@ -420,8 +427,7 @@ struct linux_target_ops the_low_target = { NULL, /* fetch_register */ cris_get_pc, cris_set_pc, - (const unsigned char *) &cris_breakpoint, - cris_breakpoint_len, + cris_breakpoint_from_pc, cris_reinsert_addr, 0, cris_breakpoint_at, diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c index 7d979f8..ef6075b 100644 --- a/gdb/gdbserver/linux-low.c +++ b/gdb/gdbserver/linux-low.c @@ -2929,7 +2929,11 @@ linux_wait_1 (ptid_t ptid, (event_child->stepping || !reinsert_breakpoint_inserted_here (event_child->stop_pc))) { - unsigned int increment_pc = the_low_target.breakpoint_len; + int increment_pc = 0; + CORE_ADDR stop_pc = event_child->stop_pc; + + (*the_low_target.breakpoint_from_pc) + (&stop_pc, &increment_pc); if (debug_threads) { @@ -6861,6 +6865,17 @@ current_lwp_ptid (void) return ptid_of (current_thread); } +const unsigned char * +linux_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr) +{ + if (the_low_target.breakpoint_from_pc != NULL) + { + return (*the_low_target.breakpoint_from_pc) (pcptr, lenptr); + } + else + return NULL; +} + static struct target_ops linux_target_ops = { linux_create_inferior, linux_arch_setup, @@ -6954,6 +6969,7 @@ static struct target_ops linux_target_ops = { linux_mntns_open_cloexec, linux_mntns_unlink, linux_mntns_readlink, + linux_breakpoint_from_pc, }; static void @@ -6981,10 +6997,16 @@ void initialize_low (void) { struct sigaction sigchld_action; + int breakpoint_len = 0; + const unsigned char *breakpoint = NULL; + memset (&sigchld_action, 0, sizeof (sigchld_action)); set_target_ops (&linux_target_ops); - set_breakpoint_data (the_low_target.breakpoint, - the_low_target.breakpoint_len); + + breakpoint = the_target->breakpoint_from_pc (NULL, &breakpoint_len); + + set_breakpoint_data (breakpoint, + breakpoint_len); linux_init_signals (); linux_ptrace_init_warnings (); diff --git a/gdb/gdbserver/linux-low.h b/gdb/gdbserver/linux-low.h index f8f6e78..c623150 100644 --- a/gdb/gdbserver/linux-low.h +++ b/gdb/gdbserver/linux-low.h @@ -141,8 +141,13 @@ struct linux_target_ops CORE_ADDR (*get_pc) (struct regcache *regcache); void (*set_pc) (struct regcache *regcache, CORE_ADDR newpc); - const unsigned char *breakpoint; - int breakpoint_len; + + /* Return the raw breakpoint for this target based on PC. Note that the PC + can be NULL, the default breakpoint for the target should be returned in + this case. The PC is ajusted to the real memory location in case a flag was + present in the PC. */ + const unsigned char *(*breakpoint_from_pc) (CORE_ADDR *pcptr, int *lenptr); + CORE_ADDR (*breakpoint_reinsert_addr) (void); int decr_pc_after_break; diff --git a/gdb/gdbserver/linux-m32r-low.c b/gdb/gdbserver/linux-m32r-low.c index 8ffeda2..4712a32 100644 --- a/gdb/gdbserver/linux-m32r-low.c +++ b/gdb/gdbserver/linux-m32r-low.c @@ -73,6 +73,13 @@ m32r_set_pc (struct regcache *regcache, CORE_ADDR pc) static const unsigned short m32r_breakpoint = 0x10f1; #define m32r_breakpoint_len 2 +static const unsigned char * +m32r_breakpoint_from_pc (CORE_ADDR *pcptr, int *len) +{ + *len = m32r_breakpoint_len; + return (const unsigned char *) &m32r_breakpoint; +} + static int m32r_breakpoint_at (CORE_ADDR where) { @@ -120,8 +127,7 @@ struct linux_target_ops the_low_target = { NULL, /* fetch_register */ m32r_get_pc, m32r_set_pc, - (const unsigned char *) &m32r_breakpoint, - m32r_breakpoint_len, + m32r_breakpoint_from_pc, NULL, 0, m32r_breakpoint_at, diff --git a/gdb/gdbserver/linux-m68k-low.c b/gdb/gdbserver/linux-m68k-low.c index 39c9cc5..39a9753 100644 --- a/gdb/gdbserver/linux-m68k-low.c +++ b/gdb/gdbserver/linux-m68k-low.c @@ -125,6 +125,13 @@ static struct regset_info m68k_regsets[] = { static const unsigned char m68k_breakpoint[] = { 0x4E, 0x4F }; #define m68k_breakpoint_len 2 +static const unsigned char * +m68k_breakpoint_from_pc (CORE_ADDR *pcptr, int *len) +{ + *len = m68k_breakpoint_len; + return (unsigned char*) &m68k_breakpoint; +} + static CORE_ADDR m68k_get_pc (struct regcache *regcache) { @@ -215,8 +222,7 @@ struct linux_target_ops the_low_target = { NULL, /* fetch_register */ m68k_get_pc, m68k_set_pc, - m68k_breakpoint, - m68k_breakpoint_len, + m68k_breakpoint_from_pc, NULL, 2, m68k_breakpoint_at, diff --git a/gdb/gdbserver/linux-mips-low.c b/gdb/gdbserver/linux-mips-low.c index d1181b6..d5333ab 100644 --- a/gdb/gdbserver/linux-mips-low.c +++ b/gdb/gdbserver/linux-mips-low.c @@ -266,6 +266,13 @@ mips_set_pc (struct regcache *regcache, CORE_ADDR pc) static const unsigned int mips_breakpoint = 0x0005000d; #define mips_breakpoint_len 4 +static const unsigned char * +mips_breakpoint_from_pc (CORE_ADDR *pcptr, int *len) +{ + *len = mips_breakpoint_len; + return (const unsigned char *) &mips_breakpoint; +} + /* We only place breakpoints in empty marker functions, and thread locking is outside of the function. So rather than importing software single-step, we can just run until exit. */ @@ -881,8 +888,7 @@ struct linux_target_ops the_low_target = { NULL, /* fetch_register */ mips_get_pc, mips_set_pc, - (const unsigned char *) &mips_breakpoint, - mips_breakpoint_len, + mips_breakpoint_from_pc, mips_reinsert_addr, 0, mips_breakpoint_at, diff --git a/gdb/gdbserver/linux-nios2-low.c b/gdb/gdbserver/linux-nios2-low.c index 71542b4..bf9ecc2 100644 --- a/gdb/gdbserver/linux-nios2-low.c +++ b/gdb/gdbserver/linux-nios2-low.c @@ -119,7 +119,6 @@ nios2_set_pc (struct regcache *regcache, CORE_ADDR pc) /* Breakpoint support. Also see comments on nios2_breakpoint_from_pc in nios2-tdep.c. */ - #if defined(__nios2_arch__) && __nios2_arch__ == 2 #define NIOS2_BREAKPOINT 0xb7fd0020 #define CDX_BREAKPOINT 0xd7c9 @@ -127,9 +126,21 @@ nios2_set_pc (struct regcache *regcache, CORE_ADDR pc) #define NIOS2_BREAKPOINT 0x003b6ffa #endif +/* We only register the 4-byte breakpoint, even on R2 targets which also + support 2-byte breakpoints. Since there is no supports_z_point_type + function provided, gdbserver never inserts software breakpoints itself + and instead relies on GDB to insert the breakpoint of the correct length + via a memory write. */ static const unsigned int nios2_breakpoint = NIOS2_BREAKPOINT; #define nios2_breakpoint_len 4 +static const unsigned char * +nios2_breakpoint_from_pc (CORE_ADDR *pcptr, int *len) +{ + *len = nios2_breakpoint_len; + return (const unsigned char *) &nios2_breakpoint; +} + /* Implement the breakpoint_reinsert_addr linux_target_ops method. */ static CORE_ADDR @@ -263,14 +274,7 @@ struct linux_target_ops the_low_target = NULL, nios2_get_pc, nios2_set_pc, - - /* We only register the 4-byte breakpoint, even on R2 targets which also - support 2-byte breakpoints. Since there is no supports_z_point_type - function provided, gdbserver never inserts software breakpoints itself - and instead relies on GDB to insert the breakpoint of the correct length - via a memory write. */ - (const unsigned char *) &nios2_breakpoint, - nios2_breakpoint_len, + nios2_breakpoint_from_pc, nios2_reinsert_addr, 0, nios2_breakpoint_at, diff --git a/gdb/gdbserver/linux-ppc-low.c b/gdb/gdbserver/linux-ppc-low.c index 188fac0..4c71cd9 100644 --- a/gdb/gdbserver/linux-ppc-low.c +++ b/gdb/gdbserver/linux-ppc-low.c @@ -486,6 +486,13 @@ ppc_arch_setup (void) static const unsigned int ppc_breakpoint = 0x7d821008; #define ppc_breakpoint_len 4 +static const unsigned char * +ppc_breakpoint_from_pc (CORE_ADDR *pcptr, int *len) +{ + *len = ppc_breakpoint_len; + return (const unsigned char *) &ppc_breakpoint; +} + static int ppc_breakpoint_at (CORE_ADDR where) { @@ -685,8 +692,7 @@ struct linux_target_ops the_low_target = { NULL, /* fetch_register */ ppc_get_pc, ppc_set_pc, - (const unsigned char *) &ppc_breakpoint, - ppc_breakpoint_len, + ppc_breakpoint_from_pc, NULL, 0, ppc_breakpoint_at, diff --git a/gdb/gdbserver/linux-s390-low.c b/gdb/gdbserver/linux-s390-low.c index 8a0a689..f76f867 100644 --- a/gdb/gdbserver/linux-s390-low.c +++ b/gdb/gdbserver/linux-s390-low.c @@ -397,6 +397,13 @@ static struct regset_info s390_regsets[] = { static const unsigned char s390_breakpoint[] = { 0, 1 }; #define s390_breakpoint_len 2 +static const unsigned char * +s390_breakpoint_from_pc (CORE_ADDR *pcptr, int *len) +{ + *len = s390_breakpoint_len; + return (const unsigned char *) &s390_breakpoint; +} + static CORE_ADDR s390_get_pc (struct regcache *regcache) { @@ -665,8 +672,7 @@ struct linux_target_ops the_low_target = { NULL, /* fetch_register */ s390_get_pc, s390_set_pc, - s390_breakpoint, - s390_breakpoint_len, + s390_breakpoint_from_pc, NULL, s390_breakpoint_len, s390_breakpoint_at, diff --git a/gdb/gdbserver/linux-sh-low.c b/gdb/gdbserver/linux-sh-low.c index 218d4d3..5c11fd7 100644 --- a/gdb/gdbserver/linux-sh-low.c +++ b/gdb/gdbserver/linux-sh-low.c @@ -77,6 +77,13 @@ sh_set_pc (struct regcache *regcache, CORE_ADDR pc) static const unsigned short sh_breakpoint = 0xc3c3; #define sh_breakpoint_len 2 +static const unsigned char * +sh_breakpoint_from_pc (CORE_ADDR *pcptr, int *len) +{ + *len = sh_breakpoint_len; + return (const unsigned char *) &sh_breakpoint; +} + static int sh_breakpoint_at (CORE_ADDR where) { @@ -148,8 +155,7 @@ struct linux_target_ops the_low_target = { NULL, /* fetch_register */ sh_get_pc, sh_set_pc, - (const unsigned char *) &sh_breakpoint, - sh_breakpoint_len, + sh_breakpoint_from_pc, NULL, 0, sh_breakpoint_at, diff --git a/gdb/gdbserver/linux-sparc-low.c b/gdb/gdbserver/linux-sparc-low.c index 796af8a..35820fb 100644 --- a/gdb/gdbserver/linux-sparc-low.c +++ b/gdb/gdbserver/linux-sparc-low.c @@ -240,6 +240,12 @@ static const unsigned char sparc_breakpoint[INSN_SIZE] = { }; #define sparc_breakpoint_len INSN_SIZE +static const unsigned char * +sparc_breakpoint_from_pc (CORE_ADDR *pcptr, int *len) +{ + *len = sparc_breakpoint_len; + return (const unsigned char *) &sparc_breakpoint; +} static int sparc_breakpoint_at (CORE_ADDR where) @@ -323,8 +329,7 @@ struct linux_target_ops the_low_target = { sparc_get_pc, /* No sparc_set_pc is needed. */ NULL, - (const unsigned char *) sparc_breakpoint, - sparc_breakpoint_len, + sparc_breakpoint_from_pc, sparc_reinsert_addr, 0, sparc_breakpoint_at, diff --git a/gdb/gdbserver/linux-tic6x-low.c b/gdb/gdbserver/linux-tic6x-low.c index a2ac3ee..86b433c 100644 --- a/gdb/gdbserver/linux-tic6x-low.c +++ b/gdb/gdbserver/linux-tic6x-low.c @@ -171,6 +171,14 @@ extern struct linux_target_ops the_low_target; static int *tic6x_regmap; static unsigned int tic6x_breakpoint; +#define tic6x_breakpoint_len 4 + +static const unsigned char * +tic6x_breakpoint_from_pc (CORE_ADDR *pcptr, int *len) +{ + *len = tic6x_breakpoint_len; + return (const unsigned char *) &tic6x_breakpoint; +} /* Forward definition. */ static struct usrregs_info tic6x_usrregs_info; @@ -247,8 +255,6 @@ tic6x_set_pc (struct regcache *regcache, CORE_ADDR pc) supply_register_by_name (regcache, "PC", newpc.buf); } -#define tic6x_breakpoint_len 4 - static int tic6x_breakpoint_at (CORE_ADDR where) { @@ -367,8 +373,7 @@ struct linux_target_ops the_low_target = { NULL, /* fetch_register */ tic6x_get_pc, tic6x_set_pc, - (const unsigned char *) &tic6x_breakpoint, - tic6x_breakpoint_len, + tic6x_breakpoint_from_pc, NULL, 0, tic6x_breakpoint_at, diff --git a/gdb/gdbserver/linux-tile-low.c b/gdb/gdbserver/linux-tile-low.c index 6aaea6a..802812b 100644 --- a/gdb/gdbserver/linux-tile-low.c +++ b/gdb/gdbserver/linux-tile-low.c @@ -88,6 +88,13 @@ tile_set_pc (struct regcache *regcache, CORE_ADDR pc) static uint64_t tile_breakpoint = 0x400b3cae70166000ULL; #define tile_breakpoint_len 8 +static const unsigned char * +tile_breakpoint_from_pc (CORE_ADDR *pcptr, int *len) +{ + *len = tile_breakpoint_len; + return (const unsigned char *) &tile_breakpoint; +} + static int tile_breakpoint_at (CORE_ADDR where) { @@ -182,8 +189,7 @@ struct linux_target_ops the_low_target = NULL, tile_get_pc, tile_set_pc, - (const unsigned char *) &tile_breakpoint, - tile_breakpoint_len, + tile_breakpoint_from_pc, NULL, 0, tile_breakpoint_at, diff --git a/gdb/gdbserver/linux-x86-low.c b/gdb/gdbserver/linux-x86-low.c index 20d4257..699eb4d 100644 --- a/gdb/gdbserver/linux-x86-low.c +++ b/gdb/gdbserver/linux-x86-low.c @@ -3243,6 +3243,13 @@ x86_emit_ops (void) return &i386_emit_ops; } +static const unsigned char * +x86_breakpoint_from_pc (CORE_ADDR *pcptr, int *len) +{ + *len = x86_breakpoint_len; + return x86_breakpoint; +} + static int x86_supports_range_stepping (void) { @@ -3261,8 +3268,7 @@ struct linux_target_ops the_low_target = NULL, /* fetch_register */ x86_get_pc, x86_set_pc, - x86_breakpoint, - x86_breakpoint_len, + x86_breakpoint_from_pc, NULL, 1, x86_breakpoint_at, diff --git a/gdb/gdbserver/linux-xtensa-low.c b/gdb/gdbserver/linux-xtensa-low.c index debe467..1e2cf94 100644 --- a/gdb/gdbserver/linux-xtensa-low.c +++ b/gdb/gdbserver/linux-xtensa-low.c @@ -154,6 +154,13 @@ static struct regset_info xtensa_regsets[] = { static const unsigned char xtensa_breakpoint[] = XTENSA_BREAKPOINT; #define xtensa_breakpoint_len 2 +static const unsigned char * +xtensa_breakpoint_from_pc (CORE_ADDR *pcptr, int *len) +{ + *len = xtensa_breakpoint_len; + return xtensa_breakpoint; +} + static CORE_ADDR xtensa_get_pc (struct regcache *regcache) { @@ -234,8 +241,7 @@ struct linux_target_ops the_low_target = { NULL, /* fetch_register */ xtensa_get_pc, xtensa_set_pc, - xtensa_breakpoint, - xtensa_breakpoint_len, + xtensa_breakpoint_from_pc, NULL, 0, xtensa_breakpoint_at, diff --git a/gdb/gdbserver/target.h b/gdb/gdbserver/target.h index 7df8df3..fc2dbd7 100644 --- a/gdb/gdbserver/target.h +++ b/gdb/gdbserver/target.h @@ -438,6 +438,11 @@ struct target_ops readlink(2). */ ssize_t (*multifs_readlink) (int pid, const char *filename, char *buf, size_t bufsiz); + + /* Return the raw breakpoint for this target based on PC. Note that the PC + can be NULL, the default breakpoint for the target should be returned in + this case. */ + const unsigned char *(*breakpoint_from_pc) (CORE_ADDR *pcptr, int *lenptr); }; extern struct target_ops *the_target; diff --git a/gdb/gdbserver/win32-arm-low.c b/gdb/gdbserver/win32-arm-low.c index d4b2c6f..1b469a3 100644 --- a/gdb/gdbserver/win32-arm-low.c +++ b/gdb/gdbserver/win32-arm-low.c @@ -113,6 +113,13 @@ arm_arch_setup (void) static const unsigned long arm_wince_breakpoint = 0xe6000010; #define arm_wince_breakpoint_len 4 +static const unsigned char * +arm_wince_breakpoint_from_pc (CORE_ADDR *pcptr, int *len) +{ + *len = arm_wince_breakpoint_len; + return (const unsigned char *) &arm_wince_breakpoint; +} + struct win32_target_ops the_low_target = { arm_arch_setup, sizeof (mappings) / sizeof (mappings[0]), @@ -123,8 +130,7 @@ struct win32_target_ops the_low_target = { arm_fetch_inferior_register, arm_store_inferior_register, NULL, /* single_step */ - (const unsigned char *) &arm_wince_breakpoint, - arm_wince_breakpoint_len, + arm_wince_breakpoint_from_pc, /* Watchpoint related functions. See target.h for comments. */ NULL, /* supports_z_point_type */ NULL, /* insert_point */ diff --git a/gdb/gdbserver/win32-i386-low.c b/gdb/gdbserver/win32-i386-low.c index 7c22f05..b9d60a7 100644 --- a/gdb/gdbserver/win32-i386-low.c +++ b/gdb/gdbserver/win32-i386-low.c @@ -444,6 +444,13 @@ i386_store_inferior_register (struct regcache *regcache, static const unsigned char i386_win32_breakpoint = 0xcc; #define i386_win32_breakpoint_len 1 +static const unsigned char * +i386_win32_breakpoint_from_pc (CORE_ADDR *pcptr, int *len) +{ + *len = i386_win32_breakpoint_len; + return (const unsigned char *) &i386_win32_breakpoint; +} + static void i386_arch_setup (void) { @@ -466,8 +473,7 @@ struct win32_target_ops the_low_target = { i386_fetch_inferior_register, i386_store_inferior_register, i386_single_step, - &i386_win32_breakpoint, - i386_win32_breakpoint_len, + i386_win32_breakpoint_from_pc, i386_supports_z_point_type, i386_insert_point, i386_remove_point,