use COMMAND_HANDLER macro to define all commands
[openocd.git] / src / server / gdb_server.c
index ea6f6b75aa7ad2242b28298526d01cc18f009996..c0c5d7751b1192639c98f25efc728e143f73c201 100644 (file)
@@ -2,7 +2,7 @@
  *   Copyright (C) 2005 by Dominic Rath                                    *
  *   Dominic.Rath@gmx.de                                                   *
  *                                                                         *
- *   Copyright (C) 2007,2008 Øyvind Harboe                                 *
+ *   Copyright (C) 2007,2008 Øyvind Harboe                                 *
  *   oyvind.harboe@zylin.com                                               *
  *                                                                         *
  *   Copyright (C) 2008 by Spencer Oliver                                  *
 #include "config.h"
 #endif
 
-#include "replacements.h"
-
 #include "gdb_server.h"
-
+#include "target_request.h"
+#include "register.h"
 #include "server.h"
-#include "log.h"
-#include "binarybuffer.h"
-#include "jtag.h"
-#include "breakpoints.h"
 #include "flash.h"
-#include "target.h"
-#include "target_request.h"
-#include "configuration.h"
+#include "image.h"
+#include "jtag.h"
 
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <stdlib.h>
 
 #if 0
 #define _DEBUG_GDB_IO_
 #endif
 
+static gdb_connection_t *current_gdb_connection;
+
 static int gdb_breakpoint_override;
 static enum breakpoint_type gdb_breakpoint_override_type;
 
 extern int gdb_error(connection_t *connection, int retval);
-static unsigned short gdb_port;
+static unsigned short gdb_port = 3333;
 static const char *DIGITS = "0123456789abcdef";
 
