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