From patchwork Mon Oct 5 16:44:09 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antoine Tremblay X-Patchwork-Id: 8929 Received: (qmail 130086 invoked by alias); 5 Oct 2015 16:44:44 -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 129916 invoked by uid 89); 5 Oct 2015 16:44:43 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.6 required=5.0 tests=AWL, BAYES_00, 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; Mon, 05 Oct 2015 16:44:35 +0000 Received: from EUSAAHC003.ericsson.se (Unknown_Domain [147.117.188.81]) by usevmg21.ericsson.net (Symantec Mail Security) with SMTP id 6E.E3.26730.80D32165; Mon, 5 Oct 2015 11:04:09 +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; Mon, 5 Oct 2015 12:44:31 -0400 From: Antoine Tremblay To: CC: Antoine Tremblay Subject: [PATCH v2 1/7] Add breakpoint_from_pc target_ops for software breakpoints in GDBServer. Date: Mon, 5 Oct 2015 12:44:09 -0400 Message-ID: <1444063455-31558-2-git-send-email-antoine.tremblay@ericsson.com> In-Reply-To: <1444063455-31558-1-git-send-email-antoine.tremblay@ericsson.com> References: <1444063455-31558-1-git-send-email-antoine.tremblay@ericsson.com> MIME-Version: 1.0 X-IsSubscribed: yes In this v2 : - Comments added for linux_target_ops method implementation - Removed cris_get_pc (void) change - Removed unneeded {} - Fixed PC/PCPTR comments - Comments adjusted for breakpoint_from_pc - Improved ChangeLog --- Add breakpoint_from_pc target_ops for software breakpoints in GDBServer. This patch is in preparation for software breakpoints on ARM 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 With gdbserver-{native,extended} / { -marm -mthumb } 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, steins. gdb/gdbserver/ChangeLog: * linux-aarch64-low.c (aarch64_breakpoint_from_pc): New function. (struct linux_target_ops) : Remove. (struct linux_target_ops) : Remove. (struct linux_target_ops) : Initialize field. * linux-arm-low.c (arm_breakpoint_from_pc): New function. (struct linux_target_ops) : Remove. (struct linux_target_ops) : Remove. (struct linux_target_ops) : Initialize field. * linux-bfin-low.c (bfin_breakpoint_from_pc): New function. (struct linux_target_ops) : Remove. (struct linux_target_ops) : Remove. (struct linux_target_ops) : Initialize field. * linux-cris-low.c (cris_breakpoint_from_pc): New function. (struct linux_target_ops) : Remove. (struct linux_target_ops) : Remove. (struct linux_target_ops) : Initialize field. * linux-crisv32-low.c (cris_breakpoint_from_pc): New function. (struct linux_target_ops) : Remove. (struct linux_target_ops) : Remove. (struct linux_target_ops) : Initialize field. * linux-low.c (linux_wait_1): Add call to breakpoint_from_pc. (linux_breakpoint_from_pc): New function. (static struct target_ops) : Initialize field. (initialize_low): Add call to breakpoint_from_pc. * linux-low.h (struct linux_target_ops) : New field. * linux-m32r-low.c (m32r_breakpoint_from_pc): New function. (struct linux_target_ops) : Remove. (struct linux_target_ops) : Remove. (struct linux_target_ops) : Initialize field. * linux-m68k-low.c (m68k_breakpoint_from_pc): New function. (struct linux_target_ops) : Remove. (struct linux_target_ops) : Remove. (struct linux_target_ops) : Initialize field. * linux-mips-low.c (mips_breakpoint_from_pc): New function. (struct linux_target_ops) : Remove. (struct linux_target_ops) : Remove. (struct linux_target_ops) : Initialize field. * linux-nios2-low.c (nios2_breakpoint_from_pc): New function. (struct linux_target_ops) : Remove. (struct linux_target_ops) : Remove. (struct linux_target_ops) : Initialize field. * linux-ppc-low.c (ppc_breakpoint_from_pc): New function. (struct linux_target_ops) : Remove. (struct linux_target_ops) : Remove. (struct linux_target_ops) : Initialize field. * linux-s390-low.c (s390_breakpoint_from_pc): Likewise. (struct linux_target_ops) : Remove. (struct linux_target_ops) : Remove. (struct linux_target_ops) : Initialize field. * linux-sh-low.c (sh_breakpoint_from_pc): New function. (struct linux_target_ops) : Remove. (struct linux_target_ops) : Remove. (struct linux_target_ops) : Initialize field. * linux-sparc-low.c (sparc_breakpoint_from_pc): New function. (struct linux_target_ops) : Remove. (struct linux_target_ops) : Remove. (struct linux_target_ops) : Initialize field. * linux-tic6x-low.c (tic6x_breakpoint_from_pc): New function. (struct linux_target_ops) : Remove. (struct linux_target_ops) : Remove. (struct linux_target_ops) : Initialize field. * linux-tile-low.c (tile_breakpoint_from_pc): New function. (struct linux_target_ops) : Remove. (struct linux_target_ops) : Remove. (struct linux_target_ops) : Initialize field. * linux-x86-low.c (x86_breakpoint_from_pc): New function. (struct linux_target_ops) : Remove. (struct linux_target_ops) : Remove. (struct linux_target_ops) : Initialize field. * linux-xtensa-low.c (xtensa_breakpoint_from_pc): New function. (struct linux_target_ops) : Remove. (struct linux_target_ops) : Remove. (struct linux_target_ops) : Initialize field. * target.h (struct target_ops) : New field. --- gdb/gdbserver/linux-aarch64-low.c | 12 ++++++++++-- gdb/gdbserver/linux-arm-low.c | 28 ++++++++++++++++------------ gdb/gdbserver/linux-bfin-low.c | 12 ++++++++++-- gdb/gdbserver/linux-cris-low.c | 12 ++++++++++-- gdb/gdbserver/linux-crisv32-low.c | 12 ++++++++++-- gdb/gdbserver/linux-low.c | 26 +++++++++++++++++++++++--- gdb/gdbserver/linux-low.h | 8 ++++++-- gdb/gdbserver/linux-m32r-low.c | 12 ++++++++++-- gdb/gdbserver/linux-m68k-low.c | 12 ++++++++++-- gdb/gdbserver/linux-mips-low.c | 12 ++++++++++-- gdb/gdbserver/linux-nios2-low.c | 23 +++++++++++++++-------- gdb/gdbserver/linux-ppc-low.c | 12 ++++++++++-- gdb/gdbserver/linux-s390-low.c | 12 ++++++++++-- gdb/gdbserver/linux-sh-low.c | 12 ++++++++++-- gdb/gdbserver/linux-sparc-low.c | 11 +++++++++-- gdb/gdbserver/linux-tic6x-low.c | 15 +++++++++++---- gdb/gdbserver/linux-tile-low.c | 12 ++++++++++-- gdb/gdbserver/linux-x86-low.c | 12 ++++++++++-- gdb/gdbserver/linux-xtensa-low.c | 12 ++++++++++-- gdb/gdbserver/target.h | 5 +++++ 20 files changed, 215 insertions(+), 57 deletions(-) diff --git a/gdb/gdbserver/linux-aarch64-low.c b/gdb/gdbserver/linux-aarch64-low.c index 5592e61..1e7a0ff 100644 --- a/gdb/gdbserver/linux-aarch64-low.c +++ b/gdb/gdbserver/linux-aarch64-low.c @@ -205,6 +205,15 @@ aarch64_set_pc (struct regcache *regcache, CORE_ADDR pc) (aarch64_default_breakpoint). */ static const gdb_byte aarch64_breakpoint[] = {0x00, 0x00, 0x20, 0xd4}; +/* Implementation of linux_target_ops method "breakpoint_from_pc". */ + +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 @@ -3238,8 +3247,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..2dc57b4 100644 --- a/gdb/gdbserver/linux-bfin-low.c +++ b/gdb/gdbserver/linux-bfin-low.c @@ -75,6 +75,15 @@ 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}; +/* Implementation of linux_target_ops method "breakpoint_from_pc". */ + +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 +131,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..64413f8 100644 --- a/gdb/gdbserver/linux-cris-low.c +++ b/gdb/gdbserver/linux-cris-low.c @@ -81,6 +81,15 @@ cris_set_pc (struct regcache *regcache, CORE_ADDR pc) static const unsigned short cris_breakpoint = 0xe938; #define cris_breakpoint_len 2 +/* Implementation of linux_target_ops method "breakpoint_from_pc". */ + +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 +149,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..7e499f2 100644 --- a/gdb/gdbserver/linux-crisv32-low.c +++ b/gdb/gdbserver/linux-crisv32-low.c @@ -77,6 +77,15 @@ cris_set_pc (struct regcache *regcache, CORE_ADDR pc) static const unsigned short cris_breakpoint = 0xe938; #define cris_breakpoint_len 2 +/* Implementation of linux_target_ops method "breakpoint_from_pc". */ + +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 +429,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 3a1a6ae..dc16fe0 100644 --- a/gdb/gdbserver/linux-low.c +++ b/gdb/gdbserver/linux-low.c @@ -3012,7 +3012,11 @@ linux_wait_1 (ptid_t ptid, if (!ptid_equal (step_over_bkpt, null_ptid) && event_child->stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT) { - 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) { @@ -6932,6 +6936,15 @@ 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, @@ -7026,6 +7039,7 @@ static struct target_ops linux_target_ops = { linux_mntns_open_cloexec, linux_mntns_unlink, linux_mntns_readlink, + linux_breakpoint_from_pc, }; static void @@ -7053,10 +7067,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..a9964ac 100644 --- a/gdb/gdbserver/linux-low.h +++ b/gdb/gdbserver/linux-low.h @@ -141,8 +141,12 @@ 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. The PCPTR 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..41c8252 100644 --- a/gdb/gdbserver/linux-m32r-low.c +++ b/gdb/gdbserver/linux-m32r-low.c @@ -73,6 +73,15 @@ m32r_set_pc (struct regcache *regcache, CORE_ADDR pc) static const unsigned short m32r_breakpoint = 0x10f1; #define m32r_breakpoint_len 2 +/* Implementation of linux_target_ops method "breakpoint_from_pc". */ + +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 +129,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..2f0c6a0 100644 --- a/gdb/gdbserver/linux-m68k-low.c +++ b/gdb/gdbserver/linux-m68k-low.c @@ -125,6 +125,15 @@ static struct regset_info m68k_regsets[] = { static const unsigned char m68k_breakpoint[] = { 0x4E, 0x4F }; #define m68k_breakpoint_len 2 +/* Implementation of linux_target_ops method "breakpoint_from_pc". */ + +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 +224,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..96cfc1c 100644 --- a/gdb/gdbserver/linux-mips-low.c +++ b/gdb/gdbserver/linux-mips-low.c @@ -266,6 +266,15 @@ mips_set_pc (struct regcache *regcache, CORE_ADDR pc) static const unsigned int mips_breakpoint = 0x0005000d; #define mips_breakpoint_len 4 +/* Implementation of linux_target_ops method "breakpoint_from_pc". */ + +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 +890,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..d04dbe0 100644 --- a/gdb/gdbserver/linux-nios2-low.c +++ b/gdb/gdbserver/linux-nios2-low.c @@ -127,9 +127,23 @@ 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 +/* Implementation of linux_target_ops method "breakpoint_from_pc". */ + +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 +277,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..92ebb03 100644 --- a/gdb/gdbserver/linux-ppc-low.c +++ b/gdb/gdbserver/linux-ppc-low.c @@ -486,6 +486,15 @@ ppc_arch_setup (void) static const unsigned int ppc_breakpoint = 0x7d821008; #define ppc_breakpoint_len 4 +/* Implementation of linux_target_ops method "breakpoint_from_pc". */ + +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 +694,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..d973f96 100644 --- a/gdb/gdbserver/linux-s390-low.c +++ b/gdb/gdbserver/linux-s390-low.c @@ -397,6 +397,15 @@ static struct regset_info s390_regsets[] = { static const unsigned char s390_breakpoint[] = { 0, 1 }; #define s390_breakpoint_len 2 +/* Implementation of linux_target_ops method "breakpoint_from_pc". */ + +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 +674,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..2b5cb15 100644 --- a/gdb/gdbserver/linux-sh-low.c +++ b/gdb/gdbserver/linux-sh-low.c @@ -77,6 +77,15 @@ sh_set_pc (struct regcache *regcache, CORE_ADDR pc) static const unsigned short sh_breakpoint = 0xc3c3; #define sh_breakpoint_len 2 +/* Implementation of linux_target_ops method "breakpoint_from_pc". */ + +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 +157,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..8e1febf 100644 --- a/gdb/gdbserver/linux-sparc-low.c +++ b/gdb/gdbserver/linux-sparc-low.c @@ -240,6 +240,14 @@ static const unsigned char sparc_breakpoint[INSN_SIZE] = { }; #define sparc_breakpoint_len INSN_SIZE +/* Implementation of linux_target_ops method "breakpoint_from_pc". */ + +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 +331,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..a259e72 100644 --- a/gdb/gdbserver/linux-tic6x-low.c +++ b/gdb/gdbserver/linux-tic6x-low.c @@ -171,6 +171,16 @@ extern struct linux_target_ops the_low_target; static int *tic6x_regmap; static unsigned int tic6x_breakpoint; +#define tic6x_breakpoint_len 4 + +/* Implementation of linux_target_ops method "breakpoint_from_pc". */ + +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 +257,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 +375,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..04c7cd0 100644 --- a/gdb/gdbserver/linux-tile-low.c +++ b/gdb/gdbserver/linux-tile-low.c @@ -88,6 +88,15 @@ tile_set_pc (struct regcache *regcache, CORE_ADDR pc) static uint64_t tile_breakpoint = 0x400b3cae70166000ULL; #define tile_breakpoint_len 8 +/* Implementation of linux_target_ops method "breakpoint_from_pc". */ + +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 +191,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..41803c4 100644 --- a/gdb/gdbserver/linux-x86-low.c +++ b/gdb/gdbserver/linux-x86-low.c @@ -3243,6 +3243,15 @@ x86_emit_ops (void) return &i386_emit_ops; } +/* Implementation of linux_target_ops method "breakpoint_from_pc". */ + +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 +3270,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..eb7c5bb 100644 --- a/gdb/gdbserver/linux-xtensa-low.c +++ b/gdb/gdbserver/linux-xtensa-low.c @@ -154,6 +154,15 @@ static struct regset_info xtensa_regsets[] = { static const unsigned char xtensa_breakpoint[] = XTENSA_BREAKPOINT; #define xtensa_breakpoint_len 2 +/* Implementation of linux_target_ops method "breakpoint_from_pc". */ + +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 +243,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 a2842b4..603819e 100644 --- a/gdb/gdbserver/target.h +++ b/gdb/gdbserver/target.h @@ -441,6 +441,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;