Linux-libre 4.19.123-gnu
[librecmc/linux-libre.git] / drivers / acpi / acpica / dsdebug.c
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 - 2018, 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 ((status & AE_CODE_MASK) == AE_CODE_CONTROL) {
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