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