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");
369 void openSimulator (char **args, int nargs)
371 struct sockaddr_in sin;
374 Dprintf(D_simi, ("simi: openSimulator\n"));
376 if (D_simi & sdcdbDebug)
378 printf("simi: openSimulator: ");
379 for (i=0; i < nargs; i++ )
381 printf("arg%d: %s ",i,args[i]);
386 invalidateCache(XMEM_CACHE);
387 invalidateCache(IMEM_CACHE);
388 invalidateCache(SREG_CACHE);
390 if ((sock = socket(AF_INET,SOCK_STREAM,0)) < 0)
392 perror("cannot create socket");
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);
402 /* connect to the simulator */
403 if (connect(sock,(struct sockaddr *) &sin, sizeof(sin)) < 0)
405 /* if failed then wait 1 second & try again
406 do this for 10 secs only */
411 simPid = execSimulator(args, nargs);
417 perror("connect failed :");
420 /* go the socket now turn it into a file handle */
421 if (!(simin = fdopen(sock,"r")))
423 fprintf(stderr,"cannot open socket for read\n");
427 if (!(simout = fdopen(sock,"w")))
429 fprintf(stderr,"cannot open socket for write\n");
432 /* now that we have opened, wait for the prompt */
433 waitForSim(200,NULL);
438 /*-----------------------------------------------------------------*/
439 /* simResponse - returns buffer to simulator's response */
440 /*-----------------------------------------------------------------*/
441 char *simResponse(void)
446 /*-----------------------------------------------------------------*/
447 /* sendSim - sends a command to the simuator */
448 /*-----------------------------------------------------------------*/
449 void sendSim(char *s)
454 Dprintf(D_simi, ("simi: sendSim-->%s", s)); // s has LF at end already
460 static int getMemString(char *buffer, char wrflag,
461 unsigned int *addr, char mem, int size )
463 int cachenr = NMEM_CACHE;
475 case 'A': /* External stack */
476 case 'F': /* External ram */
478 cachenr = XMEM_CACHE;
481 case 'D': /* Code / static segment */
484 case 'B': /* Internal stack */
485 case 'E': /* Internal ram (lower 128) bytes */
486 case 'G': /* Internal ram */
488 cachenr = IMEM_CACHE;
490 case 'H': /* Bit addressable */
491 case 'J': /* SBIT space */
497 sprintf(buffer,"%s 0x%x\n",cmd,*addr);
500 case 'I': /* SFR space */
502 cachenr = SREG_CACHE;
504 case 'R': /* Register space */
506 /* get register bank */
507 cachenr = simGetValue (0xd0,'I',1);
508 *addr += cachenr & 0x18 ;
509 cachenr = IMEM_CACHE;
512 case 'Z': /* undefined space code */
516 sprintf(buffer,"%s %s 0x%x\n",cmd,prefix,*addr);
518 sprintf(buffer,"%s %s 0x%x 0x%x\n",cmd,prefix,*addr,*addr+size-1);
522 void simSetPC( unsigned int addr )
525 sprintf(buffer,"pc %d\n", addr);
527 waitForSim(100,NULL);
531 int simSetValue (unsigned int addr,char mem, int size, unsigned long val)
540 cachenr = getMemString(buffer,1,&addr,mem,size);
541 if ( cachenr < NMEM_CACHE )
543 invalidateCache(cachenr);
545 s = buffer + strlen(buffer) -1;
546 for ( i = 0 ; i < size ; i++ )
548 sprintf(s," 0x%lx", val & 0xff);
554 waitForSim(100,NULL);
560 /*-----------------------------------------------------------------*/
561 /* simGetValue - get value @ address for mem space */
562 /*-----------------------------------------------------------------*/
563 unsigned long simGetValue (unsigned int addr,char mem, int size)
565 unsigned int b[4] = {0,0,0,0}; /* can be a max of four bytes long */
573 cachenr = getMemString(buffer,0,&addr,mem,size);
576 if ( cachenr < NMEM_CACHE )
578 resp = getMemCache(addr,cachenr,size);
582 /* create the simulator command */
584 waitForSim(100,NULL);
585 resp = simResponse();
587 /* got the response we need to parse it the response
589 [address] [v] [v] [v] ... special case in
590 case of bit variables which case it becomes
591 [address] [assembler bit address] [v] */
592 /* first skip thru white space */
593 resp = trim_left(resp);
595 if (strncmp(resp, "0x",2) == 0)
598 /* skip thru the address part */
599 while (isxdigit(*resp)) resp++;
602 /* make the branch for bit variables */
603 if ( cachenr == BIT_CACHE)
605 /* skip until newline */
606 while (*resp && *resp != '\n' ) resp++ ;
607 if ( *--resp != '0' )
612 for (i = 0 ; i < size ; i++ )
614 /* skip white space */
615 resp = trim_left(resp);
617 b[i] = strtol(resp,&resp,16);
621 return b[0] | b[1] << 8 | b[2] << 16 | b[3] << 24 ;
625 /*-----------------------------------------------------------------*/
626 /* simSetBP - set break point for a given address */
627 /*-----------------------------------------------------------------*/
628 void simSetBP (unsigned int addr)
632 sprintf(buff,"break 0x%x\n",addr);
634 waitForSim(100,NULL);
637 /*-----------------------------------------------------------------*/
638 /* simClearBP - clear a break point */
639 /*-----------------------------------------------------------------*/
640 void simClearBP (unsigned int addr)
644 sprintf(buff,"clear 0x%x\n",addr);
646 waitForSim(100,NULL);
649 /*-----------------------------------------------------------------*/
650 /* simLoadFile - load the simulator file */
651 /*-----------------------------------------------------------------*/
652 void simLoadFile (char *s)
656 sprintf(buff,"file \"%s\"\n",s);
659 waitForSim(500,NULL);
662 /*-----------------------------------------------------------------*/
663 /* simGoTillBp - send 'go' to simulator till a bp then return addr */
664 /*-----------------------------------------------------------------*/
665 unsigned int simGoTillBp ( unsigned int gaddr)
672 invalidateCache(XMEM_CACHE);
673 invalidateCache(IMEM_CACHE);
674 invalidateCache(SREG_CACHE);
676 /* initial start, start & stop from address 0 */
679 // this program is setting up a bunch of breakpoints automatically
680 // at key places. Like at startup & main() and other function
681 // entry points. So we don't need to setup one here..
682 //sendSim("break 0x0\n");
687 waitForSim(wait_ms, NULL);
688 sendSim("run 0x0\n");
689 } else if (gaddr == -1) { /* resume */
693 else if (gaddr == 1 ) { /* nexti or next */
697 else if (gaddr == 2 ) { /* stepi or step */
702 printf("Error, simGoTillBp > 0!\n");
706 waitForSim(wait_ms, NULL);
708 /* get the simulator response */
710 /* check for errors */
713 while ( *sr && *sr != 'E' ) sr++ ;
716 if ( ! strncmp(sr,"Error:",6))
725 /* get answer of stop command */
727 waitForSim(wait_ms, NULL);
729 /* better solution: ask pc */
731 waitForSim(100, NULL);
735 gaddr = strtol(sr+3,0,0);
739 /*-----------------------------------------------------------------*/
740 /* simReset - reset the simulator */
741 /*-----------------------------------------------------------------*/
744 invalidateCache(XMEM_CACHE);
745 invalidateCache(IMEM_CACHE);
746 invalidateCache(SREG_CACHE);
748 waitForSim(100,NULL);
752 /*-----------------------------------------------------------------*/
753 /* closeSimulator - close connection to simulator */
754 /*-----------------------------------------------------------------*/
755 void closeSimulator (void)
758 if ( ! simin || ! simout || INVALID_SOCKET == sock )
760 if ( ! simin || ! simout || sock == -1 )
775 TerminateProcess(simPid->hProcess, 0);
776 // Close process and thread handles.
777 CloseHandle(simPid->hProcess);
778 CloseHandle(simPid->hThread);
783 kill (simPid,SIGKILL);