1 /******************************************************************************
2  *
3  * Module Name: dsdebug - Parser/Interpreter interface - debugging
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2018, 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.h"
45 #include "accommon.h"
46 #include "acdispat.h"
47 #include "acnamesp.h"
48 #include "acdisasm.h"
49 #include "acinterp.h"
50 
51 
52 #define _COMPONENT          ACPI_DISPATCHER
53         ACPI_MODULE_NAME    ("dsdebug")
54 
55 
56 #if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
57 
58 /* Local prototypes */
59 
60 static void
61 AcpiDsPrintNodePathname (
62     ACPI_NAMESPACE_NODE     *Node,
63     const char              *Message);
64 
65 
66 /*******************************************************************************
67  *
68  * FUNCTION:    AcpiDsPrintNodePathname
69  *
70  * PARAMETERS:  Node            - Object
71  *              Message         - Prefix message
72  *
73  * DESCRIPTION: Print an object's full namespace pathname
74  *              Manages allocation/freeing of a pathname buffer
75  *
76  ******************************************************************************/
77 
78 static void
79 AcpiDsPrintNodePathname (
80     ACPI_NAMESPACE_NODE     *Node,
81     const char              *Message)
82 {
83     ACPI_BUFFER             Buffer;
84     ACPI_STATUS             Status;
85 
86 
87     ACPI_FUNCTION_TRACE (DsPrintNodePathname);
88 
89     if (!Node)
90     {
91         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DISPATCH, "[NULL NAME]"));
92         return_VOID;
93     }
94 
95     /* Convert handle to full pathname and print it (with supplied message) */
96 
97     Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
98 
99     Status = AcpiNsHandleToPathname (Node, &Buffer, TRUE);
100     if (ACPI_SUCCESS (Status))
101     {
102         if (Message)
103         {
104             ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DISPATCH, "%s ", Message));
105         }
106 
107         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DISPATCH, "[%s] (Node %p)",
108             (char *) Buffer.Pointer, Node));
109         ACPI_FREE (Buffer.Pointer);
110     }
111 
112     return_VOID;
113 }
114 
115 
116 /*******************************************************************************
117  *
118  * FUNCTION:    AcpiDsDumpMethodStack
119  *
120  * PARAMETERS:  Status          - Method execution status
121  *              WalkState       - Current state of the parse tree walk
122  *              Op              - Executing parse op
123  *
124  * RETURN:      None
125  *
126  * DESCRIPTION: Called when a method has been aborted because of an error.
127  *              Dumps the method execution stack.
128  *
129  ******************************************************************************/
130 
131 void
132 AcpiDsDumpMethodStack (
133     ACPI_STATUS             Status,
134     ACPI_WALK_STATE         *WalkState,
135     ACPI_PARSE_OBJECT       *Op)
136 {
137     ACPI_PARSE_OBJECT       *Next;
138     ACPI_THREAD_STATE       *Thread;
139     ACPI_WALK_STATE         *NextWalkState;
140     ACPI_NAMESPACE_NODE     *PreviousMethod = NULL;
141     ACPI_OPERAND_OBJECT     *MethodDesc;
142 
143 
144     ACPI_FUNCTION_TRACE (DsDumpMethodStack);
145 
146 
147     /* Ignore control codes, they are not errors */
148 
149     if ((Status & AE_CODE_MASK) == AE_CODE_CONTROL)
150     {
151         return_VOID;
152     }
153 
154     /* We may be executing a deferred opcode */
155 
156     if (WalkState->DeferredNode)
157     {
158         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
159             "Executing subtree for Buffer/Package/Region\n"));
160         return_VOID;
161     }
162 
163     /*
164      * If there is no Thread, we are not actually executing a method.
165      * This can happen when the iASL compiler calls the interpreter
166      * to perform constant folding.
167      */
168     Thread = WalkState->Thread;
169     if (!Thread)
170     {
171         return_VOID;
172     }
173 
174     /* Display exception and method name */
175 
176     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
177         "\n**** Exception %s during execution of method ",
178         AcpiFormatException (Status)));
179 
180     AcpiDsPrintNodePathname (WalkState->MethodNode, NULL);
181 
182     /* Display stack of executing methods */
183 
184     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DISPATCH,
185         "\n\nMethod Execution Stack:\n"));
186     NextWalkState = Thread->WalkStateList;
187 
188     /* Walk list of linked walk states */
189 
190     while (NextWalkState)
191     {
192         MethodDesc = NextWalkState->MethodDesc;
193         if (MethodDesc)
194         {
195             AcpiExStopTraceMethod (
196                 (ACPI_NAMESPACE_NODE *) MethodDesc->Method.Node,
197                 MethodDesc, WalkState);
198         }
199 
200         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
201             "    Method [%4.4s] executing: ",
202             AcpiUtGetNodeName (NextWalkState->MethodNode)));
203 
204         /* First method is the currently executing method */
205 
206         if (NextWalkState == WalkState)
207         {
208             if (Op)
209             {
210                 /* Display currently executing ASL statement */
211 
212                 Next = Op->Common.Next;
213                 Op->Common.Next = NULL;
214 
215 #ifdef ACPI_DISASSEMBLER
216                 if (WalkState->MethodNode != AcpiGbl_RootNode)
217                 {
218                     /* More verbose if not module-level code */
219 
220                     AcpiOsPrintf ("Failed at ");
221                     AcpiDmDisassemble (NextWalkState, Op, ACPI_UINT32_MAX);
222                 }
223 #endif
224                 Op->Common.Next = Next;
225             }
226         }
227         else
228         {
229             /*
230              * This method has called another method
231              * NOTE: the method call parse subtree is already deleted at
232              * this point, so we cannot disassemble the method invocation.
233              */
234             ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DISPATCH, "Call to method "));
235             AcpiDsPrintNodePathname (PreviousMethod, NULL);
236         }
237 
238         PreviousMethod = NextWalkState->MethodNode;
239         NextWalkState = NextWalkState->Next;
240         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DISPATCH, "\n"));
241     }
242 
243     return_VOID;
244 }
245 
246 #else
247 
248 void
249 AcpiDsDumpMethodStack (
250     ACPI_STATUS             Status,
251     ACPI_WALK_STATE         *WalkState,
252     ACPI_PARSE_OBJECT       *Op)
253 {
254     return;
255 }
256 
257 #endif
258