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 -------------------------------------------------------------------------*/
30 # include <winsock2.h>
35 # include <sys/file.h>
37 # ifdef HAVE_SYS_SOCKET_H
38 # include <sys/types.h>
39 # include <sys/socket.h>
40 # include <netinet/in.h>
41 # include <arpa/inet.h>
43 # include <sys/ioctl.h>
45 # error "Cannot build debugger without socket support"
52 FILE *simin
; /* stream for simulator input */
53 FILE *simout
; /* stream for simulator output */
56 SOCKET sock
= INVALID_SOCKET
;
57 PROCESS_INFORMATION
*simPid
= NULL
;
59 int sock
= -1; /* socket descriptor to comm with simulator */
62 static char simibuff
[MAX_SIM_BUFF
]; /* sim buffer */
63 static char *sbp
= simibuff
; /* simulator buffer pointer */
66 static memcache_t memCache
[NMEM_CACHE
];
68 /*-----------------------------------------------------------------*/
69 /* get data from memory cache/ load cache from simulator */
70 /*-----------------------------------------------------------------*/
71 static char *getMemCache(unsigned int addr
,int cachenum
, unsigned int size
)
75 memcache_t
*cache
= &memCache
[cachenum
];
77 if ( cache
->size
<= 0 ||
79 cache
->addr
+ cache
->size
< addr
+ size
)
81 if ( cachenum
== IMEM_CACHE
)
83 sendSim("di 0x0 0xff\n");
85 else if ( cachenum
== SREG_CACHE
)
87 sendSim("ds 0x80 0xff\n");
91 laddr
= addr
& 0xffffffc0;
92 sprintf(cache
->buffer
,"dx 0x%x 0x%x\n",laddr
,laddr
+0xff );
93 sendSim(cache
->buffer
);
97 cache
->addr
= strtol(resp
,0,0);
100 while ( *resp
&& *(resp
+1) && *(resp
+2))
102 /* cache is a stringbuffer with ascii data like
103 " 00 00 00 00 00 00 00 00"
107 /* skip thru the address part */
108 while (isxdigit(*resp
))
110 while ( *resp
&& *resp
!= '\n')
123 if ( cache
->addr
> addr
||
124 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 doing its job */
142 /*-----------------------------------------------------------------*/
143 void waitForSim(int timeout_ms
, char *expect
)
148 Dprintf(D_simi
, ("simi: waitForSim start(%d)\n", timeout_ms
));
151 timeout
= clock() + ((timeout_ms
* CLOCKS_PER_SEC
) / 1000);
152 while (((ch
= fgetc(simin
)) > 0 ) && (clock() <= timeout
))
157 Dprintf(D_simi
, ("waitForSim(%d) got[%s]\n", timeout_ms
, simibuff
));
160 /*-----------------------------------------------------------------*/
161 /* openSimulator - create a pipe to talk to simulator */
162 /*-----------------------------------------------------------------*/
164 static void init_winsock(void)
166 static int is_initialized
= 0;
173 // Initialize Winsock
174 iResult
= WSAStartup(MAKEWORD(2,2), &wsaData
);
177 fprintf(stderr
, "WSAStartup failed: %d\n", iResult
);
183 static PROCESS_INFORMATION
*execSimulator(char **args
, int nargs
)
186 static PROCESS_INFORMATION pi
;
187 char *cmdLine
= argsToCmdLine(args
, nargs
);
189 memset(&si
, 0, sizeof(si
));
191 memset(&pi
, 0, sizeof(pi
));
193 // Start the child process.
194 if (!CreateProcess(NULL
, // No module name (use command line)
195 cmdLine
, // Command line
196 NULL
, // Process handle not inheritable
197 NULL
, // Thread handle not inheritable
198 FALSE
, // Set handle inheritance to FALSE
199 0, // No creation flags
200 NULL
, // Use parent's environment block
201 NULL
, // Use parent's starting directory
202 &si
, // Pointer to STARTUPINFO structure
203 &pi
) // Pointer to PROCESS_INFORMATION structure
207 printf( "CreateProcess failed (%lu).\n", GetLastError() );
214 void openSimulator (char **args
, int nargs
)
216 struct sockaddr_in sin
;
225 Dprintf(D_simi
, ("simi: openSimulator\n"));
227 if (D_simi
& sdcdbDebug
)
229 printf("simi: openSimulator: ");
230 for (i
=0; i
< nargs
; i
++ )
232 printf("arg%d: %s ", i
, args
[i
]);
237 invalidateCache(XMEM_CACHE
);
238 invalidateCache(IMEM_CACHE
);
239 invalidateCache(SREG_CACHE
);
241 if (INVALID_SOCKET
== (sock
= WSASocket(PF_INET
, SOCK_STREAM
, IPPROTO_TCP
, NULL
, 0, 0)))
243 fprintf(stderr
, "cannot create socket: %d\n", WSAGetLastError());
247 memset(&sin
, 0, sizeof(sin
));
248 sin
.sin_family
= AF_INET
;
249 sin
.sin_addr
.s_addr
= inet_addr("127.0.0.1");
250 sin
.sin_port
= htons(9756);
253 /* connect to the simulator */
254 if (SOCKET_ERROR
== connect(sock
, (struct sockaddr
*)&sin
, sizeof(sin
)))
256 /* if failed then wait 1 second & try again
257 do this for 10 secs only */
261 simPid
= execSimulator(args
, nargs
);
266 perror("connect failed :");
270 iMode
= 1; /* set non-blocking mode */
271 iResult
= ioctlsocket(sock
, FIONBIO
, &iMode
);
272 if (iResult
!= NO_ERROR
)
274 perror("ioctlsocket failed");
278 fh
= _open_osfhandle(sock
, _O_TEXT
);
281 perror("cannot _open_osfhandle");
285 /* got the socket now turn it into a file handle */
286 if (!(simin
= fdopen(fh
, "r")))
288 perror("cannot open socket for read");
292 fh
= _open_osfhandle(sock
, _O_TEXT
);
295 perror("cannot _open_osfhandle");
299 if (!(simout
= fdopen(fh
, "w")))
301 perror("cannot open socket for write");
304 /* now that we have opened, wait for the prompt */
305 waitForSim(200, NULL
);
309 static int execSimulator(char **args
, int nargs
)
311 if ((simPid
= fork()))
313 Dprintf(D_simi
, ("simi: simulator pid %d\n",(int) simPid
));
317 /* we are in the child process : start the simulator */
318 signal(SIGINT
, SIG_IGN
);
319 signal(SIGABRT
, SIG_IGN
);
320 signal(SIGHUP
, SIG_IGN
);
321 signal(SIGCHLD
, SIG_IGN
);
323 if (execvp(args
[0],args
) < 0)
325 perror("cannot exec simulator");
332 void openSimulator (char **args
, int nargs
)
334 struct sockaddr_in sin
;
338 #if defined(__sun) || defined(__CYGWIN__)
342 Dprintf(D_simi
, ("simi: openSimulator\n"));
344 if (D_simi
& sdcdbDebug
)
346 printf("simi: openSimulator: ");
347 for (i
=0; i
< nargs
; i
++ )
349 printf("arg%d: %s ",i
,args
[i
]);
354 invalidateCache(XMEM_CACHE
);
355 invalidateCache(IMEM_CACHE
);
356 invalidateCache(SREG_CACHE
);
358 if ((sock
= socket(AF_INET
,SOCK_STREAM
,0)) < 0)
360 perror("cannot create socket");
364 memset(&sin
,0,sizeof(sin
));
365 sin
.sin_family
= AF_INET
;
366 sin
.sin_addr
.s_addr
= inet_addr("127.0.0.1");
367 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 :");
389 #if defined(__sun) || defined(__CYGWIN__)
390 iMode
= 1; /* set non-blocking mode */
391 iResult
= ioctl(sock
, FIONBIO
, &iMode
);
393 iResult
= fcntl(sock
, F_SETFL
, O_NONBLOCK
| O_ASYNC
);
397 perror("ioctl failed");
401 /* got the socket now turn it into a file handle */
402 if (!(simin
= fdopen(sock
, "r")))
404 fprintf(stderr
,"cannot open socket for read\n");
408 if (!(simout
= fdopen(sock
, "w")))
410 fprintf(stderr
,"cannot open socket for write\n");
413 /* now that we have opened, wait for the prompt */
414 waitForSim(200,NULL
);
419 /*-----------------------------------------------------------------*/
420 /* simResponse - returns buffer to simulator's response */
421 /*-----------------------------------------------------------------*/
422 char *simResponse(void)
427 /*-----------------------------------------------------------------*/
428 /* sendSim - sends a command to the simuator */
429 /*-----------------------------------------------------------------*/
430 void sendSim(char *s
)
435 Dprintf(D_simi
, ("simi: sendSim-->%s", s
)); // s has LF at end already
441 static int getMemString(char *buffer
, char wrflag
,
442 unsigned int *addr
, char mem
, unsigned int size
)
444 int cachenr
= NMEM_CACHE
;
456 case 'A': /* External stack */
457 case 'F': /* External ram */
459 cachenr
= XMEM_CACHE
;
462 case 'D': /* Code / static segment */
465 case 'B': /* Internal stack */
466 case 'E': /* Internal ram (lower 128) bytes */
467 case 'G': /* Internal ram */
469 cachenr
= IMEM_CACHE
;
471 case 'H': /* Bit addressable */
472 case 'J': /* SBIT space */
478 sprintf(buffer
,"%s 0x%x\n",cmd
,*addr
);
480 case 'I': /* SFR space */
482 cachenr
= SREG_CACHE
;
484 case 'R': /* Register space */
486 /* get register bank */
487 cachenr
= simGetValue (0xd0,'I',1);
488 *addr
+= cachenr
& 0x18 ;
489 cachenr
= IMEM_CACHE
;
492 case 'Z': /* undefined space code */
496 sprintf(buffer
,"%s %s 0x%x\n",cmd
,prefix
,*addr
);
498 sprintf(buffer
,"%s %s 0x%x 0x%x\n",cmd
,prefix
,*addr
,*addr
+size
-1);
502 void simSetPC( unsigned int addr
)
505 sprintf(buffer
,"pc %d\n", addr
);
507 waitForSim(100,NULL
);
511 int simSetValue (unsigned int addr
,char mem
, unsigned int size
, unsigned long val
)
521 cachenr
= getMemString(buffer
, 1, &addr
, mem
, size
);
522 if ( cachenr
< NMEM_CACHE
)
524 invalidateCache(cachenr
);
526 s
= buffer
+ strlen(buffer
) -1;
527 for ( i
= 0 ; i
< size
; i
++ )
529 sprintf(s
," 0x%lx", val
& 0xff);
535 waitForSim(100,NULL
);
540 /*-----------------------------------------------------------------*/
541 /* simGetValue - get value @ address for mem space */
542 /*-----------------------------------------------------------------*/
543 unsigned long simGetValue (unsigned int addr
,char mem
, unsigned int size
)
545 unsigned int b
[4] = {0,0,0,0}; /* can be a max of four bytes long */
553 cachenr
= getMemString(buffer
, 0, &addr
, mem
, size
);
556 if ( cachenr
< NMEM_CACHE
)
558 resp
= getMemCache(addr
,cachenr
,size
);
562 /* create the simulator command */
564 waitForSim(100,NULL
);
565 resp
= simResponse();
567 /* got the response we need to parse it the response
569 [address] [v] [v] [v] ... special case in
570 case of bit variables which case it becomes
571 [address] [assembler bit address] [v] */
572 /* first skip thru white space */
573 resp
= trim_left(resp
);
575 if (strncmp(resp
, "0x",2) == 0)
578 /* skip thru the address part */
579 while (isxdigit(*resp
))
582 /* make the branch for bit variables */
583 if ( cachenr
== BIT_CACHE
)
585 /* skip until newline */
586 while (*resp
&& *resp
!= '\n' )
588 if ( *--resp
!= '0' )
595 for (i
= 0 ; i
< size
; i
++ )
597 /* skip white space */
598 resp
= trim_left(resp
);
600 b
[i
] = strtol(resp
,&resp
,16);
604 return b
[0] | b
[1] << 8 | b
[2] << 16 | b
[3] << 24 ;
607 /*-----------------------------------------------------------------*/
608 /* simSetBP - set break point for a given address */
609 /*-----------------------------------------------------------------*/
610 void simSetBP (unsigned int addr
)
614 sprintf(buff
, "break 0x%x\n", addr
);
616 waitForSim(100, NULL
);
619 /*-----------------------------------------------------------------*/
620 /* simClearBP - clear a break point */
621 /*-----------------------------------------------------------------*/
622 void simClearBP (unsigned int addr
)
626 sprintf(buff
, "clear 0x%x\n", addr
);
628 waitForSim(100, NULL
);
631 /*-----------------------------------------------------------------*/
632 /* simLoadFile - load the simulator file */
633 /*-----------------------------------------------------------------*/
634 void simLoadFile (char *s
)
638 sprintf(buff
, "file \"%s\"\n", s
);
641 waitForSim(500, NULL
);
644 /*-----------------------------------------------------------------*/
645 /* simGoTillBp - send 'go' to simulator till a bp then return addr */
646 /*-----------------------------------------------------------------*/
647 unsigned int simGoTillBp ( unsigned int gaddr
)
652 invalidateCache(XMEM_CACHE
);
653 invalidateCache(IMEM_CACHE
);
654 invalidateCache(SREG_CACHE
);
657 /* initial start, start & stop from address 0 */
660 // this program is setting up a bunch of breakpoints automatically
661 // at key places. Like at startup & main() and other function
662 // entry points. So we don't need to setup one here..
663 //sendSim("break 0x0\n");
668 waitForSim(wait_ms
, NULL
);
669 sendSim("run 0x0\n");
671 else if (gaddr
== -1)
676 else if (gaddr
== 1 )
677 { /* nexti or next */
681 else if (gaddr
== 2 )
682 { /* stepi or step */
688 printf("Error, simGoTillBp > 0!\n");
692 waitForSim(wait_ms
, NULL
);
694 /* get the simulator response */
696 /* check for errors */
699 while ( *sr
&& *sr
!= 'E' )
703 if ( ! strncmp(sr
, "Error:", 6))
712 /* get answer of stop command */
714 waitForSim(wait_ms
, NULL
);
716 /* better solution: ask pc */
718 waitForSim(100, NULL
);
722 gaddr
= strtol(sr
+3, 0, 0);
726 /*-----------------------------------------------------------------*/
727 /* simReset - reset the simulator */
728 /*-----------------------------------------------------------------*/
731 invalidateCache(XMEM_CACHE
);
732 invalidateCache(IMEM_CACHE
);
733 invalidateCache(SREG_CACHE
);
735 waitForSim(100, NULL
);
738 /*-----------------------------------------------------------------*/
739 /* closeSimulator - close connection to simulator */
740 /*-----------------------------------------------------------------*/
741 void closeSimulator (void)
744 if ( ! simin
|| ! simout
|| INVALID_SOCKET
== sock
)
746 if ( ! simin
|| ! simout
|| sock
== -1 )
760 TerminateProcess(simPid
->hProcess
, 0);
761 // Close process and thread handles.
762 CloseHandle(simPid
->hProcess
);
763 CloseHandle(simPid
->hThread
);
769 kill (simPid
,SIGKILL
);
771 /* simin/simout are now dead as they are both associated with the closed socket */