1 /*******************************************************************************
2  *
3  * Module Name: dbobject - ACPI object decode and display
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 "acpi.h"
45 #include "accommon.h"
46 #include "acnamesp.h"
47 #include "acdebug.h"
48 
49 
50 #ifdef ACPI_DEBUGGER
51 
52 #define _COMPONENT          ACPI_CA_DEBUGGER
53         ACPI_MODULE_NAME    ("dbobject")
54 
55 
56 /* Local prototypes */
57 
58 static void
59 AcpiDbDecodeNode (
60     ACPI_NAMESPACE_NODE     *Node);
61 
62 
63 /*******************************************************************************
64  *
65  * FUNCTION:    AcpiDbDumpMethodInfo
66  *
67  * PARAMETERS:  Status          - Method execution status
68  *              WalkState       - Current state of the parse tree walk
69  *
70  * RETURN:      None
71  *
72  * DESCRIPTION: Called when a method has been aborted because of an error.
73  *              Dumps the method execution stack, and the method locals/args,
74  *              and disassembles the AML opcode that failed.
75  *
76  ******************************************************************************/
77 
78 void
79 AcpiDbDumpMethodInfo (
80     ACPI_STATUS             Status,
81     ACPI_WALK_STATE         *WalkState)
82 {
83     ACPI_THREAD_STATE       *Thread;
84 
85 
86     /* Ignore control codes, they are not errors */
87 
88     if ((Status & AE_CODE_MASK) == AE_CODE_CONTROL)
89     {
90         return;
91     }
92 
93     /* We may be executing a deferred opcode */
94 
95     if (WalkState->DeferredNode)
96     {
97         AcpiOsPrintf ("Executing subtree for Buffer/Package/Region\n");
98         return;
99     }
100 
101     /*
102      * If there is no Thread, we are not actually executing a method.
103      * This can happen when the iASL compiler calls the interpreter
104      * to perform constant folding.
105      */
106     Thread = WalkState->Thread;
107     if (!Thread)
108     {
109         return;
110     }
111 
112     /* Display the method locals and arguments */
113 
114     AcpiOsPrintf ("\n");
115     AcpiDbDecodeLocals (WalkState);
116     AcpiOsPrintf ("\n");
117     AcpiDbDecodeArguments (WalkState);
118     AcpiOsPrintf ("\n");
119 }
120 
121 
122 /*******************************************************************************
123  *
124  * FUNCTION:    AcpiDbDecodeInternalObject
125  *
126  * PARAMETERS:  ObjDesc         - Object to be displayed
127  *
128  * RETURN:      None
129  *
130  * DESCRIPTION: Short display of an internal object. Numbers/Strings/Buffers.
131  *
132  ******************************************************************************/
133 
134 void
135 AcpiDbDecodeInternalObject (
136     ACPI_OPERAND_OBJECT     *ObjDesc)
137 {
138     UINT32                  i;
139 
140 
141     if (!ObjDesc)
142     {
143         AcpiOsPrintf (" Uninitialized");
144         return;
145     }
146 
147     if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) != ACPI_DESC_TYPE_OPERAND)
148     {
149         AcpiOsPrintf (" %p [%s]", ObjDesc,
150             AcpiUtGetDescriptorName (ObjDesc));
151         return;
152     }
153 
154     AcpiOsPrintf (" %s", AcpiUtGetObjectTypeName (ObjDesc));
155 
156     switch (ObjDesc->Common.Type)
157     {
158     case ACPI_TYPE_INTEGER:
159 
160         AcpiOsPrintf (" %8.8X%8.8X",
161             ACPI_FORMAT_UINT64 (ObjDesc->Integer.Value));
162         break;
163 
164     case ACPI_TYPE_STRING:
165 
166         AcpiOsPrintf ("(%u) \"%.24s",
167             ObjDesc->String.Length, ObjDesc->String.Pointer);
168 
169         if (ObjDesc->String.Length > 24)
170         {
171             AcpiOsPrintf ("...");
172         }
173         else
174         {
175             AcpiOsPrintf ("\"");
176         }
177         break;
178 
179     case ACPI_TYPE_BUFFER:
180 
181         AcpiOsPrintf ("(%u)", ObjDesc->Buffer.Length);
182         for (i = 0; (i < 8) && (i < ObjDesc->Buffer.Length); i++)
183         {
184             AcpiOsPrintf (" %2.2X", ObjDesc->Buffer.Pointer[i]);
185         }
186         break;
187 
188     default:
189 
190         AcpiOsPrintf (" %p", ObjDesc);
191         break;
192     }
193 }
194 
195 
196 /*******************************************************************************
197  *
198  * FUNCTION:    AcpiDbDecodeNode
199  *
200  * PARAMETERS:  Node        - Object to be displayed
201  *
202  * RETURN:      None
203  *
204  * DESCRIPTION: Short display of a namespace node
205  *
206  ******************************************************************************/
207 
208 static void
209 AcpiDbDecodeNode (
210     ACPI_NAMESPACE_NODE     *Node)
211 {
212 
213     AcpiOsPrintf ("<Node>            Name %4.4s",
214         AcpiUtGetNodeName (Node));
215 
216     if (Node->Flags & ANOBJ_METHOD_ARG)
217     {
218         AcpiOsPrintf (" [Method Arg]");
219     }
220     if (Node->Flags & ANOBJ_METHOD_LOCAL)
221     {
222         AcpiOsPrintf (" [Method Local]");
223     }
224 
225     switch (Node->Type)
226     {
227     /* These types have no attached object */
228 
229     case ACPI_TYPE_DEVICE:
230 
231         AcpiOsPrintf (" Device");
232         break;
233 
234     case ACPI_TYPE_THERMAL:
235 
236         AcpiOsPrintf (" Thermal Zone");
237         break;
238 
239     default:
240 
241         AcpiDbDecodeInternalObject (AcpiNsGetAttachedObject (Node));
242         break;
243     }
244 }
245 
246 
247 /*******************************************************************************
248  *
249  * FUNCTION:    AcpiDbDisplayInternalObject
250  *
251  * PARAMETERS:  ObjDesc         - Object to be displayed
252  *              WalkState       - Current walk state
253  *
254  * RETURN:      None
255  *
256  * DESCRIPTION: Short display of an internal object
257  *
258  ******************************************************************************/
259 
260 void
261 AcpiDbDisplayInternalObject (
262     ACPI_OPERAND_OBJECT     *ObjDesc,
263     ACPI_WALK_STATE         *WalkState)
264 {
265     UINT8                   Type;
266 
267 
268     AcpiOsPrintf ("%p ", ObjDesc);
269 
270     if (!ObjDesc)
271     {
272         AcpiOsPrintf ("<Null Object>\n");
273         return;
274     }
275 
276     /* Decode the object type */
277 
278     switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc))
279     {
280     case ACPI_DESC_TYPE_PARSER:
281 
282         AcpiOsPrintf ("<Parser>  ");
283         break;
284 
285     case ACPI_DESC_TYPE_NAMED:
286 
287         AcpiDbDecodeNode ((ACPI_NAMESPACE_NODE *) ObjDesc);
288         break;
289 
290     case ACPI_DESC_TYPE_OPERAND:
291 
292         Type = ObjDesc->Common.Type;
293         if (Type > ACPI_TYPE_LOCAL_MAX)
294         {
295             AcpiOsPrintf (" Type %X [Invalid Type]", (UINT32) Type);
296             return;
297         }
298 
299         /* Decode the ACPI object type */
300 
301         switch (ObjDesc->Common.Type)
302         {
303         case ACPI_TYPE_LOCAL_REFERENCE:
304 
305             AcpiOsPrintf ("[%s] ", AcpiUtGetReferenceName (ObjDesc));
306 
307             /* Decode the refererence */
308 
309             switch (ObjDesc->Reference.Class)
310             {
311             case ACPI_REFCLASS_LOCAL:
312 
313                 AcpiOsPrintf ("%X ", ObjDesc->Reference.Value);
314                 if (WalkState)
315                 {
316                     ObjDesc = WalkState->LocalVariables
317                         [ObjDesc->Reference.Value].Object;
318                     AcpiOsPrintf ("%p", ObjDesc);
319                     AcpiDbDecodeInternalObject (ObjDesc);
320                 }
321                 break;
322 
323             case ACPI_REFCLASS_ARG:
324 
325                 AcpiOsPrintf ("%X ", ObjDesc->Reference.Value);
326                 if (WalkState)
327                 {
328                     ObjDesc = WalkState->Arguments
329                         [ObjDesc->Reference.Value].Object;
330                     AcpiOsPrintf ("%p", ObjDesc);
331                     AcpiDbDecodeInternalObject (ObjDesc);
332                 }
333                 break;
334 
335             case ACPI_REFCLASS_INDEX:
336 
337                 switch (ObjDesc->Reference.TargetType)
338                 {
339                 case ACPI_TYPE_BUFFER_FIELD:
340 
341                     AcpiOsPrintf ("%p", ObjDesc->Reference.Object);
342                     AcpiDbDecodeInternalObject (ObjDesc->Reference.Object);
343                     break;
344 
345                 case ACPI_TYPE_PACKAGE:
346 
347                     AcpiOsPrintf ("%p", ObjDesc->Reference.Where);
348                     if (!ObjDesc->Reference.Where)
349                     {
350                         AcpiOsPrintf (" Uninitialized WHERE pointer");
351                     }
352                     else
353                     {
354                         AcpiDbDecodeInternalObject (
355                             *(ObjDesc->Reference.Where));
356                     }
357                     break;
358 
359                 default:
360 
361                     AcpiOsPrintf ("Unknown index target type");
362                     break;
363                 }
364                 break;
365 
366             case ACPI_REFCLASS_REFOF:
367 
368                 if (!ObjDesc->Reference.Object)
369                 {
370                     AcpiOsPrintf (
371                         "Uninitialized reference subobject pointer");
372                     break;
373                 }
374 
375                 /* Reference can be to a Node or an Operand object */
376 
377                 switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc->Reference.Object))
378                 {
379                 case ACPI_DESC_TYPE_NAMED:
380 
381                     AcpiDbDecodeNode (ObjDesc->Reference.Object);
382                     break;
383 
384                 case ACPI_DESC_TYPE_OPERAND:
385 
386                     AcpiDbDecodeInternalObject (ObjDesc->Reference.Object);
387                     break;
388 
389                 default:
390                     break;
391                 }
392                 break;
393 
394             case ACPI_REFCLASS_NAME:
395 
396                 AcpiDbDecodeNode (ObjDesc->Reference.Node);
397                 break;
398 
399             case ACPI_REFCLASS_DEBUG:
400             case ACPI_REFCLASS_TABLE:
401 
402                 AcpiOsPrintf ("\n");
403                 break;
404 
405             default:    /* Unknown reference class */
406 
407                 AcpiOsPrintf ("%2.2X\n", ObjDesc->Reference.Class);
408                 break;
409             }
410             break;
411 
412         default:
413 
414             AcpiOsPrintf ("<Obj>            ");
415             AcpiDbDecodeInternalObject (ObjDesc);
416             break;
417         }
418         break;
419 
420     default:
421 
422         AcpiOsPrintf ("<Not a valid ACPI Object Descriptor> [%s]",
423             AcpiUtGetDescriptorName (ObjDesc));
424         break;
425     }
426 
427     AcpiOsPrintf ("\n");
428 }
429 
430 
431 /*******************************************************************************
432  *
433  * FUNCTION:    AcpiDbDecodeLocals
434  *
435  * PARAMETERS:  WalkState       - State for current method
436  *
437  * RETURN:      None
438  *
439  * DESCRIPTION: Display all locals for the currently running control method
440  *
441  ******************************************************************************/
442 
443 void
444 AcpiDbDecodeLocals (
445     ACPI_WALK_STATE         *WalkState)
446 {
447     UINT32                  i;
448     ACPI_OPERAND_OBJECT     *ObjDesc;
449     ACPI_NAMESPACE_NODE     *Node;
450     BOOLEAN                 DisplayLocals = FALSE;
451 
452 
453     ObjDesc = WalkState->MethodDesc;
454     Node    = WalkState->MethodNode;
455 
456     if (!Node)
457     {
458         AcpiOsPrintf (
459             "No method node (Executing subtree for buffer or opregion)\n");
460         return;
461     }
462 
463     if (Node->Type != ACPI_TYPE_METHOD)
464     {
465         AcpiOsPrintf ("Executing subtree for Buffer/Package/Region\n");
466         return;
467     }
468 
469     /* Are any locals actually set? */
470 
471     for (i = 0; i < ACPI_METHOD_NUM_LOCALS; i++)
472     {
473         ObjDesc = WalkState->LocalVariables[i].Object;
474         if (ObjDesc)
475         {
476             DisplayLocals = TRUE;
477             break;
478         }
479     }
480 
481     /* If any are set, only display the ones that are set */
482 
483     if (DisplayLocals)
484     {
485         AcpiOsPrintf ("\nInitialized Local Variables for method [%4.4s]:\n",
486             AcpiUtGetNodeName (Node));
487 
488         for (i = 0; i < ACPI_METHOD_NUM_LOCALS; i++)
489         {
490             ObjDesc = WalkState->LocalVariables[i].Object;
491             if (ObjDesc)
492             {
493                 AcpiOsPrintf ("    Local%X: ", i);
494                 AcpiDbDisplayInternalObject (ObjDesc, WalkState);
495             }
496         }
497     }
498     else
499     {
500         AcpiOsPrintf ("No Local Variables are initialized for method [%4.4s]\n",
501             AcpiUtGetNodeName (Node));
502     }
503 }
504 
505 
506 /*******************************************************************************
507  *
508  * FUNCTION:    AcpiDbDecodeArguments
509  *
510  * PARAMETERS:  WalkState       - State for current method
511  *
512  * RETURN:      None
513  *
514  * DESCRIPTION: Display all arguments for the currently running control method
515  *
516  ******************************************************************************/
517 
518 void
519 AcpiDbDecodeArguments (
520     ACPI_WALK_STATE         *WalkState)
521 {
522     UINT32                  i;
523     ACPI_OPERAND_OBJECT     *ObjDesc;
524     ACPI_NAMESPACE_NODE     *Node;
525     BOOLEAN                 DisplayArgs = FALSE;
526 
527 
528     Node = WalkState->MethodNode;
529     ObjDesc = WalkState->MethodDesc;
530 
531     if (!Node)
532     {
533         AcpiOsPrintf (
534             "No method node (Executing subtree for buffer or opregion)\n");
535         return;
536     }
537 
538     if (Node->Type != ACPI_TYPE_METHOD)
539     {
540         AcpiOsPrintf ("Executing subtree for Buffer/Package/Region\n");
541         return;
542     }
543 
544     /* Are any arguments actually set? */
545 
546     for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++)
547     {
548         ObjDesc = WalkState->Arguments[i].Object;
549         if (ObjDesc)
550         {
551             DisplayArgs = TRUE;
552             break;
553         }
554     }
555 
556     /* If any are set, only display the ones that are set */
557 
558     if (DisplayArgs)
559     {
560         AcpiOsPrintf (
561             "Initialized Arguments for Method [%4.4s]:  "
562             "(%X arguments defined for method invocation)\n",
563             AcpiUtGetNodeName (Node), ObjDesc->Method.ParamCount);
564 
565         for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++)
566         {
567             ObjDesc = WalkState->Arguments[i].Object;
568             if (ObjDesc)
569             {
570                 AcpiOsPrintf ("    Arg%u:   ", i);
571                 AcpiDbDisplayInternalObject (ObjDesc, WalkState);
572             }
573         }
574     }
575     else
576     {
577         AcpiOsPrintf ("No Arguments are initialized for method [%4.4s]\n",
578             AcpiUtGetNodeName (Node));
579     }
580 }
581 
582 #endif
583