This is an automated email from Gerrit. Hsiangkai Wang (hsiang...@gmail.com) just uploaded a new patch set to Gerrit, which you can find at http://openocd.zylin.com/1381
-- gerrit commit 16464448b926d2b1d2019ba68086ec7a60a4cc0b Author: Hsiangkai Wang <hsiang...@gmail.com> Date: Sun May 5 15:09:02 2013 +0800 gdb_server: support gdb target description * Add a parameter in .get_gdb_reg_list() to return different register lists as generating different register groups in target description. * Modify STRUCT REG to let gdb generate target description according to register information. The modified structure of register is struct reg { const char *name; uint32_t number; /* for regnum="num" */ struct reg_feature *feature; /* for register group feature name */ bool caller_save; /* for save-restore="yes|no" */ void *value; bool dirty; bool valid; uint32_t size; struct reg_data_type *reg_data_type; /* for type="type" */ enum reg_group group; /* for group="general|float|vector" */ void *arch_info; const struct reg_arch_type *type; }; Change-Id: I6b24efa0eb65abd2838f4ac0ae36a4d9e80466d5 Signed-off-by: Hsiangkai Wang <hsiang...@gmail.com> diff --git a/src/rtos/linux.c b/src/rtos/linux.c index 23b1a9e..c7eee70 100644 --- a/src/rtos/linux.c +++ b/src/rtos/linux.c @@ -226,7 +226,8 @@ static int linux_os_thread_reg_list(struct rtos *rtos, /*LOG_INFO("thread %lx current on core %x",thread_id, * target->coreid);*/ retval = - target_get_gdb_reg_list(target, ®_list, ®_list_size); + target_get_gdb_reg_list(target, ®_list, ®_list_size, + REG_CLASS_GENERAL); if (retval != ERROR_OK) return retval; @@ -498,7 +499,7 @@ int get_current(struct target *target, int create) int retval; if (target_get_gdb_reg_list(head->target, ®_list, - ®_list_size) != ERROR_OK) { + ®_list_size, REG_CLASS_GENERAL) != ERROR_OK) { free(buffer); return ERROR_TARGET_FAILURE; } diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index cd72658..0d31f86 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -114,6 +114,11 @@ static int gdb_flash_program = 1; */ static int gdb_report_data_abort; +/* set if we are sending target descriptions to gdb + * via qXfer:features:read packet */ +/* disabled by default */ +static int gdb_use_target_description; + static int gdb_last_signal(struct target *target) { switch (target->debug_reason) { @@ -968,7 +973,8 @@ 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_reg_list(target, ®_list, ®_list_size, + REG_CLASS_GENERAL); if (retval != ERROR_OK) return gdb_error(connection, retval); @@ -1027,7 +1033,8 @@ 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_reg_list(target, ®_list, ®_list_size, + REG_CLASS_GENERAL); if (retval != ERROR_OK) return gdb_error(connection, retval); @@ -1072,7 +1079,8 @@ static int gdb_get_register_packet(struct connection *connection, LOG_DEBUG("-"); #endif - retval = target_get_gdb_reg_list(target, ®_list, ®_list_size); + retval = target_get_gdb_reg_list(target, ®_list, ®_list_size, + REG_CLASS_ALL); if (retval != ERROR_OK) return gdb_error(connection, retval); @@ -1109,7 +1117,8 @@ static int gdb_set_register_packet(struct connection *connection, LOG_DEBUG("-"); - retval = target_get_gdb_reg_list(target, ®_list, ®_list_size); + retval = target_get_gdb_reg_list(target, ®_list, ®_list_size, + REG_CLASS_ALL); if (retval != ERROR_OK) return gdb_error(connection, retval); @@ -1670,6 +1679,276 @@ static int gdb_memory_map(struct connection *connection, return ERROR_OK; } +static const char *gdb_get_reg_type_name(enum reg_type type) +{ + switch (type) { + case REG_TYPE_INT8: + return "int8"; + case REG_TYPE_INT16: + return "int16"; + case REG_TYPE_INT32: + return "int32"; + case REG_TYPE_INT64: + return "int64"; + case REG_TYPE_INT128: + return "int128"; + case REG_TYPE_UINT8: + return "uin8"; + case REG_TYPE_UINT16: + return "uint16"; + case REG_TYPE_UINT32: + return "uint32"; + case REG_TYPE_UINT64: + return "uint64"; + case REG_TYPE_UINT128: + return "uint128"; + case REG_TYPE_CODE_PTR: + return "code_ptr"; + case REG_TYPE_DATA_PTR: + return "data_ptr"; + case REG_TYPE_IEEE_SINGLE: + return "ieee_single"; + case REG_TYPE_IEEE_DOUBLE: + return "ieee_double"; + case REG_TYPE_ARCH_DEFINED: + return "int"; /* return arbitrary string to avoid compile warning. */ + } + + return "int"; /* "int" as default value */ +} + +static const char *gdb_get_reg_group_name(enum reg_group group) +{ + switch (group) { + case REG_GROUP_GENERAL: + return "general"; + case REG_GROUP_FLOAT: + return "float"; + case REG_GROUP_VECTOR: + return "vector"; + } + + return NULL; +} + +static int gdb_generate_reg_type_description(struct target *target, + char **tdesc, int *pos, int *size, struct reg_data_type *type) +{ + int retval = ERROR_OK; + + if (type->type_class == REG_TYPE_CLASS_VECTOR) { + /* <vector id="id" type="type" count="count"/> */ + xml_printf(&retval, tdesc, pos, size, + "<vector id=\"%s\" type=\"%s\" count=\"%d\"/>\n", + type->id, type->reg_type_vector->type->id, + type->reg_type_vector->count); + + } else if (type->type_class == REG_TYPE_CLASS_UNION) { + /* <union id="id"> + * <field name="name" type="type"/> ... + * </union> */ + xml_printf(&retval, tdesc, pos, size, + "<union id=\"%s\">\n", + type->id); + + struct reg_data_type_union_field *field; + field = type->reg_type_union->fields; + while (field != NULL) { + xml_printf(&retval, tdesc, pos, size, + "<field name=\"%s\" type=\"%s\"/>\n", + field->name, field->type->id); + + field = field->next; + } + + xml_printf(&retval, tdesc, pos, size, + "</union>\n"); + + } else if (type->type_class == REG_TYPE_CLASS_STRUCT) { + struct reg_data_type_struct_field *field; + field = type->reg_type_struct->fields; + + if (field->use_bitfields) { + /* <struct id="id" size="size"> + * <field name="name" start="start" end="end"/> ... + * </struct> */ + xml_printf(&retval, tdesc, pos, size, + "<struct id=\"%s\" size=\"%d\">\n", + type->id, type->reg_type_struct->size); + while (field != NULL) { + xml_printf(&retval, tdesc, pos, size, + "<field name=\"%s\" start=\"%d\" end=\"%d\"/>\n", + field->name, field->bitfield->start, + field->bitfield->end); + + field = field->next; + } + } else { + /* <struct id="id"> + * <field name="name" type="type"/> ... + * </struct> */ + xml_printf(&retval, tdesc, pos, size, + "<struct id=\"%s\">\n", + type->id); + while (field != NULL) { + xml_printf(&retval, tdesc, pos, size, + "<field name=\"%s\" type=\"%s\"/>\n", + field->name, field->type->id); + + field = field->next; + } + } + + xml_printf(&retval, tdesc, pos, size, + "</struct>\n"); + + } else if (type->type_class == REG_TYPE_CLASS_FLAGS) { + /* <flags id="id" size="size"> + * <field name="name" start="start" end="end"/> ... + * </flags> */ + xml_printf(&retval, tdesc, pos, size, + "<flags id=\"%s\" size=\"%d\">\n", + type->id, type->reg_type_flags->size); + + struct reg_data_type_flags_field *field; + field = type->reg_type_flags->fields; + while (field != NULL) { + xml_printf(&retval, tdesc, pos, size, + "<field name=\"%s\" start=\"%d\" end=\"%d\"/>\n", + field->name, field->bitfield->start, field->bitfield->end); + + field = field->next; + } + + xml_printf(&retval, tdesc, pos, size, + "</flags>\n"); + + } + + return ERROR_OK; +} + +static int gdb_generate_target_description(struct target *target, char **tdesc) +{ + int retval = ERROR_OK; + enum target_register_class reg_class; + struct reg **reg_list; + int reg_list_size; + int pos = 0; + int size = 0; + + xml_printf(&retval, tdesc, &pos, &size, + "<?xml version=\"1.0\"?>\n" + "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">\n" + "<target version=\"1.0\">\n"); + + for (reg_class = REG_CLASS_GENERAL; reg_class != REG_CLASS_END; reg_class++) { + retval = target_get_gdb_reg_list(target, ®_list, ®_list_size, + reg_class); + + if (retval != ERROR_OK) { + LOG_ERROR("get register list %d failed", reg_class); + continue; + } + + if (reg_list_size <= 0) + continue; + + /* generate target description according to register list */ + xml_printf(&retval, tdesc, &pos, &size, + "<feature name=\"%s\">\n", + reg_list[0]->feature->name); + + int i; + for (i = 0; i < reg_list_size ;i++) { + + const char *type_str; + if (reg_list[i]->reg_data_type->type == REG_TYPE_ARCH_DEFINED) { + /* generate <type... first, if there are architecture-defined types. */ + gdb_generate_reg_type_description(target, tdesc, &pos, &size, + reg_list[i]->reg_data_type); + + type_str = reg_list[i]->reg_data_type->id; + } else { + /* predefined type */ + type_str = gdb_get_reg_type_name( + reg_list[i]->reg_data_type->type); + } + + xml_printf(&retval, tdesc, &pos, &size, + "<reg name=\"%s\"", reg_list[i]->name); + xml_printf(&retval, tdesc, &pos, &size, + " bitsize=\"%d\"", reg_list[i]->size); + xml_printf(&retval, tdesc, &pos, &size, + " regnum=\"%d\"", reg_list[i]->number); + if (reg_list[i]->caller_save) + xml_printf(&retval, tdesc, &pos, &size, + " save-restore=\"yes\""); + else + xml_printf(&retval, tdesc, &pos, &size, + " save-restore=\"no\""); + + xml_printf(&retval, tdesc, &pos, &size, + " type=\"%s\"", type_str); + + const char *group_str; + group_str = gdb_get_reg_group_name(reg_list[i]->group); + if (group_str != NULL) + xml_printf(&retval, tdesc, &pos, &size, + " group=\"%s\"", group_str); + + xml_printf(&retval, tdesc, &pos, &size, + "/>"); + } + + xml_printf(&retval, tdesc, &pos, &size, + "</feature>"); + + free(reg_list); + } + + xml_printf(&retval, tdesc, &pos, &size, + "</target>\n"); + + return ERROR_OK; +} + +static int gdb_get_target_description_chunk(struct target *target, char **chunk, + int32_t offset, uint32_t length) +{ + static char *tdesc = NULL; + static uint32_t tdesc_length = 0; + + if (tdesc == NULL) { + gdb_generate_target_description(target, &tdesc); + tdesc_length = strlen(tdesc); + } + + char transfer_type; + + if (length < (tdesc_length - offset)) + transfer_type = 'm'; + else + transfer_type = 'l'; + + *chunk = malloc(length + 2); + (*chunk)[0] = transfer_type; + if (transfer_type == 'm') { + strncpy((*chunk) + 1, tdesc + offset, length); + (*chunk)[1 + length] = '\0'; + } else { + strncpy((*chunk) + 1, tdesc + offset, tdesc_length - offset); + (*chunk)[1 + (tdesc_length - offset)] = '\0'; + + /* After gdb-server sends out last chunk, invalidate tdesc. */ + free(tdesc); + tdesc = NULL; + tdesc_length = 0; + } + + return ERROR_OK; +} + static int gdb_query_packet(struct connection *connection, char *packet, int packet_size) { @@ -1744,9 +2023,10 @@ static int gdb_query_packet(struct connection *connection, &buffer, &pos, &size, - "PacketSize=%x;qXfer:memory-map:read%c;qXfer:features:read-;QStartNoAckMode+", + "PacketSize=%x;qXfer:memory-map:read%c;qXfer:features:read%c;QStartNoAckMode+", (GDB_BUFFER_SIZE - 1), - ((gdb_use_memory_map == 1) && (flash_get_bank_count() > 0)) ? '+' : '-'); + ((gdb_use_memory_map == 1) && (flash_get_bank_count() > 0)) ? '+' : '-', + (gdb_use_target_description == 1) ? '+' : '-'); if (retval != ERROR_OK) { gdb_send_error(connection, 01); @@ -1762,8 +2042,6 @@ static int gdb_query_packet(struct connection *connection, return gdb_memory_map(connection, packet, packet_size); else if (strncmp(packet, "qXfer:features:read:", 20) == 0) { char *xml = NULL; - int size = 0; - int pos = 0; int retval = ERROR_OK; int offset; @@ -1778,17 +2056,12 @@ static int gdb_query_packet(struct connection *connection, return ERROR_OK; } - if (strcmp(annex, "target.xml") != 0) { - gdb_send_error(connection, 01); - return ERROR_OK; - } - - xml_printf(&retval, - &xml, - &pos, - &size, \ - "l < target version=\"1.0\">\n < architecture > arm</architecture>\n</target>\n"); - + /* Target should prepare correct target description for annex. + * The first character of returned xml is 'm' or 'l'. 'm' for + * there are *more* chunks to transfer. 'l' for it is the *last* + * chunk of target description. + */ + retval = gdb_get_target_description_chunk(target, &xml, offset, length); if (retval != ERROR_OK) { gdb_error(connection, retval); return retval; @@ -2372,6 +2645,15 @@ COMMAND_HANDLER(handle_gdb_breakpoint_override_command) return ERROR_OK; } +COMMAND_HANDLER(handle_gdb_target_description_command) +{ + if (CMD_ARGC != 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + COMMAND_PARSE_ENABLE(CMD_ARGV[0], gdb_use_target_description); + return ERROR_OK; +} + static const struct command_registration gdb_command_handlers[] = { { .name = "gdb_sync", @@ -2424,6 +2706,13 @@ static const struct command_registration gdb_command_handlers[] = { "to be used by gdb 'break' commands.", .usage = "('hard'|'soft'|'disable')" }, + { + .name = "gdb_target_description", + .handler = handle_gdb_target_description_command, + .mode = COMMAND_CONFIG, + .help = "enable or disable target description", + .usage = "('enable'|'disable')" + }, COMMAND_REGISTRATION_DONE }; diff --git a/src/target/arm.h b/src/target/arm.h index e476404..df276d9 100644 --- a/src/target/arm.h +++ b/src/target/arm.h @@ -211,7 +211,8 @@ extern const struct command_registration arm_command_handlers[]; int arm_arch_state(struct target *target); int arm_get_gdb_reg_list(struct target *target, - struct reg **reg_list[], int *reg_list_size); + struct reg **reg_list[], int *reg_list_size, + enum target_register_class reg_class); int arm_init_arch_info(struct target *target, struct arm *arm); diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c index b04404b..76e4c2e 100644 --- a/src/target/armv4_5.c +++ b/src/target/armv4_5.c @@ -1047,7 +1047,8 @@ const struct command_registration arm_command_handlers[] = { }; int arm_get_gdb_reg_list(struct target *target, - struct reg **reg_list[], int *reg_list_size) + struct reg **reg_list[], int *reg_list_size, + enum target_register_class reg_class) { struct arm *arm = target_to_arm(target); int i; diff --git a/src/target/armv7m.c b/src/target/armv7m.c index a3c81dc..8a3ce14 100644 --- a/src/target/armv7m.c +++ b/src/target/armv7m.c @@ -259,7 +259,7 @@ static int armv7m_write_core_reg(struct target *target, struct reg *r, * hardware, so this also fakes a set of long-obsolete FPA registers that * are not used in EABI based software stacks. */ -int armv7m_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size) +int armv7m_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size, enum target_register_class reg_class) { struct armv7m_common *armv7m = target_to_armv7m(target); int i; diff --git a/src/target/armv7m.h b/src/target/armv7m.h index c785d30..4d3faf5 100644 --- a/src/target/armv7m.h +++ b/src/target/armv7m.h @@ -195,7 +195,8 @@ int armv7m_mode_to_number(enum armv7m_mode mode); int armv7m_arch_state(struct target *target); int armv7m_get_gdb_reg_list(struct target *target, - struct reg **reg_list[], int *reg_list_size); + struct reg **reg_list[], int *reg_list_size, + enum target_register_class reg_class); int armv7m_init_arch_info(struct target *target, struct armv7m_common *armv7m); diff --git a/src/target/avr32_ap7k.c b/src/target/avr32_ap7k.c index 749bf30..3c3a6bd 100644 --- a/src/target/avr32_ap7k.c +++ b/src/target/avr32_ap7k.c @@ -576,7 +576,7 @@ int avr32_ap7k_arch_state(struct target *target) return ERROR_OK; } -int avr32_ap7k_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size) +int avr32_ap7k_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size, enum target_register_class reg_class) { #if 0 /* get pointers to arch-specific information */ diff --git a/src/target/dsp563xx.c b/src/target/dsp563xx.c index b9c8b4d..cc02c56 100644 --- a/src/target/dsp563xx.c +++ b/src/target/dsp563xx.c @@ -323,7 +323,8 @@ uint8_t gdb_reg_list_idx[] = { static int dsp563xx_get_gdb_reg_list(struct target *target, struct reg **reg_list[], - int *reg_list_size) + int *reg_list_size, + enum target_register_class reg_class) { int i; struct dsp563xx_common *dsp563xx = target_to_dsp563xx(target); diff --git a/src/target/mips32.c b/src/target/mips32.c index 55c197b..023ddc1 100644 --- a/src/target/mips32.c +++ b/src/target/mips32.c @@ -173,7 +173,7 @@ static int mips32_write_core_reg(struct target *target, int num) return ERROR_OK; } -int mips32_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size) +int mips32_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size, enum target_register_class reg_class) { /* get pointers to arch-specific information */ struct mips32_common *mips32 = target_to_mips32(target); diff --git a/src/target/mips32.h b/src/target/mips32.h index 0bdfc59..414ac47 100644 --- a/src/target/mips32.h +++ b/src/target/mips32.h @@ -241,7 +241,8 @@ int mips32_examine(struct target *target); int mips32_register_commands(struct command_context *cmd_ctx); int mips32_get_gdb_reg_list(struct target *target, - struct reg **reg_list[], int *reg_list_size); + struct reg **reg_list[], int *reg_list_size, + enum target_register_class reg_class); int mips32_checksum_memory(struct target *target, uint32_t address, uint32_t count, uint32_t *checksum); int mips32_blank_check_memory(struct target *target, diff --git a/src/target/register.h b/src/target/register.h index cf08e4a..0ec8ed1 100644 --- a/src/target/register.h +++ b/src/target/register.h @@ -26,12 +26,110 @@ struct target; +enum reg_type { + REG_TYPE_INT8, + REG_TYPE_INT16, + REG_TYPE_INT32, + REG_TYPE_INT64, + REG_TYPE_INT128, + REG_TYPE_UINT8, + REG_TYPE_UINT16, + REG_TYPE_UINT32, + REG_TYPE_UINT64, + REG_TYPE_UINT128, + REG_TYPE_CODE_PTR, + REG_TYPE_DATA_PTR, + REG_TYPE_IEEE_SINGLE, + REG_TYPE_IEEE_DOUBLE, + REG_TYPE_ARCH_DEFINED, +}; + +enum reg_group { + REG_GROUP_GENERAL, + REG_GROUP_FLOAT, + REG_GROUP_VECTOR, +}; + +struct reg_feature { + const char *name; +}; + +struct reg_data_type_vector { + struct reg_data_type *type; + uint32_t count; +}; + +struct reg_data_type_union_field { + const char *name; + struct reg_data_type *type; + struct reg_data_type_union_field *next; +}; + +struct reg_data_type_union { + struct reg_data_type_union_field *fields; +}; + +struct reg_data_type_bitfield { + uint32_t start; + uint32_t end; +}; + +struct reg_data_type_struct_field { + const char *name; + bool use_bitfields; + union { + struct reg_data_type_bitfield *bitfield; + struct reg_data_type *type; + }; + struct reg_data_type_struct_field *next; +}; + +struct reg_data_type_struct { + uint32_t size; + struct reg_data_type_struct_field *fields; +}; + +struct reg_data_type_flags_field { + const char *name; + struct reg_data_type_bitfield *bitfield; + struct reg_data_type_flags_field *next; +}; + +struct reg_data_type_flags { + uint32_t size; + struct reg_data_type_flags_field *fields; +}; + +enum reg_data_type_class { + REG_TYPE_CLASS_VECTOR, + REG_TYPE_CLASS_UNION, + REG_TYPE_CLASS_STRUCT, + REG_TYPE_CLASS_FLAGS, +}; + +struct reg_data_type { + enum reg_type type; + const char *id; + enum reg_data_type_class type_class; + union { + struct reg_data_type_vector *reg_type_vector; + struct reg_data_type_union *reg_type_union; + struct reg_data_type_struct *reg_type_struct; + struct reg_data_type_flags *reg_type_flags; + }; +}; + struct reg { const char *name; + uint32_t number; + struct reg_feature *feature; + bool caller_save; void *value; bool dirty; bool valid; uint32_t size; + struct reg_data_type *reg_data_type; + enum reg_group group; void *arch_info; const struct reg_arch_type *type; }; diff --git a/src/target/target.c b/src/target/target.c index ed1a2cc..3d9bda1 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -1028,9 +1028,10 @@ int target_remove_watchpoint(struct target *target, } int target_get_gdb_reg_list(struct target *target, - struct reg **reg_list[], int *reg_list_size) + struct reg **reg_list[], int *reg_list_size, + enum target_register_class reg_class) { - return target->type->get_gdb_reg_list(target, reg_list, reg_list_size); + return target->type->get_gdb_reg_list(target, reg_list, reg_list_size, reg_class); } 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 e6b931d..49770c3 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -114,6 +114,21 @@ struct backoff_timer { int count; }; +/* split target registers into multiple class */ +enum target_register_class { + REG_CLASS_ALL, + REG_CLASS_GENERAL, + REG_CLASS_CORE, + REG_CLASS_FPU, + REG_CLASS_ARCH_EXTENSION_1, + REG_CLASS_ARCH_EXTENSION_2, + REG_CLASS_ARCH_EXTENSION_3, + REG_CLASS_ARCH_EXTENSION_4, + REG_CLASS_ARCH_EXTENSION_5, + REG_CLASS_ARCH_EXTENSION_6, + REG_CLASS_END, +}; + /* target_type.h contains the full definition of struct target_type */ struct target { struct target_type *type; /* target type definition (name, access functions) */ @@ -399,7 +414,8 @@ int target_remove_watchpoint(struct target *target, * This routine is a wrapper for target->type->get_gdb_reg_list. */ int target_get_gdb_reg_list(struct target *target, - struct reg **reg_list[], int *reg_list_size); + struct reg **reg_list[], int *reg_list_size, + enum target_register_class reg_class); /** * Step the target. diff --git a/src/target/target_type.h b/src/target/target_type.h index 5b72d84..9b5cdbb 100644 --- a/src/target/target_type.h +++ b/src/target/target_type.h @@ -101,7 +101,8 @@ struct target_type { * list, however it is after GDB is connected that monitor commands can * be run to properly initialize the target */ - int (*get_gdb_reg_list)(struct target *target, struct reg **reg_list[], int *reg_list_size); + int (*get_gdb_reg_list)(struct target *target, struct reg **reg_list[], + int *reg_list_size, enum target_register_class reg_class); /* target memory access * size: 1 = byte (8bit), 2 = half-word (16bit), 4 = word (32bit) -- ------------------------------------------------------------------------------ Learn Graph Databases - Download FREE O'Reilly Book "Graph Databases" is the definitive new guide to graph databases and their applications. This 200-page book is written by three acclaimed leaders in the field. The early access version is available now. Download your free book today! http://p.sf.net/sfu/neotech_d2d_may _______________________________________________ OpenOCD-devel mailing list OpenOCD-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/openocd-devel