1 /*-------------------------------------------------------------------------
2 sdcdb.c - main source file for sdcdb debugger
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 -------------------------------------------------------------------------*/
31 char *currModName = NULL;
32 cdbrecs *recsRoot = NULL ;
33 set *modules = NULL; /* set of all modules */
34 set *functions = NULL ; /* set of functions */
35 set *symbols = NULL ; /* set of symbols */
37 structdef **structs = NULL ; /* all structures */
39 linkrec **linkrecs = NULL; /* all linkage editor records */
40 context *currCtxt = NULL;
42 char *ssdirl = SDCC_LIB_DIR ":" SDCC_LIB_DIR "/small" ;
47 /* fake filename & lineno to make linker */
55 char *cmd ; /* command the user will enter */
56 int (*cmdfunc)(char *,context *); /* function to execute when command is entered */
57 char *htxt ; /* short help text */
60 /* NOTE:- the search is done from the top, so "break" should
61 precede the synonym "b" */
63 { "break" , cmdSetUserBp ,
64 "{b}reak\t\t\t [LINE | FILE:LINE | FILE:FUNCTION | FUNCTION]\n",
66 { "b" , cmdSetUserBp , NULL },
68 { "clear" , cmdClrUserBp ,
69 "{cl}ear\t\t\t [LINE | FILE:LINE | FILE:FUNCTION | FUNCTION]\n"
71 { "cl" , cmdClrUserBp , NULL },
73 { "continue" , cmdContinue ,
74 "{c}ontinue\t\t Continue program being debugged, after breakpoint.\n"
76 { "c" , cmdContinue , NULL },
78 { "delete" , cmdDelUserBp ,
79 "{d}elete n\t\t clears break point number n\n"
81 { "d" , cmdDelUserBp , NULL },
84 "{h|?}elp\t\t this message\n"
86 { "?" , cmdHelp , NULL },
87 { "h" , cmdHelp , NULL },
90 "info <break stack frame registers>\n"
91 "\t list all break points, call-stack, frame or register information\n"
94 { "listasm" , cmdListAsm ,
95 "listasm {la}\t\t list assembler code for the current C line\n"
97 { "la" , cmdListAsm , NULL },
98 { "ls" , cmdListSymbols , "ls,lf,lm\t\t list symbols,functions,modules\n" },
99 { "lf" , cmdListFunctions, NULL },
100 { "lm" , cmdListModules , NULL },
101 { "list" , cmdListSrc ,
102 "{l}ist\t\t\t [LINE | FILE:LINE | FILE:FUNCTION | FUNCTION]\n"
104 { "l" , cmdListSrc , NULL },
107 " <copying warranty>\t copying & distribution terms, warranty\n"
109 { "set" , cmdSetOption , "set <srcmode>\t\t toggle between c/asm.\n" },
111 "{s}tep\t\t\t Step program until it reaches a different source line.\n"
113 { "s" , cmdStep , NULL },
115 "{n}ext\t\t\t Step program, proceeding through subroutine calls.\n"
117 { "n" , cmdNext , NULL },
119 "{r}un\t\t\t Start debugged program. \n"
121 { "r" , cmdRun , NULL },
122 { "ptype" , cmdPrintType ,
123 "{pt}ype <variable>\t print type information of a variable\n"
125 { "pt" , cmdPrintType , NULL },
126 { "print" , cmdPrint ,
127 "{p}rint <variable>\t print value of given variable\n"
129 { "p" , cmdPrint , NULL },
131 "file <filename>\t\t load symbolic information from <filename>\n"
133 { "frame" , cmdFrame ,
134 "{fr}ame\t\t\t print information about the current Stack\n"
136 { "finish" , cmdFinish ,
137 "{fi}nish\t\t execute till return of current function\n"
139 { "fi" , cmdFinish , NULL },
140 { "fr" , cmdFrame , NULL },
141 { "f" , cmdFrame , NULL },
142 { "!" , cmdSimulator ,
143 "!<simulator command>\t send a command directly to the simulator\n"
145 { "." , cmdSimulator ,
146 ".{cmd}\t switch from simulator or debugger command mode\n"
149 "{q}uit\t\t\t \"Watch me now. Iam going Down. My name is Bobby Brown\"\n"
151 { "q" , cmdQuit , NULL }
154 /*-----------------------------------------------------------------*/
155 /* gc_strdup - make a string duplicate garbage collector aware */
156 /*-----------------------------------------------------------------*/
157 char *gc_strdup(const char *s)
160 ret = Safe_malloc(strlen(s)+1);
165 /*-----------------------------------------------------------------*/
166 /* alloccpy - allocate copy and return a new string */
167 /*-----------------------------------------------------------------*/
168 char *alloccpy ( char *s, int size)
175 d = Safe_malloc(size+1);
182 /*-----------------------------------------------------------------*/
183 /* resize - resizes array of type with new size */
184 /*-----------------------------------------------------------------*/
185 void **resize (void **array, int newSize)
190 vptr = Safe_realloc(array,newSize*(sizeof(void **)));
192 vptr = calloc(1, sizeof(void **));
195 fprintf(stderr,"sdcdb: out of memory \n");
203 /*-----------------------------------------------------------------*/
204 /* readCdb - reads the cdb files & puts the records into cdbLine */
206 /*-----------------------------------------------------------------*/
207 static int readCdb (FILE *file)
213 if (!(bp = fgets(buffer,sizeof(buffer),file)))
216 currl = Safe_calloc(1,sizeof(cdbrecs));
221 /* make sure this is a cdb record */
222 if (strchr("STLFM",*bp) && *(bp+1) == ':') {
223 /* depending on the record type */
228 currl->type = SYM_REC;
231 currl->type = STRUCT_REC;
234 currl->type = LNK_REC;
237 currl->type = FUNC_REC;
240 currl->type = MOD_REC ;
244 currl->line = Safe_malloc(strlen(bp));
245 strncpy(currl->line,bp,strlen(bp)-1);
246 currl->line[strlen(bp)-1] = '\0';
249 if (!(bp = fgets(buffer,sizeof(buffer),file)))
255 currl->next = Safe_calloc(1,sizeof(cdbrecs));
259 return (recsRoot->line ? 1 : 0);
262 /*-----------------------------------------------------------------*/
263 /* searchDirsFname - search directory list & return the filename */
264 /*-----------------------------------------------------------------*/
265 char *searchDirsFname (char *fname)
271 /* first try the current directory */
272 if ((rfile = fopen(fname,"r"))) {
274 return strdup(fname) ;
278 return strdup(fname);
280 /* make a copy of the source directories */
281 dirs = sdirs = strdup(ssdirl);
283 /* assume that the separator is ':'
284 and try for each directory in the search list */
285 dirs = strtok(dirs,":");
287 if (dirs[strlen(dirs)] == '/')
288 sprintf(buffer,"%s%s",dirs,fname);
290 sprintf(buffer,"%s/%s",dirs,fname);
291 if ((rfile = fopen(buffer,"r")))
293 dirs = strtok(NULL,":");
299 return strdup(buffer);
301 return strdup(fname);
304 /*-----------------------------------------------------------------*/
305 /* searchDirsFopen - go thru list of directories for filename given*/
306 /*-----------------------------------------------------------------*/
307 FILE *searchDirsFopen(char *fname)
313 /* first try the current directory */
314 if ((rfile = fopen(fname,"r")))
319 /* make a copy of the source directories */
320 dirs = sdirs = strdup(ssdirl);
322 /* assume that the separator is ':'
323 and try for each directory in the search list */
324 dirs = strtok(dirs,":");
326 sprintf(buffer,"%s/%s",dirs,fname);
327 if ((rfile = fopen(buffer,"r")))
329 dirs = strtok(NULL,":");
337 /*-----------------------------------------------------------------*/
338 /* loadFile - loads a file into module buffer */
339 /*-----------------------------------------------------------------*/
340 srcLine **loadFile (char *name, int *nlines)
345 srcLine **slines = NULL;
348 if (!(mfile = searchDirsFopen(name))) {
349 fprintf(stderr,"sdcdb: cannot open module %s -- use '--directory=<source directory> option\n",name);
353 while ((bp = fgets(buffer,sizeof(buffer),mfile))) {
356 slines = (srcLine **)resize((void **)slines,*nlines);
358 slines[(*nlines)-1] = Safe_calloc(1,sizeof(srcLine));
359 slines[(*nlines)-1]->src = alloccpy(bp,strlen(bp));
367 /*-----------------------------------------------------------------*/
368 /* loadModules - reads the source files into module structure */
369 /*-----------------------------------------------------------------*/
370 static void loadModules ()
376 /* go thru the records & find out the module
377 records & load the modules specified */
378 for ( loop = recsRoot ; loop ; loop = loop->next ) {
380 switch (loop->type) {
381 /* for module records do */
383 currMod = parseModule(loop->line,TRUE);
384 currModName = currMod->name ;
386 currMod->cfullname = searchDirsFname(currMod->c_name);
388 /* load it into buffer */
389 currMod->cLines = loadFile (currMod->c_name,
392 /* do the same for the assembler file */
393 currMod->afullname = searchDirsFname(currMod->asm_name);
394 currMod->asmLines=loadFile (currMod->asm_name,
395 &currMod->nasmLines);
398 /* if this is a function record */
400 parseFunc(loop->line);
403 /* if this is a structure record */
405 parseStruct(loop->line);
408 /* if symbol then parse the symbol */
410 parseSymbol(loop->line,&rs);
414 parseLnkRec(loop->line);
420 /*-----------------------------------------------------------------*/
421 /* functionPoints - determine the execution points within a func */
422 /*-----------------------------------------------------------------*/
423 static void functionPoints ()
428 /* for all functions do */
429 for ( func = setFirstItem(functions); func;
430 func = setNextItem(functions)) {
436 Dprintf(D_sdcdb, ("func '%s' has entry '%x' exit '%x'\n",
441 if (!func->sym->addr && !func->sym->eaddr)
444 /* for all source lines in the module find
445 the ones with address >= start and <= end
446 and put them in the point */
448 if (! applyToSet(modules,moduleWithName,func->modName,&mod))
451 func->entryline= INT_MAX;
453 func->aentryline = INT_MAX ;
456 /* do it for the C Lines first */
457 for ( j = 0 ; j < mod->ncLines ; j++ ) {
458 if (mod->cLines[j]->addr >= sym->addr &&
459 mod->cLines[j]->addr <= sym->eaddr ) {
463 /* add it to the execution point */
464 if (func->entryline > j)
467 if (func->exitline < j)
470 ep = Safe_calloc(1,sizeof(exePoint));
471 ep->addr = mod->cLines[j]->addr ;
473 ep->block= mod->cLines[j]->block;
474 ep->level= mod->cLines[j]->level;
475 addSet(&func->cfpoints,ep);
479 /* do the same for asm execution points */
480 for ( j = 0 ; j < mod->nasmLines ; j++ ) {
481 if (mod->asmLines[j]->addr >= sym->addr &&
482 mod->asmLines[j]->addr <= sym->eaddr ) {
485 /* add it to the execution point */
486 if (func->aentryline > j)
487 func->aentryline = j;
489 if (func->aexitline < j)
492 /* add it to the execution point */
493 ep = Safe_calloc(1,sizeof(exePoint));
494 ep->addr = mod->asmLines[j]->addr ;
496 addSet(&func->afpoints,ep);
501 Dprintf(D_sdcdb, ("function '%s' has the following C exePoints\n",
506 for (ep = setFirstItem(func->cfpoints); ep;
507 ep = setNextItem(func->cfpoints))
508 Dprintf(D_sdcdb, ("{%x,%d} %s",
509 ep->addr,ep->line,mod->cLines[ep->line]->src));
511 Dprintf(D_sdcdb, (" and the following ASM exePoints\n"));
512 for (ep = setFirstItem(func->afpoints); ep;
513 ep = setNextItem(func->afpoints))
514 Dprintf (D_sdcdb, ("{%x,%d} %s",
515 ep->addr,ep->line,mod->asmLines[ep->line]->src));
522 /*-----------------------------------------------------------------*/
523 /* setEntryExitBP - set the entry & exit Break Points for functions*/
524 /*-----------------------------------------------------------------*/
525 DEFSETFUNC(setEntryExitBP)
527 function *func = item;
529 if (func->sym && func->sym->addr && func->sym->eaddr) {
531 /* set the entry break point */
532 setBreakPoint (func->sym->addr , CODE , FENTRY ,
533 fentryCB ,func->mod->c_name , func->entryline);
535 /* set the exit break point */
536 setBreakPoint (func->sym->eaddr , CODE , FEXIT ,
537 fexitCB ,func->mod->c_name , func->exitline );
543 /*-----------------------------------------------------------------*/
544 /* cmdFile - load file into the debugger */
545 /*-----------------------------------------------------------------*/
546 int cmdFile (char *s,context *cctxt)
552 while (isspace(*s)) s++;
554 fprintf(stdout,"No exec file now.\nNo symbol file now.\n");
558 sprintf(buffer,"%s.cdb",s);
559 /* try creating the cdbfile */
560 if (!(cdbFile = searchDirsFopen(buffer))) {
561 fprintf(stdout,"Cannot open file\"%s\"",buffer);
565 /* allocate for context */
566 currCtxt = Safe_calloc(1,sizeof(context));
568 /* readin the debug information */
569 if (!readCdb (cdbFile)) {
570 fprintf(stdout,"No symbolic information found in file %s.cdb\n",s);
574 /* parse and load the modules required */
577 /* determine the execution points for this
581 /* start the simulator & setup connection to it */
582 openSimulator((char **)simArgs,nsimArgs);
583 fprintf(stdout,"%s",simResponse());
584 /* now send the filename to be loaded to the simulator */
585 sprintf(buffer,"%s.ihx",s);
586 bp=searchDirsFname(buffer);
590 /*set the break points
591 required by the debugger . i.e. the function entry
592 and function exit break points */
593 applyToSet(functions,setEntryExitBP);
599 /*-----------------------------------------------------------------*/
600 /* cmdHelp - help command */
601 /*-----------------------------------------------------------------*/
602 int cmdHelp (char *s, context *cctxt)
611 endline = ((*s - '0') * 20) + 20;
613 startline = endline - 20;
616 for (i = 0 ; i < (sizeof(cmdTab)/sizeof(struct cmdtab)) ; i++) {
618 /* command string matches */
620 if ((cmdTab[i].htxt) && (i >= startline))
621 fprintf(stdout,"%s",cmdTab[i].htxt);
629 #define MAX_CMD_LEN 512
630 static char cmdbuff[MAX_CMD_LEN];
631 static int sim_cmd_mode = 0;
633 /*-----------------------------------------------------------------
634 interpretCmd - interpret and do the command. Return 0 to continue,
635 return 1 to exit program.
636 |-----------------------------------------------------------------*/
637 int interpretCmd (char *s)
639 static char *pcmd = NULL;
643 /* if nothing & previous command exists then
644 execute the previous command again */
645 if (*s == '\n' && pcmd)
648 /* if previous command exists & is different
649 from the current command then copy it */
651 if (strcmp(pcmd,s)) {
658 /* lookup the command table and do the task required */
662 if (strcmp(s,".") == 0) {
666 else if (s[0] == '.') {
667 /* kill the preceeding '.' and pass on as SDCDB command */
674 cmdSimulator (s, currCtxt);
678 if (strcmp(s,".") ==0) {
684 for (i = 0 ; i < (sizeof(cmdTab)/sizeof(struct cmdtab)) ; i++) {
686 /* command string matches */
687 if (strncmp(s,cmdTab[i].cmd,strlen(cmdTab[i].cmd)) == 0) {
688 if (!cmdTab[i].cmdfunc)
691 rv = (*cmdTab[i].cmdfunc)(s + strlen(cmdTab[i].cmd),currCtxt);
693 /* if full name then give the file name & position */
694 if (fullname && currCtxt && currCtxt->func) {
695 if (srcMode == SRC_CMODE)
696 fprintf(stdout,"\032\032%s:%d:1\n",
697 currCtxt->func->mod->cfullname,
700 fprintf(stdout,"\032\032%s:%d:1\n",
701 currCtxt->func->mod->afullname,
702 currCtxt->asmline+1);
708 fprintf(stdout,"Undefined command: \"%s\". Try \"help\".\n",s);
713 /*-----------------------------------------------------------------*/
714 /* commandLoop - the main command loop */
715 /*-----------------------------------------------------------------*/
718 char *prompt = "(sdcdb) ";
719 char *sim_prompt = "(sim) ";
723 printf("%s",sim_prompt);
725 fprintf(stdout,"%s",prompt);
729 if (fgets(cmdbuff,sizeof(cmdbuff),stdin) == NULL)
733 /* make a way to go into "ucSim" mode */
734 if (cmdbuff[0] == '$') {
735 if (sim_cmd_mode) sim_cmd_mode = 0;
736 else sim_cmd_mode = 1;
741 if (interpretCmd(cmdbuff))
746 /*-----------------------------------------------------------------*/
747 /* printVersionInfo - print the version information */
748 /*-----------------------------------------------------------------*/
749 static void printVersionInfo()
752 "SDCDB is free software and you are welcome to distribute copies of it\n"
753 "under certain conditions; type \"show copying\" to see the conditions.\n"
754 "There is absolutely no warranty for SDCDB; type \"show warranty\" for details.\n"
755 "SDCDB 0.8 . Copyright (C) 1999 Sandeep Dutta (sandeep.dutta@usa.net)\n"
756 "Type ? for help\n");
760 /*-----------------------------------------------------------------*/
761 /* parseCmdLine - parse the commandline arguments */
762 /*-----------------------------------------------------------------*/
763 static void parseCmdLine (int argc, char **argv)
766 char *filename = NULL;
767 int passon_args_flag = 0; /* if true, pass on args to simulator */
769 Dprintf(D_sdcdb, ("parseCmdLine\n"));
771 for ( i = 1; i < argc ; i++) {
772 //fprintf(stdout,"%s\n",argv[i]);
774 if (passon_args_flag) { /* if true, pass on args to simulator */
775 simArgs[nsimArgs++] = strdup(argv[i]);
779 /* if this is an option */
780 if (argv[i][0] == '-') {
782 /* if directory then mark directory */
783 if (strncmp(argv[i],"--directory=",12) == 0) {
785 ssdirl = &argv[i][12];
787 char *p = Safe_malloc(strlen(ssdirl)+strlen(&argv[i][12])+2);
788 strcat(strcat(strcpy(p,&argv[i][12]),":"),ssdirl);
794 if (strncmp(argv[i],"-fullname",9) == 0) {
799 if (strcmp(argv[i],"-cd") == 0) {
805 if (strncmp(argv[i],"-cd=",4) == 0) {
811 if (strncmp(argv[i],"-m",2) == 0) {
812 strncpy(model_str, &argv[i][2], 15);
813 if (strcmp(model_str,"avr") == 0)
815 else if (strcmp(model_str,"xa") == 0)
817 else if (strcmp(model_str,"z80") == 0)
822 /* -z all remaining options are for simulator */
823 if (strcmp(argv[i],"-z") == 0) {
824 passon_args_flag = 1;
828 /* the simulator arguments */
831 if (strcmp(argv[i],"-t") == 0 ||
832 strcmp(argv[i],"-cpu") == 0) {
834 simArgs[nsimArgs++] = "-t";
835 simArgs[nsimArgs++] = strdup(argv[++i]);
840 if (strcmp(argv[i],"-X") == 0 ||
841 strcmp(argv[i],"-frequency") == 0) {
842 simArgs[nsimArgs++] = "-X";
843 simArgs[nsimArgs++] = strdup(argv[++i]);
848 if ( (strcmp(argv[i],"-S") == 0) ||
849 (strcmp(argv[i],"-s") == 0)) {
850 simArgs[nsimArgs++] = "-s";
851 simArgs[nsimArgs++] = strdup(argv[++i]);
855 fprintf(stderr,"unknown option %s --- ignored\n",
859 /* must be file name */
861 fprintf(stderr,"too many filenames .. parameter '%s' ignored\n",
866 filename = strtok(argv[i],".");
872 cmdFile(filename,NULL);
875 /*-----------------------------------------------------------------*/
877 /*-----------------------------------------------------------------*/
879 int main ( int argc, char **argv)
882 printf("WARNING: SDCDB is EXPERIMENTAL and NOT A FULLY FUNCTIONING TOOL.\n");
884 simArgs[nsimArgs++] = "s51";
885 simArgs[nsimArgs++] = "-P";
886 simArgs[nsimArgs++] = "-r 9756";
887 /* parse command line */
889 parseCmdLine(argc,argv);