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