* support/scripts/sdcc.nsi: fixed Error: unterminated string parsing
[fw/sdcc] / debugger / mcs51 / simi.c
1 /*-------------------------------------------------------------------------
2   simi.c - source file for simulator interaction
3         Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1999)
4
5    This program is free software; you can redistribute it and/or modify it
6    under the terms of the GNU General Public License as published by the
7    Free Software Foundation; either version 2, or (at your option) any
8    later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19    In other words, you are welcome to use, share and improve this program.
20    You are forbidden to forbid anyone else to use, share and improve
21    what you give them.   Help stamp out software-hoarding!
22 -------------------------------------------------------------------------*/
23 #include "sdcdb.h"
24 #include "simi.h"
25 #include "newalloc.h"
26
27 #ifdef _WIN32
28 #include <windows.h>
29 #include <winsock2.h>
30 #include <signal.h>
31 #include <io.h>
32 #include <fcntl.h>
33 #else
34 #ifdef HAVE_SYS_SOCKET_H
35 #include <sys/types.h>
36 #include <sys/socket.h>
37 #include <netinet/in.h>
38 #include <arpa/inet.h>
39 #include <unistd.h>
40 #include <signal.h>
41 #else
42 #error "Cannot build debugger without socket support"
43 #endif
44 #endif
45
46 FILE *simin ; /* stream for simulator input */
47 FILE *simout; /* stream for simulator output */
48
49 #ifdef _WIN32
50 SOCKET sock = INVALID_SOCKET;
51 PROCESS_INFORMATION *simPid = NULL;
52 #else
53 int sock = -1; /* socket descriptor to comm with simulator */
54 pid_t simPid = -1;
55 #endif
56 static char simibuff[MAX_SIM_BUFF];    /* sim buffer       */
57 static char regBuff[MAX_SIM_BUFF];
58 static char *sbp = simibuff;           /* simulator buffer pointer */
59 extern char **environ;
60 char simactive = 0;
61
62 static memcache_t memCache[NMEM_CACHE];
63
64 /*-----------------------------------------------------------------*/
65 /* get data from  memory cache/ load cache from simulator          */
66 /*-----------------------------------------------------------------*/
67 static char *getMemCache(unsigned int addr,int cachenum, int size)
68 {
69     char *resp, *buf;
70     unsigned int laddr;
71     memcache_t *cache = &memCache[cachenum];
72
73     if ( cache->size <=   0 ||
74          cache->addr > addr ||
75          cache->addr + cache->size < addr + size )
76     {
77         if ( cachenum == IMEM_CACHE )
78         {
79             sendSim("di 0x0 0xff\n");
80         }
81         else if ( cachenum == SREG_CACHE )
82         {
83             sendSim("ds 0x80 0xff\n");
84         }
85         else
86         {
87             laddr = addr & 0xffffffc0;
88             sprintf(cache->buffer,"dx 0x%x 0x%x\n",laddr,laddr+0xff );
89             sendSim(cache->buffer);
90         }
91         waitForSim(100,NULL);
92         resp = simResponse();
93         cache->addr = strtol(resp,0,0);
94         buf = cache->buffer;
95         cache->size = 0;
96         while ( *resp && *(resp+1) && *(resp+2))
97         {
98             /* cache is a stringbuffer with ascii data like
99                " 00 00 00 00 00 00 00 00"
100             */
101             resp += 2;
102             laddr = 0;
103             /* skip thru the address part */
104             while (isxdigit(*resp)) resp++;
105             while ( *resp && *resp != '\n')
106             {
107                 if ( laddr < 24 )
108                 {
109                     laddr++ ;
110                     *buf++ = *resp ;
111                 }
112                 resp++;
113             }
114             resp++ ;
115             cache->size += 8;
116         }
117         *buf = '\0';
118         if ( cache->addr > addr ||
119              cache->addr + cache->size < addr + size )
120             return NULL;
121     }
122     return cache->buffer + (addr - cache->addr)*3;
123 }
124
125 /*-----------------------------------------------------------------*/
126 /* invalidate memory cache                                         */
127 /*-----------------------------------------------------------------*/
128 static void invalidateCache( int cachenum )
129 {
130     memCache[cachenum].size = 0;
131 }
132
133 /*-----------------------------------------------------------------*/
134 /* waitForSim - wait till simulator is done its job                */
135 /*-----------------------------------------------------------------*/
136 void waitForSim(int timeout_ms, char *expect)
137 {
138   int i=0;
139   int ch;
140
141 Dprintf(D_simi, ("simi: waitForSim start(%d)\n", timeout_ms));
142     sbp = simibuff;
143
144     while ((ch = fgetc(simin)) > 0 ) {
145       *sbp++ = ch;
146     }
147     *sbp = 0;
148     Dprintf(D_simi, ("waitForSim(%d) got[%s]\n", timeout_ms, simibuff));
149
150 }
151
152 /*-----------------------------------------------------------------*/
153 /* openSimulator - create a pipe to talk to simulator              */
154 /*-----------------------------------------------------------------*/
155 #ifdef _WIN32
156 char *argsToCmdLine(char **args, int nargs)
157 {
158 #define CHUNCK  256
159     int i;
160     int cmdPos = 0;
161     char *cmd = Safe_malloc(CHUNCK);
162     int cmdLen = CHUNCK;
163
164     for (i = 0; i < nargs; i++)
165     {
166         int quote = 0;
167         int argLen = strlen(args[i]);
168
169         if (NULL != strchr(args[i], ' '))
170         {
171             quote = 1;
172             argLen += 2;
173         }
174
175         if (0 < nargs)
176             ++argLen;
177
178         if (cmdPos + argLen >= cmdLen)
179         {
180             do
181             {
182                 cmdLen += cmdLen;
183             }
184             while (cmdPos + argLen >= cmdLen);
185             cmd = Safe_realloc(cmd, cmdLen);
186         }
187
188         if (0 < nargs)
189         {
190             cmd[cmdPos++] = ' ';
191             --argLen;
192         }
193
194         if (quote)
195         {
196             cmd[cmdPos++] = '"';
197             --argLen;
198         }
199
200         memcpy(&cmd[cmdPos], args[i], argLen);
201         cmdPos += argLen;
202
203         if (quote)
204             cmd[cmdPos++] = '"';
205     }
206
207     cmd[cmdPos] = '\0'
208
209     return cmd;
210 }
211
212 PROCESS_INFORMATION *execSimulator(char **args, int nargs)
213 {
214     STARTUPINFO si;
215     static PROCESS_INFORMATION pi;
216     char *cmdLine = argsToCmdLine(args, nargs);
217
218     memset(&si, 0, sizeof(si));
219     si.cb = sizeof(si);
220     memset(&pi, 0, sizeof(pi));
221
222     // Start the child process.
223     if (!CreateProcess(NULL,   // No module name (use command line)
224         cmdLine, // Command line
225         NULL,           // Process handle not inheritable
226         NULL,           // Thread handle not inheritable
227         FALSE,          // Set handle inheritance to FALSE
228         0,              // No creation flags
229         NULL,           // Use parent's environment block
230         NULL,           // Use parent's starting directory
231         &si,            // Pointer to STARTUPINFO structure
232         &pi)            // Pointer to PROCESS_INFORMATION structure
233     )
234     {
235         Safe_free(cmdLine);
236         printf( "CreateProcess failed (%d).\n", GetLastError() );
237         return NULL;
238     }
239
240     Safe_free(cmdLine);
241     return &pi;
242 }
243
244 void openSimulator (char **args, int nargs)
245 {
246     struct sockaddr_in sin;
247     int retry = 0;
248     int i;
249     int fh;
250     Dprintf(D_simi, ("simi: openSimulator\n"));
251 #ifdef SDCDB_DEBUG
252     if (D_simi & sdcdbDebug)
253     {
254         printf("simi: openSimulator: ");
255         for (i=0; i < nargs; i++ )
256         {
257             printf("arg%d: %s ",i,args[i]);
258         }
259         printf("\n");
260     }
261 #endif
262     invalidateCache(XMEM_CACHE);
263     invalidateCache(IMEM_CACHE);
264     invalidateCache(SREG_CACHE);
265
266  try_connect:
267     sock = WSASocket(PF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);
268
269     memset(&sin,0,sizeof(sin));
270     sin.sin_family = AF_INET;
271     sin.sin_addr.s_addr = inet_addr("127.0.0.1");
272     sin.sin_port = htons(9756);
273
274     /* connect to the simulator */
275     if (INVALID_SOCKET == connect(sock,(struct sockaddr *) &sin, sizeof(sin)))
276     {
277         /* if failed then wait 1 second & try again
278            do this for 10 secs only */
279         if (retry < 10)
280         {
281             if ( !retry )
282                 simPid = execSimulator(args, nargs);
283             retry ++;
284             Sleep(1000);
285             goto try_connect;
286         }
287         perror("connect failed :");
288         exit(1);
289     }
290     fh = _open_osfhandle((intptr_t)socket, _O_TEXT);
291     if (-1 == fh)
292     {
293         fprintf(stderr, "cannot _open_osfhandle\n");
294         exit(1);
295     }
296
297     /* go the socket now turn it into a file handle */
298     if (!(simin = fdopen(sock,"r")))
299     {
300         fprintf(stderr,"cannot open socket for read\n");
301         exit(1);
302     }
303
304     fh = _open_osfhandle((intptr_t)socket, _O_TEXT);
305     if (-1 == fh)
306     {
307         fprintf(stderr, "cannot _open_osfhandle\n");
308         exit(1);
309     }
310
311     if (!(simout = fdopen(sock,"w")))
312     {
313         fprintf(stderr,"cannot open socket for write\n");
314         exit(1);
315     }
316     /* now that we have opened, wait for the prompt */
317     waitForSim(200,NULL);
318     simactive = 1;
319 }
320 #else
321 int execSimulator(char **args, int nargs)
322 {
323     if ((simPid = fork()))
324     {
325         Dprintf(D_simi, ("simi: simulator pid %d\n",(int) simPid));
326     }
327     else
328     {
329         /* we are in the child process : start the simulator */
330         signal(SIGINT , SIG_IGN );
331         signal(SIGABRT, SIG_IGN );
332         signal(SIGHUP , SIG_IGN );
333         signal(SIGCHLD, SIG_IGN );
334
335         if (execvp(args[0],args) < 0)
336         {
337             perror("cannot exec simulator");
338             exit(1);
339         }
340     }
341 }
342
343 void openSimulator (char **args, int nargs)
344 {
345     struct sockaddr_in sin;
346     int retry = 0;
347     int i;
348     Dprintf(D_simi, ("simi: openSimulator\n"));
349 #ifdef SDCDB_DEBUG
350     if (D_simi & sdcdbDebug)
351     {
352         printf("simi: openSimulator: ");
353         for (i=0; i < nargs; i++ )
354         {
355             printf("arg%d: %s ",i,args[i]);
356         }
357         printf("\n");
358     }
359 #endif
360     invalidateCache(XMEM_CACHE);
361     invalidateCache(IMEM_CACHE);
362     invalidateCache(SREG_CACHE);
363
364  try_connect:
365     sock = socket(AF_INET,SOCK_STREAM,0);
366
367     memset(&sin,0,sizeof(sin));
368     sin.sin_family = AF_INET;
369     sin.sin_addr.s_addr = inet_addr("127.0.0.1");
370     sin.sin_port = htons(9756);
371
372     /* connect to the simulator */
373     if (connect(sock,(struct sockaddr *) &sin, sizeof(sin)) < 0)
374     {
375         /* if failed then wait 1 second & try again
376            do this for 10 secs only */
377         if (retry < 10)
378         {
379             if ( !retry )
380             {
381                 simPid = execSimulator(args, nargs);
382             }
383             retry ++;
384             sleep (1);
385             goto try_connect;
386         }
387         perror("connect failed :");
388         exit(1);
389     }
390     /* go the socket now turn it into a file handle */
391     if (!(simin = fdopen(sock,"r")))
392     {
393         fprintf(stderr,"cannot open socket for read\n");
394         exit(1);
395     }
396
397     if (!(simout = fdopen(sock,"w")))
398     {
399         fprintf(stderr,"cannot open socket for write\n");
400         exit(1);
401     }
402     /* now that we have opened, wait for the prompt */
403     waitForSim(200,NULL);
404     simactive = 1;
405 }
406 #endif
407
408 /*-----------------------------------------------------------------*/
409 /* simResponse - returns buffer to simulator's response            */
410 /*-----------------------------------------------------------------*/
411 char *simResponse()
412 {
413     return simibuff;
414 }
415
416 /*-----------------------------------------------------------------*/
417 /* sendSim - sends a command to the simuator                 */
418 /*-----------------------------------------------------------------*/
419 void sendSim(char *s)
420 {
421     if ( ! simout )
422         return;
423
424     Dprintf(D_simi, ("simi: sendSim-->%s", s));  // s has LF at end already
425     fputs(s,simout);
426     fflush(simout);
427 }
428
429
430 static int getMemString(char *buffer, char wrflag,
431                         unsigned int *addr, char mem, int size )
432 {
433     int cachenr = NMEM_CACHE;
434     char *prefix;
435     char *cmd ;
436
437     if ( wrflag )
438         cmd = "set mem";
439     else
440         cmd = "dump";
441     buffer[0] = '\0' ;
442
443     switch (mem)
444     {
445         case 'A': /* External stack */
446         case 'F': /* External ram */
447             prefix = "xram";
448             cachenr = XMEM_CACHE;
449             break;
450         case 'C': /* Code */
451         case 'D': /* Code / static segment */
452             prefix = "rom";
453             break;
454         case 'B': /* Internal stack */
455         case 'E': /* Internal ram (lower 128) bytes */
456         case 'G': /* Internal ram */
457             prefix = "iram";
458             cachenr = IMEM_CACHE;
459             break;
460         case 'H': /* Bit addressable */
461         case 'J': /* SBIT space */
462             cachenr = BIT_CACHE;
463             if ( wrflag )
464             {
465                 cmd = "set bit";
466             }
467             sprintf(buffer,"%s 0x%x\n",cmd,*addr);
468             return cachenr;
469             break;
470         case 'I': /* SFR space */
471             prefix = "sfr" ;
472             cachenr = SREG_CACHE;
473             break;
474         case 'R': /* Register space */
475             prefix = "iram";
476             /* get register bank */
477             cachenr = simGetValue (0xd0,'I',1);
478             *addr  += cachenr & 0x18 ;
479             cachenr = IMEM_CACHE;
480             break;
481         default:
482         case 'Z': /* undefined space code */
483             return cachenr;
484     }
485     if ( wrflag )
486         sprintf(buffer,"%s %s 0x%x\n",cmd,prefix,*addr);
487     else
488         sprintf(buffer,"%s %s 0x%x 0x%x\n",cmd,prefix,*addr,*addr+size-1);
489     return cachenr;
490 }
491
492 void simSetPC( unsigned int addr )
493 {
494     char buffer[40];
495     sprintf(buffer,"pc %d\n", addr);
496     sendSim(buffer);
497     waitForSim(100,NULL);
498     simResponse();
499 }
500
501 int simSetValue (unsigned int addr,char mem, int size, unsigned long val)
502 {
503     char cachenr, i;
504     char buffer[40];
505     char *s;
506
507     if ( size <= 0 )
508         return 0;
509
510     cachenr = getMemString(buffer,1,&addr,mem,size);
511     if ( cachenr < NMEM_CACHE )
512     {
513         invalidateCache(cachenr);
514     }
515     s = buffer + strlen(buffer) -1;
516     for ( i = 0 ; i < size ; i++ )
517     {
518         sprintf(s," 0x%x", val & 0xff);
519         s += strlen(s);
520         val >>= 8;
521     }
522     sprintf(s,"\n");
523     sendSim(buffer);
524     waitForSim(100,NULL);
525     simResponse();
526     return 0;
527 }
528
529
530 /*-----------------------------------------------------------------*/
531 /* simGetValue - get value @ address for mem space                 */
532 /*-----------------------------------------------------------------*/
533 unsigned long simGetValue (unsigned int addr,char mem, int size)
534 {
535     unsigned int b[4] = {0,0,0,0}; /* can be a max of four bytes long */
536     char cachenr, i;
537     char buffer[40];
538     char *resp;
539
540     if ( size <= 0 )
541         return 0;
542
543     cachenr = getMemString(buffer,0,&addr,mem,size);
544
545     resp = NULL;
546     if ( cachenr < NMEM_CACHE )
547     {
548         resp = getMemCache(addr,cachenr,size);
549     }
550     if ( !resp )
551     {
552         /* create the simulator command */
553         sendSim(buffer);
554         waitForSim(100,NULL);
555         resp = simResponse();
556
557         /* got the response we need to parse it the response
558            is of the form
559            [address] [v] [v] [v] ... special case in
560            case of bit variables which case it becomes
561            [address] [assembler bit address] [v] */
562         /* first skip thru white space */
563         while (isspace(*resp)) resp++ ;
564
565         if (strncmp(resp, "0x",2) == 0)
566             resp += 2;
567
568         /* skip thru the address part */
569         while (isxdigit(*resp)) resp++;
570
571     }
572     /* make the branch for bit variables */
573     if ( cachenr == BIT_CACHE)
574     {
575         /* skip until newline */
576         while (*resp && *resp != '\n' ) resp++ ;
577         if ( *--resp != '0' )
578             b[0] = 1;
579     }
580     else
581     {
582         for (i = 0 ; i < size ; i++ )
583         {
584             /* skip white space */
585             while (isspace(*resp)) resp++ ;
586
587             b[i] = strtol(resp,&resp,16);
588         }
589     }
590
591     return b[0] | b[1] << 8 | b[2] << 16 | b[3] << 24 ;
592
593 }
594
595 /*-----------------------------------------------------------------*/
596 /* simSetBP - set break point for a given address                  */
597 /*-----------------------------------------------------------------*/
598 void simSetBP (unsigned int addr)
599 {
600     char buff[50];
601
602     sprintf(buff,"break 0x%x\n",addr);
603     sendSim(buff);
604     waitForSim(100,NULL);
605 }
606
607 /*-----------------------------------------------------------------*/
608 /* simClearBP - clear a break point                                */
609 /*-----------------------------------------------------------------*/
610 void simClearBP (unsigned int addr)
611 {
612     char buff[50];
613
614     sprintf(buff,"clear 0x%x\n",addr);
615     sendSim(buff);
616     waitForSim(100,NULL);
617 }
618
619 /*-----------------------------------------------------------------*/
620 /* simLoadFile - load the simulator file                           */
621 /*-----------------------------------------------------------------*/
622 void simLoadFile (char *s)
623 {
624     char buff[128];
625
626     sprintf(buff,"file \"%s\"\n",s);
627     printf(buff);
628     sendSim(buff);
629     waitForSim(500,NULL);
630 }
631
632 /*-----------------------------------------------------------------*/
633 /* simGoTillBp - send 'go' to simulator till a bp then return addr */
634 /*-----------------------------------------------------------------*/
635 unsigned int simGoTillBp ( unsigned int gaddr)
636 {
637     char *sr;
638     unsigned addr ;
639     char *sfmt;
640     int wait_ms = 1000;
641
642     invalidateCache(XMEM_CACHE);
643     invalidateCache(IMEM_CACHE);
644     invalidateCache(SREG_CACHE);
645     if (gaddr == 0) {
646       /* initial start, start & stop from address 0 */
647       //char buf[20];
648
649          // this program is setting up a bunch of breakpoints automatically
650          // at key places.  Like at startup & main() and other function
651          // entry points.  So we don't need to setup one here..
652       //sendSim("break 0x0\n");
653       //sleep(1);
654       //waitForSim();
655
656       sendSim("reset\n");
657       waitForSim(wait_ms, NULL);
658       sendSim("run 0x0\n");
659     } else      if (gaddr == -1) { /* resume */
660       sendSim ("run\n");
661       wait_ms = 100;
662     }
663     else        if (gaddr == 1 ) { /* nexti or next */
664       sendSim ("next\n");
665       wait_ms = 100;
666     }
667     else        if (gaddr == 2 ) { /* stepi or step */
668       sendSim ("step\n");
669       wait_ms = 100;
670     }
671     else  {
672       printf("Error, simGoTillBp > 0!\n");
673       exit(1);
674     }
675
676     waitForSim(wait_ms, NULL);
677
678     /* get the simulator response */
679     sr = simResponse();
680     /* check for errors */
681     while ( *sr )
682     {
683         while ( *sr && *sr != 'E' ) sr++ ;
684         if ( !*sr )
685             break;
686         if ( ! strncmp(sr,"Error:",6))
687         {
688             fputs(sr,stdout);
689             break;
690         }
691         sr++ ;
692     }
693
694     nointerrupt = 1;
695     /* get answer of stop command */
696     if ( userinterrupt )
697         waitForSim(wait_ms, NULL);
698
699     /* better solution: ask pc */
700     sendSim ("pc\n");
701     waitForSim(100, NULL);
702     sr = simResponse();
703     nointerrupt = 0;
704
705     gaddr = strtol(sr+3,0,0);
706     return gaddr;
707 }
708
709 /*-----------------------------------------------------------------*/
710 /* simReset - reset the simulator                                  */
711 /*-----------------------------------------------------------------*/
712 void simReset ()
713 {
714     invalidateCache(XMEM_CACHE);
715     invalidateCache(IMEM_CACHE);
716     invalidateCache(SREG_CACHE);
717     sendSim("res\n");
718     waitForSim(100,NULL);
719 }
720
721
722 /*-----------------------------------------------------------------*/
723 /* closeSimulator - close connection to simulator                  */
724 /*-----------------------------------------------------------------*/
725 void closeSimulator ()
726 {
727 #ifdef _WIN32
728     if ( ! simin || ! simout || INVALID_SOCKET == sock )
729 #else
730     if ( ! simin || ! simout || sock == -1 )
731 #endif
732     {
733         simactive = 0;
734         return;
735     }
736     simactive = 0;
737     sendSim("quit\n");
738     fclose (simin);
739     fclose (simout);
740     shutdown(sock,2);
741 #ifdef _WIN32
742     closesocket(sock);
743     sock = -1;
744     if (NULL != simPid)
745         TerminateProcess(simPid->hProcess, 0);
746     // Close process and thread handles.
747     CloseHandle(simPid->hProcess);
748     CloseHandle(simPid->hThread);
749 #else
750     close(sock);
751     sock = -1;
752     if ( simPid > 0 )
753         kill (simPid,SIGKILL);
754 #endif
755 }