Home | History | Annotate | Line # | Download | only in compiler
aslxrefout.c revision 1.1.1.8
      1 /******************************************************************************
      2  *
      3  * Module Name: aslxrefout.c - support for optional cross-reference file
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2021, 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 "aslcompiler.h"
     45 #include "aslcompiler.y.h"
     46 #include "acnamesp.h"
     47 #include "acparser.h"
     48 #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 (!AslGbl_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 (AslGbl_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 (AslGbl_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 (AslGbl_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 (AslGbl_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 [%s]\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