home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Exec 5 / CD_Magazyn_EXEC_nr_5.iso / Programy / Programowanie / PPC / wosdb_src.lzx / stdui.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-02-13  |  17.2 KB  |  652 lines

  1. /* $VER: stdui.c V0.4c (12.02.01)
  2.  *
  3.  * This file is part of the WarpOS debugger 'wosdb'
  4.  * Copyright (c) 1999-2001  Frank Wille
  5.  *
  6.  *
  7.  * v0.4c (12.02.01) phx
  8.  *       The 'g'-command with an unknown symbol caused a data access
  9.  *       exception.
  10.  *       Updated to year 2001.
  11.  * v0.3b (30.01.00) phx
  12.  *       Updated to year 2000.
  13.  * v0.3a (06.05.99) phx
  14.  *       '?' is not repeatable.
  15.  *       The program to be debugged may have an argument string.
  16.  * v0.3  (04.05.99) phx
  17.  *       'S' shows all symbols.
  18.  * v0.2  (02.05.99) phx
  19.  *       Disassembly and memory dump display only valid memory regions.
  20.  *       Command 'tb' shows stack frame trace-back.
  21.  * v0.1  (01.05.99) phx
  22.  *       First usable version.
  23.  * v0.0  (17.04.99) phx
  24.  *       File created.
  25.  */
  26.  
  27. #include <powerpc/powerpc.h>
  28. #include <stdlib.h>
  29. #include <stdio.h>
  30. #include <string.h>
  31. #include "debugger.h"
  32.  
  33.  
  34. /* status() */
  35. #define ST_EXC 1        /* print name of exception */
  36. #define ST_SPEC 2       /* print all special registers */
  37. #define ST_FPR 4        /* print FPU registers */
  38.  
  39.  
  40. static struct EXCContext *dbcontext;
  41. static int taskloaded = 0;
  42.  
  43.  
  44. static char *get_option_arg(int,char *[],int *);
  45. static void show_version();
  46. static void show_help();
  47. static void debugger_loop(char *,char *);
  48.  
  49.  
  50.  
  51. main(int argc,char *argv[])
  52. {
  53.   static char argbuf[1024];
  54.   char *p = argbuf;
  55.   int i;
  56.   char *filename = NULL;
  57.  
  58.   /* parse arguments */
  59.   for (i=1; i<argc; i++) {
  60.     if (filename) {
  61.       char *s = argv[i];
  62.  
  63.       *p++ = ' ';
  64.       while (*p = *s++)
  65.         p++;
  66.     }
  67.     else {
  68.       if (argv[i][0] == '-') {
  69.         switch (argv[i][1]) {
  70.  
  71.           case 'h':
  72.           case '?':
  73.             show_help();
  74.             exit(1);
  75.  
  76.           case 'v':
  77.             show_version();
  78.             exit(1);
  79.  
  80.           default:
  81.             printf("Unknown option '%c' ignored.\n",argv[i][1]);
  82.             break;
  83.         }
  84.       }
  85.       else
  86.         filename = argv[i];
  87.     }
  88.   }
  89.  
  90.   *p++ = '\n';
  91.   *p = '\0';
  92.   debugger_loop(filename,argbuf);
  93.   exit(0);
  94. }
  95.  
  96.  
  97. static char *get_option_arg(int argc,char *argv[],int *i)
  98. /* get pointer to the string, which either directly follows the option
  99.    character or is stored in the next argument */
  100. {
  101.   if (argv[*i][2])
  102.     return (&argv[*i][2]);
  103.   else {
  104.     if (++*i<argc) {
  105.       if (argv[*i][0]!='-' || isdigit(argv[*i][1]))  /* another option? */
  106.         return (argv[*i]);
  107.       else
  108.         --*i;
  109.     }
  110.   }
  111.   return NULL;
  112. }
  113.  
  114.  
  115. static void show_version()
  116. {
  117.   printf(NAME " V%d.%d%c (c)1999-2001 by Frank Wille\n"
  118.          "build date: " __DATE__ ", " __TIME__ "\n\n",
  119.          VERSION,REVISION,PLEVEL?('a'+PLEVEL-1):' ');
  120. }
  121.  
  122.  
  123. static void show_help()
  124. {
  125.   show_version();
  126.  
  127.   printf("\nUsage: " NAME " [-hv?] [file name] [arguments]\n");
  128. }
  129.  
  130.  
  131. static void printgpr()
  132. {
  133.   int i;
  134.   char r[8];
  135.  
  136.   for (i=0; i<32; i++) {
  137.     if (i%8 == 0) {
  138.       sprintf(r,"R%d-R%d:",i,i+7);
  139.       printf("%-8s ",r);
  140.     }
  141.     printf("%08lx%c",dbcontext->ec_GPR[i],(i%8==7)?'\n':' ');
  142.   }
  143. }
  144.  
  145.  
  146. static void printfpr()
  147. {
  148.   int i;
  149.   char r[8];
  150.  
  151.   for (i=0; i<32; i++) {
  152.     if (i%4 == 0) {
  153.       sprintf(r,"F%d-F%d:",i,i+3);
  154.       printf("%-8s    ",r);
  155.     }
  156.     printf("%-16.4e",dbcontext->ec_FPR[i]);
  157.     if (i%4 == 3)
  158.       printf("\n");
  159.   }
  160. }
  161.  
  162.  
  163. static void printregs(int fpr)
  164. {
  165.   printf("MSR:   %08lx   XER:   %08lx   CR:    %08lx   FPSCR: %08lx\n"
  166.          "LR:    %08lx   CTR:   %08lx\n\n",
  167.          dbcontext->ec_SRR1,
  168.          dbcontext->ec_XER,
  169.          dbcontext->ec_CR,
  170.          dbcontext->ec_FPSCR,
  171.          dbcontext->ec_LR,
  172.          dbcontext->ec_CTR);
  173.   printgpr();
  174.   if (fpr) {
  175.     printf("\n");
  176.     printfpr();
  177.   }
  178. }
  179.  
  180.  
  181. static void printspecregs()
  182. {
  183.   struct SpecRegs *sr = wosdb_getspecregs();
  184.  
  185.   printf("HID0:  %08lx   HID1:  %08lx   TBL:   %08lx   TBU:   %08lx\n"
  186.          "PVR:   %08lx   DEC:   %08lx   SDR1:  %08lx   EAR:   %08lx\n"
  187.          "SRR0:  %08lx   SRR1:  %08lx   DAR:   %08lx   DSISR: %08lx\n",
  188.          sr->srHID0,sr->srHID1,sr->srTBL,sr->srTBU,
  189.          sr->srPVR,sr->srDEC,sr->srSDR1,sr->srEAR,
  190.          dbcontext->ec_UPC.ec_SRR0,dbcontext->ec_SRR1,
  191.          dbcontext->ec_DAR,dbcontext->ec_DSISR);
  192. }
  193.  
  194.  
  195. static void printinstr(ADDR addr)
  196. {
  197.   struct Breakpoint *bp;
  198.   struct DisasmPara_PPC dp;
  199.   char opcode[10];
  200.   char operands[256];
  201.   char *lab;
  202.  
  203.   if (wosdb_validaddr(addr) != 0) {
  204.     dp.opcode = opcode;
  205.     dp.operands = operands;
  206.     dp.instr = dp.iaddr = (ppc_word *)addr;
  207.     bp = wosdb_hidebreakpoint((ADDR)dp.iaddr);
  208.     PPC_Disassemble(&dp);
  209.  
  210.     wosdb_opersymbols(&dp,256);
  211.     if (lab = wosdb_label(addr))
  212.       printf("%-26.26s%c%-7s %s\n",lab,bp?'>':' ',opcode,operands);
  213.     else
  214.       printf("%08lx:  %08lx       %c%-7s %s\n",
  215.              (ULONG)addr,*(ULONG *)addr,bp?'>':' ',opcode,operands);
  216.     wosdb_showbreakpoint(bp);
  217.   }
  218.  
  219.   else
  220.     printf("%08lx:  ********        ---     ---\n",(ULONG)addr);
  221. }
  222.  
  223.  
  224. static void printasc(unsigned char *p,int sep,int cnt)
  225. {
  226.   unsigned char c;
  227.   char buf[20];
  228.   int i,v;
  229.  
  230.   for (i=0; i<sep; buf[i++]=' ');
  231.   for (i=0; i<cnt; i++) {
  232.     if ((i&3)==0)
  233.       v = wosdb_validaddr((ADDR)p);
  234.     if (v != 0) {
  235.       c = *p++;
  236.       buf[sep+i] = (char)((((c)>=0x20 && (c)<=0x7e) ||
  237.                          ((c)>=0xa0 && (c)!=0xad)) ? c : '.');
  238.     }
  239.     else
  240.       buf[sep+i] = '.';
  241.   }
  242.   buf[sep+cnt] = '\0';
  243.   printf("%s\n",buf);
  244. }
  245.  
  246.  
  247. static void printbreakpoints(struct MinList *bplist)
  248. {
  249.   struct Breakpoint *b,*next;
  250.   int n=1;
  251.   char *lab;
  252.  
  253.   for (b = (struct Breakpoint *)(bplist->mlh_Head);
  254.        next = (struct Breakpoint *)b->n.mln_Succ; b = next) {
  255.     printf("#%d: 0x%08lx %c",n++,(ULONG)b->addr,b->temporary?'T':' ');
  256.     if (lab = wosdb_label(b->addr))
  257.       printf(" %s\n",lab);
  258.     else
  259.       printf("\n");
  260.   }
  261. }
  262.  
  263.  
  264. static void status(int flags)
  265. {
  266.   if (flags & ST_EXC)
  267.     printf("\n%s\n",wosdb_exceptinfo());
  268.   if (flags & ST_SPEC)
  269.     printspecregs();
  270.   printregs(flags & ST_FPR);
  271.   printf("\n");
  272.   printinstr((ADDR)dbcontext->ec_UPC.ec_PC);
  273. }
  274.  
  275.  
  276. static void finished()
  277. {
  278.   printf("Task finished. Return code = 0x%08lx\n",wosdb_taskresult());
  279.   taskloaded = 0;
  280. }
  281.  
  282.  
  283. static char *skipeq(char *p)
  284. {
  285.   while (*p != '=' && *p != '\0')
  286.     p++;
  287.   if (*p++ == '\0')
  288.     return (NULL);
  289.   while (isspace((unsigned char)*p))
  290.     p++;
  291.   return (p);
  292. }
  293.  
  294.  
  295. static void printhelp()
  296. {
  297.   printf("+\t\tskip to next instruction\n");
  298.   printf("-\t\tskip to previous instruction\n");
  299.   printf("?\t\tshow help\n");
  300.   printf("? <exp>\t\tevaluate expression\n");
  301.   printf("@r<n> = <exp>\tset GP register\n");
  302.   printf("@f<n> = <flt>\tset FPU register\n");
  303.   printf("L \"name\" [args]\tload WOS program for debugging\n");
  304.   printf("U\t\tunload current program\n");
  305.   printf("S\t\tshow all symbols\n");
  306.   printf("b\t\tshow all breakpoints\n");
  307.   printf("b <exp>\t\tset breakpoint\n");
  308.   printf("bt <exp>\tset temporary breakpoint\n");
  309.   printf("bc <exp>\tclear breakpoint\n");
  310.   printf("--press return--");
  311.   getchar();
  312.   printf("d [<exp>]\tdisassemble\n");
  313.   printf("fpr\t\tshow FPU registers\n");
  314.   printf("g\t\trun program\n");
  315.   printf("g <exp>\t\trun program until address reached\n");
  316.   printf("gpr\t\tshow GP registers\n");
  317.   printf("m [<exp>]\tmemory dump\n");
  318.   printf("n\t\tbreak at next instruction\n");
  319.   printf("r\t\tshow all registers and current instruction\n");
  320.   printf("s\t\tstep single instruction\n");
  321.   printf("tb\t\tshow stack frame trace-back\n");
  322.   printf("x\t\texit debugger, unload debug task\n");
  323. }
  324.  
  325.  
  326. static void debugger_loop(char *filename,char *start_args)
  327. {
  328.   char cmdbuf[80],lastcmdbuf[80];
  329.   int i,r,exit = 0;
  330.   ULONG xcid,x;
  331.   ADDR addr = 0;  /* current addr for mem-dump or disassembly */
  332.   int nlines = 8; /* number of lines to display for mem-dump/disasm. */
  333.   char *s;
  334.   struct Breakpoint *bp;
  335.   struct LoadFile *lf;
  336.  
  337.   printf("\n** " NAME " V%d.%d%c\n"
  338.          "** (c)1999-2001 by Frank Wille <frank@phoenix.owl.de>\n",
  339.          VERSION,REVISION,PLEVEL?('a'+PLEVEL-1):' ');
  340.  
  341.   if (dbcontext = wosdb_init()) {
  342.     if (filename) {
  343.       /* load and stop WOS program */
  344.       if (lf = wosdb_load(filename,start_args)) {
  345.         printf("Loaded %d sections with %d symbols.\n",
  346.                lf->sections,lf->symbols);
  347.         status(ST_EXC|ST_SPEC|ST_FPR);  /* show regs and cur. instruction */
  348.         taskloaded = 1;
  349.       }
  350.       else {
  351.         printf("Can't load \"%s\".\n",filename);
  352.       }
  353.     }
  354.  
  355.     /* the main loop */
  356.     while (!exit) {
  357.       printf("wosdb>");
  358.       fflush(stdout);
  359.       gets(cmdbuf);
  360.       if (cmdbuf[0] == '\0')
  361.         strcpy(cmdbuf,lastcmdbuf);
  362.       else
  363.         strcpy(lastcmdbuf,cmdbuf);
  364.  
  365.       switch (cmdbuf[0]) {
  366.  
  367.         case '+':                              /* PC++ */
  368.           if (!taskloaded)
  369.             break;
  370.           printinstr((ADDR)(dbcontext->ec_UPC.ec_SRR0 += 4));
  371.           break;
  372.  
  373.         case '-':                              /* PC-- */
  374.           if (!taskloaded)
  375.             break;
  376.           printinstr((ADDR)(dbcontext->ec_UPC.ec_SRR0 -= 4));
  377.           break;
  378.  
  379.         case '?':                              /* display expression */
  380.           if (cmdbuf[1] == ' ') {
  381.             x = wosdb_getexp(&cmdbuf[2]);
  382.             printf("= 0x%08lx\n= %ld\n",x,(long)x);
  383.           }
  384.           else {                               /* print help */
  385.             printhelp();
  386.             lastcmdbuf[0] = '\0';
  387.           }
  388.           break;
  389.  
  390.         case '@':                              /* set register */
  391.           if (!taskloaded)
  392.             break;
  393.           if (cmdbuf[1] == 'r' || cmdbuf[1] == 'R') {
  394.             sscanf(&cmdbuf[2],"%i",&r);
  395.             if (s = skipeq(&cmdbuf[2]))
  396.               dbcontext->ec_GPR[r] = (ULONG)wosdb_getexp(s);
  397.           }
  398.           else if (cmdbuf[1] == 'f' || cmdbuf[1] == 'F') {
  399.             sscanf(&cmdbuf[2],"%i",&r);
  400.             if (s = skipeq(&cmdbuf[2])) {
  401.               double df;
  402.  
  403.               sscanf(s,"%lf",&df);
  404.               dbcontext->ec_FPR[r] = df;
  405.             }
  406.           }
  407.           break;
  408.  
  409.         case 'L':                              /* load program */
  410.           if (taskloaded) {
  411.             printf("Unloading current task.\n");
  412.             wosdb_unload();
  413.             taskloaded = 0;
  414.           }
  415.           if (cmdbuf[1] == ' ') {
  416.             static char fname[256];
  417.             static char args[1024];
  418.             char *a = args;
  419.  
  420.             /* get program name and arguments */
  421.             s = &cmdbuf[2];
  422.             i = 0;
  423.             while (*s != '\"' && *s != '\0')
  424.               s++;
  425.             if (*s == '\"') {
  426.               s++;
  427.               while (*s != '\"' && *s != '\0')
  428.                 fname[i++] = *s++;
  429.               fname[i] = '\0';
  430.               if (*s == '\"')
  431.                 s++;
  432.               while (isspace((unsigned char)*s))
  433.                 s++;
  434.               while (*a = *s++)
  435.                 a++;
  436.               *a++ = '\n';
  437.               *a = '\0';
  438.  
  439.               /* load and stop WOS program */
  440.               if (lf = wosdb_load(fname,args)) {
  441.                 printf("Loaded %d sections with %d symbols.\n",
  442.                        lf->sections,lf->symbols);
  443.                 status(ST_EXC|ST_SPEC|ST_FPR);
  444.                 taskloaded = 1;
  445.               }
  446.               else {
  447.                 printf("Can't load \"%s\".\n",fname);
  448.                 taskloaded = 0;
  449.               }
  450.               break;
  451.             }
  452.           }
  453.           printf("Missing file name.\n");
  454.           break;
  455.  
  456.         case 'S':                              /* print all symbols */
  457.           if (taskloaded) {
  458.             struct Section *sec = lf->firstsec;
  459.             struct Symbol *sym;
  460.             int scnt=0;
  461.  
  462.             while (sec) {
  463.               printf("Section %d at 0x%08lx size 0x%08lx:\n",
  464.                      scnt++,(ULONG)sec->addr,sec->len);
  465.               sym = sec->symbols;
  466.               while (sym) {
  467.                 printf("\t0x%08lx  %s\n",(ULONG)sym->addr,sym->name);
  468.                 sym = sym->next;
  469.               }
  470.               sec = sec->next;
  471.             }
  472.           }
  473.           break;
  474.  
  475.         case 'U':                              /* unload program */
  476.           if (taskloaded) {
  477.             printf("Unloading current task.\n");
  478.             wosdb_unload();
  479.             taskloaded = 0;
  480.           }
  481.           break;
  482.  
  483.         case 'b':                              /* breakpoint */
  484.           if (!taskloaded)
  485.             break;
  486.           if (cmdbuf[1] == ' ') {
  487.             /* set normal breakpoint */
  488.             if (!wosdb_setbreakpoint((ADDR)wosdb_getexp(&cmdbuf[2])))
  489.               printf("Can't set breakpoint!\n");
  490.           }
  491.           else if (cmdbuf[1] == 'c' && cmdbuf[2] == ' ') {
  492.             /* clear breakpoint */
  493.             wosdb_clearbreakpoint((ADDR)wosdb_getexp(&cmdbuf[3]));
  494.           }
  495.           else if (cmdbuf[1] == 't' && cmdbuf[2] == ' ') {
  496.             /* set temporary breakpoint */
  497.             if (!wosdb_tempbreakpoint((ADDR)wosdb_getexp(&cmdbuf[3])))
  498.               printf("Can't set temporary breakpoint!\n");
  499.           }
  500.           else {
  501.             /* show all breakpoints */
  502.             printbreakpoints(lf->breakpoints);
  503.           }
  504.           break;
  505.  
  506.         case 'd':                              /* disassemble */
  507.           if (cmdbuf[1] == ' ') {
  508.             addr = (ADDR)((ULONG)wosdb_getexp(&cmdbuf[2]) & ~3);
  509.             lastcmdbuf[1] = '\0';
  510.           }
  511.           for (i=0; i<nlines; i++,addr+=4) {
  512.             printinstr(addr);
  513.           }
  514.           break;
  515.  
  516.         case 'f':                             /* show fpr */
  517.           if (!taskloaded)
  518.             break;
  519.           if (cmdbuf[1] == 'p' && cmdbuf[2] == 'r') {
  520.             /* show floating point registers */
  521.             printfpr();
  522.           }
  523.           break;
  524.  
  525.         case 'g':                              /* go, show gpr */
  526.           if (!taskloaded)
  527.             break;
  528.           if (cmdbuf[1] == 'p' && cmdbuf[2] == 'r') {
  529.             /* show general purpose registers */
  530.             printgpr();
  531.           }
  532.           else if (cmdbuf[1] == ' ') {
  533.             /* run until address reached */
  534.             ADDR bpt = (ADDR)wosdb_getexp(&cmdbuf[2]);
  535.  
  536.             if (bpt) {
  537.               wosdb_tempbreakpoint(bpt);
  538.               xcid = wosdb_cont(FALSE,FALSE); /* run until breakpoint reached */
  539.               if (xcid==EXCF_FINISHED)
  540.                 finished();
  541.               else
  542.                 status(xcid==EXCF_BRKPT ? 0 : ST_EXC|ST_SPEC);
  543.             }
  544.           }
  545.           else {
  546.             /* run until end */
  547.             xcid = wosdb_cont(FALSE,FALSE);
  548.             if (xcid==EXCF_FINISHED)
  549.               finished();
  550.             else
  551.               status(xcid==EXCF_BRKPT ? 0 : ST_EXC|ST_SPEC);
  552.           }
  553.           break;
  554.  
  555.         case 'm':                              /* memory dump */
  556.           if (cmdbuf[1] == ' ') {
  557.             addr = (ADDR)((ULONG)wosdb_getexp(&cmdbuf[2]) & ~3);
  558.             lastcmdbuf[1] = '\0';
  559.           }
  560.           for (i=0; i<(nlines*4); i++,addr+=4) {
  561.             if (s = wosdb_label(addr)) {
  562.               if (i&3) {
  563.                 char spc[32];
  564.                 int si;
  565.  
  566.                 for (si=0; si<(4-(i&3))*9; spc[si++]=' ');
  567.                 spc[si] = '\0';
  568.                 printf("%s",spc);
  569.                 printasc(addr-(i&3)*4,3,(i&3)*4);
  570.                 if ((i = (i+3) & ~3) >= (nlines*4))
  571.                   break;
  572.               }
  573.               printf("%-15.15s ",s);
  574.             }
  575.             else if ((i&3) == 0)
  576.               printf("%08lx:       ",(ULONG)addr);
  577.  
  578.             if (wosdb_validaddr(addr) != 0) {
  579.               bp = wosdb_hidebreakpoint(addr);
  580.               printf("%08lx ",*(ULONG *)addr);
  581.               wosdb_showbreakpoint(bp);
  582.             }
  583.             else
  584.               printf("******** ");
  585.             if ((i&3) == 3)
  586.               printasc(addr-12,3,16);
  587.           }
  588.           break;
  589.  
  590.         case 'n':                              /* next */
  591.           if (!taskloaded)
  592.             break;
  593.           wosdb_tempbreakpoint((ADDR)dbcontext->ec_UPC.ec_PC + 4);
  594.           xcid = wosdb_cont(FALSE,FALSE);  /* break at next instruction */
  595.           if (xcid==EXCF_FINISHED)
  596.             finished();
  597.           else
  598.             status(xcid==EXCF_BRKPT ? 0 : ST_EXC|ST_SPEC);
  599.           break;
  600.  
  601.         case 'r':                              /* show registers */
  602.           if (!taskloaded)
  603.             break;
  604.           status(ST_EXC|ST_SPEC|ST_FPR);  /* show regs and cur. instruction */
  605.           break;
  606.  
  607.         case 's':                              /* step */
  608.           if (!taskloaded)
  609.             break;
  610.           xcid = wosdb_cont(TRUE,FALSE);  /* step one instruction */
  611.           if (xcid==EXCF_FINISHED)
  612.             finished();
  613.           else
  614.             status(xcid==EXCF_TRACE ? 0 : ST_EXC|ST_SPEC);
  615.           break;
  616.  
  617.         case 't':                              /* stack frame trace-back */
  618.           if (cmdbuf[1] == 'b') {
  619.             int depth = 0;
  620.             ULONG *tb = (ULONG *)dbcontext->ec_GPR[1];
  621.             ADDR ra;
  622.  
  623.             if (!taskloaded)
  624.               break;
  625.             while (tb = (ULONG *)*tb) {
  626.               ra = (ADDR)*(tb+2);
  627.               if (wosdb_validaddr(ra) != 0) {
  628.                 printf("\n> Level %d: Stack Frame 0x%08lx"
  629.                        "  Return Addr 0x%08lx",
  630.                        ++depth,(ULONG)tb,(ULONG)ra);
  631.                 if (s = wosdb_symbol(ra))
  632.                   printf(" %s\n",s);
  633.                 else
  634.                   printf("\n");
  635.                 printinstr(ra-4);
  636.               }
  637.             }
  638.           }
  639.           break;
  640.  
  641.         case 'x':                              /* exit */
  642.           exit = 1;  /* exit debugger */
  643.           if (taskloaded)
  644.             wosdb_unload();
  645.           break;
  646.       }
  647.     }
  648.  
  649.     wosdb_exit();
  650.   }
  651. }
  652.