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