gdb: Store watchpoints in avr_gdb_t
[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 #include "sim_gdb.h"
38
39 #define DBG(w)
40
41 #define WATCH_LIMIT (32)
42
43 typedef struct {
44         uint32_t len; /**< How many points are taken (points[0] .. points[len - 1]). */
45         struct {
46                 uint32_t addr; /**< Which address is watched. */
47                 uint32_t size; /**< How large is the watched segment. */
48                 uint32_t kind; /**< Bitmask of enum avr_gdb_watch_type values. */
49         } points[WATCH_LIMIT];
50 } avr_gdb_watchpoints_t;
51
52 typedef struct avr_gdb_t {
53         avr_t * avr;
54         int             listen; // listen socket
55         int             s;              // current gdb connection
56
57         avr_gdb_watchpoints_t breakpoints;
58         avr_gdb_watchpoints_t watchpoints;
59 } avr_gdb_t;
60
61
62 /**
63  * Returns the index of the watchpoint if found, -1 otherwise.
64  */
65 static int gdb_watch_find(const avr_gdb_watchpoints_t * w, uint32_t addr)
66 {
67         for (int i = 0; i < w->len; i++) {
68                 if (w->points[i].addr == addr) {
69                         return i;
70                 }
71         }
72
73         return -1;
74 }
75
76 /**
77  * Returns -1 on error, 0 otherwise.
78  */
79 static int gdb_watch_add_or_update(avr_gdb_watchpoints_t * w, enum avr_gdb_watch_type kind, uint32_t addr,
80                 uint32_t size)
81 {
82         /* If the watchpoint exists, update it. */
83         int i = gdb_watch_find(w, addr);
84         if (i != -1) {
85                 w->points[i].size = size;
86                 w->points[i].kind |= kind;
87                 return 0;
88         }
89
90         /* Otherwise add it. */
91         if (w->len == WATCH_LIMIT) {
92                 return -1;
93         }
94
95         w->points[w->len].kind = kind;
96         w->points[w->len].addr = addr;
97         w->points[w->len].size = size;
98
99         w->len++;
100
101         return 0;
102 }
103
104 /**
105  * Returns -1 on error or if the specified point does not exist, 0 otherwise.
106  */
107 static int gdb_watch_rm(avr_gdb_watchpoints_t * w, enum avr_gdb_watch_type kind, uint32_t addr)
108 {
109         int i = gdb_watch_find(w, addr);
110         if (i == -1) {
111                 return -1;
112         }
113
114         w->points[i].kind &= ~kind;
115         if (w->points[i].kind) {
116                 return 0;
117         }
118
119         for (i = i + 1; i < w->len; i++) {
120                 w->points[i - 1] = w->points[i];
121         }
122
123         w->len--;
124
125         return 0;
126 }
127
128 static void gdb_watch_clear(avr_gdb_watchpoints_t * w)
129 {
130         w->len = 0;
131 }
132
133 static void gdb_send_reply(avr_gdb_t * g, char * cmd)
134 {
135         uint8_t reply[1024];
136         uint8_t * dst = reply;
137         uint8_t check = 0;
138         *dst++ = '$';
139         while (*cmd) {
140                 check += *cmd;
141                 *dst++ = *cmd++;
142         }
143         sprintf((char*)dst, "#%02x", check);
144         DBG(printf("%s '%s'\n", __FUNCTION__, reply);)
145         send(g->s, reply, dst - reply + 3, 0);
146 }
147
148 static void gdb_send_quick_status(avr_gdb_t * g, uint8_t signal)
149 {
150         char cmd[64];
151
152         sprintf(cmd, "T%02x20:%02x;21:%02x%02x;22:%02x%02x%02x00;",
153                 signal ? signal : 5, g->avr->data[R_SREG], 
154                 g->avr->data[R_SPL], g->avr->data[R_SPH],
155                 g->avr->pc & 0xff, (g->avr->pc>>8)&0xff, (g->avr->pc>>16)&0xff);
156         gdb_send_reply(g, cmd);
157 }
158
159 static int gdb_change_breakpoint(avr_gdb_watchpoints_t * w, int set, enum avr_gdb_watch_type kind,
160                 uint32_t addr, uint32_t size)
161 {
162         DBG(printf("set %d kind %d addr %08x len %d\n", set, kind, addr, len);)
163
164         if (set) {
165                 return gdb_watch_add_or_update(w, kind, addr, size);
166         } else {
167                 return gdb_watch_rm(w, kind, addr);
168         }
169
170         return -1;
171 }
172
173 static int gdb_write_register(avr_gdb_t * g, int regi, uint8_t * src)
174 {
175         switch (regi) {
176                 case 0 ... 31:
177                         g->avr->data[regi] = *src;
178                         return 1;
179                 case 32:
180                         g->avr->data[R_SREG] = *src;
181                         return 1;
182                 case 33:
183                         g->avr->data[R_SPL] = src[0];
184                         g->avr->data[R_SPH] = src[1];
185                         return 2;
186                 case 34:
187                         g->avr->pc = src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
188                         return 4;
189         }
190         return 1;
191 }
192
193 static int gdb_read_register(avr_gdb_t * g, int regi, char * rep)
194 {
195         switch (regi) {
196                 case 0 ... 31:
197                         sprintf(rep, "%02x", g->avr->data[regi]);
198                         break;
199                 case 32:
200                         sprintf(rep, "%02x", g->avr->data[R_SREG]);
201                         break;
202                 case 33:
203                         sprintf(rep, "%02x%02x", g->avr->data[R_SPL], g->avr->data[R_SPH]);
204                         break;
205                 case 34:
206                         sprintf(rep, "%02x%02x%02x00", 
207                                 g->avr->pc & 0xff, (g->avr->pc>>8)&0xff, (g->avr->pc>>16)&0xff);
208                         break;
209         }
210         return strlen(rep);
211 }
212
213 static void gdb_handle_command(avr_gdb_t * g, char * cmd)
214 {
215         avr_t * avr = g->avr;
216         char rep[1024];
217         uint8_t command = *cmd++;
218         switch (command) {
219                 case '?':
220                         gdb_send_quick_status(g, 0);
221                         break;
222                 case 'G': {     // set all general purpose registers
223                         // get their binary form
224                         read_hex_string(cmd, (uint8_t*)rep, strlen(cmd));
225                         uint8_t *src = (uint8_t*)rep;
226                         for (int i = 0; i < 35; i++)
227                                 src += gdb_write_register(g, i, src);
228                         gdb_send_reply(g, "OK");                                                                                
229                 }       break;
230                 case 'g': {     // read all general purpose registers
231                         char * dst = rep;
232                         for (int i = 0; i < 35; i++)
233                                 dst += gdb_read_register(g, i, dst);
234                         gdb_send_reply(g, rep);                                         
235                 }       break;
236                 case 'p': {     // read register
237                         unsigned int regi = 0;
238                         sscanf(cmd, "%x", &regi);
239                         gdb_read_register(g, regi, rep);
240                         gdb_send_reply(g, rep);                 
241                 }       break;
242                 case 'P': {     // write register
243                         unsigned int regi = 0;
244                         char * val = strchr(cmd, '=');
245                         if (!val)
246                                 break;
247                         *val++ = 0;
248                         sscanf(cmd, "%x", &regi);
249                         read_hex_string(val, (uint8_t*)rep, strlen(val));
250                         gdb_write_register(g, regi, (uint8_t*)rep);
251                         gdb_send_reply(g, "OK");                                                                                
252                 }       break;
253                 case 'm': {     // read memory
254                         avr_flashaddr_t addr;
255                         uint32_t len;
256                         sscanf(cmd, "%x,%x", &addr, &len);
257                         uint8_t * src = NULL;
258                         if (addr < avr->flashend) {
259                                 src = avr->flash + addr;
260                         } else if (addr >= 0x800000 && (addr - 0x800000) <= avr->ramend) {
261                                 src = avr->data + addr - 0x800000;
262                         } else if (addr >= 0x810000 && (addr - 0x810000) <= avr->e2end) {
263                                 avr_eeprom_desc_t ee = {.offset = (addr - 0x810000)};
264                                 avr_ioctl(avr, AVR_IOCTL_EEPROM_GET, &ee);
265                                 if (ee.ee)
266                                         src = ee.ee;
267                                 else {
268                                         gdb_send_reply(g, "E01");
269                                         break;
270                                 }
271                         } else if (addr >= 0x800000 && (addr - 0x800000) == avr->ramend+1 && len == 2) {
272                                 // Allow GDB to read a value just after end of stack.
273                                 // This is necessary to make instruction stepping work when stack is empty
274                                 printf("GDB read just past end of stack %08x, %08x; returning zero\n", addr, len);
275                                 gdb_send_reply(g, "0000");
276                                 break;
277                         } else {
278                                 printf("read memory error %08x, %08x (ramend %04x)\n", addr, len, avr->ramend+1);
279                                 gdb_send_reply(g, "E01");
280                                 break;
281                         }
282                         char * dst = rep;
283                         while (len--) {
284                                 sprintf(dst, "%02x", *src++);
285                                 dst += 2;
286                         }
287                         *dst = 0;
288                         gdb_send_reply(g, rep);
289                 }       break;
290                 case 'M': {     // write memory
291                         uint32_t addr, len;
292                         sscanf(cmd, "%x,%x", &addr, &len);
293                         char * start = strchr(cmd, ':');
294                         if (!start) {
295                                 gdb_send_reply(g, "E01");
296                                 break;
297                         }
298                         if (addr < 0xffff) {
299                                 read_hex_string(start + 1, avr->flash + addr, strlen(start+1));
300                                 gdb_send_reply(g, "OK");                        
301                         } else if (addr >= 0x800000 && (addr - 0x800000) <= avr->ramend) {
302                                 read_hex_string(start + 1, avr->data + addr - 0x800000, strlen(start+1));
303                                 gdb_send_reply(g, "OK");                                                        
304                         } else if (addr >= 0x810000 && (addr - 0x810000) <= avr->e2end) {
305                                 read_hex_string(start + 1, (uint8_t*)rep, strlen(start+1));
306                                 avr_eeprom_desc_t ee = {.offset = (addr - 0x810000), .size = len, .ee = (uint8_t*)rep };
307                                 avr_ioctl(avr, AVR_IOCTL_EEPROM_SET, &ee);
308                                 gdb_send_reply(g, "OK");                                                        
309                         } else {
310                                 printf("write memory error %08x, %08x\n", addr, len);
311                                 gdb_send_reply(g, "E01");
312                         }               
313                 }       break;
314                 case 'c': {     // continue
315                         avr->state = cpu_Running;
316                 }       break;
317                 case 's': {     // step
318                         avr->state = cpu_Step;
319                 }       break;
320                 case 'r': {     // deprecated, suggested for AVRStudio compatibility
321                         avr->state = cpu_StepDone;
322                         avr_reset(avr);
323                 }       break;
324                 case 'Z':       // set clear break/watchpoint
325                 case 'z': {
326                         uint32_t kind, addr, len;
327                         int set = (command == 'Z');
328                         sscanf(cmd, "%d,%x,%x", &kind, &addr, &len);
329 //                      printf("breakpoint %d, %08x, %08x\n", kind, addr, len);
330                         switch (kind) {
331                                 case 0: // software breakpoint
332                                 case 1: // hardware breakpoint
333                                         if (addr > avr->flashend ||
334                                                         gdb_change_breakpoint(&g->breakpoints, set, 1 << kind, addr, len) == -1) {
335                                                 gdb_send_reply(g, "E01");
336                                                 break;
337                                         }
338
339                                         gdb_send_reply(g, "OK");
340                                         break;
341                                 case 2: // write watchpoint
342                                 case 3: // read watchpoint
343                                 case 4: // access watchpoint
344                                         /* Mask out the offset applied to SRAM addresses. */
345                                         addr &= ~0x800000;
346                                         if (addr > avr->ramend ||
347                                                         gdb_change_breakpoint(&g->watchpoints, set, 1 << kind, addr, len) == -1) {
348                                                 gdb_send_reply(g, "E01");
349                                                 break;
350                                         }
351
352                                         gdb_send_reply(g, "OK");
353                                         break;
354                                 default:
355                                         gdb_send_reply(g, "");
356                                         break;
357                         }
358                 }       break;
359                 default:
360                         gdb_send_reply(g, "");
361                         break;
362         }
363 }
364
365 static int gdb_network_handler(avr_gdb_t * g, uint32_t dosleep)
366 {
367         fd_set read_set;
368         int max;
369         FD_ZERO(&read_set);
370
371         if (g->s != -1) {
372                 FD_SET(g->s, &read_set);
373                 max = g->s + 1;
374         } else {
375                 FD_SET(g->listen, &read_set);
376                 max = g->listen + 1;
377         }
378         struct timeval timo = { 0, dosleep };   // short, but not too short interval
379         int ret = select(max, &read_set, NULL, NULL, &timo);
380
381         if (ret == 0)
382                 return 0;
383         
384         if (FD_ISSET(g->listen, &read_set)) {
385                 g->s = accept(g->listen, NULL, NULL);
386
387                 if (g->s == -1) {
388                         perror("gdb_network_handler accept");
389                         sleep(5);
390                         return 1;
391                 }
392         int i = 1;
393         setsockopt (g->s, IPPROTO_TCP, TCP_NODELAY, &i, sizeof (i));
394                 g->avr->state = cpu_Stopped;
395                 printf("%s connection opened\n", __FUNCTION__);         
396         }
397                 
398         if (g->s != -1 && FD_ISSET(g->s, &read_set)) {
399                 uint8_t buffer[1024];
400                 
401                 ssize_t r = recv(g->s, buffer, sizeof(buffer)-1, 0);
402
403                 if (r == 0) {
404                         printf("%s connection closed\n", __FUNCTION__);
405                         close(g->s);
406                         gdb_watch_clear(&g->breakpoints);
407                         gdb_watch_clear(&g->watchpoints);
408                         g->avr->state = cpu_Running;    // resume
409                         g->s = -1;
410                         return 1;
411                 }
412                 if (r == -1) {
413                         perror("gdb_network_handler recv");
414                         sleep(1);
415                         return 1;
416                 }
417                 buffer[r] = 0;
418         //      printf("%s: received %d bytes\n'%s'\n", __FUNCTION__, r, buffer);
419         //      hdump("gdb", buffer, r);
420
421                 uint8_t * src = buffer;
422                 while (*src == '+' || *src == '-')
423                         src++;
424                 // control C -- lets send the guy a nice status packet
425                 if (*src == 3) {
426                         src++;
427                         g->avr->state = cpu_StepDone;
428                         printf("GDB hit control-c\n");
429                 }
430                 if (*src  == '$') {
431                         // strip checksum
432                         uint8_t * end = buffer + r - 1;
433                         while (end > src && *end != '#')
434                                 *end-- = 0;
435                         *end = 0;
436                         src++;
437                         DBG(printf("GDB command = '%s'\n", src);)
438
439                         send(g->s, "+", 1, 0);
440
441                         gdb_handle_command(g, (char*)src);
442                 }
443         }
444         return 1;
445 }
446
447 int avr_gdb_processor(avr_t * avr, int sleep)
448 {
449         if (!avr || !avr->gdb)
450                 return 0;       
451         avr_gdb_t * g = avr->gdb;
452
453         if (avr->state == cpu_Running && gdb_watch_find(&g->breakpoints, avr->pc) != -1) {
454                 DBG(printf("avr_gdb_processor hit breakpoint at %08x\n", avr->pc);)
455                 gdb_send_quick_status(g, 0);
456                 avr->state = cpu_Stopped;
457         } else if (avr->state == cpu_StepDone) {
458                 gdb_send_quick_status(g, 0);
459                 avr->state = cpu_Stopped;
460         }
461         // this also sleeps for a bit
462         return gdb_network_handler(g, sleep);
463 }
464
465
466 int avr_gdb_init(avr_t * avr)
467 {
468         avr_gdb_t * g = malloc(sizeof(avr_gdb_t));
469         memset(g, 0, sizeof(avr_gdb_t));
470
471         avr->gdb = NULL;
472
473         if ((g->listen = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
474                 fprintf(stderr, "Can't create socket: %s", strerror(errno));
475                 return -1;
476         }
477
478         int i = 1;
479         setsockopt(g->listen, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));
480
481         struct sockaddr_in address = { 0 };
482         address.sin_family = AF_INET;
483         address.sin_port = htons (avr->gdb_port);
484
485         if (bind(g->listen, (struct sockaddr *) &address, sizeof(address))) {
486                 fprintf(stderr, "Can not bind socket: %s", strerror(errno));
487                 return -1;
488         }
489         if (listen(g->listen, 1)) {
490                 perror("listen");
491                 return -1;
492         }
493         printf("avr_gdb_init listening on port %d\n", avr->gdb_port);
494         g->avr = avr;
495         g->s = -1;
496         avr->gdb = g;
497         // change default run behaviour to use the slightly slower versions
498         avr->run = avr_callback_run_gdb;
499         avr->sleep = avr_callback_sleep_gdb;
500         
501         return 0;
502 }