aeexception.c revision 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
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 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
152 Cleanup:
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
186 void ACPI_SYSTEM_XFACE
187 AeSignalHandler (
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
250 static void
251 AeDisplayMethodCallStack (
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