From: <ge...@op...> - 2012-12-27 04:06:39
|
This is an automated email from Gerrit. Hsiangkai Wang (hsi...@gm...) just uploaded a new patch set to Gerrit, which you can find at http://openocd.zylin.com/1093 -- gerrit commit 0237dfee42c9e06e5c0868c4d019e888a8fe7aa1 Author: Hsiangkai Wang <hsi...@gm...> Date: Thu Dec 27 11:49:40 2012 +0800 gdb server: a separate callback function to get *general* registers In gdb remote serial protocol, 'g' and 'G' packets are for reading and writing *general* registers, not *all* registers. There may be exist other groups of registers in target. As gdb stops every time, it will read general registers first. The action will slow down gdb's responsiveness if it uses 'g' packet to read *all* registers, instead of only general registers. So, target needs to provide a separate callback function to only get *general* registers for 'g' and 'G' packets. On the other hand, 'p' and 'P' packets maybe modify any registers in target. So, these two packets still need *all* registers list. To improve gdb responsiveness, target needs to implement new callback function get_gdb_general_reg_list. If target does not implement the function, it will use get_gdb_reg_list to query general register list. Change-Id: Ief4a9ae58f5af87b4fc1b7a977e8e405a14d316f Signed-off-by: Hsiangkai Wang <hsi...@gm...> diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 5885c04..3c125fe 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -1024,7 +1024,7 @@ static int gdb_get_registers_packet(struct connection *connection, if ((target->rtos != NULL) && (ERROR_OK == rtos_get_gdb_reg_list(connection))) return ERROR_OK; - retval = target_get_gdb_reg_list(target, ®_list, ®_list_size); + retval = target_get_gdb_general_reg_list(target, ®_list, ®_list_size); if (retval != ERROR_OK) return gdb_error(connection, retval); @@ -1083,7 +1083,7 @@ static int gdb_set_registers_packet(struct connection *connection, return ERROR_SERVER_REMOTE_CLOSED; } - retval = target_get_gdb_reg_list(target, ®_list, ®_list_size); + retval = target_get_gdb_general_reg_list(target, ®_list, ®_list_size); if (retval != ERROR_OK) return gdb_error(connection, retval); diff --git a/src/target/target.c b/src/target/target.c index 2cda298..d9d4362 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -1051,6 +1051,17 @@ int target_get_gdb_reg_list(struct target *target, { return target->type->get_gdb_reg_list(target, reg_list, reg_list_size); } +int target_get_gdb_general_reg_list(struct target *target, + struct reg **reg_list[], int *reg_list_size) +{ + /* For backward compatible. If no implement of get_gdb_general_reg_list, use + * get_gdb_reg_list to return *all* registers */ + if (target->type->get_gdb_general_reg_list == NULL) + return target->type->get_gdb_reg_list(target, reg_list, reg_list_size); + + return target->type->get_gdb_general_reg_list(target, reg_list, reg_list_size); +} + int target_step(struct target *target, int current, uint32_t address, int handle_breakpoints) { diff --git a/src/target/target.h b/src/target/target.h index ad9b362..c6e6923 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -404,6 +404,14 @@ int target_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size); /** + * Obtain general registers for GDB. + * + * This routine is a wrapper for target->type->get_gdb_general_reg_list. + */ +int target_get_gdb_general_reg_list(struct target *target, + struct reg **reg_list[], int *reg_list_size); + +/** * Step the target. * * This routine is a wrapper for target->type->step. diff --git a/src/target/target_type.h b/src/target/target_type.h index 82fd25c..966c9e1 100644 --- a/src/target/target_type.h +++ b/src/target/target_type.h @@ -104,6 +104,24 @@ struct target_type { */ int (*get_gdb_reg_list)(struct target *target, struct reg **reg_list[], int *reg_list_size); + /** + * Target general register access for GDB. Do @b not call this function + * directly, use target_get_gdb_general_reg_list() instead. + * + * GDB has several groups of registers. In remote serial protocol, 'g' or + * 'G' packets only query @b general registers, not @b all registers. So, + * target needs a separate callback function to get @b general registers + * only. It will improve responsiveness of gdb. + * + * Danger! this function will succeed even if the target is running + * and return a register list with dummy values. + * + * The reason is that GDB connection will fail without a valid register + * list, however it is after GDB is connected that monitor commands can + * be run to properly initialize the target + */ + int (*get_gdb_general_reg_list)(struct target *target, struct reg **reg_list[], int *reg_list_size); + /* target memory access * size: 1 = byte (8bit), 2 = half-word (16bit), 4 = word (32bit) * count: number of items of <size> -- |