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