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