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

  1. /* $VER: debugger.c V0.4a (05.03.00)
  2.  *
  3.  * This file is part of the WarpOS debugger 'wosdb'
  4.  * Copyright (c) 1999-2001  Frank Wille
  5.  *
  6.  *
  7.  * v0.4a (05.03.00) phx
  8.  *       HUNK_RELOC32SHORT or HUNK_DREL32 hunks are correctly recognized now.
  9.  * v0.4  (26.02.00) phx
  10.  *       Fixed wosdb_symbol(), which returns the correct symbol for
  11.  *       stack frame trace backs now. Didn't work before, because symbols
  12.  *       are not sorted by address.
  13.  * v0.3a (07.05.99) phx
  14.  *       wosdb_load() allows passing of an argument string to the
  15.  *       program to be debugged.
  16.  *       "@_..." and "@x..." symbol names are recognized.
  17.  * v0.3  (04.05.99) phx
  18.  *       Replaced initial LR of debugged task by an own ProgramExit()
  19.  *       function, which notifies the debugger about the task's termination.
  20.  *       Stepping into or setting a breakpoint in ProgramExit() leads to
  21.  *       an immediate termination of the debugged task.
  22.  * v0.2  (02.05.99) phx
  23.  *       wosdb_validaddr(): checks whether an address belongs to the
  24.  *       debugged program.
  25.  * v0.1  (01.05.99) phx
  26.  *       First usable version.
  27.  * v0.0  (17.04.99) phx
  28.  *       File created.
  29.  */
  30.  
  31. #include <stdio.h>
  32. #include <ctype.h>
  33. #include <exec/execbase.h>
  34. #include <exec/memory.h>
  35. #include <dos/dos.h>
  36. #include <dos/dostags.h>
  37. #include <dos/doshunks.h>
  38. #include <powerpc/powerpc.h>
  39. #include <powerpc/tasksPPC.h>
  40. #include <proto/exec.h>
  41. #include <proto/dos.h>
  42. #include <proto/powerpc.h>
  43. #include "debugger.h"
  44.  
  45.  
  46. APTR oldRunPPC;             /* original RunPPC() vector */
  47. extern LONG newRunPPC();    /* new RunPPC() function (68k) */
  48.  
  49. /* the exception handlers (PPC assembler source) */
  50. extern ULONG ExceptionCatch(struct EXCContext *);
  51. extern ULONG ExceptionLeave(struct EXCContext *);
  52. extern ULONG ProgramExit(ULONG);  /* notifies debugger */
  53. extern void ProgramExitEnd();
  54. extern void clearIABR(void);
  55. extern ULONG readIABR(void);
  56.  
  57. /* exceptions */
  58. struct EXCContext ec;
  59. struct SpecRegs spr;
  60. struct TaskPPC *thisTask;       /* this task */
  61. struct TaskPPC *dbTask = NULL;  /* debugged task */
  62. int sigExcept;                  /* task-exception signal */
  63. int sigFinish;                  /* task-finished signal */
  64. int sigRun = SIGBREAKB_CTRL_D;  /* continue debugged task */
  65. BOOL sTrace = FALSE;            /* single step trace mode */
  66. BOOL bTrace = FALSE;            /* branch trace mode */
  67.  
  68. /* debugged task */
  69. ULONG initialLR;                /* init. LR (return addr) of debugged task */
  70. ULONG result;                   /* result code of a finished PPC task */
  71. static BOOL taskloaded = FALSE;
  72. static ULONG stacksize = 0x10000;
  73. static int priority = 0;
  74. static void *xhdlC = NULL;      /* exception handler locks (catch/leave) */
  75. static void *xhdlL = NULL;
  76. static void *taskpool = NULL;   /* mem pool for all task allocations */
  77. static int nSecs;               /* number of sections (68k section incl.) */
  78. static int nSyms;               /* number of total symbols */
  79. static struct Section *firstSec;/* first section of debugged task */
  80. static struct MinList breakpoints;
  81.  
  82. static char buffer[1024];       /* multi-purpose buffer */
  83.  
  84.  
  85. ULONG r2(void) = "\tmr\tr3,r2"; /* gets TOC-pointer */
  86.  
  87.  
  88.  
  89. static long getsymval(char *symname)
  90. {
  91.   struct Section *sec = firstSec;
  92.   struct Symbol *sym;
  93.  
  94.   while (sec) {
  95.     sym = sec->symbols;
  96.     while (sym) {
  97.       if (!strcmp(sym->name,symname))
  98.         return ((long)sym->addr);
  99.       sym = sym->next;
  100.     }
  101.     sec = sec->next;
  102.   }
  103.   return (0);
  104. }
  105.  
  106.  
  107. static char *getvalue(long *val,char *buf)
  108. {
  109.   if (isdigit((unsigned char)*buf)) {
  110.     /* numerical constant */
  111.     sscanf(buf++,"%li",val);
  112.     if (*buf=='x' || *buf=='x')
  113.       buf++;
  114.     while (isxdigit((unsigned char)*buf))
  115.       buf++;
  116.   }
  117.  
  118.   else if (*buf=='@' && *(buf+1)!='_' && *(buf+1)!='x') {
  119.     /* register contents */
  120.     int r;
  121.  
  122.     buf++;
  123.     if (*buf == 'r' || *buf == 'R') {
  124.       sscanf(++buf,"%i",&r);
  125.       *val = (long)ec.ec_GPR[r];
  126.       while (isdigit((unsigned char)*buf))
  127.         buf++;
  128.     }
  129.     else if ((*buf&0xdf) == 'L' && (*(buf+1)&0xdf) == 'R') {
  130.       *val = (long)ec.ec_LR;
  131.       buf += 2;
  132.     }
  133.     else if ((*buf&0xdf) == 'C' && (*(buf+1)&0xdf) == 'T' &&
  134.              (*(buf+2)&0xdf) == 'R') {
  135.       *val = (long)ec.ec_CTR;
  136.       buf += 3;
  137.     }
  138.     else if ((*buf&0xdf) == 'P' && (*(buf+1)&0xdf) == 'C') {
  139.       *val = (long)ec.ec_UPC.ec_SRR0;
  140.       buf += 2;
  141.     }
  142.   }
  143.  
  144.   else {
  145.     /* symbol value */
  146.     char *p = buffer;
  147.  
  148.     while (isalnum((unsigned char)*buf) || *buf=='_' || *buf=='@') {
  149.       *p++ = *buf++;
  150.     }
  151.     *p = '\0';
  152.     *val = getsymval(buffer);
  153.   }
  154.   return (buf);
  155. }
  156.  
  157.  
  158. static struct enode *exptree(void *expool,char *buf)
  159. {
  160.   struct enode *on=NULL,*vn,*rn;
  161.  
  162.   for (;;) {
  163.     while (isspace((unsigned char)*buf))
  164.       buf++;
  165.  
  166.     if (*buf == '(') {
  167.       /* evaluate term */
  168.       int lev=1;
  169.  
  170.       if ((vn = exptree(expool,++buf)) == NULL)
  171.         return (NULL);
  172.       while (lev>0) {
  173.         if (*buf == '(')
  174.           lev++;
  175.         else if (*buf == ')')
  176.           lev--;
  177.         buf++;
  178.       }
  179.       if (vn->operation != OPERAND)
  180.         vn->u.priority = TERMPRI;
  181.     }
  182.     else {
  183.       if ((vn = AllocPooledPPC(expool,sizeof(struct enode))) == NULL)
  184.         return (NULL);
  185.       vn->root = on;
  186.       vn->left = vn->right = NULL;
  187.       vn->operation = OPERAND;
  188.       buf = getvalue(&vn->u.value,buf);
  189.     }
  190.  
  191.     if (on != NULL)
  192.       on->right = vn;
  193.     else
  194.       rn = vn;
  195.     while (isspace((unsigned char)*buf))
  196.       buf++;
  197.     if (*buf=='\0' || *buf=='\n' || *buf==')')
  198.       return (rn);
  199.  
  200.     /* get operation */
  201.     if ((on = AllocPooledPPC(expool,sizeof(struct enode))) == NULL)
  202.       return (NULL);
  203.     on->right = NULL;
  204.     switch (*buf++) {
  205.       case '+':
  206.         on->operation = PLUS;
  207.         on->u.priority = PLUSPRI;
  208.         break;
  209.       case '-':
  210.         on->operation = MINUS;
  211.         on->u.priority = MINUSPRI;
  212.         break;
  213.       case '*':
  214.         on->operation = MULT;
  215.         on->u.priority = MULTPRI;
  216.         break;
  217.       case '/':
  218.         on->operation = DIV;
  219.         on->u.priority = DIVPRI;
  220.         break;
  221.       default:
  222.         return (NULL);
  223.     }
  224.  
  225.     if (on->u.priority <= rn->u.priority || rn->operation == OPERAND) {
  226.       on->root = NULL;
  227.       rn->root = on;
  228.       on->left = rn;
  229.       rn = on;
  230.     }
  231.     else {
  232.       on->root = rn;
  233.       rn->right->root = on;
  234.       on->left = rn->right;
  235.       rn->right = on;
  236.     }
  237.   }
  238. }
  239.  
  240.  
  241. static long calctree(struct enode *n)
  242. {
  243.   if (n->operation == OPERAND) {
  244.     return (n->u.value);
  245.   }
  246.   else {
  247.     long x = calctree(n->left);
  248.     long y = calctree(n->right);
  249.  
  250.     switch (n->operation) {
  251.       case PLUS:
  252.         return (x+y);
  253.       case MINUS:
  254.         return (x-y);
  255.       case MULT:
  256.         return (x*y);
  257.       case DIV:
  258.         return (x/y);
  259.       default:
  260.         return (0);
  261.     }
  262.   }
  263. }
  264.  
  265.  
  266. static BPTR read_sections(char *name)
  267. {
  268.   BPTR seglist;
  269.  
  270.   if (seglist = LoadSeg(name)) {
  271.     ULONG *p;
  272.     struct Section *s = NULL;
  273.  
  274.     /* get length and address of all sections */
  275.     p = (ULONG *)BADDR(seglist);
  276.     nSecs = 0;
  277.     while (p) {
  278.       if (s) {
  279.         s->next = AllocPooledPPC(taskpool,sizeof(struct Section));
  280.         s = s->next;
  281.       }
  282.       else
  283.         firstSec = s = AllocPooledPPC(taskpool,sizeof(struct Section));
  284.       if (s) {
  285.         s->next = NULL;
  286.         s->addr = (ADDR)(p+1);
  287.         s->len = *(p-1);
  288.         s->symbols = NULL;
  289.         nSecs++;
  290.         p = (ULONG *)BADDR(*p);
  291.       }
  292.       else {
  293.         /* out of memory */
  294.         DeletePoolPPC(taskpool);
  295.         taskpool = NULL;
  296.         UnLoadSeg(seglist);
  297.         return (0);
  298.       }
  299.     }
  300.   }
  301.   return (seglist);
  302. }
  303.  
  304.  
  305. static ULONG filesize(FILE *fp)
  306. {
  307.   long oldpos,size;
  308.  
  309.   if ((oldpos = ftell(fp)) >= 0)
  310.     if (fseek(fp,0,SEEK_END) >= 0)
  311.       if ((size = ftell(fp)) >= 0)
  312.         if (fseek(fp,oldpos,SEEK_SET) >= 0)
  313.           return ((ULONG)size);
  314.   return (0);
  315. }
  316.  
  317.  
  318. static void get_debug_info(char *name)
  319. {
  320.   FILE *f;
  321.   ULONG size;
  322.   ULONG *hunks;
  323.   UWORD *hunks16;
  324.  
  325.   nSyms = 0;
  326.   if (f = fopen(name,"r")) {
  327.     if (size = filesize(f)) {
  328.       if (hunks = AllocPooledPPC(taskpool,size)) {
  329.         if (fread(hunks,1,size,f) == size) {
  330.           if (*hunks++ == HUNK_HEADER) {
  331.             int i,n,cnt;
  332.             struct Section *s = firstSec;
  333.             struct Symbol *lastsym,*newsym;
  334.             ULONG type;
  335.  
  336.             n = *hunks;
  337.             hunks += n ? (n+2) : 1;
  338.             n = *hunks;
  339.             hunks += n+3;
  340.             if (n > nSecs)
  341.               n = nSecs;
  342.  
  343.             /* scan all n sections for debugging information */
  344.             for (i=0; i<n; i++,s=s->next) {
  345.               lastsym = s->symbols;
  346.               while ((type = *hunks++) != HUNK_END) {
  347.  
  348.                 switch (type & 0xffff) {
  349.                   case HUNK_CODE:
  350.                   case HUNK_DATA:
  351.                   case HUNK_NAME:
  352.                   case HUNK_DEBUG:
  353.                     hunks += *hunks+1;
  354.                     break;
  355.  
  356.                   case HUNK_BSS:
  357.                     hunks++;
  358.                     break;
  359.  
  360.                   case HUNK_RELOC32:
  361.                     while ((cnt = *hunks++) != 0)
  362.                       hunks += cnt+1;
  363.                     break;
  364.  
  365.                   case HUNK_RELOC32SHORT:
  366.                   case HUNK_DREL32:  /* V37 RELOC32SHORT */
  367.                     hunks16 = (UWORD *)hunks;
  368.                     while ((cnt = *hunks16++) != 0)
  369.                       hunks16 += cnt+1;
  370.                     if ((ULONG)hunks16 & 3)
  371.                       hunks16++;  /* 32-bit alignment */
  372.                     hunks = (ULONG *)hunks16;
  373.                     break;
  374.  
  375.                   case HUNK_SYMBOL:
  376.                     while ((cnt = *hunks++) != 0) {
  377.                       if (newsym = AllocPooledPPC(taskpool,
  378.                                                   sizeof(struct Symbol))) {
  379.                         if (newsym->name = AllocPooledPPC(taskpool,
  380.                                                           (cnt<<2)+1)) {
  381.                           memcpy(newsym->name,hunks,cnt<<2);
  382.                           *(newsym->name+(cnt<<2)) = '\0';
  383.                           newsym->addr = s->addr + *(hunks+cnt);
  384.                           newsym->next = NULL;
  385.  
  386.                           if (lastsym)
  387.                             lastsym->next = newsym;
  388.                           else
  389.                             s->symbols = newsym;
  390.                           lastsym = newsym;
  391.                           nSyms++;
  392.                         }
  393.                       }
  394.                       hunks += cnt+1;
  395.                     }
  396.                     break;
  397.  
  398.                   default:
  399.                     /* hunk type not supported - bail out! */
  400.                     fclose(f);
  401.                     return;
  402.                 }
  403.               }
  404.             }
  405.           }
  406.         }
  407.       }
  408.     }
  409.     fclose(f);
  410.   }
  411. }
  412.  
  413.  
  414. static BOOL setbreakpt(ADDR addr,BOOL tmp)
  415. {
  416.   struct Breakpoint *b,*next,*new;
  417.  
  418.   if (!taskloaded)
  419.     return (FALSE);
  420.   addr = (ADDR)((ULONG)addr & ~3);
  421.   for (b = (struct Breakpoint *)breakpoints.mlh_Head;
  422.        next = (struct Breakpoint *)b->n.mln_Succ; b = next) {
  423.     if (b->addr == addr) {
  424.       b->temporary = tmp;
  425.       return (TRUE);
  426.     }
  427.     if (b->addr > addr)
  428.       break;
  429.   }
  430.   if (new = AllocPooledPPC(taskpool,sizeof(struct Breakpoint))) {
  431.     new->addr = addr;
  432.     new->contents = *(ULONG *)addr;
  433.     new->temporary = tmp;
  434.     _insertbefore(&new->n,&b->n);
  435.     *(ULONG *)addr = TRAP_INS;
  436.     SetCache(CACHE_DCACHEFLUSH,addr,4);
  437.     SetCache(CACHE_ICACHEINV,0,0);
  438.     return (TRUE);
  439.   }
  440.   return (FALSE);
  441. }
  442.  
  443.  
  444. static BOOL clrbreakpt(ADDR addr,BOOL tmp)
  445. {
  446.   struct Breakpoint *b,*next;
  447.  
  448.   if (!taskloaded)
  449.     return (FALSE);
  450.   addr = (ADDR)((ULONG)addr & ~3);
  451.   for (b = (struct Breakpoint *)breakpoints.mlh_Head;
  452.        next = (struct Breakpoint *)b->n.mln_Succ; b = next) {
  453.     if (b->addr > addr)
  454.       break;
  455.     if (b->addr == addr) {
  456.       if (tmp==TRUE && b->temporary==FALSE)
  457.         continue;
  458.       _remove(&b->n);
  459.       *(ULONG *)addr = b->contents;
  460.       SetCache(CACHE_DCACHEFLUSH,addr,4);
  461.       SetCache(CACHE_ICACHEINV,0,0);
  462.       FreePooledPPC(taskpool,b,sizeof(struct Breakpoint));
  463.       return (TRUE);
  464.     }
  465.   }
  466.   return (FALSE);
  467. }
  468.  
  469.  
  470. static void remallbrkpts()
  471. {
  472.   struct Breakpoint *b,*next;
  473.  
  474.   if (!taskloaded)
  475.     return;
  476.   for (b = (struct Breakpoint *)breakpoints.mlh_Head;
  477.        next = (struct Breakpoint *)b->n.mln_Succ; b = next) {
  478.     _remove(&b->n);
  479.     *(ULONG *)b->addr = b->contents;
  480.     SetCache(CACHE_DCACHEFLUSH,b->addr,4);
  481.     SetCache(CACHE_ICACHEINV,0,0);
  482.     FreePooledPPC(taskpool,b,sizeof(struct Breakpoint));
  483.   }
  484.   clearIABR();
  485. }
  486.  
  487.  
  488. BOOL wosdb_setbreakpoint(ADDR addr)
  489. {
  490.   return (setbreakpt(addr,FALSE));
  491. }
  492.  
  493.  
  494. BOOL wosdb_tempbreakpoint(ADDR addr)
  495. {
  496.   return (setbreakpt(addr,TRUE));
  497. }
  498.  
  499.  
  500. BOOL wosdb_clearbreakpoint(ADDR addr)
  501. {
  502.   return (clrbreakpt(addr,FALSE));
  503. }
  504.  
  505.  
  506. struct Breakpoint *wosdb_hidebreakpoint(ADDR addr)
  507. /* If the specified address matches a breakpoint, then hide it by */
  508. /* temporarily restoring the original contents */
  509. {
  510.   struct Breakpoint *b,*next;
  511.   ADDR a1 = (ADDR)((ULONG)addr & ~3);
  512.   ADDR a2 = (ADDR)(((ULONG)addr+3) & ~3);
  513.  
  514.   if (!taskloaded)
  515.     return (NULL);
  516.   for (b = (struct Breakpoint *)breakpoints.mlh_Head;
  517.        next = (struct Breakpoint *)b->n.mln_Succ; b = next) {
  518.     if (b->addr > a2)
  519.       return (NULL);
  520.     if (b->addr == a1 || b->addr == a2) {
  521.       *(ULONG *)addr = b->contents;
  522.       SetCache(CACHE_DCACHEFLUSH,addr,4);
  523.       SetCache(CACHE_ICACHEINV,0,0);
  524.       return (b);
  525.     }
  526.   }
  527.   return (NULL);
  528. }
  529.  
  530.  
  531. void wosdb_showbreakpoint(struct Breakpoint *b)
  532. /* Reactivate a breakpoint, which was hidden by wosdb_hidebreakpoint() */
  533. {
  534.   if (b != NULL && taskloaded) {
  535.     *(ULONG *)b->addr = TRAP_INS;
  536.     SetCache(CACHE_DCACHEFLUSH,b->addr,4);
  537.     SetCache(CACHE_ICACHEINV,0,0);
  538.   }
  539. }
  540.  
  541.  
  542. struct LoadFile *wosdb_load(char *name,char *args)
  543. {
  544.   static struct LoadFile loadfile;
  545.   struct LoadFile *lf = NULL;
  546.   BPTR seglist;
  547.   struct TagItem ti[16];
  548.  
  549.   if (taskpool = CreatePoolPPC(0,0x4000,0x2000)) {
  550.     if (seglist = read_sections(name)) {
  551.       get_debug_info(name);
  552.       loadfile.name = name;
  553.       loadfile.sections = nSecs;
  554.       loadfile.symbols = nSyms;
  555.       loadfile.firstsec = firstSec;
  556.       loadfile.breakpoints = &breakpoints;
  557.       loadfile.specregs = &spr;
  558.  
  559.       /* patch RunPPC() to set a breakpoint for the first instruction */
  560.       oldRunPPC = SetFunction((struct Library *)PowerPCBase,
  561.                               -30, /* RunPPC() LVO */
  562.                               (APTR)newRunPPC);
  563.       SetCache(CACHE_DCACHEFLUSH,&oldRunPPC,4);
  564.  
  565.       /* install a global exception handler to capture the new task */
  566.       ti[0].ti_Tag = EXCATTR_CODE;
  567.       ti[0].ti_Data = (ULONG)ExceptionCatch;
  568.       ti[1].ti_Tag = EXCATTR_DATA;
  569.       ti[1].ti_Data = r2();
  570.       ti[2].ti_Tag = EXCATTR_EXCID;
  571.       ti[2].ti_Data = EXCF_PROGRAM;
  572.       ti[3].ti_Tag = EXCATTR_FLAGS;
  573.       ti[3].ti_Data = EXCF_GLOBAL | EXCF_LARGECONTEXT;
  574.       ti[4].ti_Tag = EXCATTR_PRI;
  575.       ti[4].ti_Data = 127;
  576.       ti[5].ti_Tag = TAG_DONE;
  577.  
  578.       if (xhdlC = SetExcHandler(ti)) {
  579.         /* launch the task, which will immediately run in our breakpoint */
  580.  
  581.         ti[0].ti_Tag = NP_Seglist;
  582.         ti[0].ti_Data = (ULONG)seglist;
  583.         ti[1].ti_Tag = NP_FreeSeglist;
  584.         ti[1].ti_Data = TRUE;
  585.         ti[2].ti_Tag = NP_Name;
  586.         ti[2].ti_Data = (ULONG)name;
  587.         ti[3].ti_Tag = NP_StackSize;
  588.         ti[3].ti_Data = stacksize;
  589.         ti[4].ti_Tag = NP_Priority;
  590.         ti[4].ti_Data = (ULONG)priority;
  591.         ti[5].ti_Tag = NP_Cli;
  592.         ti[5].ti_Data = TRUE;
  593.         ti[6].ti_Tag = NP_Input;
  594.         ti[6].ti_Data = (ULONG)Input();
  595.         ti[7].ti_Tag = NP_Output;
  596.         ti[7].ti_Data = (ULONG)Output();
  597.         ti[8].ti_Tag = NP_Error;
  598.         ti[8].ti_Data = (ULONG)Output();
  599.         ti[9].ti_Tag = NP_CloseInput;
  600.         ti[9].ti_Data = FALSE;
  601.         ti[10].ti_Tag = NP_CloseOutput;
  602.         ti[10].ti_Data = FALSE;
  603.         ti[11].ti_Tag = NP_CloseError;
  604.         ti[11].ti_Data = FALSE;
  605.         ti[12].ti_Tag = NP_CommandName;
  606.         ti[12].ti_Data = (ULONG)name;
  607.         ti[13].ti_Tag = NP_Arguments;
  608.         ti[13].ti_Data = (ULONG)args;
  609.         ti[14].ti_Tag = TAG_DONE;
  610.         if (CreateNewProc(ti)) {   /* start program and */
  611.           WaitPPC(1L<<sigExcept);  /* wait for breakpoint exception */
  612.  
  613.           /* undo RunPPC()-patch and remove global handler */
  614.           SetFunction((struct Library *)PowerPCBase,-30,oldRunPPC);
  615.           RemExcHandler(xhdlC);
  616.  
  617.           /* install local handlers for exception-catch and */
  618.           /* exception-leave */
  619.           ti[0].ti_Tag = EXCATTR_CODE;
  620.           ti[0].ti_Data = (ULONG)ExceptionCatch;
  621.           ti[1].ti_Tag = EXCATTR_DATA;
  622.           ti[1].ti_Data = r2();
  623.           ti[2].ti_Tag = EXCATTR_TASK;
  624.           ti[2].ti_Data = (ULONG)dbTask;
  625.           ti[3].ti_Tag = EXCATTR_EXCID;
  626.           ti[3].ti_Data = EXCF_MCHECK | EXCF_DACCESS | EXCF_IACCESS |
  627.                           EXCF_ALIGN | EXCF_PROGRAM | EXCF_FPUN |
  628.                           EXCF_TRACE | EXCF_IABR;
  629.           ti[4].ti_Tag = EXCATTR_FLAGS;
  630.           ti[4].ti_Data = EXCF_LOCAL | EXCF_LARGECONTEXT;
  631.           ti[5].ti_Tag = EXCATTR_PRI;
  632.           ti[5].ti_Data = 126;
  633.           ti[6].ti_Tag = TAG_DONE;
  634.           if (xhdlC = SetExcHandler(ti)) {
  635.             ti[0].ti_Tag = EXCATTR_CODE;
  636.             ti[0].ti_Data = (ULONG)ExceptionLeave;
  637.             ti[1].ti_Tag = EXCATTR_DATA;
  638.             ti[1].ti_Data = r2();
  639.             ti[2].ti_Tag = EXCATTR_TASK;
  640.             ti[2].ti_Data = (ULONG)dbTask;
  641.             ti[3].ti_Tag = EXCATTR_EXCID;
  642.             ti[3].ti_Data = EXCF_PROGRAM;
  643.             ti[4].ti_Tag = EXCATTR_FLAGS;
  644.             ti[4].ti_Data = EXCF_LOCAL | EXCF_LARGECONTEXT;
  645.             ti[5].ti_Tag = EXCATTR_PRI;
  646.             ti[5].ti_Data = 127;
  647.             ti[6].ti_Tag = TAG_DONE;
  648.             if (xhdlL = SetExcHandler(ti)) {
  649.               taskloaded = TRUE;
  650.               NewListPPC((struct List *)&breakpoints);
  651.  
  652.               /* Set breakpoint to PPC-task start address. */
  653.               /* WarpOS now calls the task-code by a "blrl", so we can */
  654.               /* find the start address in the LR register. */
  655.               wosdb_tempbreakpoint((ADDR)ec.ec_LR);
  656.               ec.ec_UPC.ec_SRR0 += 4;  /* skip "trap" instruction */
  657.  
  658.               /* let the task continue to run */
  659.               SignalPPC(dbTask,1L<<sigRun);
  660.  
  661.               /* wait for exception at start-address */
  662.               WaitPPC(1L<<sigExcept);  /* wait for breakpoint exception */
  663.               clrbreakpt((ADDR)ec.ec_UPC.ec_PC,TRUE);
  664.  
  665.               /* set our own exit-function to notify the debugger */
  666.               /* on task's termination */
  667.               initialLR = ec.ec_LR;
  668.               ec.ec_LR = (ULONG)ProgramExit;
  669.  
  670.               lf = &loadfile;
  671.             }
  672.             else
  673.               RemExcHandler(xhdlC);
  674.           }
  675.         }
  676.         else {
  677.           SetFunction((struct Library *)PowerPCBase,-30,oldRunPPC);
  678.           RemExcHandler(xhdlC);
  679.         }
  680.       }
  681.       else
  682.         SetFunction((struct Library *)PowerPCBase,-30,oldRunPPC);
  683.  
  684.       if (!lf) {
  685.         /* something failed, free all */
  686.         xhdlC = xhdlL = NULL;
  687.         DeletePoolPPC(taskpool);
  688.       }
  689.     }
  690.   }
  691.   return (lf);
  692. }
  693.  
  694.  
  695. void wosdb_unload()
  696. {
  697.   if (dbTask) {
  698.     remallbrkpts();
  699.     if (xhdlL) {
  700.       RemExcHandler(xhdlL);
  701.       xhdlL = NULL;
  702.     }
  703.     if (xhdlC) {
  704.       RemExcHandler(xhdlC);
  705.       xhdlC = NULL;
  706.     }
  707.     DeleteTaskPPC(dbTask);
  708.     dbTask = NULL;
  709.   }
  710.   if (taskpool) {
  711.     DeletePoolPPC(taskpool);
  712.     taskpool = NULL;
  713.   }
  714.   taskloaded = FALSE;
  715. }
  716.  
  717.  
  718. ULONG wosdb_cont(BOOL strace,BOOL btrace)
  719. /* start debugged task */
  720. {
  721.   struct Breakpoint *bp;
  722.   ULONG sigmsk,eid;
  723.  
  724.   sTrace = strace;
  725.   bTrace = btrace;
  726.  
  727.   bp = wosdb_hidebreakpoint((ADDR)ec.ec_UPC.ec_PC);
  728.   SignalPPC(dbTask,1L<<sigRun);  /* run task */
  729.   /* wait for next exception */
  730.   sigmsk = WaitPPC((1L<<sigExcept) | (1L<<sigFinish));
  731.   wosdb_showbreakpoint(bp);
  732.   clearIABR();
  733.  
  734.   if (sigmsk & (1L<<sigFinish)) {
  735.     /* task has finished... release it */
  736.     wosdb_unload();
  737.     return (EXCF_FINISHED);
  738.   }
  739.  
  740.   if (ec.ec_ExcID == EXCF_PROGRAM &&
  741.       *(ULONG *)ec.ec_UPC.ec_PC == TRAP_INS) {
  742.     /* we have run into one of our breakpoints */
  743.     clrbreakpt((ADDR)ec.ec_UPC.ec_PC,TRUE);  /* remove temp. breakpt. */
  744.     eid = EXCF_BRKPT;
  745.   }
  746.   else
  747.     eid = ec.ec_ExcID;
  748.  
  749.   /* check if we accidently entered our own ProgramExit() function */
  750.   if (ec.ec_UPC.ec_SRR0 >= (ULONG)ProgramExit &&
  751.       ec.ec_UPC.ec_SRR0 < (ULONG)ProgramExitEnd) {
  752.     /* finish task */
  753.     sTrace = bTrace = FALSE;
  754.     remallbrkpts();
  755.     SignalPPC(dbTask,1L<<sigRun);
  756.     WaitPPC(1L<<sigFinish);
  757.     wosdb_unload();
  758.     eid = EXCF_FINISHED;
  759.   }
  760.   return (eid);
  761. }
  762.  
  763.  
  764. ULONG wosdb_taskresult()
  765. {
  766.   return (result);
  767. }
  768.  
  769.  
  770. char *wosdb_exceptinfo()
  771. {
  772.   switch (ec.ec_ExcID) {
  773.     case EXCF_MCHECK:
  774.       sprintf(buffer,"MACHINE CHECK");
  775.       break;
  776.     case EXCF_DACCESS:
  777.       sprintf(buffer,"DATA ACCESS");
  778.       break;
  779.     case EXCF_IACCESS:
  780.       sprintf(buffer,"INSTRUCTION ACCESS");
  781.       break;
  782.     case EXCF_INTERRUPT:
  783.       sprintf(buffer,"EXTERNAL INTERRUPT");
  784.       break;
  785.     case EXCF_ALIGN:
  786.       sprintf(buffer,"ALIGNMENT");
  787.       break;
  788.     case EXCF_PROGRAM:
  789.       sprintf(buffer,"PROGRAM");
  790.       break;
  791.     case EXCF_FPUN:
  792.       sprintf(buffer,"FP UNAVAILABLE");
  793.       break;
  794.     case EXCF_TRACE:
  795.       sprintf(buffer,"TRACE");
  796.       break;
  797.     case EXCF_PERFMON:
  798.       sprintf(buffer,"PERF MON");
  799.       break;
  800.     case EXCF_IABR:
  801.       sprintf(buffer,"BREAKPOINT");
  802.       break;
  803.     default:
  804.       sprintf(buffer,"UNKNOWN");
  805.       break;
  806.   }
  807.   return (buffer);
  808. }
  809.  
  810.  
  811. char *wosdb_symbol(ADDR p)
  812. /* returns string with symbol and offset, if a symbol exists */
  813. {
  814.   struct Section *sec = firstSec;
  815.   struct Symbol *sym;
  816.   char *label = NULL;
  817.   ULONG offs = 0xffffffff;
  818.  
  819.   while (sec) {
  820.     if (p >= sec->addr && p < (sec->addr+sec->len)) {
  821.       sym = sec->symbols;
  822.       while (sym) {
  823.         /* @@@ this would be easier and faster when symbols are sorted */
  824.         if (sym->addr <= p) {
  825.           if ((p - sym->addr) < offs) {
  826.             offs = p - sym->addr;
  827.             label = sym->name;
  828.           }
  829.         }
  830.         sym = sym->next;
  831.       }
  832.       if (label) {
  833.         sprintf(buffer,"%s+%lx",label,offs);
  834.         return (buffer);
  835.       }
  836.       else
  837.         break;
  838.     }
  839.     sec = sec->next;
  840.   }
  841.   return (NULL);
  842. }
  843.  
  844.  
  845. char *wosdb_label(ADDR p)
  846. /* returns string with symbol, if current address matches symbol addr. */
  847. {
  848.   struct Section *sec = firstSec;
  849.   struct Symbol *sym;
  850.  
  851.   while (sec) {
  852.     if (p >= sec->addr && p < (sec->addr+sec->len)) {
  853.       sym = sec->symbols;
  854.       while (sym) {
  855.         if (sym->addr == p)
  856.           return (sym->name);
  857.         sym = sym->next;
  858.       }
  859.       break;
  860.     }
  861.     sec = sec->next;
  862.   }
  863.   return (NULL);
  864. }
  865.  
  866.  
  867. void wosdb_opersymbols(struct DisasmPara_PPC *dp,int len)
  868. /* try to replace values in operand by symbols */
  869. {
  870.   ADDR a;
  871.   char *op,*p,*sym;
  872.  
  873.   /* find beginning of last operand */
  874.   op = p = dp->operands;
  875.   while (*p) {
  876.     if (*p++ == ',')
  877.       op = p;
  878.   }
  879.  
  880.   switch (dp->type) {
  881.  
  882.     case PPCINSTR_BRANCH:
  883.       a = (ADDR)dp->iaddr + (long)dp->displacement;
  884.       if (sym = wosdb_label(a))
  885.         sprintf(op,"%s",sym);
  886.       break;
  887.  
  888.     case PPCINSTR_LDST:
  889.       a = (ADDR)(ec.ec_GPR[dp->sreg] + (long)dp->displacement);
  890.       if (sym = wosdb_label(a))
  891.         sprintf(op,"%s(r%d)",sym,(int)dp->sreg);
  892.       break;
  893.   }
  894. }
  895.  
  896.  
  897. int wosdb_validaddr(ADDR addr)
  898. /* 0: invalid address */
  899. /* 1: address belongs to normal RAM or 0x00000004 */
  900. /* 2: address belongs to a section of the debugged program */
  901. {
  902.   int rc = 0;
  903.   struct MemHeader *mh = (struct MemHeader *)SysBase->MemList.lh_Head;
  904.   struct MemHeader *nextmh;
  905.  
  906.   addr = (ADDR)((ULONG)addr & ~3);
  907.   while (nextmh = (struct MemHeader *)mh->mh_Node.ln_Succ) {
  908.     if (addr >= (ADDR)((ULONG)mh->mh_Lower & ~255) &&
  909.         addr < (ADDR)(((ULONG)mh->mh_Upper+255) & ~255)) {
  910.       rc++;
  911.       break;
  912.     }
  913.     mh = nextmh;
  914.   }
  915.   if (rc==0 && (ULONG)addr==4)  /* ExecBase 0x0004 is legal */
  916.     rc++;
  917.  
  918.   if (rc!=0 && taskloaded) {
  919.     struct Section *s = firstSec;
  920.  
  921.     while (s) {
  922.       if (addr >= s->addr && addr < (s->addr+s->len)) {
  923.         rc++;
  924.         break;
  925.       }
  926.       s = s->next;
  927.     }
  928.   }
  929.  
  930.   return (rc);
  931. }
  932.  
  933.  
  934. ULONG wosdb_getexp(char *buf)
  935. {
  936.   void *expool;
  937.   struct enode *root;
  938.   ULONG val = 0;
  939.  
  940.   if (expool = CreatePoolPPC(0,0x1000,0x1000)) {
  941.     if (root = exptree(expool,buf))
  942.       val = (ULONG)calctree(root);
  943.     DeletePoolPPC(expool);
  944.   }
  945.   return (val);
  946. }
  947.  
  948.  
  949. struct SpecRegs *wosdb_getspecregs()
  950. {
  951.   return (&spr);
  952. }
  953.  
  954.  
  955. struct EXCContext *wosdb_init()
  956. {
  957.   if ((sigExcept = AllocSignalPPC(-1)) < 0)
  958.     return (NULL);
  959.   if ((sigFinish = AllocSignalPPC(-1)) < 0) {
  960.     FreeSignalPPC(sigExcept);
  961.     return (NULL);
  962.   }
  963.   thisTask = FindTaskPPC(NULL);
  964.   return (&ec);
  965. }
  966.  
  967.  
  968. void wosdb_exit()
  969. {
  970.   wosdb_unload();
  971.   FreeSignalPPC(sigFinish);
  972.   FreeSignalPPC(sigExcept);
  973. }
  974.