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

Reply via email to