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