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 (argLen >= cmdLen)
184 while (argLen >= cmdLen);
185 cmd = Safe_realloc(cmd, cmdLen);
200 memcpy(&cmd[cmdPos], args[i], argLen);
210 PROCESS_INFORMATION *execSimulator(char **args, int nargs)
213 static PROCESS_INFORMATION pi;
214 char *cmdLine = argsToCmdLine(args, nargs);
216 memset(&si, 0, sizeof(si));
218 memset(&pi, 0, sizeof(pi));
220 // Start the child process.
221 if (!CreateProcess(NULL, // No module name (use command line)
222 cmdLine, // Command line
223 NULL, // Process handle not inheritable
224 NULL, // Thread handle not inheritable
225 FALSE, // Set handle inheritance to FALSE
226 0, // No creation flags
227 NULL, // Use parent's environment block
228 NULL, // Use parent's starting directory
229 &si, // Pointer to STARTUPINFO structure
230 &pi) // Pointer to PROCESS_INFORMATION structure
234 printf( "CreateProcess failed (%d).\n", GetLastError() );
242 void openSimulator (char **args, int nargs)
244 struct sockaddr_in sin;
248 Dprintf(D_simi, ("simi: openSimulator\n"));
250 if (D_simi & sdcdbDebug)
252 printf("simi: openSimulator: ");
253 for (i=0; i < nargs; i++ )
255 printf("arg%d: %s ",i,args[i]);
260 invalidateCache(XMEM_CACHE);
261 invalidateCache(IMEM_CACHE);
262 invalidateCache(SREG_CACHE);
265 sock = WSASocket(PF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);
267 memset(&sin,0,sizeof(sin));
268 sin.sin_family = AF_INET;
269 sin.sin_addr.s_addr = inet_addr("127.0.0.1");
270 sin.sin_port = htons(9756);
272 /* connect to the simulator */
273 if (INVALID_SOCKET == connect(sock,(struct sockaddr *) &sin, sizeof(sin)))
275 /* if failed then wait 1 second & try again
276 do this for 10 secs only */
280 simPid = execSimulator(args, nargs);
285 perror("connect failed :");
288 fh = _open_osfhandle((intptr_t)socket, _O_TEXT);
291 fprintf(stderr, "cannot _open_osfhandle\n");
295 /* go the socket now turn it into a file handle */
296 if (!(simin = fdopen(sock,"r")))
298 fprintf(stderr,"cannot open socket for read\n");
302 fh = _open_osfhandle((intptr_t)socket, _O_TEXT);
305 fprintf(stderr, "cannot _open_osfhandle\n");
309 if (!(simout = fdopen(sock,"w")))
311 fprintf(stderr,"cannot open socket for write\n");
314 /* now that we have opened, wait for the prompt */
315 waitForSim(200,NULL);
319 int execSimulator(char **args, int nargs)
321 if ((simPid = fork()))
323 Dprintf(D_simi, ("simi: simulator pid %d\n",(int) simPid));
327 /* we are in the child process : start the simulator */
328 signal(SIGINT , SIG_IGN );
329 signal(SIGABRT, SIG_IGN );
330 signal(SIGHUP , SIG_IGN );
331 signal(SIGCHLD, SIG_IGN );
333 if (execvp(args[0],args) < 0)
335 perror("cannot exec simulator");
341 void openSimulator (char **args, int nargs)
343 struct sockaddr_in sin;
346 Dprintf(D_simi, ("simi: openSimulator\n"));
348 if (D_simi & sdcdbDebug)
350 printf("simi: openSimulator: ");
351 for (i=0; i < nargs; i++ )
353 printf("arg%d: %s ",i,args[i]);
358 invalidateCache(XMEM_CACHE);
359 invalidateCache(IMEM_CACHE);
360 invalidateCache(SREG_CACHE);
363 sock = socket(AF_INET,SOCK_STREAM,0);
365 memset(&sin,0,sizeof(sin));
366 sin.sin_family = AF_INET;
367 sin.sin_addr.s_addr = inet_addr("127.0.0.1");
368 sin.sin_port = htons(9756);
370 /* connect to the simulator */
371 if (connect(sock,(struct sockaddr *) &sin, sizeof(sin)) < 0)
373 /* if failed then wait 1 second & try again
374 do this for 10 secs only */
379 simPid = execSimulator(args, nargs);
385 perror("connect failed :");
388 /* go the socket now turn it into a file handle */
389 if (!(simin = fdopen(sock,"r")))
391 fprintf(stderr,"cannot open socket for read\n");
395 if (!(simout = fdopen(sock,"w")))
397 fprintf(stderr,"cannot open socket for write\n");
400 /* now that we have opened, wait for the prompt */
401 waitForSim(200,NULL);
406 /*-----------------------------------------------------------------*/
407 /* simResponse - returns buffer to simulator's response */
408 /*-----------------------------------------------------------------*/
414 /*-----------------------------------------------------------------*/
415 /* sendSim - sends a command to the simuator */
416 /*-----------------------------------------------------------------*/
417 void sendSim(char *s)
422 Dprintf(D_simi, ("simi: sendSim-->%s", s)); // s has LF at end already
428 static int getMemString(char *buffer, char wrflag,
429 unsigned int *addr, char mem, int size )
431 int cachenr = NMEM_CACHE;
443 case 'A': /* External stack */
444 case 'F': /* External ram */
446 cachenr = XMEM_CACHE;
449 case 'D': /* Code / static segment */
452 case 'B': /* Internal stack */
453 case 'E': /* Internal ram (lower 128) bytes */
454 case 'G': /* Internal ram */
456 cachenr = IMEM_CACHE;
458 case 'H': /* Bit addressable */
459 case 'J': /* SBIT space */
465 sprintf(buffer,"%s 0x%x\n",cmd,*addr);
468 case 'I': /* SFR space */
470 cachenr = SREG_CACHE;
472 case 'R': /* Register space */
474 /* get register bank */
475 cachenr = simGetValue (0xd0,'I',1);
476 *addr += cachenr & 0x18 ;
477 cachenr = IMEM_CACHE;
480 case 'Z': /* undefined space code */
484 sprintf(buffer,"%s %s 0x%x\n",cmd,prefix,*addr);
486 sprintf(buffer,"%s %s 0x%x 0x%x\n",cmd,prefix,*addr,*addr+size-1);
490 void simSetPC( unsigned int addr )
493 sprintf(buffer,"pc %d\n", addr);
495 waitForSim(100,NULL);
499 int simSetValue (unsigned int addr,char mem, int size, unsigned long val)
508 cachenr = getMemString(buffer,1,&addr,mem,size);
509 if ( cachenr < NMEM_CACHE )
511 invalidateCache(cachenr);
513 s = buffer + strlen(buffer) -1;
514 for ( i = 0 ; i < size ; i++ )
516 sprintf(s," 0x%x", val & 0xff);
522 waitForSim(100,NULL);
528 /*-----------------------------------------------------------------*/
529 /* simGetValue - get value @ address for mem space */
530 /*-----------------------------------------------------------------*/
531 unsigned long simGetValue (unsigned int addr,char mem, int size)
533 unsigned int b[4] = {0,0,0,0}; /* can be a max of four bytes long */
541 cachenr = getMemString(buffer,0,&addr,mem,size);
544 if ( cachenr < NMEM_CACHE )
546 resp = getMemCache(addr,cachenr,size);
550 /* create the simulator command */
552 waitForSim(100,NULL);
553 resp = simResponse();
555 /* got the response we need to parse it the response
557 [address] [v] [v] [v] ... special case in
558 case of bit variables which case it becomes
559 [address] [assembler bit address] [v] */
560 /* first skip thru white space */
561 while (isspace(*resp)) resp++ ;
563 if (strncmp(resp, "0x",2) == 0)
566 /* skip thru the address part */
567 while (isxdigit(*resp)) resp++;
570 /* make the branch for bit variables */
571 if ( cachenr == BIT_CACHE)
573 /* skip until newline */
574 while (*resp && *resp != '\n' ) resp++ ;
575 if ( *--resp != '0' )
580 for (i = 0 ; i < size ; i++ )
582 /* skip white space */
583 while (isspace(*resp)) resp++ ;
585 b[i] = strtol(resp,&resp,16);
589 return b[0] | b[1] << 8 | b[2] << 16 | b[3] << 24 ;
593 /*-----------------------------------------------------------------*/
594 /* simSetBP - set break point for a given address */
595 /*-----------------------------------------------------------------*/
596 void simSetBP (unsigned int addr)
600 sprintf(buff,"break 0x%x\n",addr);
602 waitForSim(100,NULL);
605 /*-----------------------------------------------------------------*/
606 /* simClearBP - clear a break point */
607 /*-----------------------------------------------------------------*/
608 void simClearBP (unsigned int addr)
612 sprintf(buff,"clear 0x%x\n",addr);
614 waitForSim(100,NULL);
617 /*-----------------------------------------------------------------*/
618 /* simLoadFile - load the simulator file */
619 /*-----------------------------------------------------------------*/
620 void simLoadFile (char *s)
624 sprintf(buff,"file \"%s\"\n",s);
627 waitForSim(500,NULL);
630 /*-----------------------------------------------------------------*/
631 /* simGoTillBp - send 'go' to simulator till a bp then return addr */
632 /*-----------------------------------------------------------------*/
633 unsigned int simGoTillBp ( unsigned int gaddr)
640 invalidateCache(XMEM_CACHE);
641 invalidateCache(IMEM_CACHE);
642 invalidateCache(SREG_CACHE);
644 /* initial start, start & stop from address 0 */
647 // this program is setting up a bunch of breakpoints automatically
648 // at key places. Like at startup & main() and other function
649 // entry points. So we don't need to setup one here..
650 //sendSim("break 0x0\n");
655 waitForSim(wait_ms, NULL);
656 sendSim("run 0x0\n");
657 } else if (gaddr == -1) { /* resume */
661 else if (gaddr == 1 ) { /* nexti or next */
665 else if (gaddr == 2 ) { /* stepi or step */
670 printf("Error, simGoTillBp > 0!\n");
674 waitForSim(wait_ms, NULL);
676 /* get the simulator response */
678 /* check for errors */
681 while ( *sr && *sr != 'E' ) sr++ ;
684 if ( ! strncmp(sr,"Error:",6))
693 /* get answer of stop command */
695 waitForSim(wait_ms, NULL);
697 /* better solution: ask pc */
699 waitForSim(100, NULL);
703 gaddr = strtol(sr+3,0,0);
707 /*-----------------------------------------------------------------*/
708 /* simReset - reset the simulator */
709 /*-----------------------------------------------------------------*/
712 invalidateCache(XMEM_CACHE);
713 invalidateCache(IMEM_CACHE);
714 invalidateCache(SREG_CACHE);
716 waitForSim(100,NULL);
720 /*-----------------------------------------------------------------*/
721 /* closeSimulator - close connection to simulator */
722 /*-----------------------------------------------------------------*/
723 void closeSimulator ()
726 if ( ! simin || ! simout || INVALID_SOCKET == sock )
728 if ( ! simin || ! simout || sock == -1 )
743 TerminateProcess(simPid->hProcess, 0);
744 // Close process and thread handles.
745 CloseHandle(simPid->hProcess);
746 CloseHandle(simPid->hThread);
751 kill (simPid,SIGKILL);