]> git.sur5r.net Git - openocd/blobdiff - src/server/gdb_server.c
export find_file function
[openocd] / src / server / gdb_server.c
index 9a5b81a49360d19e188c7931460a734b79bd40af..c2c18baf208d7bf69824d32d397b606751f33ac0 100644 (file)
@@ -63,8 +63,10 @@ enum gdb_detach_mode detach_mode = GDB_DETACH_RESUME;
 
 /* set if we are sending a memory map to gdb
  * via qXfer:memory-map:read packet */
-int gdb_use_memory_map = 0;
-int gdb_flash_program = 0;
+/* enabled by default*/
+int gdb_use_memory_map = 1;
+/* enabled by default*/
+int gdb_flash_program = 1;
 
 /* if set, data aborts cause an error to be reported in memory read packets
  * see the code in gdb_read_memory_packet() for further explanations */
@@ -690,7 +692,7 @@ int gdb_new_connection(connection_t *connection)
         * instantaneous and thus avoiding annoying timeout problems during
         * connect. 
         */
-       gdb_service->target->type->halt(gdb_service->target);
+       target_halt(gdb_service->target);
        
        /* remove the initial ACK from the incoming buffer */
        if ((retval = gdb_get_char(connection, &initial_ack)) != ERROR_OK)
@@ -1231,7 +1233,7 @@ void gdb_step_continue_packet(connection_t *connection, target_t *target, char *
        if (packet[0] == 'c')
        {
                LOG_DEBUG("continue");
-               target->type->resume(target, current, address, 0, 0); /* resume at current address, don't handle breakpoints, not debugging */
+               target_resume(target, current, address, 0, 0); /* resume at current address, don't handle breakpoints, not debugging */
        }
        else if (packet[0] == 's')
        {
@@ -1417,6 +1419,24 @@ int gdb_calc_blocksize(flash_bank_t *bank)
        return block_size;
 }
 
+static int compare_bank (const void * a, const void * b)
+{
+       flash_bank_t *b1, *b2;
+       b1=*((flash_bank_t **)a);
+       b2=*((flash_bank_t **)b);
+       
+       if (b1->base==b2->base)
+       {
+               return 0;
+       } else if (b1->base>b2->base)
+       {
+               return 1;
+       } else
+       {
+               return -1;
+       }
+}
+
 int gdb_query_packet(connection_t *connection, target_t *target, char *packet, int packet_size)
 {
        command_context_t *cmd_ctx = connection->cmd_ctx;
@@ -1537,23 +1557,63 @@ int gdb_query_packet(connection_t *connection, target_t *target, char *packet, i
                length = strtoul(separator + 1, &separator, 16);
 
                xml_printf(&retval, &xml, &pos, &size, "<memory-map>\n");
-
+       
+               /* 
+               sort banks in ascending order, we need to make non-flash memory be ram(or rather
+               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());
                int i;
+               
                for (i=0; i<flash_get_bank_count(); i++)
                {
                        p = get_flash_bank_by_num(i);
                        if (p == NULL)
-                               break;
-
+                       {
+                               free(banks);
+                               retval = ERROR_FAIL;
+                               gdb_send_error(connection, retval);
+                               return retval;
+                       }
+                       banks[i]=p;
+               }
+               
+               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++)
+               {
+                       p = banks[i];
+                       
+                       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);
+                       }
+                       
                        /* if device has uneven sector sizes, eg. str7, lpc
                         * we pass the smallest sector size to gdb memory map */
                        blocksize = gdb_calc_blocksize(p);
-
+       
                        xml_printf(&retval, &xml, &pos, &size, "<memory type=\"flash\" start=\"0x%x\" length=\"0x%x\">\n" \
                                "<property name=\"blocksize\">0x%x</property>\n" \
                                "</memory>\n", \
                                p->base, p->size, blocksize);
+                       ram_start=p->base+p->size;                      
                }
+               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);
+               } else
+               {
+                       /* a flash chip could be at the very end of the 32 bit address space, in which case
+                       ram_start will be precisely 0 */
+               }
+               
+               free(banks);
+               banks = NULL;
 
                xml_printf(&retval, &xml, &pos, &size, "</memory-map>\n");
 
@@ -1755,7 +1815,7 @@ int gdb_detach(connection_t *connection, target_t *target)
        switch( detach_mode )
        {
                case GDB_DETACH_RESUME:
-                       target->type->resume(target, 1, 0, 1, 0);
+                       target_resume(target, 1, 0, 1, 0);
                        break;
 
                case GDB_DETACH_RESET:
@@ -1763,7 +1823,7 @@ int gdb_detach(connection_t *connection, target_t *target)
                        break;
 
                case GDB_DETACH_HALT:
-                       target->type->halt(target);
+                       target_halt(target);
                        break;
 
                case GDB_DETACH_NOTHING:
@@ -1790,11 +1850,14 @@ static void gdb_log_callback(void *priv, const char *file, int line,
        gdb_output_con(connection, string);
 }
 
+/* Do not allocate this on the stack */
+char gdb_packet_buffer[GDB_BUFFER_SIZE];
+
 int gdb_input_inner(connection_t *connection)
 {
        gdb_service_t *gdb_service = connection->service->priv;
        target_t *target = gdb_service->target;
-       char packet[GDB_BUFFER_SIZE];
+       char *packet=gdb_packet_buffer;
        int packet_size;
        int retval;
        gdb_connection_t *gdb_con = connection->priv;
@@ -1855,12 +1918,24 @@ int gdb_input_inner(connection_t *connection)
                                case 'c':
                                case 's':
                                        {
-                                       /* 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);
-                                               gdb_step_continue_packet(connection, target, packet, packet_size);
+                                               if (target->state != TARGET_HALTED)
+                                               {
+                                                       /* If the target isn't in the halted state, then we can't
+                                                        * step/continue. This might be early setup, etc.
+                                                        */
+                                                       char sig_reply[4];
+                                                       snprintf(sig_reply, 4, "T%2.2x", 2);
+                                                       gdb_put_packet(connection, sig_reply, 3);
+                                               } 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);
+                                                       gdb_step_continue_packet(connection, target, packet, packet_size);
+                                               }
                                        }
                                        break;
                                case 'v':
@@ -1904,7 +1979,7 @@ int gdb_input_inner(connection_t *connection)
                {
                        if (target->state == TARGET_RUNNING)
                        {
-                               target->type->halt(target);
+                               target_halt(target);
                                gdb_con->ctrl_c = 0;
                        }
                }