1 /****************************************************************************** 2 * 3 * Module Name: dsdebug - Parser/Interpreter interface - debugging 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 "acpi.h" 45 #include "accommon.h" 46 #include "acdispat.h" 47 #include "acnamesp.h" 48 #include "acdisasm.h" 49 #include "acinterp.h" 50 51 52 #define _COMPONENT ACPI_DISPATCHER 53 ACPI_MODULE_NAME ("dsdebug") 54 55 56 #if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) 57 58 /* Local prototypes */ 59 60 static void 61 AcpiDsPrintNodePathname ( 62 ACPI_NAMESPACE_NODE *Node, 63 const char *Message); 64 65 66 /******************************************************************************* 67 * 68 * FUNCTION: AcpiDsPrintNodePathname 69 * 70 * PARAMETERS: Node - Object 71 * Message - Prefix message 72 * 73 * DESCRIPTION: Print an object's full namespace pathname 74 * Manages allocation/freeing of a pathname buffer 75 * 76 ******************************************************************************/ 77 78 static void 79 AcpiDsPrintNodePathname ( 80 ACPI_NAMESPACE_NODE *Node, 81 const char *Message) 82 { 83 ACPI_BUFFER Buffer; 84 ACPI_STATUS Status; 85 86 87 ACPI_FUNCTION_TRACE (DsPrintNodePathname); 88 89 if (!Node) 90 { 91 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DISPATCH, "[NULL NAME]")); 92 return_VOID; 93 } 94 95 /* Convert handle to full pathname and print it (with supplied message) */ 96 97 Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER; 98 99 Status = AcpiNsHandleToPathname (Node, &Buffer, TRUE); 100 if (ACPI_SUCCESS (Status)) 101 { 102 if (Message) 103 { 104 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DISPATCH, "%s ", Message)); 105 } 106 107 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DISPATCH, "[%s] (Node %p)", 108 (char *) Buffer.Pointer, Node)); 109 ACPI_FREE (Buffer.Pointer); 110 } 111 112 return_VOID; 113 } 114 115 116 /******************************************************************************* 117 * 118 * FUNCTION: AcpiDsDumpMethodStack 119 * 120 * PARAMETERS: Status - Method execution status 121 * WalkState - Current state of the parse tree walk 122 * Op - Executing parse op 123 * 124 * RETURN: None 125 * 126 * DESCRIPTION: Called when a method has been aborted because of an error. 127 * Dumps the method execution stack. 128 * 129 ******************************************************************************/ 130 131 void 132 AcpiDsDumpMethodStack ( 133 ACPI_STATUS Status, 134 ACPI_WALK_STATE *WalkState, 135 ACPI_PARSE_OBJECT *Op) 136 { 137 ACPI_PARSE_OBJECT *Next; 138 ACPI_THREAD_STATE *Thread; 139 ACPI_WALK_STATE *NextWalkState; 140 ACPI_NAMESPACE_NODE *PreviousMethod = NULL; 141 ACPI_OPERAND_OBJECT *MethodDesc; 142 143 144 ACPI_FUNCTION_TRACE (DsDumpMethodStack); 145 146 147 /* Ignore control codes, they are not errors */ 148 149 if ((Status & AE_CODE_MASK) == AE_CODE_CONTROL) 150 { 151 return_VOID; 152 } 153 154 /* We may be executing a deferred opcode */ 155 156 if (WalkState->DeferredNode) 157 { 158 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 159 "Executing subtree for Buffer/Package/Region\n")); 160 return_VOID; 161 } 162 163 /* 164 * If there is no Thread, we are not actually executing a method. 165 * This can happen when the iASL compiler calls the interpreter 166 * to perform constant folding. 167 */ 168 Thread = WalkState->Thread; 169 if (!Thread) 170 { 171 return_VOID; 172 } 173 174 /* Display exception and method name */ 175 176 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 177 "\n**** Exception %s during execution of method ", 178 AcpiFormatException (Status))); 179 180 AcpiDsPrintNodePathname (WalkState->MethodNode, NULL); 181 182 /* Display stack of executing methods */ 183 184 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DISPATCH, 185 "\n\nMethod Execution Stack:\n")); 186 NextWalkState = Thread->WalkStateList; 187 188 /* Walk list of linked walk states */ 189 190 while (NextWalkState) 191 { 192 MethodDesc = NextWalkState->MethodDesc; 193 if (MethodDesc) 194 { 195 AcpiExStopTraceMethod ( 196 (ACPI_NAMESPACE_NODE *) MethodDesc->Method.Node, 197 MethodDesc, WalkState); 198 } 199 200 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, 201 " Method [%4.4s] executing: ", 202 AcpiUtGetNodeName (NextWalkState->MethodNode))); 203 204 /* First method is the currently executing method */ 205 206 if (NextWalkState == WalkState) 207 { 208 if (Op) 209 { 210 /* Display currently executing ASL statement */ 211 212 Next = Op->Common.Next; 213 Op->Common.Next = NULL; 214 215 #ifdef ACPI_DISASSEMBLER 216 if (WalkState->MethodNode != AcpiGbl_RootNode) 217 { 218 /* More verbose if not module-level code */ 219 220 AcpiOsPrintf ("Failed at "); 221 AcpiDmDisassemble (NextWalkState, Op, ACPI_UINT32_MAX); 222 } 223 #endif 224 Op->Common.Next = Next; 225 } 226 } 227 else 228 { 229 /* 230 * This method has called another method 231 * NOTE: the method call parse subtree is already deleted at 232 * this point, so we cannot disassemble the method invocation. 233 */ 234 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DISPATCH, "Call to method ")); 235 AcpiDsPrintNodePathname (PreviousMethod, NULL); 236 } 237 238 PreviousMethod = NextWalkState->MethodNode; 239 NextWalkState = NextWalkState->Next; 240 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DISPATCH, "\n")); 241 } 242 243 return_VOID; 244 } 245 246 #else 247 248 void 249 AcpiDsDumpMethodStack ( 250 ACPI_STATUS Status, 251 ACPI_WALK_STATE *WalkState, 252 ACPI_PARSE_OBJECT *Op) 253 { 254 return; 255 } 256 257 #endif 258