gdb: Adds the 'reset' command
[simavr] / simavr / sim / sim_gdb.c
1 /*
2         sim_gdb.c
3
4         Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
5
6         This file is part of simavr.
7
8         simavr is free software: you can redistribute it and/or modify
9         it under the terms of the GNU General Public License as published by
10         the Free Software Foundation, either version 3 of the License, or
11         (at your option) any later version.
12
13         simavr is distributed in the hope that it will be useful,
14         but WITHOUT ANY WARRANTY; without even the implied warranty of
15         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16         GNU General Public License for more details.
17
18         You should have received a copy of the GNU General Public License
19         along with simavr.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include <netinet/in.h>
23 #include <netinet/tcp.h>
24 #include <arpa/inet.h>
25 #include <sys/socket.h>
26 #include <sys/time.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <unistd.h>
30 #include <string.h>
31 #include <errno.h>
32 #include <poll.h>
33 #include <pthread.h>
34 #include "sim_avr.h"
35 #include "sim_hex.h"
36 #include "avr_eeprom.h"
37
38 #define DBG(w)
39
40 typedef struct avr_gdb_t {
41         avr_t * avr;
42         int             listen; // listen socket
43         int             s;              // current gdb connection
44
45         uint32_t        watchmap;
46         struct {
47                 uint32_t        pc;
48                 uint32_t        len;
49                 int kind;
50         } watch[32];
51 } avr_gdb_t;
52
53
54 static void gdb_send_reply(avr_gdb_t * g, char * cmd)
55 {
56         uint8_t reply[1024];
57         uint8_t * dst = reply;
58         uint8_t check = 0;
59         *dst++ = '$';
60         while (*cmd) {
61                 check += *cmd;
62                 *dst++ = *cmd++;
63         }
64         sprintf((char*)dst, "#%02x", check);
65         DBG(printf("%s '%s'\n", __FUNCTION__, reply);)
66         send(g->s, reply, dst - reply + 3, 0);
67 }
68
69 static void gdb_send_quick_status(avr_gdb_t * g, uint8_t signal)
70 {
71         char cmd[64];
72
73         sprintf(cmd, "T%02x20:%02x;21:%02x%02x;22:%02x%02x%02x00;",
74                 signal ? signal : 5, g->avr->data[R_SREG], 
75                 g->avr->data[R_SPL], g->avr->data[R_SPH],
76                 g->avr->pc & 0xff, (g->avr->pc>>8)&0xff, (g->avr->pc>>16)&0xff);
77         gdb_send_reply(g, cmd);
78 }
79
80 static int gdb_change_breakpoint(avr_gdb_t * g, int set, int kind, uint32_t addr, uint32_t len)
81 {
82         DBG(printf("set %d kind %d addr %08x len %d (map %08x)\n", set, kind, addr, len, g->watchmap);)
83         if (set) {
84                 if (g->watchmap == 0xffffffff)
85                         return -1;      // map full
86
87                 // check to see if it exists
88                 for (int i = 0; i < 32; i++)
89                         if ((g->watchmap & (1 << i)) && g->watch[i].pc == addr) {
90                                 g->watch[i].len = len;
91                                 return 0;
92                         }
93                 for (int i = 0; i < 32; i++)
94                         if (!(g->watchmap & (1 << i))) {
95                                 g->watchmap |= (1 << i);
96                                 g->watch[i].len = len;
97                                 g->watch[i].pc = addr;
98                                 g->watch[i].kind = kind;
99                                 return 0;
100                         }
101         } else {
102                 for (int i = 0; i < 32; i++)
103                         if ((g->watchmap & (1 << i)) && g->watch[i].pc == addr) {
104                                 g->watchmap &= ~(1 << i);
105                                 g->watch[i].len = 0;
106                                 g->watch[i].pc = 0;
107                                 g->watch[i].kind = 0;
108                                 return 0;
109                         }
110         }
111         return -1;
112 }
113
114 static int gdb_write_register(avr_gdb_t * g, int regi, uint8_t * src)
115 {
116         switch (regi) {
117                 case 0 ... 31:
118                         g->avr->data[regi] = *src;
119                         return 1;
120                 case 32:
121                         g->avr->data[R_SREG] = *src;
122                         return 1;
123                 case 33:
124                         g->avr->data[R_SPL] = src[0];
125                         g->avr->data[R_SPH] = src[1];
126                         return 2;
127                 case 34:
128                         g->avr->pc = src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
129                         return 4;
130         }
131         return 1;
132 }
133
134 static int gdb_read_register(avr_gdb_t * g, int regi, char * rep)
135 {
136         switch (regi) {
137                 case 0 ... 31:
138                         sprintf(rep, "%02x", g->avr->data[regi]);
139                         break;
140                 case 32:
141                         sprintf(rep, "%02x", g->avr->data[R_SREG]);
142                         break;
143                 case 33:
144                         sprintf(rep, "%02x%02x", g->avr->data[R_SPL], g->avr->data[R_SPH]);
145                         break;
146                 case 34:
147                         sprintf(rep, "%02x%02x%02x00", 
148                                 g->avr->pc & 0xff, (g->avr->pc>>8)&0xff, (g->avr->pc>>16)&0xff);
149                         break;
150         }
151         return strlen(rep);
152 }
153
154 static void gdb_handle_command(avr_gdb_t * g, char * cmd)
155 {
156         avr_t * avr = g->avr;
157         char rep[1024];
158         uint8_t command = *cmd++;
159         switch (command) {
160                 case '?':
161                         gdb_send_quick_status(g, 0);
162                         break;
163                 case 'G': {     // set all general purpose registers
164                         // get their binary form
165                         read_hex_string(cmd, (uint8_t*)rep, strlen(cmd));
166                         uint8_t *src = (uint8_t*)rep;
167                         for (int i = 0; i < 35; i++)
168                                 src += gdb_write_register(g, i, src);
169                         gdb_send_reply(g, "OK");                                                                                
170                 }       break;
171                 case 'g': {     // read all general purpose registers
172                         char * dst = rep;
173                         for (int i = 0; i < 35; i++)
174                                 dst += gdb_read_register(g, i, dst);
175                         gdb_send_reply(g, rep);                                         
176                 }       break;
177                 case 'p': {     // read register
178                         unsigned int regi = 0;
179                         sscanf(cmd, "%x", &regi);
180                         gdb_read_register(g, regi, rep);
181                         gdb_send_reply(g, rep);                 
182                 }       break;
183                 case 'P': {     // write register
184                         unsigned int regi = 0;
185                         char * val = strchr(cmd, '=');
186                         if (!val)
187                                 break;
188                         *val++ = 0;
189                         sscanf(cmd, "%x", &regi);
190                         read_hex_string(val, (uint8_t*)rep, strlen(val));
191                         gdb_write_register(g, regi, (uint8_t*)rep);
192                         gdb_send_reply(g, "OK");                                                                                
193                 }       break;
194                 case 'm': {     // read memory
195                         uint32_t addr, len;
196                         sscanf(cmd, "%x,%x", &addr, &len);
197                         uint8_t * src = NULL;
198                         if (addr < 0xffff) {
199                                 src = avr->flash + addr;
200                         } else if (addr >= 0x800000 && (addr - 0x800000) <= avr->ramend) {
201                                 src = avr->data + addr - 0x800000;
202                         } else if (addr >= 0x810000 && (addr - 0x810000) <= avr->e2end) {
203                                 avr_eeprom_desc_t ee = {.offset = (addr - 0x810000)};
204                                 avr_ioctl(avr, AVR_IOCTL_EEPROM_GET, &ee);
205                                 if (ee.ee)
206                                         src = ee.ee;
207                                 else {
208                                         gdb_send_reply(g, "E01");
209                                         break;
210                                 }
211                         } else {
212                                 printf("read memory error %08x, %08x (ramend %04x)\n", addr, len, avr->ramend+1);
213                                 gdb_send_reply(g, "E01");
214                                 break;
215                         }
216                         char * dst = rep;
217                         while (len--) {
218                                 sprintf(dst, "%02x", *src++);
219                                 dst += 2;
220                         }
221                         *dst = 0;
222                         gdb_send_reply(g, rep);
223                 }       break;
224                 case 'M': {     // write memory
225                         uint32_t addr, len;
226                         sscanf(cmd, "%x,%x", &addr, &len);
227                         char * start = strchr(cmd, ':');
228                         if (!start) {
229                                 gdb_send_reply(g, "E01");
230                                 break;
231                         }
232                         if (addr < 0xffff) {
233                                 read_hex_string(start + 1, avr->flash + addr, strlen(start+1));
234                                 gdb_send_reply(g, "OK");                        
235                         } else if (addr >= 0x800000 && (addr - 0x800000) <= avr->ramend) {
236                                 read_hex_string(start + 1, avr->data + addr - 0x800000, strlen(start+1));
237                                 gdb_send_reply(g, "OK");                                                        
238                         } else if (addr >= 0x810000 && (addr - 0x810000) <= avr->e2end) {
239                                 read_hex_string(start + 1, (uint8_t*)rep, strlen(start+1));
240                                 avr_eeprom_desc_t ee = {.offset = (addr - 0x810000), .size = len, .ee = (uint8_t*)rep };
241                                 avr_ioctl(avr, AVR_IOCTL_EEPROM_SET, &ee);
242                                 gdb_send_reply(g, "OK");                                                        
243                         } else {
244                                 printf("write memory error %08x, %08x\n", addr, len);
245                                 gdb_send_reply(g, "E01");
246                         }               
247                 }       break;
248                 case 'c': {     // continue
249                         avr->state = cpu_Running;
250                 }       break;
251                 case 's': {     // step
252                         avr->state = cpu_Step;
253                 }       break;
254                 case 'r': {     // deprecated, suggested for AVRStudio compatibility
255                         avr->state = cpu_StepDone;
256                         avr_reset(avr);
257                 }       break;
258                 case 'Z':       // set clear break/watchpoint
259                 case 'z': {
260                         uint32_t kind, addr, len;
261                         sscanf(cmd, "%d,%x,%x", &kind, &addr, &len);
262 //                      printf("breakbpoint %d, %08x, %08x\n", kind, addr, len);
263                         switch (kind) {
264                                 case 0: // software breakpoint
265                                 case 1: // hardware breakpoint
266                                         if (addr <= avr->flashend) {
267                                                 if (gdb_change_breakpoint(g, command == 'Z', kind, addr, len))
268                                                         gdb_send_reply(g, "E01");
269                                                 else
270                                                         gdb_send_reply(g, "OK");
271                                         } else
272                                                 gdb_send_reply(g, "E01");               // out of flash address
273                                         break;
274                                 // TODO
275                                 case 2: // write watchpoint
276                                 case 3: // read watchpoint
277                                 case 4: // access watchpoint
278                                 default:
279                                         gdb_send_reply(g, "");
280                         }       
281                 }       break;
282                 default:
283                         gdb_send_reply(g, "");
284         }
285 }
286
287 static int gdb_network_handler(avr_gdb_t * g, uint32_t dosleep)
288 {
289         fd_set read_set;
290         int max;
291         FD_ZERO(&read_set);
292
293         if (g->s != -1) {
294                 FD_SET(g->s, &read_set);
295                 max = g->s + 1;
296         } else {
297                 FD_SET(g->listen, &read_set);
298                 max = g->listen + 1;
299         }
300         struct timeval timo = { 0, dosleep };   // short, but not too short interval
301         int ret = select(max, &read_set, NULL, NULL, &timo);
302
303         if (ret == 0)
304                 return 0;
305         
306         if (FD_ISSET(g->listen, &read_set)) {
307                 g->s = accept(g->listen, NULL, NULL);
308
309                 if (g->s == -1) {
310                         perror("gdb_network_handler accept");
311                         sleep(5);
312                         return 1;
313                 }
314         int i = 1;
315         setsockopt (g->s, IPPROTO_TCP, TCP_NODELAY, &i, sizeof (i));
316                 g->avr->state = cpu_Stopped;
317                 printf("%s connection opened\n", __FUNCTION__);         
318         }
319                 
320         if (g->s != -1 && FD_ISSET(g->s, &read_set)) {
321                 uint8_t buffer[1024];
322                 
323                 ssize_t r = recv(g->s, buffer, sizeof(buffer)-1, 0);
324
325                 if (r == 0) {
326                         printf("%s connection closed\n", __FUNCTION__);
327                         close(g->s);
328                         g->watchmap = 0;                                // clear breakpoints
329                         g->avr->state = cpu_Running;    // resume
330                         g->s = -1;
331                         return 1;
332                 }
333                 if (r == -1) {
334                         perror("gdb_network_handler recv");
335                         sleep(1);
336                         return 1;
337                 }
338                 buffer[r] = 0;
339         //      printf("%s: received %d bytes\n'%s'\n", __FUNCTION__, r, buffer);
340         //      hdump("gdb", buffer, r);
341
342                 uint8_t * src = buffer;
343                 while (*src == '+' || *src == '-')
344                         src++;
345                 // control C -- lets send the guy a nice status packet
346                 if (*src == 3) {
347                         src++;
348                         g->avr->state = cpu_StepDone;
349                         printf("GDB hit control-c\n");
350                 }
351                 if (*src  == '$') {
352                         // strip checksum
353                         uint8_t * end = buffer + r - 1;
354                         while (end > src && *end != '#')
355                                 *end-- = 0;
356                         *end = 0;
357                         src++;
358                         DBG(printf("GDB command = '%s'\n", src);)
359
360                         send(g->s, "+", 1, 0);
361
362                         gdb_handle_command(g, (char*)src);
363                 }
364         }
365         return 1;
366 }
367
368 int avr_gdb_processor(avr_t * avr, int sleep)
369 {
370         if (!avr || !avr->gdb)
371                 return 0;       
372         avr_gdb_t * g = avr->gdb;
373
374         if (g->watchmap && avr->state == cpu_Running) {
375                 for (int i = 0; i < 32; i++)
376                         if ((g->watchmap & (1 << i)) && g->watch[i].pc == avr->pc) {
377                                 DBG(printf("avr_gdb_processor hit breakpoint at %08x\n", avr->pc);)
378                                 gdb_send_quick_status(g, 0);
379                                 avr->state = cpu_Stopped;
380                         }               
381         }
382         if (avr->state == cpu_StepDone) {
383                 gdb_send_quick_status(g, 0);
384                 avr->state = cpu_Stopped;
385         }
386         // this also sleeps for a bit
387         return gdb_network_handler(g, sleep);
388 }
389
390
391 int avr_gdb_init(avr_t * avr)
392 {
393         avr_gdb_t * g = malloc(sizeof(avr_gdb_t));
394         memset(g, 0, sizeof(avr_gdb_t));
395
396         avr->gdb = NULL;
397
398         if ((g->listen = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
399                 fprintf(stderr, "Can't create socket: %s", strerror(errno));
400                 return -1;
401         }
402
403         int i = 1;
404         setsockopt(g->listen, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));
405
406         struct sockaddr_in address = { 0 };
407         address.sin_family = AF_INET;
408         address.sin_port = htons (avr->gdb_port);
409
410         if (bind(g->listen, (struct sockaddr *) &address, sizeof(address))) {
411                 fprintf(stderr, "Can not bind socket: %s", strerror(errno));
412                 return -1;
413         }
414         if (listen(g->listen, 1)) {
415                 perror("listen");
416                 return -1;
417         }
418         printf("avr_gdb_init listening on port %d\n", avr->gdb_port);
419         g->avr = avr;
420         g->s = -1;
421         avr->gdb = g;
422         
423         return 0;
424 }