Extract call stack from running machine.
[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 static void init_winsock(void)
157 {
158     static int is_initialized = 0;
159
160     if (!is_initialized)
161     {
162         WSADATA wsaData;
163         int iResult;
164
165         // Initialize Winsock
166         if (0 != WSAStartup(MAKEWORD(2,2), &wsaData))
167         {
168             fprintf(stderr, "WSAStartup failed: %d\n", iResult);
169             exit(1);
170         }
171     }
172 }
173
174 static char *argsToCmdLine(char **args, int nargs)
175 {
176 #define CHUNCK  256
177     int i;
178     int cmdPos = 0;
179     char *cmd = Safe_malloc(CHUNCK);
180     int cmdLen = CHUNCK;
181
182     for (i = 0; i < nargs; i++)
183     {
184         int quote = 0;
185         int argLen = strlen(args[i]);
186
187         if (NULL != strchr(args[i], ' '))
188         {
189             quote = 1;
190             argLen += 2;
191         }
192
193         if (0 < i)
194             ++argLen;
195
196         if (cmdPos + argLen >= cmdLen)
197         {
198             do
199             {
200                 cmdLen += cmdLen;
201             }
202             while (cmdPos + argLen >= cmdLen);
203             cmd = Safe_realloc(cmd, cmdLen);
204         }
205
206         if (0 < i)
207         {
208             cmd[cmdPos++] = ' ';
209             --argLen;
210         }
211
212         if (quote)
213         {
214             cmd[cmdPos++] = '"';
215             --argLen;
216         }
217
218         memcpy(&cmd[cmdPos], args[i], argLen);
219         cmdPos += argLen;
220
221         if (quote)
222             cmd[cmdPos++] = '"';
223     }
224
225     cmd[cmdPos] = '\0';
226
227     return cmd;
228 }
229
230 static PROCESS_INFORMATION *execSimulator(char **args, int nargs)
231 {
232     STARTUPINFO si;
233     static PROCESS_INFORMATION pi;
234     char *cmdLine = argsToCmdLine(args, nargs);
235
236     memset(&si, 0, sizeof(si));
237     si.cb = sizeof(si);
238     memset(&pi, 0, sizeof(pi));
239
240     // Start the child process.
241     if (!CreateProcess(NULL,   // No module name (use command line)
242         cmdLine, // Command line
243         NULL,           // Process handle not inheritable
244         NULL,           // Thread handle not inheritable
245         FALSE,          // Set handle inheritance to FALSE
246         0,              // No creation flags
247         NULL,           // Use parent's environment block
248         NULL,           // Use parent's starting directory
249         &si,            // Pointer to STARTUPINFO structure
250         &pi)            // Pointer to PROCESS_INFORMATION structure
251     )
252     {
253         Safe_free(cmdLine);
254         printf( "CreateProcess failed (%d).\n", GetLastError() );
255         return NULL;
256     }
257
258     Safe_free(cmdLine);
259     return &pi;
260 }
261
262 void openSimulator (char **args, int nargs)
263 {
264     struct sockaddr_in sin;
265     int retry = 0;
266     int i;
267     int fh;
268
269     init_winsock();
270
271     Dprintf(D_simi, ("simi: openSimulator\n"));
272 #ifdef SDCDB_DEBUG
273     if (D_simi & sdcdbDebug)
274     {
275         printf("simi: openSimulator: ");
276         for (i=0; i < nargs; i++ )
277         {
278             printf("arg%d: %s ",i,args[i]);
279         }
280         printf("\n");
281     }
282 #endif
283     invalidateCache(XMEM_CACHE);
284     invalidateCache(IMEM_CACHE);
285     invalidateCache(SREG_CACHE);
286
287     if (INVALID_SOCKET == (sock = WSASocket(PF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0))) {
288         fprintf(stderr, "cannot create socket: %d\n", WSAGetLastError());
289         exit(1);
290     }
291
292     memset(&sin,0,sizeof(sin));
293     sin.sin_family = AF_INET;
294     sin.sin_addr.s_addr = inet_addr("127.0.0.1");
295     sin.sin_port = htons(9756);
296
297  try_connect:
298     /* connect to the simulator */
299     if (SOCKET_ERROR == connect(sock, (struct sockaddr *)&sin, sizeof(sin)))
300     {
301         /* if failed then wait 1 second & try again
302            do this for 10 secs only */
303         if (retry < 10)
304         {
305             if ( !retry )
306                 simPid = execSimulator(args, nargs);
307             retry ++;
308             Sleep(1000);
309             goto try_connect;
310         }
311         perror("connect failed :");
312         exit(1);
313     }
314
315     fh = _open_osfhandle((intptr_t)sock, _O_TEXT);
316     if (-1 == fh)
317     {
318         perror("cannot _open_osfhandle");
319         exit(1);
320     }
321
322     /* go the socket now turn it into a file handle */
323     if (!(simin = fdopen(fh, "r")))
324     {
325         perror("cannot open socket for read");
326         exit(1);
327     }
328
329     fh = _open_osfhandle((intptr_t)sock, _O_TEXT);
330     if (-1 == fh)
331     {
332         perror("cannot _open_osfhandle");
333         exit(1);
334     }
335
336     if (!(simout = fdopen(fh, "w")))
337     {
338         perror("cannot open socket for write");
339         exit(1);
340     }
341     /* now that we have opened, wait for the prompt */
342     waitForSim(200, NULL);
343     simactive = 1;
344 }
345 #else
346 static int execSimulator(char **args, int nargs)
347 {
348     if ((simPid = fork()))
349     {
350         Dprintf(D_simi, ("simi: simulator pid %d\n",(int) simPid));
351     }
352     else
353     {
354         /* we are in the child process : start the simulator */
355         signal(SIGINT , SIG_IGN );
356         signal(SIGABRT, SIG_IGN );
357         signal(SIGHUP , SIG_IGN );
358         signal(SIGCHLD, SIG_IGN );
359
360         if (execvp(args[0],args) < 0)
361         {
362             perror("cannot exec simulator");
363             exit(1);
364         }
365     }
366     return simPid;
367 }
368
369 void openSimulator (char **args, int nargs)
370 {
371     struct sockaddr_in sin;
372     int retry = 0;
373     int i;
374     Dprintf(D_simi, ("simi: openSimulator\n"));
375 #ifdef SDCDB_DEBUG
376     if (D_simi & sdcdbDebug)
377     {
378         printf("simi: openSimulator: ");
379         for (i=0; i < nargs; i++ )
380         {
381             printf("arg%d: %s ",i,args[i]);
382         }
383         printf("\n");
384     }
385 #endif
386     invalidateCache(XMEM_CACHE);
387     invalidateCache(IMEM_CACHE);
388     invalidateCache(SREG_CACHE);
389
390     if ((sock = socket(AF_INET,SOCK_STREAM,0)) < 0)
391     {
392         perror("cannot create socket");
393         exit(1);
394     }
395
396     memset(&sin,0,sizeof(sin));
397     sin.sin_family = AF_INET;
398     sin.sin_addr.s_addr = inet_addr("127.0.0.1");
399     sin.sin_port = htons(9756);
400
401  try_connect:
402     /* connect to the simulator */
403     if (connect(sock,(struct sockaddr *) &sin, sizeof(sin)) < 0)
404     {
405         /* if failed then wait 1 second & try again
406            do this for 10 secs only */
407         if (retry < 10)
408         {
409             if ( !retry )
410             {
411                 simPid = execSimulator(args, nargs);
412             }
413             retry ++;
414             sleep (1);
415             goto try_connect;
416         }
417         perror("connect failed :");
418         exit(1);
419     }
420     /* go the socket now turn it into a file handle */
421     if (!(simin = fdopen(sock,"r")))
422     {
423         fprintf(stderr,"cannot open socket for read\n");
424         exit(1);
425     }
426
427     if (!(simout = fdopen(sock,"w")))
428     {
429         fprintf(stderr,"cannot open socket for write\n");
430         exit(1);
431     }
432     /* now that we have opened, wait for the prompt */
433     waitForSim(200,NULL);
434     simactive = 1;
435 }
436 #endif
437
438 /*-----------------------------------------------------------------*/
439 /* simResponse - returns buffer to simulator's response            */
440 /*-----------------------------------------------------------------*/
441 char *simResponse(void)
442 {
443     return simibuff;
444 }
445
446 /*-----------------------------------------------------------------*/
447 /* sendSim - sends a command to the simuator                 */
448 /*-----------------------------------------------------------------*/
449 void sendSim(char *s)
450 {
451     if ( ! simout )
452         return;
453
454     Dprintf(D_simi, ("simi: sendSim-->%s", s));  // s has LF at end already
455     fputs(s,simout);
456     fflush(simout);
457 }
458
459
460 static int getMemString(char *buffer, char wrflag,
461                         unsigned int *addr, char mem, int size )
462 {
463     int cachenr = NMEM_CACHE;
464     char *prefix;
465     char *cmd ;
466
467     if ( wrflag )
468         cmd = "set mem";
469     else
470         cmd = "dump";
471     buffer[0] = '\0' ;
472
473     switch (mem)
474     {
475         case 'A': /* External stack */
476         case 'F': /* External ram */
477             prefix = "xram";
478             cachenr = XMEM_CACHE;
479             break;
480         case 'C': /* Code */
481         case 'D': /* Code / static segment */
482             prefix = "rom";
483             break;
484         case 'B': /* Internal stack */
485         case 'E': /* Internal ram (lower 128) bytes */
486         case 'G': /* Internal ram */
487             prefix = "iram";
488             cachenr = IMEM_CACHE;
489             break;
490         case 'H': /* Bit addressable */
491         case 'J': /* SBIT space */
492             cachenr = BIT_CACHE;
493             if ( wrflag )
494             {
495                 cmd = "set bit";
496             }
497             sprintf(buffer,"%s 0x%x\n",cmd,*addr);
498             return cachenr;
499             break;
500         case 'I': /* SFR space */
501             prefix = "sfr" ;
502             cachenr = SREG_CACHE;
503             break;
504         case 'R': /* Register space */
505             prefix = "iram";
506             /* get register bank */
507             cachenr = simGetValue (0xd0,'I',1);
508             *addr  += cachenr & 0x18 ;
509             cachenr = IMEM_CACHE;
510             break;
511         default:
512         case 'Z': /* undefined space code */
513             return cachenr;
514     }
515     if ( wrflag )
516         sprintf(buffer,"%s %s 0x%x\n",cmd,prefix,*addr);
517     else
518         sprintf(buffer,"%s %s 0x%x 0x%x\n",cmd,prefix,*addr,*addr+size-1);
519     return cachenr;
520 }
521
522 void simSetPC( unsigned int addr )
523 {
524     char buffer[40];
525     sprintf(buffer,"pc %d\n", addr);
526     sendSim(buffer);
527     waitForSim(100,NULL);
528     simResponse();
529 }
530
531 unsigned int simGetPC(void)
532 {
533     char *sr;
534     sendSim("pc\n");
535     waitForSim(100,NULL);
536     simResponse();
537     sr = simResponse();
538     return strtol(sr+3,0,0);
539 }
540     
541 int simSetValue (unsigned int addr,char mem, int size, unsigned long val)
542 {
543     char cachenr, i;
544     char buffer[40];
545     char *s;
546
547     if ( size <= 0 )
548         return 0;
549
550     cachenr = getMemString(buffer,1,&addr,mem,size);
551     if ( cachenr < NMEM_CACHE )
552     {
553         invalidateCache(cachenr);
554     }
555     s = buffer + strlen(buffer) -1;
556     for ( i = 0 ; i < size ; i++ )
557     {
558         sprintf(s," 0x%lx", val & 0xff);
559         s += strlen(s);
560         val >>= 8;
561     }
562     sprintf(s,"\n");
563     sendSim(buffer);
564     waitForSim(100,NULL);
565     simResponse();
566     return 0;
567 }
568
569
570 /*-----------------------------------------------------------------*/
571 /* simGetValue - get value @ address for mem space                 */
572 /*-----------------------------------------------------------------*/
573 unsigned long simGetValue (unsigned int addr,char mem, int size)
574 {
575     unsigned int b[4] = {0,0,0,0}; /* can be a max of four bytes long */
576     char cachenr, i;
577     char buffer[40];
578     char *resp;
579
580     if ( size <= 0 )
581         return 0;
582
583     cachenr = getMemString(buffer,0,&addr,mem,size);
584
585     resp = NULL;
586     if ( cachenr < NMEM_CACHE )
587     {
588         resp = getMemCache(addr,cachenr,size);
589     }
590     if ( !resp )
591     {
592         /* create the simulator command */
593         sendSim(buffer);
594         waitForSim(100,NULL);
595         resp = simResponse();
596
597         /* got the response we need to parse it the response
598            is of the form
599            [address] [v] [v] [v] ... special case in
600            case of bit variables which case it becomes
601            [address] [assembler bit address] [v] */
602         /* first skip thru white space */
603         resp = trim_left(resp);
604
605         if (strncmp(resp, "0x",2) == 0)
606             resp += 2;
607
608         /* skip thru the address part */
609         while (isxdigit(*resp)) resp++;
610
611     }
612     /* make the branch for bit variables */
613     if ( cachenr == BIT_CACHE)
614     {
615         /* skip until newline */
616         while (*resp && *resp != '\n' ) resp++ ;
617         if ( *--resp != '0' )
618             b[0] = 1;
619     }
620     else
621     {
622         for (i = 0 ; i < size ; i++ )
623         {
624             /* skip white space */
625             resp = trim_left(resp);
626
627             b[i] = strtol(resp,&resp,16);
628         }
629     }
630
631     return b[0] | b[1] << 8 | b[2] << 16 | b[3] << 24 ;
632
633 }
634
635 /*-----------------------------------------------------------------*/
636 /* simSetBP - set break point for a given address                  */
637 /*-----------------------------------------------------------------*/
638 void simSetBP (unsigned int addr)
639 {
640     char buff[50];
641
642     sprintf(buff,"break 0x%x\n",addr);
643     sendSim(buff);
644     waitForSim(100,NULL);
645 }
646
647 /*-----------------------------------------------------------------*/
648 /* simClearBP - clear a break point                                */
649 /*-----------------------------------------------------------------*/
650 void simClearBP (unsigned int addr)
651 {
652     char buff[50];
653
654     sprintf(buff,"clear 0x%x\n",addr);
655     sendSim(buff);
656     waitForSim(100,NULL);
657 }
658
659 /*-----------------------------------------------------------------*/
660 /* simLoadFile - load the simulator file                           */
661 /*-----------------------------------------------------------------*/
662 void simLoadFile (char *s)
663 {
664     char buff[128];
665
666     sprintf(buff,"file \"%s\"\n",s);
667     printf("%s",buff);
668     sendSim(buff);
669     waitForSim(500,NULL);
670 }
671
672 /*-----------------------------------------------------------------*/
673 /* simGoTillBp - send 'go' to simulator till a bp then return addr */
674 /*-----------------------------------------------------------------*/
675 unsigned int simGoTillBp ( unsigned int gaddr)
676 {
677     char *sr;
678     unsigned addr ;
679     char *sfmt;
680     int wait_ms = 1000;
681
682     invalidateCache(XMEM_CACHE);
683     invalidateCache(IMEM_CACHE);
684     invalidateCache(SREG_CACHE);
685     if (gaddr == 0) {
686         /* initial start, start & stop from address 0 */
687         //char buf[20];
688
689            // this program is setting up a bunch of breakpoints automatically
690            // at key places.  Like at startup & main() and other function
691            // entry points.  So we don't need to setup one here..
692         //sendSim("break 0x0\n");
693         //sleep(1);
694         //waitForSim();
695
696         sendSim("reset\n");
697         waitForSim(wait_ms, NULL);
698         sendSim("run 0x0\n");
699     } else      if (gaddr == -1) { /* resume */
700         sendSim ("run\n");
701         wait_ms = 100;
702     }
703     else        if (gaddr == 1 ) { /* nexti or next */
704         sendSim ("next\n");
705         wait_ms = 100;
706     }
707     else        if (gaddr == 2 ) { /* stepi or step */
708         sendSim ("step\n");
709         wait_ms = 100;
710     }
711     else  {
712         printf("Error, simGoTillBp > 0!\n");
713         exit(1);
714     }
715
716     waitForSim(wait_ms, NULL);
717
718     /* get the simulator response */
719     sr = simResponse();
720     /* check for errors */
721     while ( *sr )
722     {
723         while ( *sr && *sr != 'E' ) sr++ ;
724         if ( !*sr )
725             break;
726         if ( ! strncmp(sr,"Error:",6))
727         {
728             fputs(sr,stdout);
729             break;
730         }
731         sr++ ;
732     }
733
734     nointerrupt = 1;
735     /* get answer of stop command */
736     if ( userinterrupt )
737         waitForSim(wait_ms, NULL);
738
739     /* better solution: ask pc */
740     sendSim ("pc\n");
741     waitForSim(100, NULL);
742     sr = simResponse();
743     nointerrupt = 0;
744
745     gaddr = strtol(sr+3,0,0);
746     return gaddr;
747 }
748
749 /*-----------------------------------------------------------------*/
750 /* simReset - reset the simulator                                  */
751 /*-----------------------------------------------------------------*/
752 void simReset (void)
753 {
754     invalidateCache(XMEM_CACHE);
755     invalidateCache(IMEM_CACHE);
756     invalidateCache(SREG_CACHE);
757     sendSim("res\n");
758     waitForSim(100,NULL);
759 }
760
761
762 /*-----------------------------------------------------------------*/
763 /* closeSimulator - close connection to simulator                  */
764 /*-----------------------------------------------------------------*/
765 void closeSimulator (void)
766 {
767 #ifdef _WIN32
768     if ( ! simin || ! simout || INVALID_SOCKET == sock )
769 #else
770     if ( ! simin || ! simout || sock == -1 )
771 #endif
772     {
773         simactive = 0;
774         return;
775     }
776     simactive = 0;
777     sendSim("quit\n");
778     fclose (simin);
779     fclose (simout);
780     shutdown(sock,2);
781 #ifdef _WIN32
782     closesocket(sock);
783     sock = -1;
784     if (NULL != simPid)
785         TerminateProcess(simPid->hProcess, 0);
786     // Close process and thread handles.
787     CloseHandle(simPid->hProcess);
788     CloseHandle(simPid->hThread);
789 #else
790     close(sock);
791     sock = -1;
792     if ( simPid > 0 )
793         kill (simPid,SIGKILL);
794 #endif
795 }