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 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