- added patch to Improving progress/error output for telnet & GDB monitor
authormifi <mifi@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Wed, 13 Feb 2008 19:02:17 +0000 (19:02 +0000)
committermifi <mifi@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Wed, 13 Feb 2008 19:02:17 +0000 (19:02 +0000)
(thanks to Ã˜yvind for the patch)

git-svn-id: svn://svn.berlios.de/openocd/trunk@293 b42882b7-edfa-0310-969c-e2dbd0fdcd60

src/helper/command.c
src/helper/log.c
src/helper/log.h
src/server/gdb_server.c
src/server/telnet_server.c

index afd866729f19d60f96815ec0e0cd04b9d47f03bc..9f756d412a102afea06307ec3101b392dcf1bba1 100644 (file)
@@ -268,7 +268,7 @@ void command_print(command_context_t *context, char *format, ...)
        /* process format string */
        /* TODO: possible bug. va_list is undefined after the first call to vsnprintf */
        while (!buffer || (n = vsnprintf(buffer, size, format, ap)) >= size)
-       {
+               {
                /* increase buffer until it fits the whole string */
                if (!(p = realloc(buffer, size += 4096)))
                {
@@ -359,7 +359,7 @@ int find_and_run_command(command_context_t *context, command_t *commands, char *
        return ERROR_OK;
 }
 
-int command_run_line(command_context_t *context, char *line)
+static int command_run_line_inner(command_context_t *context, char *line)
 {
        int nwords;
        char *words[128] = {0};
@@ -399,6 +399,17 @@ int command_run_line(command_context_t *context, char *line)
        return retval;
 }
 
+int command_run_line(command_context_t *context, char *line)
+{
+       int retval=command_run_line_inner(context, line);
+       // we don't want any dangling callbacks!
+       // 
+       // Capturing output from logging is *very* loosly modeled on C/C++ exceptions.
+       // the capture must be set up at function entry and 
+       // stops when the function call returns
+       log_setCallback(NULL, NULL);
+       return retval;
+}
 int command_run_file(command_context_t *context, FILE *file, enum command_mode mode)
 {
        int retval = ERROR_OK;
@@ -441,7 +452,7 @@ int command_run_file(command_context_t *context, FILE *file, enum command_mode m
                        break;
 
                /* run line */
-               if ((retval = command_run_line(context, cmd)) == ERROR_COMMAND_CLOSE_CONNECTION)
+               if ((retval = command_run_line_inner(context, cmd)) == ERROR_COMMAND_CLOSE_CONNECTION)
                        break;
        }
        
index 744070788d22eded912b664e07e4b41fbdd70a50..db0bc0bd6f889bd154babff3678bce6bf56d5ac7 100644 (file)
@@ -33,6 +33,16 @@ int debug_level = -1;
 
 static FILE* log_output;
 
+
+static void *privData;
+static logCallback callback;
+
+void log_setCallback(logCallback c, void *p)
+{
+       callback=c;
+       privData=p;
+}
+
 static char *log_strings[4] = 
 {
        "Error:  ",
@@ -56,25 +66,18 @@ void log_printf(enum log_levels level, const char *file, int line, const char *f
        fflush(log_output);
        
        va_end(args);
-}
 
-void short_log_printf(enum log_levels level, const char *format, ...)
+       if (callback)
 {
-       va_list args;
-       char buffer[512];
-
-       if (level > debug_level)
-               return;
-
        va_start(args, format);
-       vsnprintf(buffer, 512, format, args);
 
-       fprintf(log_output, "%s %s\n", log_strings[level], buffer);
-       fflush(log_output);
+               callback(privData, file, line, function, format, args);
 
        va_end(args);
 }
 
+}
+
 /* change the current debug level on the fly
  * 0: only ERRORS
  * 1: + WARNINGS
@@ -136,3 +139,42 @@ int log_init(struct command_context_s *cmd_ctx)
        
        return ERROR_OK;
 }
+       
+int set_log_output(struct command_context_s *cmd_ctx, FILE *output)
+{
+       log_output=output;
+       return ERROR_OK;
+}
+
+/* return allocated string w/printf() result */
+char *allocPrintf(const char *fmt, va_list ap)
+{
+       char *string=NULL;
+       int size=0; // start by 0 to exercise all the code paths. Need minimum 2 bytes to fit 1 char and 0 terminator.
+       int first=1;
+       for (;;)
+       {
+               if ((string==NULL)||(!first))
+               {
+                       size=size*2+2;
+                       char *t=string;
+                       string=realloc(string, size);
+                       if (string==NULL)
+                       {
+                               if (t!=NULL)
+                                       free(t);
+                               return NULL;
+                       }
+               }
+       
+           int ret;
+           ret = vsnprintf(string, size, fmt, ap);
+           // NB! The result of the vsnprintf() might be an *EMPTY* string!
+           if ((ret>=0)&&((ret+1)<size))
+           {
+               return string;
+           }
+           // there was just enough or not enough space, allocate more.
+           first=0;
+       }
+}
index 6e799ad36f933252e5c8f2b6428557595624087f..34646e70217374539ef21dee2e1c57554333d8c4 100644 (file)
@@ -44,6 +44,12 @@ extern void log_printf(enum log_levels level, const char *file, int line,
        __attribute__ ((format (printf, 5, 6)));
 extern int log_register_commands(struct command_context_s *cmd_ctx);
 extern int log_init(struct command_context_s *cmd_ctx);
+extern int set_log_output(struct command_context_s *cmd_ctx, FILE *output);
+
+typedef void (*logCallback)(void *privData, const char *file, int line, 
+               const char *function, const char *format, va_list args);
+
+void log_setCallback(logCallback callback, void *privData);            
 
 extern int debug_level;
 
@@ -67,25 +73,6 @@ extern int debug_level;
                log_printf (LOG_ERROR, __FILE__, __LINE__, __FUNCTION__, expr); \
        } while(0)
 
-#define SDEBUG(expr ...) \
-       do { \
-               short_log_printf (LOG_DEBUG, expr); \
-       } while(0)
-
-#define SINFO(expr ...) \
-       do { \
-               short_log_printf (LOG_INFO, expr); \
-       } while(0)
-
-#define SWARNING(expr ...) \
-       do { \
-               short_log_printf (LOG_WARNING, expr); \
-       } while(0)
-
-#define SERROR(expr ...) \
-       do { \
-               short_log_printf (LOG_ERROR, expr); \
-       } while(0)
 
 /* general failures
  * error codes < 100
@@ -95,4 +82,7 @@ extern int debug_level;
 #define ERROR_NO_CONFIG_FILE           (-2)
 #define ERROR_BUF_TOO_SMALL                    (-3)
 
-#endif /* ERROR_H */
+char *allocPrintf(const char *fmt, va_list ap);
+
+
+#endif /* LOG_H */
index d48101f4591a6b39d3111a39188ed8d03f4262d6..b15c29d38be3397c8f6df091d6c755f2019ce21d 100644 (file)
 
 static unsigned short gdb_port;
 
+static void gdb_log_callback(void *privData, const char *file, int line, 
+               const char *function, const char *format, va_list args);
+
+
 enum gdb_detach_mode
 {
        GDB_DETACH_RESUME,
@@ -180,7 +184,7 @@ int gdb_putback_char(connection_t *connection, int last_char)
        return ERROR_OK;
 }
 
-int gdb_put_packet(connection_t *connection, char *buffer, int len)
+int gdb_put_packet_inner(connection_t *connection, char *buffer, int len)
 {
        int i;
        unsigned char my_checksum = 0;
@@ -245,10 +249,19 @@ int gdb_put_packet(connection_t *connection, char *buffer, int len)
        return ERROR_OK;
 }
 
-int gdb_get_packet(connection_t *connection, char *buffer, int *len)
+int gdb_put_packet(connection_t *connection, char *buffer, int len)
+{
+       gdb_connection_t *gdb_connection = connection->priv;
+       gdb_connection->output_disable=1;
+       int retval=gdb_put_packet_inner(connection, buffer, len);
+       gdb_connection->output_disable=0;
+       return retval;
+}
+
+int gdb_get_packet_inner(connection_t *connection, char *buffer, int *len)
 {
        int character;
-       int count;
+       int count = 0;
        int retval;
        char checksum[3];
        unsigned char my_checksum = 0;
@@ -286,8 +299,9 @@ int gdb_get_packet(connection_t *connection, char *buffer, int *len)
                } while (character != '$');
 
                my_checksum = 0;
-               count = 0;
                
+               count=0;
+               gdb_connection_t *gdb_con = connection->priv;
                for (;;)
                {
                        /* The common case is that we have an entire packet with no escape chars.
@@ -391,11 +405,18 @@ int gdb_get_packet(connection_t *connection, char *buffer, int *len)
        return ERROR_OK;
 }
 
-int gdb_output(struct command_context_s *context, char* line)
+int gdb_get_packet(connection_t *connection, char *buffer, int *len)
 {
-       connection_t *connection = context->output_handler_priv;
        gdb_connection_t *gdb_connection = connection->priv;
+       gdb_connection->output_disable=1;
+       int retval=gdb_get_packet_inner(connection, buffer, len);
+       gdb_connection->output_disable=0;
+       return retval;
+}
        
+int gdb_output_con(connection_t *connection, char* line)
+{
+       gdb_connection_t *gdb_connection = connection->priv;
        char *hex_buffer;
        int i, bin_size;
 
@@ -422,6 +443,12 @@ int gdb_output(struct command_context_s *context, char* line)
        return ERROR_OK;
 }
 
+int gdb_output(struct command_context_s *context, char* line)
+{
+       connection_t *connection = context->output_handler_priv;
+       return gdb_output_con(connection, line);
+}
+
 int gdb_program_handler(struct target_s *target, enum target_event event, void *priv)
 {
        FILE *script;
@@ -458,6 +485,9 @@ int gdb_target_callback_event_handler(struct target_s *target, enum target_event
                case TARGET_EVENT_HALTED:
                        if (gdb_connection->frontend_state == TARGET_RUNNING)
                        {
+                               // stop forwarding log packets!
+                               log_setCallback(NULL, NULL);
+                               
                                if (gdb_connection->ctrl_c)
                                {
                                        signal = 0x2;
@@ -895,7 +925,6 @@ int gdb_memory_packet_error(connection_t *connection, int retval)
                case ERROR_TARGET_NOT_HALTED:
                        ERROR("gdb tried to read memory but we're not halted, dropping connection");
                        return ERROR_SERVER_REMOTE_CLOSED;
-                       break;
                case ERROR_TARGET_DATA_ABORT:
                        gdb_send_error(connection, EIO);
                        break;
@@ -1398,6 +1427,9 @@ int gdb_query_packet(connection_t *connection, target_t *target, char *packet, i
                                cmd[i] = tmp;
                        }
                        cmd[(packet_size - 6)/2] = 0x0;
+                       
+                       /* We want to print all debug output to GDB connection */
+                       log_setCallback(gdb_log_callback, connection);
                        target_call_timer_callbacks();
                        command_run_line(cmd_ctx, cmd);
                        free(cmd);
@@ -1759,6 +1791,22 @@ int gdb_detach(connection_t *connection, target_t *target)
        return ERROR_OK;
 }
 
+
+
+static void gdb_log_callback(void *privData, const char *file, int line, 
+               const char *function, const char *format, va_list args)
+{
+       connection_t *connection=(connection_t *)privData;
+       
+       char *t=allocPrintf(format, args);
+       if (t==NULL)
+               return;
+       
+       gdb_output_con(connection, t); 
+       
+       free(t);
+}
+
 int gdb_input(connection_t *connection)
 {
        gdb_service_t *gdb_service = connection->service->priv;
@@ -1833,6 +1881,9 @@ int gdb_input(connection_t *connection)
                                        break;
                                case 'c':
                                case 's':
+                                       /* We're running/stepping, in which case we can 
+                                        * forward log output until the target is halted */
+                                       log_setCallback(gdb_log_callback, connection);
                                        gdb_step_continue_packet(connection, target, packet, packet_size);
                                        break;
                                case 'v':
index 3a74f5ac4c8905dd1c98e7b4b12220f4a9611742..af49050a912aa7c3a398e7f9c4c206dbce44fb3b 100644 (file)
@@ -57,6 +57,12 @@ void telnet_prompt(connection_t *connection)
        write_socket(connection->fd, t_con->prompt, strlen(t_con->prompt));
 }
 
+int telnet_outputline(connection_t *connection, char* line)
+{
+       write_socket(connection->fd, line, strlen(line));
+       return write_socket(connection->fd, "\r\n\0", 3);
+}
+
 int telnet_output(struct command_context_s *cmd_ctx, char* line)
 {
        connection_t *connection = cmd_ctx->output_handler_priv;
@@ -67,6 +73,19 @@ int telnet_output(struct command_context_s *cmd_ctx, char* line)
        return ERROR_OK;
 }
 
+void telnet_log_callback(void *privData, const char *file, int line, 
+               const char *function, const char *format, va_list args)
+{
+       connection_t *connection=(connection_t *)privData;
+       char *t=allocPrintf(format, args);
+       if (t==NULL)
+               return;
+       
+       telnet_outputline(connection, t);
+       
+       free(t);
+}
+
 int telnet_target_callback_event_handler(struct target_s *target, enum target_event event, void *priv)
 {
        struct command_context_s *cmd_ctx = priv;
@@ -244,6 +263,10 @@ int telnet_input(connection_t *connection)
                                                                continue;
                                                        }
                                                        
+
+                                                       
+                                                       log_setCallback(telnet_log_callback, connection);
+                                                       
                                                        if ((retval = command_run_line(command_context, t_con->line)) != ERROR_OK)
                                                        {
                                                                if (retval == ERROR_COMMAND_CLOSE_CONNECTION)

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)