Home | History | Annotate | Line # | Download | only in acpiexec
aeexception.c revision 1.1.1.4
      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 /******************************************************************************
     58  *
     59  * FUNCTION:    AeExceptionHandler
     60  *
     61  * PARAMETERS:  Standard exception handler parameters
     62  *
     63  * RETURN:      Status
     64  *
     65  * DESCRIPTION: System exception handler for AcpiExec utility. Called from
     66  *              the core ACPICA code after any exception during method
     67  *              execution.
     68  *
     69  *****************************************************************************/
     70 
     71 ACPI_STATUS
     72 AeExceptionHandler (
     73     ACPI_STATUS             AmlStatus,
     74     ACPI_NAME               Name,
     75     UINT16                  Opcode,
     76     UINT32                  AmlOffset,
     77     void                    *Context)
     78 {
     79     ACPI_STATUS             NewAmlStatus = AmlStatus;
     80     ACPI_STATUS             Status;
     81     ACPI_BUFFER             ReturnObj;
     82     ACPI_OBJECT_LIST        ArgList;
     83     ACPI_OBJECT             Arg[3];
     84     const char              *Exception;
     85     ACPI_HANDLE             ErrHandle;
     86 
     87 
     88     Exception = AcpiFormatException (AmlStatus);
     89     AcpiOsPrintf (AE_PREFIX
     90         "Exception %s during execution\n", Exception);
     91 
     92     if (Name)
     93     {
     94         if (ACPI_COMPARE_NAME (&Name, ACPI_ROOT_PATHNAME))
     95         {
     96             AcpiOsPrintf (AE_PREFIX
     97                 "Evaluating executable code at [%s]\n", ACPI_NAMESPACE_ROOT);
     98         }
     99         else
    100         {
    101             AcpiOsPrintf (AE_PREFIX
    102                 "Evaluating Method or Node: [%4.4s]\n", (char *) &Name);
    103         }
    104     }
    105 
    106     /* Be terse about loop timeouts */
    107 
    108     if ((AmlStatus == AE_AML_LOOP_TIMEOUT) && AcpiGbl_AbortLoopOnTimeout)
    109     {
    110         AcpiOsPrintf (AE_PREFIX "Aborting loop after timeout\n");
    111         return (AE_OK);
    112     }
    113 
    114     AcpiOsPrintf ("\n" AE_PREFIX
    115         "AML Opcode [%s], Method Offset ~%5.5X\n",
    116         AcpiPsGetOpcodeName (Opcode), AmlOffset);
    117 
    118     /* Invoke the _ERR method if present */
    119 
    120     Status = AcpiGetHandle (NULL, "\\_ERR", &ErrHandle);
    121     if (ACPI_FAILURE (Status))
    122     {
    123         goto Cleanup;
    124     }
    125 
    126     /* Setup parameter object */
    127 
    128     ArgList.Count = 3;
    129     ArgList.Pointer = Arg;
    130 
    131     Arg[0].Type = ACPI_TYPE_INTEGER;
    132     Arg[0].Integer.Value = AmlStatus;
    133 
    134     Arg[1].Type = ACPI_TYPE_STRING;
    135     Arg[1].String.Pointer = ACPI_CAST_PTR (char, Exception);
    136     Arg[1].String.Length = strlen (Exception);
    137 
    138     Arg[2].Type = ACPI_TYPE_INTEGER;
    139     Arg[2].Integer.Value = AcpiOsGetThreadId();
    140 
    141     /* Setup return buffer */
    142 
    143     ReturnObj.Pointer = NULL;
    144     ReturnObj.Length = ACPI_ALLOCATE_BUFFER;
    145 
    146     Status = AcpiEvaluateObject (ErrHandle, NULL, &ArgList, &ReturnObj);
    147     if (ACPI_SUCCESS (Status))
    148     {
    149         if (ReturnObj.Pointer)
    150         {
    151             /* Override original status */
    152 
    153             NewAmlStatus = (ACPI_STATUS)
    154                 ((ACPI_OBJECT *) ReturnObj.Pointer)->Integer.Value;
    155 
    156             /* Free a buffer created via ACPI_ALLOCATE_BUFFER */
    157 
    158             AcpiOsFree (ReturnObj.Pointer);
    159         }
    160     }
    161     else if (Status != AE_NOT_FOUND)
    162     {
    163         AcpiOsPrintf (AE_PREFIX
    164             "Could not execute _ERR method, %s\n",
    165             AcpiFormatException (Status));
    166     }
    167 
    168 Cleanup:
    169 
    170     if (AcpiGbl_IgnoreErrors)
    171     {
    172         /* Global option to ignore all method errors, just return OK */
    173 
    174         NewAmlStatus = AE_OK;
    175     }
    176     if (NewAmlStatus != AmlStatus)
    177     {
    178         /* Request to override actual status with a different status */
    179 
    180         AcpiOsPrintf (AE_PREFIX
    181             "Exception override, new status %s\n\n",
    182             AcpiFormatException (NewAmlStatus));
    183     }
    184 
    185     return (NewAmlStatus);
    186 }
    187 
    188 
    189 /******************************************************************************
    190  *
    191  * FUNCTION:    AeSignalHandler
    192  *
    193  * PARAMETERS:  Sig
    194  *
    195  * RETURN:      none
    196  *
    197  * DESCRIPTION: Master signal handler. Currently handles SIGINT (ctrl-c),
    198  *              and SIGSEGV (Segment violation).
    199  *
    200  *****************************************************************************/
    201 
    202 void ACPI_SYSTEM_XFACE
    203 AeSignalHandler (
    204     int                     Sig)
    205 {
    206 
    207     fflush(stdout);
    208     AcpiOsPrintf ("\n" AE_PREFIX);
    209 
    210     switch (Sig)
    211     {
    212     case SIGINT:
    213         signal(Sig, SIG_IGN);
    214         AcpiOsPrintf ("<Control-C>\n");
    215 
    216         /* Abort the application if there are no methods executing */
    217 
    218         if (!AcpiGbl_MethodExecuting)
    219         {
    220             break;
    221         }
    222 
    223         /*
    224          * Abort the method(s). This will also dump the method call
    225          * stack so there is no need to do it here. The application
    226          * will then drop back into the debugger interface.
    227          */
    228         AcpiGbl_AbortMethod = TRUE;
    229         AcpiOsPrintf (AE_PREFIX "Control Method Call Stack:\n");
    230         signal (SIGINT, AeSignalHandler);
    231         return;
    232 
    233     case SIGSEGV:
    234         AcpiOsPrintf ("Segmentation Fault\n");
    235         AeDisplayMethodCallStack ();
    236         break;
    237 
    238     default:
    239         AcpiOsPrintf ("Unknown Signal, %X\n", Sig);
    240         break;
    241     }
    242 
    243     /* Terminate application -- cleanup then exit */
    244 
    245     AcpiOsPrintf (AE_PREFIX "Terminating\n");
    246     (void) AcpiOsTerminate ();
    247     exit (0);
    248 }
    249 
    250 
    251 /******************************************************************************
    252  *
    253  * FUNCTION:    AeDisplayMethodCallStack
    254  *
    255  * PARAMETERS:  None
    256  *
    257  * RETURN:      None
    258  *
    259  * DESCRIPTION: Display current method call stack, if possible.
    260  *
    261  * NOTE:        Currently only called from a SIGSEGV, so AcpiExec is about
    262  *              to terminate.
    263  *
    264  *****************************************************************************/
    265 
    266 static void
    267 AeDisplayMethodCallStack (
    268     void)
    269 {
    270     ACPI_WALK_STATE         *WalkState;
    271     ACPI_THREAD_STATE       *ThreadList = AcpiGbl_CurrentWalkList;
    272     char                    *FullPathname = NULL;
    273 
    274 
    275     if (!AcpiGbl_MethodExecuting)
    276     {
    277         AcpiOsPrintf (AE_PREFIX "No method is executing\n");
    278         return;
    279     }
    280 
    281     /*
    282      * Try to find the currently executing control method(s)
    283      *
    284      * Note: The following code may fault if the data structures are
    285      * in an indeterminate state when the interrupt occurs. However,
    286      * in practice, this works quite well and can provide very
    287      * valuable information.
    288      *
    289      * 1) Walk the global thread list
    290      */
    291     while (ThreadList &&
    292         (ThreadList->DescriptorType == ACPI_DESC_TYPE_STATE_THREAD))
    293     {
    294         /* 2) Walk the walk state list for this thread */
    295 
    296         WalkState = ThreadList->WalkStateList;
    297         while (WalkState &&
    298             (WalkState->DescriptorType == ACPI_DESC_TYPE_WALK))
    299         {
    300             /* An executing control method */
    301 
    302             if (WalkState->MethodNode)
    303             {
    304                 FullPathname = AcpiNsGetExternalPathname (
    305                     WalkState->MethodNode);
    306 
    307                 AcpiOsPrintf (AE_PREFIX
    308                     "Executing Method: %s\n", FullPathname);
    309             }
    310 
    311             /* Execution of a deferred opcode/node */
    312 
    313             if (WalkState->DeferredNode)
    314             {
    315                 FullPathname = AcpiNsGetExternalPathname (
    316                     WalkState->DeferredNode);
    317 
    318                 AcpiOsPrintf (AE_PREFIX
    319                     "Evaluating deferred node: %s\n", FullPathname);
    320             }
    321 
    322             /* Get the currently executing AML opcode */
    323 
    324             if ((WalkState->Opcode != AML_INT_METHODCALL_OP) &&
    325                 FullPathname)
    326             {
    327                 AcpiOsPrintf (AE_PREFIX
    328                     "Current AML Opcode in %s: [%s]-0x%4.4X at %p\n",
    329                     FullPathname, AcpiPsGetOpcodeName (WalkState->Opcode),
    330                     WalkState->Opcode, WalkState->Aml);
    331             }
    332 
    333             if (FullPathname)
    334             {
    335                 ACPI_FREE (FullPathname);
    336                 FullPathname = NULL;
    337             }
    338 
    339             WalkState = WalkState->Next;
    340         }
    341 
    342         ThreadList = ThreadList->Next;
    343     }
    344 }
    345