xref: /xnu-11215/iokit/Kernel/IOKitDebug.cpp (revision 8d741a5d)
1c1dac77fSApple OSS Distributions /*
288cc0b97SApple OSS Distributions  * Copyright (c) 1998-2016 Apple Inc. All rights reserved.
3c1dac77fSApple OSS Distributions  *
4e13b1fa5SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5c1dac77fSApple OSS Distributions  *
6e13b1fa5SApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7e13b1fa5SApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8e13b1fa5SApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9e13b1fa5SApple OSS Distributions  * compliance with the License. The rights granted to you under the License
10e13b1fa5SApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
11e13b1fa5SApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
12e13b1fa5SApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
13e13b1fa5SApple OSS Distributions  * terms of an Apple operating system software license agreement.
14c1dac77fSApple OSS Distributions  *
15e13b1fa5SApple OSS Distributions  * Please obtain a copy of the License at
16e13b1fa5SApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17e13b1fa5SApple OSS Distributions  *
18e13b1fa5SApple OSS Distributions  * The Original Code and all software distributed under the License are
19e13b1fa5SApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20c1dac77fSApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21c1dac77fSApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22e13b1fa5SApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23e13b1fa5SApple OSS Distributions  * Please see the License for the specific language governing rights and
24e13b1fa5SApple OSS Distributions  * limitations under the License.
25c1dac77fSApple OSS Distributions  *
26e13b1fa5SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27c1dac77fSApple OSS Distributions  */
28c1dac77fSApple OSS Distributions 
2914e3d835SApple OSS Distributions #include <sys/sysctl.h>
300f3703acSApple OSS Distributions extern "C" {
31*8d741a5dSApple OSS Distributions #include <vm/vm_kern_xnu.h>
3288cc0b97SApple OSS Distributions #include <kern/task.h>
3388cc0b97SApple OSS Distributions #include <kern/debug.h>
340f3703acSApple OSS Distributions }
3514e3d835SApple OSS Distributions 
36855239e5SApple OSS Distributions #include <libkern/c++/OSContainers.h>
370f3703acSApple OSS Distributions #include <libkern/OSDebug.h>
38855239e5SApple OSS Distributions #include <libkern/c++/OSCPPDebug.h>
3988cc0b97SApple OSS Distributions #include <kern/backtrace.h>
40e7776783SApple OSS Distributions #include <kern/btlog.h>
41855239e5SApple OSS Distributions 
42c1dac77fSApple OSS Distributions #include <IOKit/IOKitDebug.h>
43c1dac77fSApple OSS Distributions #include <IOKit/IOLib.h>
44c1dac77fSApple OSS Distributions #include <IOKit/assert.h>
45c1dac77fSApple OSS Distributions #include <IOKit/IODeviceTreeSupport.h>
46c1dac77fSApple OSS Distributions #include <IOKit/IOService.h>
47c1dac77fSApple OSS Distributions 
4888cc0b97SApple OSS Distributions #include "IOKitKernelInternal.h"
4988cc0b97SApple OSS Distributions 
50e6231be0SApple OSS Distributions TUNABLE_WRITEABLE(SInt64, gIOKitDebug, "io", DEBUG_INIT_VALUE);
515c2921b0SApple OSS Distributions TUNABLE_DEV_WRITEABLE(SInt64, gIOKitTrace, "iotrace", 0);
52855239e5SApple OSS Distributions 
53a3bb9fccSApple OSS Distributions #if DEVELOPMENT || DEBUG
54a3bb9fccSApple OSS Distributions #define IODEBUG_CTLFLAGS        CTLFLAG_RW
55a3bb9fccSApple OSS Distributions #else
56a3bb9fccSApple OSS Distributions #define IODEBUG_CTLFLAGS        CTLFLAG_RD
57a3bb9fccSApple OSS Distributions #endif
58a3bb9fccSApple OSS Distributions 
595c2921b0SApple OSS Distributions SYSCTL_QUAD(_debug, OID_AUTO, iotrace, IODEBUG_CTLFLAGS | CTLFLAG_LOCKED, &gIOKitTrace, "trace io");
6014e3d835SApple OSS Distributions 
6176e12aa3SApple OSS Distributions static int
sysctl_debug_iokit(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)6276e12aa3SApple OSS Distributions sysctl_debug_iokit
6376e12aa3SApple OSS Distributions (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
6476e12aa3SApple OSS Distributions {
6576e12aa3SApple OSS Distributions 	SInt64 newValue;
6676e12aa3SApple OSS Distributions 	int changed, error = sysctl_io_number(req, gIOKitDebug, sizeof(gIOKitDebug), &newValue, &changed);
6776e12aa3SApple OSS Distributions 	if (changed) {
6876e12aa3SApple OSS Distributions 		gIOKitDebug = ((gIOKitDebug & ~kIOKitDebugUserOptions) | (newValue & kIOKitDebugUserOptions));
6976e12aa3SApple OSS Distributions 	}
70a5e72196SApple OSS Distributions 	return error;
7176e12aa3SApple OSS Distributions }
7276e12aa3SApple OSS Distributions 
7376e12aa3SApple OSS Distributions SYSCTL_PROC(_debug, OID_AUTO, iokit,
74e6231be0SApple OSS Distributions     CTLTYPE_QUAD | IODEBUG_CTLFLAGS | CTLFLAG_KERN | CTLFLAG_LOCKED,
7576e12aa3SApple OSS Distributions     &gIOKitDebug, 0, sysctl_debug_iokit, "Q", "boot_arg io");
76c1dac77fSApple OSS Distributions 
775c2921b0SApple OSS Distributions void           (*gIOTrackingLeakScanCallback)(uint32_t notification) = NULL;
785c2921b0SApple OSS Distributions 
79bb611c8fSApple OSS Distributions size_t          debug_malloc_size;
80bb611c8fSApple OSS Distributions size_t          debug_iomalloc_size;
81e13b1fa5SApple OSS Distributions 
8214e3d835SApple OSS Distributions vm_size_t       debug_iomallocpageable_size;
83bb611c8fSApple OSS Distributions size_t          debug_container_malloc_size;
84c1dac77fSApple OSS Distributions // int          debug_ivars_size; // in OSObject.cpp
85c1dac77fSApple OSS Distributions 
8614e3d835SApple OSS Distributions extern "C" {
873ca3bd55SApple OSS Distributions #if 0
883ca3bd55SApple OSS Distributions #define DEBG(fmt, args...)   { kprintf(fmt, ## args); }
893ca3bd55SApple OSS Distributions #else
903ca3bd55SApple OSS Distributions #define DEBG(fmt, args...)   { IOLog(fmt, ## args); }
913ca3bd55SApple OSS Distributions #endif
9214e3d835SApple OSS Distributions 
93a5e72196SApple OSS Distributions void
IOPrintPlane(const IORegistryPlane * plane)94a5e72196SApple OSS Distributions IOPrintPlane( const IORegistryPlane * plane )
95c1dac77fSApple OSS Distributions {
96c1dac77fSApple OSS Distributions 	IORegistryEntry *           next;
97c1dac77fSApple OSS Distributions 	IORegistryIterator *        iter;
98c1dac77fSApple OSS Distributions 	OSOrderedSet *              all;
99c1dac77fSApple OSS Distributions 	IOService *                 service;
100c1dac77fSApple OSS Distributions 
101c1dac77fSApple OSS Distributions 	iter = IORegistryIterator::iterateOver( plane );
102c1dac77fSApple OSS Distributions 	assert( iter );
103c1dac77fSApple OSS Distributions 	all = iter->iterateAll();
104c1dac77fSApple OSS Distributions 	if (all) {
1053ca3bd55SApple OSS Distributions 		DEBG("Count %d\n", all->getCount());
106c1dac77fSApple OSS Distributions 		all->release();
107a5e72196SApple OSS Distributions 	} else {
1083ca3bd55SApple OSS Distributions 		DEBG("Empty\n");
109a5e72196SApple OSS Distributions 	}
110c1dac77fSApple OSS Distributions 
111c1dac77fSApple OSS Distributions 	iter->reset();
112c1dac77fSApple OSS Distributions 	while ((next = iter->getNextObjectRecursive())) {
113e7776783SApple OSS Distributions 		DEBG( "%*s\033[33m%s", 2 * next->getDepth( plane ), "", next->getName( plane ));
114a5e72196SApple OSS Distributions 		if ((next->getLocation( plane ))) {
1153ca3bd55SApple OSS Distributions 			DEBG("@%s", next->getLocation( plane ));
116a5e72196SApple OSS Distributions 		}
1173ca3bd55SApple OSS Distributions 		DEBG("\033[0m <class %s", next->getMetaClass()->getClassName());
118a5e72196SApple OSS Distributions 		if ((service = OSDynamicCast(IOService, next))) {
1193ca3bd55SApple OSS Distributions 			DEBG(", busy %ld", (long) service->getBusyState());
120a5e72196SApple OSS Distributions 		}
1213ca3bd55SApple OSS Distributions 		DEBG( ">\n");
1223ca3bd55SApple OSS Distributions //      IOSleep(250);
123c1dac77fSApple OSS Distributions 	}
124c1dac77fSApple OSS Distributions 	iter->release();
125e7776783SApple OSS Distributions 
126e7776783SApple OSS Distributions #undef IOPrintPlaneFormat
127c1dac77fSApple OSS Distributions }
128c1dac77fSApple OSS Distributions 
129a5e72196SApple OSS Distributions void
db_piokjunk(void)130a5e72196SApple OSS Distributions db_piokjunk(void)
131368ad365SApple OSS Distributions {
132368ad365SApple OSS Distributions }
133d0c1fef6SApple OSS Distributions 
134a5e72196SApple OSS Distributions void
db_dumpiojunk(const IORegistryPlane * plane __unused)135a5e72196SApple OSS Distributions db_dumpiojunk( const IORegistryPlane * plane __unused )
136d0c1fef6SApple OSS Distributions {
137368ad365SApple OSS Distributions }
138368ad365SApple OSS Distributions 
139a5e72196SApple OSS Distributions void
IOPrintMemory(void)140a5e72196SApple OSS Distributions IOPrintMemory( void )
141c1dac77fSApple OSS Distributions {
142c1dac77fSApple OSS Distributions //    OSMetaClass::printInstanceCounts();
143c1dac77fSApple OSS Distributions 
144c1dac77fSApple OSS Distributions 	IOLog("\n"
145bb611c8fSApple OSS Distributions 	    "ivar kalloc()       0x%08lx\n"
146bb611c8fSApple OSS Distributions 	    "malloc()            0x%08lx\n"
147bb611c8fSApple OSS Distributions 	    "containers kalloc() 0x%08lx\n"
148bb611c8fSApple OSS Distributions 	    "IOMalloc()          0x%08lx\n"
149c1dac77fSApple OSS Distributions 	    "----------------------------------------\n",
150c1dac77fSApple OSS Distributions 	    debug_ivars_size,
151c1dac77fSApple OSS Distributions 	    debug_malloc_size,
152c1dac77fSApple OSS Distributions 	    debug_container_malloc_size,
153c1dac77fSApple OSS Distributions 	    debug_iomalloc_size
154c1dac77fSApple OSS Distributions 	    );
155c1dac77fSApple OSS Distributions }
156c1dac77fSApple OSS Distributions } /* extern "C" */
157c1dac77fSApple OSS Distributions 
1580f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
159c1dac77fSApple OSS Distributions 
160c1dac77fSApple OSS Distributions #define super OSObject
OSDefineMetaClassAndStructors(IOKitDiagnostics,OSObject)161c1dac77fSApple OSS Distributions OSDefineMetaClassAndStructors(IOKitDiagnostics, OSObject)
162c1dac77fSApple OSS Distributions 
1630f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
164c1dac77fSApple OSS Distributions 
165c1dac77fSApple OSS Distributions OSObject * IOKitDiagnostics::diagnostics( void )
166c1dac77fSApple OSS Distributions {
167c1dac77fSApple OSS Distributions 	IOKitDiagnostics * diags;
168c1dac77fSApple OSS Distributions 
169c1dac77fSApple OSS Distributions 	diags = new IOKitDiagnostics;
170c1dac77fSApple OSS Distributions 	if (diags && !diags->init()) {
171c1dac77fSApple OSS Distributions 		diags->release();
172a5e72196SApple OSS Distributions 		diags = NULL;
173c1dac77fSApple OSS Distributions 	}
174c1dac77fSApple OSS Distributions 
175a5e72196SApple OSS Distributions 	return diags;
176c1dac77fSApple OSS Distributions }
177c1dac77fSApple OSS Distributions 
178a5e72196SApple OSS Distributions void
updateOffset(OSDictionary * dict,UInt64 value,const char * name)179a5e72196SApple OSS Distributions IOKitDiagnostics::updateOffset( OSDictionary * dict,
1800f3703acSApple OSS Distributions     UInt64 value, const char * name )
181c1dac77fSApple OSS Distributions {
182c1dac77fSApple OSS Distributions 	OSNumber * off;
183c1dac77fSApple OSS Distributions 
1840f3703acSApple OSS Distributions 	off = OSNumber::withNumber( value, 64 );
185a5e72196SApple OSS Distributions 	if (!off) {
186c1dac77fSApple OSS Distributions 		return;
187a5e72196SApple OSS Distributions 	}
188c1dac77fSApple OSS Distributions 
189c1dac77fSApple OSS Distributions 	dict->setObject( name, off );
190c1dac77fSApple OSS Distributions 	off->release();
191c1dac77fSApple OSS Distributions }
192c1dac77fSApple OSS Distributions 
193a5e72196SApple OSS Distributions bool
serialize(OSSerialize * s) const194a5e72196SApple OSS Distributions IOKitDiagnostics::serialize(OSSerialize *s) const
195c1dac77fSApple OSS Distributions {
196c1dac77fSApple OSS Distributions 	OSDictionary *      dict;
197c1dac77fSApple OSS Distributions 	bool                ok;
198c1dac77fSApple OSS Distributions 
199c1dac77fSApple OSS Distributions 	dict = OSDictionary::withCapacity( 5 );
200a5e72196SApple OSS Distributions 	if (!dict) {
201a5e72196SApple OSS Distributions 		return false;
202a5e72196SApple OSS Distributions 	}
203c1dac77fSApple OSS Distributions 
204c1dac77fSApple OSS Distributions 	updateOffset( dict, debug_ivars_size, "Instance allocation" );
205c1dac77fSApple OSS Distributions 	updateOffset( dict, debug_container_malloc_size, "Container allocation" );
206c1dac77fSApple OSS Distributions 	updateOffset( dict, debug_iomalloc_size, "IOMalloc allocation" );
20714e3d835SApple OSS Distributions 	updateOffset( dict, debug_iomallocpageable_size, "Pageable allocation" );
208c1dac77fSApple OSS Distributions 
209368ad365SApple OSS Distributions 	OSMetaClass::serializeClassDictionary(dict);
210c1dac77fSApple OSS Distributions 
211c1dac77fSApple OSS Distributions 	ok = dict->serialize( s );
212c1dac77fSApple OSS Distributions 
213c1dac77fSApple OSS Distributions 	dict->release();
214c1dac77fSApple OSS Distributions 
215a5e72196SApple OSS Distributions 	return ok;
216c1dac77fSApple OSS Distributions }
217c1dac77fSApple OSS Distributions 
2180f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2190f3703acSApple OSS Distributions 
2200f3703acSApple OSS Distributions #if IOTRACKING
2210f3703acSApple OSS Distributions 
2220f3703acSApple OSS Distributions #include <libkern/c++/OSCPPDebug.h>
2230f3703acSApple OSS Distributions #include <libkern/c++/OSKext.h>
2240f3703acSApple OSS Distributions #include <kern/zalloc.h>
2250f3703acSApple OSS Distributions 
2260f3703acSApple OSS Distributions __private_extern__ "C" void qsort(
2270f3703acSApple OSS Distributions 	void * array,
2280f3703acSApple OSS Distributions 	size_t nmembers,
2290f3703acSApple OSS Distributions 	size_t member_size,
2300f3703acSApple OSS Distributions 	int (*)(const void *, const void *));
2310f3703acSApple OSS Distributions 
2320f3703acSApple OSS Distributions extern "C" ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va);
2330f3703acSApple OSS Distributions extern "C" ppnum_t pmap_valid_page(ppnum_t pn);
2340f3703acSApple OSS Distributions 
2350f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2360f3703acSApple OSS Distributions 
237a5e72196SApple OSS Distributions struct IOTRecursiveLock {
2380f3703acSApple OSS Distributions 	lck_mtx_t * mutex;
2390f3703acSApple OSS Distributions 	thread_t    thread;
2400f3703acSApple OSS Distributions 	UInt32      count;
2410f3703acSApple OSS Distributions };
2420f3703acSApple OSS Distributions 
243a5e72196SApple OSS Distributions struct IOTrackingQueue {
2440f3703acSApple OSS Distributions 	queue_chain_t     link;
2450f3703acSApple OSS Distributions 	IOTRecursiveLock  lock;
2460f3703acSApple OSS Distributions 	const char *      name;
24788cc0b97SApple OSS Distributions 	uintptr_t         btEntry;
2480f3703acSApple OSS Distributions 	size_t            allocSize;
2490f3703acSApple OSS Distributions 	size_t            minCaptureSize;
2500f3703acSApple OSS Distributions 	uint32_t          siteCount;
25188cc0b97SApple OSS Distributions 	uint32_t          type;
25288cc0b97SApple OSS Distributions 	uint32_t          numSiteQs;
2530f3703acSApple OSS Distributions 	uint8_t           captureOn;
25488cc0b97SApple OSS Distributions 	queue_head_t      sites[];
2550f3703acSApple OSS Distributions };
2560f3703acSApple OSS Distributions 
257bb611c8fSApple OSS Distributions 
258bb611c8fSApple OSS Distributions struct IOTrackingCallSiteUser {
259bb611c8fSApple OSS Distributions 	pid_t         pid;
260bb611c8fSApple OSS Distributions 	uint8_t       user32;
261bb611c8fSApple OSS Distributions 	uint8_t       userCount;
262bb611c8fSApple OSS Distributions 	uintptr_t     bt[kIOTrackingCallSiteBTs];
263bb611c8fSApple OSS Distributions };
264bb611c8fSApple OSS Distributions 
265a5e72196SApple OSS Distributions struct IOTrackingCallSite {
2660f3703acSApple OSS Distributions 	queue_chain_t          link;
267bb611c8fSApple OSS Distributions 	queue_head_t           instances;
2680f3703acSApple OSS Distributions 	IOTrackingQueue *      queue;
2695c2921b0SApple OSS Distributions 	IOTracking **          addresses;
270bb611c8fSApple OSS Distributions 	size_t        size[2];
2710f3703acSApple OSS Distributions 	uint32_t               crc;
272bb611c8fSApple OSS Distributions 	uint32_t      count;
27388cc0b97SApple OSS Distributions 
27476e12aa3SApple OSS Distributions 	vm_tag_t      tag;
275bb611c8fSApple OSS Distributions 	uint8_t       user32;
276bb611c8fSApple OSS Distributions 	uint8_t       userCount;
277bb611c8fSApple OSS Distributions 	pid_t         btPID;
27888cc0b97SApple OSS Distributions 
279bb611c8fSApple OSS Distributions 	uintptr_t     bt[kIOTrackingCallSiteBTs];
280bb611c8fSApple OSS Distributions 	IOTrackingCallSiteUser     user[0];
2810f3703acSApple OSS Distributions };
2820f3703acSApple OSS Distributions 
283e6231be0SApple OSS Distributions struct IOTrackingCallSiteWithUser {
284e6231be0SApple OSS Distributions 	struct IOTrackingCallSite     site;
285e6231be0SApple OSS Distributions 	struct IOTrackingCallSiteUser user;
286e6231be0SApple OSS Distributions };
287bb611c8fSApple OSS Distributions 
288e7776783SApple OSS Distributions static void IOTrackingFreeCallSite(uint32_t type, IOTrackingCallSite ** site);
289e7776783SApple OSS Distributions 
290a5e72196SApple OSS Distributions struct IOTrackingLeaksRef {
2910f3703acSApple OSS Distributions 	uintptr_t * instances;
29288cc0b97SApple OSS Distributions 	uint32_t    zoneSize;
2930f3703acSApple OSS Distributions 	uint32_t    count;
2940f3703acSApple OSS Distributions 	uint32_t    found;
29576e12aa3SApple OSS Distributions 	uint32_t    foundzlen;
2960f3703acSApple OSS Distributions 	size_t      bytes;
2970f3703acSApple OSS Distributions };
2980f3703acSApple OSS Distributions 
2990f3703acSApple OSS Distributions lck_mtx_t *  gIOTrackingLock;
3000f3703acSApple OSS Distributions queue_head_t gIOTrackingQ;
3010f3703acSApple OSS Distributions 
302a5e72196SApple OSS Distributions enum{
3030f3703acSApple OSS Distributions 	kTrackingAddressFlagAllocated    = 0x00000001
3040f3703acSApple OSS Distributions };
3050f3703acSApple OSS Distributions 
3060f3703acSApple OSS Distributions #if defined(__LP64__)
3070f3703acSApple OSS Distributions #define IOTrackingAddressFlags(ptr)     (ptr->flags)
3080f3703acSApple OSS Distributions #else
3090f3703acSApple OSS Distributions #define IOTrackingAddressFlags(ptr)     (ptr->tracking.flags)
3100f3703acSApple OSS Distributions #endif
3110f3703acSApple OSS Distributions 
3120f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3130f3703acSApple OSS Distributions 
3140f3703acSApple OSS Distributions static void
IOTRecursiveLockLock(IOTRecursiveLock * lock)3150f3703acSApple OSS Distributions IOTRecursiveLockLock(IOTRecursiveLock * lock)
3160f3703acSApple OSS Distributions {
317a5e72196SApple OSS Distributions 	if (lock->thread == current_thread()) {
318a5e72196SApple OSS Distributions 		lock->count++;
319a5e72196SApple OSS Distributions 	} else {
3200f3703acSApple OSS Distributions 		lck_mtx_lock(lock->mutex);
321a5e72196SApple OSS Distributions 		assert(lock->thread == NULL);
3220f3703acSApple OSS Distributions 		assert(lock->count == 0);
3230f3703acSApple OSS Distributions 		lock->thread = current_thread();
3240f3703acSApple OSS Distributions 		lock->count = 1;
3250f3703acSApple OSS Distributions 	}
3260f3703acSApple OSS Distributions }
3270f3703acSApple OSS Distributions 
3280f3703acSApple OSS Distributions static void
IOTRecursiveLockUnlock(IOTRecursiveLock * lock)3290f3703acSApple OSS Distributions IOTRecursiveLockUnlock(IOTRecursiveLock * lock)
3300f3703acSApple OSS Distributions {
3310f3703acSApple OSS Distributions 	assert(lock->thread == current_thread());
332a5e72196SApple OSS Distributions 	if (0 == (--lock->count)) {
333a5e72196SApple OSS Distributions 		lock->thread = NULL;
3340f3703acSApple OSS Distributions 		lck_mtx_unlock(lock->mutex);
3350f3703acSApple OSS Distributions 	}
3360f3703acSApple OSS Distributions }
3370f3703acSApple OSS Distributions 
3380f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3390f3703acSApple OSS Distributions 
3400f3703acSApple OSS Distributions void
IOTrackingInit(void)3410f3703acSApple OSS Distributions IOTrackingInit(void)
3420f3703acSApple OSS Distributions {
3430f3703acSApple OSS Distributions 	queue_init(&gIOTrackingQ);
3440f3703acSApple OSS Distributions 	gIOTrackingLock = lck_mtx_alloc_init(IOLockGroup, LCK_ATTR_NULL);
3450f3703acSApple OSS Distributions }
3460f3703acSApple OSS Distributions 
3470f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3480f3703acSApple OSS Distributions 
3490f3703acSApple OSS Distributions IOTrackingQueue *
IOTrackingQueueAlloc(const char * name,uintptr_t btEntry,size_t allocSize,size_t minCaptureSize,uint32_t type,uint32_t numSiteQs)35088cc0b97SApple OSS Distributions IOTrackingQueueAlloc(const char * name, uintptr_t btEntry,
35188cc0b97SApple OSS Distributions     size_t allocSize, size_t minCaptureSize,
35288cc0b97SApple OSS Distributions     uint32_t type, uint32_t numSiteQs)
3530f3703acSApple OSS Distributions {
3540f3703acSApple OSS Distributions 	IOTrackingQueue * queue;
35588cc0b97SApple OSS Distributions 	uint32_t          idx;
35688cc0b97SApple OSS Distributions 
357a5e72196SApple OSS Distributions 	if (!numSiteQs) {
358a5e72196SApple OSS Distributions 		numSiteQs = 1;
359a5e72196SApple OSS Distributions 	}
360e6231be0SApple OSS Distributions 	queue = kalloc_type(IOTrackingQueue, queue_head_t, numSiteQs, Z_WAITOK_ZERO);
3610f3703acSApple OSS Distributions 	queue->name           = name;
36288cc0b97SApple OSS Distributions 	queue->btEntry        = btEntry;
3630f3703acSApple OSS Distributions 	queue->allocSize      = allocSize;
3640f3703acSApple OSS Distributions 	queue->minCaptureSize = minCaptureSize;
3650f3703acSApple OSS Distributions 	queue->lock.mutex     = lck_mtx_alloc_init(IOLockGroup, LCK_ATTR_NULL);
36688cc0b97SApple OSS Distributions 	queue->numSiteQs      = numSiteQs;
36788cc0b97SApple OSS Distributions 	queue->type           = type;
36888cc0b97SApple OSS Distributions 	enum { kFlags = (kIOTracking | kIOTrackingBoot) };
36988cc0b97SApple OSS Distributions 	queue->captureOn = (kFlags == (kFlags & gIOKitDebug))
37088cc0b97SApple OSS Distributions 	    || (kIOTrackingQueueTypeDefaultOn & type);
3710f3703acSApple OSS Distributions 
372a5e72196SApple OSS Distributions 	for (idx = 0; idx < numSiteQs; idx++) {
373a5e72196SApple OSS Distributions 		queue_init(&queue->sites[idx]);
374a5e72196SApple OSS Distributions 	}
3750f3703acSApple OSS Distributions 
3760f3703acSApple OSS Distributions 	lck_mtx_lock(gIOTrackingLock);
3770f3703acSApple OSS Distributions 	queue_enter(&gIOTrackingQ, queue, IOTrackingQueue *, link);
3780f3703acSApple OSS Distributions 	lck_mtx_unlock(gIOTrackingLock);
3790f3703acSApple OSS Distributions 
380a5e72196SApple OSS Distributions 	return queue;
3810f3703acSApple OSS Distributions };
3820f3703acSApple OSS Distributions 
383bb611c8fSApple OSS Distributions void
IOTrackingQueueCollectUser(IOTrackingQueue * queue)384bb611c8fSApple OSS Distributions IOTrackingQueueCollectUser(IOTrackingQueue * queue)
385bb611c8fSApple OSS Distributions {
386bb611c8fSApple OSS Distributions 	assert(0 == queue->siteCount);
387bb611c8fSApple OSS Distributions 	queue->type |= kIOTrackingQueueTypeUser;
388bb611c8fSApple OSS Distributions }
389bb611c8fSApple OSS Distributions 
3900f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3910f3703acSApple OSS Distributions 
3920f3703acSApple OSS Distributions void
IOTrackingQueueFree(IOTrackingQueue * queue)3930f3703acSApple OSS Distributions IOTrackingQueueFree(IOTrackingQueue * queue)
3940f3703acSApple OSS Distributions {
3950f3703acSApple OSS Distributions 	lck_mtx_lock(gIOTrackingLock);
3960f3703acSApple OSS Distributions 	IOTrackingReset(queue);
3970f3703acSApple OSS Distributions 	remque(&queue->link);
3980f3703acSApple OSS Distributions 	lck_mtx_unlock(gIOTrackingLock);
3990f3703acSApple OSS Distributions 
4000f3703acSApple OSS Distributions 	lck_mtx_free(queue->lock.mutex, IOLockGroup);
4010f3703acSApple OSS Distributions 
402e6231be0SApple OSS Distributions 	kfree_type(IOTrackingQueue, queue_head_t, queue->numSiteQs, queue);
4030f3703acSApple OSS Distributions };
4040f3703acSApple OSS Distributions 
4050f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
4060f3703acSApple OSS Distributions 
4070f3703acSApple OSS Distributions /* fasthash
408a5e72196SApple OSS Distributions  *  The MIT License
409a5e72196SApple OSS Distributions  *
410a5e72196SApple OSS Distributions  *  Copyright (C) 2012 Zilong Tan ([email protected])
411a5e72196SApple OSS Distributions  *
412a5e72196SApple OSS Distributions  *  Permission is hereby granted, free of charge, to any person
413a5e72196SApple OSS Distributions  *  obtaining a copy of this software and associated documentation
414a5e72196SApple OSS Distributions  *  files (the "Software"), to deal in the Software without
415a5e72196SApple OSS Distributions  *  restriction, including without limitation the rights to use, copy,
416a5e72196SApple OSS Distributions  *  modify, merge, publish, distribute, sublicense, and/or sell copies
417a5e72196SApple OSS Distributions  *  of the Software, and to permit persons to whom the Software is
418a5e72196SApple OSS Distributions  *  furnished to do so, subject to the following conditions:
419a5e72196SApple OSS Distributions  *
420a5e72196SApple OSS Distributions  *  The above copyright notice and this permission notice shall be
421a5e72196SApple OSS Distributions  *  included in all copies or substantial portions of the Software.
422a5e72196SApple OSS Distributions  *
423a5e72196SApple OSS Distributions  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
424a5e72196SApple OSS Distributions  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
425a5e72196SApple OSS Distributions  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
426a5e72196SApple OSS Distributions  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
427a5e72196SApple OSS Distributions  *  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
428a5e72196SApple OSS Distributions  *  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
429a5e72196SApple OSS Distributions  *  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
430a5e72196SApple OSS Distributions  *  SOFTWARE.
4310f3703acSApple OSS Distributions  */
4320f3703acSApple OSS Distributions 
4330f3703acSApple OSS Distributions 
4340f3703acSApple OSS Distributions // Compression function for Merkle-Damgard construction.
4350f3703acSApple OSS Distributions // This function is generated using the framework provided.
4360f3703acSApple OSS Distributions #define mix(h) ({                               \
4370f3703acSApple OSS Distributions 	          (h) ^= (h) >> 23;             \
4380f3703acSApple OSS Distributions 	          (h) *= 0x2127599bf4325c37ULL; \
4390f3703acSApple OSS Distributions 	          (h) ^= (h) >> 47; })
4400f3703acSApple OSS Distributions 
4410f3703acSApple OSS Distributions static uint64_t
fasthash64(const void * buf,size_t len,uint64_t seed)4420f3703acSApple OSS Distributions fasthash64(const void *buf, size_t len, uint64_t seed)
4430f3703acSApple OSS Distributions {
4440f3703acSApple OSS Distributions 	const uint64_t    m = 0x880355f21e6d1965ULL;
4450f3703acSApple OSS Distributions 	const uint64_t *pos = (const uint64_t *)buf;
4460f3703acSApple OSS Distributions 	const uint64_t *end = pos + (len / 8);
4470f3703acSApple OSS Distributions 	const unsigned char *pos2;
4480f3703acSApple OSS Distributions 	uint64_t h = seed ^ (len * m);
4490f3703acSApple OSS Distributions 	uint64_t v;
4500f3703acSApple OSS Distributions 
4510f3703acSApple OSS Distributions 	while (pos != end) {
4520f3703acSApple OSS Distributions 		v  = *pos++;
4530f3703acSApple OSS Distributions 		h ^= mix(v);
4540f3703acSApple OSS Distributions 		h *= m;
4550f3703acSApple OSS Distributions 	}
4560f3703acSApple OSS Distributions 
4570f3703acSApple OSS Distributions 	pos2 = (const unsigned char*)pos;
4580f3703acSApple OSS Distributions 	v = 0;
4590f3703acSApple OSS Distributions 
4600f3703acSApple OSS Distributions 	switch (len & 7) {
4610f3703acSApple OSS Distributions 	case 7: v ^= (uint64_t)pos2[6] << 48;
46288cc0b97SApple OSS Distributions 		[[clang::fallthrough]];
4630f3703acSApple OSS Distributions 	case 6: v ^= (uint64_t)pos2[5] << 40;
46488cc0b97SApple OSS Distributions 		[[clang::fallthrough]];
4650f3703acSApple OSS Distributions 	case 5: v ^= (uint64_t)pos2[4] << 32;
46688cc0b97SApple OSS Distributions 		[[clang::fallthrough]];
4670f3703acSApple OSS Distributions 	case 4: v ^= (uint64_t)pos2[3] << 24;
46888cc0b97SApple OSS Distributions 		[[clang::fallthrough]];
4690f3703acSApple OSS Distributions 	case 3: v ^= (uint64_t)pos2[2] << 16;
47088cc0b97SApple OSS Distributions 		[[clang::fallthrough]];
4710f3703acSApple OSS Distributions 	case 2: v ^= (uint64_t)pos2[1] << 8;
47288cc0b97SApple OSS Distributions 		[[clang::fallthrough]];
4730f3703acSApple OSS Distributions 	case 1: v ^= (uint64_t)pos2[0];
4740f3703acSApple OSS Distributions 		h ^= mix(v);
4750f3703acSApple OSS Distributions 		h *= m;
4760f3703acSApple OSS Distributions 	}
4770f3703acSApple OSS Distributions 
4780f3703acSApple OSS Distributions 	return mix(h);
4790f3703acSApple OSS Distributions }
4800f3703acSApple OSS Distributions 
4810f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
4820f3703acSApple OSS Distributions 
4830f3703acSApple OSS Distributions static uint32_t
fasthash32(const void * buf,size_t len,uint32_t seed)4840f3703acSApple OSS Distributions fasthash32(const void *buf, size_t len, uint32_t seed)
4850f3703acSApple OSS Distributions {
4860f3703acSApple OSS Distributions 	// the following trick converts the 64-bit hashcode to Fermat
4870f3703acSApple OSS Distributions 	// residue, which shall retain information from both the higher
4880f3703acSApple OSS Distributions 	// and lower parts of hashcode.
4890f3703acSApple OSS Distributions 	uint64_t h = fasthash64(buf, len, seed);
490bb611c8fSApple OSS Distributions 	return (uint32_t) (h - (h >> 32));
4910f3703acSApple OSS Distributions }
4920f3703acSApple OSS Distributions 
4930f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
4940f3703acSApple OSS Distributions 
4950f3703acSApple OSS Distributions void
IOTrackingAddUser(IOTrackingQueue * queue,IOTrackingUser * mem,vm_size_t size)49688cc0b97SApple OSS Distributions IOTrackingAddUser(IOTrackingQueue * queue, IOTrackingUser * mem, vm_size_t size)
49788cc0b97SApple OSS Distributions {
49888cc0b97SApple OSS Distributions 	uint32_t num;
499bb611c8fSApple OSS Distributions 	int pid;
50088cc0b97SApple OSS Distributions 
501a5e72196SApple OSS Distributions 	if (!queue->captureOn) {
502a5e72196SApple OSS Distributions 		return;
503a5e72196SApple OSS Distributions 	}
504a5e72196SApple OSS Distributions 	if (size < queue->minCaptureSize) {
505a5e72196SApple OSS Distributions 		return;
506a5e72196SApple OSS Distributions 	}
50788cc0b97SApple OSS Distributions 
50888cc0b97SApple OSS Distributions 	assert(!mem->link.next);
50988cc0b97SApple OSS Distributions 
510e6231be0SApple OSS Distributions 	num = backtrace(&mem->bt[0], kIOTrackingCallSiteBTs, NULL, NULL);
51188cc0b97SApple OSS Distributions 	num = 0;
512bb611c8fSApple OSS Distributions 	if ((kernel_task != current_task()) && (pid = proc_selfpid())) {
513e6231be0SApple OSS Distributions 		struct backtrace_user_info btinfo = BTUINFO_INIT;
514bb611c8fSApple OSS Distributions 		mem->btPID = pid;
515e6231be0SApple OSS Distributions 		num = backtrace_user(&mem->btUser[0], kIOTrackingCallSiteBTs - 1,
516e6231be0SApple OSS Distributions 		    NULL, &btinfo);
517e6231be0SApple OSS Distributions 		mem->user32 = !(btinfo.btui_info & BTI_64_BIT);
51888cc0b97SApple OSS Distributions 	}
51988cc0b97SApple OSS Distributions 	assert(num <= kIOTrackingCallSiteBTs);
520bb611c8fSApple OSS Distributions 	static_assert(kIOTrackingCallSiteBTs <= UINT8_MAX);
521bb611c8fSApple OSS Distributions 	mem->userCount = ((uint8_t) num);
52288cc0b97SApple OSS Distributions 
52388cc0b97SApple OSS Distributions 	IOTRecursiveLockLock(&queue->lock);
52488cc0b97SApple OSS Distributions 	queue_enter/*last*/ (&queue->sites[0], mem, IOTrackingUser *, link);
52588cc0b97SApple OSS Distributions 	queue->siteCount++;
52688cc0b97SApple OSS Distributions 	IOTRecursiveLockUnlock(&queue->lock);
52788cc0b97SApple OSS Distributions }
52888cc0b97SApple OSS Distributions 
52988cc0b97SApple OSS Distributions void
IOTrackingRemoveUser(IOTrackingQueue * queue,IOTrackingUser * mem)53088cc0b97SApple OSS Distributions IOTrackingRemoveUser(IOTrackingQueue * queue, IOTrackingUser * mem)
53188cc0b97SApple OSS Distributions {
532a5e72196SApple OSS Distributions 	if (!mem->link.next) {
533a5e72196SApple OSS Distributions 		return;
534a5e72196SApple OSS Distributions 	}
53588cc0b97SApple OSS Distributions 
53688cc0b97SApple OSS Distributions 	IOTRecursiveLockLock(&queue->lock);
537a5e72196SApple OSS Distributions 	if (mem->link.next) {
53888cc0b97SApple OSS Distributions 		remque(&mem->link);
53988cc0b97SApple OSS Distributions 		assert(queue->siteCount);
54088cc0b97SApple OSS Distributions 		queue->siteCount--;
54188cc0b97SApple OSS Distributions 	}
54288cc0b97SApple OSS Distributions 	IOTRecursiveLockUnlock(&queue->lock);
54388cc0b97SApple OSS Distributions }
54488cc0b97SApple OSS Distributions 
54588cc0b97SApple OSS Distributions uint64_t gIOTrackingAddTime;
54688cc0b97SApple OSS Distributions 
54788cc0b97SApple OSS Distributions void
IOTrackingAdd(IOTrackingQueue * queue,IOTracking * mem,size_t size,bool address,vm_tag_t tag)54876e12aa3SApple OSS Distributions IOTrackingAdd(IOTrackingQueue * queue, IOTracking * mem, size_t size, bool address, vm_tag_t tag)
5490f3703acSApple OSS Distributions {
5500f3703acSApple OSS Distributions 	IOTrackingCallSite * site;
5510f3703acSApple OSS Distributions 	uint32_t             crc, num;
5520f3703acSApple OSS Distributions 	uintptr_t            bt[kIOTrackingCallSiteBTs + 1];
553bb611c8fSApple OSS Distributions 	uintptr_t            btUser[kIOTrackingCallSiteBTs];
55488cc0b97SApple OSS Distributions 	queue_head_t       * que;
555bb611c8fSApple OSS Distributions 	bool                 user;
556bb611c8fSApple OSS Distributions 	int                  pid;
557bb611c8fSApple OSS Distributions 	int                  userCount;
5580f3703acSApple OSS Distributions 
559a5e72196SApple OSS Distributions 	if (mem->site) {
560a5e72196SApple OSS Distributions 		return;
561a5e72196SApple OSS Distributions 	}
562a5e72196SApple OSS Distributions 	if (!queue->captureOn) {
563a5e72196SApple OSS Distributions 		return;
564a5e72196SApple OSS Distributions 	}
565a5e72196SApple OSS Distributions 	if (size < queue->minCaptureSize) {
566a5e72196SApple OSS Distributions 		return;
567a5e72196SApple OSS Distributions 	}
5680f3703acSApple OSS Distributions 
569bb611c8fSApple OSS Distributions 	user = (0 != (kIOTrackingQueueTypeUser & queue->type));
570bb611c8fSApple OSS Distributions 
5710f3703acSApple OSS Distributions 	assert(!mem->link.next);
5720f3703acSApple OSS Distributions 
573e6231be0SApple OSS Distributions 	num  = backtrace(&bt[0], kIOTrackingCallSiteBTs + 1, NULL, NULL);
574a5e72196SApple OSS Distributions 	if (!num) {
575a5e72196SApple OSS Distributions 		return;
576a5e72196SApple OSS Distributions 	}
5770f3703acSApple OSS Distributions 	num--;
5780f3703acSApple OSS Distributions 	crc = fasthash32(&bt[1], num * sizeof(bt[0]), 0x04C11DB7);
5790f3703acSApple OSS Distributions 
580bb611c8fSApple OSS Distributions 	userCount = 0;
581bb611c8fSApple OSS Distributions 	pid = 0;
582e6231be0SApple OSS Distributions 	backtrace_info_t btinfo = BTI_NONE;
583bb611c8fSApple OSS Distributions 	if (user) {
584bb611c8fSApple OSS Distributions 		if ((kernel_task != current_task()) && (pid = proc_selfpid())) {
585e6231be0SApple OSS Distributions 			struct backtrace_user_info btuinfo = BTUINFO_INIT;
586e6231be0SApple OSS Distributions 			userCount = backtrace_user(&btUser[0], kIOTrackingCallSiteBTs,
587e6231be0SApple OSS Distributions 			    NULL, &btuinfo);
588bb611c8fSApple OSS Distributions 			assert(userCount <= kIOTrackingCallSiteBTs);
589e6231be0SApple OSS Distributions 			btinfo = btuinfo.btui_info;
590bb611c8fSApple OSS Distributions 			crc = fasthash32(&btUser[0], userCount * sizeof(bt[0]), crc);
591bb611c8fSApple OSS Distributions 		}
592bb611c8fSApple OSS Distributions 	}
593bb611c8fSApple OSS Distributions 
5940f3703acSApple OSS Distributions 	IOTRecursiveLockLock(&queue->lock);
59588cc0b97SApple OSS Distributions 	que = &queue->sites[crc % queue->numSiteQs];
59688cc0b97SApple OSS Distributions 	queue_iterate(que, site, IOTrackingCallSite *, link)
5970f3703acSApple OSS Distributions 	{
598a5e72196SApple OSS Distributions 		if (tag != site->tag) {
599a5e72196SApple OSS Distributions 			continue;
600a5e72196SApple OSS Distributions 		}
601bb611c8fSApple OSS Distributions 		if (user && (pid != site->user[0].pid)) {
602bb611c8fSApple OSS Distributions 			continue;
603bb611c8fSApple OSS Distributions 		}
604a5e72196SApple OSS Distributions 		if (crc == site->crc) {
605a5e72196SApple OSS Distributions 			break;
606a5e72196SApple OSS Distributions 		}
6070f3703acSApple OSS Distributions 	}
6080f3703acSApple OSS Distributions 
609a5e72196SApple OSS Distributions 	if (queue_end(que, (queue_entry_t) site)) {
610bb611c8fSApple OSS Distributions 		if (user) {
611e6231be0SApple OSS Distributions 			site = &kalloc_type(IOTrackingCallSiteWithUser,
612e6231be0SApple OSS Distributions 			    Z_WAITOK_ZERO_NOFAIL)->site;
613e6231be0SApple OSS Distributions 		} else {
614e6231be0SApple OSS Distributions 			site = kalloc_type(IOTrackingCallSite,
615e6231be0SApple OSS Distributions 			    Z_WAITOK_ZERO_NOFAIL);
616bb611c8fSApple OSS Distributions 		}
6170f3703acSApple OSS Distributions 
6180f3703acSApple OSS Distributions 		queue_init(&site->instances);
6195c2921b0SApple OSS Distributions 		site->addresses  = NULL;
6200f3703acSApple OSS Distributions 		site->queue      = queue;
6210f3703acSApple OSS Distributions 		site->crc        = crc;
62288cc0b97SApple OSS Distributions 		site->count      = 0;
62376e12aa3SApple OSS Distributions 		site->tag        = tag;
62488cc0b97SApple OSS Distributions 		memset(&site->size[0], 0, sizeof(site->size));
62588cc0b97SApple OSS Distributions 		bcopy(&bt[1], &site->bt[0], num * sizeof(site->bt[0]));
6260f3703acSApple OSS Distributions 		assert(num <= kIOTrackingCallSiteBTs);
62788cc0b97SApple OSS Distributions 		bzero(&site->bt[num], (kIOTrackingCallSiteBTs - num) * sizeof(site->bt[0]));
628bb611c8fSApple OSS Distributions 		if (user) {
629bb611c8fSApple OSS Distributions 			bcopy(&btUser[0], &site->user[0].bt[0], userCount * sizeof(site->user[0].bt[0]));
630bb611c8fSApple OSS Distributions 			assert(userCount <= kIOTrackingCallSiteBTs);
631bb611c8fSApple OSS Distributions 			bzero(&site->user[0].bt[userCount], (kIOTrackingCallSiteBTs - userCount) * sizeof(site->user[0].bt[0]));
632bb611c8fSApple OSS Distributions 			site->user[0].pid  = pid;
633e6231be0SApple OSS Distributions 			site->user[0].user32 = !(btinfo & BTI_64_BIT);
634bb611c8fSApple OSS Distributions 			static_assert(kIOTrackingCallSiteBTs <= UINT8_MAX);
635bb611c8fSApple OSS Distributions 			site->user[0].userCount = ((uint8_t) userCount);
636bb611c8fSApple OSS Distributions 		}
63788cc0b97SApple OSS Distributions 		queue_enter_first(que, site, IOTrackingCallSite *, link);
6380f3703acSApple OSS Distributions 		queue->siteCount++;
6390f3703acSApple OSS Distributions 	}
6400f3703acSApple OSS Distributions 
641a5e72196SApple OSS Distributions 	if (address) {
6425c2921b0SApple OSS Distributions 		IOTrackingAddress * memAddr = (typeof(memAddr))mem;
6435c2921b0SApple OSS Distributions 		uint32_t hashIdx;
6445c2921b0SApple OSS Distributions 
6455c2921b0SApple OSS Distributions 		if (NULL == site->addresses) {
6465c2921b0SApple OSS Distributions 			site->addresses = kalloc_type(IOTracking *, queue->numSiteQs, Z_WAITOK_ZERO_NOFAIL);
6475c2921b0SApple OSS Distributions 			for (hashIdx = 0; hashIdx < queue->numSiteQs; hashIdx++) {
6485c2921b0SApple OSS Distributions 				site->addresses[hashIdx] = (IOTracking *) &site->instances;
6490f3703acSApple OSS Distributions 			}
6505c2921b0SApple OSS Distributions 		}
6515c2921b0SApple OSS Distributions 		hashIdx = atop(memAddr->address) % queue->numSiteQs;
6525c2921b0SApple OSS Distributions 		if (queue_end(&site->instances, (queue_entry_t)site->addresses[hashIdx])) {
6535c2921b0SApple OSS Distributions 			queue_enter/*last*/ (&site->instances, mem, IOTracking *, link);
6545c2921b0SApple OSS Distributions 		} else {
6555c2921b0SApple OSS Distributions 			queue_insert_before(&site->instances, mem, site->addresses[hashIdx], IOTracking *, link);
6565c2921b0SApple OSS Distributions 		}
6575c2921b0SApple OSS Distributions 		site->addresses[hashIdx] = mem;
658a5e72196SApple OSS Distributions 	} else {
659a5e72196SApple OSS Distributions 		queue_enter_first(&site->instances, mem, IOTracking *, link);
660a5e72196SApple OSS Distributions 	}
6610f3703acSApple OSS Distributions 
6620f3703acSApple OSS Distributions 	mem->site      = site;
66388cc0b97SApple OSS Distributions 	site->size[0] += size;
66488cc0b97SApple OSS Distributions 	site->count++;
6650f3703acSApple OSS Distributions 
6660f3703acSApple OSS Distributions 	IOTRecursiveLockUnlock(&queue->lock);
6670f3703acSApple OSS Distributions }
6680f3703acSApple OSS Distributions 
6690f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
6700f3703acSApple OSS Distributions 
6715c2921b0SApple OSS Distributions static void
IOTrackingRemoveInternal(IOTrackingQueue * queue,IOTracking * mem,size_t size,uint32_t addressIdx)6725c2921b0SApple OSS Distributions IOTrackingRemoveInternal(IOTrackingQueue * queue, IOTracking * mem, size_t size, uint32_t addressIdx)
6730f3703acSApple OSS Distributions {
6745c2921b0SApple OSS Distributions 	IOTrackingCallSite * site;
6755c2921b0SApple OSS Distributions 	IOTrackingAddress  * nextAddress;
6765c2921b0SApple OSS Distributions 
677a5e72196SApple OSS Distributions 	if (!mem->link.next) {
678a5e72196SApple OSS Distributions 		return;
679a5e72196SApple OSS Distributions 	}
6800f3703acSApple OSS Distributions 
6810f3703acSApple OSS Distributions 	IOTRecursiveLockLock(&queue->lock);
682a5e72196SApple OSS Distributions 	if (mem->link.next) {
6830f3703acSApple OSS Distributions 		assert(mem->site);
6845c2921b0SApple OSS Distributions 		site = mem->site;
6850f3703acSApple OSS Distributions 
6865c2921b0SApple OSS Distributions 		if ((-1U != addressIdx) && (mem == site->addresses[addressIdx])) {
6875c2921b0SApple OSS Distributions 			nextAddress = (IOTrackingAddress *) queue_next(&mem->link);
6885c2921b0SApple OSS Distributions 			if (!queue_end(&site->instances, &nextAddress->tracking.link)
6895c2921b0SApple OSS Distributions 			    && (addressIdx != (atop(nextAddress->address) % queue->numSiteQs))) {
6905c2921b0SApple OSS Distributions 				nextAddress = (IOTrackingAddress *) &site->instances;
691a5e72196SApple OSS Distributions 			}
6925c2921b0SApple OSS Distributions 			site->addresses[addressIdx] = &nextAddress->tracking;
6935c2921b0SApple OSS Distributions 		}
6945c2921b0SApple OSS Distributions 
6950f3703acSApple OSS Distributions 		remque(&mem->link);
6965c2921b0SApple OSS Distributions 		assert(site->count);
6975c2921b0SApple OSS Distributions 		site->count--;
6985c2921b0SApple OSS Distributions 		assert(site->size[0] >= size);
6995c2921b0SApple OSS Distributions 		site->size[0] -= size;
7005c2921b0SApple OSS Distributions 		if (!site->count) {
7015c2921b0SApple OSS Distributions 			assert(queue_empty(&site->instances));
7025c2921b0SApple OSS Distributions 			assert(!site->size[0]);
7035c2921b0SApple OSS Distributions 			assert(!site->size[1]);
7040f3703acSApple OSS Distributions 
7055c2921b0SApple OSS Distributions 			remque(&site->link);
7060f3703acSApple OSS Distributions 			assert(queue->siteCount);
7070f3703acSApple OSS Distributions 			queue->siteCount--;
7085c2921b0SApple OSS Distributions 			IOTrackingFreeCallSite(queue->type, &site);
7090f3703acSApple OSS Distributions 		}
71076e12aa3SApple OSS Distributions 		mem->site = NULL;
71188cc0b97SApple OSS Distributions 	}
7120f3703acSApple OSS Distributions 	IOTRecursiveLockUnlock(&queue->lock);
7130f3703acSApple OSS Distributions }
7140f3703acSApple OSS Distributions 
7150f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
7160f3703acSApple OSS Distributions 
7170f3703acSApple OSS Distributions void
IOTrackingRemove(IOTrackingQueue * queue,IOTracking * mem,size_t size)7185c2921b0SApple OSS Distributions IOTrackingRemove(IOTrackingQueue * queue, IOTracking * mem, size_t size)
7195c2921b0SApple OSS Distributions {
7205c2921b0SApple OSS Distributions 	return IOTrackingRemoveInternal(queue, mem, size, -1U);
7215c2921b0SApple OSS Distributions }
7225c2921b0SApple OSS Distributions 
7235c2921b0SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
7245c2921b0SApple OSS Distributions 
7255c2921b0SApple OSS Distributions void
IOTrackingRemoveAddress(IOTrackingQueue * queue,IOTrackingAddress * mem,size_t size)7265c2921b0SApple OSS Distributions IOTrackingRemoveAddress(IOTrackingQueue * queue, IOTrackingAddress * mem, size_t size)
7275c2921b0SApple OSS Distributions {
7285c2921b0SApple OSS Distributions 	uint32_t addressIdx;
7295c2921b0SApple OSS Distributions 	uint64_t address;
7305c2921b0SApple OSS Distributions 
7315c2921b0SApple OSS Distributions 	address = mem->address;
7325c2921b0SApple OSS Distributions 	addressIdx = atop(address) % queue->numSiteQs;
7335c2921b0SApple OSS Distributions 
7345c2921b0SApple OSS Distributions 	return IOTrackingRemoveInternal(queue, &mem->tracking, size, addressIdx);
7355c2921b0SApple OSS Distributions }
7365c2921b0SApple OSS Distributions 
7375c2921b0SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
7385c2921b0SApple OSS Distributions 
7395c2921b0SApple OSS Distributions void
IOTrackingAlloc(IOTrackingQueue * queue,uintptr_t address,size_t size)7400f3703acSApple OSS Distributions IOTrackingAlloc(IOTrackingQueue * queue, uintptr_t address, size_t size)
7410f3703acSApple OSS Distributions {
7420f3703acSApple OSS Distributions 	IOTrackingAddress * tracking;
7430f3703acSApple OSS Distributions 
744a5e72196SApple OSS Distributions 	if (!queue->captureOn) {
745a5e72196SApple OSS Distributions 		return;
746a5e72196SApple OSS Distributions 	}
747a5e72196SApple OSS Distributions 	if (size < queue->minCaptureSize) {
748a5e72196SApple OSS Distributions 		return;
749a5e72196SApple OSS Distributions 	}
7500f3703acSApple OSS Distributions 
7510f3703acSApple OSS Distributions 	address = ~address;
752e6231be0SApple OSS Distributions 	tracking = kalloc_type(IOTrackingAddress, (zalloc_flags_t)(Z_WAITOK | Z_ZERO));
7530f3703acSApple OSS Distributions 	IOTrackingAddressFlags(tracking) |= kTrackingAddressFlagAllocated;
7540f3703acSApple OSS Distributions 	tracking->address = address;
7550f3703acSApple OSS Distributions 	tracking->size    = size;
7560f3703acSApple OSS Distributions 
75776e12aa3SApple OSS Distributions 	IOTrackingAdd(queue, &tracking->tracking, size, true, VM_KERN_MEMORY_NONE);
7580f3703acSApple OSS Distributions }
7590f3703acSApple OSS Distributions 
7600f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
7610f3703acSApple OSS Distributions 
7620f3703acSApple OSS Distributions void
IOTrackingFree(IOTrackingQueue * queue,uintptr_t address,size_t size)7630f3703acSApple OSS Distributions IOTrackingFree(IOTrackingQueue * queue, uintptr_t address, size_t size)
7640f3703acSApple OSS Distributions {
7650f3703acSApple OSS Distributions 	IOTrackingCallSite * site;
7660f3703acSApple OSS Distributions 	IOTrackingAddress  * tracking;
7675c2921b0SApple OSS Distributions 	IOTrackingAddress  * nextAddress;
7685c2921b0SApple OSS Distributions 	uint32_t             idx, hashIdx;
7690f3703acSApple OSS Distributions 	bool                 done;
7700f3703acSApple OSS Distributions 
7710f3703acSApple OSS Distributions 	address = ~address;
7720f3703acSApple OSS Distributions 	IOTRecursiveLockLock(&queue->lock);
7735c2921b0SApple OSS Distributions 
7745c2921b0SApple OSS Distributions 	hashIdx = atop(address) % queue->numSiteQs;
7755c2921b0SApple OSS Distributions 
7760f3703acSApple OSS Distributions 	done = false;
777a5e72196SApple OSS Distributions 	for (idx = 0; idx < queue->numSiteQs; idx++) {
77888cc0b97SApple OSS Distributions 		queue_iterate(&queue->sites[idx], site, IOTrackingCallSite *, link)
7790f3703acSApple OSS Distributions 		{
7805c2921b0SApple OSS Distributions 			if (!site->addresses) {
7815c2921b0SApple OSS Distributions 				continue;
7825c2921b0SApple OSS Distributions 			}
7835c2921b0SApple OSS Distributions 			tracking = (IOTrackingAddress *) site->addresses[hashIdx];
784a5e72196SApple OSS Distributions 			while (!queue_end(&site->instances, &tracking->tracking.link)) {
7855c2921b0SApple OSS Distributions 				nextAddress = (IOTrackingAddress *) queue_next(&tracking->tracking.link);
7865c2921b0SApple OSS Distributions 				if (!queue_end(&site->instances, &nextAddress->tracking.link)
7875c2921b0SApple OSS Distributions 				    && (hashIdx != (atop(nextAddress->address) % queue->numSiteQs))) {
7885c2921b0SApple OSS Distributions 					nextAddress = (IOTrackingAddress *) &site->instances;
7895c2921b0SApple OSS Distributions 				}
790a5e72196SApple OSS Distributions 				if ((done = (address == tracking->address))) {
7915c2921b0SApple OSS Distributions 					if (tracking == (IOTrackingAddress *) site->addresses[hashIdx]) {
7925c2921b0SApple OSS Distributions 						site->addresses[hashIdx] = &nextAddress->tracking;
7935c2921b0SApple OSS Distributions 					}
7945c2921b0SApple OSS Distributions 					IOTrackingRemoveInternal(queue, &tracking->tracking, size, -1U);
795e6231be0SApple OSS Distributions 					kfree_type(IOTrackingAddress, tracking);
796a5e72196SApple OSS Distributions 					break;
7970f3703acSApple OSS Distributions 				}
7985c2921b0SApple OSS Distributions 				tracking = nextAddress;
7990f3703acSApple OSS Distributions 			}
800a5e72196SApple OSS Distributions 			if (done) {
801a5e72196SApple OSS Distributions 				break;
8020f3703acSApple OSS Distributions 			}
803a5e72196SApple OSS Distributions 		}
804a5e72196SApple OSS Distributions 		if (done) {
805a5e72196SApple OSS Distributions 			break;
806a5e72196SApple OSS Distributions 		}
80788cc0b97SApple OSS Distributions 	}
8080f3703acSApple OSS Distributions 	IOTRecursiveLockUnlock(&queue->lock);
8090f3703acSApple OSS Distributions }
8100f3703acSApple OSS Distributions 
811e7776783SApple OSS Distributions static void
IOTrackingFreeCallSite(uint32_t type,IOTrackingCallSite ** pSite)8125c2921b0SApple OSS Distributions IOTrackingFreeCallSite(uint32_t type, IOTrackingCallSite ** pSite)
813e7776783SApple OSS Distributions {
8145c2921b0SApple OSS Distributions 	IOTrackingCallSite * site;
815e7776783SApple OSS Distributions 	void ** ptr;
816e7776783SApple OSS Distributions 
8175c2921b0SApple OSS Distributions 	site = *pSite;
8185c2921b0SApple OSS Distributions 	kfree_type(IOTracking *, site->queue->numSiteQs, site->addresses);
8195c2921b0SApple OSS Distributions 
8205c2921b0SApple OSS Distributions 	ptr = reinterpret_cast<void **>(pSite);
821e7776783SApple OSS Distributions 	if (kIOTrackingQueueTypeUser & type) {
822e7776783SApple OSS Distributions 		kfree_type(IOTrackingCallSiteWithUser, *ptr);
823e7776783SApple OSS Distributions 	} else {
824e7776783SApple OSS Distributions 		kfree_type(IOTrackingCallSite, *ptr);
825e7776783SApple OSS Distributions 	}
826e7776783SApple OSS Distributions }
827e7776783SApple OSS Distributions 
8280f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
8290f3703acSApple OSS Distributions 
8300f3703acSApple OSS Distributions void
IOTrackingAccumSize(IOTrackingQueue * queue,IOTracking * mem,size_t size)8310f3703acSApple OSS Distributions IOTrackingAccumSize(IOTrackingQueue * queue, IOTracking * mem, size_t size)
8320f3703acSApple OSS Distributions {
8330f3703acSApple OSS Distributions 	IOTRecursiveLockLock(&queue->lock);
834a5e72196SApple OSS Distributions 	if (mem->link.next) {
8350f3703acSApple OSS Distributions 		assert(mem->site);
83688cc0b97SApple OSS Distributions 		assert((size > 0) || (mem->site->size[1] >= -size));
83788cc0b97SApple OSS Distributions 		mem->site->size[1] += size;
838a5e72196SApple OSS Distributions 	}
839a5e72196SApple OSS Distributions 	;
8400f3703acSApple OSS Distributions 	IOTRecursiveLockUnlock(&queue->lock);
8410f3703acSApple OSS Distributions }
8420f3703acSApple OSS Distributions 
8430f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
8440f3703acSApple OSS Distributions 
8450f3703acSApple OSS Distributions void
IOTrackingReset(IOTrackingQueue * queue)8460f3703acSApple OSS Distributions IOTrackingReset(IOTrackingQueue * queue)
8470f3703acSApple OSS Distributions {
8480f3703acSApple OSS Distributions 	IOTrackingCallSite * site;
84988cc0b97SApple OSS Distributions 	IOTrackingUser     * user;
8500f3703acSApple OSS Distributions 	IOTracking         * tracking;
8510f3703acSApple OSS Distributions 	IOTrackingAddress  * trackingAddress;
8525c2921b0SApple OSS Distributions 	uint32_t             idx, hashIdx;
8530f3703acSApple OSS Distributions 	bool                 addresses;
8540f3703acSApple OSS Distributions 
8550f3703acSApple OSS Distributions 	IOTRecursiveLockLock(&queue->lock);
856a5e72196SApple OSS Distributions 	for (idx = 0; idx < queue->numSiteQs; idx++) {
857a5e72196SApple OSS Distributions 		while (!queue_empty(&queue->sites[idx])) {
858a5e72196SApple OSS Distributions 			if (kIOTrackingQueueTypeMap & queue->type) {
85988cc0b97SApple OSS Distributions 				queue_remove_first(&queue->sites[idx], user, IOTrackingUser *, link);
86088cc0b97SApple OSS Distributions 				user->link.next = user->link.prev = NULL;
861a5e72196SApple OSS Distributions 			} else {
86288cc0b97SApple OSS Distributions 				queue_remove_first(&queue->sites[idx], site, IOTrackingCallSite *, link);
8630f3703acSApple OSS Distributions 				addresses = false;
864a5e72196SApple OSS Distributions 				while (!queue_empty(&site->instances)) {
8650f3703acSApple OSS Distributions 					queue_remove_first(&site->instances, tracking, IOTracking *, link);
8665c2921b0SApple OSS Distributions 					if (site->addresses) {
8675c2921b0SApple OSS Distributions 						for (hashIdx = 0; !addresses && (hashIdx < queue->numSiteQs); hashIdx++) {
8685c2921b0SApple OSS Distributions 							if (tracking == site->addresses[hashIdx]) {
869a5e72196SApple OSS Distributions 								addresses = true;
870a5e72196SApple OSS Distributions 							}
8715c2921b0SApple OSS Distributions 						}
8725c2921b0SApple OSS Distributions 					}
873a5e72196SApple OSS Distributions 					if (addresses) {
8740f3703acSApple OSS Distributions 						trackingAddress = (typeof(trackingAddress))tracking;
875a5e72196SApple OSS Distributions 						if (kTrackingAddressFlagAllocated & IOTrackingAddressFlags(trackingAddress)) {
876e7776783SApple OSS Distributions 							kfree_type(IOTrackingAddress, trackingAddress);
8770f3703acSApple OSS Distributions 						}
8780f3703acSApple OSS Distributions 					}
8790f3703acSApple OSS Distributions 				}
880e7776783SApple OSS Distributions 				IOTrackingFreeCallSite(queue->type, &site);
8810f3703acSApple OSS Distributions 			}
88288cc0b97SApple OSS Distributions 		}
88388cc0b97SApple OSS Distributions 	}
8840f3703acSApple OSS Distributions 	queue->siteCount = 0;
8850f3703acSApple OSS Distributions 	IOTRecursiveLockUnlock(&queue->lock);
8860f3703acSApple OSS Distributions }
8870f3703acSApple OSS Distributions 
8880f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
8890f3703acSApple OSS Distributions 
8900f3703acSApple OSS Distributions static int
IOTrackingCallSiteInfoCompare(const void * left,const void * right)8910f3703acSApple OSS Distributions IOTrackingCallSiteInfoCompare(const void * left, const void * right)
8920f3703acSApple OSS Distributions {
8930f3703acSApple OSS Distributions 	IOTrackingCallSiteInfo * l = (typeof(l))left;
8940f3703acSApple OSS Distributions 	IOTrackingCallSiteInfo * r = (typeof(r))right;
8950f3703acSApple OSS Distributions 	size_t                   lsize, rsize;
8960f3703acSApple OSS Distributions 
8970f3703acSApple OSS Distributions 	rsize = r->size[0] + r->size[1];
8980f3703acSApple OSS Distributions 	lsize = l->size[0] + l->size[1];
8990f3703acSApple OSS Distributions 
900a5e72196SApple OSS Distributions 	return (rsize > lsize) ? 1 : ((rsize == lsize) ? 0 : -1);
9010f3703acSApple OSS Distributions }
9020f3703acSApple OSS Distributions 
9030f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
9040f3703acSApple OSS Distributions 
9050f3703acSApple OSS Distributions static int
IOTrackingAddressCompare(const void * left,const void * right)9060f3703acSApple OSS Distributions IOTrackingAddressCompare(const void * left, const void * right)
9070f3703acSApple OSS Distributions {
9080f3703acSApple OSS Distributions 	IOTracking * instance;
9090f3703acSApple OSS Distributions 	uintptr_t    inst, laddr, raddr;
9100f3703acSApple OSS Distributions 
9110f3703acSApple OSS Distributions 	inst = ((typeof(inst) *)left)[0];
91288cc0b97SApple OSS Distributions 	instance = (typeof(instance))INSTANCE_GET(inst);
913a5e72196SApple OSS Distributions 	if (kInstanceFlagAddress & inst) {
914a5e72196SApple OSS Distributions 		laddr = ~((IOTrackingAddress *)instance)->address;
915a5e72196SApple OSS Distributions 	} else {
916a5e72196SApple OSS Distributions 		laddr = (uintptr_t) (instance + 1);
917a5e72196SApple OSS Distributions 	}
9180f3703acSApple OSS Distributions 
9190f3703acSApple OSS Distributions 	inst = ((typeof(inst) *)right)[0];
9200f3703acSApple OSS Distributions 	instance = (typeof(instance))(inst & ~kInstanceFlags);
921a5e72196SApple OSS Distributions 	if (kInstanceFlagAddress & inst) {
922a5e72196SApple OSS Distributions 		raddr = ~((IOTrackingAddress *)instance)->address;
923a5e72196SApple OSS Distributions 	} else {
924a5e72196SApple OSS Distributions 		raddr = (uintptr_t) (instance + 1);
925a5e72196SApple OSS Distributions 	}
9260f3703acSApple OSS Distributions 
927a5e72196SApple OSS Distributions 	return (laddr > raddr) ? 1 : ((laddr == raddr) ? 0 : -1);
9280f3703acSApple OSS Distributions }
9290f3703acSApple OSS Distributions 
93088cc0b97SApple OSS Distributions 
93188cc0b97SApple OSS Distributions static int
IOTrackingZoneElementCompare(const void * left,const void * right)93288cc0b97SApple OSS Distributions IOTrackingZoneElementCompare(const void * left, const void * right)
93388cc0b97SApple OSS Distributions {
93488cc0b97SApple OSS Distributions 	uintptr_t    inst, laddr, raddr;
93588cc0b97SApple OSS Distributions 
93688cc0b97SApple OSS Distributions 	inst = ((typeof(inst) *)left)[0];
93788cc0b97SApple OSS Distributions 	laddr = INSTANCE_PUT(inst);
93888cc0b97SApple OSS Distributions 	inst = ((typeof(inst) *)right)[0];
93988cc0b97SApple OSS Distributions 	raddr = INSTANCE_PUT(inst);
94088cc0b97SApple OSS Distributions 
941a5e72196SApple OSS Distributions 	return (laddr > raddr) ? 1 : ((laddr == raddr) ? 0 : -1);
94288cc0b97SApple OSS Distributions }
94388cc0b97SApple OSS Distributions 
94488cc0b97SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
94588cc0b97SApple OSS Distributions 
94688cc0b97SApple OSS Distributions static void
CopyOutBacktraces(IOTrackingCallSite * site,IOTrackingCallSiteInfo * siteInfo)947bb611c8fSApple OSS Distributions CopyOutBacktraces(IOTrackingCallSite * site, IOTrackingCallSiteInfo * siteInfo)
94888cc0b97SApple OSS Distributions {
94988cc0b97SApple OSS Distributions 	uint32_t j;
95088cc0b97SApple OSS Distributions 	mach_vm_address_t bt, btEntry;
95188cc0b97SApple OSS Distributions 
95288cc0b97SApple OSS Distributions 	btEntry = site->queue->btEntry;
953a5e72196SApple OSS Distributions 	for (j = 0; j < kIOTrackingCallSiteBTs; j++) {
95488cc0b97SApple OSS Distributions 		bt = site->bt[j];
95588cc0b97SApple OSS Distributions 		if (btEntry
956a5e72196SApple OSS Distributions 		    && (!bt || (j == (kIOTrackingCallSiteBTs - 1)))) {
95788cc0b97SApple OSS Distributions 			bt = btEntry;
95888cc0b97SApple OSS Distributions 			btEntry = 0;
95988cc0b97SApple OSS Distributions 		}
96088cc0b97SApple OSS Distributions 		siteInfo->bt[0][j] = VM_KERNEL_UNSLIDE(bt);
96188cc0b97SApple OSS Distributions 	}
962bb611c8fSApple OSS Distributions 
963bb611c8fSApple OSS Distributions 	siteInfo->btPID = 0;
964bb611c8fSApple OSS Distributions 	if (kIOTrackingQueueTypeUser & site->queue->type) {
965bb611c8fSApple OSS Distributions 		siteInfo->btPID = site->user[0].pid;
966bb611c8fSApple OSS Distributions 		uint32_t * bt32 = (typeof(bt32))((void *) &site->user[0].bt[0]);
967bb611c8fSApple OSS Distributions 		uint64_t * bt64 = (typeof(bt64))((void *) &site->user[0].bt[0]);
968bb611c8fSApple OSS Distributions 		for (uint32_t j = 0; j < kIOTrackingCallSiteBTs; j++) {
969bb611c8fSApple OSS Distributions 			if (j >= site->user[0].userCount) {
970bb611c8fSApple OSS Distributions 				siteInfo->bt[1][j] = 0;
971bb611c8fSApple OSS Distributions 			} else if (site->user[0].user32) {
972bb611c8fSApple OSS Distributions 				siteInfo->bt[1][j] = bt32[j];
973bb611c8fSApple OSS Distributions 			} else {
974bb611c8fSApple OSS Distributions 				siteInfo->bt[1][j] = bt64[j];
975bb611c8fSApple OSS Distributions 			}
976bb611c8fSApple OSS Distributions 		}
977bb611c8fSApple OSS Distributions 	}
97888cc0b97SApple OSS Distributions }
97988cc0b97SApple OSS Distributions 
9800f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
9810f3703acSApple OSS Distributions 
9820f3703acSApple OSS Distributions static void
IOTrackingLeakScan(void * refcon)9830f3703acSApple OSS Distributions IOTrackingLeakScan(void * refcon)
9840f3703acSApple OSS Distributions {
9850f3703acSApple OSS Distributions 	IOTrackingLeaksRef * ref = (typeof(ref))refcon;
9860f3703acSApple OSS Distributions 	uintptr_t          * instances;
9870f3703acSApple OSS Distributions 	IOTracking         * instance;
9880f3703acSApple OSS Distributions 	uint64_t             vaddr, vincr;
9890f3703acSApple OSS Distributions 	ppnum_t              ppn;
99088cc0b97SApple OSS Distributions 	uintptr_t            ptr, addr, vphysaddr, inst;
99176e12aa3SApple OSS Distributions 	size_t               size, origsize;
9920f3703acSApple OSS Distributions 	uint32_t             baseIdx, lim, ptrIdx, count;
9930f3703acSApple OSS Distributions 	boolean_t            is;
99488cc0b97SApple OSS Distributions 	AbsoluteTime         deadline;
9950f3703acSApple OSS Distributions 
9960f3703acSApple OSS Distributions 	instances       = ref->instances;
9970f3703acSApple OSS Distributions 	count           = ref->count;
99876e12aa3SApple OSS Distributions 	size = origsize = ref->zoneSize;
9990f3703acSApple OSS Distributions 
10005c2921b0SApple OSS Distributions 	if (gIOTrackingLeakScanCallback) {
10015c2921b0SApple OSS Distributions 		gIOTrackingLeakScanCallback(kIOTrackingLeakScanStart);
10025c2921b0SApple OSS Distributions 	}
10035c2921b0SApple OSS Distributions 
100488cc0b97SApple OSS Distributions 	for (deadline = 0, vaddr = VM_MIN_KERNEL_AND_KEXT_ADDRESS;
100588cc0b97SApple OSS Distributions 	    ;
1006a5e72196SApple OSS Distributions 	    vaddr += vincr) {
1007a5e72196SApple OSS Distributions 		if ((mach_absolute_time() > deadline) || (vaddr >= VM_MAX_KERNEL_ADDRESS)) {
1008a5e72196SApple OSS Distributions 			if (deadline) {
10095c2921b0SApple OSS Distributions #if SCHED_HYGIENE_DEBUG
10105c2921b0SApple OSS Distributions 				if (is) {
10115c2921b0SApple OSS Distributions 					// Reset the interrupt timeout to avoid panics
10125c2921b0SApple OSS Distributions 					ml_spin_debug_clear_self();
10135c2921b0SApple OSS Distributions 				}
10145c2921b0SApple OSS Distributions #endif /* SCHED_HYGIENE_DEBUG */
101588cc0b97SApple OSS Distributions 				ml_set_interrupts_enabled(is);
101688cc0b97SApple OSS Distributions 				IODelay(10);
101788cc0b97SApple OSS Distributions 			}
1018a5e72196SApple OSS Distributions 			if (vaddr >= VM_MAX_KERNEL_ADDRESS) {
1019a5e72196SApple OSS Distributions 				break;
1020a5e72196SApple OSS Distributions 			}
10210f3703acSApple OSS Distributions 			is = ml_set_interrupts_enabled(false);
102288cc0b97SApple OSS Distributions 			clock_interval_to_deadline(10, kMillisecondScale, &deadline);
102388cc0b97SApple OSS Distributions 		}
10240f3703acSApple OSS Distributions 
102588cc0b97SApple OSS Distributions 		ppn = kernel_pmap_present_mapping(vaddr, &vincr, &vphysaddr);
10260f3703acSApple OSS Distributions 		// check noencrypt to avoid VM structs (map entries) with pointers
1027a5e72196SApple OSS Distributions 		if (ppn && (!pmap_valid_page(ppn) || (!ref->zoneSize && pmap_is_noencrypt(ppn)))) {
1028a5e72196SApple OSS Distributions 			ppn = 0;
1029a5e72196SApple OSS Distributions 		}
1030a5e72196SApple OSS Distributions 		if (!ppn) {
1031a5e72196SApple OSS Distributions 			continue;
1032a5e72196SApple OSS Distributions 		}
10330f3703acSApple OSS Distributions 
1034a5e72196SApple OSS Distributions 		for (ptrIdx = 0; ptrIdx < (page_size / sizeof(uintptr_t)); ptrIdx++) {
103588cc0b97SApple OSS Distributions 			ptr = ((uintptr_t *)vphysaddr)[ptrIdx];
1036bb611c8fSApple OSS Distributions #if defined(HAS_APPLE_PAC)
1037bb611c8fSApple OSS Distributions 			// strip possible ptrauth signature from candidate data pointer
1038bb611c8fSApple OSS Distributions 			ptr = (uintptr_t)ptrauth_strip((void*)ptr, ptrauth_key_process_independent_data);
1039bb611c8fSApple OSS Distributions #endif /* defined(HAS_APPLE_PAC) */
10400f3703acSApple OSS Distributions 
1041a5e72196SApple OSS Distributions 			for (lim = count, baseIdx = 0; lim; lim >>= 1) {
10420f3703acSApple OSS Distributions 				inst = instances[baseIdx + (lim >> 1)];
104388cc0b97SApple OSS Distributions 				instance = (typeof(instance))INSTANCE_GET(inst);
104488cc0b97SApple OSS Distributions 
1045a5e72196SApple OSS Distributions 				if (ref->zoneSize) {
104688cc0b97SApple OSS Distributions 					addr = INSTANCE_PUT(inst) & ~kInstanceFlags;
1047a5e72196SApple OSS Distributions 				} else if (kInstanceFlagAddress & inst) {
10480f3703acSApple OSS Distributions 					addr            = ~((IOTrackingAddress *)instance)->address;
104976e12aa3SApple OSS Distributions 					origsize = size = ((IOTrackingAddress *)instance)->size;
1050a5e72196SApple OSS Distributions 					if (!size) {
1051a5e72196SApple OSS Distributions 						size = 1;
10520f3703acSApple OSS Distributions 					}
1053a5e72196SApple OSS Distributions 				} else {
10540f3703acSApple OSS Distributions 					addr            = (uintptr_t) (instance + 1);
105576e12aa3SApple OSS Distributions 					origsize = size = instance->site->queue->allocSize;
10560f3703acSApple OSS Distributions 				}
105788cc0b97SApple OSS Distributions 				if ((ptr >= addr) && (ptr < (addr + size))
105888cc0b97SApple OSS Distributions 
105988cc0b97SApple OSS Distributions 				    && (((vaddr + ptrIdx * sizeof(uintptr_t)) < addr)
1060a5e72196SApple OSS Distributions 				    || ((vaddr + ptrIdx * sizeof(uintptr_t)) >= (addr + size)))) {
1061a5e72196SApple OSS Distributions 					if (!(kInstanceFlagReferenced & inst)) {
10620f3703acSApple OSS Distributions 						inst |= kInstanceFlagReferenced;
10630f3703acSApple OSS Distributions 						instances[baseIdx + (lim >> 1)] = inst;
10640f3703acSApple OSS Distributions 						ref->found++;
1065a5e72196SApple OSS Distributions 						if (!origsize) {
1066a5e72196SApple OSS Distributions 							ref->foundzlen++;
1067a5e72196SApple OSS Distributions 						}
10680f3703acSApple OSS Distributions 					}
10690f3703acSApple OSS Distributions 					break;
10700f3703acSApple OSS Distributions 				}
1071a5e72196SApple OSS Distributions 				if (ptr > addr) {
10720f3703acSApple OSS Distributions 					// move right
10730f3703acSApple OSS Distributions 					baseIdx += (lim >> 1) + 1;
10740f3703acSApple OSS Distributions 					lim--;
10750f3703acSApple OSS Distributions 				}
10760f3703acSApple OSS Distributions 				// else move left
10770f3703acSApple OSS Distributions 			}
10780f3703acSApple OSS Distributions 		}
10790f3703acSApple OSS Distributions 		ref->bytes += page_size;
10800f3703acSApple OSS Distributions 	}
10815c2921b0SApple OSS Distributions 
10825c2921b0SApple OSS Distributions 	if (gIOTrackingLeakScanCallback) {
10835c2921b0SApple OSS Distributions 		gIOTrackingLeakScanCallback(kIOTrackingLeakScanEnd);
10845c2921b0SApple OSS Distributions 	}
10850f3703acSApple OSS Distributions }
10860f3703acSApple OSS Distributions 
10870f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
10880f3703acSApple OSS Distributions 
108988cc0b97SApple OSS Distributions extern "C" void
zone_leaks_scan(uintptr_t * instances,uint32_t count,uint32_t zoneSize,uint32_t * found)109088cc0b97SApple OSS Distributions zone_leaks_scan(uintptr_t * instances, uint32_t count, uint32_t zoneSize, uint32_t * found)
109188cc0b97SApple OSS Distributions {
109288cc0b97SApple OSS Distributions 	IOTrackingLeaksRef       ref;
109388cc0b97SApple OSS Distributions 	IOTrackingCallSiteInfo   siteInfo;
109488cc0b97SApple OSS Distributions 	uint32_t                 idx;
109588cc0b97SApple OSS Distributions 
109688cc0b97SApple OSS Distributions 	qsort(instances, count, sizeof(*instances), &IOTrackingZoneElementCompare);
109788cc0b97SApple OSS Distributions 
109888cc0b97SApple OSS Distributions 	bzero(&siteInfo, sizeof(siteInfo));
109988cc0b97SApple OSS Distributions 	bzero(&ref, sizeof(ref));
110088cc0b97SApple OSS Distributions 	ref.instances = instances;
110188cc0b97SApple OSS Distributions 	ref.count = count;
110288cc0b97SApple OSS Distributions 	ref.zoneSize = zoneSize;
110388cc0b97SApple OSS Distributions 
1104a5e72196SApple OSS Distributions 	for (idx = 0; idx < 2; idx++) {
110588cc0b97SApple OSS Distributions 		ref.bytes = 0;
110688cc0b97SApple OSS Distributions 		IOTrackingLeakScan(&ref);
110788cc0b97SApple OSS Distributions 		IOLog("leaks(%d) scanned %ld MB, instance count %d, found %d\n", idx, ref.bytes / 1024 / 1024, count, ref.found);
1108a5e72196SApple OSS Distributions 		if (count <= ref.found) {
1109a5e72196SApple OSS Distributions 			break;
1110a5e72196SApple OSS Distributions 		}
111188cc0b97SApple OSS Distributions 	}
111288cc0b97SApple OSS Distributions 
111388cc0b97SApple OSS Distributions 	*found = ref.found;
111488cc0b97SApple OSS Distributions }
111588cc0b97SApple OSS Distributions 
111688cc0b97SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
111788cc0b97SApple OSS Distributions 
11180f3703acSApple OSS Distributions static OSData *
IOTrackingLeaks(LIBKERN_CONSUMED OSData * data)1119a5e72196SApple OSS Distributions IOTrackingLeaks(LIBKERN_CONSUMED OSData * data)
11200f3703acSApple OSS Distributions {
11210f3703acSApple OSS Distributions 	IOTrackingLeaksRef       ref;
112288cc0b97SApple OSS Distributions 	IOTrackingCallSiteInfo   siteInfo;
11230f3703acSApple OSS Distributions 	IOTrackingCallSite     * site;
11240f3703acSApple OSS Distributions 	OSData                 * leakData;
11250f3703acSApple OSS Distributions 	uintptr_t              * instances;
11260f3703acSApple OSS Distributions 	IOTracking             * instance;
11270f3703acSApple OSS Distributions 	uintptr_t                inst;
11280f3703acSApple OSS Distributions 	uint32_t                 count, idx, numSites, dups, siteCount;
11290f3703acSApple OSS Distributions 
1130*8d741a5dSApple OSS Distributions 	/* BEGIN IGNORE CODESTYLE */
1131*8d741a5dSApple OSS Distributions 	__typed_allocators_ignore_push
11320f3703acSApple OSS Distributions 	instances = (typeof(instances))data->getBytesNoCopy();
1133*8d741a5dSApple OSS Distributions 	__typed_allocators_ignore_pop
1134*8d741a5dSApple OSS Distributions 	/* END IGNORE CODESTYLE */
11350f3703acSApple OSS Distributions 	count = (data->getLength() / sizeof(*instances));
11360f3703acSApple OSS Distributions 	qsort(instances, count, sizeof(*instances), &IOTrackingAddressCompare);
11370f3703acSApple OSS Distributions 
113888cc0b97SApple OSS Distributions 	bzero(&siteInfo, sizeof(siteInfo));
11390f3703acSApple OSS Distributions 	bzero(&ref, sizeof(ref));
11400f3703acSApple OSS Distributions 	ref.instances = instances;
11410f3703acSApple OSS Distributions 	ref.count = count;
1142a5e72196SApple OSS Distributions 	for (idx = 0; idx < 2; idx++) {
114388cc0b97SApple OSS Distributions 		ref.bytes = 0;
11440f3703acSApple OSS Distributions 		IOTrackingLeakScan(&ref);
114576e12aa3SApple OSS Distributions 		IOLog("leaks(%d) scanned %ld MB, instance count %d, found %d (zlen %d)\n", idx, ref.bytes / 1024 / 1024, count, ref.found, ref.foundzlen);
1146a5e72196SApple OSS Distributions 		if (count <= ref.found) {
1147a5e72196SApple OSS Distributions 			break;
1148a5e72196SApple OSS Distributions 		}
114988cc0b97SApple OSS Distributions 	}
11500f3703acSApple OSS Distributions 
1151*8d741a5dSApple OSS Distributions 	/* BEGIN IGNORE CODESTYLE */
1152*8d741a5dSApple OSS Distributions 	__typed_allocators_ignore_push
11530f3703acSApple OSS Distributions 	leakData = OSData::withCapacity(128 * sizeof(IOTrackingCallSiteInfo));
1154*8d741a5dSApple OSS Distributions 	__typed_allocators_ignore_pop
1155*8d741a5dSApple OSS Distributions 	/* END IGNORE CODESTYLE */
11560f3703acSApple OSS Distributions 
1157a5e72196SApple OSS Distributions 	for (numSites = 0, idx = 0; idx < count; idx++) {
11580f3703acSApple OSS Distributions 		inst = instances[idx];
1159a5e72196SApple OSS Distributions 		if (kInstanceFlagReferenced & inst) {
1160a5e72196SApple OSS Distributions 			continue;
1161a5e72196SApple OSS Distributions 		}
116288cc0b97SApple OSS Distributions 		instance = (typeof(instance))INSTANCE_GET(inst);
11630f3703acSApple OSS Distributions 		site = instance->site;
11640f3703acSApple OSS Distributions 		instances[numSites] = (uintptr_t) site;
11650f3703acSApple OSS Distributions 		numSites++;
11660f3703acSApple OSS Distributions 	}
11670f3703acSApple OSS Distributions 
1168a5e72196SApple OSS Distributions 	for (idx = 0; idx < numSites; idx++) {
11690f3703acSApple OSS Distributions 		inst = instances[idx];
1170a5e72196SApple OSS Distributions 		if (!inst) {
1171a5e72196SApple OSS Distributions 			continue;
1172a5e72196SApple OSS Distributions 		}
11730f3703acSApple OSS Distributions 		site = (typeof(site))inst;
1174a5e72196SApple OSS Distributions 		for (siteCount = 1, dups = (idx + 1); dups < numSites; dups++) {
1175a5e72196SApple OSS Distributions 			if (instances[dups] == (uintptr_t) site) {
11760f3703acSApple OSS Distributions 				siteCount++;
11770f3703acSApple OSS Distributions 				instances[dups] = 0;
11780f3703acSApple OSS Distributions 			}
11790f3703acSApple OSS Distributions 		}
1180*8d741a5dSApple OSS Distributions 		// leak byte size is reported as:
1181*8d741a5dSApple OSS Distributions 		// (total bytes allocated by the callsite * number of leaked instances)
1182*8d741a5dSApple OSS Distributions 		// divided by (number of allocations by callsite)
118388cc0b97SApple OSS Distributions 		siteInfo.count   = siteCount;
1184*8d741a5dSApple OSS Distributions 		siteInfo.size[0] = (site->size[0] * siteCount) / site->count;
1185*8d741a5dSApple OSS Distributions 		siteInfo.size[1] = (site->size[1] * siteCount) / site->count;
1186bb611c8fSApple OSS Distributions 		CopyOutBacktraces(site, &siteInfo);
1187*8d741a5dSApple OSS Distributions 		__typed_allocators_ignore_push
118888cc0b97SApple OSS Distributions 		leakData->appendBytes(&siteInfo, sizeof(siteInfo));
1189*8d741a5dSApple OSS Distributions 		__typed_allocators_ignore_pop
11900f3703acSApple OSS Distributions 	}
11910f3703acSApple OSS Distributions 	data->release();
11920f3703acSApple OSS Distributions 
1193a5e72196SApple OSS Distributions 	return leakData;
11940f3703acSApple OSS Distributions }
11950f3703acSApple OSS Distributions 
11960f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
11970f3703acSApple OSS Distributions 
11980f3703acSApple OSS Distributions static bool
SkipName(uint32_t options,const char * name,size_t namesLen,const char * names)11990f3703acSApple OSS Distributions SkipName(uint32_t options, const char * name, size_t namesLen, const char * names)
12000f3703acSApple OSS Distributions {
12010f3703acSApple OSS Distributions 	const char * scan;
12020f3703acSApple OSS Distributions 	const char * next;
12030f3703acSApple OSS Distributions 	bool         exclude, found;
12040f3703acSApple OSS Distributions 	size_t       qLen, sLen;
12050f3703acSApple OSS Distributions 
1206a5e72196SApple OSS Distributions 	if (!namesLen || !names) {
1207a5e72196SApple OSS Distributions 		return false;
1208a5e72196SApple OSS Distributions 	}
12090f3703acSApple OSS Distributions 	// <len><name>...<len><name><0>
12100f3703acSApple OSS Distributions 	exclude = (0 != (kIOTrackingExcludeNames & options));
12110f3703acSApple OSS Distributions 	qLen    = strlen(name);
12120f3703acSApple OSS Distributions 	scan    = names;
12130f3703acSApple OSS Distributions 	found   = false;
1214a5e72196SApple OSS Distributions 	do{
12150f3703acSApple OSS Distributions 		sLen = scan[0];
12160f3703acSApple OSS Distributions 		scan++;
12170f3703acSApple OSS Distributions 		next = scan + sLen;
1218a5e72196SApple OSS Distributions 		if (next >= (names + namesLen)) {
1219a5e72196SApple OSS Distributions 			break;
1220a5e72196SApple OSS Distributions 		}
12210f3703acSApple OSS Distributions 		found = ((sLen == qLen) && !strncmp(scan, name, sLen));
12220f3703acSApple OSS Distributions 		scan = next;
1223a5e72196SApple OSS Distributions 	}while (!found && (scan < (names + namesLen)));
12240f3703acSApple OSS Distributions 
1225a5e72196SApple OSS Distributions 	return !(exclude ^ found);
12260f3703acSApple OSS Distributions }
12270f3703acSApple OSS Distributions 
12280f3703acSApple OSS Distributions #endif /* IOTRACKING */
12290f3703acSApple OSS Distributions 
12300f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12310f3703acSApple OSS Distributions 
123276e12aa3SApple OSS Distributions static kern_return_t
IOTrackingDebug(uint32_t selector,uint32_t options,uint64_t value,uint32_t intag,uint32_t inzsize,const char * names,size_t namesLen,size_t size,OSObject ** result)123388cc0b97SApple OSS Distributions IOTrackingDebug(uint32_t selector, uint32_t options, uint64_t value,
123476e12aa3SApple OSS Distributions     uint32_t intag, uint32_t inzsize,
12350f3703acSApple OSS Distributions     const char * names, size_t namesLen,
12360f3703acSApple OSS Distributions     size_t size, OSObject ** result)
12370f3703acSApple OSS Distributions {
12380f3703acSApple OSS Distributions 	kern_return_t            ret;
12390f3703acSApple OSS Distributions 	OSData                 * data;
12400f3703acSApple OSS Distributions 
1241a5e72196SApple OSS Distributions 	if (result) {
1242a5e72196SApple OSS Distributions 		*result = NULL;
1243a5e72196SApple OSS Distributions 	}
1244a5e72196SApple OSS Distributions 	data = NULL;
12450f3703acSApple OSS Distributions 	ret = kIOReturnNotReady;
12460f3703acSApple OSS Distributions 
12470f3703acSApple OSS Distributions #if IOTRACKING
12480f3703acSApple OSS Distributions 
124988cc0b97SApple OSS Distributions 	kern_return_t            kr;
12500f3703acSApple OSS Distributions 	IOTrackingQueue        * queue;
12510f3703acSApple OSS Distributions 	IOTracking             * instance;
12520f3703acSApple OSS Distributions 	IOTrackingCallSite     * site;
125388cc0b97SApple OSS Distributions 	IOTrackingCallSiteInfo   siteInfo;
125488cc0b97SApple OSS Distributions 	IOTrackingUser         * user;
125588cc0b97SApple OSS Distributions 	task_t                   mapTask;
125688cc0b97SApple OSS Distributions 	mach_vm_address_t        mapAddress;
125788cc0b97SApple OSS Distributions 	mach_vm_size_t           mapSize;
125888cc0b97SApple OSS Distributions 	uint32_t                 num, idx, qIdx;
12590f3703acSApple OSS Distributions 	uintptr_t                instFlags;
126088cc0b97SApple OSS Distributions 	proc_t                   proc;
126188cc0b97SApple OSS Distributions 	bool                     addresses;
12620f3703acSApple OSS Distributions 
12630f3703acSApple OSS Distributions 	ret = kIOReturnNotFound;
126488cc0b97SApple OSS Distributions 	proc = NULL;
1265a5e72196SApple OSS Distributions 	if (kIOTrackingGetMappings == selector) {
1266a5e72196SApple OSS Distributions 		if (value != -1ULL) {
1267bb611c8fSApple OSS Distributions 			proc = proc_find((pid_t) value);
1268a5e72196SApple OSS Distributions 			if (!proc) {
1269a5e72196SApple OSS Distributions 				return kIOReturnNotFound;
1270a5e72196SApple OSS Distributions 			}
127188cc0b97SApple OSS Distributions 		}
127288cc0b97SApple OSS Distributions 	}
12730f3703acSApple OSS Distributions 
127488cc0b97SApple OSS Distributions 	bzero(&siteInfo, sizeof(siteInfo));
12750f3703acSApple OSS Distributions 	lck_mtx_lock(gIOTrackingLock);
12760f3703acSApple OSS Distributions 	queue_iterate(&gIOTrackingQ, queue, IOTrackingQueue *, link)
12770f3703acSApple OSS Distributions 	{
1278a5e72196SApple OSS Distributions 		if (SkipName(options, queue->name, namesLen, names)) {
1279a5e72196SApple OSS Distributions 			continue;
1280a5e72196SApple OSS Distributions 		}
12810f3703acSApple OSS Distributions 
1282a5e72196SApple OSS Distributions 		if (!(kIOTracking & gIOKitDebug) && (kIOTrackingQueueTypeAlloc & queue->type)) {
1283a5e72196SApple OSS Distributions 			continue;
1284a5e72196SApple OSS Distributions 		}
128588cc0b97SApple OSS Distributions 
1286a5e72196SApple OSS Distributions 		switch (selector) {
12870f3703acSApple OSS Distributions 		case kIOTrackingResetTracking:
12880f3703acSApple OSS Distributions 		{
12890f3703acSApple OSS Distributions 			IOTrackingReset(queue);
12900f3703acSApple OSS Distributions 			ret = kIOReturnSuccess;
12910f3703acSApple OSS Distributions 			break;
12920f3703acSApple OSS Distributions 		}
12930f3703acSApple OSS Distributions 
12940f3703acSApple OSS Distributions 		case kIOTrackingStartCapture:
12950f3703acSApple OSS Distributions 		case kIOTrackingStopCapture:
12960f3703acSApple OSS Distributions 		{
12970f3703acSApple OSS Distributions 			queue->captureOn = (kIOTrackingStartCapture == selector);
12980f3703acSApple OSS Distributions 			ret = kIOReturnSuccess;
12990f3703acSApple OSS Distributions 			break;
13000f3703acSApple OSS Distributions 		}
13010f3703acSApple OSS Distributions 
13020f3703acSApple OSS Distributions 		case kIOTrackingSetMinCaptureSize:
13030f3703acSApple OSS Distributions 		{
13040f3703acSApple OSS Distributions 			queue->minCaptureSize = size;
13050f3703acSApple OSS Distributions 			ret = kIOReturnSuccess;
13060f3703acSApple OSS Distributions 			break;
13070f3703acSApple OSS Distributions 		}
13080f3703acSApple OSS Distributions 
13090f3703acSApple OSS Distributions 		case kIOTrackingLeaks:
13100f3703acSApple OSS Distributions 		{
1311a5e72196SApple OSS Distributions 			if (!(kIOTrackingQueueTypeAlloc & queue->type)) {
1312a5e72196SApple OSS Distributions 				break;
1313a5e72196SApple OSS Distributions 			}
13140f3703acSApple OSS Distributions 
1315a5e72196SApple OSS Distributions 			if (!data) {
1316*8d741a5dSApple OSS Distributions 				/* BEGIN IGNORE CODESTYLE */
1317*8d741a5dSApple OSS Distributions 				__typed_allocators_ignore_push
1318a5e72196SApple OSS Distributions 				data = OSData::withCapacity(1024 * sizeof(uintptr_t));
1319*8d741a5dSApple OSS Distributions 				__typed_allocators_ignore_pop
1320*8d741a5dSApple OSS Distributions 				/* END IGNORE CODESTYLE */
1321a5e72196SApple OSS Distributions 			}
13220f3703acSApple OSS Distributions 
13230f3703acSApple OSS Distributions 			IOTRecursiveLockLock(&queue->lock);
1324a5e72196SApple OSS Distributions 			for (idx = 0; idx < queue->numSiteQs; idx++) {
132588cc0b97SApple OSS Distributions 				queue_iterate(&queue->sites[idx], site, IOTrackingCallSite *, link)
13260f3703acSApple OSS Distributions 				{
13270f3703acSApple OSS Distributions 					addresses = false;
13280f3703acSApple OSS Distributions 					queue_iterate(&site->instances, instance, IOTracking *, link)
13290f3703acSApple OSS Distributions 					{
13305c2921b0SApple OSS Distributions 						if (site->addresses) {
13315c2921b0SApple OSS Distributions 							for (uint32_t hashIdx = 0; !addresses && (hashIdx < queue->numSiteQs); hashIdx++) {
13325c2921b0SApple OSS Distributions 								if (instance == site->addresses[hashIdx]) {
1333a5e72196SApple OSS Distributions 									addresses = true;
1334a5e72196SApple OSS Distributions 								}
13355c2921b0SApple OSS Distributions 							}
13365c2921b0SApple OSS Distributions 						}
13370f3703acSApple OSS Distributions 						instFlags = (typeof(instFlags))instance;
1338a5e72196SApple OSS Distributions 						if (addresses) {
1339a5e72196SApple OSS Distributions 							instFlags |= kInstanceFlagAddress;
1340a5e72196SApple OSS Distributions 						}
1341e7776783SApple OSS Distributions 						data->appendValue(instFlags);
13420f3703acSApple OSS Distributions 					}
13430f3703acSApple OSS Distributions 				}
134488cc0b97SApple OSS Distributions 			}
13450f3703acSApple OSS Distributions 			// queue is locked
13460f3703acSApple OSS Distributions 			ret = kIOReturnSuccess;
13470f3703acSApple OSS Distributions 			break;
13480f3703acSApple OSS Distributions 		}
13490f3703acSApple OSS Distributions 
135076e12aa3SApple OSS Distributions 
13510f3703acSApple OSS Distributions 		case kIOTrackingGetTracking:
13520f3703acSApple OSS Distributions 		{
1353a5e72196SApple OSS Distributions 			if (kIOTrackingQueueTypeMap & queue->type) {
1354a5e72196SApple OSS Distributions 				break;
1355a5e72196SApple OSS Distributions 			}
135688cc0b97SApple OSS Distributions 
1357a5e72196SApple OSS Distributions 			if (!data) {
1358*8d741a5dSApple OSS Distributions 				/* BEGIN IGNORE CODESTYLE */
1359*8d741a5dSApple OSS Distributions 				__typed_allocators_ignore_push
1360a5e72196SApple OSS Distributions 				data = OSData::withCapacity(128 * sizeof(IOTrackingCallSiteInfo));
1361*8d741a5dSApple OSS Distributions 				__typed_allocators_ignore_pop
1362*8d741a5dSApple OSS Distributions 				/* END IGNORE CODESTYLE */
1363a5e72196SApple OSS Distributions 			}
13640f3703acSApple OSS Distributions 
13650f3703acSApple OSS Distributions 			IOTRecursiveLockLock(&queue->lock);
13660f3703acSApple OSS Distributions 			num = queue->siteCount;
13670f3703acSApple OSS Distributions 			idx = 0;
1368a5e72196SApple OSS Distributions 			for (qIdx = 0; qIdx < queue->numSiteQs; qIdx++) {
136988cc0b97SApple OSS Distributions 				queue_iterate(&queue->sites[qIdx], site, IOTrackingCallSite *, link)
13700f3703acSApple OSS Distributions 				{
13710f3703acSApple OSS Distributions 					assert(idx < num);
13720f3703acSApple OSS Distributions 					idx++;
13730f3703acSApple OSS Distributions 
137476e12aa3SApple OSS Distributions 					size_t tsize[2];
137576e12aa3SApple OSS Distributions 					uint32_t count = site->count;
137676e12aa3SApple OSS Distributions 					tsize[0] = site->size[0];
137776e12aa3SApple OSS Distributions 					tsize[1] = site->size[1];
13780f3703acSApple OSS Distributions 
1379a5e72196SApple OSS Distributions 					if (intag || inzsize) {
138076e12aa3SApple OSS Distributions 						uintptr_t addr;
138176e12aa3SApple OSS Distributions 						vm_size_t size, zoneSize;
138276e12aa3SApple OSS Distributions 						vm_tag_t  tag;
138376e12aa3SApple OSS Distributions 
1384a5e72196SApple OSS Distributions 						if (kIOTrackingQueueTypeAlloc & queue->type) {
138576e12aa3SApple OSS Distributions 							addresses = false;
138676e12aa3SApple OSS Distributions 							count = 0;
138776e12aa3SApple OSS Distributions 							tsize[0] = tsize[1] = 0;
138876e12aa3SApple OSS Distributions 							queue_iterate(&site->instances, instance, IOTracking *, link)
138976e12aa3SApple OSS Distributions 							{
13905c2921b0SApple OSS Distributions 								if (site->addresses) {
13915c2921b0SApple OSS Distributions 									for (uint32_t hashIdx = 0; !addresses && (hashIdx < queue->numSiteQs); hashIdx++) {
13925c2921b0SApple OSS Distributions 										if (instance == site->addresses[hashIdx]) {
1393a5e72196SApple OSS Distributions 											addresses = true;
1394a5e72196SApple OSS Distributions 										}
13955c2921b0SApple OSS Distributions 									}
13965c2921b0SApple OSS Distributions 								}
139776e12aa3SApple OSS Distributions 
1398a5e72196SApple OSS Distributions 								if (addresses) {
1399a5e72196SApple OSS Distributions 									addr = ~((IOTrackingAddress *)instance)->address;
1400a5e72196SApple OSS Distributions 								} else {
1401a5e72196SApple OSS Distributions 									addr = (uintptr_t) (instance + 1);
1402a5e72196SApple OSS Distributions 								}
140376e12aa3SApple OSS Distributions 
140476e12aa3SApple OSS Distributions 								kr = vm_kern_allocation_info(addr, &size, &tag, &zoneSize);
1405a5e72196SApple OSS Distributions 								if (KERN_SUCCESS != kr) {
1406a5e72196SApple OSS Distributions 									continue;
1407a5e72196SApple OSS Distributions 								}
140876e12aa3SApple OSS Distributions 
1409a5e72196SApple OSS Distributions 								if ((VM_KERN_MEMORY_NONE != intag) && (intag != tag)) {
1410a5e72196SApple OSS Distributions 									continue;
1411a5e72196SApple OSS Distributions 								}
1412a5e72196SApple OSS Distributions 								if (inzsize && (inzsize != zoneSize)) {
1413a5e72196SApple OSS Distributions 									continue;
1414a5e72196SApple OSS Distributions 								}
141576e12aa3SApple OSS Distributions 
141676e12aa3SApple OSS Distributions 								count++;
141776e12aa3SApple OSS Distributions 								tsize[0] += size;
141876e12aa3SApple OSS Distributions 							}
1419a5e72196SApple OSS Distributions 						} else {
1420a5e72196SApple OSS Distributions 							if (!intag || inzsize || (intag != site->tag)) {
1421a5e72196SApple OSS Distributions 								continue;
142276e12aa3SApple OSS Distributions 							}
142376e12aa3SApple OSS Distributions 						}
142476e12aa3SApple OSS Distributions 					}
142576e12aa3SApple OSS Distributions 
1426a5e72196SApple OSS Distributions 					if (!count) {
1427a5e72196SApple OSS Distributions 						continue;
1428a5e72196SApple OSS Distributions 					}
1429a5e72196SApple OSS Distributions 					if (size && ((tsize[0] + tsize[1]) < size)) {
1430a5e72196SApple OSS Distributions 						continue;
1431a5e72196SApple OSS Distributions 					}
143276e12aa3SApple OSS Distributions 					siteInfo.count   = count;
143376e12aa3SApple OSS Distributions 					siteInfo.size[0] = tsize[0];
143476e12aa3SApple OSS Distributions 					siteInfo.size[1] = tsize[1];
1435bb611c8fSApple OSS Distributions 					CopyOutBacktraces(site, &siteInfo);
1436*8d741a5dSApple OSS Distributions 					__typed_allocators_ignore_push
143788cc0b97SApple OSS Distributions 					data->appendBytes(&siteInfo, sizeof(siteInfo));
1438*8d741a5dSApple OSS Distributions 					__typed_allocators_ignore_pop
14390f3703acSApple OSS Distributions 				}
14400f3703acSApple OSS Distributions 			}
14410f3703acSApple OSS Distributions 			assert(idx == num);
14420f3703acSApple OSS Distributions 			IOTRecursiveLockUnlock(&queue->lock);
14430f3703acSApple OSS Distributions 			ret = kIOReturnSuccess;
14440f3703acSApple OSS Distributions 			break;
14450f3703acSApple OSS Distributions 		}
144688cc0b97SApple OSS Distributions 
144788cc0b97SApple OSS Distributions 		case kIOTrackingGetMappings:
144888cc0b97SApple OSS Distributions 		{
1449a5e72196SApple OSS Distributions 			if (!(kIOTrackingQueueTypeMap & queue->type)) {
1450a5e72196SApple OSS Distributions 				break;
1451a5e72196SApple OSS Distributions 			}
1452a5e72196SApple OSS Distributions 			if (!data) {
1453bb611c8fSApple OSS Distributions 				data = OSData::withCapacity((unsigned int) page_size);
1454a5e72196SApple OSS Distributions 			}
145588cc0b97SApple OSS Distributions 
145688cc0b97SApple OSS Distributions 			IOTRecursiveLockLock(&queue->lock);
145788cc0b97SApple OSS Distributions 			num = queue->siteCount;
145888cc0b97SApple OSS Distributions 			idx = 0;
1459a5e72196SApple OSS Distributions 			for (qIdx = 0; qIdx < queue->numSiteQs; qIdx++) {
146088cc0b97SApple OSS Distributions 				queue_iterate(&queue->sites[qIdx], user, IOTrackingUser *, link)
146188cc0b97SApple OSS Distributions 				{
146288cc0b97SApple OSS Distributions 					assert(idx < num);
146388cc0b97SApple OSS Distributions 					idx++;
146488cc0b97SApple OSS Distributions 
146588cc0b97SApple OSS Distributions 					kr = IOMemoryMapTracking(user, &mapTask, &mapAddress, &mapSize);
1466a5e72196SApple OSS Distributions 					if (kIOReturnSuccess != kr) {
1467a5e72196SApple OSS Distributions 						continue;
1468a5e72196SApple OSS Distributions 					}
1469a5e72196SApple OSS Distributions 					if (proc && (mapTask != proc_task(proc))) {
1470a5e72196SApple OSS Distributions 						continue;
1471a5e72196SApple OSS Distributions 					}
1472a5e72196SApple OSS Distributions 					if (size && (mapSize < size)) {
1473a5e72196SApple OSS Distributions 						continue;
1474a5e72196SApple OSS Distributions 					}
147588cc0b97SApple OSS Distributions 
147688cc0b97SApple OSS Distributions 					siteInfo.count      = 1;
147788cc0b97SApple OSS Distributions 					siteInfo.size[0]    = mapSize;
147888cc0b97SApple OSS Distributions 					siteInfo.address    = mapAddress;
147988cc0b97SApple OSS Distributions 					siteInfo.addressPID = task_pid(mapTask);
148088cc0b97SApple OSS Distributions 					siteInfo.btPID      = user->btPID;
148188cc0b97SApple OSS Distributions 
1482a5e72196SApple OSS Distributions 					for (uint32_t j = 0; j < kIOTrackingCallSiteBTs; j++) {
148388cc0b97SApple OSS Distributions 						siteInfo.bt[0][j] = VM_KERNEL_UNSLIDE(user->bt[j]);
148488cc0b97SApple OSS Distributions 					}
148588cc0b97SApple OSS Distributions 					uint32_t * bt32 = (typeof(bt32)) & user->btUser[0];
148688cc0b97SApple OSS Distributions 					uint64_t * bt64 = (typeof(bt64))((void *) &user->btUser[0]);
1487a5e72196SApple OSS Distributions 					for (uint32_t j = 0; j < kIOTrackingCallSiteBTs; j++) {
1488a5e72196SApple OSS Distributions 						if (j >= user->userCount) {
1489a5e72196SApple OSS Distributions 							siteInfo.bt[1][j] = 0;
1490a5e72196SApple OSS Distributions 						} else if (user->user32) {
1491a5e72196SApple OSS Distributions 							siteInfo.bt[1][j] = bt32[j];
1492a5e72196SApple OSS Distributions 						} else {
1493a5e72196SApple OSS Distributions 							siteInfo.bt[1][j] = bt64[j];
1494a5e72196SApple OSS Distributions 						}
149588cc0b97SApple OSS Distributions 					}
1496*8d741a5dSApple OSS Distributions 					__typed_allocators_ignore_push
149788cc0b97SApple OSS Distributions 					data->appendBytes(&siteInfo, sizeof(siteInfo));
1498*8d741a5dSApple OSS Distributions 					__typed_allocators_ignore_pop
149988cc0b97SApple OSS Distributions 				}
150088cc0b97SApple OSS Distributions 			}
150188cc0b97SApple OSS Distributions 			assert(idx == num);
150288cc0b97SApple OSS Distributions 			IOTRecursiveLockUnlock(&queue->lock);
150388cc0b97SApple OSS Distributions 			ret = kIOReturnSuccess;
150488cc0b97SApple OSS Distributions 			break;
150588cc0b97SApple OSS Distributions 		}
150688cc0b97SApple OSS Distributions 
15070f3703acSApple OSS Distributions 		default:
15080f3703acSApple OSS Distributions 			ret = kIOReturnUnsupported;
15090f3703acSApple OSS Distributions 			break;
15100f3703acSApple OSS Distributions 		}
15110f3703acSApple OSS Distributions 	}
15120f3703acSApple OSS Distributions 
1513a5e72196SApple OSS Distributions 	if ((kIOTrackingLeaks == selector) && data) {
15140f3703acSApple OSS Distributions 		data = IOTrackingLeaks(data);
15150f3703acSApple OSS Distributions 		queue_iterate(&gIOTrackingQ, queue, IOTrackingQueue *, link)
15160f3703acSApple OSS Distributions 		{
1517a5e72196SApple OSS Distributions 			if (SkipName(options, queue->name, namesLen, names)) {
1518a5e72196SApple OSS Distributions 				continue;
1519a5e72196SApple OSS Distributions 			}
1520a5e72196SApple OSS Distributions 			if (!(kIOTrackingQueueTypeAlloc & queue->type)) {
1521a5e72196SApple OSS Distributions 				continue;
1522a5e72196SApple OSS Distributions 			}
15230f3703acSApple OSS Distributions 			IOTRecursiveLockUnlock(&queue->lock);
15240f3703acSApple OSS Distributions 		}
15250f3703acSApple OSS Distributions 	}
15260f3703acSApple OSS Distributions 
15270f3703acSApple OSS Distributions 	lck_mtx_unlock(gIOTrackingLock);
15280f3703acSApple OSS Distributions 
1529a5e72196SApple OSS Distributions 	if ((kIOTrackingLeaks == selector) && namesLen && names) {
153088cc0b97SApple OSS Distributions 		const char * scan;
153188cc0b97SApple OSS Distributions 		const char * next;
1532bb611c8fSApple OSS Distributions 		uint8_t      sLen;
15330f3703acSApple OSS Distributions 
1534a5e72196SApple OSS Distributions 		if (!data) {
1535*8d741a5dSApple OSS Distributions 			/* BEGIN IGNORE CODESTYLE */
1536*8d741a5dSApple OSS Distributions 			__typed_allocators_ignore_push
1537a5e72196SApple OSS Distributions 			data = OSData::withCapacity(4096 * sizeof(uintptr_t));
1538*8d741a5dSApple OSS Distributions 			__typed_allocators_ignore_pop
1539*8d741a5dSApple OSS Distributions 			/* END IGNORE CODESTYLE */
1540a5e72196SApple OSS Distributions 		}
154188cc0b97SApple OSS Distributions 
154288cc0b97SApple OSS Distributions 		// <len><name>...<len><name><0>
154388cc0b97SApple OSS Distributions 		scan    = names;
1544a5e72196SApple OSS Distributions 		do{
1545bb611c8fSApple OSS Distributions 			sLen = ((uint8_t) scan[0]);
154688cc0b97SApple OSS Distributions 			scan++;
154788cc0b97SApple OSS Distributions 			next = scan + sLen;
1548a5e72196SApple OSS Distributions 			if (next >= (names + namesLen)) {
1549a5e72196SApple OSS Distributions 				break;
155088cc0b97SApple OSS Distributions 			}
1551e7776783SApple OSS Distributions 			kr = zone_leaks(scan, sLen, ^(uint32_t count, uint32_t eSize, btref_t ref) {
1552e7776783SApple OSS Distributions 				IOTrackingCallSiteInfo siteInfo = {
1553e7776783SApple OSS Distributions 				        .count   = count,
1554e7776783SApple OSS Distributions 				        .size[0] = eSize * count,
1555e7776783SApple OSS Distributions 				};
1556e7776783SApple OSS Distributions 
1557e7776783SApple OSS Distributions 				btref_decode_unslide(ref, siteInfo.bt[0]);
1558*8d741a5dSApple OSS Distributions 				__typed_allocators_ignore_push
1559e7776783SApple OSS Distributions 				data->appendBytes(&siteInfo, sizeof(siteInfo));
1560*8d741a5dSApple OSS Distributions 				__typed_allocators_ignore_pop
1561e7776783SApple OSS Distributions 			});
1562a5e72196SApple OSS Distributions 			if (KERN_SUCCESS == kr) {
1563a5e72196SApple OSS Distributions 				ret = kIOReturnSuccess;
1564a5e72196SApple OSS Distributions 			} else if (KERN_INVALID_NAME != kr) {
1565a5e72196SApple OSS Distributions 				ret = kIOReturnVMError;
1566a5e72196SApple OSS Distributions 			}
1567a5e72196SApple OSS Distributions 			scan = next;
1568a5e72196SApple OSS Distributions 		}while (scan < (names + namesLen));
156988cc0b97SApple OSS Distributions 	}
157088cc0b97SApple OSS Distributions 
1571a5e72196SApple OSS Distributions 	if (data) {
1572a5e72196SApple OSS Distributions 		switch (selector) {
157388cc0b97SApple OSS Distributions 		case kIOTrackingLeaks:
157488cc0b97SApple OSS Distributions 		case kIOTrackingGetTracking:
157588cc0b97SApple OSS Distributions 		case kIOTrackingGetMappings:
157688cc0b97SApple OSS Distributions 		{
157788cc0b97SApple OSS Distributions 			IOTrackingCallSiteInfo * siteInfos;
1578*8d741a5dSApple OSS Distributions 			/* BEGIN IGNORE CODESTYLE */
1579*8d741a5dSApple OSS Distributions 			__typed_allocators_ignore_push
158088cc0b97SApple OSS Distributions 			siteInfos = (typeof(siteInfos))data->getBytesNoCopy();
1581*8d741a5dSApple OSS Distributions 			__typed_allocators_ignore_pop
1582*8d741a5dSApple OSS Distributions 			/* END IGNORE CODESTYLE */
158388cc0b97SApple OSS Distributions 			num = (data->getLength() / sizeof(*siteInfos));
158488cc0b97SApple OSS Distributions 			qsort(siteInfos, num, sizeof(*siteInfos), &IOTrackingCallSiteInfoCompare);
158588cc0b97SApple OSS Distributions 			break;
15860f3703acSApple OSS Distributions 		}
158788cc0b97SApple OSS Distributions 		default: assert(false); break;
15880f3703acSApple OSS Distributions 		}
1589a5e72196SApple OSS Distributions 	}
15900f3703acSApple OSS Distributions 
15910f3703acSApple OSS Distributions 	*result = data;
1592a5e72196SApple OSS Distributions 	if (proc) {
1593a5e72196SApple OSS Distributions 		proc_rele(proc);
1594a5e72196SApple OSS Distributions 	}
15950f3703acSApple OSS Distributions 
15960f3703acSApple OSS Distributions #endif /* IOTRACKING */
15970f3703acSApple OSS Distributions 
1598a5e72196SApple OSS Distributions 	return ret;
15990f3703acSApple OSS Distributions }
16000f3703acSApple OSS Distributions 
16010f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
16020f3703acSApple OSS Distributions 
16030f3703acSApple OSS Distributions #include <IOKit/IOKitDiagnosticsUserClient.h>
16040f3703acSApple OSS Distributions 
16050f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
16060f3703acSApple OSS Distributions 
16070f3703acSApple OSS Distributions #undef super
16085c2921b0SApple OSS Distributions #define super IOUserClient2022
16090f3703acSApple OSS Distributions 
OSDefineMetaClassAndStructors(IOKitDiagnosticsClient,IOUserClient2022)16105c2921b0SApple OSS Distributions OSDefineMetaClassAndStructors(IOKitDiagnosticsClient, IOUserClient2022)
16110f3703acSApple OSS Distributions 
16120f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
16130f3703acSApple OSS Distributions 
16140f3703acSApple OSS Distributions IOUserClient * IOKitDiagnosticsClient::withTask(task_t owningTask)
16150f3703acSApple OSS Distributions {
16165c2921b0SApple OSS Distributions #if IOTRACKING
16170f3703acSApple OSS Distributions 	IOKitDiagnosticsClient * inst;
16180f3703acSApple OSS Distributions 
16190f3703acSApple OSS Distributions 	inst = new IOKitDiagnosticsClient;
1620a5e72196SApple OSS Distributions 	if (inst && !inst->init()) {
16210f3703acSApple OSS Distributions 		inst->release();
1622a5e72196SApple OSS Distributions 		inst = NULL;
16230f3703acSApple OSS Distributions 	}
16240f3703acSApple OSS Distributions 
16255c2921b0SApple OSS Distributions 	inst->setProperty(kIOUserClientDefaultLockingKey, kOSBooleanTrue);
16265c2921b0SApple OSS Distributions 	inst->setProperty(kIOUserClientDefaultLockingSetPropertiesKey, kOSBooleanTrue);
16275c2921b0SApple OSS Distributions 	inst->setProperty(kIOUserClientDefaultLockingSingleThreadExternalMethodKey, kOSBooleanTrue);
16285c2921b0SApple OSS Distributions 
16295c2921b0SApple OSS Distributions 	inst->setProperty(kIOUserClientEntitlementsKey, kOSBooleanFalse);
16305c2921b0SApple OSS Distributions 
1631a5e72196SApple OSS Distributions 	return inst;
16325c2921b0SApple OSS Distributions #else
16335c2921b0SApple OSS Distributions 	return NULL;
16345c2921b0SApple OSS Distributions #endif
16350f3703acSApple OSS Distributions }
16360f3703acSApple OSS Distributions 
1637a5e72196SApple OSS Distributions IOReturn
clientClose(void)1638a5e72196SApple OSS Distributions IOKitDiagnosticsClient::clientClose(void)
16390f3703acSApple OSS Distributions {
16400f3703acSApple OSS Distributions 	terminate();
1641a5e72196SApple OSS Distributions 	return kIOReturnSuccess;
16420f3703acSApple OSS Distributions }
16430f3703acSApple OSS Distributions 
1644a5e72196SApple OSS Distributions IOReturn
setProperties(OSObject * properties)1645a5e72196SApple OSS Distributions IOKitDiagnosticsClient::setProperties(OSObject * properties)
16460f3703acSApple OSS Distributions {
16470f3703acSApple OSS Distributions 	IOReturn kr = kIOReturnUnsupported;
1648a5e72196SApple OSS Distributions 	return kr;
16490f3703acSApple OSS Distributions }
16500f3703acSApple OSS Distributions 
16515c2921b0SApple OSS Distributions 
1652a5e72196SApple OSS Distributions IOReturn
IOTrackingMethodDispatched(OSObject * target,void * reference,IOExternalMethodArguments * args)16535c2921b0SApple OSS Distributions IOTrackingMethodDispatched(OSObject * target, void * reference,
16545c2921b0SApple OSS Distributions     IOExternalMethodArguments * args)
16550f3703acSApple OSS Distributions {
16560f3703acSApple OSS Distributions 	IOReturn                           ret = kIOReturnBadArgument;
16570f3703acSApple OSS Distributions 	const IOKitDiagnosticsParameters * params;
16580f3703acSApple OSS Distributions 	const char * names;
16590f3703acSApple OSS Distributions 	size_t       namesLen;
16600f3703acSApple OSS Distributions 	OSObject   * result;
16610f3703acSApple OSS Distributions 
1662a5e72196SApple OSS Distributions 	if (args->structureInputSize < sizeof(IOKitDiagnosticsParameters)) {
1663a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
1664a5e72196SApple OSS Distributions 	}
16650f3703acSApple OSS Distributions 	params = (typeof(params))args->structureInput;
1666a5e72196SApple OSS Distributions 	if (!params) {
1667a5e72196SApple OSS Distributions 		return kIOReturnBadArgument;
1668a5e72196SApple OSS Distributions 	}
16690f3703acSApple OSS Distributions 
1670a5e72196SApple OSS Distributions 	names = NULL;
16710f3703acSApple OSS Distributions 	namesLen = args->structureInputSize - sizeof(IOKitDiagnosticsParameters);
1672a5e72196SApple OSS Distributions 	if (namesLen) {
1673a5e72196SApple OSS Distributions 		names = (typeof(names))(params + 1);
1674a5e72196SApple OSS Distributions 	}
16750f3703acSApple OSS Distributions 
16765c2921b0SApple OSS Distributions 	ret = IOTrackingDebug(args->selector, params->options, params->value, params->tag, params->zsize, names, namesLen, params->size, &result);
1677a5e72196SApple OSS Distributions 	if ((kIOReturnSuccess == ret) && args->structureVariableOutputData) {
1678a5e72196SApple OSS Distributions 		*args->structureVariableOutputData = result;
1679a5e72196SApple OSS Distributions 	} else if (result) {
1680a5e72196SApple OSS Distributions 		result->release();
1681a5e72196SApple OSS Distributions 	}
1682a5e72196SApple OSS Distributions 	return ret;
16830f3703acSApple OSS Distributions }
16840f3703acSApple OSS Distributions 
16855c2921b0SApple OSS Distributions IOReturn
externalMethod(uint32_t selector,IOExternalMethodArgumentsOpaque * args)16865c2921b0SApple OSS Distributions IOKitDiagnosticsClient::externalMethod(uint32_t selector, IOExternalMethodArgumentsOpaque * args)
16875c2921b0SApple OSS Distributions {
16885c2921b0SApple OSS Distributions 	static const IOExternalMethodDispatch2022 dispatchArray[] = {
16895c2921b0SApple OSS Distributions 		[kIOTrackingGetTracking] = {
16905c2921b0SApple OSS Distributions 			.function                             = &IOTrackingMethodDispatched,
16915c2921b0SApple OSS Distributions 			.checkScalarInputCount    = 0,
16925c2921b0SApple OSS Distributions 			.checkStructureInputSize  = kIOUCVariableStructureSize,
16935c2921b0SApple OSS Distributions 			.checkScalarOutputCount   = 0,
16945c2921b0SApple OSS Distributions 			.checkStructureOutputSize = 0,
16955c2921b0SApple OSS Distributions 			.allowAsync               = false,
16965c2921b0SApple OSS Distributions 			.checkEntitlement         = NULL,
16975c2921b0SApple OSS Distributions 		},
16985c2921b0SApple OSS Distributions 		[kIOTrackingGetMappings] = {
16995c2921b0SApple OSS Distributions 			.function                             = &IOTrackingMethodDispatched,
17005c2921b0SApple OSS Distributions 			.checkScalarInputCount    = 0,
17015c2921b0SApple OSS Distributions 			.checkStructureInputSize  = kIOUCVariableStructureSize,
17025c2921b0SApple OSS Distributions 			.checkScalarOutputCount   = 0,
17035c2921b0SApple OSS Distributions 			.checkStructureOutputSize = 0,
17045c2921b0SApple OSS Distributions 			.allowAsync               = false,
17055c2921b0SApple OSS Distributions 			.checkEntitlement         = NULL,
17065c2921b0SApple OSS Distributions 		},
17075c2921b0SApple OSS Distributions 		[kIOTrackingResetTracking] = {
17085c2921b0SApple OSS Distributions 			.function                             = &IOTrackingMethodDispatched,
17095c2921b0SApple OSS Distributions 			.checkScalarInputCount    = 0,
17105c2921b0SApple OSS Distributions 			.checkStructureInputSize  = kIOUCVariableStructureSize,
17115c2921b0SApple OSS Distributions 			.checkScalarOutputCount   = 0,
17125c2921b0SApple OSS Distributions 			.checkStructureOutputSize = 0,
17135c2921b0SApple OSS Distributions 			.allowAsync               = false,
17145c2921b0SApple OSS Distributions 			.checkEntitlement         = NULL,
17155c2921b0SApple OSS Distributions 		},
17165c2921b0SApple OSS Distributions 		[kIOTrackingStartCapture] = {
17175c2921b0SApple OSS Distributions 			.function                             = &IOTrackingMethodDispatched,
17185c2921b0SApple OSS Distributions 			.checkScalarInputCount    = 0,
17195c2921b0SApple OSS Distributions 			.checkStructureInputSize  = kIOUCVariableStructureSize,
17205c2921b0SApple OSS Distributions 			.checkScalarOutputCount   = 0,
17215c2921b0SApple OSS Distributions 			.checkStructureOutputSize = 0,
17225c2921b0SApple OSS Distributions 			.allowAsync               = false,
17235c2921b0SApple OSS Distributions 			.checkEntitlement         = NULL,
17245c2921b0SApple OSS Distributions 		},
17255c2921b0SApple OSS Distributions 		[kIOTrackingStopCapture] = {
17265c2921b0SApple OSS Distributions 			.function                             = &IOTrackingMethodDispatched,
17275c2921b0SApple OSS Distributions 			.checkScalarInputCount    = 0,
17285c2921b0SApple OSS Distributions 			.checkStructureInputSize  = kIOUCVariableStructureSize,
17295c2921b0SApple OSS Distributions 			.checkScalarOutputCount   = 0,
17305c2921b0SApple OSS Distributions 			.checkStructureOutputSize = 0,
17315c2921b0SApple OSS Distributions 			.allowAsync               = false,
17325c2921b0SApple OSS Distributions 			.checkEntitlement         = NULL,
17335c2921b0SApple OSS Distributions 		},
17345c2921b0SApple OSS Distributions 		[kIOTrackingSetMinCaptureSize] = {
17355c2921b0SApple OSS Distributions 			.function                             = &IOTrackingMethodDispatched,
17365c2921b0SApple OSS Distributions 			.checkScalarInputCount    = 0,
17375c2921b0SApple OSS Distributions 			.checkStructureInputSize  = kIOUCVariableStructureSize,
17385c2921b0SApple OSS Distributions 			.checkScalarOutputCount   = 0,
17395c2921b0SApple OSS Distributions 			.checkStructureOutputSize = 0,
17405c2921b0SApple OSS Distributions 			.allowAsync               = false,
17415c2921b0SApple OSS Distributions 			.checkEntitlement         = NULL,
17425c2921b0SApple OSS Distributions 		},
17435c2921b0SApple OSS Distributions 		[kIOTrackingLeaks] = {
17445c2921b0SApple OSS Distributions 			.function                             = &IOTrackingMethodDispatched,
17455c2921b0SApple OSS Distributions 			.checkScalarInputCount    = 0,
17465c2921b0SApple OSS Distributions 			.checkStructureInputSize  = kIOUCVariableStructureSize,
17475c2921b0SApple OSS Distributions 			.checkScalarOutputCount   = 0,
17485c2921b0SApple OSS Distributions 			.checkStructureOutputSize = 0,
17495c2921b0SApple OSS Distributions 			.allowAsync               = false,
17505c2921b0SApple OSS Distributions 			.checkEntitlement         = NULL,
17515c2921b0SApple OSS Distributions 		},
17525c2921b0SApple OSS Distributions 	};
17535c2921b0SApple OSS Distributions 
17545c2921b0SApple OSS Distributions 	return dispatchExternalMethod(selector, args, dispatchArray, sizeof(dispatchArray) / sizeof(dispatchArray[0]), this, NULL);
17555c2921b0SApple OSS Distributions }
17565c2921b0SApple OSS Distributions 
17570f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1758