xref: /freebsd/sys/contrib/dev/acpica/components/dispatcher/dsdebug.c (revision a0ee8cc636cd5c2374ec44ca71226564ea0bca95)
1 /******************************************************************************
2  *
3  * Module Name: dsdebug - Parser/Interpreter interface - debugging
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2015, 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 <contrib/dev/acpica/include/acpi.h>
45 #include <contrib/dev/acpica/include/accommon.h>
46 #include <contrib/dev/acpica/include/acdispat.h>
47 #include <contrib/dev/acpica/include/acnamesp.h>
48 #include <contrib/dev/acpica/include/acdisasm.h>
49 #include <contrib/dev/acpica/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     AcpiDsPrintNodePathname (WalkState->MethodNode, NULL);
179 
180     /* Display stack of executing methods */
181 
182     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DISPATCH,
183         "\n\nMethod Execution Stack:\n"));
184     NextWalkState = Thread->WalkStateList;
185 
186     /* Walk list of linked walk states */
187 
188     while (NextWalkState)
189     {
190         MethodDesc = NextWalkState->MethodDesc;
191         if (MethodDesc)
192         {
193             AcpiExStopTraceMethod (
194                     (ACPI_NAMESPACE_NODE *) MethodDesc->Method.Node,
195                     MethodDesc, WalkState);
196         }
197 
198         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
199             "    Method [%4.4s] executing: ",
200             AcpiUtGetNodeName (NextWalkState->MethodNode)));
201 
202         /* First method is the currently executing method */
203 
204         if (NextWalkState == WalkState)
205         {
206             if (Op)
207             {
208                 /* Display currently executing ASL statement */
209 
210                 Next = Op->Common.Next;
211                 Op->Common.Next = NULL;
212 
213 #ifdef ACPI_DISASSEMBLER
214                 AcpiDmDisassemble (NextWalkState, Op, ACPI_UINT32_MAX);
215 #endif
216                 Op->Common.Next = Next;
217             }
218         }
219         else
220         {
221             /*
222              * This method has called another method
223              * NOTE: the method call parse subtree is already deleted at this
224              * point, so we cannot disassemble the method invocation.
225              */
226             ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DISPATCH, "Call to method "));
227             AcpiDsPrintNodePathname (PreviousMethod, NULL);
228         }
229 
230         PreviousMethod = NextWalkState->MethodNode;
231         NextWalkState = NextWalkState->Next;
232         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DISPATCH, "\n"));
233     }
234 
235     return_VOID;
236 }
237 
238 #else
239 
240 void
241 AcpiDsDumpMethodStack (
242     ACPI_STATUS             Status,
243     ACPI_WALK_STATE         *WalkState,
244     ACPI_PARSE_OBJECT       *Op)
245 {
246     return;
247 }
248 
249 #endif
250