aslxrefout.c revision 306536
1/******************************************************************************
2 *
3 * Module Name: aslxrefout.c - support for optional cross-reference file
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2016, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions, and the following disclaimer,
16 *    without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 *    substantially similar to the "NO WARRANTY" disclaimer below
19 *    ("Disclaimer") and any redistribution must be conditioned upon
20 *    including a substantially similar Disclaimer requirement for further
21 *    binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 *    of any contributors may be used to endorse or promote products derived
24 *    from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include <contrib/dev/acpica/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
56static ACPI_STATUS
57OtXrefWalkPart2 (
58    ACPI_PARSE_OBJECT       *Op,
59    UINT32                  Level,
60    void                    *Context);
61
62static ACPI_STATUS
63OtXrefWalkPart3 (
64    ACPI_PARSE_OBJECT       *Op,
65    UINT32                  Level,
66    void                    *Context);
67
68static ACPI_STATUS
69OtXrefAnalysisWalkPart1 (
70    ACPI_PARSE_OBJECT       *Op,
71    UINT32                  Level,
72    void                    *Context);
73
74
75static ACPI_STATUS
76OtXrefAnalysisWalkPart2 (
77    ACPI_PARSE_OBJECT       *Op,
78    UINT32                  Level,
79    void                    *Context);
80
81static ACPI_STATUS
82OtXrefAnalysisWalkPart3 (
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
100void
101OtPrintHeaders (
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
134void
135OtCreateXrefFile (
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
226void
227OtXrefWalkPart1 (
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
405static ACPI_STATUS
406OtXrefAnalysisWalkPart1 (
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
476static ACPI_STATUS
477OtXrefWalkPart2 (
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
549static ACPI_STATUS
550OtXrefAnalysisWalkPart2 (
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
624static ACPI_STATUS
625OtXrefWalkPart3 (
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
714static ACPI_STATUS
715OtXrefAnalysisWalkPart3 (
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