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