1285728Sjkim/******************************************************************************
2285728Sjkim *
3285728Sjkim * Module Name: dsdebug - Parser/Interpreter interface - debugging
4285728Sjkim *
5285728Sjkim *****************************************************************************/
6285728Sjkim
7285728Sjkim/*
8306536Sjkim * Copyright (C) 2000 - 2016, Intel Corp.
9285728Sjkim * All rights reserved.
10285728Sjkim *
11285728Sjkim * Redistribution and use in source and binary forms, with or without
12285728Sjkim * modification, are permitted provided that the following conditions
13285728Sjkim * are met:
14285728Sjkim * 1. Redistributions of source code must retain the above copyright
15285728Sjkim *    notice, this list of conditions, and the following disclaimer,
16285728Sjkim *    without modification.
17285728Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18285728Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
19285728Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
20285728Sjkim *    including a substantially similar Disclaimer requirement for further
21285728Sjkim *    binary redistribution.
22285728Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
23285728Sjkim *    of any contributors may be used to endorse or promote products derived
24285728Sjkim *    from this software without specific prior written permission.
25285728Sjkim *
26285728Sjkim * Alternatively, this software may be distributed under the terms of the
27285728Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
28285728Sjkim * Software Foundation.
29285728Sjkim *
30285728Sjkim * NO WARRANTY
31285728Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32285728Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33285728Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34285728Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35285728Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36285728Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37285728Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38285728Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39285728Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40285728Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41285728Sjkim * POSSIBILITY OF SUCH DAMAGES.
42285728Sjkim */
43285728Sjkim
44285797Sjkim#include <contrib/dev/acpica/include/acpi.h>
45285797Sjkim#include <contrib/dev/acpica/include/accommon.h>
46285797Sjkim#include <contrib/dev/acpica/include/acdispat.h>
47285797Sjkim#include <contrib/dev/acpica/include/acnamesp.h>
48285797Sjkim#include <contrib/dev/acpica/include/acdisasm.h>
49285797Sjkim#include <contrib/dev/acpica/include/acinterp.h>
50285728Sjkim
51285728Sjkim
52285728Sjkim#define _COMPONENT          ACPI_DISPATCHER
53285728Sjkim        ACPI_MODULE_NAME    ("dsdebug")
54285728Sjkim
55285728Sjkim
56285728Sjkim#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
57285728Sjkim
58285728Sjkim/* Local prototypes */
59285728Sjkim
60285728Sjkimstatic void
61285728SjkimAcpiDsPrintNodePathname (
62285728Sjkim    ACPI_NAMESPACE_NODE     *Node,
63285728Sjkim    const char              *Message);
64285728Sjkim
65285728Sjkim
66285728Sjkim/*******************************************************************************
67285728Sjkim *
68285728Sjkim * FUNCTION:    AcpiDsPrintNodePathname
69285728Sjkim *
70285728Sjkim * PARAMETERS:  Node            - Object
71285728Sjkim *              Message         - Prefix message
72285728Sjkim *
73285728Sjkim * DESCRIPTION: Print an object's full namespace pathname
74285728Sjkim *              Manages allocation/freeing of a pathname buffer
75285728Sjkim *
76285728Sjkim ******************************************************************************/
77285728Sjkim
78285728Sjkimstatic void
79285728SjkimAcpiDsPrintNodePathname (
80285728Sjkim    ACPI_NAMESPACE_NODE     *Node,
81285728Sjkim    const char              *Message)
82285728Sjkim{
83285728Sjkim    ACPI_BUFFER             Buffer;
84285728Sjkim    ACPI_STATUS             Status;
85285728Sjkim
86285728Sjkim
87285728Sjkim    ACPI_FUNCTION_TRACE (DsPrintNodePathname);
88285728Sjkim
89285728Sjkim    if (!Node)
90285728Sjkim    {
91285728Sjkim        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DISPATCH, "[NULL NAME]"));
92285728Sjkim        return_VOID;
93285728Sjkim    }
94285728Sjkim
95285728Sjkim    /* Convert handle to full pathname and print it (with supplied message) */
96285728Sjkim
97285728Sjkim    Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
98285728Sjkim
99306536Sjkim    Status = AcpiNsHandleToPathname (Node, &Buffer, TRUE);
100285728Sjkim    if (ACPI_SUCCESS (Status))
101285728Sjkim    {
102285728Sjkim        if (Message)
103285728Sjkim        {
104285728Sjkim            ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DISPATCH, "%s ", Message));
105285728Sjkim        }
106285728Sjkim
107285728Sjkim        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DISPATCH, "[%s] (Node %p)",
108285728Sjkim            (char *) Buffer.Pointer, Node));
109285728Sjkim        ACPI_FREE (Buffer.Pointer);
110285728Sjkim    }
111285728Sjkim
112285728Sjkim    return_VOID;
113285728Sjkim}
114285728Sjkim
115285728Sjkim
116285728Sjkim/*******************************************************************************
117285728Sjkim *
118285728Sjkim * FUNCTION:    AcpiDsDumpMethodStack
119285728Sjkim *
120285728Sjkim * PARAMETERS:  Status          - Method execution status
121285728Sjkim *              WalkState       - Current state of the parse tree walk
122285728Sjkim *              Op              - Executing parse op
123285728Sjkim *
124285728Sjkim * RETURN:      None
125285728Sjkim *
126285728Sjkim * DESCRIPTION: Called when a method has been aborted because of an error.
127285728Sjkim *              Dumps the method execution stack.
128285728Sjkim *
129285728Sjkim ******************************************************************************/
130285728Sjkim
131285728Sjkimvoid
132285728SjkimAcpiDsDumpMethodStack (
133285728Sjkim    ACPI_STATUS             Status,
134285728Sjkim    ACPI_WALK_STATE         *WalkState,
135285728Sjkim    ACPI_PARSE_OBJECT       *Op)
136285728Sjkim{
137285728Sjkim    ACPI_PARSE_OBJECT       *Next;
138285728Sjkim    ACPI_THREAD_STATE       *Thread;
139285728Sjkim    ACPI_WALK_STATE         *NextWalkState;
140285728Sjkim    ACPI_NAMESPACE_NODE     *PreviousMethod = NULL;
141285728Sjkim    ACPI_OPERAND_OBJECT     *MethodDesc;
142285728Sjkim
143285728Sjkim
144285728Sjkim    ACPI_FUNCTION_TRACE (DsDumpMethodStack);
145285728Sjkim
146285728Sjkim    /* Ignore control codes, they are not errors */
147285728Sjkim
148285728Sjkim    if ((Status & AE_CODE_MASK) == AE_CODE_CONTROL)
149285728Sjkim    {
150285728Sjkim        return_VOID;
151285728Sjkim    }
152285728Sjkim
153285728Sjkim    /* We may be executing a deferred opcode */
154285728Sjkim
155285728Sjkim    if (WalkState->DeferredNode)
156285728Sjkim    {
157285728Sjkim        ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
158285728Sjkim            "Executing subtree for Buffer/Package/Region\n"));
159285728Sjkim        return_VOID;
160285728Sjkim    }
161285728Sjkim
162285728Sjkim    /*
163285728Sjkim     * If there is no Thread, we are not actually executing a method.
164285728Sjkim     * This can happen when the iASL compiler calls the interpreter
165285728Sjkim     * to perform constant folding.
166285728Sjkim     */
167285728Sjkim    Thread = WalkState->Thread;
168285728Sjkim    if (!Thread)
169285728Sjkim    {
170285728Sjkim        return_VOID;
171285728Sjkim    }
172285728Sjkim
173285728Sjkim    /* Display exception and method name */
174285728Sjkim
175285728Sjkim    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
176285728Sjkim        "\n**** Exception %s during execution of method ",
177285728Sjkim        AcpiFormatException (Status)));
178306536Sjkim
179285728Sjkim    AcpiDsPrintNodePathname (WalkState->MethodNode, NULL);
180285728Sjkim
181285728Sjkim    /* Display stack of executing methods */
182285728Sjkim
183285728Sjkim    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DISPATCH,
184285728Sjkim        "\n\nMethod Execution Stack:\n"));
185285728Sjkim    NextWalkState = Thread->WalkStateList;
186285728Sjkim
187285728Sjkim    /* Walk list of linked walk states */
188285728Sjkim
189285728Sjkim    while (NextWalkState)
190285728Sjkim    {
191285728Sjkim        MethodDesc = NextWalkState->MethodDesc;
192285728Sjkim        if (MethodDesc)
193285728Sjkim        {
194285728Sjkim            AcpiExStopTraceMethod (
195306536Sjkim                (ACPI_NAMESPACE_NODE *) MethodDesc->Method.Node,
196306536Sjkim                MethodDesc, WalkState);
197285728Sjkim        }
198285728Sjkim
199285728Sjkim        ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
200285728Sjkim            "    Method [%4.4s] executing: ",
201285728Sjkim            AcpiUtGetNodeName (NextWalkState->MethodNode)));
202285728Sjkim
203285728Sjkim        /* First method is the currently executing method */
204285728Sjkim
205285728Sjkim        if (NextWalkState == WalkState)
206285728Sjkim        {
207285728Sjkim            if (Op)
208285728Sjkim            {
209285728Sjkim                /* Display currently executing ASL statement */
210285728Sjkim
211285728Sjkim                Next = Op->Common.Next;
212285728Sjkim                Op->Common.Next = NULL;
213285728Sjkim
214285728Sjkim#ifdef ACPI_DISASSEMBLER
215285728Sjkim                AcpiDmDisassemble (NextWalkState, Op, ACPI_UINT32_MAX);
216285728Sjkim#endif
217285728Sjkim                Op->Common.Next = Next;
218285728Sjkim            }
219285728Sjkim        }
220285728Sjkim        else
221285728Sjkim        {
222285728Sjkim            /*
223285728Sjkim             * This method has called another method
224306536Sjkim             * NOTE: the method call parse subtree is already deleted at
225306536Sjkim             * this point, so we cannot disassemble the method invocation.
226285728Sjkim             */
227285728Sjkim            ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DISPATCH, "Call to method "));
228285728Sjkim            AcpiDsPrintNodePathname (PreviousMethod, NULL);
229285728Sjkim        }
230285728Sjkim
231285728Sjkim        PreviousMethod = NextWalkState->MethodNode;
232285728Sjkim        NextWalkState = NextWalkState->Next;
233285728Sjkim        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DISPATCH, "\n"));
234285728Sjkim    }
235285728Sjkim
236285728Sjkim    return_VOID;
237285728Sjkim}
238285728Sjkim
239285728Sjkim#else
240285728Sjkim
241285728Sjkimvoid
242285728SjkimAcpiDsDumpMethodStack (
243285728Sjkim    ACPI_STATUS             Status,
244285728Sjkim    ACPI_WALK_STATE         *WalkState,
245285728Sjkim    ACPI_PARSE_OBJECT       *Op)
246285728Sjkim{
247285728Sjkim    return;
248285728Sjkim}
249285728Sjkim
250285728Sjkim#endif
251