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