Transform 'u8' to 'uint8_t'
[openocd.git] / src / server / gdb_server.c
index febad6e2f5e4f8f2a0aaf8122e3b9e70f1ba5735..3a7f7881659b7fe7b8cd13d0d8e2ec722e487b4e 100644 (file)
 #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_
@@ -54,7 +44,7 @@ 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,
@@ -71,6 +61,10 @@ enum gdb_detach_mode
 /* 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 */
 /* enabled by default*/
@@ -126,7 +120,7 @@ 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
@@ -169,10 +163,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;
@@ -269,9 +271,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;
@@ -307,7 +320,7 @@ int gdb_put_packet_inner(connection_t *connection, char *buffer, int len)
                if ((retval = gdb_get_char(connection, &reply)) != ERROR_OK)
                        return retval;
                if( reply == '$' ){
-                       // fix a problem with some IAR tools
+                       /* fix a problem with some IAR tools */
                        gdb_putback_char( connection, reply );
                        LOG_DEBUG("Unexpected start of new packet");
                        break;
@@ -329,7 +342,7 @@ 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++);
@@ -581,7 +594,7 @@ 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
                 */
@@ -719,7 +732,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));
@@ -789,6 +801,9 @@ 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 );
+
+       gdb_actual_connections++;
+
        return ERROR_OK;
 }
 
@@ -797,6 +812,8 @@ int gdb_connection_closed(connection_t *connection)
        gdb_service_t *gdb_service = connection->service->priv;
        gdb_connection_t *gdb_connection = connection->priv;
 
+       gdb_actual_connections--;
+
        /* see if an image built with vFlash commands is left */
        if (gdb_connection->vflash_image)
        {
@@ -827,7 +844,7 @@ int gdb_connection_closed(connection_t *connection)
        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 );
@@ -847,40 +864,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);
        }
 
+       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 +947,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 +1005,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 +1013,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 +1031,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 +1057,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 +1083,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 +1092,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 +1110,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 */
+
+       gdb_target_to_reg(target, separator + 1, chars, bin_buf);
 
-       /* get register arch_type, and call set method */
+               /* 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;
@@ -1119,7 +1166,7 @@ int gdb_read_memory_packet(connection_t *connection, target_t *target, char *pac
        u32 addr = 0;
        u32 len = 0;
 
-       u8 *buffer;
+       uint8_t *buffer;
        char *hex_buffer;
 
        int retval = ERROR_OK;
@@ -1165,10 +1212,10 @@ int gdb_read_memory_packet(connection_t *connection, target_t *target, char *pac
        {
                hex_buffer = malloc(len * 2 + 1);
 
-               int i;
+               u32 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];
                }
@@ -1193,9 +1240,9 @@ int gdb_write_memory_packet(connection_t *connection, target_t *target, char *pa
        u32 addr = 0;
        u32 len = 0;
 
-       u8 *buffer;
+       uint8_t *buffer;
 
-       int i;
+       u32 i;
        int retval;
 
        /* skip command character */
@@ -1276,7 +1323,7 @@ int gdb_write_memory_binary_packet(connection_t *connection, target_t *target, c
        {
                LOG_DEBUG("addr: 0x%8.8x, len: 0x%8.8x", 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)
@@ -1319,7 +1366,8 @@ int gdb_step_continue_packet(connection_t *connection, target_t *target, char *p
        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;
 }
@@ -1492,12 +1540,12 @@ static int decode_xfer_read(char *buf, char **annex, int *ofs, unsigned int *len
 
 int gdb_calc_blocksize(flash_bank_t *bank)
 {
-       int i;
-       int block_size = 0xffffffff;
+       u32 i;
+       u32 block_size = 0xffffffff;
 
        /* loop through all sectors and return smallest sector size */
 
-       for (i = 0; i < bank->num_sectors; i++)
+       for (i = 0; i < (u32)bank->num_sectors; i++)
        {
                if (bank->sectors[i].size < block_size)
                        block_size = bank->sectors[i].size;
@@ -1870,7 +1918,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;
                }
@@ -2129,7 +2177,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,32 +2196,38 @@ 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 using pipes",
+                               target_get_name(target));
+       }
+       else
+       {
+               while (target)
+               {
+                       gdb_service = malloc(sizeof(gdb_service_t));
+                       gdb_service->target = target;
 
-               LOG_DEBUG("gdb service for target %s at port %i",
-                         target->type->name,
-                         gdb_port + target->target_number);
+                       add_service("gdb", CONNECTION_TCP, gdb_port + target->target_number, 1, gdb_new_connection, gdb_input, gdb_connection_closed, gdb_service);
 
-               target = target->next;
+                       LOG_DEBUG("gdb service for target %s at port %i",
+                                       target_get_name(target),
+                                       gdb_port + target->target_number);
+                       target = target->next;
+               }
        }
 
        return ERROR_OK;
@@ -2184,7 +2238,7 @@ int handle_gdb_port_command(struct command_context_s *cmd_ctx, char *cmd, char *
 {
        if (argc == 0)
        {
-               command_print(cmd_ctx, "gdb_port: %ld", gdb_port);
+               command_print(cmd_ctx, "%d", gdb_port);
                return ERROR_OK;
        }
 
@@ -2323,23 +2377,20 @@ 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");
+                       COMMAND_ANY, "daemon configuration command gdb_port");
        register_command(command_context, NULL, "gdb_detach", handle_gdb_detach_command,
-                       COMMAND_CONFIG, "");
+                       COMMAND_CONFIG, "resume/reset/halt/nothing - "
+                       "specify behavior when GDB detaches from the target");
        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");
+                       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/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");
+                       COMMAND_EXEC, "hard/soft/disable - force breakpoint type for 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)