1 /******************************************************************************
3 * Module Name: aslxrefout.c - support for optional cross-reference file
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2016, Intel Corp.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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.
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.
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>
50 #define _COMPONENT ACPI_COMPILER
51 ACPI_MODULE_NAME ("aslxrefout")
54 /* Local prototypes */
58 ACPI_PARSE_OBJECT *Op,
64 ACPI_PARSE_OBJECT *Op,
69 OtXrefAnalysisWalkPart1 (
70 ACPI_PARSE_OBJECT *Op,
76 OtXrefAnalysisWalkPart2 (
77 ACPI_PARSE_OBJECT *Op,
82 OtXrefAnalysisWalkPart3 (
83 ACPI_PARSE_OBJECT *Op,
88 /*******************************************************************************
90 * FUNCTION: OtPrintHeaders
92 * PARAMETERS: Message - Main header message
96 * DESCRIPTION: Emits the main header message along with field descriptions
98 ******************************************************************************/
107 Length = strlen (Message);
109 FlPrintFile (ASL_FILE_XREF_OUTPUT, "\n\n%s\n", Message);
112 FlPrintFile (ASL_FILE_XREF_OUTPUT, "-");
116 FlPrintFile (ASL_FILE_XREF_OUTPUT, "\n\nLineno %-40s Description\n",
121 /*******************************************************************************
123 * FUNCTION: OtCreateXrefFile
129 * DESCRIPTION Main entry point for parts 2 and 3 of the cross-reference
132 ******************************************************************************/
138 ASL_XREF_INFO XrefInfo;
141 /* Build cross-reference output file if requested */
143 if (!Gbl_CrossReferenceOutput)
148 memset (&XrefInfo, 0, sizeof (ASL_XREF_INFO));
150 /* Cross-reference output file, part 2 (Method invocations) */
152 OtPrintHeaders ("Part 2: Method Reference Map "
153 "(Invocations of each user-defined control method)");
155 TrWalkParseTree (Gbl_ParseTreeRoot, ASL_WALK_VISIT_DOWNWARD,
156 OtXrefWalkPart2, NULL, &XrefInfo);
158 /* Cross-reference output file, part 3 (All other object refs) */
160 OtPrintHeaders ("Part 3: Full Object Reference Map "
161 "(Methods that reference each object in namespace");
163 TrWalkParseTree (Gbl_ParseTreeRoot, ASL_WALK_VISIT_DOWNWARD,
164 OtXrefWalkPart3, NULL, &XrefInfo);
166 /* Cross-reference summary */
168 FlPrintFile (ASL_FILE_XREF_OUTPUT, "\n\nObject Summary\n");
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);
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);
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);
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.
197 * Part 2 and 3 are below part 1.
200 /*******************************************************************************
202 * FUNCTION: OtXrefWalkPart1
204 * PARAMETERS: Op - Current parse Op
205 * Level - Current tree nesting level
206 * MethodInfo - Info block for the current method
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.
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.
221 * Called during a normal namespace walk, once per namespace
222 * object. (MtMethodAnalysisWalkBegin)
224 ******************************************************************************/
228 ACPI_PARSE_OBJECT *Op,
230 ASL_METHOD_INFO *MethodInfo)
232 ACPI_NAMESPACE_NODE *Node;
233 ACPI_PARSE_OBJECT *NextOp;
234 ACPI_PARSE_OBJECT *FieldOp;
240 switch (Op->Asl.ParseOpcode)
242 case PARSEOP_NAMESEG:
243 case PARSEOP_NAMESTRING:
244 case PARSEOP_METHODCALL:
247 (MethodInfo->Op->Asl.Child == Op) ||
253 MethodInfo->CurrentOp = Op;
256 /* Find all objects referenced by this method */
258 Status = TrWalkParseTree (MethodInfo->Op, ASL_WALK_VISIT_DOWNWARD,
259 OtXrefAnalysisWalkPart1, NULL, MethodInfo);
261 if (Status == AE_CTRL_TERMINATE)
263 ParentPath = AcpiNsGetNormalizedPathname (Node, TRUE);
265 FlPrintFile (ASL_FILE_XREF_OUTPUT, " %-40s %s",
266 ParentPath, AcpiUtGetTypeName (Node->Type));
267 ACPI_FREE (ParentPath);
271 /* Handle externals */
274 case ACPI_TYPE_FIELD_UNIT:
276 FlPrintFile (ASL_FILE_XREF_OUTPUT, " <External Object>");
279 case ACPI_TYPE_INTEGER:
281 FlPrintFile (ASL_FILE_XREF_OUTPUT, " %8.8X%8.8X",
282 ACPI_FORMAT_UINT64 (Op->Asl.Value.Integer));
285 case ACPI_TYPE_METHOD:
287 FlPrintFile (ASL_FILE_XREF_OUTPUT, " Invocation (%u args)",
291 case ACPI_TYPE_BUFFER_FIELD:
293 NextOp = Node->Op; /* Create Buffer Field Op */
294 switch (NextOp->Asl.ParseOpcode)
296 case PARSEOP_CREATEBITFIELD:
300 case PARSEOP_CREATEBYTEFIELD:
304 case PARSEOP_CREATEWORDFIELD:
308 case PARSEOP_CREATEDWORDFIELD:
312 case PARSEOP_CREATEQWORDFIELD:
321 NextOp = NextOp->Asl.Child; /* Buffer name */
323 if (!NextOp->Asl.ExternalName)
325 FlPrintFile (ASL_FILE_XREF_OUTPUT, " in Arg/Local");
329 ParentPath = AcpiNsGetNormalizedPathname (
330 NextOp->Asl.Node, TRUE);
332 FlPrintFile (ASL_FILE_XREF_OUTPUT, " (%.2u bit) in Buffer %s",
334 ACPI_FREE (ParentPath);
338 case ACPI_TYPE_LOCAL_REGION_FIELD:
341 FieldOp = NextOp->Asl.Parent;
342 NextOp = FieldOp->Asl.Child;
344 ParentPath = AcpiNsGetNormalizedPathname (
345 NextOp->Asl.Node, TRUE);
347 FlPrintFile (ASL_FILE_XREF_OUTPUT, " (%.2u bit) in Region %s",
348 (UINT32) Node->Op->Asl.Child->Asl.Value.Integer,
350 ACPI_FREE (ParentPath);
352 if (FieldOp->Asl.ParseOpcode == PARSEOP_FIELD)
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;
359 /* Get region space/addr/len? */
361 FlPrintFile (ASL_FILE_XREF_OUTPUT, " (%s)",
362 AcpiUtGetRegionName ((UINT8)
363 NextOp->Asl.Value.Integer));
371 FlPrintFile (ASL_FILE_XREF_OUTPUT, "\n");
377 ParentPath = AcpiNsGetNormalizedPathname (Op->Asl.Node, TRUE);
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);
384 ACPI_FREE (ParentPath);
393 /*******************************************************************************
395 * FUNCTION: OtXrefAnalysisWalkPart1
397 * PARAMETERS: ASL_WALK_CALLBACK
401 * DESCRIPTION: Secondary walk for cross-reference part 1.
403 ******************************************************************************/
406 OtXrefAnalysisWalkPart1 (
407 ACPI_PARSE_OBJECT *Op,
411 ASL_METHOD_INFO *MethodInfo = (ASL_METHOD_INFO *) Context;
412 ACPI_PARSE_OBJECT *Next;
415 /* Only interested in name string Ops -- ignore all others */
417 if ((Op->Asl.ParseOpcode != PARSEOP_NAMESEG) &&
418 (Op->Asl.ParseOpcode != PARSEOP_NAMESTRING) &&
419 (Op->Asl.ParseOpcode != PARSEOP_METHODCALL))
424 /* No node means a locally declared object -- ignore */
431 /* When we encounter the source Op, we are done */
433 Next = MethodInfo->CurrentOp;
436 return (AE_CTRL_TERMINATE);
439 /* If we have a name match, this Op is a duplicate */
441 if ((Next->Asl.ParseOpcode == PARSEOP_NAMESEG) ||
442 (Next->Asl.ParseOpcode == PARSEOP_NAMESTRING) ||
443 (Next->Asl.ParseOpcode == PARSEOP_METHODCALL))
445 if (!strcmp (Op->Asl.ExternalName, Next->Asl.ExternalName))
447 return (AE_ALREADY_EXISTS);
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.
461 /*******************************************************************************
463 * FUNCTION: OtXrefWalkPart2
465 * PARAMETERS: ASL_WALK_CALLBACK
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).
474 ******************************************************************************/
478 ACPI_PARSE_OBJECT *Op,
482 ASL_XREF_INFO *XrefInfo = (ASL_XREF_INFO *) Context;
483 ACPI_NAMESPACE_NODE *Node;
487 /* Looking for Method Declaration Ops only */
490 (Op->Asl.ParseOpcode != PARSEOP_METHOD))
495 /* Ignore predefined names */
497 if (Op->Asl.Node->Name.Ascii[0] == '_')
499 XrefInfo->TotalPredefinedMethods++;
504 ParentPath = AcpiNsGetNormalizedPathname (Node, TRUE);
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);
511 XrefInfo->TotalUserMethods++;
512 XrefInfo->ThisMethodInvocations = 0;
513 XrefInfo->MethodOp = Op;
515 (void) TrWalkParseTree (Gbl_ParseTreeRoot, ASL_WALK_VISIT_DOWNWARD,
516 OtXrefAnalysisWalkPart2, NULL, XrefInfo);
518 if (!XrefInfo->ThisMethodInvocations)
520 FlPrintFile (ASL_FILE_XREF_OUTPUT,
521 " Zero invocations of this method in this module\n");
522 XrefInfo->TotalUnreferenceUserMethods++;
526 FlPrintFile (ASL_FILE_XREF_OUTPUT,
527 " %u invocations of method %s in this module\n",
528 XrefInfo->ThisMethodInvocations, ParentPath);
531 ACPI_FREE (ParentPath);
536 /*******************************************************************************
538 * FUNCTION: OtXrefAnalysisWalkPart2
540 * PARAMETERS: ASL_WALK_CALLBACK
544 * DESCRIPTION: For every Op that is a method invocation, emit a reference
545 * line if the Op is invoking the target method.
547 ******************************************************************************/
550 OtXrefAnalysisWalkPart2 (
551 ACPI_PARSE_OBJECT *Op,
555 ASL_XREF_INFO *XrefInfo = (ASL_XREF_INFO *) Context;
556 ACPI_PARSE_OBJECT *CallerOp;
557 char *CallerFullPathname;
560 /* Looking for MethodCall Ops only */
563 (Op->Asl.ParseOpcode != PARSEOP_METHODCALL))
568 /* If not a match to the target method, we are done */
570 if (Op->Asl.Node != XrefInfo->MethodOp->Asl.Node)
572 return (AE_CTRL_DEPTH);
575 /* Find parent method to get method caller namepath */
577 CallerOp = Op->Asl.Parent;
579 (CallerOp->Asl.ParseOpcode != PARSEOP_METHOD))
581 CallerOp = CallerOp->Asl.Parent;
584 /* There is no parent method for External() statements */
591 CallerFullPathname = AcpiNsGetNormalizedPathname (
592 CallerOp->Asl.Node, TRUE);
594 FlPrintFile (ASL_FILE_XREF_OUTPUT,
595 "[%5u] %-40s Invocation path: %s\n",
596 Op->Asl.LogicalLineNumber, CallerFullPathname,
597 Op->Asl.ExternalName);
599 ACPI_FREE (CallerFullPathname);
600 XrefInfo->ThisMethodInvocations++;
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.
611 /*******************************************************************************
613 * FUNCTION: OtXrefWalkPart3
615 * PARAMETERS: ASL_WALK_CALLBACK
619 * DESCRIPTION: Cross-reference part 3. references to objects other than
622 ******************************************************************************/
626 ACPI_PARSE_OBJECT *Op,
630 ASL_XREF_INFO *XrefInfo = (ASL_XREF_INFO *) Context;
631 ACPI_NAMESPACE_NODE *Node;
633 const ACPI_OPCODE_INFO *OpInfo;
636 /* Ignore method declarations */
639 (Op->Asl.ParseOpcode == PARSEOP_METHOD))
644 OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
645 if (!(OpInfo->Class & AML_CLASS_NAMED_OBJECT))
650 /* Only care about named object creation opcodes */
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))
662 /* Ignore predefined names */
664 if (Op->Asl.Node->Name.Ascii[0] == '_')
670 ParentPath = AcpiNsGetNormalizedPathname (Node, TRUE);
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);
678 XrefInfo->MethodOp = Op;
679 XrefInfo->ThisObjectReferences = 0;
680 XrefInfo->TotalObjects = 0;
682 (void) TrWalkParseTree (Gbl_ParseTreeRoot, ASL_WALK_VISIT_DOWNWARD,
683 OtXrefAnalysisWalkPart3, NULL, XrefInfo);
685 if (!XrefInfo->ThisObjectReferences)
687 FlPrintFile (ASL_FILE_XREF_OUTPUT,
688 " Zero references to this object in this module\n");
689 XrefInfo->TotalUnreferencedObjects++;
693 FlPrintFile (ASL_FILE_XREF_OUTPUT,
694 " %u references to this object in this module\n",
695 XrefInfo->ThisObjectReferences, ParentPath);
702 /*******************************************************************************
704 * FUNCTION: OtXrefAnalysisWalkPart3
706 * PARAMETERS: ASL_WALK_CALLBACK
710 * DESCRIPTION: Secondary walk for cross-reference part 3.
712 ******************************************************************************/
715 OtXrefAnalysisWalkPart3 (
716 ACPI_PARSE_OBJECT *Op,
720 ASL_XREF_INFO *XrefInfo = (ASL_XREF_INFO *) Context;
721 char *CallerFullPathname = NULL;
722 ACPI_PARSE_OBJECT *CallerOp;
723 const char *Operator;
731 XrefInfo->TotalObjects++;
733 /* Ignore Op that actually defined the object */
735 if (Op == XrefInfo->MethodOp)
740 /* Only interested in Ops that reference the target node */
742 if (Op->Asl.Node != XrefInfo->MethodOp->Asl.Node)
747 /* Find parent "open scope" object to get method caller namepath */
749 CallerOp = Op->Asl.Parent;
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))
758 CallerOp = CallerOp->Asl.Parent;
761 if (CallerOp == XrefInfo->CurrentMethodOp)
766 /* Null CallerOp means the caller is at the namespace root */
770 CallerFullPathname = AcpiNsGetNormalizedPathname (
771 CallerOp->Asl.Node, TRUE);
774 /* There are some special cases for the oddball operators */
776 if (Op->Asl.ParseOpcode == PARSEOP_SCOPE)
780 else if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_ALIAS)
786 Operator = "ModLevel";
790 Operator = AcpiUtGetTypeName (CallerOp->Asl.Node->Type);
793 FlPrintFile (ASL_FILE_XREF_OUTPUT,
794 "[%5u] %-40s %-8s via path: %s, Operator: %s\n",
795 Op->Asl.LogicalLineNumber,
796 CallerFullPathname ? CallerFullPathname : "<root>",
798 Op->Asl.ExternalName,
799 Op->Asl.Parent->Asl.ParseOpName);
803 CallerOp = ACPI_TO_POINTER (0xFFFFFFFF);
806 if (CallerFullPathname)
808 ACPI_FREE (CallerFullPathname);
811 XrefInfo->CurrentMethodOp = CallerOp;
812 XrefInfo->ThisObjectReferences++;