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 static void init_winsock(void)
158 static int is_initialized = 0;
165 // Initialize Winsock
166 if (0 != WSAStartup(MAKEWORD(2,2), &wsaData))
168 fprintf(stderr, "WSAStartup failed: %d\n", iResult);
174 static char *argsToCmdLine(char **args, int nargs)
179 char *cmd = Safe_malloc(CHUNCK);
182 for (i = 0; i < nargs; i++)
185 int argLen = strlen(args[i]);
187 if (NULL != strchr(args[i], ' '))
196 if (cmdPos + argLen >= cmdLen)
202 while (cmdPos + argLen >= cmdLen);
203 cmd = Safe_realloc(cmd, cmdLen);
218 memcpy(&cmd[cmdPos], args[i], argLen);
230 static PROCESS_INFORMATION *execSimulator(char **args, int nargs)
233 static PROCESS_INFORMATION pi;
234 char *cmdLine = argsToCmdLine(args, nargs);
236 memset(&si, 0, sizeof(si));
238 memset(&pi, 0, sizeof(pi));
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
254 printf( "CreateProcess failed (%d).\n", GetLastError() );
262 void openSimulator (char **args, int nargs)
264 struct sockaddr_in sin;
271 Dprintf(D_simi, ("simi: openSimulator\n"));
273 if (D_simi & sdcdbDebug)
275 printf("simi: openSimulator: ");
276 for (i=0; i < nargs; i++ )
278 printf("arg%d: %s ",i,args[i]);
283 invalidateCache(XMEM_CACHE);
284 invalidateCache(IMEM_CACHE);
285 invalidateCache(SREG_CACHE);
287 if (INVALID_SOCKET == (sock = WSASocket(PF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0))) {
288 fprintf(stderr, "cannot create socket: %d\n", WSAGetLastError());
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);
298 /* connect to the simulator */
299 if (SOCKET_ERROR == connect(sock, (struct sockaddr *)&sin, sizeof(sin)))
301 /* if failed then wait 1 second & try again
302 do this for 10 secs only */
306 simPid = execSimulator(args, nargs);
311 perror("connect failed :");
315 fh = _open_osfhandle((intptr_t)sock, _O_TEXT);
318 perror("cannot _open_osfhandle");
322 /* go the socket now turn it into a file handle */
323 if (!(simin = fdopen(fh, "r")))
325 perror("cannot open socket for read");
329 fh = _open_osfhandle((intptr_t)sock, _O_TEXT);
332 perror("cannot _open_osfhandle");
336 if (!(simout = fdopen(fh, "w")))
338 perror("cannot open socket for write");
341 /* now that we have opened, wait for the prompt */
342 waitForSim(200, NULL);
346 static int execSimulator(char **args, int nargs)
348 if ((simPid = fork()))
350 Dprintf(D_simi, ("simi: simulator pid %d\n",(int) simPid));
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 );
360 if (execvp(args[0],args) < 0)
362 perror("cannot exec simulator");
368 void openSimulator (char **args, int nargs)
370 struct sockaddr_in sin;
373 Dprintf(D_simi, ("simi: openSimulator\n"));
375 if (D_simi & sdcdbDebug)
377 printf("simi: openSimulator: ");
378 for (i=0; i < nargs; i++ )
380 printf("arg%d: %s ",i,args[i]);
385 invalidateCache(XMEM_CACHE);
386 invalidateCache(IMEM_CACHE);
387 invalidateCache(SREG_CACHE);
389 if ((sock = socket(AF_INET,SOCK_STREAM,0)) < 0)
391 perror("cannot create socket");
395 memset(&sin,0,sizeof(sin));
396 sin.sin_family = AF_INET;
397 sin.sin_addr.s_addr = inet_addr("127.0.0.1");
398 sin.sin_port = htons(9756);
401 /* connect to the simulator */
402 if (connect(sock,(struct sockaddr *) &sin, sizeof(sin)) < 0)
404 /* if failed then wait 1 second & try again
405 do this for 10 secs only */
410 simPid = execSimulator(args, nargs);
416 perror("connect failed :");
419 /* go the socket now turn it into a file handle */
420 if (!(simin = fdopen(sock,"r")))
422 fprintf(stderr,"cannot open socket for read\n");
426 if (!(simout = fdopen(sock,"w")))
428 fprintf(stderr,"cannot open socket for write\n");
431 /* now that we have opened, wait for the prompt */
432 waitForSim(200,NULL);
437 /*-----------------------------------------------------------------*/
438 /* simResponse - returns buffer to simulator's response */
439 /*-----------------------------------------------------------------*/
440 char *simResponse(void)
445 /*-----------------------------------------------------------------*/
446 /* sendSim - sends a command to the simuator */
447 /*-----------------------------------------------------------------*/
448 void sendSim(char *s)
453 Dprintf(D_simi, ("simi: sendSim-->%s", s)); // s has LF at end already
459 static int getMemString(char *buffer, char wrflag,
460 unsigned int *addr, char mem, int size )
462 int cachenr = NMEM_CACHE;
474 case 'A': /* External stack */
475 case 'F': /* External ram */
477 cachenr = XMEM_CACHE;
480 case 'D': /* Code / static segment */
483 case 'B': /* Internal stack */
484 case 'E': /* Internal ram (lower 128) bytes */
485 case 'G': /* Internal ram */
487 cachenr = IMEM_CACHE;
489 case 'H': /* Bit addressable */
490 case 'J': /* SBIT space */
496 sprintf(buffer,"%s 0x%x\n",cmd,*addr);
499 case 'I': /* SFR space */
501 cachenr = SREG_CACHE;
503 case 'R': /* Register space */
505 /* get register bank */
506 cachenr = simGetValue (0xd0,'I',1);
507 *addr += cachenr & 0x18 ;
508 cachenr = IMEM_CACHE;
511 case 'Z': /* undefined space code */
515 sprintf(buffer,"%s %s 0x%x\n",cmd,prefix,*addr);
517 sprintf(buffer,"%s %s 0x%x 0x%x\n",cmd,prefix,*addr,*addr+size-1);
521 void simSetPC( unsigned int addr )
524 sprintf(buffer,"pc %d\n", addr);
526 waitForSim(100,NULL);
530 int simSetValue (unsigned int addr,char mem, int size, unsigned long val)
539 cachenr = getMemString(buffer,1,&addr,mem,size);
540 if ( cachenr < NMEM_CACHE )
542 invalidateCache(cachenr);
544 s = buffer + strlen(buffer) -1;
545 for ( i = 0 ; i < size ; i++ )
547 sprintf(s," 0x%x", val & 0xff);
553 waitForSim(100,NULL);
559 /*-----------------------------------------------------------------*/
560 /* simGetValue - get value @ address for mem space */
561 /*-----------------------------------------------------------------*/
562 unsigned long simGetValue (unsigned int addr,char mem, int size)
564 unsigned int b[4] = {0,0,0,0}; /* can be a max of four bytes long */
572 cachenr = getMemString(buffer,0,&addr,mem,size);
575 if ( cachenr < NMEM_CACHE )
577 resp = getMemCache(addr,cachenr,size);
581 /* create the simulator command */
583 waitForSim(100,NULL);
584 resp = simResponse();
586 /* got the response we need to parse it the response
588 [address] [v] [v] [v] ... special case in
589 case of bit variables which case it becomes
590 [address] [assembler bit address] [v] */
591 /* first skip thru white space */
592 resp = trim_left(resp);
594 if (strncmp(resp, "0x",2) == 0)
597 /* skip thru the address part */
598 while (isxdigit(*resp)) resp++;
601 /* make the branch for bit variables */
602 if ( cachenr == BIT_CACHE)
604 /* skip until newline */
605 while (*resp && *resp != '\n' ) resp++ ;
606 if ( *--resp != '0' )
611 for (i = 0 ; i < size ; i++ )
613 /* skip white space */
614 resp = trim_left(resp);
616 b[i] = strtol(resp,&resp,16);
620 return b[0] | b[1] << 8 | b[2] << 16 | b[3] << 24 ;
624 /*-----------------------------------------------------------------*/
625 /* simSetBP - set break point for a given address */
626 /*-----------------------------------------------------------------*/
627 void simSetBP (unsigned int addr)
631 sprintf(buff,"break 0x%x\n",addr);
633 waitForSim(100,NULL);
636 /*-----------------------------------------------------------------*/
637 /* simClearBP - clear a break point */
638 /*-----------------------------------------------------------------*/
639 void simClearBP (unsigned int addr)
643 sprintf(buff,"clear 0x%x\n",addr);
645 waitForSim(100,NULL);
648 /*-----------------------------------------------------------------*/
649 /* simLoadFile - load the simulator file */
650 /*-----------------------------------------------------------------*/
651 void simLoadFile (char *s)
655 sprintf(buff,"file \"%s\"\n",s);
658 waitForSim(500,NULL);
661 /*-----------------------------------------------------------------*/
662 /* simGoTillBp - send 'go' to simulator till a bp then return addr */
663 /*-----------------------------------------------------------------*/
664 unsigned int simGoTillBp ( unsigned int gaddr)
671 invalidateCache(XMEM_CACHE);
672 invalidateCache(IMEM_CACHE);
673 invalidateCache(SREG_CACHE);
675 /* initial start, start & stop from address 0 */
678 // this program is setting up a bunch of breakpoints automatically
679 // at key places. Like at startup & main() and other function
680 // entry points. So we don't need to setup one here..
681 //sendSim("break 0x0\n");
686 waitForSim(wait_ms, NULL);
687 sendSim("run 0x0\n");
688 } else if (gaddr == -1) { /* resume */
692 else if (gaddr == 1 ) { /* nexti or next */
696 else if (gaddr == 2 ) { /* stepi or step */
701 printf("Error, simGoTillBp > 0!\n");
705 waitForSim(wait_ms, NULL);
707 /* get the simulator response */
709 /* check for errors */
712 while ( *sr && *sr != 'E' ) sr++ ;
715 if ( ! strncmp(sr,"Error:",6))
724 /* get answer of stop command */
726 waitForSim(wait_ms, NULL);
728 /* better solution: ask pc */
730 waitForSim(100, NULL);
734 gaddr = strtol(sr+3,0,0);
738 /*-----------------------------------------------------------------*/
739 /* simReset - reset the simulator */
740 /*-----------------------------------------------------------------*/
743 invalidateCache(XMEM_CACHE);
744 invalidateCache(IMEM_CACHE);
745 invalidateCache(SREG_CACHE);
747 waitForSim(100,NULL);
751 /*-----------------------------------------------------------------*/
752 /* closeSimulator - close connection to simulator */
753 /*-----------------------------------------------------------------*/
754 void closeSimulator (void)
757 if ( ! simin || ! simout || INVALID_SOCKET == sock )
759 if ( ! simin || ! simout || sock == -1 )
774 TerminateProcess(simPid->hProcess, 0);
775 // Close process and thread handles.
776 CloseHandle(simPid->hProcess);
777 CloseHandle(simPid->hThread);
782 kill (simPid,SIGKILL);