diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index 55648bc98d..7f7b6c1482 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,48 @@ +2015-12-07 Yao Qi + + * configure.srv: Append arm.o to srv_tgtobj for + aarch64*-*-linux* target. + * linux-aarch32-low.c (arm_abi_breakpoint): New macro. Moved + from linux-arm-low.c. + (arm_eabi_breakpoint, arm_breakpoint): Likewise. + (arm_breakpoint_len, thumb_breakpoint): Likewise. + (thumb_breakpoint_len, thumb2_breakpoint): Likewise. + (thumb2_breakpoint_len): Likewise. + (arm_is_thumb_mode, arm_breakpoint_at): Likewise. + (arm_breakpoint_kinds): Likewise. + (arm_breakpoint_kind_from_pc): Likewise. + (arm_sw_breakpoint_from_kind): Likewise. + (arm_breakpoint_kind_from_current_state): Likewise. + * linux-aarch32-low.h (arm_breakpoint_kind_from_pc): Declare. + (arm_sw_breakpoint_from_kind): Declare. + (arm_breakpoint_kind_from_current_state): Declare. + (arm_breakpoint_at): Declare. + * linux-aarch64-low.c (aarch64_sw_breakpoint_from_kind): Call + arm_sw_breakpoint_from_kind if process is 32-bit. + (aarch64_breakpoint_kind_from_pc): New function. + (aarch64_breakpoint_kind_from_current_state): New function. + (the_low_target): Initialize fields breakpoint_kind_from_pc + and breakpoint_kind_from_current_state. + * linux-arm-low.c (arm_breakpoint_kinds): Move to + linux-aarch32-low.c. + (arm_abi_breakpoint, arm_eabi_breakpoint): Likewise. + (arm_breakpoint, arm_breakpoint_len): Likewise. + (thumb_breakpoint, thumb_breakpoint_len): Likewise. + (thumb2_breakpoint, thumb2_breakpoint_len): Likewise. + (arm_is_thumb_mode): Likewise. + (arm_breakpoint_at): Likewise. + (arm_breakpoint_kind_from_pc): Likewise. + (arm_sw_breakpoint_from_kind): Likewise. + (arm_breakpoint_kind_from_current_state): Likewise. + + Revert: + 2015-08-04 Yao Qi + + * linux-aarch64-low.c (aarch64_supports_z_point_type): Return + 0 for Z_PACKET_SW_BP if it may be used in multi-arch debugging. + * server.c (extended_protocol): Remove "static". + * server.h (extended_protocol): Declare it. + 2015-12-04 Josh Stone * target.h (struct target_ops) : Rename to ... diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv index e85411097a..6dfd6e06e2 100644 --- a/gdb/gdbserver/configure.srv +++ b/gdb/gdbserver/configure.srv @@ -52,6 +52,7 @@ case "${target}" in srv_regobj="${srv_regobj} arm-with-neon.o" srv_tgtobj="linux-aarch64-low.o aarch64-linux-hw-point.o" srv_tgtobj="$srv_tgtobj linux-aarch32-low.o" + srv_tgtobj="${srv_tgtobj} arm.o" srv_tgtobj="$srv_tgtobj aarch64-linux.o" srv_tgtobj="$srv_tgtobj aarch64-insn.o" srv_tgtobj="${srv_tgtobj} $srv_linux_obj" diff --git a/gdb/gdbserver/linux-aarch32-low.c b/gdb/gdbserver/linux-aarch32-low.c index 221b5b9970..7379350b05 100644 --- a/gdb/gdbserver/linux-aarch32-low.c +++ b/gdb/gdbserver/linux-aarch32-low.c @@ -137,6 +137,165 @@ struct regs_info regs_info_aarch32 = &aarch32_regsets_info }; +/* Correct in either endianness. */ +#define arm_abi_breakpoint 0xef9f0001UL + +/* For new EABI binaries. We recognize it regardless of which ABI + is used for gdbserver, so single threaded debugging should work + OK, but for multi-threaded debugging we only insert the current + ABI's breakpoint instruction. For now at least. */ +#define arm_eabi_breakpoint 0xe7f001f0UL + +#ifndef __ARM_EABI__ +static const unsigned long arm_breakpoint = arm_abi_breakpoint; +#else +static const unsigned long arm_breakpoint = arm_eabi_breakpoint; +#endif + +#define arm_breakpoint_len 4 +static const unsigned short thumb_breakpoint = 0xde01; +#define thumb_breakpoint_len 2 +static const unsigned short thumb2_breakpoint[] = { 0xf7f0, 0xa000 }; +#define thumb2_breakpoint_len 4 + +/* Returns 1 if the current instruction set is thumb, 0 otherwise. */ + +static int +arm_is_thumb_mode (void) +{ + struct regcache *regcache = get_thread_regcache (current_thread, 1); + unsigned long cpsr; + + collect_register_by_name (regcache, "cpsr", &cpsr); + + if (cpsr & 0x20) + return 1; + else + return 0; +} + +/* Returns 1 if there is a software breakpoint at location. */ + +int +arm_breakpoint_at (CORE_ADDR where) +{ + if (arm_is_thumb_mode ()) + { + /* Thumb mode. */ + unsigned short insn; + + (*the_target->read_memory) (where, (unsigned char *) &insn, 2); + if (insn == thumb_breakpoint) + return 1; + + if (insn == thumb2_breakpoint[0]) + { + (*the_target->read_memory) (where + 2, (unsigned char *) &insn, 2); + if (insn == thumb2_breakpoint[1]) + return 1; + } + } + else + { + /* ARM mode. */ + unsigned long insn; + + (*the_target->read_memory) (where, (unsigned char *) &insn, 4); + if (insn == arm_abi_breakpoint) + return 1; + + if (insn == arm_eabi_breakpoint) + return 1; + } + + return 0; +} + +/* Enum describing the different kinds of breakpoints. */ +enum arm_breakpoint_kinds +{ + ARM_BP_KIND_THUMB = 2, + ARM_BP_KIND_THUMB2 = 3, + ARM_BP_KIND_ARM = 4, +}; + +/* Implementation of linux_target_ops method "breakpoint_kind_from_pc". + + Determine the type and size of breakpoint to insert at PCPTR. Uses the + program counter value to determine whether a 16-bit or 32-bit breakpoint + should be used. It returns the breakpoint's kind, and adjusts the program + counter (if necessary) to point to the actual memory location where the + breakpoint should be inserted. */ + +int +arm_breakpoint_kind_from_pc (CORE_ADDR *pcptr) +{ + if (IS_THUMB_ADDR (*pcptr)) + { + gdb_byte buf[2]; + + *pcptr = UNMAKE_THUMB_ADDR (*pcptr); + + /* Check whether we are replacing a thumb2 32-bit instruction. */ + if ((*the_target->read_memory) (*pcptr, buf, 2) == 0) + { + unsigned short inst1 = 0; + + (*the_target->read_memory) (*pcptr, (gdb_byte *) &inst1, 2); + if (thumb_insn_size (inst1) == 4) + return ARM_BP_KIND_THUMB2; + } + return ARM_BP_KIND_THUMB; + } + else + return ARM_BP_KIND_ARM; +} + +/* Implementation of the linux_target_ops method "sw_breakpoint_from_kind". */ + +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. */ + switch (kind) + { + case ARM_BP_KIND_THUMB: + *size = thumb_breakpoint_len; + return (gdb_byte *) &thumb_breakpoint; + case ARM_BP_KIND_THUMB2: + *size = thumb2_breakpoint_len; + return (gdb_byte *) &thumb2_breakpoint; + case ARM_BP_KIND_ARM: + *size = arm_breakpoint_len; + return (const gdb_byte *) &arm_breakpoint; + default: + return NULL; + } + return NULL; +} + +/* Implementation of the linux_target_ops method + "breakpoint_kind_from_current_state". */ + +int +arm_breakpoint_kind_from_current_state (CORE_ADDR *pcptr) +{ + if (arm_is_thumb_mode ()) + { + *pcptr = MAKE_THUMB_ADDR (*pcptr); + return arm_breakpoint_kind_from_pc (pcptr); + } + else + { + return arm_breakpoint_kind_from_pc (pcptr); + } +} + void initialize_low_arch_aarch32 (void) { diff --git a/gdb/gdbserver/linux-aarch32-low.h b/gdb/gdbserver/linux-aarch32-low.h index 6682f0a7f6..0afddc84f3 100644 --- a/gdb/gdbserver/linux-aarch32-low.h +++ b/gdb/gdbserver/linux-aarch32-low.h @@ -23,6 +23,11 @@ void arm_fill_vfpregset_num (struct regcache *regcache, void *buf, int num); void arm_store_vfpregset_num (struct regcache *regcache, const void *buf, int num); +int arm_breakpoint_kind_from_pc (CORE_ADDR *pcptr); +const gdb_byte *arm_sw_breakpoint_from_kind (int kind , int *size); +int arm_breakpoint_kind_from_current_state (CORE_ADDR *pcptr); +int arm_breakpoint_at (CORE_ADDR where); + void initialize_low_arch_aarch32 (void); void init_registers_arm_with_neon (void); diff --git a/gdb/gdbserver/linux-aarch64-low.c b/gdb/gdbserver/linux-aarch64-low.c index 17798ff24a..5fd3f5151c 100644 --- a/gdb/gdbserver/linux-aarch64-low.c +++ b/gdb/gdbserver/linux-aarch64-low.c @@ -260,22 +260,6 @@ aarch64_supports_z_point_type (char z_type) switch (z_type) { case Z_PACKET_SW_BP: - { - if (!extended_protocol && is_64bit_tdesc ()) - { - /* Only enable Z0 packet in non-multi-arch debugging. If - extended protocol is used, don't enable Z0 packet because - GDBserver may attach to 32-bit process. */ - return 1; - } - else - { - /* Disable Z0 packet so that GDBserver doesn't have to handle - different breakpoint instructions (aarch64, arm, thumb etc) - in multi-arch debugging. */ - return 0; - } - } case Z_PACKET_HW_BP: case Z_PACKET_WRITE_WP: case Z_PACKET_READ_WP: @@ -2940,8 +2924,36 @@ aarch64_supports_range_stepping (void) static const gdb_byte * aarch64_sw_breakpoint_from_kind (int kind, int *size) { - *size = aarch64_breakpoint_len; - return aarch64_breakpoint; + if (is_64bit_tdesc ()) + { + *size = aarch64_breakpoint_len; + return aarch64_breakpoint; + } + else + return arm_sw_breakpoint_from_kind (kind, size); +} + +/* Implementation of linux_target_ops method "breakpoint_kind_from_pc". */ + +static int +aarch64_breakpoint_kind_from_pc (CORE_ADDR *pcptr) +{ + if (is_64bit_tdesc ()) + return aarch64_breakpoint_len; + else + return arm_breakpoint_kind_from_pc (pcptr); +} + +/* Implementation of the linux_target_ops method + "breakpoint_kind_from_current_state". */ + +static int +aarch64_breakpoint_kind_from_current_state (CORE_ADDR *pcptr) +{ + if (is_64bit_tdesc ()) + return aarch64_breakpoint_len; + else + return arm_breakpoint_kind_from_current_state (pcptr); } /* Support for hardware single step. */ @@ -2961,7 +2973,7 @@ struct linux_target_ops the_low_target = NULL, /* fetch_register */ aarch64_get_pc, aarch64_set_pc, - NULL, /* breakpoint_kind_from_pc */ + aarch64_breakpoint_kind_from_pc, aarch64_sw_breakpoint_from_kind, NULL, /* breakpoint_reinsert_addr */ 0, /* decr_pc_after_break */ @@ -2985,7 +2997,7 @@ struct linux_target_ops the_low_target = aarch64_emit_ops, aarch64_get_min_fast_tracepoint_insn_len, aarch64_supports_range_stepping, - NULL, /* breakpoint_kind_from_current_state */ + aarch64_breakpoint_kind_from_current_state, aarch64_supports_hardware_single_step, }; diff --git a/gdb/gdbserver/linux-arm-low.c b/gdb/gdbserver/linux-arm-low.c index 7703008808..d4d58a8c98 100644 --- a/gdb/gdbserver/linux-arm-low.c +++ b/gdb/gdbserver/linux-arm-low.c @@ -80,14 +80,6 @@ typedef enum arm_hwbp_access = 3 } arm_hwbp_type; -/* Enum describing the different kinds of breakpoints. */ -enum arm_breakpoint_kinds -{ - ARM_BP_KIND_THUMB = 2, - ARM_BP_KIND_THUMB2 = 3, - ARM_BP_KIND_ARM = 4, -}; - /* Type describing an ARM Hardware Breakpoint Control register value. */ typedef unsigned int arm_hwbp_control_t; @@ -241,80 +233,6 @@ arm_set_pc (struct regcache *regcache, CORE_ADDR pc) supply_register_by_name (regcache, "pc", &newpc); } -/* Correct in either endianness. */ -#define arm_abi_breakpoint 0xef9f0001UL - -/* For new EABI binaries. We recognize it regardless of which ABI - is used for gdbserver, so single threaded debugging should work - OK, but for multi-threaded debugging we only insert the current - ABI's breakpoint instruction. For now at least. */ -#define arm_eabi_breakpoint 0xe7f001f0UL - -#ifndef __ARM_EABI__ -static const unsigned long arm_breakpoint = arm_abi_breakpoint; -#else -static const unsigned long arm_breakpoint = arm_eabi_breakpoint; -#endif - -#define arm_breakpoint_len 4 -static const unsigned short thumb_breakpoint = 0xde01; -#define thumb_breakpoint_len 2 -static const unsigned short thumb2_breakpoint[] = { 0xf7f0, 0xa000 }; -#define thumb2_breakpoint_len 4 - -/* Returns 1 if the current instruction set is thumb, 0 otherwise. */ - -static int -arm_is_thumb_mode (void) -{ - struct regcache *regcache = get_thread_regcache (current_thread, 1); - unsigned long cpsr; - - collect_register_by_name (regcache, "cpsr", &cpsr); - - if (cpsr & 0x20) - return 1; - else - return 0; -} - -/* Returns 1 if there is a software breakpoint at location. */ - -static int -arm_breakpoint_at (CORE_ADDR where) -{ - if (arm_is_thumb_mode ()) - { - /* Thumb mode. */ - unsigned short insn; - - (*the_target->read_memory) (where, (unsigned char *) &insn, 2); - if (insn == thumb_breakpoint) - return 1; - - if (insn == thumb2_breakpoint[0]) - { - (*the_target->read_memory) (where + 2, (unsigned char *) &insn, 2); - if (insn == thumb2_breakpoint[1]) - return 1; - } - } - else - { - /* ARM mode. */ - unsigned long insn; - - (*the_target->read_memory) (where, (unsigned char *) &insn, 4); - if (insn == arm_abi_breakpoint) - return 1; - - if (insn == arm_eabi_breakpoint) - return 1; - } - - return 0; -} - /* Fetch the thread-local storage pointer for libthread_db. */ ps_err_e @@ -943,83 +861,6 @@ arm_regs_info (void) return ®s_info_arm; } -/* Implementation of linux_target_ops method "breakpoint_kind_from_pc". - - Determine the type and size of breakpoint to insert at PCPTR. Uses the - program counter value to determine whether a 16-bit or 32-bit breakpoint - should be used. It returns the breakpoint's kind, and adjusts the program - counter (if necessary) to point to the actual memory location where the - breakpoint should be inserted. */ - -static int -arm_breakpoint_kind_from_pc (CORE_ADDR *pcptr) -{ - if (IS_THUMB_ADDR (*pcptr)) - { - gdb_byte buf[2]; - - *pcptr = UNMAKE_THUMB_ADDR (*pcptr); - - /* Check whether we are replacing a thumb2 32-bit instruction. */ - if ((*the_target->read_memory) (*pcptr, buf, 2) == 0) - { - unsigned short inst1 = 0; - - (*the_target->read_memory) (*pcptr, (gdb_byte *) &inst1, 2); - if (thumb_insn_size (inst1) == 4) - return ARM_BP_KIND_THUMB2; - } - return ARM_BP_KIND_THUMB; - } - else - return ARM_BP_KIND_ARM; -} - -/* Implementation of the 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. */ - switch (kind) - { - case ARM_BP_KIND_THUMB: - *size = thumb_breakpoint_len; - return (gdb_byte *) &thumb_breakpoint; - case ARM_BP_KIND_THUMB2: - *size = thumb2_breakpoint_len; - return (gdb_byte *) &thumb2_breakpoint; - case ARM_BP_KIND_ARM: - *size = arm_breakpoint_len; - return (const gdb_byte *) &arm_breakpoint; - default: - return NULL; - } - return NULL; -} - -/* Implementation of the linux_target_ops method - "breakpoint_kind_from_current_state". */ - -static int -arm_breakpoint_kind_from_current_state (CORE_ADDR *pcptr) -{ - if (arm_is_thumb_mode ()) - { - *pcptr = MAKE_THUMB_ADDR (*pcptr); - return arm_breakpoint_kind_from_pc (pcptr); - } - else - { - return arm_breakpoint_kind_from_pc (pcptr); - } -} - struct linux_target_ops the_low_target = { arm_arch_setup, arm_regs_info, diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c index 6d151ee35d..a09841c6a0 100644 --- a/gdb/gdbserver/server.c +++ b/gdb/gdbserver/server.c @@ -49,7 +49,7 @@ ptid_t general_thread; int server_waiting; -int extended_protocol; +static int extended_protocol; static int response_needed; static int exit_requested; diff --git a/gdb/gdbserver/server.h b/gdb/gdbserver/server.h index dc0361fdcd..18095f23a3 100644 --- a/gdb/gdbserver/server.h +++ b/gdb/gdbserver/server.h @@ -89,7 +89,6 @@ extern int report_vfork_events; extern int report_exec_events; extern int report_thread_events; extern int non_stop; -extern int extended_protocol; /* True if the "swbreak+" feature is active. In that case, GDB wants us to report whether a trap is explained by a software breakpoint