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 = DATADIR LIB_DIR_SUFFIX ":" DATADIR LIB_DIR_SUFFIX "/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\", no symbolic information loaded\n",buffer);
565 /* allocate for context */
566 currCtxt = Safe_calloc(1,sizeof(context));
569 /* readin the debug information */
570 if (!readCdb (cdbFile)) {
571 fprintf(stdout,"No symbolic information found in file %s.cdb\n",s);
576 /* parse and load the modules required */
579 /* determine the execution points for this
583 /* start the simulator & setup connection to it */
584 openSimulator((char **)simArgs,nsimArgs);
585 fprintf(stdout,"%s",simResponse());
586 /* now send the filename to be loaded to the simulator */
587 sprintf(buffer,"%s.ihx",s);
588 bp=searchDirsFname(buffer);
592 /*set the break points
593 required by the debugger . i.e. the function entry
594 and function exit break points */
595 applyToSet(functions,setEntryExitBP);
601 /*-----------------------------------------------------------------*/
602 /* cmdHelp - help command */
603 /*-----------------------------------------------------------------*/
604 int cmdHelp (char *s, context *cctxt)
613 endline = ((*s - '0') * 20) + 20;
615 startline = endline - 20;
618 for (i = 0 ; i < (sizeof(cmdTab)/sizeof(struct cmdtab)) ; i++) {
620 /* command string matches */
622 if ((cmdTab[i].htxt) && (i >= startline))
623 fprintf(stdout,"%s",cmdTab[i].htxt);
631 #define MAX_CMD_LEN 512
632 static char cmdbuff[MAX_CMD_LEN];
633 static int sim_cmd_mode = 0;
635 /*-----------------------------------------------------------------
636 interpretCmd - interpret and do the command. Return 0 to continue,
637 return 1 to exit program.
638 |-----------------------------------------------------------------*/
639 int interpretCmd (char *s)
641 static char *pcmd = NULL;
645 /* if nothing & previous command exists then
646 execute the previous command again */
647 if (*s == '\n' && pcmd)
650 /* if previous command exists & is different
651 from the current command then copy it */
653 if (strcmp(pcmd,s)) {
660 /* lookup the command table and do the task required */
664 if (strcmp(s,".") == 0) {
668 else if (s[0] == '.') {
669 /* kill the preceeding '.' and pass on as SDCDB command */
676 cmdSimulator (s, currCtxt);
680 if (strcmp(s,".") ==0) {
686 for (i = 0 ; i < (sizeof(cmdTab)/sizeof(struct cmdtab)) ; i++) {
688 /* command string matches */
689 if (strncmp(s,cmdTab[i].cmd,strlen(cmdTab[i].cmd)) == 0) {
690 if (!cmdTab[i].cmdfunc)
693 rv = (*cmdTab[i].cmdfunc)(s + strlen(cmdTab[i].cmd),currCtxt);
695 /* if full name then give the file name & position */
696 if (fullname && currCtxt && currCtxt->func) {
697 if (srcMode == SRC_CMODE)
698 fprintf(stdout,"\032\032%s:%d:1\n",
699 currCtxt->func->mod->cfullname,
702 fprintf(stdout,"\032\032%s:%d:1\n",
703 currCtxt->func->mod->afullname,
704 currCtxt->asmline+1);
710 fprintf(stdout,"Undefined command: \"%s\". Try \"help\".\n",s);
715 /*-----------------------------------------------------------------*/
716 /* commandLoop - the main command loop */
717 /*-----------------------------------------------------------------*/
720 char *prompt = "(sdcdb) ";
721 char *sim_prompt = "(sim) ";
725 printf("%s",sim_prompt);
727 fprintf(stdout,"%s",prompt);
731 if (fgets(cmdbuff,sizeof(cmdbuff),stdin) == NULL)
735 /* make a way to go into "ucSim" mode */
736 if (cmdbuff[0] == '$') {
737 if (sim_cmd_mode) sim_cmd_mode = 0;
738 else sim_cmd_mode = 1;
743 if (interpretCmd(cmdbuff))
748 /*-----------------------------------------------------------------*/
749 /* printVersionInfo - print the version information */
750 /*-----------------------------------------------------------------*/
751 static void printVersionInfo()
754 "SDCDB is free software and you are welcome to distribute copies of it\n"
755 "under certain conditions; type \"show copying\" to see the conditions.\n"
756 "There is absolutely no warranty for SDCDB; type \"show warranty\" for details.\n"
757 "SDCDB 0.8 . Copyright (C) 1999 Sandeep Dutta (sandeep.dutta@usa.net)\n"
758 "Type ? for help\n");
762 /*-----------------------------------------------------------------*/
763 /* parseCmdLine - parse the commandline arguments */
764 /*-----------------------------------------------------------------*/
765 static void parseCmdLine (int argc, char **argv)
768 char *filename = NULL;
769 int passon_args_flag = 0; /* if true, pass on args to simulator */
771 Dprintf(D_sdcdb, ("parseCmdLine\n"));
773 for ( i = 1; i < argc ; i++) {
774 //fprintf(stdout,"%s\n",argv[i]);
776 if (passon_args_flag) { /* if true, pass on args to simulator */
777 simArgs[nsimArgs++] = strdup(argv[i]);
781 /* if this is an option */
782 if (argv[i][0] == '-') {
784 /* if directory then mark directory */
785 if (strncmp(argv[i],"--directory=",12) == 0) {
787 ssdirl = &argv[i][12];
789 char *p = Safe_malloc(strlen(ssdirl)+strlen(&argv[i][12])+2);
790 strcat(strcat(strcpy(p,&argv[i][12]),":"),ssdirl);
796 if (strncmp(argv[i],"-fullname",9) == 0) {
801 if (strcmp(argv[i],"-cd") == 0) {
807 if (strncmp(argv[i],"-cd=",4) == 0) {
813 if (strncmp(argv[i],"-m",2) == 0) {
814 strncpy(model_str, &argv[i][2], 15);
815 if (strcmp(model_str,"avr") == 0)
817 else if (strcmp(model_str,"xa") == 0)
819 else if (strcmp(model_str,"z80") == 0)
824 /* -z all remaining options are for simulator */
825 if (strcmp(argv[i],"-z") == 0) {
826 passon_args_flag = 1;
830 /* the simulator arguments */
833 if (strcmp(argv[i],"-t") == 0 ||
834 strcmp(argv[i],"-cpu") == 0) {
836 simArgs[nsimArgs++] = "-t";
837 simArgs[nsimArgs++] = strdup(argv[++i]);
842 if (strcmp(argv[i],"-X") == 0 ||
843 strcmp(argv[i],"-frequency") == 0) {
844 simArgs[nsimArgs++] = "-X";
845 simArgs[nsimArgs++] = strdup(argv[++i]);
850 if ( (strcmp(argv[i],"-S") == 0) ||
851 (strcmp(argv[i],"-s") == 0)) {
852 simArgs[nsimArgs++] = "-s";
853 simArgs[nsimArgs++] = strdup(argv[++i]);
857 fprintf(stderr,"unknown option %s --- ignored\n",
861 /* must be file name */
863 fprintf(stderr,"too many filenames .. parameter '%s' ignored\n",
868 filename = strtok(argv[i],".");
874 cmdFile(filename,NULL);
877 /*-----------------------------------------------------------------*/
879 /*-----------------------------------------------------------------*/
881 int main ( int argc, char **argv)
884 printf("WARNING: SDCDB is EXPERIMENTAL and NOT A FULLY FUNCTIONING TOOL.\n");
886 simArgs[nsimArgs++] = "s51";
887 simArgs[nsimArgs++] = "-P";
888 simArgs[nsimArgs++] = "-r 9756";
889 /* parse command line */
891 parseCmdLine(argc,argv);