Home | History | Annotate | Line # | Download | only in acpiexec
aeexception.c revision 1.1.1.5
      1 /******************************************************************************
      2  *
      3  * Module Name: aeexception - Exception and signal handlers
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2018, Intel Corp.
      9  * All rights reserved.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions, and the following disclaimer,
     16  *    without modification.
     17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
     18  *    substantially similar to the "NO WARRANTY" disclaimer below
     19  *    ("Disclaimer") and any redistribution must be conditioned upon
     20  *    including a substantially similar Disclaimer requirement for further
     21  *    binary redistribution.
     22  * 3. Neither the names of the above-listed copyright holders nor the names
     23  *    of any contributors may be used to endorse or promote products derived
     24  *    from this software without specific prior written permission.
     25  *
     26  * Alternatively, this software may be distributed under the terms of the
     27  * GNU General Public License ("GPL") version 2 as published by the Free
     28  * Software Foundation.
     29  *
     30  * NO WARRANTY
     31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
     34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
     40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     41  * POSSIBILITY OF SUCH DAMAGES.
     42  */
     43 
     44 #include "aecommon.h"
     45 
     46 #define _COMPONENT          ACPI_TOOLS
     47         ACPI_MODULE_NAME    ("aeexception")
     48 
     49 
     50 /* Local prototypes */
     51 
     52 static void
     53 AeDisplayMethodCallStack (
     54     void);
     55 
     56 
     57 UINT32                      SigintCount = 0;
     58 #define ACPI_MAX_CONTROL_C  5
     59 
     60 
     61 /******************************************************************************
     62  *
     63  * FUNCTION:    AeExceptionHandler
     64  *
     65  * PARAMETERS:  Standard exception handler parameters
     66  *
     67  * RETURN:      Status
     68  *
     69  * DESCRIPTION: System exception handler for AcpiExec utility. Called from
     70  *              the core ACPICA code after any exception during method
     71  *              execution.
     72  *
     73  *****************************************************************************/
     74 
     75 ACPI_STATUS
     76 AeExceptionHandler (
     77     ACPI_STATUS             AmlStatus,
     78     ACPI_NAME               Name,
     79     UINT16                  Opcode,
     80     UINT32                  AmlOffset,
     81     void                    *Context)
     82 {
     83     ACPI_STATUS             NewAmlStatus = AmlStatus;
     84     ACPI_STATUS             Status;
     85     ACPI_BUFFER             ReturnObj;
     86     ACPI_OBJECT_LIST        ArgList;
     87     ACPI_OBJECT             Arg[3];
     88     const char              *Exception;
     89     ACPI_HANDLE             ErrHandle;
     90 
     91 
     92     Exception = AcpiFormatException (AmlStatus);
     93 
     94     if (AcpiGbl_VerboseHandlers)
     95     {
     96         AcpiOsPrintf (AE_PREFIX
     97             "Exception %s during execution\n", Exception);
     98 
     99         if (Name)
    100         {
    101             if (ACPI_COMPARE_NAME (&Name, ACPI_ROOT_PATHNAME))
    102             {
    103                 AcpiOsPrintf (AE_PREFIX
    104                     "Evaluating executable code at [%s]\n", ACPI_NAMESPACE_ROOT);
    105             }
    106             else
    107             {
    108                 AcpiOsPrintf (AE_PREFIX
    109                     "Evaluating Method or Node: [%4.4s]\n", (char *) &Name);
    110             }
    111         }
    112 
    113         /* Be terse about loop timeouts */
    114 
    115         if ((AmlStatus == AE_AML_LOOP_TIMEOUT) && AcpiGbl_AbortLoopOnTimeout)
    116         {
    117             AcpiOsPrintf (AE_PREFIX "Aborting loop after timeout\n");
    118             return (AE_OK);
    119         }
    120 
    121         AcpiOsPrintf ("\n" AE_PREFIX
    122             "AML Opcode [%s], Method Offset ~%5.5X\n",
    123             AcpiPsGetOpcodeName (Opcode), AmlOffset);
    124     }
    125 
    126     /* Invoke the _ERR method if present */
    127 
    128     Status = AcpiGetHandle (NULL, "\\_ERR", &ErrHandle);
    129     if (ACPI_FAILURE (Status))
    130     {
    131         goto Cleanup;
    132     }
    133 
    134     /* Setup parameter object */
    135 
    136     ArgList.Count = 3;
    137     ArgList.Pointer = Arg;
    138 
    139     Arg[0].Type = ACPI_TYPE_INTEGER;
    140     Arg[0].Integer.Value = AmlStatus;
    141 
    142     Arg[1].Type = ACPI_TYPE_STRING;
    143     Arg[1].String.Pointer = ACPI_CAST_PTR (char, Exception);
    144     Arg[1].String.Length = strlen (Exception);
    145 
    146     Arg[2].Type = ACPI_TYPE_INTEGER;
    147     Arg[2].Integer.Value = AcpiOsGetThreadId();
    148 
    149     /* Setup return buffer */
    150 
    151     ReturnObj.Pointer = NULL;
    152     ReturnObj.Length = ACPI_ALLOCATE_BUFFER;
    153 
    154     Status = AcpiEvaluateObject (ErrHandle, NULL, &ArgList, &ReturnObj);
    155     if (ACPI_SUCCESS (Status))
    156     {
    157         if (ReturnObj.Pointer)
    158         {
    159             /* Override original status */
    160 
    161             NewAmlStatus = (ACPI_STATUS)
    162                 ((ACPI_OBJECT *) ReturnObj.Pointer)->Integer.Value;
    163 
    164             /* Free a buffer created via ACPI_ALLOCATE_BUFFER */
    165 
    166             AcpiOsFree (ReturnObj.Pointer);
    167         }
    168     }
    169     else if (Status != AE_NOT_FOUND)
    170     {
    171         AcpiOsPrintf (AE_PREFIX
    172             "Could not execute _ERR method, %s\n",
    173             AcpiFormatException (Status));
    174     }
    175 
    176 Cleanup:
    177 
    178     if (AcpiGbl_IgnoreErrors)
    179     {
    180         /* Global option to ignore all method errors, just return OK */
    181 
    182         NewAmlStatus = AE_OK;
    183     }
    184     if (NewAmlStatus != AmlStatus)
    185     {
    186         /* Request to override actual status with a different status */
    187 
    188         AcpiOsPrintf (AE_PREFIX
    189             "Exception override, new status %s\n\n",
    190             AcpiFormatException (NewAmlStatus));
    191     }
    192 
    193     return (NewAmlStatus);
    194 }
    195 
    196 
    197 /******************************************************************************
    198  *
    199  * FUNCTION:    AeSignalHandler
    200  *
    201  * PARAMETERS:  Sig
    202  *
    203  * RETURN:      none
    204  *
    205  * DESCRIPTION: Master signal handler. Currently handles SIGINT (ctrl-c),
    206  *              and SIGSEGV (Segment violation).
    207  *
    208  *****************************************************************************/
    209 
    210 void ACPI_SYSTEM_XFACE
    211 AeSignalHandler (
    212     int                     Sig)
    213 {
    214 
    215     fflush(stdout);
    216     AcpiOsPrintf ("\n" AE_PREFIX);
    217 
    218     switch (Sig)
    219     {
    220     case SIGINT:
    221         signal(Sig, SIG_IGN);
    222         AcpiOsPrintf ("<Control-C>\n");
    223 
    224         /* Force exit on multiple control-c */
    225 
    226         SigintCount++;
    227         if (SigintCount >= ACPI_MAX_CONTROL_C)
    228         {
    229             exit (0);
    230         }
    231 
    232         /* Abort the application if there are no methods executing */
    233 
    234         if (!AcpiGbl_MethodExecuting)
    235         {
    236             break;
    237         }
    238 
    239         /*
    240          * Abort the method(s). This will also dump the method call
    241          * stack so there is no need to do it here. The application
    242          * will then drop back into the debugger interface.
    243          */
    244         AcpiGbl_AbortMethod = TRUE;
    245         AcpiOsPrintf (AE_PREFIX "Control Method Call Stack:\n");
    246         signal (SIGINT, AeSignalHandler);
    247         return;
    248 
    249     case SIGSEGV:
    250         AcpiOsPrintf ("Segmentation Fault\n");
    251         AeDisplayMethodCallStack ();
    252         break;
    253 
    254     default:
    255         AcpiOsPrintf ("Unknown Signal, %X\n", Sig);
    256         break;
    257     }
    258 
    259     /* Terminate application -- cleanup then exit */
    260 
    261     AcpiOsPrintf (AE_PREFIX "Terminating\n");
    262     (void) AcpiOsTerminate ();
    263     exit (0);
    264 }
    265 
    266 
    267 /******************************************************************************
    268  *
    269  * FUNCTION:    AeDisplayMethodCallStack
    270  *
    271  * PARAMETERS:  None
    272  *
    273  * RETURN:      None
    274  *
    275  * DESCRIPTION: Display current method call stack, if possible.
    276  *
    277  * NOTE:        Currently only called from a SIGSEGV, so AcpiExec is about
    278  *              to terminate.
    279  *
    280  *****************************************************************************/
    281 
    282 static void
    283 AeDisplayMethodCallStack (
    284     void)
    285 {
    286     ACPI_WALK_STATE         *WalkState;
    287     ACPI_THREAD_STATE       *ThreadList = AcpiGbl_CurrentWalkList;
    288     char                    *FullPathname = NULL;
    289 
    290 
    291     if (!AcpiGbl_MethodExecuting)
    292     {
    293         AcpiOsPrintf (AE_PREFIX "No method is executing\n");
    294         return;
    295     }
    296 
    297     /*
    298      * Try to find the currently executing control method(s)
    299      *
    300      * Note: The following code may fault if the data structures are
    301      * in an indeterminate state when the interrupt occurs. However,
    302      * in practice, this works quite well and can provide very
    303      * valuable information.
    304      *
    305      * 1) Walk the global thread list
    306      */
    307     while (ThreadList &&
    308         (ThreadList->DescriptorType == ACPI_DESC_TYPE_STATE_THREAD))
    309     {
    310         /* 2) Walk the walk state list for this thread */
    311 
    312         WalkState = ThreadList->WalkStateList;
    313         while (WalkState &&
    314             (WalkState->DescriptorType == ACPI_DESC_TYPE_WALK))
    315         {
    316             /* An executing control method */
    317 
    318             if (WalkState->MethodNode)
    319             {
    320                 FullPathname = AcpiNsGetExternalPathname (
    321                     WalkState->MethodNode);
    322 
    323                 AcpiOsPrintf (AE_PREFIX
    324                     "Executing Method: %s\n", FullPathname);
    325             }
    326 
    327             /* Execution of a deferred opcode/node */
    328 
    329             if (WalkState->DeferredNode)
    330             {
    331                 FullPathname = AcpiNsGetExternalPathname (
    332                     WalkState->DeferredNode);
    333 
    334                 AcpiOsPrintf (AE_PREFIX
    335                     "Evaluating deferred node: %s\n", FullPathname);
    336             }
    337 
    338             /* Get the currently executing AML opcode */
    339 
    340             if ((WalkState->Opcode != AML_INT_METHODCALL_OP) &&
    341                 FullPathname)
    342             {
    343                 AcpiOsPrintf (AE_PREFIX
    344                     "Current AML Opcode in %s: [%s]-0x%4.4X at %p\n",
    345                     FullPathname, AcpiPsGetOpcodeName (WalkState->Opcode),
    346                     WalkState->Opcode, WalkState->Aml);
    347             }
    348 
    349             if (FullPathname)
    350             {
    351                 ACPI_FREE (FullPathname);
    352                 FullPathname = NULL;
    353             }
    354 
    355             WalkState = WalkState->Next;
    356         }
    357 
    358         ThreadList = ThreadList->Next;
    359     }
    360 }
    361