aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/gdbserver/ChangeLog91
-rw-r--r--gdb/gdbserver/linux-aarch64-low.c13
-rw-r--r--gdb/gdbserver/linux-arm-low.c30
-rw-r--r--gdb/gdbserver/linux-bfin-low.c15
-rw-r--r--gdb/gdbserver/linux-cris-low.c13
-rw-r--r--gdb/gdbserver/linux-crisv32-low.c13
-rw-r--r--gdb/gdbserver/linux-low.c45
-rw-r--r--gdb/gdbserver/linux-low.h9
-rw-r--r--gdb/gdbserver/linux-m32r-low.c13
-rw-r--r--gdb/gdbserver/linux-m68k-low.c15
-rw-r--r--gdb/gdbserver/linux-mips-low.c13
-rw-r--r--gdb/gdbserver/linux-nios2-low.c24
-rw-r--r--gdb/gdbserver/linux-ppc-low.c13
-rw-r--r--gdb/gdbserver/linux-s390-low.c15
-rw-r--r--gdb/gdbserver/linux-sh-low.c13
-rw-r--r--gdb/gdbserver/linux-sparc-low.c14
-rw-r--r--gdb/gdbserver/linux-tic6x-low.c16
-rw-r--r--gdb/gdbserver/linux-tile-low.c13
-rw-r--r--gdb/gdbserver/linux-x86-low.c15
-rw-r--r--gdb/gdbserver/linux-xtensa-low.c15
-rw-r--r--gdb/gdbserver/target.h10
21 files changed, 356 insertions, 62 deletions
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index 8e73d9f..10ae158 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,5 +1,96 @@
2015-10-21 Antoine Tremblay <antoine.tremblay@ericsson.com>
+ * linux-aarch64-low.c (aarch64_sw_breakpoint_from_kind): New function.
+ (struct linux_target_ops) <breakpoint>: Remove.
+ (struct linux_target_ops) <breakpoint_len>: Remove.
+ (struct linux_target_ops) <breakpoint_kind_from_pc>: Initialize field.
+ (struct linux_target_ops) <sw_breakpoint_from_kind>: Initialize field.
+ * linux-arm-low.c (arm_breakpoint_kind_from_pc): New function.
+ (arm_sw_breakpoint_from_kind): New function.
+ * linux-bfin-low.c (bfin_sw_breakpoint_from_kind): New function.
+ (struct linux_target_ops) <breakpoint>: Remove.
+ (struct linux_target_ops) <breakpoint_len>: Remove.
+ (struct linux_target_ops) <breakpoint_kind_from_pc>: Initialize field.
+ (struct linux_target_ops) <sw_breakpoint_from_kind>: Initialize field.
+ * linux-cris-low.c (cris_sw_breakpoint_from_kind): New function.
+ (struct linux_target_ops) <breakpoint>: Remove.
+ (struct linux_target_ops) <breakpoint_len>: Remove.
+ (struct linux_target_ops) <breakpoint_kind_from_pc>: Initialize field.
+ (struct linux_target_ops) <sw_breakpoint_from_kind>: Initialize field.
+ * linux-crisv32-low.c (cris_sw_breakpoint_from_kind): New function.
+ (struct linux_target_ops) <breakpoint>: Remove.
+ (struct linux_target_ops) <breakpoint_len>: Remove.
+ (struct linux_target_ops) <breakpoint_kind_from_pc>: Initialize field.
+ (struct linux_target_ops) <sw_breakpoint_from_kind>: Initialize field.
+ * linux-low.c (linux_wait_1): Call breakpoint_kind_from_pc
+ and sw_breakpoint_from_kind to increment the pc.
+ (linux_breakpoint_kind_from_pc): New function.
+ (linux_sw_breakpoint_from_kind): New function.
+ (struct target_ops) <sw_breakpoint_from_kind>: Initialize field.
+ (initialize_low): Call breakpoint_kind_from_pc and
+ sw_breakpoint_from_kind to replace breakpoint_data/len.
+ * linux-low.h (struct linux_target_ops) <breakpoint_kind_from_pc>:
+ New field.
+ (struct linux_target_ops) <sw_breakpoint_from_kind>: Likewise.
+ * linux-m32r-low.c (m32r_sw_breakpoint_from_kind): New function.
+ (struct linux_target_ops) <breakpoint>: Remove.
+ (struct linux_target_ops) <breakpoint_len>: Remove.
+ (struct linux_target_ops) <breakpoint_kind_from_pc>: Initialize field.
+ (struct linux_target_ops) <sw_breakpoint_from_kind>: Initialize field.
+ * linux-m68k-low.c (m68k_sw_breakpoint_from_kind): New function.
+ (struct linux_target_ops) <breakpoint>: Remove.
+ (struct linux_target_ops) <breakpoint_len>: Remove.
+ (struct linux_target_ops) <breakpoint_kind_from_pc>: Initialize field.
+ (struct linux_target_ops) <sw_breakpoint_from_kind>: Initialize field.
+ * linux-mips-low.c (mips_sw_breakpoint_from_kind): New function.
+ (struct linux_target_ops) <breakpoint>: Remove.
+ (struct linux_target_ops) <breakpoint_len>: Remove.
+ (struct linux_target_ops) <breakpoint_kind_from_pc>: Initialize field.
+ (struct linux_target_ops) <sw_breakpoint_from_kind>: Initialize field.
+ * linux-nios2-low.c (nios2_sw_breakpoint_from_kind): New function.
+ (struct linux_target_ops) <breakpoint>: Remove.
+ (struct linux_target_ops) <breakpoint_len>: Remove.
+ (struct linux_target_ops) <breakpoint_kind_from_pc>: Initialize field.
+ (struct linux_target_ops) <sw_breakpoint_from_kind>: Initialize field.
+ * linux-ppc-low.c (ppc_sw_breakpoint_from_kind): New function.
+ (struct linux_target_ops) <breakpoint>: Remove.
+ (struct linux_target_ops) <breakpoint_len>: Remove.
+ (struct linux_target_ops) <breakpoint_kind_from_pc>: Initialize field.
+ (struct linux_target_ops) <sw_breakpoint_from_kind>: Initialize field.
+ * linux-s390-low.c (s390_sw_breakpoint_from_kind): New function.
+ (struct linux_target_ops) <breakpoint>: Remove.
+ (struct linux_target_ops) <breakpoint_len>: Remove.
+ (struct linux_target_ops) <breakpoint_kind_from_pc>: Initialize field.
+ (struct linux_target_ops) <sw_breakpoint_from_kind>: Initialize field.
+ * linux-sh-low.c (sh_sw_breakpoint_from_kind): New function.
+ (struct linux_target_ops) <breakpoint>: Remove.
+ (struct linux_target_ops) <breakpoint_len>: Remove.
+ (struct linux_target_ops) <breakpoint_kind_from_pc>: Initialize field.
+ (struct linux_target_ops) <sw_breakpoint_from_kind>: Initialize field.
+ * linux-sparc-low.c (sparc_sw_breakpoint_from_kind): New function.
+ (struct linux_target_ops) <breakpoint>: Remove.
+ (struct linux_target_ops) <breakpoint_len>: Remove.
+ (struct linux_target_ops) <breakpoint_kind_from_pc>: Initialize field.
+ (struct linux_target_ops) <sw_breakpoint_from_kind>: Initialize field.
+ * linux-tic6x-low.c (tic6x_sw_breakpoint_from_kind): New function.
+ (struct linux_target_ops) <breakpoint>: Remove.
+ (struct linux_target_ops) <breakpoint_len>: Remove.
+ (struct linux_target_ops) <breakpoint_kind_from_pc>: Initialize field.
+ (struct linux_target_ops) <sw_breakpoint_from_kind>: Initialize field.
+ * linux-tile-low.c (tile_sw_breakpoint_from_kind): New function.
+ * linux-x86-low.c (x86_sw_breakpoint_from_kind): New function.
+ (struct linux_target_ops) <breakpoint>: Remove.
+ (struct linux_target_ops) <breakpoint_len>: Remove.
+ (struct linux_target_ops) <breakpoint_kind_from_pc>: Initialize field.
+ (struct linux_target_ops) <sw_breakpoint_from_kind>: Initialize field.
+ * linux-xtensa-low.c (xtensa_sw_breakpoint_from_kind) New function.
+ (struct linux_target_ops) <breakpoint>: Remove.
+ (struct linux_target_ops) <breakpoint_len>: Remove.
+ (struct linux_target_ops) <breakpoint_kind_from_pc>: Initialize field.
+ (struct linux_target_ops) <sw_breakpoint_from_kind>: Initialize field.
+
+2015-10-21 Antoine Tremblay <antoine.tremblay@ericsson.com>
+
* linux-cris-low.c (cris_get_pc): Remove void arg.
2015-10-16 Aleksandar Ristovski <aristovski@qnx.com>
diff --git a/gdb/gdbserver/linux-aarch64-low.c b/gdb/gdbserver/linux-aarch64-low.c
index 780c5e3..cb49a04 100644
--- a/gdb/gdbserver/linux-aarch64-low.c
+++ b/gdb/gdbserver/linux-aarch64-low.c
@@ -2931,6 +2931,15 @@ aarch64_supports_range_stepping (void)
return 1;
}
+/* Implementation of linux_target_ops method "sw_breakpoint_from_kind". */
+
+static const gdb_byte *
+aarch64_sw_breakpoint_from_kind (int kind, int *size)
+{
+ *size = aarch64_breakpoint_len;
+ return aarch64_breakpoint;
+}
+
struct linux_target_ops the_low_target =
{
aarch64_arch_setup,
@@ -2940,8 +2949,8 @@ struct linux_target_ops the_low_target =
NULL, /* fetch_register */
aarch64_get_pc,
aarch64_set_pc,
- (const unsigned char *) &aarch64_breakpoint,
- aarch64_breakpoint_len,
+ NULL, /* breakpoint_kind_from_pc */
+ aarch64_sw_breakpoint_from_kind,
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..3a56620 100644
--- a/gdb/gdbserver/linux-arm-low.c
+++ b/gdb/gdbserver/linux-arm-low.c
@@ -913,26 +913,34 @@ arm_regs_info (void)
return &regs_info_arm;
}
-struct linux_target_ops the_low_target = {
- arm_arch_setup,
- arm_regs_info,
- arm_cannot_fetch_register,
- arm_cannot_store_register,
- NULL, /* fetch_register */
- arm_get_pc,
- arm_set_pc,
+/* Implementation of linux_target_ops method "sw_breakpoint_from_kind". */
+static const gdb_byte *
+arm_sw_breakpoint_from_kind (int kind , int *size)
+{
+ *size = 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__
- (const unsigned char *) &arm_breakpoint,
+ return (const gdb_byte *) &arm_breakpoint;
#else
- (const unsigned char *) &arm_eabi_breakpoint,
+ return (const gdb_byte *) &arm_eabi_breakpoint;
#endif
- arm_breakpoint_len,
+}
+
+struct linux_target_ops the_low_target = {
+ arm_arch_setup,
+ arm_regs_info,
+ arm_cannot_fetch_register,
+ arm_cannot_store_register,
+ NULL, /* fetch_register */
+ arm_get_pc,
+ arm_set_pc,
+ NULL, /* breakpoint_kind_from_pc */
+ arm_sw_breakpoint_from_kind,
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..d3b83fc 100644
--- a/gdb/gdbserver/linux-bfin-low.c
+++ b/gdb/gdbserver/linux-bfin-low.c
@@ -73,7 +73,16 @@ 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 gdb_byte bfin_breakpoint[bfin_breakpoint_len] = {0xa1, 0x00};
+
+/* Implementation of linux_target_ops method "sw_breakpoint_from_kind". */
+
+static const gdb_byte *
+bfin_sw_breakpoint_from_kind (int kind, int *size)
+{
+ *size = bfin_breakpoint_len;
+ return bfin_breakpoint;
+}
static int
bfin_breakpoint_at (CORE_ADDR where)
@@ -122,8 +131,8 @@ struct linux_target_ops the_low_target = {
NULL, /* fetch_register */
bfin_get_pc,
bfin_set_pc,
- bfin_breakpoint,
- bfin_breakpoint_len,
+ NULL, /* breakpoint_kind_from_pc */
+ bfin_sw_breakpoint_from_kind,
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 135e37a..d7b70e3 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 "sw_breakpoint_from_kind". */
+
+static const gdb_byte *
+cris_sw_breakpoint_from_kind (int kind, int *size)
+{
+ *size = cris_breakpoint_len;
+ return (const gdb_byte *) &cris_breakpoint;
+}
+
static int
cris_breakpoint_at (CORE_ADDR where)
{
@@ -140,8 +149,8 @@ struct linux_target_ops the_low_target = {
NULL, /* fetch_register */
cris_get_pc,
cris_set_pc,
- (const unsigned char *) &cris_breakpoint,
- cris_breakpoint_len,
+ NULL, /* breakpoint_kind_from_pc */
+ cris_sw_breakpoint_from_kind,
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..f97122e 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 "sw_breakpoint_from_kind". */
+
+static const gdb_byte *
+cris_sw_breakpoint_from_kind (int kind, int *size)
+{
+ *size = cris_breakpoint_len;
+ return (const gdb_byte *) &cris_breakpoint;
+}
+
static int
cris_breakpoint_at (CORE_ADDR where)
{
@@ -420,8 +429,8 @@ struct linux_target_ops the_low_target = {
NULL, /* fetch_register */
cris_get_pc,
cris_set_pc,
- (const unsigned char *) &cris_breakpoint,
- cris_breakpoint_len,
+ NULL, /* breakpoint_kind_from_pc */
+ cris_sw_breakpoint_from_kind,
cris_reinsert_addr,
0,
cris_breakpoint_at,
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index 3a1a6ae..398c0aa 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -3012,7 +3012,12 @@ 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;
+ int breakpoint_kind = 0;
+ CORE_ADDR stop_pc = event_child->stop_pc;
+
+ breakpoint_kind = the_target->breakpoint_kind_from_pc (&stop_pc);
+ the_target->sw_breakpoint_from_kind (breakpoint_kind, &increment_pc);
if (debug_threads)
{
@@ -6932,6 +6937,28 @@ current_lwp_ptid (void)
return ptid_of (current_thread);
}
+/* Implementation of the target_ops method "breakpoint_kind_from_pc". */
+
+static int
+linux_breakpoint_kind_from_pc (CORE_ADDR *pcptr)
+{
+ if (the_low_target.breakpoint_kind_from_pc != NULL)
+ return (*the_low_target.breakpoint_kind_from_pc) (pcptr);
+ else
+ /* Default breakpoint kind value. */
+ return 0;
+}
+
+/* Implementation of the target_ops method "sw_breakpoint_from_kind". */
+
+static const gdb_byte *
+linux_sw_breakpoint_from_kind (int kind, int *size)
+{
+ gdb_assert (the_low_target.sw_breakpoint_from_kind != NULL);
+
+ return (*the_low_target.sw_breakpoint_from_kind) (kind, size);
+}
+
static struct target_ops linux_target_ops = {
linux_create_inferior,
linux_arch_setup,
@@ -7026,6 +7053,8 @@ static struct target_ops linux_target_ops = {
linux_mntns_open_cloexec,
linux_mntns_unlink,
linux_mntns_readlink,
+ linux_breakpoint_kind_from_pc,
+ linux_sw_breakpoint_from_kind
};
static void
@@ -7053,10 +7082,20 @@ void
initialize_low (void)
{
struct sigaction sigchld_action;
+ int breakpoint_kind = 0;
+ int breakpoint_size = 0;
+ const gdb_byte *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_kind = the_target->breakpoint_kind_from_pc (NULL);
+ breakpoint = the_target->sw_breakpoint_from_kind (breakpoint_kind,
+ &breakpoint_size);
+
+ set_breakpoint_data (breakpoint,
+ breakpoint_size);
+
linux_init_signals ();
linux_ptrace_init_warnings ();
diff --git a/gdb/gdbserver/linux-low.h b/gdb/gdbserver/linux-low.h
index f8f6e78..28dd4db 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;
+
+ /* See target.h for details. */
+ int (*breakpoint_kind_from_pc) (CORE_ADDR *pcptr);
+
+ /* See target.h for details. */
+ const gdb_byte *(*sw_breakpoint_from_kind) (int kind, int *size);
+
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..bb1002f 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 "sw_breakpoint_from_kind". */
+
+static const gdb_byte *
+m32r_sw_breakpoint_from_kind (int kind, int *size)
+{
+ *size = m32r_breakpoint_len;
+ return (const gdb_byte *) &m32r_breakpoint;
+}
+
static int
m32r_breakpoint_at (CORE_ADDR where)
{
@@ -120,8 +129,8 @@ struct linux_target_ops the_low_target = {
NULL, /* fetch_register */
m32r_get_pc,
m32r_set_pc,
- (const unsigned char *) &m32r_breakpoint,
- m32r_breakpoint_len,
+ NULL, /* breakpoint_from_pc */
+ m32r_sw_breakpoint_from_kind,
NULL,
0,
m32r_breakpoint_at,
diff --git a/gdb/gdbserver/linux-m68k-low.c b/gdb/gdbserver/linux-m68k-low.c
index 39c9cc5..ba8e5e9 100644
--- a/gdb/gdbserver/linux-m68k-low.c
+++ b/gdb/gdbserver/linux-m68k-low.c
@@ -122,9 +122,18 @@ static struct regset_info m68k_regsets[] = {
{ 0, 0, 0, -1, -1, NULL, NULL }
};
-static const unsigned char m68k_breakpoint[] = { 0x4E, 0x4F };
+static const gdb_byte m68k_breakpoint[] = { 0x4E, 0x4F };
#define m68k_breakpoint_len 2
+/* Implementation of linux_target_ops method "sw_breakpoint_from_kind". */
+
+static const gdb_byte *
+m68k_sw_breakpoint_from_kind (int kind, int *size)
+{
+ *size = m68k_breakpoint_len;
+ return m68k_breakpoint;
+}
+
static CORE_ADDR
m68k_get_pc (struct regcache *regcache)
{
@@ -215,8 +224,8 @@ struct linux_target_ops the_low_target = {
NULL, /* fetch_register */
m68k_get_pc,
m68k_set_pc,
- m68k_breakpoint,
- m68k_breakpoint_len,
+ NULL, /* breakpoint_kind_from_pc */
+ m68k_sw_breakpoint_from_kind,
NULL,
2,
m68k_breakpoint_at,
diff --git a/gdb/gdbserver/linux-mips-low.c b/gdb/gdbserver/linux-mips-low.c
index d1181b6..344d7a5 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 "sw_breakpoint_from_kind". */
+
+static const gdb_byte *
+mips_sw_breakpoint_from_kind (int kind, int *size)
+{
+ *size = mips_breakpoint_len;
+ return (const gdb_byte *) &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,8 @@ struct linux_target_ops the_low_target = {
NULL, /* fetch_register */
mips_get_pc,
mips_set_pc,
- (const unsigned char *) &mips_breakpoint,
- mips_breakpoint_len,
+ NULL, /* breakpoint_kind_from_pc */
+ mips_sw_breakpoint_from_kind,
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..95a2d9e 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 "sw_breakpoint_from_kind". */
+
+static const gdb_byte *
+nios2_sw_breakpoint_from_kind (int kind, int *size)
+{
+ *size = nios2_breakpoint_len;
+ return (const gdb_byte *) &nios2_breakpoint;
+}
+
/* Implement the breakpoint_reinsert_addr linux_target_ops method. */
static CORE_ADDR
@@ -263,14 +277,8 @@ 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,
+ NULL, /* breakpoint_kind_from_pc */
+ nios2_sw_breakpoint_from_kind,
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..6e6a936 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 "sw_breakpoint_from_kind". */
+
+static const gdb_byte *
+ppc_sw_breakpoint_from_kind (int kind, int *size)
+{
+ *size = ppc_breakpoint_len;
+ return (const gdb_byte *) &ppc_breakpoint;
+}
+
static int
ppc_breakpoint_at (CORE_ADDR where)
{
@@ -685,8 +694,8 @@ struct linux_target_ops the_low_target = {
NULL, /* fetch_register */
ppc_get_pc,
ppc_set_pc,
- (const unsigned char *) &ppc_breakpoint,
- ppc_breakpoint_len,
+ NULL, /* breakpoint_kind_from_pc */
+ ppc_sw_breakpoint_from_kind,
NULL,
0,
ppc_breakpoint_at,
diff --git a/gdb/gdbserver/linux-s390-low.c b/gdb/gdbserver/linux-s390-low.c
index 8a0a689..2ba1221 100644
--- a/gdb/gdbserver/linux-s390-low.c
+++ b/gdb/gdbserver/linux-s390-low.c
@@ -394,9 +394,18 @@ static struct regset_info s390_regsets[] = {
};
-static const unsigned char s390_breakpoint[] = { 0, 1 };
+static const gdb_byte s390_breakpoint[] = { 0, 1 };
#define s390_breakpoint_len 2
+/* Implementation of linux_target_ops method "sw_breakpoint_from_kind". */
+
+static const gdb_byte *
+s390_sw_breakpoint_from_kind (int kind, int *size)
+{
+ *size = s390_breakpoint_len;
+ return s390_breakpoint;
+}
+
static CORE_ADDR
s390_get_pc (struct regcache *regcache)
{
@@ -665,8 +674,8 @@ struct linux_target_ops the_low_target = {
NULL, /* fetch_register */
s390_get_pc,
s390_set_pc,
- s390_breakpoint,
- s390_breakpoint_len,
+ NULL, /* breakpoint_kind_from_pc */
+ s390_sw_breakpoint_from_kind,
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..f7f3239 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 "sw_breakpoint_from_kind". */
+
+static const gdb_byte *
+sh_sw_breakpoint_from_kind (int kind, int *size)
+{
+ *size = sh_breakpoint_len;
+ return (const gdb_byte *) &sh_breakpoint;
+}
+
static int
sh_breakpoint_at (CORE_ADDR where)
{
@@ -148,8 +157,8 @@ struct linux_target_ops the_low_target = {
NULL, /* fetch_register */
sh_get_pc,
sh_set_pc,
- (const unsigned char *) &sh_breakpoint,
- sh_breakpoint_len,
+ NULL, /* breakpoint_kind_from_pc */
+ sh_sw_breakpoint_from_kind,
NULL,
0,
sh_breakpoint_at,
diff --git a/gdb/gdbserver/linux-sparc-low.c b/gdb/gdbserver/linux-sparc-low.c
index 796af8a..0691867 100644
--- a/gdb/gdbserver/linux-sparc-low.c
+++ b/gdb/gdbserver/linux-sparc-low.c
@@ -235,11 +235,19 @@ sparc_get_pc (struct regcache *regcache)
return pc;
}
-static const unsigned char sparc_breakpoint[INSN_SIZE] = {
+static const gdb_byte sparc_breakpoint[INSN_SIZE] = {
0x91, 0xd0, 0x20, 0x01
};
#define sparc_breakpoint_len INSN_SIZE
+/* Implementation of linux_target_ops method "sw_breakpoint_from_kind". */
+
+static const unsigned char *
+sparc_sw_breakpoint_from_kind (int kind, int *size)
+{
+ *size = sparc_breakpoint_len;
+ return sparc_breakpoint;
+}
static int
sparc_breakpoint_at (CORE_ADDR where)
@@ -323,8 +331,8 @@ 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,
+ NULL, /* breakpoint_kind_from_pc */
+ sparc_sw_breakpoint_from_kind,
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..d9476fd 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 "sw_breakpoint_from_kind". */
+
+static const gdb_byte *
+tic6x_sw_breakpoint_from_kind (int kind, int *size)
+{
+ *size = tic6x_breakpoint_len;
+ return (const gdb_byte *) &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,8 @@ struct linux_target_ops the_low_target = {
NULL, /* fetch_register */
tic6x_get_pc,
tic6x_set_pc,
- (const unsigned char *) &tic6x_breakpoint,
- tic6x_breakpoint_len,
+ NULL, /* breakpoint_kind_from_pc */
+ tic6x_sw_breakpoint_from_kind,
NULL,
0,
tic6x_breakpoint_at,
diff --git a/gdb/gdbserver/linux-tile-low.c b/gdb/gdbserver/linux-tile-low.c
index 6aaea6a..e31a620 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 "sw_breakpoint_from_kind". */
+
+static const gdb_byte *
+tile_sw_breakpoint_from_kind (int kind, int *size)
+{
+ *size = tile_breakpoint_len;
+ return (const gdb_byte *) &tile_breakpoint;
+}
+
static int
tile_breakpoint_at (CORE_ADDR where)
{
@@ -182,8 +191,8 @@ struct linux_target_ops the_low_target =
NULL,
tile_get_pc,
tile_set_pc,
- (const unsigned char *) &tile_breakpoint,
- tile_breakpoint_len,
+ NULL, /* breakpoint_kind_from_pc */
+ tile_sw_breakpoint_from_kind,
NULL,
0,
tile_breakpoint_at,
diff --git a/gdb/gdbserver/linux-x86-low.c b/gdb/gdbserver/linux-x86-low.c
index 20d4257..406d552 100644
--- a/gdb/gdbserver/linux-x86-low.c
+++ b/gdb/gdbserver/linux-x86-low.c
@@ -502,7 +502,7 @@ x86_set_pc (struct regcache *regcache, CORE_ADDR pc)
}
}
-static const unsigned char x86_breakpoint[] = { 0xCC };
+static const gdb_byte x86_breakpoint[] = { 0xCC };
#define x86_breakpoint_len 1
static int
@@ -3243,6 +3243,15 @@ x86_emit_ops (void)
return &i386_emit_ops;
}
+/* Implementation of linux_target_ops method "sw_breakpoint_from_kind". */
+
+static const gdb_byte *
+x86_sw_breakpoint_from_kind (int kind, int *size)
+{
+ *size = x86_breakpoint_len;
+ return x86_breakpoint;
+}
+
static int
x86_supports_range_stepping (void)
{
@@ -3261,8 +3270,8 @@ struct linux_target_ops the_low_target =
NULL, /* fetch_register */
x86_get_pc,
x86_set_pc,
- x86_breakpoint,
- x86_breakpoint_len,
+ NULL, /* breakpoint_kind_from_pc */
+ x86_sw_breakpoint_from_kind,
NULL,
1,
x86_breakpoint_at,
diff --git a/gdb/gdbserver/linux-xtensa-low.c b/gdb/gdbserver/linux-xtensa-low.c
index debe467..fa6f418 100644
--- a/gdb/gdbserver/linux-xtensa-low.c
+++ b/gdb/gdbserver/linux-xtensa-low.c
@@ -151,9 +151,18 @@ static struct regset_info xtensa_regsets[] = {
#define XTENSA_BREAKPOINT {0x2d,0xf0}
#endif
-static const unsigned char xtensa_breakpoint[] = XTENSA_BREAKPOINT;
+static const gdb_byte xtensa_breakpoint[] = XTENSA_BREAKPOINT;
#define xtensa_breakpoint_len 2
+/* Implementation of linux_target_ops method "sw_breakpoint_from_kind". */
+
+static const gdb_byte *
+xtensa_sw_breakpoint_from_kind (int kind, int *size)
+{
+ *size = xtensa_breakpoint_len;
+ return xtensa_breakpoint;
+}
+
static CORE_ADDR
xtensa_get_pc (struct regcache *regcache)
{
@@ -234,8 +243,8 @@ struct linux_target_ops the_low_target = {
NULL, /* fetch_register */
xtensa_get_pc,
xtensa_set_pc,
- xtensa_breakpoint,
- xtensa_breakpoint_len,
+ NULL, /* breakpoint_kind_from_pc */
+ xtensa_sw_breakpoint_from_kind,
NULL,
0,
xtensa_breakpoint_at,
diff --git a/gdb/gdbserver/target.h b/gdb/gdbserver/target.h
index a2842b4..e4c0639 100644
--- a/gdb/gdbserver/target.h
+++ b/gdb/gdbserver/target.h
@@ -441,6 +441,16 @@ struct target_ops
readlink(2). */
ssize_t (*multifs_readlink) (int pid, const char *filename,
char *buf, size_t bufsiz);
+
+ /* Return the breakpoint kind for this target based on PC. The PCPTR is
+ adjusted to the real memory location in case a flag (e.g., the Thumb bit on
+ ARM) was present in the PC. */
+ int (*breakpoint_kind_from_pc) (CORE_ADDR *pcptr);
+
+ /* Return the software breakpoint from KIND. KIND can have target
+ specific meaning like the Z0 kind parameter.
+ SIZE is set to the software breakpoint's length in memory. */
+ const gdb_byte *(*sw_breakpoint_from_kind) (int kind, int *size);
};
extern struct target_ops *the_target;