2012/12/27 <[email protected]>: > This is an automated email from Gerrit. > > Hsiangkai Wang ([email protected]) just uploaded a new patch set to Gerrit, > which you can find at http://openocd.zylin.com/1094 > > -- gerrit > > commit 3197816865c195806517249bfa320f3709ab4d77 > Author: Hsiangkai Wang <[email protected]> > Date: Thu Dec 27 15:41:32 2012 +0800 > > gdb server: provide an implementation for gdb target description > > If target supports gdb target description, users could use > gdb_target_description [enable|disable] to config the feature. > The default setting is disable. After the feature is enabled, > gdb_server will response qXfer:features:read+ to "qSupported" > packet. Target has the responsibility to provide correct > target description as gdb_server received "qXfer:features:read:" > In order to provide target descriptions, target needs to implement > callback function, get_gdb_target_description. > > The sample code extracted from nds32 implementation is as follow > (nds32 implementation is ongoing) > > int nds32_get_gdb_target_description(struct target *target, char **xml, > char *annex, int32_t offset, uint32_t length) > { > struct nds32 *nds32 = target_to_nds32(target); > struct nds32_cpu_version *cpu_version = &(nds32->cpu_version); > struct nds32_misc_config *misc_config = &(nds32->misc_config); > int retval = ERROR_OK; > int pos = 0; > int size = 0; > char *tdesc; > > if (strcmp(annex, "target.xml") == 0) { > char *fpu_desc = ""; > char *audio_desc = ""; > > if (misc_config->audio_isa) > audio_desc = "<xi:include href=\"nds32-audio.xml\"/>"; > > if (cpu_version->cop_fpu_extension) > fpu_desc = "<xi:include href=\"nds32-fpu.xml\"/>"; > > const char *main_description = "l<?xml version=\"1.0\"?>" \ > "<!DOCTYPE target SYSTEM > \"gdb-target.dtd\">" \ > > "<target><architecture>nds32</architecture>" \ > "<xi:include > href=\"nds32-core.xml\"/>" \ > "<xi:include > href=\"nds32-system.xml\"/>" \ > "%s" \ > "%s" \ > "</target>"; > nds32_xml_printf(&retval, xml, &pos, &size, main_description, > audio_desc, fpu_desc); > > return retval; > } else if (strcmp(annex, "nds32-core.xml") == 0) { > tdesc = nds32_tdesc[NDS32_CORE_TDESC]; > if (tdesc == NULL) > return ERROR_FAIL; > } else if (strcmp(annex, "nds32-system.xml") == 0) { > tdesc = nds32_tdesc[NDS32_SYSTEM_TDESC]; > if (tdesc == NULL) > return ERROR_FAIL; > } else if (strcmp(annex, "nds32-audio.xml") == 0) { > tdesc = nds32_tdesc[NDS32_AUDIO_TDESC]; > if (tdesc == NULL) > return ERROR_FAIL; > } else if (strcmp(annex, "nds32-fpu.xml") == 0) { > tdesc = nds32_tdesc[NDS32_FPU_TDESC]; > if (tdesc == NULL) > return ERROR_FAIL; > } else { > return ERROR_FAIL; > } > > char transfer_type; > uint32_t tdesc_length = strlen(tdesc); > > if (length < (tdesc_length - offset)) > transfer_type = 'm'; > else > transfer_type = 'l'; > > *xml = malloc(length+2); > (*xml)[0] = transfer_type; > if (transfer_type == 'm') > { > strncpy((*xml) + 1, tdesc + offset, length); > (*xml)[1 + length] = '\0'; > } > else > { > strncpy((*xml) + 1, tdesc + offset, tdesc_length - offset); > (*xml)[1 + (tdesc_length - offset)] = '\0'; > } > > return ERROR_OK; > } > > Change-Id: I07b9907b1e773209c0efb15e79249d0fe855643b > Signed-off-by: Hsiangkai Wang <[email protected]> > > diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c > index 3c125fe..299b102 100644 > --- a/src/server/gdb_server.c > +++ b/src/server/gdb_server.c > @@ -115,6 +115,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) { > @@ -1815,9 +1820,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); > @@ -1833,8 +1839,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; > @@ -1849,24 +1853,25 @@ 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. > + * > + * example of xml (as annex == "target.xml"): > + * > + * "l<?xml version=\"1.0\"?>" \ > + * "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">" \ > + * "<target><architecture>arm</architecture>" \ > + * "</target> > + */ > + retval = target_get_gdb_target_description(target, &xml, > annex, offset, length); > if (retval != ERROR_OK) { > gdb_error(connection, retval); > return retval; > } > > gdb_put_packet(connection, xml, strlen(xml)); > - > free(xml); > return ERROR_OK; > } else if (strncmp(packet, "QStartNoAckMode", 15) == 0) { > @@ -2443,6 +2448,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", > @@ -2495,6 +2509,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/target.c b/src/target/target.c > index d9d4362..c781955 100644 > --- a/src/target/target.c > +++ b/src/target/target.c > @@ -60,6 +60,8 @@ static int target_read_buffer_default(struct target > *target, uint32_t address, > uint32_t size, uint8_t *buffer); > static int target_write_buffer_default(struct target *target, uint32_t > address, > uint32_t size, const uint8_t *buffer); > +static int target_get_gdb_target_description_default(struct target *target, > char **xml, > + char *annex, int32_t offset, uint32_t length); > static int target_array2mem(Jim_Interp *interp, struct target *target, > int argc, Jim_Obj * const *argv); > static int target_mem2array(Jim_Interp *interp, struct target *target, > @@ -1062,6 +1064,16 @@ int target_get_gdb_general_reg_list(struct target > *target, > return target->type->get_gdb_general_reg_list(target, reg_list, > reg_list_size); > } > > +int target_get_gdb_target_description(struct target *target, > + char **xml, char *annex, int32_t offset, uint32_t length) > +{ > + if (target->state != TARGET_HALTED) { > + LOG_WARNING("target %s is not halted", target->cmd_name); > + return ERROR_TARGET_NOT_HALTED; > + } > + return target->type->get_gdb_target_description(target, xml, annex, > offset, length); > +} > + > int target_step(struct target *target, > int current, uint32_t address, int handle_breakpoints) > { > @@ -1168,6 +1180,9 @@ static int target_init_one(struct command_context > *cmd_ctx, > if (target->type->write_buffer == NULL) > target->type->write_buffer = target_write_buffer_default; > > + if (target->type->get_gdb_target_description == NULL) > + target->type->get_gdb_target_description = > target_get_gdb_target_description_default; > + > return ERROR_OK; > } > > @@ -1798,6 +1813,27 @@ static int target_write_buffer_default(struct target > *target, uint32_t address, > return retval; > } > > +static int target_get_gdb_target_description_default(struct target *target, > char **xml, > + char *annex, int32_t offset, uint32_t length) > +{ > + if (strcmp(annex, "target.xml") != 0) > + return ERROR_FAIL; > + > + const char *default_description = "l<?xml version=\"1.0\"?>" \ > + "<!DOCTYPE target SYSTEM > \"gdb-target.dtd\">" \ > + > "<target><architecture>arm</architecture>" \ > + "</target>"; > + const int description_length = strlen(default_description); > + > + *xml = realloc(*xml, description_length + 1); > + if (*xml == NULL) > + return ERROR_FAIL; > + > + strcpy(*xml, default_description); > + > + return ERROR_OK; > +} > + > /* Single aligned words are guaranteed to use 16 or 32 bit access > * mode respectively, otherwise data is handled as quickly as > * possible > diff --git a/src/target/target.h b/src/target/target.h > index c6e6923..2e39e4d 100644 > --- a/src/target/target.h > +++ b/src/target/target.h > @@ -412,6 +412,14 @@ int target_get_gdb_general_reg_list(struct target > *target, > struct reg **reg_list[], int *reg_list_size); > > /** > + * Obtain target description for GDB. > + * > + * This routine is a wrapper for target->type->get_gdb_target_description. > + */ > +int target_get_gdb_target_description(struct target *target, > + char **xml, char *annex, int32_t offset, uint32_t length); > + > +/** > * 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 966c9e1..44521bb 100644 > --- a/src/target/target_type.h > +++ b/src/target/target_type.h > @@ -122,6 +122,12 @@ struct target_type { > */ > int (*get_gdb_general_reg_list)(struct target *target, struct reg > **reg_list[], int *reg_list_size); > > + /** > + * Get target description for GDB. Do @b not call this function > + * directly, use target_get_gdb_target_description() instead. > + */ > + int (*get_gdb_target_description)(struct target *target, char **xml, > char *annex, int32_t offset, uint32_t length); > + > /* target memory access > * size: 1 = byte (8bit), 2 = half-word (16bit), 4 = word (32bit) > * count: number of items of <size> > > -- > > ------------------------------------------------------------------------------ > Master Visual Studio, SharePoint, SQL, ASP.NET, C# 2012, HTML5, CSS, > MVC, Windows 8 Apps, JavaScript and much more. Keep your skills current > with LearnDevNow - 3,200 step-by-step video tutorials by Microsoft > MVPs and experts. ON SALE this month only -- learn more at: > http://p.sf.net/sfu/learnmore_122712 > _______________________________________________ > OpenOCD-devel mailing list > [email protected] > https://lists.sourceforge.net/lists/listinfo/openocd-devel
Hi, I just pushed something similar some days ago: http://openocd.zylin.com/#/c/1051/ In case you want to take a look. Franck. ------------------------------------------------------------------------------ Master Visual Studio, SharePoint, SQL, ASP.NET, C# 2012, HTML5, CSS, MVC, Windows 8 Apps, JavaScript and much more. Keep your skills current with LearnDevNow - 3,200 step-by-step video tutorials by Microsoft MVPs and experts. ON SALE this month only -- learn more at: http://p.sf.net/sfu/learnmore_122712 _______________________________________________ OpenOCD-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/openocd-devel
