162306a36Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
262306a36Sopenharmony_ci/******************************************************************************
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Module Name: dsdebug - Parser/Interpreter interface - debugging
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Copyright (C) 2000 - 2023, Intel Corp.
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci *****************************************************************************/
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <acpi/acpi.h>
1162306a36Sopenharmony_ci#include "accommon.h"
1262306a36Sopenharmony_ci#include "acdispat.h"
1362306a36Sopenharmony_ci#include "acnamesp.h"
1462306a36Sopenharmony_ci#ifdef ACPI_DISASSEMBLER
1562306a36Sopenharmony_ci#include "acdisasm.h"
1662306a36Sopenharmony_ci#endif
1762306a36Sopenharmony_ci#include "acinterp.h"
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#define _COMPONENT          ACPI_DISPATCHER
2062306a36Sopenharmony_ciACPI_MODULE_NAME("dsdebug")
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
2362306a36Sopenharmony_ci/* Local prototypes */
2462306a36Sopenharmony_cistatic void
2562306a36Sopenharmony_ciacpi_ds_print_node_pathname(struct acpi_namespace_node *node,
2662306a36Sopenharmony_ci			    const char *message);
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci/*******************************************************************************
2962306a36Sopenharmony_ci *
3062306a36Sopenharmony_ci * FUNCTION:    acpi_ds_print_node_pathname
3162306a36Sopenharmony_ci *
3262306a36Sopenharmony_ci * PARAMETERS:  node            - Object
3362306a36Sopenharmony_ci *              message         - Prefix message
3462306a36Sopenharmony_ci *
3562306a36Sopenharmony_ci * DESCRIPTION: Print an object's full namespace pathname
3662306a36Sopenharmony_ci *              Manages allocation/freeing of a pathname buffer
3762306a36Sopenharmony_ci *
3862306a36Sopenharmony_ci ******************************************************************************/
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_cistatic void
4162306a36Sopenharmony_ciacpi_ds_print_node_pathname(struct acpi_namespace_node *node,
4262306a36Sopenharmony_ci			    const char *message)
4362306a36Sopenharmony_ci{
4462306a36Sopenharmony_ci	struct acpi_buffer buffer;
4562306a36Sopenharmony_ci	acpi_status status;
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci	ACPI_FUNCTION_TRACE(ds_print_node_pathname);
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	if (!node) {
5062306a36Sopenharmony_ci		ACPI_DEBUG_PRINT_RAW((ACPI_DB_DISPATCH, "[NULL NAME]"));
5162306a36Sopenharmony_ci		return_VOID;
5262306a36Sopenharmony_ci	}
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci	/* Convert handle to full pathname and print it (with supplied message) */
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	status = acpi_ns_handle_to_pathname(node, &buffer, TRUE);
5962306a36Sopenharmony_ci	if (ACPI_SUCCESS(status)) {
6062306a36Sopenharmony_ci		if (message) {
6162306a36Sopenharmony_ci			ACPI_DEBUG_PRINT_RAW((ACPI_DB_DISPATCH, "%s ",
6262306a36Sopenharmony_ci					      message));
6362306a36Sopenharmony_ci		}
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci		ACPI_DEBUG_PRINT_RAW((ACPI_DB_DISPATCH, "[%s] (Node %p)",
6662306a36Sopenharmony_ci				      (char *)buffer.pointer, node));
6762306a36Sopenharmony_ci		ACPI_FREE(buffer.pointer);
6862306a36Sopenharmony_ci	}
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	return_VOID;
7162306a36Sopenharmony_ci}
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci/*******************************************************************************
7462306a36Sopenharmony_ci *
7562306a36Sopenharmony_ci * FUNCTION:    acpi_ds_dump_method_stack
7662306a36Sopenharmony_ci *
7762306a36Sopenharmony_ci * PARAMETERS:  status          - Method execution status
7862306a36Sopenharmony_ci *              walk_state      - Current state of the parse tree walk
7962306a36Sopenharmony_ci *              op              - Executing parse op
8062306a36Sopenharmony_ci *
8162306a36Sopenharmony_ci * RETURN:      None
8262306a36Sopenharmony_ci *
8362306a36Sopenharmony_ci * DESCRIPTION: Called when a method has been aborted because of an error.
8462306a36Sopenharmony_ci *              Dumps the method execution stack.
8562306a36Sopenharmony_ci *
8662306a36Sopenharmony_ci ******************************************************************************/
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_civoid
8962306a36Sopenharmony_ciacpi_ds_dump_method_stack(acpi_status status,
9062306a36Sopenharmony_ci			  struct acpi_walk_state *walk_state,
9162306a36Sopenharmony_ci			  union acpi_parse_object *op)
9262306a36Sopenharmony_ci{
9362306a36Sopenharmony_ci	union acpi_parse_object *next;
9462306a36Sopenharmony_ci	struct acpi_thread_state *thread;
9562306a36Sopenharmony_ci	struct acpi_walk_state *next_walk_state;
9662306a36Sopenharmony_ci	struct acpi_namespace_node *previous_method = NULL;
9762306a36Sopenharmony_ci	union acpi_operand_object *method_desc;
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	ACPI_FUNCTION_TRACE(ds_dump_method_stack);
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci	/* Ignore control codes, they are not errors */
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	if (ACPI_CNTL_EXCEPTION(status)) {
10462306a36Sopenharmony_ci		return_VOID;
10562306a36Sopenharmony_ci	}
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci	/* We may be executing a deferred opcode */
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	if (walk_state->deferred_node) {
11062306a36Sopenharmony_ci		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
11162306a36Sopenharmony_ci				  "Executing subtree for Buffer/Package/Region\n"));
11262306a36Sopenharmony_ci		return_VOID;
11362306a36Sopenharmony_ci	}
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci	/*
11662306a36Sopenharmony_ci	 * If there is no Thread, we are not actually executing a method.
11762306a36Sopenharmony_ci	 * This can happen when the iASL compiler calls the interpreter
11862306a36Sopenharmony_ci	 * to perform constant folding.
11962306a36Sopenharmony_ci	 */
12062306a36Sopenharmony_ci	thread = walk_state->thread;
12162306a36Sopenharmony_ci	if (!thread) {
12262306a36Sopenharmony_ci		return_VOID;
12362306a36Sopenharmony_ci	}
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	/* Display exception and method name */
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
12862306a36Sopenharmony_ci			  "\n**** Exception %s during execution of method ",
12962306a36Sopenharmony_ci			  acpi_format_exception(status)));
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci	acpi_ds_print_node_pathname(walk_state->method_node, NULL);
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	/* Display stack of executing methods */
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	ACPI_DEBUG_PRINT_RAW((ACPI_DB_DISPATCH,
13662306a36Sopenharmony_ci			      "\n\nMethod Execution Stack:\n"));
13762306a36Sopenharmony_ci	next_walk_state = thread->walk_state_list;
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci	/* Walk list of linked walk states */
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci	while (next_walk_state) {
14262306a36Sopenharmony_ci		method_desc = next_walk_state->method_desc;
14362306a36Sopenharmony_ci		if (method_desc) {
14462306a36Sopenharmony_ci			acpi_ex_stop_trace_method((struct acpi_namespace_node *)
14562306a36Sopenharmony_ci						  method_desc->method.node,
14662306a36Sopenharmony_ci						  method_desc, walk_state);
14762306a36Sopenharmony_ci		}
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
15062306a36Sopenharmony_ci				  "    Method [%4.4s] executing: ",
15162306a36Sopenharmony_ci				  acpi_ut_get_node_name(next_walk_state->
15262306a36Sopenharmony_ci							method_node)));
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci		/* First method is the currently executing method */
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci		if (next_walk_state == walk_state) {
15762306a36Sopenharmony_ci			if (op) {
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci				/* Display currently executing ASL statement */
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci				next = op->common.next;
16262306a36Sopenharmony_ci				op->common.next = NULL;
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci#ifdef ACPI_DISASSEMBLER
16562306a36Sopenharmony_ci				if (walk_state->method_node !=
16662306a36Sopenharmony_ci				    acpi_gbl_root_node) {
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci					/* More verbose if not module-level code */
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci					acpi_os_printf("Failed at ");
17162306a36Sopenharmony_ci					acpi_dm_disassemble(next_walk_state, op,
17262306a36Sopenharmony_ci							    ACPI_UINT32_MAX);
17362306a36Sopenharmony_ci				}
17462306a36Sopenharmony_ci#endif
17562306a36Sopenharmony_ci				op->common.next = next;
17662306a36Sopenharmony_ci			}
17762306a36Sopenharmony_ci		} else {
17862306a36Sopenharmony_ci			/*
17962306a36Sopenharmony_ci			 * This method has called another method
18062306a36Sopenharmony_ci			 * NOTE: the method call parse subtree is already deleted at
18162306a36Sopenharmony_ci			 * this point, so we cannot disassemble the method invocation.
18262306a36Sopenharmony_ci			 */
18362306a36Sopenharmony_ci			ACPI_DEBUG_PRINT_RAW((ACPI_DB_DISPATCH,
18462306a36Sopenharmony_ci					      "Call to method "));
18562306a36Sopenharmony_ci			acpi_ds_print_node_pathname(previous_method, NULL);
18662306a36Sopenharmony_ci		}
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci		previous_method = next_walk_state->method_node;
18962306a36Sopenharmony_ci		next_walk_state = next_walk_state->next;
19062306a36Sopenharmony_ci		ACPI_DEBUG_PRINT_RAW((ACPI_DB_DISPATCH, "\n"));
19162306a36Sopenharmony_ci	}
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci	return_VOID;
19462306a36Sopenharmony_ci}
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci#else
19762306a36Sopenharmony_civoid
19862306a36Sopenharmony_ciacpi_ds_dump_method_stack(acpi_status status,
19962306a36Sopenharmony_ci			  struct acpi_walk_state *walk_state,
20062306a36Sopenharmony_ci			  union acpi_parse_object *op)
20162306a36Sopenharmony_ci{
20262306a36Sopenharmony_ci	return;
20362306a36Sopenharmony_ci}
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci#endif
206