Merge pull request #101 from prattmic/master
[fw/stlink] / gdbserver / gdb-server.c
index f6ec15bf5fde4913c1bbec49728bbc77ff5bc4eb..ae06952bf83041f633803a7fd01a0b2393c511a4 100644 (file)
 #include <stdlib.h>
 #include <unistd.h>
 #include <sys/types.h>
+#ifdef __MINGW32__
+#include "mingw.h"
+#else
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <signal.h>
+#endif
 
 #include <stlink-common.h>
 
@@ -159,15 +163,27 @@ int main(int argc, char** argv) {
                if(sl == NULL) return 1;
                break;
     }
-    
+
        printf("Chip ID is %08x, Core ID is  %08x.\n", sl->chip_id, sl->core_id);
 
        sl->verbose=0;
 
        current_memory_map = make_memory_map(sl);
 
+#ifdef __MINGW32__
+       WSADATA wsadata;
+       if (WSAStartup(MAKEWORD(2,2),&wsadata) !=0 ) {
+               goto winsock_error;
+       }
+#endif
+
        while(serve(sl, state.listen_port) == 0);
 
+#ifdef __MINGW32__
+winsock_error:
+       WSACleanup();
+#endif
+
        /* Switch back to mass storage mode before closing. */
        stlink_run(sl);
        stlink_exit_debug_mode(sl);
@@ -176,6 +192,71 @@ int main(int argc, char** argv) {
        return 0;
 }
 
