1 /******************************************************************************
2  *
3  * Module Name: dsdebug - Parser/Interpreter interface - debugging
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2016, 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     /* Ignore control codes, they are not errors */
147 
148     if ((Status & AE_CODE_MASK) == AE_CODE_CONTROL)
149     {
150         return_VOID;
151     }
152 
153     /* We may be executing a deferred opcode */
154 
155     if (WalkState->DeferredNode)
156     {
157         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
158             "Executing subtree for Buffer/Package/Region\n"));
159         return_VOID;
160     }
161 
162     /*
163      * If there is no Thread, we are not actually executing a method.
164      * This can happen when the iASL compiler calls the interpreter
165      * to perform constant folding.
166      */
167     Thread = WalkState->Thread;
168     if (!Thread)
169     {
170         return_VOID;
171     }
172 
173     /* Display exception and method name */
174 
175     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
176         "\n**** Exception %s during execution of method ",
177         AcpiFormatException (Status)));
178 
179     AcpiDsPrintNodePathname (WalkState->MethodNode, NULL);
180 
181     /* Display stack of executing methods */
182 
183     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DISPATCH,
184         "\n\nMethod Execution Stack:\n"));
185     NextWalkState = Thread->WalkStateList;
186 
187     /* Walk list of linked walk states */
188 
189     while (NextWalkState)
190     {
191         MethodDesc = NextWalkState->MethodDesc;
192         if (MethodDesc)
193         {
194             AcpiExStopTraceMethod (
195                 (ACPI_NAMESPACE_NODE *) MethodDesc->Method.Node,
196                 MethodDesc, WalkState);
197         }
198 
199         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
200             "    Method [%4.4s] executing: ",
201             AcpiUtGetNodeName (NextWalkState->MethodNode)));
202 
203         /* First method is the currently executing method */
204 
205         if (NextWalkState == WalkState)
206         {
207             if (Op)
208             {
209                 /* Display currently executing ASL statement */
210 
211                 Next = Op->Common.Next;
212                 Op->Common.Next = NULL;
213 
214 #ifdef ACPI_DISASSEMBLER
215                 AcpiDmDisassemble (NextWalkState, Op, ACPI_UINT32_MAX);
216 #endif
217                 Op->Common.Next = Next;
218             }
219         }
220         else
221         {
222             /*
223              * This method has called another method
224              * NOTE: the method call parse subtree is already deleted at
225              * this point, so we cannot disassemble the method invocation.
226              */
227             ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DISPATCH, "Call to method "));
228             AcpiDsPrintNodePathname (PreviousMethod, NULL);
229         }
230 
231         PreviousMethod = NextWalkState->MethodNode;
232         NextWalkState = NextWalkState->Next;
233         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DISPATCH, "\n"));
234     }
235 
236     return_VOID;
237 }
238 
239 #else
240 
241 void
242 AcpiDsDumpMethodStack (
243     ACPI_STATUS             Status,
244     ACPI_WALK_STATE         *WalkState,
245     ACPI_PARSE_OBJECT       *Op)
246 {
247     return;
248 }
249 
250 #endif
251