1 /*-------------------------------------------------------------------------
2 simi.c - source file for simulator interaction
3 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999)
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
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.
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.
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 -------------------------------------------------------------------------*/
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>
42 #error "Cannot build debugger without socket support"
46 FILE *simin ; /* stream for simulator input */
47 FILE *simout; /* stream for simulator output */
50 SOCKET sock = INVALID_SOCKET;
51 PROCESS_INFORMATION *simPid = NULL;
53 int sock = -1; /* socket descriptor to comm with simulator */
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;
62 static memcache_t memCache[NMEM_CACHE];
64 /*-----------------------------------------------------------------*/
65 /* get data from memory cache/ load cache from simulator */
66 /*-----------------------------------------------------------------*/
67 static char *getMemCache(unsigned int addr,int cachenum, int size)
71 memcache_t *cache = &memCache[cachenum];
73 if ( cache->size <= 0 ||
75 cache->addr + cache->size < addr + size )
77 if ( cachenum == IMEM_CACHE )
79 sendSim("di 0x0 0xff\n");
81 else if ( cachenum == SREG_CACHE )
83 sendSim("ds 0x80 0xff\n");
85 else if ( cachenum == CMEM_CACHE )
87 #define CMEM_CACHE_MASK ((MAX_CACHE_SIZE >> 2) - 1)
88 laddr = addr & ~CMEM_CACHE_MASK;
89 sprintf(cache->buffer,"dump rom 0x%x 0x%x\n",laddr,laddr+CMEM_CACHE_MASK );
90 sendSim(cache->buffer);
94 laddr = addr & 0xffffffc0;
95 sprintf(cache->buffer,"dx 0x%x 0x%x\n",laddr,laddr+0xff );
96 sendSim(cache->buffer);
100 cache->addr = strtol(resp,0,0);
103 while ( *resp && *(resp+1) && *(resp+2))
105 /* cache is a stringbuffer with ascii data like
106 " 00 00 00 00 00 00 00 00"
110 /* skip thru the address part */
111 while (isxdigit(*resp)) resp++;
112 while ( *resp && *resp != '\n')
125 if ( cache->addr > addr ||
126 cache->addr + cache->size < addr + size )
129 return cache->buffer + (addr - cache->addr)*3;
132 /*-----------------------------------------------------------------*/
133 /* invalidate memory cache */
134 /*-----------------------------------------------------------------*/
135 static void invalidateCache( int cachenum )
137 memCache[cachenum].size = 0;
140 /*-----------------------------------------------------------------*/
141 /* waitForSim - wait till simulator is done its job */
142 /*-----------------------------------------------------------------*/
143 void waitForSim(int timeout_ms, char *expect)
148 Dprintf(D_simi, ("simi: waitForSim start(%d)\n", timeout_ms));
151 while ((ch = fgetc(simin)) > 0 ) {
155 Dprintf(D_simi, ("waitForSim(%d) got[%s]\n", timeout_ms, simibuff));
159 /*-----------------------------------------------------------------*/
160 /* openSimulator - create a pipe to talk to simulator */
161 /*-----------------------------------------------------------------*/
163 static void init_winsock(void)
165 static int is_initialized = 0;
172 // Initialize Winsock
173 if (0 != WSAStartup(MAKEWORD(2,2), &wsaData))
175 fprintf(stderr, "WSAStartup failed: %d\n", iResult);
181 static char *argsToCmdLine(char **args, int nargs)
186 char *cmd = Safe_malloc(CHUNCK);
189 for (i = 0; i < nargs; i++)
192 int argLen = strlen(args[i]);
194 if (NULL != strchr(args[i], ' '))
203 if (cmdPos + argLen >= cmdLen)
209 while (cmdPos + argLen >= cmdLen);
210 cmd = Safe_realloc(cmd, cmdLen);
225 memcpy(&cmd[cmdPos], args[i], argLen);
237 static PROCESS_INFORMATION *execSimulator(char **args, int nargs)
240 static PROCESS_INFORMATION pi;
241 char *cmdLine = argsToCmdLine(args, nargs);
243 memset(&si, 0, sizeof(si));
245 memset(&pi, 0, sizeof(pi));
247 // Start the child process.
248 if (!CreateProcess(NULL, // No module name (use command line)
249 cmdLine, // Command line
250 NULL, // Process handle not inheritable
251 NULL, // Thread handle not inheritable
252 FALSE, // Set handle inheritance to FALSE
253 0, // No creation flags
254 NULL, // Use parent's environment block
255 NULL, // Use parent's starting directory
256 &si, // Pointer to STARTUPINFO structure
257 &pi) // Pointer to PROCESS_INFORMATION structure
261 printf( "CreateProcess failed (%d).\n", GetLastError() );
269 void openSimulator (char **args, int nargs)
271 struct sockaddr_in sin;
278 Dprintf(D_simi, ("simi: openSimulator\n"));
280 if (D_simi & sdcdbDebug)
282 printf("simi: openSimulator: ");
283 for (i=0; i < nargs; i++ )
285 printf("arg%d: %s ",i,args[i]);
290 invalidateCache(XMEM_CACHE);
291 invalidateCache(IMEM_CACHE);
292 invalidateCache(SREG_CACHE);
293 invalidateCache(CMEM_CACHE);
295 if (INVALID_SOCKET == (sock = WSASocket(PF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0))) {
296 fprintf(stderr, "cannot create socket: %d\n", WSAGetLastError());
300 memset(&sin,0,sizeof(sin));
301 sin.sin_family = AF_INET;
302 sin.sin_addr.s_addr = inet_addr("127.0.0.1");
303 sin.sin_port = htons(9756);
306 /* connect to the simulator */
307 if (SOCKET_ERROR == connect(sock, (struct sockaddr *)&sin, sizeof(sin)))
309 /* if failed then wait 1 second & try again
310 do this for 10 secs only */
314 simPid = execSimulator(args, nargs);
319 perror("connect failed :");
323 fh = _open_osfhandle((intptr_t)sock, _O_TEXT);
326 perror("cannot _open_osfhandle");
330 /* go the socket now turn it into a file handle */
331 if (!(simin = fdopen(fh, "r")))
333 perror("cannot open socket for read");
337 fh = _open_osfhandle((intptr_t)sock, _O_TEXT);
340 perror("cannot _open_osfhandle");
344 if (!(simout = fdopen(fh, "w")))
346 perror("cannot open socket for write");
349 /* now that we have opened, wait for the prompt */
350 waitForSim(200, NULL);
354 static int execSimulator(char **args, int nargs)
356 if ((simPid = fork()))
358 Dprintf(D_simi, ("simi: simulator pid %d\n",(int) simPid));
362 /* we are in the child process : start the simulator */
363 signal(SIGINT , SIG_IGN );
364 signal(SIGABRT, SIG_IGN );
365 signal(SIGHUP , SIG_IGN );
366 signal(SIGCHLD, SIG_IGN );
368 if (execvp(args[0],args) < 0)
370 perror("cannot exec simulator");
377 void openSimulator (char **args, int nargs)
379 struct sockaddr_in sin;
382 Dprintf(D_simi, ("simi: openSimulator\n"));
384 if (D_simi & sdcdbDebug)
386 printf("simi: openSimulator: ");
387 for (i=0; i < nargs; i++ )
389 printf("arg%d: %s ",i,args[i]);
394 invalidateCache(XMEM_CACHE);
395 invalidateCache(IMEM_CACHE);
396 invalidateCache(SREG_CACHE);
397 invalidateCache(CMEM_CACHE);
399 if ((sock = socket(AF_INET,SOCK_STREAM,0)) < 0)
401 perror("cannot create socket");
405 memset(&sin,0,sizeof(sin));
406 sin.sin_family = AF_INET;
407 sin.sin_addr.s_addr = inet_addr("127.0.0.1");
408 sin.sin_port = htons(9756);
411 /* connect to the simulator */
412 if (connect(sock,(struct sockaddr *) &sin, sizeof(sin)) < 0)
414 /* if failed then wait 1 second & try again
415 do this for 10 secs only */
420 simPid = execSimulator(args, nargs);
426 perror("connect failed :");
429 /* go the socket now turn it into a file handle */
430 if (!(simin = fdopen(sock,"r")))
432 fprintf(stderr,"cannot open socket for read\n");
436 if (!(simout = fdopen(sock,"w")))
438 fprintf(stderr,"cannot open socket for write\n");
441 /* now that we have opened, wait for the prompt */
442 waitForSim(200,NULL);
447 /*-----------------------------------------------------------------*/
448 /* simResponse - returns buffer to simulator's response */
449 /*-----------------------------------------------------------------*/
450 char *simResponse(void)
455 /*-----------------------------------------------------------------*/
456 /* sendSim - sends a command to the simuator */
457 /*-----------------------------------------------------------------*/
458 void sendSim(char *s)
463 Dprintf(D_simi, ("simi: sendSim-->%s", s)); // s has LF at end already
469 static int getMemString(char *buffer, char wrflag,
470 unsigned int *addr, char mem, int size )
472 int cachenr = NMEM_CACHE;
484 case 'A': /* External stack */
485 case 'F': /* External ram */
486 case 'P': /* Pdata space */
488 cachenr = XMEM_CACHE;
491 case 'D': /* Code / static segment */
493 cachenr = CMEM_CACHE;
495 case 'B': /* Internal stack */
496 case 'E': /* Internal ram (lower 128) bytes */
497 case 'G': /* Internal ram */
499 cachenr = IMEM_CACHE;
501 case 'H': /* Bit addressable */
502 case 'J': /* SBIT space */
508 sprintf(buffer,"%s 0x%x\n",cmd,*addr);
511 case 'I': /* SFR space */
513 cachenr = SREG_CACHE;
515 case 'R': /* Register space */
517 /* get register bank */
518 cachenr = simGetValue (0xd0,'I',1);
519 *addr += cachenr & 0x18 ;
520 cachenr = IMEM_CACHE;
523 case 'Z': /* undefined space code */
527 sprintf(buffer,"%s %s 0x%x\n",cmd,prefix,*addr);
529 sprintf(buffer,"%s %s 0x%x 0x%x\n",cmd,prefix,*addr,*addr+size-1);
533 void simSetPC( unsigned int addr )
536 sprintf(buffer,"pc %d\n", addr);
538 waitForSim(100,NULL);
542 unsigned int simGetPC(void)
546 waitForSim(100,NULL);
549 return strtol(sr+3,0,0);
552 int simSetValue (unsigned int addr,char mem, int size, unsigned long val)
561 cachenr = getMemString(buffer,1,&addr,mem,size);
562 if ( cachenr < NMEM_CACHE )
564 invalidateCache(cachenr);
566 s = buffer + strlen(buffer) -1;
567 for ( i = 0 ; i < size ; i++ )
569 sprintf(s," 0x%lx", val & 0xff);
575 waitForSim(100,NULL);
581 /*-----------------------------------------------------------------*/
582 /* simGetValue - get value @ address for mem space */
583 /*-----------------------------------------------------------------*/
584 unsigned long simGetValue (unsigned int addr,char mem, int size)
586 unsigned int b[4] = {0,0,0,0}; /* can be a max of four bytes long */
594 cachenr = getMemString(buffer,0,&addr,mem,size);
597 if ( cachenr < NMEM_CACHE )
599 resp = getMemCache(addr,cachenr,size);
603 /* create the simulator command */
605 waitForSim(100,NULL);
606 resp = simResponse();
608 /* got the response we need to parse it the response
610 [address] [v] [v] [v] ... special case in
611 case of bit variables which case it becomes
612 [address] [assembler bit address] [v] */
613 /* first skip thru white space */
614 resp = trim_left(resp);
616 if (strncmp(resp, "0x",2) == 0)
619 /* skip thru the address part */
620 while (isxdigit(*resp)) resp++;
623 /* make the branch for bit variables */
624 if ( cachenr == BIT_CACHE)
626 /* skip until newline */
627 while (*resp && *resp != '\n' ) resp++ ;
628 if ( *--resp != '0' )
633 for (i = 0 ; i < size ; i++ )
635 /* skip white space */
636 resp = trim_left(resp);
638 b[i] = strtol(resp,&resp,16);
642 return b[0] | b[1] << 8 | b[2] << 16 | b[3] << 24 ;
646 /*-----------------------------------------------------------------*/
647 /* simSetBP - set break point for a given address */
648 /*-----------------------------------------------------------------*/
649 void simSetBP (unsigned int addr)
653 sprintf(buff,"break 0x%x\n",addr);
655 waitForSim(100,NULL);
658 /*-----------------------------------------------------------------*/
659 /* simClearBP - clear a break point */
660 /*-----------------------------------------------------------------*/
661 void simClearBP (unsigned int addr)
665 sprintf(buff,"clear 0x%x\n",addr);
667 waitForSim(100,NULL);
670 /*-----------------------------------------------------------------*/
671 /* simLoadFile - load the simulator file */
672 /*-----------------------------------------------------------------*/
673 void simLoadFile (char *s)
677 sprintf(buff,"file \"%s\"\n",s);
680 waitForSim(500,NULL);
683 /*-----------------------------------------------------------------*/
684 /* simGoTillBp - send 'go' to simulator till a bp then return addr */
685 /*-----------------------------------------------------------------*/
686 unsigned int simGoTillBp ( unsigned int gaddr)
693 invalidateCache(XMEM_CACHE);
694 invalidateCache(IMEM_CACHE);
695 invalidateCache(SREG_CACHE);
697 /* initial start, start & stop from address 0 */
700 // this program is setting up a bunch of breakpoints automatically
701 // at key places. Like at startup & main() and other function
702 // entry points. So we don't need to setup one here..
703 //sendSim("break 0x0\n");
708 waitForSim(wait_ms, NULL);
709 sendSim("run 0x0\n");
710 } else if (gaddr == -1) { /* resume */
714 else if (gaddr == 1 ) { /* nexti or next */
718 else if (gaddr == 2 ) { /* stepi or step */
723 printf("Error, simGoTillBp > 0!\n");
727 waitForSim(wait_ms, NULL);
729 /* get the simulator response */
731 /* check for errors */
734 while ( *sr && *sr != 'E' ) sr++ ;
737 if ( ! strncmp(sr,"Error:",6))
746 /* get answer of stop command */
748 waitForSim(wait_ms, NULL);
750 /* better solution: ask pc */
752 waitForSim(100, NULL);
756 gaddr = strtol(sr+3,0,0);
760 /*-----------------------------------------------------------------*/
761 /* simReset - reset the simulator */
762 /*-----------------------------------------------------------------*/
765 invalidateCache(XMEM_CACHE);
766 invalidateCache(IMEM_CACHE);
767 invalidateCache(SREG_CACHE);
768 invalidateCache(CMEM_CACHE);
770 waitForSim(100,NULL);
774 /*-----------------------------------------------------------------*/
775 /* closeSimulator - close connection to simulator */
776 /*-----------------------------------------------------------------*/
777 void closeSimulator (void)
780 if ( ! simin || ! simout || INVALID_SOCKET == sock )
782 if ( ! simin || ! simout || sock == -1 )
797 TerminateProcess(simPid->hProcess, 0);
798 // Close process and thread handles.
799 CloseHandle(simPid->hProcess);
800 CloseHandle(simPid->hThread);
805 kill (simPid,SIGKILL);