+static const char* const target_description_F4 =
+    "<?xml version=\"1.0\"?>"
+    "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">"
+    "<target version=\"1.0\">"
+    "   <architecture>arm</architecture>"
+    "   <feature name=\"org.gnu.gdb.arm.m-profile\">"
+    "       <reg name=\"r0\" bitsize=\"32\"/>"
+    "       <reg name=\"r1\" bitsize=\"32\"/>"
+    "       <reg name=\"r2\" bitsize=\"32\"/>"
+    "       <reg name=\"r3\" bitsize=\"32\"/>"
+    "       <reg name=\"r4\" bitsize=\"32\"/>"
+    "       <reg name=\"r5\" bitsize=\"32\"/>"
+    "       <reg name=\"r6\" bitsize=\"32\"/>"
+    "       <reg name=\"r7\" bitsize=\"32\"/>"
+    "       <reg name=\"r8\" bitsize=\"32\"/>"
+    "       <reg name=\"r9\" bitsize=\"32\"/>"
+    "       <reg name=\"r10\" bitsize=\"32\"/>"
+    "       <reg name=\"r11\" bitsize=\"32\"/>"
+    "       <reg name=\"r12\" bitsize=\"32\"/>"
+    "       <reg name=\"sp\" bitsize=\"32\" type=\"data_ptr\"/>"
+    "       <reg name=\"lr\" bitsize=\"32\"/>"
+    "       <reg name=\"pc\" bitsize=\"32\" type=\"code_ptr\"/>"
+    "       <reg name=\"xpsr\" bitsize=\"32\" regnum=\"25\"/>"
+    "       <reg name=\"msp\" bitsize=\"32\" regnum=\"26\" type=\"data_ptr\" group=\"general\" />"
+    "       <reg name=\"psp\" bitsize=\"32\" regnum=\"27\" type=\"data_ptr\" group=\"general\" />"
+    "       <reg name=\"control\" bitsize=\"8\" regnum=\"28\" type=\"int\" group=\"general\" />"
+    "       <reg name=\"faultmask\" bitsize=\"8\" regnum=\"29\" type=\"int\" group=\"general\" />"
+    "       <reg name=\"basepri\" bitsize=\"8\" regnum=\"30\" type=\"int\" group=\"general\" />"
+    "       <reg name=\"primask\" bitsize=\"8\" regnum=\"31\" type=\"int\" group=\"general\" />"
+    "       <reg name=\"s0\" bitsize=\"32\" regnum=\"32\" type=\"float\" group=\"float\" />"
+    "       <reg name=\"s1\" bitsize=\"32\" type=\"float\" group=\"float\" />"
+    "       <reg name=\"s2\" bitsize=\"32\" type=\"float\" group=\"float\" />"
+    "       <reg name=\"s3\" bitsize=\"32\" type=\"float\" group=\"float\" />"
+    "       <reg name=\"s4\" bitsize=\"32\" type=\"float\" group=\"float\" />"
+    "       <reg name=\"s5\" bitsize=\"32\" type=\"float\" group=\"float\" />"
+    "       <reg name=\"s6\" bitsize=\"32\" type=\"float\" group=\"float\" />"
+    "       <reg name=\"s7\" bitsize=\"32\" type=\"float\" group=\"float\" />"
+    "       <reg name=\"s8\" bitsize=\"32\" type=\"float\" group=\"float\" />"
+    "       <reg name=\"s9\" bitsize=\"32\" type=\"float\" group=\"float\" />"
+    "       <reg name=\"s10\" bitsize=\"32\" type=\"float\" group=\"float\" />"
+    "       <reg name=\"s11\" bitsize=\"32\" type=\"float\" group=\"float\" />"
+    "       <reg name=\"s12\" bitsize=\"32\" type=\"float\" group=\"float\" />"
+    "       <reg name=\"s13\" bitsize=\"32\" type=\"float\" group=\"float\" />"
+    "       <reg name=\"s14\" bitsize=\"32\" type=\"float\" group=\"float\" />"
+    "       <reg name=\"s15\" bitsize=\"32\" type=\"float\" group=\"float\" />"
+    "       <reg name=\"s16\" bitsize=\"32\" type=\"float\" group=\"float\" />"
+    "       <reg name=\"s17\" bitsize=\"32\" type=\"float\" group=\"float\" />"
+    "       <reg name=\"s18\" bitsize=\"32\" type=\"float\" group=\"float\" />"
+    "       <reg name=\"s19\" bitsize=\"32\" type=\"float\" group=\"float\" />"
+    "       <reg name=\"s20\" bitsize=\"32\" type=\"float\" group=\"float\" />"
+    "       <reg name=\"s21\" bitsize=\"32\" type=\"float\" group=\"float\" />"
+    "       <reg name=\"s22\" bitsize=\"32\" type=\"float\" group=\"float\" />"
+    "       <reg name=\"s23\" bitsize=\"32\" type=\"float\" group=\"float\" />"
+    "       <reg name=\"s24\" bitsize=\"32\" type=\"float\" group=\"float\" />"
+    "       <reg name=\"s25\" bitsize=\"32\" type=\"float\" group=\"float\" />"
+    "       <reg name=\"s26\" bitsize=\"32\" type=\"float\" group=\"float\" />"
+    "       <reg name=\"s27\" bitsize=\"32\" type=\"float\" group=\"float\" />"
+    "       <reg name=\"s28\" bitsize=\"32\" type=\"float\" group=\"float\" />"
+    "       <reg name=\"s29\" bitsize=\"32\" type=\"float\" group=\"float\" />"
+    "       <reg name=\"s30\" bitsize=\"32\" type=\"float\" group=\"float\" />"
+    "       <reg name=\"s31\" bitsize=\"32\" type=\"float\" group=\"float\" />"
+    "       <reg name=\"fpscr\" bitsize=\"32\" type=\"int\" group=\"float\" />"
+    "   </feature>"
+    "</target>";
+
 static const char* const memory_map_template_F4 =
   "<?xml version=\"1.0\"?>"
   "<!DOCTYPE memory-map PUBLIC \"+//IDN gnu.org//DTD GDB Memory Map V1.0//EN\""
@@ -204,15 +285,15 @@ static const char* const memory_map_template =
   "<!DOCTYPE memory-map PUBLIC \"+//IDN gnu.org//DTD GDB Memory Map V1.0//EN\""
   "     \"http://sourceware.org/gdb/gdb-memory-map.dtd\">"
   "<memory-map>"
