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/1102
-- gerrit commit f51f07c30bb9df5fa926deb21724784999dcde63 Author: Hsiangkai Wang <[email protected]> Date: Wed Jan 2 12:02:00 2013 +0800 gdb_server: support File-I/O Remote Protocol Extension The File I/O remote protocol extension allows the target to use the host's file system and console I/O to perform various system calls. To use the function, targets need to prepare two callback functions: * get_gdb_finish_info: to get file I/O parameters from target * gdb_fileio_end: pass file I/O response to target As target wants gdb_server to do system call handling, target will be halted and issue event, TARGET_EVENT_GDB_FILEIO, to gdb_server. As gdb_server handles TARGET_EVENT_GDB_FILEIO, it will get information from target through target_get_gdb_fileio_info(). After gdb finishes system call, gdb will pass response of the system call to target through target_gdb_fileio_end() and continue to run(continue or step). To implement the function, I add a new data structure in struct target, called struct gdb_fileio_info, to record file I/O name and parameters. Details refer to GDB manual "File-I/O Remote Protocol Extension" Change-Id: I7f4d45e7c9e967b6d898dc79ba01d86bc46315d3 Signed-off-by: Hsiangkai Wang <[email protected]> diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 299b102..318194a 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -120,6 +120,9 @@ static int gdb_report_data_abort; /* disabled by default */ static int gdb_use_target_description; +/* current processing free-run type, used by file-I/O */ +static char gdb_running_type; + static int gdb_last_signal(struct target *target) { switch (target->debug_reason) { @@ -764,6 +767,95 @@ static void gdb_frontend_halted(struct target *target, struct connection *connec } } +static void gdb_fileio_issue(struct target *target, struct connection *connection) +{ + struct gdb_connection *gdb_connection = connection->priv; + + /* A system call is possible only when GDB is waiting for a response from + * 'C', 'c', 'S' or 's' packets. */ + if (gdb_connection->frontend_state == TARGET_RUNNING) { + if (target_get_gdb_fileio_info(target, target->fileio_info) == ERROR_OK) { + + /* stop forwarding log packets! */ + log_remove_callback(gdb_log_callback, connection); + + char fileio_command[256]; + int command_len; + + if (strcmp(target->fileio_info->identifier, "open") == 0) + sprintf(fileio_command, "F%s,%x/%x,%x,%x", target->fileio_info->identifier, + target->fileio_info->param_1, + target->fileio_info->param_2, + target->fileio_info->param_3, + target->fileio_info->param_4); + else if (strcmp(target->fileio_info->identifier, "close") == 0) + sprintf(fileio_command, "F%s,%x", target->fileio_info->identifier, + target->fileio_info->param_1); + else if (strcmp(target->fileio_info->identifier, "read") == 0) + sprintf(fileio_command, "F%s,%x,%x,%x", target->fileio_info->identifier, + target->fileio_info->param_1, + target->fileio_info->param_2, + target->fileio_info->param_3); + else if (strcmp(target->fileio_info->identifier, "write") == 0) + sprintf(fileio_command, "F%s,%x,%x,%x", target->fileio_info->identifier, + target->fileio_info->param_1, + target->fileio_info->param_2, + target->fileio_info->param_3); + else if (strcmp(target->fileio_info->identifier, "lseek") == 0) + sprintf(fileio_command, "F%s,%x,%x,%x", target->fileio_info->identifier, + target->fileio_info->param_1, + target->fileio_info->param_2, + target->fileio_info->param_3); + else if (strcmp(target->fileio_info->identifier, "rename") == 0) + sprintf(fileio_command, "F%s,%x/%x,%x/%x", target->fileio_info->identifier, + target->fileio_info->param_1, + target->fileio_info->param_2, + target->fileio_info->param_3, + target->fileio_info->param_4); + else if (strcmp(target->fileio_info->identifier, "unlink") == 0) + sprintf(fileio_command, "F%s,%x/%x", target->fileio_info->identifier, + target->fileio_info->param_1, + target->fileio_info->param_2); + else if (strcmp(target->fileio_info->identifier, "stat") == 0) + sprintf(fileio_command, "F%s,%x/%x,%x", target->fileio_info->identifier, + target->fileio_info->param_1, + target->fileio_info->param_2, + target->fileio_info->param_3); + else if (strcmp(target->fileio_info->identifier, "fstat") == 0) + sprintf(fileio_command, "F%s,%x,%x", target->fileio_info->identifier, + target->fileio_info->param_1, + target->fileio_info->param_2); + else if (strcmp(target->fileio_info->identifier, "gettimeofday") == 0) + sprintf(fileio_command, "F%s,%x,%x", target->fileio_info->identifier, + target->fileio_info->param_1, + target->fileio_info->param_2); + else if (strcmp(target->fileio_info->identifier, "isatty") == 0) + sprintf(fileio_command, "F%s,%x", target->fileio_info->identifier, + target->fileio_info->param_1); + else if (strcmp(target->fileio_info->identifier, "system") == 0) + sprintf(fileio_command, "F%s,%x/%x", target->fileio_info->identifier, + target->fileio_info->param_1, + target->fileio_info->param_2); + else if (strcmp(target->fileio_info->identifier, "exit") == 0) + sprintf(fileio_command, "W%02x", target->fileio_info->param_1); + else { + LOG_DEBUG("Unknown syscall: %s", target->fileio_info->identifier); + + /* encounter unknown syscall, continue */ + target_resume(target, 1, 0x0, 0, 0); + return; + } + + command_len = strlen(fileio_command); + + gdb_put_packet(connection, fileio_command, command_len); + gdb_connection->frontend_state = TARGET_HALTED; + rtos_update_threads(target); + } else + gdb_frontend_halted(target, connection); + } +} + static int gdb_target_callback_event_handler(struct target *target, enum target_event event, void *priv) { @@ -783,6 +875,9 @@ static int gdb_target_callback_event_handler(struct target *target, if (retval != ERROR_OK) return retval; break; + case TARGET_EVENT_GDB_FILEIO: + gdb_fileio_issue(target, connection); + break; default: break; } @@ -1417,6 +1512,7 @@ static int gdb_step_continue_packet(struct connection *connection, } else current = 1; + gdb_running_type = packet[0]; if (packet[0] == 'c') { LOG_DEBUG("continue"); /* resume at current address, don't handle breakpoints, not debugging */ @@ -2027,6 +2123,54 @@ static int gdb_detach(struct connection *connection) return gdb_put_packet(connection, "OK", 2); } +/* The format of 'F' response packet is + * Fretcode,errno,Ctrl-C flag;call-specific attachment + */ +static int gdb_fileio_response_packet(struct connection *connection, + char *packet, int packet_size) +{ + struct target *target = get_target_from_connection(connection); + char *separator; + char *parsing_point; + int fileio_retcode = strtoul(packet + 1, &separator, 16); + int fileio_errno = 0; + bool fileio_ctrl_c = false; + int retval; + + LOG_DEBUG("-"); + + if (*separator == ',') { + parsing_point = separator + 1; + fileio_errno = strtoul(parsing_point, &separator, 16); + if (*separator == ',') { + if (*(separator + 1) == 'C') { + /* TODO: process ctrl-c */ + fileio_ctrl_c = true; + } + } + } + + LOG_DEBUG("File-I/O response, retcode: 0x%x, errno: 0x%x, ctrl-c: %s", + fileio_retcode, fileio_errno, fileio_ctrl_c ? "true" : "false"); + + retval = target_gdb_fileio_end(target, fileio_retcode, fileio_errno, fileio_ctrl_c); + if (retval != ERROR_OK) + return ERROR_FAIL; + + /* After File-I/O ends, keep continue or step */ + if (gdb_running_type == 'c') + retval = target_resume(target, 1, 0x0, 0, 0); + else if (gdb_running_type == 's') + retval = target_step(target, 1, 0x0, 0); + else + retval = ERROR_FAIL; + + if (retval != ERROR_OK) + return ERROR_FAIL; + + return ERROR_OK; +} + static void gdb_log_callback(void *priv, const char *file, unsigned line, const char *function, const char *string) { @@ -2253,6 +2397,19 @@ static int gdb_input_inner(struct connection *connection) gdb_write_smp_packet(connection, packet, packet_size); break; + case 'F': + /* File-I/O extension */ + /* After gdb uses host-side syscall to complete target file + * I/O, gdb sends host-side syscall return value to target + * by 'F' packet. + * The format of 'F' response packet is + * Fretcode,errno,Ctrl-C flag;call-specific attachment + */ + gdb_con->frontend_state = TARGET_RUNNING; + log_add_callback(gdb_log_callback, connection); + gdb_fileio_response_packet(connection, packet, packet_size); + break; + default: /* ignore unknown packets */ LOG_DEBUG("ignoring 0x%2.2x packet", packet[0]); diff --git a/src/target/target.c b/src/target/target.c index c781955..a6f0893 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -62,6 +62,10 @@ 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_get_gdb_fileio_info_default(struct target *target, + struct gdb_fileio_info *fileio_info); +static int target_gdb_fileio_end_default(struct target *target, int retcode, + int fileio_errno, bool ctrl_c); 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, @@ -196,6 +200,8 @@ static const Jim_Nvp nvp_target_event[] = { { .value = TARGET_EVENT_GDB_FLASH_ERASE_START, .name = "gdb-flash-erase-start" }, { .value = TARGET_EVENT_GDB_FLASH_ERASE_END , .name = "gdb-flash-erase-end" }, + { .value = TARGET_EVENT_GDB_FILEIO , .name = "gdb-fileio" }, + { .name = NULL, .value = -1 } }; @@ -1080,6 +1086,24 @@ int target_step(struct target *target, return target->type->step(target, current, address, handle_breakpoints); } +int target_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fileio_info) +{ + 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_fileio_info(target, fileio_info); +} + +int target_gdb_fileio_end(struct target *target, int retcode, int fileio_errno, bool ctrl_c) +{ + if (target->state != TARGET_HALTED) { + LOG_WARNING("target %s is not halted", target->cmd_name); + return ERROR_TARGET_NOT_HALTED; + } + return target->type->gdb_fileio_end(target, retcode, fileio_errno, ctrl_c); +} + /** * Reset the @c examined flag for the given target. * Pure paranoia -- targets are zeroed on allocation. @@ -1183,6 +1207,12 @@ static int target_init_one(struct command_context *cmd_ctx, if (target->type->get_gdb_target_description == NULL) target->type->get_gdb_target_description = target_get_gdb_target_description_default; + if (target->type->get_gdb_fileio_info == NULL) + target->type->get_gdb_fileio_info = target_get_gdb_fileio_info_default; + + if (target->type->gdb_fileio_end == NULL) + target->type->gdb_fileio_end = target_gdb_fileio_end_default; + return ERROR_OK; } @@ -1834,6 +1864,18 @@ static int target_get_gdb_target_description_default(struct target *target, char return ERROR_OK; } +static int target_get_gdb_fileio_info_default(struct target *target, struct gdb_fileio_info *fileio_info) +{ + LOG_ERROR("Not implemented: %s", __func__); + return ERROR_FAIL; +} + +static int target_gdb_fileio_end_default(struct target *target, int retcode, int fileio_errno, bool ctrl_c) +{ + LOG_ERROR("Not implemented: %s", __func__); + 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 2e39e4d..2822ef9 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -41,6 +41,7 @@ struct watchpoint; struct mem_param; struct reg_param; struct target_list; +struct gdb_fileio_info; /* * TARGET_UNKNOWN = 0: we don't know anything about the target yet @@ -179,6 +180,9 @@ struct target { * the target attached to the gdb is changing dynamically by changing * gdb_service->target pointer */ struct gdb_service *gdb_service; + + /* file-I/O information for host to do syscall */ + struct gdb_fileio_info *fileio_info; }; struct target_list { @@ -186,6 +190,14 @@ struct target_list { struct target_list *next; }; +struct gdb_fileio_info { + char *identifier; + uint32_t param_1; + uint32_t param_2; + uint32_t param_3; + uint32_t param_4; +}; + /** Returns the instance-specific name of the specified target. */ static inline const char *target_name(struct target *target) { @@ -240,6 +252,8 @@ enum target_event { TARGET_EVENT_GDB_FLASH_ERASE_END, TARGET_EVENT_GDB_FLASH_WRITE_START, TARGET_EVENT_GDB_FLASH_WRITE_END, + + TARGET_EVENT_GDB_FILEIO, }; struct target_event_action { @@ -543,6 +557,22 @@ int target_blank_check_memory(struct target *target, uint32_t address, uint32_t size, uint32_t *blank); int target_wait_state(struct target *target, enum target_state state, int ms); +/** + * Obtain file-I/O information from target for GDB to do syscall. + * + * This routine is a wrapper for target->type->get_gdb_fileio_info. + */ +int target_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fileio_info); + +/** + * Pass GDB file-I/O response to target after finishing host syscall. + * + * This routine is a wrapper for target->type->gdb_fileio_end. + */ +int target_gdb_fileio_end(struct target *target, int retcode, int fileio_errno, bool ctrl_c); + + + /** Return the *name* of this targets current state */ const char *target_state_name(struct target *target); diff --git a/src/target/target_type.h b/src/target/target_type.h index 44521bb..6358bd8 100644 --- a/src/target/target_type.h +++ b/src/target/target_type.h @@ -291,6 +291,15 @@ struct target_type { * circumstances. */ int (*check_reset)(struct target *target); + + /* get GDB file-I/O parameters from target + */ + int (*get_gdb_fileio_info)(struct target *target, struct gdb_fileio_info *fileio_info); + + /* pass GDB file-I/O response to target + */ + int (*gdb_fileio_end)(struct target *target, int retcode, int fileio_errno, bool ctrl_c); + }; #endif /* TARGET_TYPE_H */ -- ------------------------------------------------------------------------------ Master Java SE, Java EE, Eclipse, Spring, Hibernate, JavaScript, jQuery and much more. Keep your Java skills current with LearnJavaNow - 200+ hours of step-by-step video tutorials by Java experts. SALE $49.99 this month only -- learn more at: http://p.sf.net/sfu/learnmore_122612 _______________________________________________ OpenOCD-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/openocd-devel