-static void gdb_log_callback(void *priv, const char *file, int line,
+static void gdb_log_callback(void *priv, const char *file, unsigned line,
                const char *function, const char *string);
 
-enum gdb_detach_mode
-{
-       GDB_DETACH_RESUME,
-       GDB_DETACH_RESET,
-       GDB_DETACH_HALT,
-       GDB_DETACH_NOTHING
-};
-
-/* target behaviour on gdb detach */
-enum gdb_detach_mode detach_mode = GDB_DETACH_RESUME;
+/* number of gdb connections, mainly to supress gdb related debugging spam
+ * in helper/log.c when no gdb connections are actually active */
+int gdb_actual_connections;
 
 /* set if we are sending a memory map to gdb
  * via qXfer:memory-map:read packet */
@@ -111,11 +96,11 @@ int check_pending(connection_t *connection, int timeout_s, int *got_data)
        fd_set read_fds;
        gdb_connection_t *gdb_con = connection->priv;
        int t;
-       if (got_data==NULL)
+       if (got_data == NULL)
                got_data=&t;
-       *got_data=0;
+       *got_data = 0;
 
-       if (gdb_con->buf_cnt>0)
+       if (gdb_con->buf_cnt > 0)
        {
                *got_data = 1;
                return ERROR_OK;
@@ -126,12 +111,12 @@ int check_pending(connection_t *connection, int timeout_s, int *got_data)
 
        tv.tv_sec = timeout_s;
        tv.tv_usec = 0;
-       if (select(connection->fd + 1, &read_fds, NULL, NULL, &tv) == 0)
+       if (socket_select(connection->fd + 1, &read_fds, NULL, NULL, &tv) == 0)
        {
                /* This can typically be because a "monitor" command took too long
                 * before printing any progress messages
                 */
-               if (timeout_s>0)
+               if (timeout_s > 0)
                {
                        return ERROR_GDB_TIMEOUT;
                } else
@@ -139,14 +124,14 @@ int check_pending(connection_t *connection, int timeout_s, int *got_data)
                        return ERROR_OK;
                }
        }
-       *got_data=FD_ISSET(connection->fd, &read_fds)!=0;
+       *got_data = FD_ISSET(connection->fd, &read_fds) != 0;
        return ERROR_OK;
 }
 
 int gdb_get_char(connection_t *connection, int* next_char)
 {
        gdb_connection_t *gdb_con = connection->priv;
-       int retval=ERROR_OK;
+       int retval = ERROR_OK;
 
 #ifdef _DEBUG_GDB_IO_
        char *debug_buffer;
@@ -169,10 +154,18 @@ int gdb_get_char(connection_t *connection, int* next_char)
 
        for (;;)
        {
-               retval=check_pending(connection, 1, NULL);
-               if (retval!=ERROR_OK)
-                       return retval;
-               gdb_con->buf_cnt = read_socket(connection->fd, gdb_con->buffer, GDB_BUFFER_SIZE);
+               if (connection->service->type == CONNECTION_PIPE)
+               {
+                       gdb_con->buf_cnt = read(connection->fd, gdb_con->buffer, GDB_BUFFER_SIZE);
+               }
+               else
+               {
+                       retval = check_pending(connection, 1, NULL);
+                       if (retval != ERROR_OK)
+                               return retval;
+                       gdb_con->buf_cnt = read_socket(connection->fd, gdb_con->buffer, GDB_BUFFER_SIZE);
+               }
+
                if (gdb_con->buf_cnt > 0)
                {
                        break;
@@ -186,7 +179,7 @@ int gdb_get_char(connection_t *connection, int* next_char)
 #ifdef _WIN32
                errno = WSAGetLastError();
 
-               switch(errno)
+               switch (errno)
                {
                        case WSAEWOULDBLOCK:
                                usleep(1000);
@@ -202,7 +195,7 @@ int gdb_get_char(connection_t *connection, int* next_char)
                                exit(-1);
                }
 #else
-               switch(errno)
+               switch (errno)
                {
                        case EAGAIN:
                                usleep(1000);
@@ -269,9 +262,20 @@ int gdb_write(connection_t *connection, void *data, int len)
        if (gdb_con->closed)
                return ERROR_SERVER_REMOTE_CLOSED;
 
-       if (write_socket(connection->fd, data, len) == len)
+       if (connection->service->type == CONNECTION_PIPE)
        {
-               return ERROR_OK;
+               /* write to stdout */
+               if (write(STDOUT_FILENO, data, len) == len)
+               {
+                       return ERROR_OK;
+               }
+       }
+       else
+       {
+               if (write_socket(connection->fd, data, len) == len)
+               {
+                       return ERROR_OK;
+               }
        }
        gdb_con->closed = 1;
        return ERROR_SERVER_REMOTE_CLOSED;
@@ -300,15 +304,15 @@ int gdb_put_packet_inner(connection_t *connection, char *buffer, int len)
        int gotdata;
        for (;;)
        {
-               if ((retval=check_pending(connection, 0, &gotdata))!=ERROR_OK)
+               if ((retval = check_pending(connection, 0, &gotdata)) != ERROR_OK)
                        return retval;
                if (!gotdata)
                        break;
                if ((retval = gdb_get_char(connection, &reply)) != ERROR_OK)
                        return retval;
-               if( reply == '$' ){
-                       // fix a problem with some IAR tools
-                       gdb_putback_char( connection, reply );
+               if (reply == '$') {
+                       /* fix a problem with some IAR tools */
+                       gdb_putback_char(connection, reply);
                        LOG_DEBUG("Unexpected start of new packet");
                        break;
                }
@@ -329,14 +333,14 @@ int gdb_put_packet_inner(connection_t *connection, char *buffer, int len)
 
                char local_buffer[1024];
                local_buffer[0] = '$';
-               if (len+4 <= sizeof(local_buffer))
+               if ((size_t)len + 4 <= sizeof(local_buffer))
                {
                        /* performance gain on smaller packets by only a single call to gdb_write() */
-                       memcpy(local_buffer+1, buffer, len++);
+                       memcpy(local_buffer + 1, buffer, len++);
                        local_buffer[len++] = '#';
                        local_buffer[len++] = DIGITS[(my_checksum >> 4) & 0xf];
                        local_buffer[len++] = DIGITS[my_checksum & 0xf];
-                       if((retval = gdb_write(connection, local_buffer, len)) != ERROR_OK)
+                       if ((retval = gdb_write(connection, local_buffer, len)) != ERROR_OK)
                        {
                                return retval;
                        }
@@ -348,15 +352,15 @@ int gdb_put_packet_inner(connection_t *connection, char *buffer, int len)
                        local_buffer[1] = '#';
                        local_buffer[2] = DIGITS[(my_checksum >> 4) & 0xf];
                        local_buffer[3] = DIGITS[my_checksum & 0xf];
-                       if((retval = gdb_write(connection, local_buffer, 1)) != ERROR_OK)
+                       if ((retval = gdb_write(connection, local_buffer, 1)) != ERROR_OK)
                        {
                                return retval;
                        }
-                       if((retval = gdb_write(connection, buffer, len)) != ERROR_OK)
+                       if ((retval = gdb_write(connection, buffer, len)) != ERROR_OK)
                        {
                                return retval;
                        }
-                       if((retval = gdb_write(connection, local_buffer+1, 3)) != ERROR_OK)
+                       if ((retval = gdb_write(connection, local_buffer + 1, 3)) != ERROR_OK)
                        {
                                return retval;
                        }
@@ -389,26 +393,26 @@ int gdb_put_packet_inner(connection_t *connection, char *buffer, int len)
                                log_remove_callback(gdb_log_callback, connection);
                                LOG_WARNING("negative reply, retrying");
                        }
-                       else if( reply == '$' ){
+                       else if (reply == '$') {
                                LOG_ERROR("GDB missing ack(1) - assumed good");
-                               gdb_putback_char( connection, reply );
+                               gdb_putback_char(connection, reply);
                                return ERROR_OK;
                        } else {
 
                                LOG_ERROR("unknown character(1) 0x%2.2x in reply, dropping connection", reply);
-                               gdb_con->closed=1;
+                               gdb_con->closed = 1;
                                return ERROR_SERVER_REMOTE_CLOSED;
                        }
                }
-               else if( reply == '$' ){
+               else if (reply == '$') {
                        LOG_ERROR("GDB missing ack(2) - assumed good");
-                       gdb_putback_char( connection, reply );
+                       gdb_putback_char(connection, reply);
                        return ERROR_OK;
                }
                else
                {
                        LOG_ERROR("unknown character(2) 0x%2.2x in reply, dropping connection", reply);
-                       gdb_con->closed=1;
+                       gdb_con->closed = 1;
                        return ERROR_SERVER_REMOTE_CLOSED;
                }
        }
@@ -448,7 +452,7 @@ static __inline__ int fetch_packet(connection_t *connection, int *checksum_ok, i
                 * We need to leave at least 2 bytes in the buffer to have
                 * gdb_get_char() update various bits and bobs correctly.
                 */
-               if ((gdb_con->buf_cnt > 2) && ((gdb_con->buf_cnt+count) < *len))
+               if ((gdb_con->buf_cnt > 2) && ((gdb_con->buf_cnt + count) < *len))
                {
                        /* The compiler will struggle a bit with constant propagation and
                         * aliasing, so we help it by showing that these values do not
@@ -534,7 +538,7 @@ static __inline__ int fetch_packet(connection_t *connection, int *checksum_ok, i
 
        if (!noack)
        {
-               *checksum_ok=(my_checksum == strtoul(checksum, NULL, 16));
+               *checksum_ok = (my_checksum == strtoul(checksum, NULL, 16));
        }
 
        return ERROR_OK;
@@ -581,17 +585,17 @@ int gdb_get_packet_inner(connection_t *connection, char *buffer, int *len)
 
 
 
-               int checksum_ok;
+               int checksum_ok = 0;
                /* explicit code expansion here to get faster inlined code in -O3 by not
                 * calculating checksum
                 */
                if (gdb_con->noack_mode)
                {
-                       if ((retval=fetch_packet(connection, &checksum_ok, 1, len, buffer))!=ERROR_OK)
+                       if ((retval = fetch_packet(connection, &checksum_ok, 1, len, buffer)) != ERROR_OK)
                                return retval;
                } else
                {
-                       if ((retval=fetch_packet(connection, &checksum_ok, 0, len, buffer))!=ERROR_OK)
+                       if ((retval = fetch_packet(connection, &checksum_ok, 0, len, buffer)) != ERROR_OK)
                                return retval;
                }
 
@@ -636,9 +640,9 @@ int gdb_output_con(connection_t *connection, const char* line)
                return ERROR_GDB_BUFFER_TOO_SMALL;
 
        hex_buffer[0] = 'O';
-       for (i=0; i<bin_size; i++)
+       for (i = 0; i < bin_size; i++)
                snprintf(hex_buffer + 1 + i*2, 3, "%2.2x", line[i]);
-       hex_buffer[bin_size*2+1] = 0;
+       hex_buffer[bin_size*2 + 1] = 0;
 
        int retval = gdb_put_packet(connection, hex_buffer, bin_size*2 + 1);
 
@@ -658,7 +662,7 @@ static void gdb_frontend_halted(struct target_s *target, connection_t *connectio
 {
        gdb_connection_t *gdb_connection = connection->priv;
 
-       /* In the GDB protocol when we are stepping or coninuing execution,
+       /* In the GDB protocol when we are stepping or continuing execution,
         * we have a lingering reply. Upon receiving a halted event
         * when we have that lingering packet, we reply to the original
         * step or continue packet.
@@ -696,18 +700,18 @@ int gdb_target_callback_event_handler(struct target_s *target, enum target_event
        int retval;
        connection_t *connection = priv;
 
-       target_handle_event( target, event );
+       target_handle_event(target, event);
        switch (event)
        {
-               case TARGET_EVENT_EARLY_HALTED:
+               case TARGET_EVENT_GDB_HALT:
                        gdb_frontend_halted(target, connection);
                        break;
                case TARGET_EVENT_HALTED:
                        target_call_event_callbacks(target, TARGET_EVENT_GDB_END);
                        break;
                case TARGET_EVENT_GDB_FLASH_ERASE_START:
-                       target_handle_event( target, TARGET_EVENT_OLD_gdb_program_config );
-                       if((retval = jtag_execute_queue()) != ERROR_OK)
+                       target_handle_event(target, TARGET_EVENT_OLD_gdb_program_config);
+                       if ((retval = jtag_execute_queue()) != ERROR_OK)
                        {
                                return retval;
                        }
@@ -719,7 +723,6 @@ int gdb_target_callback_event_handler(struct target_s *target, enum target_event
        return ERROR_OK;
 }
 
-
 int gdb_new_connection(connection_t *connection)
 {
        gdb_connection_t *gdb_connection = malloc(sizeof(gdb_connection_t));
@@ -738,6 +741,7 @@ int gdb_new_connection(connection_t *connection)
        gdb_connection->closed = 0;
        gdb_connection->busy = 0;
        gdb_connection->noack_mode = 0;
+       gdb_connection->sync = true;
 
        /* send ACK to GDB for debug request */
        gdb_write(connection, "+", 1);
@@ -755,30 +759,6 @@ int gdb_new_connection(connection_t *connection)
        /* register callback to be informed about target events */
        target_register_event_callback(gdb_target_callback_event_handler, connection);
 
-       /* a gdb session just attached, try to put the target in halt mode.
-        *
-        * DANGER!!!!
-        *
-        * If the halt fails(e.g. target needs a reset, JTAG communication not
-        * working, etc.), then the GDB connect will succeed as
-        * the get_gdb_reg_list() will lie and return a register list with
-        * dummy values.
-        *
-        * This allows GDB monitor commands to be run from a GDB init script to
-        * initialize the target
-        *
-        * Also, since the halt() is asynchronous target connect will be
-        * instantaneous and thus avoiding annoying timeout problems during
-        * connect.
-        */
-       target_halt(gdb_service->target);
-       /* FIX!!!! could extended-remote work better here?
-        *
-        *  wait a tiny bit for halted state or we just continue. The
-        * GDB register packet will then contain garbage
-        */
-       target_wait_state(gdb_service->target, TARGET_HALTED, 500);
-
        /* remove the initial ACK from the incoming buffer */
        if ((retval = gdb_get_char(connection, &initial_ack)) != ERROR_OK)
                return retval;
@@ -788,7 +768,14 @@ int gdb_new_connection(connection_t *connection)
         */
        if (initial_ack != '+')
                gdb_putback_char(connection, initial_ack);
-       target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_ATTACH );
+       target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_ATTACH);
+
+       gdb_actual_connections++;
+       LOG_DEBUG("New GDB Connection: %d, Target %s, state: %s",
+                 gdb_actual_connections,
+                 gdb_service->target->cmd_name,
+                 target_state_name(gdb_service->target));
+
        return ERROR_OK;
 }
 
@@ -797,6 +784,17 @@ int gdb_connection_closed(connection_t *connection)
        gdb_service_t *gdb_service = connection->service->priv;
        gdb_connection_t *gdb_connection = connection->priv;
 
+       /* we're done forwarding messages. Tear down callback before
+        * cleaning up connection.
+        */
+       log_remove_callback(gdb_log_callback, connection);
+
+       gdb_actual_connections--;
+       LOG_DEBUG("GDB Close, Target: %s, state: %s, gdb_actual_connections=%d",
+                 gdb_service->target->cmd_name,
+                 target_state_name(gdb_service->target),
+                 gdb_actual_connections);
+
        /* see if an image built with vFlash commands is left */
        if (gdb_connection->vflash_image)
        {
@@ -818,19 +816,20 @@ int gdb_connection_closed(connection_t *connection)
                LOG_ERROR("BUG: connection->priv == NULL");
        }
 
+
        target_unregister_event_callback(gdb_target_callback_event_handler, connection);
+
        target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_END);
-       log_remove_callback(gdb_log_callback, connection);
 
-       target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_DETACH );
+       target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_DETACH);
 
        return ERROR_OK;
 }
 
-void gdb_send_error(connection_t *connection, u8 the_error)
+void gdb_send_error(connection_t *connection, uint8_t the_error)
 {
        char err[4];
-       snprintf(err, 4, "E%2.2X", the_error );
+       snprintf(err, 4, "E%2.2X", the_error);
        gdb_put_packet(connection, err, 3);
 }
 
@@ -847,40 +846,72 @@ int gdb_last_signal_packet(connection_t *connection, target_t *target, char* pac
        return ERROR_OK;
 }
 
-/* Convert register to string of bits. NB! The # of bits in the
+static int gdb_reg_pos(target_t *target, int pos, int len)
+{
+       if (target->endianness == TARGET_LITTLE_ENDIAN)
+               return pos;
+       else
+               return len - 1 - pos;
+}
+
+/* Convert register to string of bytes. NB! The # of bits in the
  * register might be non-divisible by 8(a byte), in which
- * case an entire byte is shown. */
+ * case an entire byte is shown.
+ *
+ * NB! the format on the wire is the target endianess
+ *
+ * The format of reg->value is little endian
+ *
+ */
 void gdb_str_to_target(target_t *target, char *tstr, reg_t *reg)
 {
        int i;
 
-       u8 *buf;
+       uint8_t *buf;
        int buf_len;
        buf = reg->value;
        buf_len = CEIL(reg->size, 8);
 
        for (i = 0; i < buf_len; i++)
        {
-               tstr[i*2]   = DIGITS[(buf[i]>>4) & 0xf];
-               tstr[i*2+1] = DIGITS[buf[i]&0xf];
+               int j = gdb_reg_pos(target, i, buf_len);
+               tstr[i*2]   = DIGITS[(buf[j]>>4) & 0xf];
+               tstr[i*2 + 1] = DIGITS[buf[j]&0xf];
        }
 }
 
-void gdb_target_to_str(target_t *target, char *tstr, char *str)
+static int hextoint(char c)
 {
-       int str_len = strlen(tstr);
-       int i;
+       if (c>='0'&&c<='9')
+       {
+               return c-'0';
+       }
+       c = toupper(c);
+       if (c>='A'&&c<='F')
+       {
+               return c-'A'+10;
+       }
+       LOG_ERROR("BUG: invalid register value %08x", c);
+       return 0;
+}
 
+/* copy over in register buffer */
+void gdb_target_to_reg(target_t *target, char *tstr, int str_len, uint8_t *bin)
+{
        if (str_len % 2)
        {
                LOG_ERROR("BUG: gdb value with uneven number of characters encountered");
                exit(-1);
        }
 
-       for (i = 0; i < str_len; i+=2)
+       int i;
+       for (i = 0; i < str_len; i += 2)
        {
-               str[str_len - i - 1] = tstr[i + 1];
-               str[str_len - i - 2] = tstr[i];
+               uint8_t t = hextoint(tstr[i]) << 4;
+               t |= hextoint(tstr[i + 1]);
+
+               int j = gdb_reg_pos(target, i/2, str_len/2);
+               bin[j] = t;
        }
 }
 
@@ -898,7 +929,7 @@ int gdb_get_registers_packet(connection_t *connection, target_t *target, char* p
        LOG_DEBUG("-");
 #endif
 
-       if ((retval = target->type->get_gdb_reg_list(target, &reg_list, &reg_list_size)) != ERROR_OK)
+       if ((retval = target_get_gdb_reg_list(target, &reg_list, &reg_list_size)) != ERROR_OK)
        {
                return gdb_error(connection, retval);
        }
@@ -956,7 +987,7 @@ int gdb_set_registers_packet(connection_t *connection, target_t *target, char *p
                return ERROR_SERVER_REMOTE_CLOSED;
        }
 
-       if ((retval = target->type->get_gdb_reg_list(target, &reg_list, &reg_list_size)) != ERROR_OK)
+       if ((retval = target_get_gdb_reg_list(target, &reg_list, &reg_list_size)) != ERROR_OK)
        {
                return gdb_error(connection, retval);
        }
@@ -964,17 +995,17 @@ int gdb_set_registers_packet(connection_t *connection, target_t *target, char *p
        packet_p = packet;
        for (i = 0; i < reg_list_size; i++)
        {
-               u8 *bin_buf;
-               char *hex_buf;
-               reg_arch_type_t *arch_type;
+               uint8_t *bin_buf;
+               int chars = (CEIL(reg_list[i]->size, 8) * 2);
 
-               /* convert from GDB-string (target-endian) to hex-string (big-endian) */
-               hex_buf = malloc(CEIL(reg_list[i]->size, 8) * 2);
-               gdb_target_to_str(target, packet_p, hex_buf);
+               if (packet_p + chars > packet + packet_size)
+               {
+                       LOG_ERROR("BUG: register packet is too small for registers");
+               }
 
-               /* convert hex-string to binary buffer */
+               reg_arch_type_t *arch_type;
                bin_buf = malloc(CEIL(reg_list[i]->size, 8));
-               str_to_buf(hex_buf, CEIL(reg_list[i]->size, 8) * 2, bin_buf, reg_list[i]->size, 16);
+               gdb_target_to_reg(target, packet_p, chars, bin_buf);
 
                /* get register arch_type, and call set method */
                arch_type = register_get_arch_type(reg_list[i]->arch_type);
@@ -982,10 +1013,10 @@ int gdb_set_registers_packet(connection_t *connection, target_t *target, char *p
                arch_type->set(reg_list[i], bin_buf);
 
                /* advance packet pointer */
-               packet_p += (CEIL(reg_list[i]->size, 8) * 2);
+               packet_p += chars;
+
 
                free(bin_buf);
-               free(hex_buf);
        }
 
        /* free reg_t *reg_list[] array allocated by get_gdb_reg_list */
@@ -1008,7 +1039,7 @@ int gdb_get_register_packet(connection_t *connection, target_t *target, char *pa
        LOG_DEBUG("-");
 #endif
 
-       if ((retval = target->type->get_gdb_reg_list(target, &reg_list, &reg_list_size)) != ERROR_OK)
+       if ((retval = target_get_gdb_reg_list(target, &reg_list, &reg_list_size)) != ERROR_OK)
        {
                return gdb_error(connection, retval);
        }
@@ -1034,8 +1065,7 @@ int gdb_get_register_packet(connection_t *connection, target_t *target, char *pa
 int gdb_set_register_packet(connection_t *connection, target_t *target, char *packet, int packet_size)
 {
        char *separator;
-       char *hex_buf;
-       u8 *bin_buf;
+       uint8_t *bin_buf;
        int reg_num = strtoul(packet + 1, &separator, 16);
        reg_t **reg_list;
        int reg_list_size;
@@ -1044,7 +1074,7 @@ int gdb_set_register_packet(connection_t *connection, target_t *target, char *pa
 
        LOG_DEBUG("-");
 
-       if ((retval = target->type->get_gdb_reg_list(target, &reg_list, &reg_list_size)) != ERROR_OK)
+       if ((retval = target_get_gdb_reg_list(target, &reg_list, &reg_list_size)) != ERROR_OK)
        {
                return gdb_error(connection, retval);
        }
@@ -1062,21 +1092,20 @@ int gdb_set_register_packet(connection_t *connection, target_t *target, char *pa
        }
 
        /* convert from GDB-string (target-endian) to hex-string (big-endian) */
-       hex_buf = malloc(CEIL(reg_list[reg_num]->size, 8) * 2);
-       gdb_target_to_str(target, separator + 1, hex_buf);
-
-       /* convert hex-string to binary buffer */
        bin_buf = malloc(CEIL(reg_list[reg_num]->size, 8));
-       str_to_buf(hex_buf, CEIL(reg_list[reg_num]->size, 8) * 2, bin_buf, reg_list[reg_num]->size, 16);
+       int chars = (CEIL(reg_list[reg_num]->size, 8) * 2);
+
+       /* fix!!! add some sanity checks on packet size here */
 
-       /* get register arch_type, and call set method */
+       gdb_target_to_reg(target, separator + 1, chars, bin_buf);
+
+               /* get register arch_type, and call set method */
        arch_type = register_get_arch_type(reg_list[reg_num]->arch_type);
        arch_type->set(reg_list[reg_num], bin_buf);
 
        gdb_put_packet(connection, "OK", 2);
 
        free(bin_buf);
-       free(hex_buf);
        free(reg_list);
 
        return ERROR_OK;
@@ -1116,10 +1145,10 @@ int gdb_error(connection_t *connection, int retval)
 int gdb_read_memory_packet(connection_t *connection, target_t *target, char *packet, int packet_size)
 {
        char *separator;
-       u32 addr = 0;
-       u32 len = 0;
+       uint32_t addr = 0;
+       uint32_t len = 0;
 
-       u8 *buffer;
+       uint8_t *buffer;
        char *hex_buffer;
 
        int retval = ERROR_OK;
@@ -1135,15 +1164,15 @@ int gdb_read_memory_packet(connection_t *connection, target_t *target, char *pac
                return ERROR_SERVER_REMOTE_CLOSED;
        }
 
-       len = strtoul(separator+1, NULL, 16);
+       len = strtoul(separator + 1, NULL, 16);
 
        buffer = malloc(len);
 
-       LOG_DEBUG("addr: 0x%8.8x, len: 0x%8.8x", addr, len);
+       LOG_DEBUG("addr: 0x%8.8" PRIx32 ", len: 0x%8.8" PRIx32 "", addr, len);
 
        retval = target_read_buffer(target, addr, len, buffer);
 
-       if ((retval!=ERROR_OK)&&!gdb_report_data_abort)
+       if ((retval != ERROR_OK)&&!gdb_report_data_abort)
        {
                /* TODO : Here we have to lie and send back all zero's lest stack traces won't work.
                 * At some point this might be fixed in GDB, in which case this code can be removed.
@@ -1152,7 +1181,7 @@ int gdb_read_memory_packet(connection_t *connection, target_t *target, char *pac
                 * gained by involving the user in this problem that hopefully will get resolved
                 * eventually
                 *
-                * http://sourceware.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gdb&pr=2395
+                * http://sourceware.org/cgi-bin/gnatsweb.pl?cmd = view%20audit-trail&database = gdb&pr = 2395
                 *
                 * For now, the default is to fix up things to make current GDB versions work.
                 * This can be overwritten using the gdb_report_data_abort <'enable'|'disable'> command.
@@ -1165,10 +1194,10 @@ int gdb_read_memory_packet(connection_t *connection, target_t *target, char *pac
        {
                hex_buffer = malloc(len * 2 + 1);
 
-               int i;
+               uint32_t i;
                for (i = 0; i < len; i++)
                {
-                       u8 t = buffer[i];
+                       uint8_t t = buffer[i];
                        hex_buffer[2 * i] = DIGITS[(t >> 4) & 0xf];
                        hex_buffer[2 * i + 1] = DIGITS[t & 0xf];
                }
@@ -1190,12 +1219,12 @@ int gdb_read_memory_packet(connection_t *connection, target_t *target, char *pac
 int gdb_write_memory_packet(connection_t *connection, target_t *target, char *packet, int packet_size)
 {
        char *separator;
-       u32 addr = 0;
-       u32 len = 0;
+       uint32_t addr = 0;
+       uint32_t len = 0;
 
-       u8 *buffer;
+       uint8_t *buffer;
 
-       int i;
+       uint32_t i;
        int retval;
 
        /* skip command character */
@@ -1209,7 +1238,7 @@ int gdb_write_memory_packet(connection_t *connection, target_t *target, char *pa
                return ERROR_SERVER_REMOTE_CLOSED;
        }
 
-       len = strtoul(separator+1, &separator, 16);
+       len = strtoul(separator + 1, &separator, 16);
 
        if (*(separator++) != ':')
        {
@@ -1219,12 +1248,12 @@ int gdb_write_memory_packet(connection_t *connection, target_t *target, char *pa
 
        buffer = malloc(len);
 
-       LOG_DEBUG("addr: 0x%8.8x, len: 0x%8.8x", addr, len);
+       LOG_DEBUG("addr: 0x%8.8" PRIx32 ", len: 0x%8.8" PRIx32 "", addr, len);
 
-       for (i=0; i<len; i++)
+       for (i = 0; i < len; i++)
        {
-               u32 tmp;
-               sscanf(separator + 2*i, "%2x", &tmp);
+               uint32_t tmp;
+               sscanf(separator + 2*i, "%2" SCNx32 , &tmp);
                buffer[i] = tmp;
        }
 
@@ -1247,8 +1276,8 @@ int gdb_write_memory_packet(connection_t *connection, target_t *target, char *pa
 int gdb_write_memory_binary_packet(connection_t *connection, target_t *target, char *packet, int packet_size)
 {
        char *separator;
-       u32 addr = 0;
-       u32 len = 0;
+       uint32_t addr = 0;
+       uint32_t len = 0;
 
        int retval;
 
@@ -1263,7 +1292,7 @@ int gdb_write_memory_binary_packet(connection_t *connection, target_t *target, c
                return ERROR_SERVER_REMOTE_CLOSED;
        }
 
-       len = strtoul(separator+1, &separator, 16);
+       len = strtoul(separator + 1, &separator, 16);
 
        if (*(separator++) != ':')
        {
@@ -1274,9 +1303,9 @@ int gdb_write_memory_binary_packet(connection_t *connection, target_t *target, c
        retval = ERROR_OK;
        if (len)
        {
-               LOG_DEBUG("addr: 0x%8.8x, len: 0x%8.8x", addr, len);
+               LOG_DEBUG("addr: 0x%8.8" PRIx32 ", len: 0x%8.8" PRIx32 "", addr, len);
 
-               retval = target_write_buffer(target, addr, len, (u8*)separator);
+               retval = target_write_buffer(target, addr, len, (uint8_t*)separator);
        }
 
        if (retval == ERROR_OK)
@@ -1295,8 +1324,8 @@ int gdb_write_memory_binary_packet(connection_t *connection, target_t *target, c
 int gdb_step_continue_packet(connection_t *connection, target_t *target, char *packet, int packet_size)
 {
        int current = 0;
-       u32 address = 0x0;
-       int retval=ERROR_OK;
+       uint32_t address = 0x0;
+       int retval = ERROR_OK;
 
        LOG_DEBUG("-");
 
@@ -1313,13 +1342,14 @@ int gdb_step_continue_packet(connection_t *connection, target_t *target, char *p
        if (packet[0] == 'c')
        {
                LOG_DEBUG("continue");
-               target_handle_event( target, TARGET_EVENT_OLD_pre_resume );
-               retval=target_resume(target, current, address, 0, 0); /* resume at current address, don't handle breakpoints, not debugging */
+               target_handle_event(target, TARGET_EVENT_OLD_pre_resume);
+               retval = target_resume(target, current, address, 0, 0); /* resume at current address, don't handle breakpoints, not debugging */
        }
        else if (packet[0] == 's')
        {
                LOG_DEBUG("step");
-               retval=target->type->step(target, current, address, 0); /* step at current or address, don't handle breakpoints */
+               /* step at current or address, don't handle breakpoints */
+               retval = target_step(target, current, address, 0);
        }
        return retval;
 }
@@ -1329,8 +1359,8 @@ int gdb_breakpoint_watchpoint_packet(connection_t *connection, target_t *target,
        int type;
        enum breakpoint_type bp_type = BKPT_SOFT /* dummy init to avoid warning */;
        enum watchpoint_rw wp_type;
-       u32 address;
-       u32 size;
+       uint32_t address;
+       uint32_t size;
        char *separator;
        int retval;
 
@@ -1349,9 +1379,9 @@ int gdb_breakpoint_watchpoint_packet(connection_t *connection, target_t *target,
        else if (type == 4) /* access watchpoint */
                wp_type = WPT_ACCESS;
 
-       if (gdb_breakpoint_override&&((bp_type==BKPT_SOFT)||(bp_type==BKPT_HARD)))
+       if (gdb_breakpoint_override && ((bp_type == BKPT_SOFT)||(bp_type == BKPT_HARD)))
        {
-               bp_type=gdb_breakpoint_override_type;
+               bp_type = gdb_breakpoint_override_type;
        }
 
        if (*separator != ',')
@@ -1360,7 +1390,7 @@ int gdb_breakpoint_watchpoint_packet(connection_t *connection, target_t *target,
                return ERROR_SERVER_REMOTE_CLOSED;
        }
 
-       address = strtoul(separator+1, &separator, 16);
+       address = strtoul(separator + 1, &separator, 16);
 
        if (*separator != ',')
        {
@@ -1368,7 +1398,7 @@ int gdb_breakpoint_watchpoint_packet(connection_t *connection, target_t *target,
                return ERROR_SERVER_REMOTE_CLOSED;
        }
 
-       size = strtoul(separator+1, &separator, 16);
+       size = strtoul(separator + 1, &separator, 16);
 
        switch (type)
        {
@@ -1485,19 +1515,19 @@ static int decode_xfer_read(char *buf, char **annex, int *ofs, unsigned int *len
        if (*separator != ',')
                return -1;
 
-       *len = strtoul(separator+1, NULL, 16);
+       *len = strtoul(separator + 1, NULL, 16);
 
        return 0;
 }
 
 int gdb_calc_blocksize(flash_bank_t *bank)
 {
-       int i;
-       int block_size = 0xffffffff;
+       uint32_t i;
+       uint32_t block_size = 0xffffffff;
 
        /* loop through all sectors and return smallest sector size */
 
-       for (i = 0; i < bank->num_sectors; i++)
+       for (i = 0; i < (uint32_t)bank->num_sectors; i++)
        {
                if (bank->sectors[i].size < block_size)
                        block_size = bank->sectors[i].size;
@@ -1512,10 +1542,10 @@ static int compare_bank (const void * a, const void * b)
        b1=*((flash_bank_t **)a);
        b2=*((flash_bank_t **)b);
 
-       if (b1->base==b2->base)
+       if (b1->base == b2->base)
        {
                return 0;
-       } else if (b1->base>b2->base)
+       } else if (b1->base > b2->base)
        {
                return 1;
        } else
@@ -1536,10 +1566,10 @@ int gdb_query_packet(connection_t *connection, target_t *target, char *packet, i
                        char *cmd;
                        int i;
                        cmd = malloc((packet_size - 6)/2 + 1);
-                       for (i=0; i < (packet_size - 6)/2; i++)
+                       for (i = 0; i < (packet_size - 6)/2; i++)
                        {
-                               u32 tmp;
-                               sscanf(packet + 6 + 2*i, "%2x", &tmp);
+                               uint32_t tmp;
+                               sscanf(packet + 6 + 2*i, "%2" SCNx32 , &tmp);
                                cmd[i] = tmp;
                        }
                        cmd[(packet_size - 6)/2] = 0x0;
@@ -1547,7 +1577,11 @@ int gdb_query_packet(connection_t *connection, target_t *target, char *packet, i
                        /* We want to print all debug output to GDB connection */
                        log_add_callback(gdb_log_callback, connection);
                        target_call_timer_callbacks_now();
+                       /* some commands need to know the GDB connection, make note of current
+                        * GDB connection. */
+                       current_gdb_connection = gdb_connection;
                        command_run_line(cmd_ctx, cmd);
+                       current_gdb_connection = NULL;
                        target_call_timer_callbacks_now();
                        log_remove_callback(gdb_log_callback, connection);
                        free(cmd);
@@ -1562,9 +1596,9 @@ int gdb_query_packet(connection_t *connection, target_t *target, char *packet, i
                        int retval;
                        char gdb_reply[10];
                        char *separator;
-                       u32 checksum;
-                       u32 addr = 0;
-                       u32 len = 0;
+                       uint32_t checksum;
+                       uint32_t addr = 0;
+                       uint32_t len = 0;
 
                        /* skip command character */
                        packet += 5;
@@ -1583,7 +1617,7 @@ int gdb_query_packet(connection_t *connection, target_t *target, char *packet, i
 
                        if (retval == ERROR_OK)
                        {
-                               snprintf(gdb_reply, 10, "C%8.8x", checksum);
+                               snprintf(gdb_reply, 10, "C%8.8" PRIx32 "", checksum);
                                gdb_put_packet(connection, gdb_reply, 9);
                        }
                        else
@@ -1606,7 +1640,7 @@ int gdb_query_packet(connection_t *connection, target_t *target, char *packet, i
 
                xml_printf(&retval, &buffer, &pos, &size,
                                "PacketSize=%x;qXfer:memory-map:read%c;qXfer:features:read-;QStartNoAckMode+",
-                               (GDB_BUFFER_SIZE - 1), ((gdb_use_memory_map == 1)&&(flash_get_bank_count()>0)) ? '+' : '-');
+                               (GDB_BUFFER_SIZE - 1), ((gdb_use_memory_map == 1) && (flash_get_bank_count() > 0)) ? '+' : '-');
 
                if (retval != ERROR_OK)
                {
@@ -1619,7 +1653,7 @@ int gdb_query_packet(connection_t *connection, target_t *target, char *packet, i
 
                return ERROR_OK;
        }
-       else if (strstr(packet, "qXfer:memory-map:read::")&&(flash_get_bank_count()>0))
+       else if (strstr(packet, "qXfer:memory-map:read::") && (flash_get_bank_count() > 0))
        {
                /* We get away with only specifying flash here. Regions that are not
                 * specified are treated as if we provided no memory map(if not we
@@ -1651,10 +1685,10 @@ int gdb_query_packet(connection_t *connection, target_t *target, char *packet, i
                read/write) by default for GDB.
                GDB does not have a concept of non-cacheable read/write memory.
                 */
-               flash_bank_t **banks=malloc(sizeof(flash_bank_t *)*flash_get_bank_count());
+               flash_bank_t **banks = malloc(sizeof(flash_bank_t *)*flash_get_bank_count());
                int i;
 
-               for (i=0; i<flash_get_bank_count(); i++)
+               for (i = 0; i < flash_get_bank_count(); i++)
                {
                        p = get_flash_bank_by_num(i);
                        if (p == NULL)
@@ -1669,12 +1703,12 @@ int gdb_query_packet(connection_t *connection, target_t *target, char *packet, i
 
                qsort(banks, flash_get_bank_count(), sizeof(flash_bank_t *), compare_bank);
 
-               u32 ram_start=0;
-               for (i=0; i<flash_get_bank_count(); i++)
+               uint32_t ram_start = 0;
+               for (i = 0; i < flash_get_bank_count(); i++)
                {
                        p = banks[i];
 
-                       if (ram_start<p->base)
+                       if (ram_start < p->base)
                        {
                                xml_printf(&retval, &xml, &pos, &size, "<memory type=\"ram\" start=\"0x%x\" length=\"0x%x\"/>\n",
                                        ram_start, p->base-ram_start);
@@ -1688,9 +1722,9 @@ int gdb_query_packet(connection_t *connection, target_t *target, char *packet, i
                                "<property name=\"blocksize\">0x%x</property>\n" \
                                "</memory>\n", \
                                p->base, p->size, blocksize);
-                       ram_start=p->base+p->size;
+                       ram_start = p->base + p->size;
                }
-               if (ram_start!=0)
+               if (ram_start != 0)
                {
                        xml_printf(&retval, &xml, &pos, &size, "<memory type=\"ram\" start=\"0x%x\" length=\"0x%x\"/>\n",
                                ram_start, 0-ram_start);
@@ -1752,7 +1786,7 @@ int gdb_query_packet(connection_t *connection, target_t *target, char *packet, i
                }
 
                xml_printf(&retval, &xml, &pos, &size, \
-                       "l<target version=\"1.0\">\n<architecture>arm</architecture>\n</target>\n");
+                       "l < target version=\"1.0\">\n < architecture > arm</architecture>\n</target>\n");
 
                if (retval != ERROR_OK)
                {
@@ -1824,7 +1858,7 @@ int gdb_v_packet(connection_t *connection, target_t *target, char *packet, int p
 
                /* perform any target specific operations before the erase */
                target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_FLASH_ERASE_START);
-               result = flash_erase_address_range(gdb_service->target, addr, length );
+               result = flash_erase_address_range(gdb_service->target, addr, length);
                target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_FLASH_ERASE_END);
 
                /* perform erase */
@@ -1870,7 +1904,7 @@ int gdb_v_packet(connection_t *connection, target_t *target, char *packet, int p
                }
 
                /* create new section with content from packet buffer */
-               if((retval = image_add_section(gdb_connection->vflash_image, addr, length, 0x0, (u8*)parse)) != ERROR_OK)
+               if ((retval = image_add_section(gdb_connection->vflash_image, addr, length, 0x0, (uint8_t*)parse)) != ERROR_OK)
                {
                        return retval;
                }
@@ -1882,14 +1916,14 @@ int gdb_v_packet(connection_t *connection, target_t *target, char *packet, int p
 
        if (!strcmp(packet, "vFlashDone"))
        {
-               u32 written;
+               uint32_t written;
 
                /* process the flashing buffer. No need to erase as GDB
                 * always issues a vFlashErase first. */
                target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_FLASH_WRITE_START);
                result = flash_write(gdb_service->target, gdb_connection->vflash_image, &written, 0);
                target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_FLASH_WRITE_END);
-               if ( result != ERROR_OK)
+               if (result != ERROR_OK)
                {
                        if (result == ERROR_FLASH_DST_OUT_OF_BANK)
                                gdb_put_packet(connection, "E.memtype", 9);
@@ -1898,7 +1932,7 @@ int gdb_v_packet(connection_t *connection, target_t *target, char *packet, int p
                        }
                else
                {
-                       LOG_DEBUG("wrote %u bytes from vFlash image to flash", written);
+                       LOG_DEBUG("wrote %u bytes from vFlash image to flash", (unsigned)written);
                        gdb_put_packet(connection, "OK", 2);
                }
 
@@ -1915,32 +1949,14 @@ int gdb_v_packet(connection_t *connection, target_t *target, char *packet, int p
 
 int gdb_detach(connection_t *connection, target_t *target)
 {
+       gdb_service_t *gdb_service = connection->service->priv;
 
-       switch( detach_mode )
-       {
-               case GDB_DETACH_RESUME:
-                       target_handle_event( target, TARGET_EVENT_OLD_pre_resume );
-                       target_resume(target, 1, 0, 1, 0);
-                       break;
-
-               case GDB_DETACH_RESET:
-                       /* FIX?? make this configurable?? */
-                       target_process_reset(connection->cmd_ctx, RESET_HALT);
-                       break;
-
-               case GDB_DETACH_HALT:
-                       target_halt(target);
-                       break;
-
-               case GDB_DETACH_NOTHING:
-                       break;
-       }
+       target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_DETACH);
 
-       gdb_put_packet(connection, "OK", 2);
-       return ERROR_OK;
+       return gdb_put_packet(connection, "OK", 2);
 }
 
-static void gdb_log_callback(void *priv, const char *file, int line,
+static void gdb_log_callback(void *priv, const char *file, unsigned line,
                const char *function, const char *string)
 {
        connection_t *connection = priv;
@@ -1970,7 +1986,7 @@ int gdb_input_inner(connection_t *connection)
 {
        gdb_service_t *gdb_service = connection->service->priv;
        target_t *target = gdb_service->target;
-       char *packet=gdb_packet_buffer;
+       char *packet = gdb_packet_buffer;
        int packet_size;
        int retval;
        gdb_connection_t *gdb_con = connection->priv;
@@ -1988,18 +2004,18 @@ int gdb_input_inner(connection_t *connection)
                /* terminate with zero */
                packet[packet_size] = 0;
 
-               if( LOG_LEVEL_IS( LOG_LVL_DEBUG ) ){
-                       if( packet[0] == 'X' ){
+               if (LOG_LEVEL_IS(LOG_LVL_DEBUG)) {
+                       if (packet[0] == 'X') {
                                // binary packets spew junk into the debug log stream
                                char buf[ 50 ];
                                int x;
-                               for( x = 0 ; (x < 49) && (packet[x] != ':') ; x++ ){
+                               for (x = 0 ; (x < 49) && (packet[x] != ':') ; x++) {
                                        buf[x] = packet[x];
                                }
                                buf[x] = 0;
-                               LOG_DEBUG("received packet: '%s:<binary-data>'", buf );
+                               LOG_DEBUG("received packet: '%s:<binary-data>'", buf);
                        } else {
-                               LOG_DEBUG("received packet: '%s'", packet );
+                               LOG_DEBUG("received packet: '%s'", packet);
                        }
                }
 
@@ -2045,23 +2061,55 @@ int gdb_input_inner(connection_t *connection)
                                case 'c':
                                case 's':
                                        {
-                                               if (target->state != TARGET_HALTED)
+                                               int retval = ERROR_OK;
+
+                                               gdb_connection_t *gdb_con = connection->priv;
+                                               log_add_callback(gdb_log_callback, connection);
+
+                                               bool nostep = false;
+                                               if (target->state == TARGET_RUNNING)
+                                               {
+                                                       LOG_WARNING("The target is already running. Halt target before stepi/continue.");
+                                                       retval = target_halt(target);
+                                                       if (retval == ERROR_OK)
+                                                               retval = target_wait_state(target, TARGET_HALTED, 100);
+                                               } else if (target->state != TARGET_HALTED)
+                                               {
+                                                       LOG_WARNING("The target is not in the halted nor running stated, stepi/continue ignored.");
+                                                       nostep = true;
+                                               } else if ((packet[0] == 's') && gdb_con->sync)
                                                {
-                                                       /* If the target isn't in the halted state, then we can't
+                                                       /* Hmm..... when you issue a continue in GDB, then a "stepi" is
+                                                        * sent by GDB first to OpenOCD, thus defeating the check to
+                                                        * make only the single stepping have the sync feature...
+                                                        */
+                                                       nostep = true;
+                                                       LOG_WARNING("stepi ignored. GDB will now fetch the register state from the target.");
+                                               }
+                                               gdb_con->sync = false;
+
+                                               if ((retval!=ERROR_OK) || nostep)
+                                               {
+                                                       /* Either the target isn't in the halted state, then we can't
                                                         * step/continue. This might be early setup, etc.
+                                                        *
+                                                        * Or we want to allow GDB to pick up a fresh set of
+                                                        * register values without modifying the target state.
+                                                        *
                                                         */
                                                        gdb_sig_halted(connection);
+
+                                                       /* stop forwarding log packets! */
+                                                       log_remove_callback(gdb_log_callback, connection);
                                                } else
                                                {
                                                        /* We're running/stepping, in which case we can
                                                         * forward log output until the target is halted
                                                         */
-                                                       gdb_connection_t *gdb_con = connection->priv;
                                                        gdb_con->frontend_state = TARGET_RUNNING;
-                                                       log_add_callback(gdb_log_callback, connection);
                                                        target_call_event_callbacks(target, TARGET_EVENT_GDB_START);
-                                                       int retval=gdb_step_continue_packet(connection, target, packet, packet_size);
-                                                       if (retval!=ERROR_OK)
+                                                       int retval = gdb_step_continue_packet(connection, target, packet, packet_size);
+                                                       if (retval != ERROR_OK)
                                                        {
                                                                /* we'll never receive a halted condition... issue a false one.. */
                                                                gdb_frontend_halted(target, connection);
@@ -2094,7 +2142,9 @@ int gdb_input_inner(connection_t *connection)
                                        /* handle extended restart packet */
                                        breakpoint_clear_target(gdb_service->target);
                                        watchpoint_clear_target(gdb_service->target);
-                                       command_run_linef(connection->cmd_ctx, "ocd_gdb_restart %d", get_num_by_target(target));
+                                       command_run_linef(connection->cmd_ctx,
+                                                       "ocd_gdb_restart %s",
+                                                       target->cmd_name);
                                        break;
                                default:
                                        /* ignore unkown packets */
@@ -2112,8 +2162,16 @@ int gdb_input_inner(connection_t *connection)
                {
                        if (target->state == TARGET_RUNNING)
                        {
-                               target_halt(target);
+                               retval = target_halt(target);
+                               if (retval != ERROR_OK)
+                               {
+                                       target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT);
+                               }
                                gdb_con->ctrl_c = 0;
+                       } else
+                       {
+                               LOG_INFO("The target is not running when halt was requested, stopping GDB.");
+                               target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT);
                        }
                }
 
@@ -2129,7 +2187,7 @@ int gdb_input(connection_t *connection)
        if (retval == ERROR_SERVER_REMOTE_CLOSED)
                return retval;
 
-       /* logging does not propagate the error, yet can set th gdb_con->closed flag */
+       /* logging does not propagate the error, yet can set the gdb_con->closed flag */
        if (gdb_con->closed)
                return ERROR_SERVER_REMOTE_CLOSED;
 
@@ -2148,85 +2206,75 @@ int gdb_init(void)
                return ERROR_OK;
        }
 
-       if (gdb_port == 0)
+       if (gdb_port == 0 && server_use_pipes == 0)
        {
-               LOG_WARNING("no gdb port specified, using default port 3333");
-               gdb_port = 3333;
+               LOG_INFO("gdb port disabled");
+               return ERROR_OK;
        }
 
-       while (target)
+       if (server_use_pipes)
        {
-               char service_name[8];
-
-               snprintf(service_name, 8, "gdb-%2.2i", target->target_number);
+               /* only a single gdb connection when using a pipe */
 
                gdb_service = malloc(sizeof(gdb_service_t));
                gdb_service->target = target;
 
-               add_service("gdb", CONNECTION_GDB,
-                           gdb_port + target->target_number,
-                           1, gdb_new_connection, gdb_input,
-                           gdb_connection_closed,
-                           gdb_service);
+               add_service("gdb", CONNECTION_PIPE, 0, 1, gdb_new_connection, gdb_input, gdb_connection_closed, gdb_service);
 
-               LOG_DEBUG("gdb service for target %s at port %i",
-                         target->type->name,
-                         gdb_port + target->target_number);
+               LOG_DEBUG("gdb service for target %s using pipes",
+                               target_get_name(target));
+       }
+       else
+       {
+               unsigned short port = gdb_port;
 
-               target = target->next;
+               while (target)
+               {
+                       gdb_service = malloc(sizeof(gdb_service_t));
+                       gdb_service->target = target;
+
+                       add_service("gdb", CONNECTION_TCP,
+                                       port, 1,
+                                       gdb_new_connection, gdb_input,
+                                       gdb_connection_closed, gdb_service);
+
+                       LOG_DEBUG("gdb service for target %s at TCP port %i",
+                                       target_get_name(target),
+                                       port);
+                       target = target->next;
+                       port++;
+               }
        }
 
        return ERROR_OK;
 }
 
-/* daemon configuration command gdb_port */
-int handle_gdb_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+COMMAND_HANDLER(handle_gdb_sync_command)
 {
-       if (argc == 0)
+       if (argc != 0)
        {
-               command_print(cmd_ctx, "%d", gdb_port);
-               return ERROR_OK;
+               return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
-       /* only if the port wasn't overwritten by cmdline */
-       if (gdb_port == 0)
-               gdb_port = strtoul(args[0], NULL, 0);
+       if (current_gdb_connection == NULL)
+       {
+               command_print(cmd_ctx,
+                               "gdb_sync command can only be run from within gdb using \"monitor gdb_sync\"");
+               return ERROR_FAIL;
+       }
+
+       current_gdb_connection->sync = true;
 
        return ERROR_OK;
 }
 
-int handle_gdb_detach_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+/* daemon configuration command gdb_port */
+COMMAND_HANDLER(handle_gdb_port_command)
 {
-       if (argc == 1)
-       {
-               if (strcmp(args[0], "resume") == 0)
-               {
-                       detach_mode = GDB_DETACH_RESUME;
-                       return ERROR_OK;
-               }
-               else if (strcmp(args[0], "reset") == 0)
-               {
-                       detach_mode = GDB_DETACH_RESET;
-                       return ERROR_OK;
-               }
-               else if (strcmp(args[0], "halt") == 0)
-               {
-                       detach_mode = GDB_DETACH_HALT;
-                       return ERROR_OK;
-               }
-               else if (strcmp(args[0], "nothing") == 0)
-               {
-                       detach_mode = GDB_DETACH_NOTHING;
-                       return ERROR_OK;
-               }
-               else
-                       LOG_WARNING("invalid gdb_detach configuration directive: %s", args[0]);
-       }
-
-       return ERROR_COMMAND_SYNTAX_ERROR;
+       return server_port_command(cmd_ctx, cmd, args, argc, &gdb_port);
 }
 
-int handle_gdb_memory_map_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+COMMAND_HANDLER(handle_gdb_memory_map_command)
 {
        if (argc == 1)
        {
@@ -2247,7 +2295,7 @@ int handle_gdb_memory_map_command(struct command_context_s *cmd_ctx, char *cmd,
        return ERROR_COMMAND_SYNTAX_ERROR;
 }
 
-int handle_gdb_flash_program_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+COMMAND_HANDLER(handle_gdb_flash_program_command)
 {
        if (argc == 1)
        {
@@ -2268,7 +2316,7 @@ int handle_gdb_flash_program_command(struct command_context_s *cmd_ctx, char *cm
        return ERROR_COMMAND_SYNTAX_ERROR;
 }
 
-int handle_gdb_report_data_abort_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+COMMAND_HANDLER(handle_gdb_report_data_abort_command)
 {
        if (argc == 1)
        {
@@ -2290,20 +2338,20 @@ int handle_gdb_report_data_abort_command(struct command_context_s *cmd_ctx, char
 }
 
 /* gdb_breakpoint_override */
-int handle_gdb_breakpoint_override_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+COMMAND_HANDLER(handle_gdb_breakpoint_override_command)
 {
        if (argc == 0)
        {
 
-       } else if (argc==1)
+       } else if (argc == 1)
        {
                gdb_breakpoint_override = 1;
-               if (strcmp(args[0], "hard")==0)
+               if (strcmp(args[0], "hard") == 0)
                {
-                       gdb_breakpoint_override_type=BKPT_HARD;
-               } else if (strcmp(args[0], "soft")==0)
+                       gdb_breakpoint_override_type = BKPT_HARD;
+               } else if (strcmp(args[0], "soft") == 0)
                {
-                       gdb_breakpoint_override_type=BKPT_SOFT;
+                       gdb_breakpoint_override_type = BKPT_SOFT;
                } else if (strcmp(args[0], "disable") == 0)
                {
                        gdb_breakpoint_override = 0;
@@ -2314,7 +2362,7 @@ int handle_gdb_breakpoint_override_command(struct command_context_s *cmd_ctx, ch
        }
        if (gdb_breakpoint_override)
        {
-               LOG_USER("force %s breakpoints", (gdb_breakpoint_override_type==BKPT_HARD)?"hard":"soft");
+               LOG_USER("force %s breakpoints", (gdb_breakpoint_override_type == BKPT_HARD)?"hard":"soft");
        } else
        {
                LOG_USER("breakpoint type is not overriden");
@@ -2323,23 +2371,27 @@ int handle_gdb_breakpoint_override_command(struct command_context_s *cmd_ctx, ch
        return ERROR_OK;
 }
 
-
 int gdb_register_commands(command_context_t *command_context)
 {
-       register_command(command_context, NULL, "gdb_port", handle_gdb_port_command,
-                       COMMAND_CONFIG, "daemon configuration command gdb_port");
-       register_command(command_context, NULL, "gdb_detach", handle_gdb_detach_command,
-                       COMMAND_CONFIG, "");
-       register_command(command_context, NULL, "gdb_memory_map", handle_gdb_memory_map_command,
-                       COMMAND_CONFIG, "enable or disable memory map");
-       register_command(command_context, NULL, "gdb_flash_program", handle_gdb_flash_program_command,
-                       COMMAND_CONFIG, "enable or disable flash program");
-       register_command(command_context, NULL, "gdb_report_data_abort", handle_gdb_report_data_abort_command,
-                       COMMAND_CONFIG, "enable or disable report data");
-       register_command(command_context, NULL, "gdb_breakpoint_override", handle_gdb_breakpoint_override_command,
-                       COMMAND_EXEC, "hard/soft/disabled - force breakpoint type for gdb 'break' commands."
-                       "The raison d'etre for this option is to support GDB GUI's without "
-                       "a hard/soft breakpoint concept where the default OpenOCD behaviour "
-                       "is not sufficient");
+       register_command(command_context, NULL, "gdb_sync",
+                       handle_gdb_sync_command, COMMAND_ANY,
+                       "next stepi will return immediately allowing GDB to "
+                       "fetch register state without affecting target state");
+       register_command(command_context, NULL, "gdb_port",
+                       handle_gdb_port_command, COMMAND_ANY,
+                       "daemon configuration command gdb_port");
+       register_command(command_context, NULL, "gdb_memory_map",
+                       handle_gdb_memory_map_command, COMMAND_CONFIG,
+                       "enable or disable memory map");
+       register_command(command_context, NULL, "gdb_flash_program",
+                       handle_gdb_flash_program_command, COMMAND_CONFIG,
+                       "enable or disable flash program");
+       register_command(command_context, NULL, "gdb_report_data_abort",
+                       handle_gdb_report_data_abort_command, COMMAND_CONFIG,
+                       "enable or disable reporting data aborts");
+       register_command(command_context, NULL, "gdb_breakpoint_override",
+                       handle_gdb_breakpoint_override_command, COMMAND_EXEC,
+                       "hard/soft/disable - force type of breakpoint "
+                       "used by gdb 'break' commands.");
        return ERROR_OK;
 }

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)