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 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