xref: /freebsd/sys/contrib/dev/acpica/compiler/aslxrefout.c (revision 076ad2f836d5f49dc1375f1677335a48fe0d4b82)
1 /******************************************************************************
2  *
3  * Module Name: aslxrefout.c - support for optional cross-reference file
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2017, 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/compiler/aslcompiler.h>
45 #include "aslcompiler.y.h"
46 #include <contrib/dev/acpica/include/acnamesp.h>
47 #include <contrib/dev/acpica/include/acparser.h>
48 #include <contrib/dev/acpica/include/amlcode.h>
49 
50 #define _COMPONENT          ACPI_COMPILER
51         ACPI_MODULE_NAME    ("aslxrefout")
52 
53 
54 /* Local prototypes */
55 
56 static ACPI_STATUS
57 OtXrefWalkPart2 (
58     ACPI_PARSE_OBJECT       *Op,
59     UINT32                  Level,
60     void                    *Context);
61 
62 static ACPI_STATUS
63 OtXrefWalkPart3 (
64     ACPI_PARSE_OBJECT       *Op,
65     UINT32                  Level,
66     void                    *Context);
67 
68 static ACPI_STATUS
69 OtXrefAnalysisWalkPart1 (
70     ACPI_PARSE_OBJECT       *Op,
71     UINT32                  Level,
72     void                    *Context);
73 
74 
75 static ACPI_STATUS
76 OtXrefAnalysisWalkPart2 (
77     ACPI_PARSE_OBJECT       *Op,
78     UINT32                  Level,
79     void                    *Context);
80 
81 static ACPI_STATUS
82 OtXrefAnalysisWalkPart3 (
83     ACPI_PARSE_OBJECT       *Op,
84     UINT32                  Level,
85     void                    *Context);
86 
87 
88 /*******************************************************************************
89  *
90  * FUNCTION:    OtPrintHeaders
91  *
92  * PARAMETERS:  Message             - Main header message
93  *
94  * RETURN:      None
95  *
96  * DESCRIPTION: Emits the main header message along with field descriptions
97  *
98  ******************************************************************************/
99 
100 void
101 OtPrintHeaders (
102     char                    *Message)
103 {
104     UINT32                  Length;
105 
106 
107     Length = strlen (Message);
108 
109     FlPrintFile (ASL_FILE_XREF_OUTPUT, "\n\n%s\n", Message);
110     while (Length)
111     {
112         FlPrintFile (ASL_FILE_XREF_OUTPUT, "-");
113         Length--;
114     }
115 
116     FlPrintFile (ASL_FILE_XREF_OUTPUT, "\n\nLineno   %-40s Description\n",
117         "Full Pathname");
118 }
119 
120 
121 /*******************************************************************************
122  *
123  * FUNCTION:    OtCreateXrefFile
124  *
125  * PARAMETERS:  None
126  *
127  * RETURN:      None
128  *
129  * DESCRIPTION  Main entry point for parts 2 and 3 of the cross-reference
130  *              file.
131  *
132  ******************************************************************************/
133 
134 void
135 OtCreateXrefFile (
136     void)
137 {
138     ASL_XREF_INFO           XrefInfo;
139 
140 
141     /* Build cross-reference output file if requested */
142 
143     if (!Gbl_CrossReferenceOutput)
144     {
145         return;
146     }
147 
148     memset (&XrefInfo, 0, sizeof (ASL_XREF_INFO));
149 
150     /* Cross-reference output file, part 2 (Method invocations) */
151 
152     OtPrintHeaders ("Part 2: Method Reference Map "
153         "(Invocations of each user-defined control method)");
154 
155     TrWalkParseTree (Gbl_ParseTreeRoot, ASL_WALK_VISIT_DOWNWARD,
156         OtXrefWalkPart2, NULL, &XrefInfo);
157 
158     /* Cross-reference output file, part 3 (All other object refs) */
159 
160     OtPrintHeaders ("Part 3: Full Object Reference Map "
161         "(Methods that reference each object in namespace");
162 
163     TrWalkParseTree (Gbl_ParseTreeRoot, ASL_WALK_VISIT_DOWNWARD,
164         OtXrefWalkPart3, NULL, &XrefInfo);
165 
166     /* Cross-reference summary */
167 
168     FlPrintFile (ASL_FILE_XREF_OUTPUT, "\n\nObject Summary\n");
169 
170     FlPrintFile (ASL_FILE_XREF_OUTPUT,
171         "\nTotal methods:                   %u\n",
172         XrefInfo.TotalPredefinedMethods + XrefInfo.TotalUserMethods);
173     FlPrintFile (ASL_FILE_XREF_OUTPUT,
174         "Total predefined methods:        %u\n",
175         XrefInfo.TotalPredefinedMethods);
176 
177     FlPrintFile (ASL_FILE_XREF_OUTPUT,
178         "\nTotal user methods:              %u\n",
179         XrefInfo.TotalUserMethods);
180     FlPrintFile (ASL_FILE_XREF_OUTPUT,
181         "Total unreferenced user methods  %u\n",
182         XrefInfo.TotalUnreferenceUserMethods);
183 
184     FlPrintFile (ASL_FILE_XREF_OUTPUT,
185         "\nTotal defined objects:           %u\n",
186         XrefInfo.TotalObjects);
187     FlPrintFile (ASL_FILE_XREF_OUTPUT,
188         "Total unreferenced objects:      %u\n",
189         XrefInfo.TotalUnreferencedObjects);
190 }
191 
192 
193 /*
194  * Part 1 of the cross reference file. This part emits the namespace objects
195  * that are referenced by each control method in the namespace.
196  *
197  * Part 2 and 3 are below part 1.
198  */
199 
200 /*******************************************************************************
201  *
202  * FUNCTION:    OtXrefWalkPart1
203  *
204  * PARAMETERS:  Op                      - Current parse Op
205  *              Level                   - Current tree nesting level
206  *              MethodInfo              - Info block for the current method
207  *
208  *
209  * RETURN:      None
210  *
211  * DESCRIPTION: Entry point for the creation of the method call reference map.
212  *              For each control method in the namespace, all other methods
213  *              that invoke the method are listed. Predefined names/methods
214  *              that start with an underscore are ignored, because these are
215  *              essentially external/public interfaces.
216 
217  * DESCRIPTION: Entry point for the creation of the object reference map.
218  *              For each control method in the namespace, all objects that
219  *              are referenced by the method are listed.
220  *
221  *              Called during a normal namespace walk, once per namespace
222  *              object. (MtMethodAnalysisWalkBegin)
223  *
224  ******************************************************************************/
225 
226 void
227 OtXrefWalkPart1 (
228     ACPI_PARSE_OBJECT       *Op,
229     UINT32                  Level,
230     ASL_METHOD_INFO         *MethodInfo)
231 {
232     ACPI_NAMESPACE_NODE     *Node;
233     ACPI_PARSE_OBJECT       *NextOp;
234     ACPI_PARSE_OBJECT       *FieldOp;
235     char                    *ParentPath;
236     UINT32                  Length;
237     ACPI_STATUS             Status;
238 
239 
240     switch (Op->Asl.ParseOpcode)
241     {
242     case PARSEOP_NAMESEG:
243     case PARSEOP_NAMESTRING:
244     case PARSEOP_METHODCALL:
245 
246         if (!MethodInfo ||
247             (MethodInfo->Op->Asl.Child == Op) ||
248             !Op->Asl.Node)
249         {
250             break;
251         }
252 
253         MethodInfo->CurrentOp = Op;
254         Node = Op->Asl.Node;
255 
256         /* Find all objects referenced by this method */
257 
258         Status = TrWalkParseTree (MethodInfo->Op, ASL_WALK_VISIT_DOWNWARD,
259             OtXrefAnalysisWalkPart1, NULL, MethodInfo);
260 
261         if (Status == AE_CTRL_TERMINATE)
262         {
263             ParentPath = AcpiNsGetNormalizedPathname (Node, TRUE);
264 
265             FlPrintFile (ASL_FILE_XREF_OUTPUT, "            %-40s %s",
266                 ParentPath, AcpiUtGetTypeName (Node->Type));
267             ACPI_FREE (ParentPath);
268 
269             switch (Node->Type)
270             {
271                 /* Handle externals */
272 
273             case ACPI_TYPE_ANY:
274             case ACPI_TYPE_FIELD_UNIT:
275 
276                 FlPrintFile (ASL_FILE_XREF_OUTPUT, " <External Object>");
277                 break;
278 
279             case ACPI_TYPE_INTEGER:
280 
281                 FlPrintFile (ASL_FILE_XREF_OUTPUT, " %8.8X%8.8X",
282                     ACPI_FORMAT_UINT64 (Op->Asl.Value.Integer));
283                 break;
284 
285             case ACPI_TYPE_METHOD:
286 
287                 FlPrintFile (ASL_FILE_XREF_OUTPUT, " Invocation (%u args)",
288                     Node->ArgCount);
289                 break;
290 
291             case ACPI_TYPE_BUFFER_FIELD:
292 
293                 NextOp = Node->Op;              /* Create Buffer Field Op */
294                 switch (NextOp->Asl.ParseOpcode)
295                 {
296                 case PARSEOP_CREATEBITFIELD:
297                     Length = 1;
298                     break;
299 
300                 case PARSEOP_CREATEBYTEFIELD:
301                     Length = 8;
302                     break;
303 
304                 case PARSEOP_CREATEWORDFIELD:
305                     Length = 16;
306                     break;
307 
308                 case PARSEOP_CREATEDWORDFIELD:
309                     Length = 32;
310                     break;
311 
312                 case PARSEOP_CREATEQWORDFIELD:
313                     Length = 64;
314                     break;
315 
316                 default:
317                     Length = 0;
318                     break;
319                 }
320 
321                 NextOp = NextOp->Asl.Child;     /* Buffer name */
322 
323                 if (!NextOp->Asl.ExternalName)
324                 {
325                     FlPrintFile (ASL_FILE_XREF_OUTPUT, " in Arg/Local");
326                 }
327                 else
328                 {
329                     ParentPath = AcpiNsGetNormalizedPathname (
330                         NextOp->Asl.Node, TRUE);
331 
332                     FlPrintFile (ASL_FILE_XREF_OUTPUT, " (%.2u bit) in Buffer %s",
333                         Length, ParentPath);
334                     ACPI_FREE (ParentPath);
335                 }
336                 break;
337 
338             case ACPI_TYPE_LOCAL_REGION_FIELD:
339 
340                 NextOp = Node->Op;
341                 FieldOp = NextOp->Asl.Parent;
342                 NextOp = FieldOp->Asl.Child;
343 
344                 ParentPath = AcpiNsGetNormalizedPathname (
345                     NextOp->Asl.Node, TRUE);
346 
347                 FlPrintFile (ASL_FILE_XREF_OUTPUT, " (%.2u bit) in Region %s",
348                     (UINT32) Node->Op->Asl.Child->Asl.Value.Integer,
349                     ParentPath);
350                 ACPI_FREE (ParentPath);
351 
352                 if (FieldOp->Asl.ParseOpcode == PARSEOP_FIELD)
353                 {
354                     Node = NextOp->Asl.Node;        /* Region node */
355                     NextOp = Node->Op;              /* PARSEOP_REGION */
356                     NextOp = NextOp->Asl.Child;     /* Region name */
357                     NextOp = NextOp->Asl.Next;
358 
359                     /* Get region space/addr/len? */
360 
361                     FlPrintFile (ASL_FILE_XREF_OUTPUT, " (%s)",
362                         AcpiUtGetRegionName ((UINT8)
363                         NextOp->Asl.Value.Integer));
364                 }
365                 break;
366 
367             default:
368                 break;
369             }
370 
371             FlPrintFile (ASL_FILE_XREF_OUTPUT, "\n");
372         }
373         break;
374 
375     case PARSEOP_METHOD:
376 
377         ParentPath = AcpiNsGetNormalizedPathname (Op->Asl.Node, TRUE);
378 
379         FlPrintFile (ASL_FILE_XREF_OUTPUT,
380             "\n[%5u]  %-40s %s Declaration (%u args)\n",
381             Op->Asl.LogicalLineNumber, ParentPath,
382             AcpiUtGetTypeName (Op->Asl.Node->Type), Op->Asl.Node->ArgCount);
383 
384         ACPI_FREE (ParentPath);
385         break;
386 
387     default:
388         break;
389     }
390 }
391 
392 
393 /*******************************************************************************
394  *
395  * FUNCTION:    OtXrefAnalysisWalkPart1
396  *
397  * PARAMETERS:  ASL_WALK_CALLBACK
398  *
399  * RETURN:      Status
400  *
401  * DESCRIPTION: Secondary walk for cross-reference part 1.
402  *
403  ******************************************************************************/
404 
405 static ACPI_STATUS
406 OtXrefAnalysisWalkPart1 (
407     ACPI_PARSE_OBJECT       *Op,
408     UINT32                  Level,
409     void                    *Context)
410 {
411     ASL_METHOD_INFO         *MethodInfo = (ASL_METHOD_INFO *) Context;
412     ACPI_PARSE_OBJECT       *Next;
413 
414 
415     /* Only interested in name string Ops -- ignore all others */
416 
417     if ((Op->Asl.ParseOpcode != PARSEOP_NAMESEG) &&
418         (Op->Asl.ParseOpcode != PARSEOP_NAMESTRING) &&
419         (Op->Asl.ParseOpcode != PARSEOP_METHODCALL))
420     {
421         return (AE_OK);
422     }
423 
424     /* No node means a locally declared object -- ignore */
425 
426     if (!Op->Asl.Node)
427     {
428         return (AE_OK);
429     }
430 
431     /* When we encounter the source Op, we are done */
432 
433     Next = MethodInfo->CurrentOp;
434     if (Next == Op)
435     {
436         return (AE_CTRL_TERMINATE);
437     }
438 
439     /* If we have a name match, this Op is a duplicate */
440 
441     if ((Next->Asl.ParseOpcode == PARSEOP_NAMESEG)      ||
442         (Next->Asl.ParseOpcode == PARSEOP_NAMESTRING)   ||
443         (Next->Asl.ParseOpcode == PARSEOP_METHODCALL))
444     {
445         if (!strcmp (Op->Asl.ExternalName, Next->Asl.ExternalName))
446         {
447             return (AE_ALREADY_EXISTS);
448         }
449     }
450 
451     return (AE_OK);
452 }
453 
454 
455 /*
456  * Part 2 of the cross reference file. This part emits the names of each
457  * non-predefined method in the namespace (user methods), along with the
458  * names of each control method that references that method.
459  */
460 
461 /*******************************************************************************
462  *
463  * FUNCTION:    OtXrefWalkPart2
464  *
465  * PARAMETERS:  ASL_WALK_CALLBACK
466  *
467  * RETURN:      Status
468  *
469  * DESCRIPTION: For each control method in the namespace, we will re-walk the
470  *              namespace to find each and every invocation of that control
471  *              method. Brute force, but does not matter, even for large
472  *              namespaces. Ignore predefined names (start with underscore).
473  *
474  ******************************************************************************/
475 
476 static ACPI_STATUS
477 OtXrefWalkPart2 (
478     ACPI_PARSE_OBJECT       *Op,
479     UINT32                  Level,
480     void                    *Context)
481 {
482     ASL_XREF_INFO           *XrefInfo = (ASL_XREF_INFO *) Context;
483     ACPI_NAMESPACE_NODE     *Node;
484     char                    *ParentPath;
485 
486 
487     /* Looking for Method Declaration Ops only */
488 
489     if (!Op->Asl.Node ||
490         (Op->Asl.ParseOpcode != PARSEOP_METHOD))
491     {
492         return (AE_OK);
493     }
494 
495     /* Ignore predefined names */
496 
497     if (Op->Asl.Node->Name.Ascii[0] == '_')
498     {
499         XrefInfo->TotalPredefinedMethods++;
500         return (AE_OK);
501     }
502 
503     Node = Op->Asl.Node;
504     ParentPath = AcpiNsGetNormalizedPathname (Node, TRUE);
505 
506     FlPrintFile (ASL_FILE_XREF_OUTPUT,
507         "\n[%5u]  %-40s %s Declaration (%u args)\n",
508         Op->Asl.LogicalLineNumber, ParentPath,
509         AcpiUtGetTypeName (Node->Type), Node->ArgCount);
510 
511     XrefInfo->TotalUserMethods++;
512     XrefInfo->ThisMethodInvocations = 0;
513     XrefInfo->MethodOp = Op;
514 
515     (void) TrWalkParseTree (Gbl_ParseTreeRoot, ASL_WALK_VISIT_DOWNWARD,
516         OtXrefAnalysisWalkPart2, NULL, XrefInfo);
517 
518     if (!XrefInfo->ThisMethodInvocations)
519     {
520         FlPrintFile (ASL_FILE_XREF_OUTPUT,
521             "            Zero invocations of this method in this module\n");
522         XrefInfo->TotalUnreferenceUserMethods++;
523     }
524     else
525     {
526         FlPrintFile (ASL_FILE_XREF_OUTPUT,
527             "            %u invocations of method %s in this module\n",
528             XrefInfo->ThisMethodInvocations, ParentPath);
529     }
530 
531     ACPI_FREE (ParentPath);
532     return (AE_OK);
533 }
534 
535 
536 /*******************************************************************************
537  *
538  * FUNCTION:    OtXrefAnalysisWalkPart2
539  *
540  * PARAMETERS:  ASL_WALK_CALLBACK
541  *
542  * RETURN:      Status
543  *
544  * DESCRIPTION: For every Op that is a method invocation, emit a reference
545  *              line if the Op is invoking the target method.
546  *
547  ******************************************************************************/
548 
549 static ACPI_STATUS
550 OtXrefAnalysisWalkPart2 (
551     ACPI_PARSE_OBJECT       *Op,
552     UINT32                  Level,
553     void                    *Context)
554 {
555     ASL_XREF_INFO           *XrefInfo = (ASL_XREF_INFO *) Context;
556     ACPI_PARSE_OBJECT       *CallerOp;
557     char                    *CallerFullPathname;
558 
559 
560     /* Looking for MethodCall Ops only */
561 
562     if (!Op->Asl.Node ||
563         (Op->Asl.ParseOpcode != PARSEOP_METHODCALL))
564     {
565         return (AE_OK);
566     }
567 
568     /* If not a match to the target method, we are done */
569 
570     if (Op->Asl.Node != XrefInfo->MethodOp->Asl.Node)
571     {
572         return (AE_CTRL_DEPTH);
573     }
574 
575     /* Find parent method to get method caller namepath */
576 
577     CallerOp = Op->Asl.Parent;
578     while (CallerOp &&
579         (CallerOp->Asl.ParseOpcode != PARSEOP_METHOD))
580     {
581         CallerOp = CallerOp->Asl.Parent;
582     }
583 
584     /* There is no parent method for External() statements */
585 
586     if (!CallerOp)
587     {
588         return (AE_OK);
589     }
590 
591     CallerFullPathname = AcpiNsGetNormalizedPathname (
592         CallerOp->Asl.Node, TRUE);
593 
594     FlPrintFile (ASL_FILE_XREF_OUTPUT,
595         "[%5u]     %-40s Invocation path: %s\n",
596         Op->Asl.LogicalLineNumber, CallerFullPathname,
597         Op->Asl.ExternalName);
598 
599     ACPI_FREE (CallerFullPathname);
600     XrefInfo->ThisMethodInvocations++;
601     return (AE_OK);
602 }
603 
604 
605 /*
606  * Part 3 of the cross reference file. This part emits the names of each
607  * non-predefined method in the namespace (user methods), along with the
608  * names of each control method that references that method.
609  */
610 
611 /*******************************************************************************
612  *
613  * FUNCTION:    OtXrefWalkPart3
614  *
615  * PARAMETERS:  ASL_WALK_CALLBACK
616  *
617  * RETURN:      Status
618  *
619  * DESCRIPTION: Cross-reference part 3. references to objects other than
620  *              control methods.
621  *
622  ******************************************************************************/
623 
624 static ACPI_STATUS
625 OtXrefWalkPart3 (
626     ACPI_PARSE_OBJECT       *Op,
627     UINT32                  Level,
628     void                    *Context)
629 {
630     ASL_XREF_INFO           *XrefInfo = (ASL_XREF_INFO *) Context;
631     ACPI_NAMESPACE_NODE     *Node;
632     char                    *ParentPath;
633     const ACPI_OPCODE_INFO  *OpInfo;
634 
635 
636     /* Ignore method declarations */
637 
638     if (!Op->Asl.Node ||
639         (Op->Asl.ParseOpcode == PARSEOP_METHOD))
640     {
641         return (AE_OK);
642     }
643 
644     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
645     if (!(OpInfo->Class & AML_CLASS_NAMED_OBJECT))
646     {
647         return (AE_OK);
648     }
649 
650     /* Only care about named object creation opcodes */
651 
652     if ((Op->Asl.ParseOpcode != PARSEOP_NAME) &&
653         (Op->Asl.ParseOpcode != PARSEOP_DEVICE) &&
654         (Op->Asl.ParseOpcode != PARSEOP_MUTEX) &&
655         (Op->Asl.ParseOpcode != PARSEOP_OPERATIONREGION) &&
656         (Op->Asl.ParseOpcode != PARSEOP_FIELD) &&
657         (Op->Asl.ParseOpcode != PARSEOP_EVENT))
658     {
659         return (AE_OK);
660     }
661 
662     /* Ignore predefined names */
663 
664     if (Op->Asl.Node->Name.Ascii[0] == '_')
665     {
666         return (AE_OK);
667     }
668 
669     Node = Op->Asl.Node;
670     ParentPath = AcpiNsGetNormalizedPathname (Node, TRUE);
671 
672     FlPrintFile (ASL_FILE_XREF_OUTPUT,
673         "\n[%5u]  %-40s %s Declaration\n",
674         Op->Asl.LogicalLineNumber, ParentPath,
675         AcpiUtGetTypeName (Node->Type));
676     ACPI_FREE (ParentPath);
677 
678     XrefInfo->MethodOp = Op;
679     XrefInfo->ThisObjectReferences = 0;
680     XrefInfo->TotalObjects = 0;
681 
682     (void) TrWalkParseTree (Gbl_ParseTreeRoot, ASL_WALK_VISIT_DOWNWARD,
683         OtXrefAnalysisWalkPart3, NULL, XrefInfo);
684 
685     if (!XrefInfo->ThisObjectReferences)
686     {
687         FlPrintFile (ASL_FILE_XREF_OUTPUT,
688             "            Zero references to this object in this module\n");
689         XrefInfo->TotalUnreferencedObjects++;
690     }
691     else
692     {
693         FlPrintFile (ASL_FILE_XREF_OUTPUT,
694             "            %u references to this object in this module\n",
695             XrefInfo->ThisObjectReferences, ParentPath);
696     }
697 
698     return (AE_OK);
699 }
700 
701 
702 /*******************************************************************************
703  *
704  * FUNCTION:    OtXrefAnalysisWalkPart3
705  *
706  * PARAMETERS:  ASL_WALK_CALLBACK
707  *
708  * RETURN:      Status
709  *
710  * DESCRIPTION: Secondary walk for cross-reference part 3.
711  *
712  ******************************************************************************/
713 
714 static ACPI_STATUS
715 OtXrefAnalysisWalkPart3 (
716     ACPI_PARSE_OBJECT       *Op,
717     UINT32                  Level,
718     void                    *Context)
719 {
720     ASL_XREF_INFO           *XrefInfo = (ASL_XREF_INFO *) Context;
721     char                    *CallerFullPathname = NULL;
722     ACPI_PARSE_OBJECT       *CallerOp;
723     const char              *Operator;
724 
725 
726     if (!Op->Asl.Node)
727     {
728         return (AE_OK);
729     }
730 
731     XrefInfo->TotalObjects++;
732 
733     /* Ignore Op that actually defined the object */
734 
735     if (Op == XrefInfo->MethodOp)
736     {
737         return (AE_OK);
738     }
739 
740     /* Only interested in Ops that reference the target node */
741 
742     if (Op->Asl.Node != XrefInfo->MethodOp->Asl.Node)
743     {
744         return (AE_OK);
745     }
746 
747     /* Find parent "open scope" object to get method caller namepath */
748 
749     CallerOp = Op->Asl.Parent;
750     while (CallerOp &&
751         (CallerOp->Asl.ParseOpcode != PARSEOP_NAME) &&
752         (CallerOp->Asl.ParseOpcode != PARSEOP_METHOD) &&
753         (CallerOp->Asl.ParseOpcode != PARSEOP_DEVICE) &&
754         (CallerOp->Asl.ParseOpcode != PARSEOP_POWERRESOURCE) &&
755         (CallerOp->Asl.ParseOpcode != PARSEOP_PROCESSOR) &&
756         (CallerOp->Asl.ParseOpcode != PARSEOP_THERMALZONE))
757     {
758         CallerOp = CallerOp->Asl.Parent;
759     }
760 
761     if (CallerOp == XrefInfo->CurrentMethodOp)
762     {
763         return (AE_OK);
764     }
765 
766     /* Null CallerOp means the caller is at the namespace root */
767 
768     if (CallerOp)
769     {
770         CallerFullPathname = AcpiNsGetNormalizedPathname (
771             CallerOp->Asl.Node, TRUE);
772     }
773 
774     /* There are some special cases for the oddball operators */
775 
776     if (Op->Asl.ParseOpcode == PARSEOP_SCOPE)
777     {
778         Operator = "Scope";
779     }
780     else if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_ALIAS)
781     {
782         Operator = "Alias";
783     }
784     else if (!CallerOp)
785     {
786         Operator = "ModLevel";
787     }
788     else
789     {
790         Operator = AcpiUtGetTypeName (CallerOp->Asl.Node->Type);
791     }
792 
793     FlPrintFile (ASL_FILE_XREF_OUTPUT,
794         "[%5u]     %-40s %-8s via path: %s, Operator: %s\n",
795         Op->Asl.LogicalLineNumber,
796         CallerFullPathname ? CallerFullPathname : "<root>",
797         Operator,
798         Op->Asl.ExternalName,
799         Op->Asl.Parent->Asl.ParseOpName);
800 
801     if (!CallerOp)
802     {
803         CallerOp = ACPI_TO_POINTER (0xFFFFFFFF);
804     }
805 
806     if (CallerFullPathname)
807     {
808         ACPI_FREE (CallerFullPathname);
809     }
810 
811     XrefInfo->CurrentMethodOp = CallerOp;
812     XrefInfo->ThisObjectReferences++;
813     return (AE_OK);
814 }
815