home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / Contributions / Olaf_Barthel / Tools / Debugging / Blowup / Source / showcrashinfo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-06-12  |  5.9 KB  |  229 lines

  1. /*
  2.  * $Id: showcrashinfo.c 1.7 1998/06/13 08:20:14 olsen Exp olsen $
  3.  *
  4.  * :ts=4
  5.  *
  6.  * Blowup -- Catches and displays task errors
  7.  *
  8.  * Written by Olaf `Olsen' Barthel <olsen@sourcery.han.de>
  9.  * Public Domain
  10.  */
  11.  
  12. #ifndef _GLOBAL_H
  13. #include "global.h"
  14. #endif    /* _GLOBAL_H */
  15.  
  16. /******************************************************************************/
  17.  
  18. #define TROUBLE    (-1)    /* could not open the requester */
  19. #define REBOOT    ( 0)    /* user wants to reboot the machine */
  20. #define SUSPEND    ( 1)    /* user wants the trapped task to be suspended */
  21.  
  22. /******************************************************************************/
  23.  
  24. STATIC LONG
  25. ShowEasyRequest(
  26.     const STRPTR    title,
  27.     const STRPTR    gadgets,
  28.     const STRPTR    text,
  29.                     ...)
  30. {
  31.     struct Process * thisProcess;
  32.     struct Window * parentWindow;
  33.     LONG result = TROUBLE;
  34.  
  35.     /* set up the parent window pointer so the requester will
  36.      * open on the program's preferred screen; this works only
  37.      * for processes, which may not want this requester to show
  38.      * up in the first place
  39.      */
  40.  
  41.     parentWindow = NULL;
  42.  
  43.     thisProcess = (struct Process *)FindTask(NULL);
  44.     if(thisProcess->pr_Task.tc_Node.ln_Type == NT_PROCESS)
  45.     {
  46.         parentWindow = thisProcess->pr_WindowPtr;
  47.     }
  48.  
  49.     /* if the pointer is invalid, do not show the requester */
  50.     if(parentWindow != (struct Window *)~0)
  51.     {
  52.         struct EasyStruct es;
  53.         va_list varArgs;
  54.     
  55.         es.es_StructSize    = sizeof(es);
  56.         es.es_Flags            = NULL;
  57.         es.es_Title            = (STRPTR)title;
  58.         es.es_TextFormat    = (STRPTR)text;
  59.         es.es_GadgetFormat    = (STRPTR)gadgets;
  60.     
  61.         va_start(varArgs,text);
  62.         result = EasyRequestArgs(parentWindow,&es,NULL,(APTR)varArgs);
  63.         va_end(varArgs);
  64.     }
  65.  
  66.     return(result);
  67. }
  68.  
  69. /******************************************************************************/
  70.  
  71. VOID ASM
  72. ShowCrashInfo(
  73.     REG(d0) UBYTE    trapType,
  74.     REG(d1) ULONG    pc,
  75.     REG(d2) UWORD    sr,
  76.     REG(a0) ULONG *    stackFrame)
  77. {
  78.     /* a short table to associate trap types with human-readable information */
  79.     STATIC const struct { ULONG Type; STRPTR Name; } TrapTypes[] =
  80.     {
  81.         2,    "Bus error",
  82.         3,    "Address error",
  83.         4,    "Illegal instruction",
  84.         5,    "Zero divide",
  85.         6,    "CHK, CHK2 instructions",
  86.         7,    "cpTRAPc, TRAPcc, TRAPV instructions",
  87.         8,    "Privilege violation",
  88.         9,    "Trace",
  89.         10,    "Line 1010 emulator",
  90.         11,    "Line 1111 emulator",
  91.         13,    "Coprocessor protocol violation",
  92.         14,    "Stack frame format error",
  93.         15,    "Uninitialized interrupt",
  94.         24,    "Spurious interrupt",
  95.         25,    "Level 1 interrupt autovector (SOFTINT, DSKBLK, TBE)",
  96.         26,    "Level 2 interrupt autovector (PORTS)",
  97.         27,    "Level 3 interrupt autovector (COPER, VERTB, BLIT)",
  98.         28,    "Level 4 interrupt autovector (AUD2, AUD0, AUD3, AUD1)",
  99.         29,    "Level 5 interrupt autovector (RBF, DSKSYNC)",
  100.         30,    "Level 6 interrupt autovector (EXTER)",
  101.         31,    "Level 7 interrupt autovector (NMI)",
  102.         32,    "TRAP #0 instruction",
  103.         33,    "TRAP #1 instruction",
  104.         34,    "TRAP #2 instruction",
  105.         35,    "TRAP #3 instruction",
  106.         36,    "TRAP #4 instruction",
  107.         37,    "TRAP #5 instruction",
  108.         38,    "TRAP #6 instruction",
  109.         39,    "TRAP #7 instruction",
  110.         40,    "TRAP #8 instruction",
  111.         41,    "TRAP #9 instruction",
  112.         42,    "TRAP #10 instruction",
  113.         43,    "TRAP #11 instruction",
  114.         44,    "TRAP #12 instruction",
  115.         45,    "TRAP #13 instruction",
  116.         46,    "TRAP #14 instruction",
  117.         47,    "TRAP #15 instruction",
  118.         48,    "FPCP Branch or Set on unordered condition",
  119.         49,    "FPCP inexact result",
  120.         50,    "FPCP divide by zero",
  121.         51,    "FPCP underflow",
  122.         52,    "FPCP operand error",
  123.         53,    "FPCP overflow",
  124.         54,    "FPCP signaling NAN",
  125.         56,    "MMU configuration error",
  126.         57,    "MMU illegal operation error",
  127.         58,    "MMU access level violation error"
  128.     };
  129.  
  130.     UBYTE errorBuffer[40];
  131.     STRPTR errorType;
  132.     UBYTE nameBuffer[MAX_FILENAME_LEN];
  133.     struct Process * thisProcess;
  134.     STRPTR taskType;
  135.     LONG response;
  136.     int i;
  137.  
  138.     /* check whether the exception came from supervisor mode
  139.      * or whether it was triggered from an interrupt; if that
  140.      * happens, we will know that we are in trouble and thus
  141.      * fall straight into a dead-end alert
  142.      */
  143.     if((sr & 0x2700) != 0)
  144.     {
  145.         Alert(AT_DeadEnd | trapType);
  146.     }
  147.  
  148.     /* we really are busy now */
  149.     ObtainSemaphoreShared(&BusySemaphore);
  150.  
  151.     /* find an explanation for the exception condition */
  152.     errorType = NULL;
  153.     for(i = 0 ; i < NUM_ELEMENTS(TrapTypes) ; i++)
  154.     {
  155.         if(TrapTypes[i].Type == trapType)
  156.         {
  157.             errorType = (STRPTR)TrapTypes[i].Name;
  158.             break;
  159.         }
  160.     }
  161.  
  162.     /* if no explanation could be found, just list the trap number */
  163.     if(errorType == NULL)
  164.     {
  165.         errorType = errorBuffer;
  166.  
  167.         SPrintfN(sizeof(errorBuffer),errorBuffer,"Exception #%ld",trapType);
  168.     }
  169.  
  170.     /* show the error and the status information */
  171.     VoiceComplaint(trapType,sr,pc,stackFrame,"%s\n",errorType);
  172.  
  173.     /* determine the name and the type of the current task */
  174.     thisProcess = (struct Process *)FindTask(NULL);
  175.     
  176.     StrcpyN(sizeof(nameBuffer),nameBuffer,thisProcess->pr_Task.tc_Node.ln_Name);
  177.     
  178.     if(thisProcess->pr_Task.tc_Node.ln_Type == NT_PROCESS)
  179.     {
  180.         struct CommandLineInterface * cli;
  181.     
  182.         taskType = "Process";
  183.     
  184.         cli = BADDR(thisProcess->pr_CLI);
  185.         if(cli != NULL)
  186.         {
  187.             if(cli->cli_CommandName != NULL)
  188.             {
  189.                 SPrintfN(sizeof(nameBuffer),nameBuffer,"%b",cli->cli_CommandName);
  190.                 taskType = "Shell program";
  191.             }
  192.         }
  193.     }
  194.     else
  195.     {
  196.         taskType = "Task";
  197.     }
  198.     
  199.     /* say what happened and ask the user to decide what to do next */
  200.     response = ShowEasyRequest("Software error","Suspend|Reboot",
  201.         "%s \"%s\" stopped.\n\n"
  202.         "Finish ALL disk activity\n"
  203.         "before you select \"Reboot\"!",taskType,nameBuffer);
  204.     
  205.     /* release the busy semaphore, but without allowing multitasking
  206.      * to resume; that would be a bad idea because we are not going
  207.      * to be busy any more in a minute but wouldn't want anyone else
  208.      * to consider us busy until we have actually gone into suspension
  209.      */
  210.     Forbid();
  211.  
  212.     ReleaseSemaphore(&BusySemaphore);
  213.     
  214.     /* if the requester did not open or if the task was to be
  215.      * suspended, wait forever for a signal that will never arrive
  216.      */
  217.     if(response == TROUBLE || response == SUSPEND)
  218.     {
  219.         Wait(0);
  220.     }
  221.     else
  222.     {
  223.         /* drop straight into a dead-end alert that
  224.          * will eventually trigger a reboot
  225.          */
  226.         Alert(AT_DeadEnd | trapType);
  227.     }
  228. }
  229.