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