-  "  <memory type=\"rom\" start=\"0x00000000\" length=\"0x%x\"/>"       // code = sram, bootrom or flash; flash is bigger
-  "  <memory type=\"ram\" start=\"0x20000000\" length=\"0x%x\"/>"       // sram 8k
-  "  <memory type=\"flash\" start=\"0x08000000\" length=\"0x%x\">"
-  "    <property name=\"blocksize\">0x%x</property>"
+  "  <memory type=\"rom\" start=\"0x00000000\" length=\"0x%zx\"/>"       // code = sram, bootrom or flash; flash is bigger
+  "  <memory type=\"ram\" start=\"0x20000000\" length=\"0x%zx\"/>"       // sram 8k
+  "  <memory type=\"flash\" start=\"0x08000000\" length=\"0x%zx\">"
+  "    <property name=\"blocksize\">0x%zx</property>"
   "  </memory>"
   "  <memory type=\"ram\" start=\"0x40000000\" length=\"0x1fffffff\"/>" // peripheral regs
   "  <memory type=\"ram\" start=\"0xe0000000\" length=\"0x1fffffff\"/>" // cortex regs
-  "  <memory type=\"rom\" start=\"0x%08x\" length=\"0x%x\"/>"           // bootrom
-  "  <memory type=\"rom\" start=\"0x1ffff800\" length=\"0x8\"/>"        // option byte area
+  "  <memory type=\"rom\" start=\"0x%08x\" length=\"0x%zx\"/>"           // bootrom
+  "  <memory type=\"rom\" start=\"0x1ffff800\" length=\"0x10\"/>"        // option byte area
   "</memory-map>";
 
 char* make_memory_map(stlink_t *sl) {
@@ -233,7 +314,7 @@ char* make_memory_map(stlink_t *sl) {
 }
 
 
-/* 
+/*
  * DWT_COMP0     0xE0001020
  * DWT_MASK0     0xE0001024
  * DWT_FUNCTION0 0xE0001028
@@ -266,7 +347,7 @@ static void init_data_watchpoints(stlink_t *sl) {
        #endif
 
        // set trcena in debug command to turn on dwt unit
-       stlink_write_debug32(sl, 0xE000EDFC, 
+       stlink_write_debug32(sl, 0xE000EDFC,
                             stlink_read_debug32(sl, 0xE000EDFC) | (1<<24));
 
        // make sure all watchpoints are cleared
@@ -292,7 +373,7 @@ static int add_data_watchpoint(stlink_t *sl, enum watchfun wf, stm32_addr_t addr
                mask++;
        }
 
-       if((mask != -1) && (mask < 16)) {
+       if((mask != (uint32_t)-1) && (mask < 16)) {
                for(i = 0; i < DATA_WATCH_NUM; i++) {
                        // is this an empty slot ?
                        if(data_watches[i].fun == WATCHDISABLED) {
@@ -462,7 +543,7 @@ static int flash_add_block(stm32_addr_t addr, unsigned length, stlink_t *sl) {
 }
 
 static int flash_populate(stm32_addr_t addr, uint8_t* data, unsigned length) {
-       int fit_blocks = 0, fit_length = 0;
+       unsigned int fit_blocks = 0, fit_length = 0;
 
        for(struct flash_block* fb = flash_root; fb; fb = fb->next) {
                /* Block: ------X------Y--------
@@ -552,9 +633,10 @@ int serve(stlink_t *sl, int port) {
        }
 
        unsigned int val = 1;
-       setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
+       setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));
 
-       struct sockaddr_in serv_addr = {0};
+       struct sockaddr_in serv_addr;
+       memset(&serv_addr,0,sizeof(struct sockaddr_in));
        serv_addr.sin_family = AF_INET;
        serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
        serv_addr.sin_port = htons(port);
@@ -577,7 +659,7 @@ int serve(stlink_t *sl, int port) {
        printf("Listening at *:%d...\n", port);
 
        int client = accept(sock, NULL, NULL);
-       signal (SIGINT, SIG_DFL);
+       //signal (SIGINT, SIG_DFL);
        if(client < 0) {
                perror("accept");
                return 1;
@@ -632,19 +714,24 @@ int serve(stlink_t *sl, int port) {
                        #endif
 
                        if(!strcmp(queryName, "Supported")) {
-                               reply = strdup("PacketSize=3fff;qXfer:memory-map:read+");
+                if(sl->chip_id==STM32_CHIPID_F4) {
+                    reply = strdup("PacketSize=3fff;qXfer:memory-map:read+;qXfer:features:read+");
+                }
+                else {
+                    reply = strdup("PacketSize=3fff;qXfer:memory-map:read+");
+                }
                        } else if(!strcmp(queryName, "Xfer")) {
-                               char *type, *op, *s_addr, *s_length;
+                               char *type, *op, *__s_addr, *s_length;
                                char *tok = params;
                                char *annex __attribute__((unused));
 
                                type     = strsep(&tok, ":");
                                op       = strsep(&tok, ":");
                                annex    = strsep(&tok, ":");
-                               s_addr   = strsep(&tok, ",");
+                               __s_addr   = strsep(&tok, ",");
                                s_length = tok;
 
-                               unsigned addr = strtoul(s_addr, NULL, 16),
+                               unsigned addr = strtoul(__s_addr, NULL, 16),
                                       length = strtoul(s_length, NULL, 16);
 
                                #ifdef DEBUG
@@ -657,6 +744,9 @@ int serve(stlink_t *sl, int port) {
                                if(!strcmp(type, "memory-map") && !strcmp(op, "read"))
                                        data = current_memory_map;
 
+                               if(!strcmp(type, "features") && !strcmp(op, "read"))
+                                       data = target_description_F4;
+
                                if(data) {
                                        unsigned data_length = strlen(data);
                                        if(addr + length > data_length)
@@ -678,31 +768,31 @@ int serve(stlink_t *sl, int port) {
                                } else {
                                        params = separator + 1;
                                }
-                               
 
-                               if (!strncmp(params,"7265",4)) {// resume
+
+                               if (!strncmp(params,"726573756d65",12)) {// resume
 #ifdef DEBUG
                                        printf("Rcmd: resume\n");
 #endif
                                        stlink_run(sl);
 
                                        reply = strdup("OK");
-                               } else if (!strncmp(params,"6861",4)) { //half
+                } else if (!strncmp(params,"68616c74",8)) { //halt
                                        reply = strdup("OK");
-                                       
+
                                        stlink_force_debug(sl);
 
 #ifdef DEBUG
                                        printf("Rcmd: halt\n");
 #endif
-                               } else if (!strncmp(params,"7265",4)) { //reset
+                } else if (!strncmp(params,"7265736574",10)) { //reset
                                        reply = strdup("OK");
-                                       
+
                                        stlink_force_debug(sl);
                                        stlink_reset(sl);
                                        init_code_breakpoints(sl);
                                        init_data_watchpoints(sl);
-                                       
+
 #ifdef DEBUG
                                        printf("Rcmd: reset\n");
 #endif
@@ -712,7 +802,7 @@ int serve(stlink_t *sl, int port) {
 #endif
 
                                }
-                               
+
                        }
 
                        if(reply == NULL)
@@ -730,13 +820,13 @@ int serve(stlink_t *sl, int port) {
                        cmdName++; // vCommand -> Command
 
                        if(!strcmp(cmdName, "FlashErase")) {
-                               char *s_addr, *s_length;
+                               char *__s_addr, *s_length;
                                char *tok = params;
 
-                               s_addr   = strsep(&tok, ",");
+                               __s_addr   = strsep(&tok, ",");
                                s_length = tok;
 
-                               unsigned addr = strtoul(s_addr, NULL, 16),
+                               unsigned addr = strtoul(__s_addr, NULL, 16),
                                       length = strtoul(s_length, NULL, 16);
 
                                #ifdef DEBUG
@@ -750,13 +840,13 @@ int serve(stlink_t *sl, int port) {
                                        reply = strdup("OK");
                                }
                        } else if(!strcmp(cmdName, "FlashWrite")) {
-                               char *s_addr, *data;
+                               char *__s_addr, *data;
                                char *tok = params;
 
-                               s_addr = strsep(&tok, ":");
+                               __s_addr = strsep(&tok, ":");
                                data   = tok;
 
-                               unsigned addr = strtoul(s_addr, NULL, 16);
+                               unsigned addr = strtoul(__s_addr, NULL, 16);
                                unsigned data_length = status - (data - packet);
 
                                // Length of decoded data cannot be more than
@@ -764,7 +854,7 @@ int serve(stlink_t *sl, int port) {
                                // Additional byte is reserved for alignment fix.
                                uint8_t *decoded = calloc(data_length + 1, 1);
                                unsigned dec_index = 0;
-                               for(int i = 0; i < data_length; i++) {
+                               for(unsigned int i = 0; i < data_length; i++) {
                                        if(data[i] == 0x7d) {
                                                i++;
                                                decoded[dec_index++] = data[i] ^ 0x20;
@@ -864,6 +954,30 @@ int serve(stlink_t *sl, int port) {
                        } else if(id == 0x19) {
                                stlink_read_reg(sl, 16, &regp);
                                myreg = htonl(regp.xpsr);
+                       } else if(id == 0x1A) {
+                               stlink_read_reg(sl, 17, &regp);
+                               myreg = htonl(regp.main_sp);
+                       } else if(id == 0x1B) {
+                               stlink_read_reg(sl, 18, &regp);
+                               myreg = htonl(regp.process_sp);
+                       } else if(id == 0x1C) {
+                               stlink_read_unsupported_reg(sl, id, &regp);
+                               myreg = htonl(regp.control);
+                       } else if(id == 0x1D) {
+                               stlink_read_unsupported_reg(sl, id, &regp);
+                               myreg = htonl(regp.faultmask);
+                       } else if(id == 0x1E) {
+                               stlink_read_unsupported_reg(sl, id, &regp);
+                               myreg = htonl(regp.basepri);
+                       } else if(id == 0x1F) {
+                               stlink_read_unsupported_reg(sl, id, &regp);
+                               myreg = htonl(regp.primask);
+            } else if(id >= 0x20 && id < 0x40) {
+                stlink_read_unsupported_reg(sl, id, &regp);
+                myreg = htonl(regp.s[id-0x20]);
+                       } else if(id == 0x40) {
+                stlink_read_unsupported_reg(sl, id, &regp);
+                myreg = htonl(regp.fpscr);
                        } else {
                                reply = strdup("E00");
                        }
@@ -885,6 +999,22 @@ int serve(stlink_t *sl, int port) {
                                stlink_write_reg(sl, ntohl(value), reg);
                        } else if(reg == 0x19) {
                                stlink_write_reg(sl, ntohl(value), 16);
+                       } else if(reg == 0x1A) {
+                               stlink_write_reg(sl, ntohl(value), 17);
+                       } else if(reg == 0x1B) {
+                               stlink_write_reg(sl, ntohl(value), 18);
+                       } else if(reg == 0x1C) {
+                               stlink_write_unsupported_reg(sl, ntohl(value), reg, &regp);
+                       } else if(reg == 0x1D) {
+                               stlink_write_unsupported_reg(sl, ntohl(value), reg, &regp);
+                       } else if(reg == 0x1E) {
+                               stlink_write_unsupported_reg(sl, ntohl(value), reg, &regp);
+                       } else if(reg == 0x1F) {
+                               stlink_write_unsupported_reg(sl, ntohl(value), reg, &regp);
+            } else if(reg >= 0x20 && reg < 0x40) {
+                stlink_write_unsupported_reg(sl, ntohl(value), reg, &regp);
+                       } else if(reg == 0x40) {
+                stlink_write_unsupported_reg(sl, ntohl(value), reg, &regp);
                        } else {
                                reply = strdup("E00");
                        }
@@ -920,7 +1050,7 @@ int serve(stlink_t *sl, int port) {
                                                count : count + 4 - (count % 4));
 
                        reply = calloc(count * 2 + 1, 1);
-                       for(int i = 0; i < count; i++) {
+                       for(unsigned int i = 0; i < count; i++) {
                                reply[i * 2 + 0] = hex[sl->q_buf[i + adj_start] >> 4];
                                reply[i * 2 + 1] = hex[sl->q_buf[i + adj_start] & 0xf];
                        }
@@ -936,7 +1066,7 @@ int serve(stlink_t *sl, int port) {
                        stm32_addr_t start = strtoul(s_start, NULL, 16);
                        unsigned     count = strtoul(s_count, NULL, 16);
 
-                       for(int i = 0; i < count; i ++) {
+                       for(unsigned int i = 0; i < count; i ++) {
                                char hex[3] = { hexdata[i*2], hexdata[i*2+1], 0 };
                                uint8_t byte = strtoul(hex, NULL, 16);
                                sl->q_buf[i] = byte;