1 /******************************************************************************
2  *
3  * Module Name: uttrack - Memory allocation tracking routines (debug only)
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2022, 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 /*
45  * These procedures are used for tracking memory leaks in the subsystem, and
46  * they get compiled out when the ACPI_DBG_TRACK_ALLOCATIONS is not set.
47  *
48  * Each memory allocation is tracked via a doubly linked list. Each
49  * element contains the caller's component, module name, function name, and
50  * line number. AcpiUtAllocate and AcpiUtAllocateZeroed call
51  * AcpiUtTrackAllocation to add an element to the list; deletion
52  * occurs in the body of AcpiUtFree.
53  */
54 
55 #include "acpi.h"
56 #include "accommon.h"
57 
58 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
59 
60 #define _COMPONENT          ACPI_UTILITIES
61         ACPI_MODULE_NAME    ("uttrack")
62 
63 
64 /* Local prototypes */
65 
66 static ACPI_DEBUG_MEM_BLOCK *
67 AcpiUtFindAllocation (
68     ACPI_DEBUG_MEM_BLOCK    *Allocation);
69 
70 static ACPI_STATUS
71 AcpiUtTrackAllocation (
72     ACPI_DEBUG_MEM_BLOCK    *Address,
73     ACPI_SIZE               Size,
74     UINT8                   AllocType,
75     UINT32                  Component,
76     const char              *Module,
77     UINT32                  Line);
78 
79 static ACPI_STATUS
80 AcpiUtRemoveAllocation (
81     ACPI_DEBUG_MEM_BLOCK    *Address,
82     UINT32                  Component,
83     const char              *Module,
84     UINT32                  Line);
85 
86 
87 /*******************************************************************************
88  *
89  * FUNCTION:    AcpiUtCreateList
90  *
91  * PARAMETERS:  CacheName       - Ascii name for the cache
92  *              ObjectSize      - Size of each cached object
93  *              ReturnCache     - Where the new cache object is returned
94  *
95  * RETURN:      Status
96  *
97  * DESCRIPTION: Create a local memory list for tracking purposed
98  *
99  ******************************************************************************/
100 
101 ACPI_STATUS
AcpiUtCreateList(const char * ListName,UINT16 ObjectSize,ACPI_MEMORY_LIST ** ReturnCache)102 AcpiUtCreateList (
103     const char              *ListName,
104     UINT16                  ObjectSize,
105     ACPI_MEMORY_LIST        **ReturnCache)
106 {
107     ACPI_MEMORY_LIST        *Cache;
108 
109 
110     Cache = AcpiOsAllocateZeroed (sizeof (ACPI_MEMORY_LIST));
111     if (!Cache)
112     {
113         return (AE_NO_MEMORY);
114     }
115 
116     Cache->ListName = ListName;
117     Cache->ObjectSize = ObjectSize;
118 
119     *ReturnCache = Cache;
120     return (AE_OK);
121 }
122 
123 
124 /*******************************************************************************
125  *
126  * FUNCTION:    AcpiUtAllocateAndTrack
127  *
128  * PARAMETERS:  Size                - Size of the allocation
129  *              Component           - Component type of caller
130  *              Module              - Source file name of caller
131  *              Line                - Line number of caller
132  *
133  * RETURN:      Address of the allocated memory on success, NULL on failure.
134  *
135  * DESCRIPTION: The subsystem's equivalent of malloc.
136  *
137  ******************************************************************************/
138 
139 void *
AcpiUtAllocateAndTrack(ACPI_SIZE Size,UINT32 Component,const char * Module,UINT32 Line)140 AcpiUtAllocateAndTrack (
141     ACPI_SIZE               Size,
142     UINT32                  Component,
143     const char              *Module,
144     UINT32                  Line)
145 {
146     ACPI_DEBUG_MEM_BLOCK    *Allocation;
147     ACPI_STATUS             Status;
148 
149 
150     /* Check for an inadvertent size of zero bytes */
151 
152     if (!Size)
153     {
154         ACPI_WARNING ((Module, Line,
155             "Attempt to allocate zero bytes, allocating 1 byte"));
156         Size = 1;
157     }
158 
159     Allocation = AcpiOsAllocate (Size + sizeof (ACPI_DEBUG_MEM_HEADER));
160     if (!Allocation)
161     {
162         /* Report allocation error */
163 
164         ACPI_WARNING ((Module, Line,
165             "Could not allocate size %u", (UINT32) Size));
166 
167         return (NULL);
168     }
169 
170     Status = AcpiUtTrackAllocation (
171         Allocation, Size, ACPI_MEM_MALLOC, Component, Module, Line);
172     if (ACPI_FAILURE (Status))
173     {
174         AcpiOsFree (Allocation);
175         return (NULL);
176     }
177 
178     AcpiGbl_GlobalList->TotalAllocated++;
179     AcpiGbl_GlobalList->TotalSize += (UINT32) Size;
180     AcpiGbl_GlobalList->CurrentTotalSize += (UINT32) Size;
181 
182     if (AcpiGbl_GlobalList->CurrentTotalSize >
183         AcpiGbl_GlobalList->MaxOccupied)
184     {
185         AcpiGbl_GlobalList->MaxOccupied =
186             AcpiGbl_GlobalList->CurrentTotalSize;
187     }
188 
189     return ((void *) &Allocation->UserSpace);
190 }
191 
192 
193 /*******************************************************************************
194  *
195  * FUNCTION:    AcpiUtAllocateZeroedAndTrack
196  *
197  * PARAMETERS:  Size                - Size of the allocation
198  *              Component           - Component type of caller
199  *              Module              - Source file name of caller
200  *              Line                - Line number of caller
201  *
202  * RETURN:      Address of the allocated memory on success, NULL on failure.
203  *
204  * DESCRIPTION: Subsystem equivalent of calloc.
205  *
206  ******************************************************************************/
207 
208 void *
AcpiUtAllocateZeroedAndTrack(ACPI_SIZE Size,UINT32 Component,const char * Module,UINT32 Line)209 AcpiUtAllocateZeroedAndTrack (
210     ACPI_SIZE               Size,
211     UINT32                  Component,
212     const char              *Module,
213     UINT32                  Line)
214 {
215     ACPI_DEBUG_MEM_BLOCK    *Allocation;
216     ACPI_STATUS             Status;
217 
218 
219     /* Check for an inadvertent size of zero bytes */
220 
221     if (!Size)
222     {
223         ACPI_WARNING ((Module, Line,
224             "Attempt to allocate zero bytes, allocating 1 byte"));
225         Size = 1;
226     }
227 
228     Allocation = AcpiOsAllocateZeroed (
229         Size + sizeof (ACPI_DEBUG_MEM_HEADER));
230     if (!Allocation)
231     {
232         /* Report allocation error */
233 
234         ACPI_ERROR ((Module, Line,
235             "Could not allocate size %u", (UINT32) Size));
236         return (NULL);
237     }
238 
239     Status = AcpiUtTrackAllocation (Allocation, Size,
240         ACPI_MEM_CALLOC, Component, Module, Line);
241     if (ACPI_FAILURE (Status))
242     {
243         AcpiOsFree (Allocation);
244         return (NULL);
245     }
246 
247     AcpiGbl_GlobalList->TotalAllocated++;
248     AcpiGbl_GlobalList->TotalSize += (UINT32) Size;
249     AcpiGbl_GlobalList->CurrentTotalSize += (UINT32) Size;
250 
251     if (AcpiGbl_GlobalList->CurrentTotalSize >
252         AcpiGbl_GlobalList->MaxOccupied)
253     {
254         AcpiGbl_GlobalList->MaxOccupied =
255             AcpiGbl_GlobalList->CurrentTotalSize;
256     }
257 
258     return ((void *) &Allocation->UserSpace);
259 }
260 
261 
262 /*******************************************************************************
263  *
264  * FUNCTION:    AcpiUtFreeAndTrack
265  *
266  * PARAMETERS:  Allocation          - Address of the memory to deallocate
267  *              Component           - Component type of caller
268  *              Module              - Source file name of caller
269  *              Line                - Line number of caller
270  *
271  * RETURN:      None
272  *
273  * DESCRIPTION: Frees the memory at Allocation
274  *
275  ******************************************************************************/
276 
277 void
AcpiUtFreeAndTrack(void * Allocation,UINT32 Component,const char * Module,UINT32 Line)278 AcpiUtFreeAndTrack (
279     void                    *Allocation,
280     UINT32                  Component,
281     const char              *Module,
282     UINT32                  Line)
283 {
284     ACPI_DEBUG_MEM_BLOCK    *DebugBlock;
285     ACPI_STATUS             Status;
286 
287 
288     ACPI_FUNCTION_TRACE_PTR (UtFree, Allocation);
289 
290 
291     if (NULL == Allocation)
292     {
293         ACPI_ERROR ((Module, Line,
294             "Attempt to delete a NULL address"));
295 
296         return_VOID;
297     }
298 
299     DebugBlock = ACPI_CAST_PTR (ACPI_DEBUG_MEM_BLOCK,
300         (((char *) Allocation) - sizeof (ACPI_DEBUG_MEM_HEADER)));
301 
302     AcpiGbl_GlobalList->TotalFreed++;
303     AcpiGbl_GlobalList->CurrentTotalSize -= DebugBlock->Size;
304 
305     Status = AcpiUtRemoveAllocation (DebugBlock, Component, Module, Line);
306     if (ACPI_FAILURE (Status))
307     {
308         ACPI_EXCEPTION ((AE_INFO, Status, "Could not free memory"));
309     }
310 
311     AcpiOsFree (DebugBlock);
312     ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "%p freed (block %p)\n",
313         Allocation, DebugBlock));
314     return_VOID;
315 }
316 
317 
318 /*******************************************************************************
319  *
320  * FUNCTION:    AcpiUtFindAllocation
321  *
322  * PARAMETERS:  Allocation              - Address of allocated memory
323  *
324  * RETURN:      Three cases:
325  *              1) List is empty, NULL is returned.
326  *              2) Element was found. Returns Allocation parameter.
327  *              3) Element was not found. Returns position where it should be
328  *                  inserted into the list.
329  *
330  * DESCRIPTION: Searches for an element in the global allocation tracking list.
331  *              If the element is not found, returns the location within the
332  *              list where the element should be inserted.
333  *
334  *              Note: The list is ordered by larger-to-smaller addresses.
335  *
336  *              This global list is used to detect memory leaks in ACPICA as
337  *              well as other issues such as an attempt to release the same
338  *              internal object more than once. Although expensive as far
339  *              as cpu time, this list is much more helpful for finding these
340  *              types of issues than using memory leak detectors outside of
341  *              the ACPICA code.
342  *
343  ******************************************************************************/
344 
345 static ACPI_DEBUG_MEM_BLOCK *
AcpiUtFindAllocation(ACPI_DEBUG_MEM_BLOCK * Allocation)346 AcpiUtFindAllocation (
347     ACPI_DEBUG_MEM_BLOCK    *Allocation)
348 {
349     ACPI_DEBUG_MEM_BLOCK    *Element;
350 
351 
352     Element = AcpiGbl_GlobalList->ListHead;
353     if (!Element)
354     {
355         return (NULL);
356     }
357 
358     /*
359      * Search for the address.
360      *
361      * Note: List is ordered by larger-to-smaller addresses, on the
362      * assumption that a new allocation usually has a larger address
363      * than previous allocations.
364      */
365     while (Element > Allocation)
366     {
367         /* Check for end-of-list */
368 
369         if (!Element->Next)
370         {
371             return (Element);
372         }
373 
374         Element = Element->Next;
375     }
376 
377     if (Element == Allocation)
378     {
379         return (Element);
380     }
381 
382     return (Element->Previous);
383 }
384 
385 
386 /*******************************************************************************
387  *
388  * FUNCTION:    AcpiUtTrackAllocation
389  *
390  * PARAMETERS:  Allocation          - Address of allocated memory
391  *              Size                - Size of the allocation
392  *              AllocType           - MEM_MALLOC or MEM_CALLOC
393  *              Component           - Component type of caller
394  *              Module              - Source file name of caller
395  *              Line                - Line number of caller
396  *
397  * RETURN:      Status
398  *
399  * DESCRIPTION: Inserts an element into the global allocation tracking list.
400  *
401  ******************************************************************************/
402 
403 static ACPI_STATUS
AcpiUtTrackAllocation(ACPI_DEBUG_MEM_BLOCK * Allocation,ACPI_SIZE Size,UINT8 AllocType,UINT32 Component,const char * Module,UINT32 Line)404 AcpiUtTrackAllocation (
405     ACPI_DEBUG_MEM_BLOCK    *Allocation,
406     ACPI_SIZE               Size,
407     UINT8                   AllocType,
408     UINT32                  Component,
409     const char              *Module,
410     UINT32                  Line)
411 {
412     ACPI_MEMORY_LIST        *MemList;
413     ACPI_DEBUG_MEM_BLOCK    *Element;
414     ACPI_STATUS             Status = AE_OK;
415 
416 
417     ACPI_FUNCTION_TRACE_PTR (UtTrackAllocation, Allocation);
418 
419 
420     if (AcpiGbl_DisableMemTracking)
421     {
422         return_ACPI_STATUS (AE_OK);
423     }
424 
425     MemList = AcpiGbl_GlobalList;
426     Status = AcpiUtAcquireMutex (ACPI_MTX_MEMORY);
427     if (ACPI_FAILURE (Status))
428     {
429         return_ACPI_STATUS (Status);
430     }
431 
432     /*
433      * Search the global list for this address to make sure it is not
434      * already present. This will catch several kinds of problems.
435      */
436     Element = AcpiUtFindAllocation (Allocation);
437     if (Element == Allocation)
438     {
439         ACPI_ERROR ((AE_INFO,
440             "UtTrackAllocation: Allocation (%p) already present in global list!",
441             Allocation));
442         goto UnlockAndExit;
443     }
444 
445     /* Fill in the instance data */
446 
447     Allocation->Size = (UINT32) Size;
448     Allocation->AllocType = AllocType;
449     Allocation->Component = Component;
450     Allocation->Line = Line;
451 
452     AcpiUtSafeStrncpy (Allocation->Module, (char *) Module, ACPI_MAX_MODULE_NAME);
453 
454     if (!Element)
455     {
456         /* Insert at list head */
457 
458         if (MemList->ListHead)
459         {
460             ((ACPI_DEBUG_MEM_BLOCK *)(MemList->ListHead))->Previous =
461                 Allocation;
462         }
463 
464         Allocation->Next = MemList->ListHead;
465         Allocation->Previous = NULL;
466 
467         MemList->ListHead = Allocation;
468     }
469     else
470     {
471         /* Insert after element */
472 
473         Allocation->Next = Element->Next;
474         Allocation->Previous = Element;
475 
476         if (Element->Next)
477         {
478             (Element->Next)->Previous = Allocation;
479         }
480 
481         Element->Next = Allocation;
482     }
483 
484 
485 UnlockAndExit:
486     Status = AcpiUtReleaseMutex (ACPI_MTX_MEMORY);
487     return_ACPI_STATUS (Status);
488 }
489 
490 
491 /*******************************************************************************
492  *
493  * FUNCTION:    AcpiUtRemoveAllocation
494  *
495  * PARAMETERS:  Allocation          - Address of allocated memory
496  *              Component           - Component type of caller
497  *              Module              - Source file name of caller
498  *              Line                - Line number of caller
499  *
500  * RETURN:      Status
501  *
502  * DESCRIPTION: Deletes an element from the global allocation tracking list.
503  *
504  ******************************************************************************/
505 
506 static ACPI_STATUS
AcpiUtRemoveAllocation(ACPI_DEBUG_MEM_BLOCK * Allocation,UINT32 Component,const char * Module,UINT32 Line)507 AcpiUtRemoveAllocation (
508     ACPI_DEBUG_MEM_BLOCK    *Allocation,
509     UINT32                  Component,
510     const char              *Module,
511     UINT32                  Line)
512 {
513     ACPI_MEMORY_LIST        *MemList;
514     ACPI_STATUS             Status;
515 
516 
517     ACPI_FUNCTION_NAME (UtRemoveAllocation);
518 
519 
520     if (AcpiGbl_DisableMemTracking)
521     {
522         return (AE_OK);
523     }
524 
525     MemList = AcpiGbl_GlobalList;
526     if (NULL == MemList->ListHead)
527     {
528         /* No allocations! */
529 
530         ACPI_ERROR ((Module, Line,
531             "Empty allocation list, nothing to free!"));
532 
533         return (AE_OK);
534     }
535 
536     Status = AcpiUtAcquireMutex (ACPI_MTX_MEMORY);
537     if (ACPI_FAILURE (Status))
538     {
539         return (Status);
540     }
541 
542     /* Unlink */
543 
544     if (Allocation->Previous)
545     {
546         (Allocation->Previous)->Next = Allocation->Next;
547     }
548     else
549     {
550         MemList->ListHead = Allocation->Next;
551     }
552 
553     if (Allocation->Next)
554     {
555         (Allocation->Next)->Previous = Allocation->Previous;
556     }
557 
558     ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Freeing %p, size 0%X\n",
559         &Allocation->UserSpace, Allocation->Size));
560 
561     /* Mark the segment as deleted */
562 
563     memset (&Allocation->UserSpace, 0xEA, Allocation->Size);
564 
565     Status = AcpiUtReleaseMutex (ACPI_MTX_MEMORY);
566     return (Status);
567 }
568 
569 
570 /*******************************************************************************
571  *
572  * FUNCTION:    AcpiUtDumpAllocationInfo
573  *
574  * PARAMETERS:  None
575  *
576  * RETURN:      None
577  *
578  * DESCRIPTION: Print some info about the outstanding allocations.
579  *
580  ******************************************************************************/
581 
582 void
AcpiUtDumpAllocationInfo(void)583 AcpiUtDumpAllocationInfo (
584     void)
585 {
586 /*
587     ACPI_MEMORY_LIST        *MemList;
588 */
589 
590     ACPI_FUNCTION_TRACE (UtDumpAllocationInfo);
591 
592 /*
593     ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
594         ("%30s: %4d (%3d Kb)\n", "Current allocations",
595         MemList->CurrentCount,
596         ROUND_UP_TO_1K (MemList->CurrentSize)));
597 
598     ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
599         ("%30s: %4d (%3d Kb)\n", "Max concurrent allocations",
600         MemList->MaxConcurrentCount,
601         ROUND_UP_TO_1K (MemList->MaxConcurrentSize)));
602 
603 
604     ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
605         ("%30s: %4d (%3d Kb)\n", "Total (all) internal objects",
606         RunningObjectCount,
607         ROUND_UP_TO_1K (RunningObjectSize)));
608 
609     ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
610         ("%30s: %4d (%3d Kb)\n", "Total (all) allocations",
611         RunningAllocCount,
612         ROUND_UP_TO_1K (RunningAllocSize)));
613 
614 
615     ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
616         ("%30s: %4d (%3d Kb)\n", "Current Nodes",
617         AcpiGbl_CurrentNodeCount,
618         ROUND_UP_TO_1K (AcpiGbl_CurrentNodeSize)));
619 
620     ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
621         ("%30s: %4d (%3d Kb)\n", "Max Nodes",
622         AcpiGbl_MaxConcurrentNodeCount,
623         ROUND_UP_TO_1K ((AcpiGbl_MaxConcurrentNodeCount *
624             sizeof (ACPI_NAMESPACE_NODE)))));
625 */
626     return_VOID;
627 }
628 
629 
630 /*******************************************************************************
631  *
632  * FUNCTION:    AcpiUtDumpAllocations
633  *
634  * PARAMETERS:  Component           - Component(s) to dump info for.
635  *              Module              - Module to dump info for. NULL means all.
636  *
637  * RETURN:      None
638  *
639  * DESCRIPTION: Print a list of all outstanding allocations.
640  *
641  ******************************************************************************/
642 
643 void
AcpiUtDumpAllocations(UINT32 Component,const char * Module)644 AcpiUtDumpAllocations (
645     UINT32                  Component,
646     const char              *Module)
647 {
648     ACPI_DEBUG_MEM_BLOCK    *Element;
649     ACPI_DESCRIPTOR         *Descriptor;
650     UINT32                  NumOutstanding = 0;
651     UINT8                   DescriptorType;
652 
653 
654     ACPI_FUNCTION_TRACE (UtDumpAllocations);
655 
656 
657     if (AcpiGbl_DisableMemTracking)
658     {
659         return_VOID;
660     }
661 
662     /*
663      * Walk the allocation list.
664      */
665     if (ACPI_FAILURE (AcpiUtAcquireMutex (ACPI_MTX_MEMORY)))
666     {
667         return_VOID;
668     }
669 
670     if (!AcpiGbl_GlobalList)
671     {
672         goto Exit;
673     }
674 
675     Element = AcpiGbl_GlobalList->ListHead;
676     while (Element)
677     {
678         if ((Element->Component & Component) &&
679             ((Module == NULL) || (0 == strcmp (Module, Element->Module))))
680         {
681             Descriptor = ACPI_CAST_PTR (
682                 ACPI_DESCRIPTOR, &Element->UserSpace);
683 
684             if (Element->Size < sizeof (ACPI_COMMON_DESCRIPTOR))
685             {
686                 AcpiOsPrintf ("%p Length 0x%04X %9.9s-%4.4u "
687                     "[Not a Descriptor - too small]\n",
688                     Descriptor, Element->Size, Element->Module,
689                     Element->Line);
690             }
691             else
692             {
693                 /* Ignore allocated objects that are in a cache */
694 
695                 if (ACPI_GET_DESCRIPTOR_TYPE (Descriptor) !=
696                     ACPI_DESC_TYPE_CACHED)
697                 {
698                     AcpiOsPrintf ("%p Length 0x%04X %9.9s-%4.4u [%s] ",
699                         Descriptor, Element->Size, Element->Module,
700                         Element->Line, AcpiUtGetDescriptorName (Descriptor));
701 
702                     /* Optional object hex dump */
703 
704                     if (AcpiGbl_VerboseLeakDump)
705                     {
706                         AcpiOsPrintf ("\n");
707                         AcpiUtDumpBuffer ((UINT8 *) Descriptor, Element->Size,
708                             DB_BYTE_DISPLAY, 0);
709                     }
710 
711                     /* Validate the descriptor type using Type field and length */
712 
713                     DescriptorType = 0; /* Not a valid descriptor type */
714 
715                     switch (ACPI_GET_DESCRIPTOR_TYPE (Descriptor))
716                     {
717                     case ACPI_DESC_TYPE_OPERAND:
718 
719                         if (Element->Size == sizeof (ACPI_OPERAND_OBJECT))
720                         {
721                             DescriptorType = ACPI_DESC_TYPE_OPERAND;
722                         }
723                         break;
724 
725                     case ACPI_DESC_TYPE_PARSER:
726 
727                         if (Element->Size == sizeof (ACPI_PARSE_OBJECT))
728                         {
729                             DescriptorType = ACPI_DESC_TYPE_PARSER;
730                         }
731                         break;
732 
733                     case ACPI_DESC_TYPE_NAMED:
734 
735                         if (Element->Size == sizeof (ACPI_NAMESPACE_NODE))
736                         {
737                             DescriptorType = ACPI_DESC_TYPE_NAMED;
738                         }
739                         break;
740 
741                     default:
742 
743                         break;
744                     }
745 
746                     /* Display additional info for the major descriptor types */
747 
748                     switch (DescriptorType)
749                     {
750                     case ACPI_DESC_TYPE_OPERAND:
751 
752                         AcpiOsPrintf ("%12.12s  RefCount 0x%04X\n",
753                             AcpiUtGetTypeName (Descriptor->Object.Common.Type),
754                             Descriptor->Object.Common.ReferenceCount);
755                         break;
756 
757                     case ACPI_DESC_TYPE_PARSER:
758 
759                         AcpiOsPrintf ("AmlOpcode 0x%04X\n",
760                             Descriptor->Op.Asl.AmlOpcode);
761                         break;
762 
763                     case ACPI_DESC_TYPE_NAMED:
764 
765                         AcpiOsPrintf ("%4.4s\n",
766                             AcpiUtGetNodeName (&Descriptor->Node));
767                         break;
768 
769                     default:
770 
771                         AcpiOsPrintf ( "\n");
772                         break;
773                     }
774                 }
775             }
776 
777             NumOutstanding++;
778         }
779 
780         Element = Element->Next;
781     }
782 
783 Exit:
784     (void) AcpiUtReleaseMutex (ACPI_MTX_MEMORY);
785 
786     /* Print summary */
787 
788     if (!NumOutstanding)
789     {
790         ACPI_INFO (("No outstanding allocations"));
791     }
792     else
793     {
794         ACPI_ERROR ((AE_INFO, "%u (0x%X) Outstanding cache allocations",
795             NumOutstanding, NumOutstanding));
796     }
797 
798     return_VOID;
799 }
800 
801 #endif  /* ACPI_DBG_TRACK_ALLOCATIONS */
802