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");
87 laddr = addr & 0xffffffc0;
88 sprintf(cache->buffer,"dx 0x%x 0x%x\n",laddr,laddr+0xff );
89 sendSim(cache->buffer);
93 cache->addr = strtol(resp,0,0);
96 while ( *resp && *(resp+1) && *(resp+2))
98 /* cache is a stringbuffer with ascii data like
99 " 00 00 00 00 00 00 00 00"
103 /* skip thru the address part */
104 while (isxdigit(*resp)) resp++;
105 while ( *resp && *resp != '\n')
118 if ( cache->addr > addr ||
119 cache->addr + cache->size < addr + size )
122 return cache->buffer + (addr - cache->addr)*3;
125 /*-----------------------------------------------------------------*/
126 /* invalidate memory cache */
127 /*-----------------------------------------------------------------*/
128 static void invalidateCache( int cachenum )
130 memCache[cachenum].size = 0;
133 /*-----------------------------------------------------------------*/
134 /* waitForSim - wait till simulator is done its job */
135 /*-----------------------------------------------------------------*/
136 void waitForSim(int timeout_ms, char *expect)
141 Dprintf(D_simi, ("simi: waitForSim start(%d)\n", timeout_ms));
144 while ((ch = fgetc(simin)) > 0 ) {
148 Dprintf(D_simi, ("waitForSim(%d) got[%s]\n", timeout_ms, simibuff));
152 /*-----------------------------------------------------------------*/
153 /* openSimulator - create a pipe to talk to simulator */
154 /*-----------------------------------------------------------------*/
156 char *argsToCmdLine(char **args, int nargs)
161 char *cmd = Safe_malloc(CHUNCK);
164 for (i = 0; i < nargs; i++)
167 int argLen = strlen(args[i]);
169 if (NULL != strchr(args[i], ' '))
178 if (cmdPos + argLen >= cmdLen)
184 while (cmdPos + argLen >= cmdLen);
185 cmd = Safe_realloc(cmd, cmdLen);
200 memcpy(&cmd[cmdPos], args[i], argLen);
212 PROCESS_INFORMATION *execSimulator(char **args, int nargs)
215 static PROCESS_INFORMATION pi;
216 char *cmdLine = argsToCmdLine(args, nargs);
218 memset(&si, 0, sizeof(si));
220 memset(&pi, 0, sizeof(pi));
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
236 printf( "CreateProcess failed (%d).\n", GetLastError() );
244 void openSimulator (char **args, int nargs)
246 struct sockaddr_in sin;
250 Dprintf(D_simi, ("simi: openSimulator\n"));
252 if (D_simi & sdcdbDebug)
254 printf("simi: openSimulator: ");
255 for (i=0; i < nargs; i++ )
257 printf("arg%d: %s ",i,args[i]);
262 invalidateCache(XMEM_CACHE);
263 invalidateCache(IMEM_CACHE);
264 invalidateCache(SREG_CACHE);
267 sock = WSASocket(PF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);
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);
274 /* connect to the simulator */
275 if (INVALID_SOCKET == connect(sock,(struct sockaddr *) &sin, sizeof(sin)))
277 /* if failed then wait 1 second & try again
278 do this for 10 secs only */
282 simPid = execSimulator(args, nargs);
287 perror("connect failed :");
290 fh = _open_osfhandle((intptr_t)socket, _O_TEXT);
293 fprintf(stderr, "cannot _open_osfhandle\n");
297 /* go the socket now turn it into a file handle */
298 if (!(simin = fdopen(sock,"r")))
300 fprintf(stderr,"cannot open socket for read\n");
304 fh = _open_osfhandle((intptr_t)socket, _O_TEXT);
307 fprintf(stderr, "cannot _open_osfhandle\n");
311 if (!(simout = fdopen(sock,"w")))
313 fprintf(stderr,"cannot open socket for write\n");
316 /* now that we have opened, wait for the prompt */
317 waitForSim(200,NULL);
321 int execSimulator(char **args, int nargs)
323 if ((simPid = fork()))
325 Dprintf(D_simi, ("simi: simulator pid %d\n",(int) simPid));
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 );
335 if (execvp(args[0],args) < 0)
337 perror("cannot exec simulator");
343 void openSimulator (char **args, int nargs)
345 struct sockaddr_in sin;
348 Dprintf(D_simi, ("simi: openSimulator\n"));
350 if (D_simi & sdcdbDebug)
352 printf("simi: openSimulator: ");
353 for (i=0; i < nargs; i++ )
355 printf("arg%d: %s ",i,args[i]);
360 invalidateCache(XMEM_CACHE);
361 invalidateCache(IMEM_CACHE);
362 invalidateCache(SREG_CACHE);
365 sock = socket(AF_INET,SOCK_STREAM,0);
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);
372 /* connect to the simulator */
373 if (connect(sock,(struct sockaddr *) &sin, sizeof(sin)) < 0)
375 /* if failed then wait 1 second & try again
376 do this for 10 secs only */
381 simPid = execSimulator(args, nargs);
387 perror("connect failed :");
390 /* go the socket now turn it into a file handle */
391 if (!(simin = fdopen(sock,"r")))
393 fprintf(stderr,"cannot open socket for read\n");
397 if (!(simout = fdopen(sock,"w")))
399 fprintf(stderr,"cannot open socket for write\n");
402 /* now that we have opened, wait for the prompt */
403 waitForSim(200,NULL);
408 /*-----------------------------------------------------------------*/
409 /* simResponse - returns buffer to simulator's response */
410 /*-----------------------------------------------------------------*/
416 /*-----------------------------------------------------------------*/
417 /* sendSim - sends a command to the simuator */
418 /*-----------------------------------------------------------------*/
419 void sendSim(char *s)
424 Dprintf(D_simi, ("simi: sendSim-->%s", s)); // s has LF at end already
430 static int getMemString(char *buffer, char wrflag,
431 unsigned int *addr, char mem, int size )
433 int cachenr = NMEM_CACHE;
445 case 'A': /* External stack */
446 case 'F': /* External ram */
448 cachenr = XMEM_CACHE;
451 case 'D': /* Code / static segment */
454 case 'B': /* Internal stack */
455 case 'E': /* Internal ram (lower 128) bytes */
456 case 'G': /* Internal ram */
458 cachenr = IMEM_CACHE;
460 case 'H': /* Bit addressable */
461 case 'J': /* SBIT space */
467 sprintf(buffer,"%s 0x%x\n",cmd,*addr);
470 case 'I': /* SFR space */
472 cachenr = SREG_CACHE;
474 case 'R': /* Register space */
476 /* get register bank */
477 cachenr = simGetValue (0xd0,'I',1);
478 *addr += cachenr & 0x18 ;
479 cachenr = IMEM_CACHE;
482 case 'Z': /* undefined space code */
486 sprintf(buffer,"%s %s 0x%x\n",cmd,prefix,*addr);
488 sprintf(buffer,"%s %s 0x%x 0x%x\n",cmd,prefix,*addr,*addr+size-1);
492 void simSetPC( unsigned int addr )
495 sprintf(buffer,"pc %d\n", addr);
497 waitForSim(100,NULL);
501 int simSetValue (unsigned int addr,char mem, int size, unsigned long val)
510 cachenr = getMemString(buffer,1,&addr,mem,size);
511 if ( cachenr < NMEM_CACHE )
513 invalidateCache(cachenr);
515 s = buffer + strlen(buffer) -1;
516 for ( i = 0 ; i < size ; i++ )
518 sprintf(s," 0x%x", val & 0xff);
524 waitForSim(100,NULL);
530 /*-----------------------------------------------------------------*/
531 /* simGetValue - get value @ address for mem space */
532 /*-----------------------------------------------------------------*/
533 unsigned long simGetValue (unsigned int addr,char mem, int size)
535 unsigned int b[4] = {0,0,0,0}; /* can be a max of four bytes long */
543 cachenr = getMemString(buffer,0,&addr,mem,size);
546 if ( cachenr < NMEM_CACHE )
548 resp = getMemCache(addr,cachenr,size);
552 /* create the simulator command */
554 waitForSim(100,NULL);
555 resp = simResponse();
557 /* got the response we need to parse it the response
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++ ;
565 if (strncmp(resp, "0x",2) == 0)
568 /* skip thru the address part */
569 while (isxdigit(*resp)) resp++;
572 /* make the branch for bit variables */
573 if ( cachenr == BIT_CACHE)
575 /* skip until newline */
576 while (*resp && *resp != '\n' ) resp++ ;
577 if ( *--resp != '0' )
582 for (i = 0 ; i < size ; i++ )
584 /* skip white space */
585 while (isspace(*resp)) resp++ ;
587 b[i] = strtol(resp,&resp,16);
591 return b[0] | b[1] << 8 | b[2] << 16 | b[3] << 24 ;
595 /*-----------------------------------------------------------------*/
596 /* simSetBP - set break point for a given address */
597 /*-----------------------------------------------------------------*/
598 void simSetBP (unsigned int addr)
602 sprintf(buff,"break 0x%x\n",addr);
604 waitForSim(100,NULL);
607 /*-----------------------------------------------------------------*/
608 /* simClearBP - clear a break point */
609 /*-----------------------------------------------------------------*/
610 void simClearBP (unsigned int addr)
614 sprintf(buff,"clear 0x%x\n",addr);
616 waitForSim(100,NULL);
619 /*-----------------------------------------------------------------*/
620 /* simLoadFile - load the simulator file */
621 /*-----------------------------------------------------------------*/
622 void simLoadFile (char *s)
626 sprintf(buff,"file \"%s\"\n",s);
629 waitForSim(500,NULL);
632 /*-----------------------------------------------------------------*/
633 /* simGoTillBp - send 'go' to simulator till a bp then return addr */
634 /*-----------------------------------------------------------------*/
635 unsigned int simGoTillBp ( unsigned int gaddr)
642 invalidateCache(XMEM_CACHE);
643 invalidateCache(IMEM_CACHE);
644 invalidateCache(SREG_CACHE);
646 /* initial start, start & stop from address 0 */
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");
657 waitForSim(wait_ms, NULL);
658 sendSim("run 0x0\n");
659 } else if (gaddr == -1) { /* resume */
663 else if (gaddr == 1 ) { /* nexti or next */
667 else if (gaddr == 2 ) { /* stepi or step */
672 printf("Error, simGoTillBp > 0!\n");
676 waitForSim(wait_ms, NULL);
678 /* get the simulator response */
680 /* check for errors */
683 while ( *sr && *sr != 'E' ) sr++ ;
686 if ( ! strncmp(sr,"Error:",6))
695 /* get answer of stop command */
697 waitForSim(wait_ms, NULL);
699 /* better solution: ask pc */
701 waitForSim(100, NULL);
705 gaddr = strtol(sr+3,0,0);
709 /*-----------------------------------------------------------------*/
710 /* simReset - reset the simulator */
711 /*-----------------------------------------------------------------*/
714 invalidateCache(XMEM_CACHE);
715 invalidateCache(IMEM_CACHE);
716 invalidateCache(SREG_CACHE);
718 waitForSim(100,NULL);
722 /*-----------------------------------------------------------------*/
723 /* closeSimulator - close connection to simulator */
724 /*-----------------------------------------------------------------*/
725 void closeSimulator ()
728 if ( ! simin || ! simout || INVALID_SOCKET == sock )
730 if ( ! simin || ! simout || sock == -1 )
745 TerminateProcess(simPid->hProcess, 0);
746 // Close process and thread handles.
747 CloseHandle(simPid->hProcess);
748 CloseHandle(simPid->hThread);
753 kill (simPid,SIGKILL);