xref: /xnu-10002.1.13/iokit/Kernel/IOKitDebug.cpp (revision 1031c584a5e37aff177559b9f69dbd3c8c3fd30a)
1*1031c584SApple OSS Distributions /*
2*1031c584SApple OSS Distributions  * Copyright (c) 1998-2016 Apple Inc. All rights reserved.
3*1031c584SApple OSS Distributions  *
4*1031c584SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*1031c584SApple OSS Distributions  *
6*1031c584SApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7*1031c584SApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8*1031c584SApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9*1031c584SApple OSS Distributions  * compliance with the License. The rights granted to you under the License
10*1031c584SApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
11*1031c584SApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
12*1031c584SApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
13*1031c584SApple OSS Distributions  * terms of an Apple operating system software license agreement.
14*1031c584SApple OSS Distributions  *
15*1031c584SApple OSS Distributions  * Please obtain a copy of the License at
16*1031c584SApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*1031c584SApple OSS Distributions  *
18*1031c584SApple OSS Distributions  * The Original Code and all software distributed under the License are
19*1031c584SApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*1031c584SApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*1031c584SApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*1031c584SApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*1031c584SApple OSS Distributions  * Please see the License for the specific language governing rights and
24*1031c584SApple OSS Distributions  * limitations under the License.
25*1031c584SApple OSS Distributions  *
26*1031c584SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*1031c584SApple OSS Distributions  */
28*1031c584SApple OSS Distributions 
29*1031c584SApple OSS Distributions #include <sys/sysctl.h>
30*1031c584SApple OSS Distributions extern "C" {
31*1031c584SApple OSS Distributions #include <vm/vm_kern.h>
32*1031c584SApple OSS Distributions #include <kern/task.h>
33*1031c584SApple OSS Distributions #include <kern/debug.h>
34*1031c584SApple OSS Distributions }
35*1031c584SApple OSS Distributions 
36*1031c584SApple OSS Distributions #include <libkern/c++/OSContainers.h>
37*1031c584SApple OSS Distributions #include <libkern/OSDebug.h>
38*1031c584SApple OSS Distributions #include <libkern/c++/OSCPPDebug.h>
39*1031c584SApple OSS Distributions #include <kern/backtrace.h>
40*1031c584SApple OSS Distributions #include <kern/btlog.h>
41*1031c584SApple OSS Distributions 
42*1031c584SApple OSS Distributions #include <IOKit/IOKitDebug.h>
43*1031c584SApple OSS Distributions #include <IOKit/IOLib.h>
44*1031c584SApple OSS Distributions #include <IOKit/assert.h>
45*1031c584SApple OSS Distributions #include <IOKit/IODeviceTreeSupport.h>
46*1031c584SApple OSS Distributions #include <IOKit/IOService.h>
47*1031c584SApple OSS Distributions 
48*1031c584SApple OSS Distributions #include "IOKitKernelInternal.h"
49*1031c584SApple OSS Distributions 
50*1031c584SApple OSS Distributions TUNABLE_WRITEABLE(SInt64, gIOKitDebug, "io", DEBUG_INIT_VALUE);
51*1031c584SApple OSS Distributions TUNABLE_DEV_WRITEABLE(SInt64, gIOKitTrace, "iotrace", 0);
52*1031c584SApple OSS Distributions 
53*1031c584SApple OSS Distributions #if DEVELOPMENT || DEBUG
54*1031c584SApple OSS Distributions #define IODEBUG_CTLFLAGS        CTLFLAG_RW
55*1031c584SApple OSS Distributions #else
56*1031c584SApple OSS Distributions #define IODEBUG_CTLFLAGS        CTLFLAG_RD
57*1031c584SApple OSS Distributions #endif
58*1031c584SApple OSS Distributions 
59*1031c584SApple OSS Distributions SYSCTL_QUAD(_debug, OID_AUTO, iotrace, IODEBUG_CTLFLAGS | CTLFLAG_LOCKED, &gIOKitTrace, "trace io");
60*1031c584SApple OSS Distributions 
61*1031c584SApple OSS Distributions static int
sysctl_debug_iokit(__unused struct sysctl_oid * oidp,__unused void * arg1,__unused int arg2,struct sysctl_req * req)62*1031c584SApple OSS Distributions sysctl_debug_iokit
63*1031c584SApple OSS Distributions (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
64*1031c584SApple OSS Distributions {
65*1031c584SApple OSS Distributions 	SInt64 newValue;
66*1031c584SApple OSS Distributions 	int changed, error = sysctl_io_number(req, gIOKitDebug, sizeof(gIOKitDebug), &newValue, &changed);
67*1031c584SApple OSS Distributions 	if (changed) {
68*1031c584SApple OSS Distributions 		gIOKitDebug = ((gIOKitDebug & ~kIOKitDebugUserOptions) | (newValue & kIOKitDebugUserOptions));
69*1031c584SApple OSS Distributions 	}
70*1031c584SApple OSS Distributions 	return error;
71*1031c584SApple OSS Distributions }
72*1031c584SApple OSS Distributions 
73*1031c584SApple OSS Distributions SYSCTL_PROC(_debug, OID_AUTO, iokit,
74*1031c584SApple OSS Distributions     CTLTYPE_QUAD | IODEBUG_CTLFLAGS | CTLFLAG_KERN | CTLFLAG_LOCKED,
75*1031c584SApple OSS Distributions     &gIOKitDebug, 0, sysctl_debug_iokit, "Q", "boot_arg io");
76*1031c584SApple OSS Distributions 
77*1031c584SApple OSS Distributions void           (*gIOTrackingLeakScanCallback)(uint32_t notification) = NULL;
78*1031c584SApple OSS Distributions 
79*1031c584SApple OSS Distributions size_t          debug_malloc_size;
80*1031c584SApple OSS Distributions size_t          debug_iomalloc_size;
81*1031c584SApple OSS Distributions 
82*1031c584SApple OSS Distributions vm_size_t       debug_iomallocpageable_size;
83*1031c584SApple OSS Distributions size_t          debug_container_malloc_size;
84*1031c584SApple OSS Distributions // int          debug_ivars_size; // in OSObject.cpp
85*1031c584SApple OSS Distributions 
86*1031c584SApple OSS Distributions extern "C" {
87*1031c584SApple OSS Distributions #if 0
88*1031c584SApple OSS Distributions #define DEBG(fmt, args...)   { kprintf(fmt, ## args); }
89*1031c584SApple OSS Distributions #else
90*1031c584SApple OSS Distributions #define DEBG(fmt, args...)   { IOLog(fmt, ## args); }
91*1031c584SApple OSS Distributions #endif
92*1031c584SApple OSS Distributions 
93*1031c584SApple OSS Distributions void
IOPrintPlane(const IORegistryPlane * plane)94*1031c584SApple OSS Distributions IOPrintPlane( const IORegistryPlane * plane )
95*1031c584SApple OSS Distributions {
96*1031c584SApple OSS Distributions 	IORegistryEntry *           next;
97*1031c584SApple OSS Distributions 	IORegistryIterator *        iter;
98*1031c584SApple OSS Distributions 	OSOrderedSet *              all;
99*1031c584SApple OSS Distributions 	IOService *                 service;
100*1031c584SApple OSS Distributions 
101*1031c584SApple OSS Distributions 	iter = IORegistryIterator::iterateOver( plane );
102*1031c584SApple OSS Distributions 	assert( iter );
103*1031c584SApple OSS Distributions 	all = iter->iterateAll();
104*1031c584SApple OSS Distributions 	if (all) {
105*1031c584SApple OSS Distributions 		DEBG("Count %d\n", all->getCount());
106*1031c584SApple OSS Distributions 		all->release();
107*1031c584SApple OSS Distributions 	} else {
108*1031c584SApple OSS Distributions 		DEBG("Empty\n");
109*1031c584SApple OSS Distributions 	}
110*1031c584SApple OSS Distributions 
111*1031c584SApple OSS Distributions 	iter->reset();
112*1031c584SApple OSS Distributions 	while ((next = iter->getNextObjectRecursive())) {
113*1031c584SApple OSS Distributions 		DEBG( "%*s\033[33m%s", 2 * next->getDepth( plane ), "", next->getName( plane ));
114*1031c584SApple OSS Distributions 		if ((next->getLocation( plane ))) {
115*1031c584SApple OSS Distributions 			DEBG("@%s", next->getLocation( plane ));
116*1031c584SApple OSS Distributions 		}
117*1031c584SApple OSS Distributions 		DEBG("\033[0m <class %s", next->getMetaClass()->getClassName());
118*1031c584SApple OSS Distributions 		if ((service = OSDynamicCast(IOService, next))) {
119*1031c584SApple OSS Distributions 			DEBG(", busy %ld", (long) service->getBusyState());
120*1031c584SApple OSS Distributions 		}
121*1031c584SApple OSS Distributions 		DEBG( ">\n");
122*1031c584SApple OSS Distributions //      IOSleep(250);
123*1031c584SApple OSS Distributions 	}
124*1031c584SApple OSS Distributions 	iter->release();
125*1031c584SApple OSS Distributions 
126*1031c584SApple OSS Distributions #undef IOPrintPlaneFormat
127*1031c584SApple OSS Distributions }
128*1031c584SApple OSS Distributions 
129*1031c584SApple OSS Distributions void
db_piokjunk(void)130*1031c584SApple OSS Distributions db_piokjunk(void)
131*1031c584SApple OSS Distributions {
132*1031c584SApple OSS Distributions }
133*1031c584SApple OSS Distributions 
134*1031c584SApple OSS Distributions void
db_dumpiojunk(const IORegistryPlane * plane __unused)135*1031c584SApple OSS Distributions db_dumpiojunk( const IORegistryPlane * plane __unused )
136*1031c584SApple OSS Distributions {
137*1031c584SApple OSS Distributions }
138*1031c584SApple OSS Distributions 
139*1031c584SApple OSS Distributions void
IOPrintMemory(void)140*1031c584SApple OSS Distributions IOPrintMemory( void )
141*1031c584SApple OSS Distributions {
142*1031c584SApple OSS Distributions //    OSMetaClass::printInstanceCounts();
143*1031c584SApple OSS Distributions 
144*1031c584SApple OSS Distributions 	IOLog("\n"
145*1031c584SApple OSS Distributions 	    "ivar kalloc()       0x%08lx\n"
146*1031c584SApple OSS Distributions 	    "malloc()            0x%08lx\n"
147*1031c584SApple OSS Distributions 	    "containers kalloc() 0x%08lx\n"
148*1031c584SApple OSS Distributions 	    "IOMalloc()          0x%08lx\n"
149*1031c584SApple OSS Distributions 	    "----------------------------------------\n",
150*1031c584SApple OSS Distributions 	    debug_ivars_size,
151*1031c584SApple OSS Distributions 	    debug_malloc_size,
152*1031c584SApple OSS Distributions 	    debug_container_malloc_size,
153*1031c584SApple OSS Distributions 	    debug_iomalloc_size
154*1031c584SApple OSS Distributions 	    );
155*1031c584SApple OSS Distributions }
156*1031c584SApple OSS Distributions } /* extern "C" */
157*1031c584SApple OSS Distributions 
158*1031c584SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
159*1031c584SApple OSS Distributions 
160*1031c584SApple OSS Distributions #define super OSObject
OSDefineMetaClassAndStructors(IOKitDiagnostics,OSObject)161*1031c584SApple OSS Distributions OSDefineMetaClassAndStructors(IOKitDiagnostics, OSObject)
162*1031c584SApple OSS Distributions 
163*1031c584SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
164*1031c584SApple OSS Distributions 
165*1031c584SApple OSS Distributions OSObject * IOKitDiagnostics::diagnostics( void )
166*1031c584SApple OSS Distributions {
167*1031c584SApple OSS Distributions 	IOKitDiagnostics * diags;
168*1031c584SApple OSS Distributions 
169*1031c584SApple OSS Distributions 	diags = new IOKitDiagnostics;
170*1031c584SApple OSS Distributions 	if (diags && !diags->init()) {
171*1031c584SApple OSS Distributions 		diags->release();
172*1031c584SApple OSS Distributions 		diags = NULL;
173*1031c584SApple OSS Distributions 	}
174*1031c584SApple OSS Distributions 
175*1031c584SApple OSS Distributions 	return diags;
176*1031c584SApple OSS Distributions }
177*1031c584SApple OSS Distributions 
178*1031c584SApple OSS Distributions void
updateOffset(OSDictionary * dict,UInt64 value,const char * name)179*1031c584SApple OSS Distributions IOKitDiagnostics::updateOffset( OSDictionary * dict,
180*1031c584SApple OSS Distributions     UInt64 value, const char * name )
181*1031c584SApple OSS Distributions {
182*1031c584SApple OSS Distributions 	OSNumber * off;
183*1031c584SApple OSS Distributions 
184*1031c584SApple OSS Distributions 	off = OSNumber::withNumber( value, 64 );
185*1031c584SApple OSS Distributions 	if (!off) {
186*1031c584SApple OSS Distributions 		return;
187*1031c584SApple OSS Distributions 	}
188*1031c584SApple OSS Distributions 
189*1031c584SApple OSS Distributions 	dict->setObject( name, off );
190*1031c584SApple OSS Distributions 	off->release();
191*1031c584SApple OSS Distributions }
192*1031c584SApple OSS Distributions 
193*1031c584SApple OSS Distributions bool
serialize(OSSerialize * s) const194*1031c584SApple OSS Distributions IOKitDiagnostics::serialize(OSSerialize *s) const
195*1031c584SApple OSS Distributions {
196*1031c584SApple OSS Distributions 	OSDictionary *      dict;
197*1031c584SApple OSS Distributions 	bool                ok;
198*1031c584SApple OSS Distributions 
199*1031c584SApple OSS Distributions 	dict = OSDictionary::withCapacity( 5 );
200*1031c584SApple OSS Distributions 	if (!dict) {
201*1031c584SApple OSS Distributions 		return false;
202*1031c584SApple OSS Distributions 	}
203*1031c584SApple OSS Distributions 
204*1031c584SApple OSS Distributions 	updateOffset( dict, debug_ivars_size, "Instance allocation" );
205*1031c584SApple OSS Distributions 	updateOffset( dict, debug_container_malloc_size, "Container allocation" );
206*1031c584SApple OSS Distributions 	updateOffset( dict, debug_iomalloc_size, "IOMalloc allocation" );
207*1031c584SApple OSS Distributions 	updateOffset( dict, debug_iomallocpageable_size, "Pageable allocation" );
208*1031c584SApple OSS Distributions 
209*1031c584SApple OSS Distributions 	OSMetaClass::serializeClassDictionary(dict);
210*1031c584SApple OSS Distributions 
211*1031c584SApple OSS Distributions 	ok = dict->serialize( s );
212*1031c584SApple OSS Distributions 
213*1031c584SApple OSS Distributions 	dict->release();
214*1031c584SApple OSS Distributions 
215*1031c584SApple OSS Distributions 	return ok;
216*1031c584SApple OSS Distributions }
217*1031c584SApple OSS Distributions 
218*1031c584SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
219*1031c584SApple OSS Distributions 
220*1031c584SApple OSS Distributions #if IOTRACKING
221*1031c584SApple OSS Distributions 
222*1031c584SApple OSS Distributions #include <libkern/c++/OSCPPDebug.h>
223*1031c584SApple OSS Distributions #include <libkern/c++/OSKext.h>
224*1031c584SApple OSS Distributions #include <kern/zalloc.h>
225*1031c584SApple OSS Distributions 
226*1031c584SApple OSS Distributions __private_extern__ "C" void qsort(
227*1031c584SApple OSS Distributions 	void * array,
228*1031c584SApple OSS Distributions 	size_t nmembers,
229*1031c584SApple OSS Distributions 	size_t member_size,
230*1031c584SApple OSS Distributions 	int (*)(const void *, const void *));
231*1031c584SApple OSS Distributions 
232*1031c584SApple OSS Distributions extern "C" ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va);
233*1031c584SApple OSS Distributions extern "C" ppnum_t pmap_valid_page(ppnum_t pn);
234*1031c584SApple OSS Distributions 
235*1031c584SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
236*1031c584SApple OSS Distributions 
237*1031c584SApple OSS Distributions struct IOTRecursiveLock {
238*1031c584SApple OSS Distributions 	lck_mtx_t * mutex;
239*1031c584SApple OSS Distributions 	thread_t    thread;
240*1031c584SApple OSS Distributions 	UInt32      count;
241*1031c584SApple OSS Distributions };
242*1031c584SApple OSS Distributions 
243*1031c584SApple OSS Distributions struct IOTrackingQueue {
244*1031c584SApple OSS Distributions 	queue_chain_t     link;
245*1031c584SApple OSS Distributions 	IOTRecursiveLock  lock;
246*1031c584SApple OSS Distributions 	const char *      name;
247*1031c584SApple OSS Distributions 	uintptr_t         btEntry;
248*1031c584SApple OSS Distributions 	size_t            allocSize;
249*1031c584SApple OSS Distributions 	size_t            minCaptureSize;
250*1031c584SApple OSS Distributions 	uint32_t          siteCount;
251*1031c584SApple OSS Distributions 	uint32_t          type;
252*1031c584SApple OSS Distributions 	uint32_t          numSiteQs;
253*1031c584SApple OSS Distributions 	uint8_t           captureOn;
254*1031c584SApple OSS Distributions 	queue_head_t      sites[];
255*1031c584SApple OSS Distributions };
256*1031c584SApple OSS Distributions 
257*1031c584SApple OSS Distributions 
258*1031c584SApple OSS Distributions struct IOTrackingCallSiteUser {
259*1031c584SApple OSS Distributions 	pid_t         pid;
260*1031c584SApple OSS Distributions 	uint8_t       user32;
261*1031c584SApple OSS Distributions 	uint8_t       userCount;
262*1031c584SApple OSS Distributions 	uintptr_t     bt[kIOTrackingCallSiteBTs];
263*1031c584SApple OSS Distributions };
264*1031c584SApple OSS Distributions 
265*1031c584SApple OSS Distributions struct IOTrackingCallSite {
266*1031c584SApple OSS Distributions 	queue_chain_t          link;
267*1031c584SApple OSS Distributions 	queue_head_t           instances;
268*1031c584SApple OSS Distributions 	IOTrackingQueue *      queue;
269*1031c584SApple OSS Distributions 	IOTracking **          addresses;
270*1031c584SApple OSS Distributions 	size_t        size[2];
271*1031c584SApple OSS Distributions 	uint32_t               crc;
272*1031c584SApple OSS Distributions 	uint32_t      count;
273*1031c584SApple OSS Distributions 
274*1031c584SApple OSS Distributions 	vm_tag_t      tag;
275*1031c584SApple OSS Distributions 	uint8_t       user32;
276*1031c584SApple OSS Distributions 	uint8_t       userCount;
277*1031c584SApple OSS Distributions 	pid_t         btPID;
278*1031c584SApple OSS Distributions 
279*1031c584SApple OSS Distributions 	uintptr_t     bt[kIOTrackingCallSiteBTs];
280*1031c584SApple OSS Distributions 	IOTrackingCallSiteUser     user[0];
281*1031c584SApple OSS Distributions };
282*1031c584SApple OSS Distributions 
283*1031c584SApple OSS Distributions struct IOTrackingCallSiteWithUser {
284*1031c584SApple OSS Distributions 	struct IOTrackingCallSite     site;
285*1031c584SApple OSS Distributions 	struct IOTrackingCallSiteUser user;
286*1031c584SApple OSS Distributions };
287*1031c584SApple OSS Distributions 
288*1031c584SApple OSS Distributions static void IOTrackingFreeCallSite(uint32_t type, IOTrackingCallSite ** site);
289*1031c584SApple OSS Distributions 
290*1031c584SApple OSS Distributions struct IOTrackingLeaksRef {
291*1031c584SApple OSS Distributions 	uintptr_t * instances;
292*1031c584SApple OSS Distributions 	uint32_t    zoneSize;
293*1031c584SApple OSS Distributions 	uint32_t    count;
294*1031c584SApple OSS Distributions 	uint32_t    found;
295*1031c584SApple OSS Distributions 	uint32_t    foundzlen;
296*1031c584SApple OSS Distributions 	size_t      bytes;
297*1031c584SApple OSS Distributions };
298*1031c584SApple OSS Distributions 
299*1031c584SApple OSS Distributions lck_mtx_t *  gIOTrackingLock;
300*1031c584SApple OSS Distributions queue_head_t gIOTrackingQ;
301*1031c584SApple OSS Distributions 
302*1031c584SApple OSS Distributions enum{
303*1031c584SApple OSS Distributions 	kTrackingAddressFlagAllocated    = 0x00000001
304*1031c584SApple OSS Distributions };
305*1031c584SApple OSS Distributions 
306*1031c584SApple OSS Distributions #if defined(__LP64__)
307*1031c584SApple OSS Distributions #define IOTrackingAddressFlags(ptr)     (ptr->flags)
308*1031c584SApple OSS Distributions #else
309*1031c584SApple OSS Distributions #define IOTrackingAddressFlags(ptr)     (ptr->tracking.flags)
310*1031c584SApple OSS Distributions #endif
311*1031c584SApple OSS Distributions 
312*1031c584SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
313*1031c584SApple OSS Distributions 
314*1031c584SApple OSS Distributions static void
IOTRecursiveLockLock(IOTRecursiveLock * lock)315*1031c584SApple OSS Distributions IOTRecursiveLockLock(IOTRecursiveLock * lock)
316*1031c584SApple OSS Distributions {
317*1031c584SApple OSS Distributions 	if (lock->thread == current_thread()) {
318*1031c584SApple OSS Distributions 		lock->count++;
319*1031c584SApple OSS Distributions 	} else {
320*1031c584SApple OSS Distributions 		lck_mtx_lock(lock->mutex);
321*1031c584SApple OSS Distributions 		assert(lock->thread == NULL);
322*1031c584SApple OSS Distributions 		assert(lock->count == 0);
323*1031c584SApple OSS Distributions 		lock->thread = current_thread();
324*1031c584SApple OSS Distributions 		lock->count = 1;
325*1031c584SApple OSS Distributions 	}
326*1031c584SApple OSS Distributions }
327*1031c584SApple OSS Distributions 
328*1031c584SApple OSS Distributions static void
IOTRecursiveLockUnlock(IOTRecursiveLock * lock)329*1031c584SApple OSS Distributions IOTRecursiveLockUnlock(IOTRecursiveLock * lock)
330*1031c584SApple OSS Distributions {
331*1031c584SApple OSS Distributions 	assert(lock->thread == current_thread());
332*1031c584SApple OSS Distributions 	if (0 == (--lock->count)) {
333*1031c584SApple OSS Distributions 		lock->thread = NULL;
334*1031c584SApple OSS Distributions 		lck_mtx_unlock(lock->mutex);
335*1031c584SApple OSS Distributions 	}
336*1031c584SApple OSS Distributions }
337*1031c584SApple OSS Distributions 
338*1031c584SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
339*1031c584SApple OSS Distributions 
340*1031c584SApple OSS Distributions void
IOTrackingInit(void)341*1031c584SApple OSS Distributions IOTrackingInit(void)
342*1031c584SApple OSS Distributions {
343*1031c584SApple OSS Distributions 	queue_init(&gIOTrackingQ);
344*1031c584SApple OSS Distributions 	gIOTrackingLock = lck_mtx_alloc_init(IOLockGroup, LCK_ATTR_NULL);
345*1031c584SApple OSS Distributions }
346*1031c584SApple OSS Distributions 
347*1031c584SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
348*1031c584SApple OSS Distributions 
349*1031c584SApple OSS Distributions IOTrackingQueue *
IOTrackingQueueAlloc(const char * name,uintptr_t btEntry,size_t allocSize,size_t minCaptureSize,uint32_t type,uint32_t numSiteQs)350*1031c584SApple OSS Distributions IOTrackingQueueAlloc(const char * name, uintptr_t btEntry,
351*1031c584SApple OSS Distributions     size_t allocSize, size_t minCaptureSize,
352*1031c584SApple OSS Distributions     uint32_t type, uint32_t numSiteQs)
353*1031c584SApple OSS Distributions {
354*1031c584SApple OSS Distributions 	IOTrackingQueue * queue;
355*1031c584SApple OSS Distributions 	uint32_t          idx;
356*1031c584SApple OSS Distributions 
357*1031c584SApple OSS Distributions 	if (!numSiteQs) {
358*1031c584SApple OSS Distributions 		numSiteQs = 1;
359*1031c584SApple OSS Distributions 	}
360*1031c584SApple OSS Distributions 	queue = kalloc_type(IOTrackingQueue, queue_head_t, numSiteQs, Z_WAITOK_ZERO);
361*1031c584SApple OSS Distributions 	queue->name           = name;
362*1031c584SApple OSS Distributions 	queue->btEntry        = btEntry;
363*1031c584SApple OSS Distributions 	queue->allocSize      = allocSize;
364*1031c584SApple OSS Distributions 	queue->minCaptureSize = minCaptureSize;
365*1031c584SApple OSS Distributions 	queue->lock.mutex     = lck_mtx_alloc_init(IOLockGroup, LCK_ATTR_NULL);
366*1031c584SApple OSS Distributions 	queue->numSiteQs      = numSiteQs;
367*1031c584SApple OSS Distributions 	queue->type           = type;
368*1031c584SApple OSS Distributions 	enum { kFlags = (kIOTracking | kIOTrackingBoot) };
369*1031c584SApple OSS Distributions 	queue->captureOn = (kFlags == (kFlags & gIOKitDebug))
370*1031c584SApple OSS Distributions 	    || (kIOTrackingQueueTypeDefaultOn & type);
371*1031c584SApple OSS Distributions 
372*1031c584SApple OSS Distributions 	for (idx = 0; idx < numSiteQs; idx++) {
373*1031c584SApple OSS Distributions 		queue_init(&queue->sites[idx]);
374*1031c584SApple OSS Distributions 	}
375*1031c584SApple OSS Distributions 
376*1031c584SApple OSS Distributions 	lck_mtx_lock(gIOTrackingLock);
377*1031c584SApple OSS Distributions 	queue_enter(&gIOTrackingQ, queue, IOTrackingQueue *, link);
378*1031c584SApple OSS Distributions 	lck_mtx_unlock(gIOTrackingLock);
379*1031c584SApple OSS Distributions 
380*1031c584SApple OSS Distributions 	return queue;
381*1031c584SApple OSS Distributions };
382*1031c584SApple OSS Distributions 
383*1031c584SApple OSS Distributions void
IOTrackingQueueCollectUser(IOTrackingQueue * queue)384*1031c584SApple OSS Distributions IOTrackingQueueCollectUser(IOTrackingQueue * queue)
385*1031c584SApple OSS Distributions {
386*1031c584SApple OSS Distributions 	assert(0 == queue->siteCount);
387*1031c584SApple OSS Distributions 	queue->type |= kIOTrackingQueueTypeUser;
388*1031c584SApple OSS Distributions }
389*1031c584SApple OSS Distributions 
390*1031c584SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
391*1031c584SApple OSS Distributions 
392*1031c584SApple OSS Distributions void
IOTrackingQueueFree(IOTrackingQueue * queue)393*1031c584SApple OSS Distributions IOTrackingQueueFree(IOTrackingQueue * queue)
394*1031c584SApple OSS Distributions {
395*1031c584SApple OSS Distributions 	lck_mtx_lock(gIOTrackingLock);
396*1031c584SApple OSS Distributions 	IOTrackingReset(queue);
397*1031c584SApple OSS Distributions 	remque(&queue->link);
398*1031c584SApple OSS Distributions 	lck_mtx_unlock(gIOTrackingLock);
399*1031c584SApple OSS Distributions 
400*1031c584SApple OSS Distributions 	lck_mtx_free(queue->lock.mutex, IOLockGroup);
401*1031c584SApple OSS Distributions 
402*1031c584SApple OSS Distributions 	kfree_type(IOTrackingQueue, queue_head_t, queue->numSiteQs, queue);
403*1031c584SApple OSS Distributions };
404*1031c584SApple OSS Distributions 
405*1031c584SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
406*1031c584SApple OSS Distributions 
407*1031c584SApple OSS Distributions /* fasthash
408*1031c584SApple OSS Distributions  *  The MIT License
409*1031c584SApple OSS Distributions  *
410*1031c584SApple OSS Distributions  *  Copyright (C) 2012 Zilong Tan ([email protected])
411*1031c584SApple OSS Distributions  *
412*1031c584SApple OSS Distributions  *  Permission is hereby granted, free of charge, to any person
413*1031c584SApple OSS Distributions  *  obtaining a copy of this software and associated documentation
414*1031c584SApple OSS Distributions  *  files (the "Software"), to deal in the Software without
415*1031c584SApple OSS Distributions  *  restriction, including without limitation the rights to use, copy,
416*1031c584SApple OSS Distributions  *  modify, merge, publish, distribute, sublicense, and/or sell copies
417*1031c584SApple OSS Distributions  *  of the Software, and to permit persons to whom the Software is
418*1031c584SApple OSS Distributions  *  furnished to do so, subject to the following conditions:
419*1031c584SApple OSS Distributions  *
420*1031c584SApple OSS Distributions  *  The above copyright notice and this permission notice shall be
421*1031c584SApple OSS Distributions  *  included in all copies or substantial portions of the Software.
422*1031c584SApple OSS Distributions  *
423*1031c584SApple OSS Distributions  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
424*1031c584SApple OSS Distributions  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
425*1031c584SApple OSS Distributions  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
426*1031c584SApple OSS Distributions  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
427*1031c584SApple OSS Distributions  *  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
428*1031c584SApple OSS Distributions  *  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
429*1031c584SApple OSS Distributions  *  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
430*1031c584SApple OSS Distributions  *  SOFTWARE.
431*1031c584SApple OSS Distributions  */
432*1031c584SApple OSS Distributions 
433*1031c584SApple OSS Distributions 
434*1031c584SApple OSS Distributions // Compression function for Merkle-Damgard construction.
435*1031c584SApple OSS Distributions // This function is generated using the framework provided.
436*1031c584SApple OSS Distributions #define mix(h) ({                               \
437*1031c584SApple OSS Distributions 	          (h) ^= (h) >> 23;             \
438*1031c584SApple OSS Distributions 	          (h) *= 0x2127599bf4325c37ULL; \
439*1031c584SApple OSS Distributions 	          (h) ^= (h) >> 47; })
440*1031c584SApple OSS Distributions 
441*1031c584SApple OSS Distributions static uint64_t
fasthash64(const void * buf,size_t len,uint64_t seed)442*1031c584SApple OSS Distributions fasthash64(const void *buf, size_t len, uint64_t seed)
443*1031c584SApple OSS Distributions {
444*1031c584SApple OSS Distributions 	const uint64_t    m = 0x880355f21e6d1965ULL;
445*1031c584SApple OSS Distributions 	const uint64_t *pos = (const uint64_t *)buf;
446*1031c584SApple OSS Distributions 	const uint64_t *end = pos + (len / 8);
447*1031c584SApple OSS Distributions 	const unsigned char *pos2;
448*1031c584SApple OSS Distributions 	uint64_t h = seed ^ (len * m);
449*1031c584SApple OSS Distributions 	uint64_t v;
450*1031c584SApple OSS Distributions 
451*1031c584SApple OSS Distributions 	while (pos != end) {
452*1031c584SApple OSS Distributions 		v  = *pos++;
453*1031c584SApple OSS Distributions 		h ^= mix(v);
454*1031c584SApple OSS Distributions 		h *= m;
455*1031c584SApple OSS Distributions 	}
456*1031c584SApple OSS Distributions 
457*1031c584SApple OSS Distributions 	pos2 = (const unsigned char*)pos;
458*1031c584SApple OSS Distributions 	v = 0;
459*1031c584SApple OSS Distributions 
460*1031c584SApple OSS Distributions 	switch (len & 7) {
461*1031c584SApple OSS Distributions 	case 7: v ^= (uint64_t)pos2[6] << 48;
462*1031c584SApple OSS Distributions 		[[clang::fallthrough]];
463*1031c584SApple OSS Distributions 	case 6: v ^= (uint64_t)pos2[5] << 40;
464*1031c584SApple OSS Distributions 		[[clang::fallthrough]];
465*1031c584SApple OSS Distributions 	case 5: v ^= (uint64_t)pos2[4] << 32;
466*1031c584SApple OSS Distributions 		[[clang::fallthrough]];
467*1031c584SApple OSS Distributions 	case 4: v ^= (uint64_t)pos2[3] << 24;
468*1031c584SApple OSS Distributions 		[[clang::fallthrough]];
469*1031c584SApple OSS Distributions 	case 3: v ^= (uint64_t)pos2[2] << 16;
470*1031c584SApple OSS Distributions 		[[clang::fallthrough]];
471*1031c584SApple OSS Distributions 	case 2: v ^= (uint64_t)pos2[1] << 8;
472*1031c584SApple OSS Distributions 		[[clang::fallthrough]];
473*1031c584SApple OSS Distributions 	case 1: v ^= (uint64_t)pos2[0];
474*1031c584SApple OSS Distributions 		h ^= mix(v);
475*1031c584SApple OSS Distributions 		h *= m;
476*1031c584SApple OSS Distributions 	}
477*1031c584SApple OSS Distributions 
478*1031c584SApple OSS Distributions 	return mix(h);
479*1031c584SApple OSS Distributions }
480*1031c584SApple OSS Distributions 
481*1031c584SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
482*1031c584SApple OSS Distributions 
483*1031c584SApple OSS Distributions static uint32_t
fasthash32(const void * buf,size_t len,uint32_t seed)484*1031c584SApple OSS Distributions fasthash32(const void *buf, size_t len, uint32_t seed)
485*1031c584SApple OSS Distributions {
486*1031c584SApple OSS Distributions 	// the following trick converts the 64-bit hashcode to Fermat
487*1031c584SApple OSS Distributions 	// residue, which shall retain information from both the higher
488*1031c584SApple OSS Distributions 	// and lower parts of hashcode.
489*1031c584SApple OSS Distributions 	uint64_t h = fasthash64(buf, len, seed);
490*1031c584SApple OSS Distributions 	return (uint32_t) (h - (h >> 32));
491*1031c584SApple OSS Distributions }
492*1031c584SApple OSS Distributions 
493*1031c584SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
494*1031c584SApple OSS Distributions 
495*1031c584SApple OSS Distributions void
IOTrackingAddUser(IOTrackingQueue * queue,IOTrackingUser * mem,vm_size_t size)496*1031c584SApple OSS Distributions IOTrackingAddUser(IOTrackingQueue * queue, IOTrackingUser * mem, vm_size_t size)
497*1031c584SApple OSS Distributions {
498*1031c584SApple OSS Distributions 	uint32_t num;
499*1031c584SApple OSS Distributions 	int pid;
500*1031c584SApple OSS Distributions 
501*1031c584SApple OSS Distributions 	if (!queue->captureOn) {
502*1031c584SApple OSS Distributions 		return;
503*1031c584SApple OSS Distributions 	}
504*1031c584SApple OSS Distributions 	if (size < queue->minCaptureSize) {
505*1031c584SApple OSS Distributions 		return;
506*1031c584SApple OSS Distributions 	}
507*1031c584SApple OSS Distributions 
508*1031c584SApple OSS Distributions 	assert(!mem->link.next);
509*1031c584SApple OSS Distributions 
510*1031c584SApple OSS Distributions 	num = backtrace(&mem->bt[0], kIOTrackingCallSiteBTs, NULL, NULL);
511*1031c584SApple OSS Distributions 	num = 0;
512*1031c584SApple OSS Distributions 	if ((kernel_task != current_task()) && (pid = proc_selfpid())) {
513*1031c584SApple OSS Distributions 		struct backtrace_user_info btinfo = BTUINFO_INIT;
514*1031c584SApple OSS Distributions 		mem->btPID = pid;
515*1031c584SApple OSS Distributions 		num = backtrace_user(&mem->btUser[0], kIOTrackingCallSiteBTs - 1,
516*1031c584SApple OSS Distributions 		    NULL, &btinfo);
517*1031c584SApple OSS Distributions 		mem->user32 = !(btinfo.btui_info & BTI_64_BIT);
518*1031c584SApple OSS Distributions 	}
519*1031c584SApple OSS Distributions 	assert(num <= kIOTrackingCallSiteBTs);
520*1031c584SApple OSS Distributions 	static_assert(kIOTrackingCallSiteBTs <= UINT8_MAX);
521*1031c584SApple OSS Distributions 	mem->userCount = ((uint8_t) num);
522*1031c584SApple OSS Distributions 
523*1031c584SApple OSS Distributions 	IOTRecursiveLockLock(&queue->lock);
524*1031c584SApple OSS Distributions 	queue_enter/*last*/ (&queue->sites[0], mem, IOTrackingUser *, link);
525*1031c584SApple OSS Distributions 	queue->siteCount++;
526*1031c584SApple OSS Distributions 	IOTRecursiveLockUnlock(&queue->lock);
527*1031c584SApple OSS Distributions }
528*1031c584SApple OSS Distributions 
529*1031c584SApple OSS Distributions void
IOTrackingRemoveUser(IOTrackingQueue * queue,IOTrackingUser * mem)530*1031c584SApple OSS Distributions IOTrackingRemoveUser(IOTrackingQueue * queue, IOTrackingUser * mem)
531*1031c584SApple OSS Distributions {
532*1031c584SApple OSS Distributions 	if (!mem->link.next) {
533*1031c584SApple OSS Distributions 		return;
534*1031c584SApple OSS Distributions 	}
535*1031c584SApple OSS Distributions 
536*1031c584SApple OSS Distributions 	IOTRecursiveLockLock(&queue->lock);
537*1031c584SApple OSS Distributions 	if (mem->link.next) {
538*1031c584SApple OSS Distributions 		remque(&mem->link);
539*1031c584SApple OSS Distributions 		assert(queue->siteCount);
540*1031c584SApple OSS Distributions 		queue->siteCount--;
541*1031c584SApple OSS Distributions 	}
542*1031c584SApple OSS Distributions 	IOTRecursiveLockUnlock(&queue->lock);
543*1031c584SApple OSS Distributions }
544*1031c584SApple OSS Distributions 
545*1031c584SApple OSS Distributions uint64_t gIOTrackingAddTime;
546*1031c584SApple OSS Distributions 
547*1031c584SApple OSS Distributions void
IOTrackingAdd(IOTrackingQueue * queue,IOTracking * mem,size_t size,bool address,vm_tag_t tag)548*1031c584SApple OSS Distributions IOTrackingAdd(IOTrackingQueue * queue, IOTracking * mem, size_t size, bool address, vm_tag_t tag)
549*1031c584SApple OSS Distributions {
550*1031c584SApple OSS Distributions 	IOTrackingCallSite * site;
551*1031c584SApple OSS Distributions 	uint32_t             crc, num;
552*1031c584SApple OSS Distributions 	uintptr_t            bt[kIOTrackingCallSiteBTs + 1];
553*1031c584SApple OSS Distributions 	uintptr_t            btUser[kIOTrackingCallSiteBTs];
554*1031c584SApple OSS Distributions 	queue_head_t       * que;
555*1031c584SApple OSS Distributions 	bool                 user;
556*1031c584SApple OSS Distributions 	int                  pid;
557*1031c584SApple OSS Distributions 	int                  userCount;
558*1031c584SApple OSS Distributions 
559*1031c584SApple OSS Distributions 	if (mem->site) {
560*1031c584SApple OSS Distributions 		return;
561*1031c584SApple OSS Distributions 	}
562*1031c584SApple OSS Distributions 	if (!queue->captureOn) {
563*1031c584SApple OSS Distributions 		return;
564*1031c584SApple OSS Distributions 	}
565*1031c584SApple OSS Distributions 	if (size < queue->minCaptureSize) {
566*1031c584SApple OSS Distributions 		return;
567*1031c584SApple OSS Distributions 	}
568*1031c584SApple OSS Distributions 
569*1031c584SApple OSS Distributions 	user = (0 != (kIOTrackingQueueTypeUser & queue->type));
570*1031c584SApple OSS Distributions 
571*1031c584SApple OSS Distributions 	assert(!mem->link.next);
572*1031c584SApple OSS Distributions 
573*1031c584SApple OSS Distributions 	num  = backtrace(&bt[0], kIOTrackingCallSiteBTs + 1, NULL, NULL);
574*1031c584SApple OSS Distributions 	if (!num) {
575*1031c584SApple OSS Distributions 		return;
576*1031c584SApple OSS Distributions 	}
577*1031c584SApple OSS Distributions 	num--;
578*1031c584SApple OSS Distributions 	crc = fasthash32(&bt[1], num * sizeof(bt[0]), 0x04C11DB7);
579*1031c584SApple OSS Distributions 
580*1031c584SApple OSS Distributions 	userCount = 0;
581*1031c584SApple OSS Distributions 	pid = 0;
582*1031c584SApple OSS Distributions 	backtrace_info_t btinfo = BTI_NONE;
583*1031c584SApple OSS Distributions 	if (user) {
584*1031c584SApple OSS Distributions 		if ((kernel_task != current_task()) && (pid = proc_selfpid())) {
585*1031c584SApple OSS Distributions 			struct backtrace_user_info btuinfo = BTUINFO_INIT;
586*1031c584SApple OSS Distributions 			userCount = backtrace_user(&btUser[0], kIOTrackingCallSiteBTs,
587*1031c584SApple OSS Distributions 			    NULL, &btuinfo);
588*1031c584SApple OSS Distributions 			assert(userCount <= kIOTrackingCallSiteBTs);
589*1031c584SApple OSS Distributions 			btinfo = btuinfo.btui_info;
590*1031c584SApple OSS Distributions 			crc = fasthash32(&btUser[0], userCount * sizeof(bt[0]), crc);
591*1031c584SApple OSS Distributions 		}
592*1031c584SApple OSS Distributions 	}
593*1031c584SApple OSS Distributions 
594*1031c584SApple OSS Distributions 	IOTRecursiveLockLock(&queue->lock);
595*1031c584SApple OSS Distributions 	que = &queue->sites[crc % queue->numSiteQs];
596*1031c584SApple OSS Distributions 	queue_iterate(que, site, IOTrackingCallSite *, link)
597*1031c584SApple OSS Distributions 	{
598*1031c584SApple OSS Distributions 		if (tag != site->tag) {
599*1031c584SApple OSS Distributions 			continue;
600*1031c584SApple OSS Distributions 		}
601*1031c584SApple OSS Distributions 		if (user && (pid != site->user[0].pid)) {
602*1031c584SApple OSS Distributions 			continue;
603*1031c584SApple OSS Distributions 		}
604*1031c584SApple OSS Distributions 		if (crc == site->crc) {
605*1031c584SApple OSS Distributions 			break;
606*1031c584SApple OSS Distributions 		}
607*1031c584SApple OSS Distributions 	}
608*1031c584SApple OSS Distributions 
609*1031c584SApple OSS Distributions 	if (queue_end(que, (queue_entry_t) site)) {
610*1031c584SApple OSS Distributions 		if (user) {
611*1031c584SApple OSS Distributions 			site = &kalloc_type(IOTrackingCallSiteWithUser,
612*1031c584SApple OSS Distributions 			    Z_WAITOK_ZERO_NOFAIL)->site;
613*1031c584SApple OSS Distributions 		} else {
614*1031c584SApple OSS Distributions 			site = kalloc_type(IOTrackingCallSite,
615*1031c584SApple OSS Distributions 			    Z_WAITOK_ZERO_NOFAIL);
616*1031c584SApple OSS Distributions 		}
617*1031c584SApple OSS Distributions 
618*1031c584SApple OSS Distributions 		queue_init(&site->instances);
619*1031c584SApple OSS Distributions 		site->addresses  = NULL;
620*1031c584SApple OSS Distributions 		site->queue      = queue;
621*1031c584SApple OSS Distributions 		site->crc        = crc;
622*1031c584SApple OSS Distributions 		site->count      = 0;
623*1031c584SApple OSS Distributions 		site->tag        = tag;
624*1031c584SApple OSS Distributions 		memset(&site->size[0], 0, sizeof(site->size));
625*1031c584SApple OSS Distributions 		bcopy(&bt[1], &site->bt[0], num * sizeof(site->bt[0]));
626*1031c584SApple OSS Distributions 		assert(num <= kIOTrackingCallSiteBTs);
627*1031c584SApple OSS Distributions 		bzero(&site->bt[num], (kIOTrackingCallSiteBTs - num) * sizeof(site->bt[0]));
628*1031c584SApple OSS Distributions 		if (user) {
629*1031c584SApple OSS Distributions 			bcopy(&btUser[0], &site->user[0].bt[0], userCount * sizeof(site->user[0].bt[0]));
630*1031c584SApple OSS Distributions 			assert(userCount <= kIOTrackingCallSiteBTs);
631*1031c584SApple OSS Distributions 			bzero(&site->user[0].bt[userCount], (kIOTrackingCallSiteBTs - userCount) * sizeof(site->user[0].bt[0]));
632*1031c584SApple OSS Distributions 			site->user[0].pid  = pid;
633*1031c584SApple OSS Distributions 			site->user[0].user32 = !(btinfo & BTI_64_BIT);
634*1031c584SApple OSS Distributions 			static_assert(kIOTrackingCallSiteBTs <= UINT8_MAX);
635*1031c584SApple OSS Distributions 			site->user[0].userCount = ((uint8_t) userCount);
636*1031c584SApple OSS Distributions 		}
637*1031c584SApple OSS Distributions 		queue_enter_first(que, site, IOTrackingCallSite *, link);
638*1031c584SApple OSS Distributions 		queue->siteCount++;
639*1031c584SApple OSS Distributions 	}
640*1031c584SApple OSS Distributions 
641*1031c584SApple OSS Distributions 	if (address) {
642*1031c584SApple OSS Distributions 		IOTrackingAddress * memAddr = (typeof(memAddr))mem;
643*1031c584SApple OSS Distributions 		uint32_t hashIdx;
644*1031c584SApple OSS Distributions 
645*1031c584SApple OSS Distributions 		if (NULL == site->addresses) {
646*1031c584SApple OSS Distributions 			site->addresses = kalloc_type(IOTracking *, queue->numSiteQs, Z_WAITOK_ZERO_NOFAIL);
647*1031c584SApple OSS Distributions 			for (hashIdx = 0; hashIdx < queue->numSiteQs; hashIdx++) {
648*1031c584SApple OSS Distributions 				site->addresses[hashIdx] = (IOTracking *) &site->instances;
649*1031c584SApple OSS Distributions 			}
650*1031c584SApple OSS Distributions 		}
651*1031c584SApple OSS Distributions 		hashIdx = atop(memAddr->address) % queue->numSiteQs;
652*1031c584SApple OSS Distributions 		if (queue_end(&site->instances, (queue_entry_t)site->addresses[hashIdx])) {
653*1031c584SApple OSS Distributions 			queue_enter/*last*/ (&site->instances, mem, IOTracking *, link);
654*1031c584SApple OSS Distributions 		} else {
655*1031c584SApple OSS Distributions 			queue_insert_before(&site->instances, mem, site->addresses[hashIdx], IOTracking *, link);
656*1031c584SApple OSS Distributions 		}
657*1031c584SApple OSS Distributions 		site->addresses[hashIdx] = mem;
658*1031c584SApple OSS Distributions 	} else {
659*1031c584SApple OSS Distributions 		queue_enter_first(&site->instances, mem, IOTracking *, link);
660*1031c584SApple OSS Distributions 	}
661*1031c584SApple OSS Distributions 
662*1031c584SApple OSS Distributions 	mem->site      = site;
663*1031c584SApple OSS Distributions 	site->size[0] += size;
664*1031c584SApple OSS Distributions 	site->count++;
665*1031c584SApple OSS Distributions 
666*1031c584SApple OSS Distributions 	IOTRecursiveLockUnlock(&queue->lock);
667*1031c584SApple OSS Distributions }
668*1031c584SApple OSS Distributions 
669*1031c584SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
670*1031c584SApple OSS Distributions 
671*1031c584SApple OSS Distributions static void
IOTrackingRemoveInternal(IOTrackingQueue * queue,IOTracking * mem,size_t size,uint32_t addressIdx)672*1031c584SApple OSS Distributions IOTrackingRemoveInternal(IOTrackingQueue * queue, IOTracking * mem, size_t size, uint32_t addressIdx)
673*1031c584SApple OSS Distributions {
674*1031c584SApple OSS Distributions 	IOTrackingCallSite * site;
675*1031c584SApple OSS Distributions 	IOTrackingAddress  * nextAddress;
676*1031c584SApple OSS Distributions 
677*1031c584SApple OSS Distributions 	if (!mem->link.next) {
678*1031c584SApple OSS Distributions 		return;
679*1031c584SApple OSS Distributions 	}
680*1031c584SApple OSS Distributions 
681*1031c584SApple OSS Distributions 	IOTRecursiveLockLock(&queue->lock);
682*1031c584SApple OSS Distributions 	if (mem->link.next) {
683*1031c584SApple OSS Distributions 		assert(mem->site);
684*1031c584SApple OSS Distributions 		site = mem->site;
685*1031c584SApple OSS Distributions 
686*1031c584SApple OSS Distributions 		if ((-1U != addressIdx) && (mem == site->addresses[addressIdx])) {
687*1031c584SApple OSS Distributions 			nextAddress = (IOTrackingAddress *) queue_next(&mem->link);
688*1031c584SApple OSS Distributions 			if (!queue_end(&site->instances, &nextAddress->tracking.link)
689*1031c584SApple OSS Distributions 			    && (addressIdx != (atop(nextAddress->address) % queue->numSiteQs))) {
690*1031c584SApple OSS Distributions 				nextAddress = (IOTrackingAddress *) &site->instances;
691*1031c584SApple OSS Distributions 			}
692*1031c584SApple OSS Distributions 			site->addresses[addressIdx] = &nextAddress->tracking;
693*1031c584SApple OSS Distributions 		}
694*1031c584SApple OSS Distributions 
695*1031c584SApple OSS Distributions 		remque(&mem->link);
696*1031c584SApple OSS Distributions 		assert(site->count);
697*1031c584SApple OSS Distributions 		site->count--;
698*1031c584SApple OSS Distributions 		assert(site->size[0] >= size);
699*1031c584SApple OSS Distributions 		site->size[0] -= size;
700*1031c584SApple OSS Distributions 		if (!site->count) {
701*1031c584SApple OSS Distributions 			assert(queue_empty(&site->instances));
702*1031c584SApple OSS Distributions 			assert(!site->size[0]);
703*1031c584SApple OSS Distributions 			assert(!site->size[1]);
704*1031c584SApple OSS Distributions 
705*1031c584SApple OSS Distributions 			remque(&site->link);
706*1031c584SApple OSS Distributions 			assert(queue->siteCount);
707*1031c584SApple OSS Distributions 			queue->siteCount--;
708*1031c584SApple OSS Distributions 			IOTrackingFreeCallSite(queue->type, &site);
709*1031c584SApple OSS Distributions 		}
710*1031c584SApple OSS Distributions 		mem->site = NULL;
711*1031c584SApple OSS Distributions 	}
712*1031c584SApple OSS Distributions 	IOTRecursiveLockUnlock(&queue->lock);
713*1031c584SApple OSS Distributions }
714*1031c584SApple OSS Distributions 
715*1031c584SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
716*1031c584SApple OSS Distributions 
717*1031c584SApple OSS Distributions void
IOTrackingRemove(IOTrackingQueue * queue,IOTracking * mem,size_t size)718*1031c584SApple OSS Distributions IOTrackingRemove(IOTrackingQueue * queue, IOTracking * mem, size_t size)
719*1031c584SApple OSS Distributions {
720*1031c584SApple OSS Distributions 	return IOTrackingRemoveInternal(queue, mem, size, -1U);
721*1031c584SApple OSS Distributions }
722*1031c584SApple OSS Distributions 
723*1031c584SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
724*1031c584SApple OSS Distributions 
725*1031c584SApple OSS Distributions void
IOTrackingRemoveAddress(IOTrackingQueue * queue,IOTrackingAddress * mem,size_t size)726*1031c584SApple OSS Distributions IOTrackingRemoveAddress(IOTrackingQueue * queue, IOTrackingAddress * mem, size_t size)
727*1031c584SApple OSS Distributions {
728*1031c584SApple OSS Distributions 	uint32_t addressIdx;
729*1031c584SApple OSS Distributions 	uint64_t address;
730*1031c584SApple OSS Distributions 
731*1031c584SApple OSS Distributions 	address = mem->address;
732*1031c584SApple OSS Distributions 	addressIdx = atop(address) % queue->numSiteQs;
733*1031c584SApple OSS Distributions 
734*1031c584SApple OSS Distributions 	return IOTrackingRemoveInternal(queue, &mem->tracking, size, addressIdx);
735*1031c584SApple OSS Distributions }
736*1031c584SApple OSS Distributions 
737*1031c584SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
738*1031c584SApple OSS Distributions 
739*1031c584SApple OSS Distributions void
IOTrackingAlloc(IOTrackingQueue * queue,uintptr_t address,size_t size)740*1031c584SApple OSS Distributions IOTrackingAlloc(IOTrackingQueue * queue, uintptr_t address, size_t size)
741*1031c584SApple OSS Distributions {
742*1031c584SApple OSS Distributions 	IOTrackingAddress * tracking;
743*1031c584SApple OSS Distributions 
744*1031c584SApple OSS Distributions 	if (!queue->captureOn) {
745*1031c584SApple OSS Distributions 		return;
746*1031c584SApple OSS Distributions 	}
747*1031c584SApple OSS Distributions 	if (size < queue->minCaptureSize) {
748*1031c584SApple OSS Distributions 		return;
749*1031c584SApple OSS Distributions 	}
750*1031c584SApple OSS Distributions 
751*1031c584SApple OSS Distributions 	address = ~address;
752*1031c584SApple OSS Distributions 	tracking = kalloc_type(IOTrackingAddress, (zalloc_flags_t)(Z_WAITOK | Z_ZERO));
753*1031c584SApple OSS Distributions 	IOTrackingAddressFlags(tracking) |= kTrackingAddressFlagAllocated;
754*1031c584SApple OSS Distributions 	tracking->address = address;
755*1031c584SApple OSS Distributions 	tracking->size    = size;
756*1031c584SApple OSS Distributions 
757*1031c584SApple OSS Distributions 	IOTrackingAdd(queue, &tracking->tracking, size, true, VM_KERN_MEMORY_NONE);
758*1031c584SApple OSS Distributions }
759*1031c584SApple OSS Distributions 
760*1031c584SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
761*1031c584SApple OSS Distributions 
762*1031c584SApple OSS Distributions void
IOTrackingFree(IOTrackingQueue * queue,uintptr_t address,size_t size)763*1031c584SApple OSS Distributions IOTrackingFree(IOTrackingQueue * queue, uintptr_t address, size_t size)
764*1031c584SApple OSS Distributions {
765*1031c584SApple OSS Distributions 	IOTrackingCallSite * site;
766*1031c584SApple OSS Distributions 	IOTrackingAddress  * tracking;
767*1031c584SApple OSS Distributions 	IOTrackingAddress  * nextAddress;
768*1031c584SApple OSS Distributions 	uint32_t             idx, hashIdx;
769*1031c584SApple OSS Distributions 	bool                 done;
770*1031c584SApple OSS Distributions 
771*1031c584SApple OSS Distributions 	address = ~address;
772*1031c584SApple OSS Distributions 	IOTRecursiveLockLock(&queue->lock);
773*1031c584SApple OSS Distributions 
774*1031c584SApple OSS Distributions 	hashIdx = atop(address) % queue->numSiteQs;
775*1031c584SApple OSS Distributions 
776*1031c584SApple OSS Distributions 	done = false;
777*1031c584SApple OSS Distributions 	for (idx = 0; idx < queue->numSiteQs; idx++) {
778*1031c584SApple OSS Distributions 		queue_iterate(&queue->sites[idx], site, IOTrackingCallSite *, link)
779*1031c584SApple OSS Distributions 		{
780*1031c584SApple OSS Distributions 			if (!site->addresses) {
781*1031c584SApple OSS Distributions 				continue;
782*1031c584SApple OSS Distributions 			}
783*1031c584SApple OSS Distributions 			tracking = (IOTrackingAddress *) site->addresses[hashIdx];
784*1031c584SApple OSS Distributions 			while (!queue_end(&site->instances, &tracking->tracking.link)) {
785*1031c584SApple OSS Distributions 				nextAddress = (IOTrackingAddress *) queue_next(&tracking->tracking.link);
786*1031c584SApple OSS Distributions 				if (!queue_end(&site->instances, &nextAddress->tracking.link)
787*1031c584SApple OSS Distributions 				    && (hashIdx != (atop(nextAddress->address) % queue->numSiteQs))) {
788*1031c584SApple OSS Distributions 					nextAddress = (IOTrackingAddress *) &site->instances;
789*1031c584SApple OSS Distributions 				}
790*1031c584SApple OSS Distributions 				if ((done = (address == tracking->address))) {
791*1031c584SApple OSS Distributions 					if (tracking == (IOTrackingAddress *) site->addresses[hashIdx]) {
792*1031c584SApple OSS Distributions 						site->addresses[hashIdx] = &nextAddress->tracking;
793*1031c584SApple OSS Distributions 					}
794*1031c584SApple OSS Distributions 					IOTrackingRemoveInternal(queue, &tracking->tracking, size, -1U);
795*1031c584SApple OSS Distributions 					kfree_type(IOTrackingAddress, tracking);
796*1031c584SApple OSS Distributions 					break;
797*1031c584SApple OSS Distributions 				}
798*1031c584SApple OSS Distributions 				tracking = nextAddress;
799*1031c584SApple OSS Distributions 			}
800*1031c584SApple OSS Distributions 			if (done) {
801*1031c584SApple OSS Distributions 				break;
802*1031c584SApple OSS Distributions 			}
803*1031c584SApple OSS Distributions 		}
804*1031c584SApple OSS Distributions 		if (done) {
805*1031c584SApple OSS Distributions 			break;
806*1031c584SApple OSS Distributions 		}
807*1031c584SApple OSS Distributions 	}
808*1031c584SApple OSS Distributions 	IOTRecursiveLockUnlock(&queue->lock);
809*1031c584SApple OSS Distributions }
810*1031c584SApple OSS Distributions 
811*1031c584SApple OSS Distributions static void
IOTrackingFreeCallSite(uint32_t type,IOTrackingCallSite ** pSite)812*1031c584SApple OSS Distributions IOTrackingFreeCallSite(uint32_t type, IOTrackingCallSite ** pSite)
813*1031c584SApple OSS Distributions {
814*1031c584SApple OSS Distributions 	IOTrackingCallSite * site;
815*1031c584SApple OSS Distributions 	void ** ptr;
816*1031c584SApple OSS Distributions 
817*1031c584SApple OSS Distributions 	site = *pSite;
818*1031c584SApple OSS Distributions 	kfree_type(IOTracking *, site->queue->numSiteQs, site->addresses);
819*1031c584SApple OSS Distributions 
820*1031c584SApple OSS Distributions 	ptr = reinterpret_cast<void **>(pSite);
821*1031c584SApple OSS Distributions 	if (kIOTrackingQueueTypeUser & type) {
822*1031c584SApple OSS Distributions 		kfree_type(IOTrackingCallSiteWithUser, *ptr);
823*1031c584SApple OSS Distributions 	} else {
824*1031c584SApple OSS Distributions 		kfree_type(IOTrackingCallSite, *ptr);
825*1031c584SApple OSS Distributions 	}
826*1031c584SApple OSS Distributions }
827*1031c584SApple OSS Distributions 
828*1031c584SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
829*1031c584SApple OSS Distributions 
830*1031c584SApple OSS Distributions void
IOTrackingAccumSize(IOTrackingQueue * queue,IOTracking * mem,size_t size)831*1031c584SApple OSS Distributions IOTrackingAccumSize(IOTrackingQueue * queue, IOTracking * mem, size_t size)
832*1031c584SApple OSS Distributions {
833*1031c584SApple OSS Distributions 	IOTRecursiveLockLock(&queue->lock);
834*1031c584SApple OSS Distributions 	if (mem->link.next) {
835*1031c584SApple OSS Distributions 		assert(mem->site);
836*1031c584SApple OSS Distributions 		assert((size > 0) || (mem->site->size[1] >= -size));
837*1031c584SApple OSS Distributions 		mem->site->size[1] += size;
838*1031c584SApple OSS Distributions 	}
839*1031c584SApple OSS Distributions 	;
840*1031c584SApple OSS Distributions 	IOTRecursiveLockUnlock(&queue->lock);
841*1031c584SApple OSS Distributions }
842*1031c584SApple OSS Distributions 
843*1031c584SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
844*1031c584SApple OSS Distributions 
845*1031c584SApple OSS Distributions void
IOTrackingReset(IOTrackingQueue * queue)846*1031c584SApple OSS Distributions IOTrackingReset(IOTrackingQueue * queue)
847*1031c584SApple OSS Distributions {
848*1031c584SApple OSS Distributions 	IOTrackingCallSite * site;
849*1031c584SApple OSS Distributions 	IOTrackingUser     * user;
850*1031c584SApple OSS Distributions 	IOTracking         * tracking;
851*1031c584SApple OSS Distributions 	IOTrackingAddress  * trackingAddress;
852*1031c584SApple OSS Distributions 	uint32_t             idx, hashIdx;
853*1031c584SApple OSS Distributions 	bool                 addresses;
854*1031c584SApple OSS Distributions 
855*1031c584SApple OSS Distributions 	IOTRecursiveLockLock(&queue->lock);
856*1031c584SApple OSS Distributions 	for (idx = 0; idx < queue->numSiteQs; idx++) {
857*1031c584SApple OSS Distributions 		while (!queue_empty(&queue->sites[idx])) {
858*1031c584SApple OSS Distributions 			if (kIOTrackingQueueTypeMap & queue->type) {
859*1031c584SApple OSS Distributions 				queue_remove_first(&queue->sites[idx], user, IOTrackingUser *, link);
860*1031c584SApple OSS Distributions 				user->link.next = user->link.prev = NULL;
861*1031c584SApple OSS Distributions 			} else {
862*1031c584SApple OSS Distributions 				queue_remove_first(&queue->sites[idx], site, IOTrackingCallSite *, link);
863*1031c584SApple OSS Distributions 				addresses = false;
864*1031c584SApple OSS Distributions 				while (!queue_empty(&site->instances)) {
865*1031c584SApple OSS Distributions 					queue_remove_first(&site->instances, tracking, IOTracking *, link);
866*1031c584SApple OSS Distributions 					if (site->addresses) {
867*1031c584SApple OSS Distributions 						for (hashIdx = 0; !addresses && (hashIdx < queue->numSiteQs); hashIdx++) {
868*1031c584SApple OSS Distributions 							if (tracking == site->addresses[hashIdx]) {
869*1031c584SApple OSS Distributions 								addresses = true;
870*1031c584SApple OSS Distributions 							}
871*1031c584SApple OSS Distributions 						}
872*1031c584SApple OSS Distributions 					}
873*1031c584SApple OSS Distributions 					if (addresses) {
874*1031c584SApple OSS Distributions 						trackingAddress = (typeof(trackingAddress))tracking;
875*1031c584SApple OSS Distributions 						if (kTrackingAddressFlagAllocated & IOTrackingAddressFlags(trackingAddress)) {
876*1031c584SApple OSS Distributions 							kfree_type(IOTrackingAddress, trackingAddress);
877*1031c584SApple OSS Distributions 						}
878*1031c584SApple OSS Distributions 					}
879*1031c584SApple OSS Distributions 				}
880*1031c584SApple OSS Distributions 				IOTrackingFreeCallSite(queue->type, &site);
881*1031c584SApple OSS Distributions 			}
882*1031c584SApple OSS Distributions 		}
883*1031c584SApple OSS Distributions 	}
884*1031c584SApple OSS Distributions 	queue->siteCount = 0;
885*1031c584SApple OSS Distributions 	IOTRecursiveLockUnlock(&queue->lock);
886*1031c584SApple OSS Distributions }
887*1031c584SApple OSS Distributions 
888*1031c584SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
889*1031c584SApple OSS Distributions 
890*1031c584SApple OSS Distributions static int
IOTrackingCallSiteInfoCompare(const void * left,const void * right)891*1031c584SApple OSS Distributions IOTrackingCallSiteInfoCompare(const void * left, const void * right)
892*1031c584SApple OSS Distributions {
893*1031c584SApple OSS Distributions 	IOTrackingCallSiteInfo * l = (typeof(l))left;
894*1031c584SApple OSS Distributions 	IOTrackingCallSiteInfo * r = (typeof(r))right;
895*1031c584SApple OSS Distributions 	size_t                   lsize, rsize;
896*1031c584SApple OSS Distributions 
897*1031c584SApple OSS Distributions 	rsize = r->size[0] + r->size[1];
898*1031c584SApple OSS Distributions 	lsize = l->size[0] + l->size[1];
899*1031c584SApple OSS Distributions 
900*1031c584SApple OSS Distributions 	return (rsize > lsize) ? 1 : ((rsize == lsize) ? 0 : -1);
901*1031c584SApple OSS Distributions }
902*1031c584SApple OSS Distributions 
903*1031c584SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
904*1031c584SApple OSS Distributions 
905*1031c584SApple OSS Distributions static int
IOTrackingAddressCompare(const void * left,const void * right)906*1031c584SApple OSS Distributions IOTrackingAddressCompare(const void * left, const void * right)
907*1031c584SApple OSS Distributions {
908*1031c584SApple OSS Distributions 	IOTracking * instance;
909*1031c584SApple OSS Distributions 	uintptr_t    inst, laddr, raddr;
910*1031c584SApple OSS Distributions 
911*1031c584SApple OSS Distributions 	inst = ((typeof(inst) *)left)[0];
912*1031c584SApple OSS Distributions 	instance = (typeof(instance))INSTANCE_GET(inst);
913*1031c584SApple OSS Distributions 	if (kInstanceFlagAddress & inst) {
914*1031c584SApple OSS Distributions 		laddr = ~((IOTrackingAddress *)instance)->address;
915*1031c584SApple OSS Distributions 	} else {
916*1031c584SApple OSS Distributions 		laddr = (uintptr_t) (instance + 1);
917*1031c584SApple OSS Distributions 	}
918*1031c584SApple OSS Distributions 
919*1031c584SApple OSS Distributions 	inst = ((typeof(inst) *)right)[0];
920*1031c584SApple OSS Distributions 	instance = (typeof(instance))(inst & ~kInstanceFlags);
921*1031c584SApple OSS Distributions 	if (kInstanceFlagAddress & inst) {
922*1031c584SApple OSS Distributions 		raddr = ~((IOTrackingAddress *)instance)->address;
923*1031c584SApple OSS Distributions 	} else {
924*1031c584SApple OSS Distributions 		raddr = (uintptr_t) (instance + 1);
925*1031c584SApple OSS Distributions 	}
926*1031c584SApple OSS Distributions 
927*1031c584SApple OSS Distributions 	return (laddr > raddr) ? 1 : ((laddr == raddr) ? 0 : -1);
928*1031c584SApple OSS Distributions }
929*1031c584SApple OSS Distributions 
930*1031c584SApple OSS Distributions 
931*1031c584SApple OSS Distributions static int
IOTrackingZoneElementCompare(const void * left,const void * right)932*1031c584SApple OSS Distributions IOTrackingZoneElementCompare(const void * left, const void * right)
933*1031c584SApple OSS Distributions {
934*1031c584SApple OSS Distributions 	uintptr_t    inst, laddr, raddr;
935*1031c584SApple OSS Distributions 
936*1031c584SApple OSS Distributions 	inst = ((typeof(inst) *)left)[0];
937*1031c584SApple OSS Distributions 	laddr = INSTANCE_PUT(inst);
938*1031c584SApple OSS Distributions 	inst = ((typeof(inst) *)right)[0];
939*1031c584SApple OSS Distributions 	raddr = INSTANCE_PUT(inst);
940*1031c584SApple OSS Distributions 
941*1031c584SApple OSS Distributions 	return (laddr > raddr) ? 1 : ((laddr == raddr) ? 0 : -1);
942*1031c584SApple OSS Distributions }
943*1031c584SApple OSS Distributions 
944*1031c584SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
945*1031c584SApple OSS Distributions 
946*1031c584SApple OSS Distributions static void
CopyOutBacktraces(IOTrackingCallSite * site,IOTrackingCallSiteInfo * siteInfo)947*1031c584SApple OSS Distributions CopyOutBacktraces(IOTrackingCallSite * site, IOTrackingCallSiteInfo * siteInfo)
948*1031c584SApple OSS Distributions {
949*1031c584SApple OSS Distributions 	uint32_t j;
950*1031c584SApple OSS Distributions 	mach_vm_address_t bt, btEntry;
951*1031c584SApple OSS Distributions 
952*1031c584SApple OSS Distributions 	btEntry = site->queue->btEntry;
953*1031c584SApple OSS Distributions 	for (j = 0; j < kIOTrackingCallSiteBTs; j++) {
954*1031c584SApple OSS Distributions 		bt = site->bt[j];
955*1031c584SApple OSS Distributions 		if (btEntry
956*1031c584SApple OSS Distributions 		    && (!bt || (j == (kIOTrackingCallSiteBTs - 1)))) {
957*1031c584SApple OSS Distributions 			bt = btEntry;
958*1031c584SApple OSS Distributions 			btEntry = 0;
959*1031c584SApple OSS Distributions 		}
960*1031c584SApple OSS Distributions 		siteInfo->bt[0][j] = VM_KERNEL_UNSLIDE(bt);
961*1031c584SApple OSS Distributions 	}
962*1031c584SApple OSS Distributions 
963*1031c584SApple OSS Distributions 	siteInfo->btPID = 0;
964*1031c584SApple OSS Distributions 	if (kIOTrackingQueueTypeUser & site->queue->type) {
965*1031c584SApple OSS Distributions 		siteInfo->btPID = site->user[0].pid;
966*1031c584SApple OSS Distributions 		uint32_t * bt32 = (typeof(bt32))((void *) &site->user[0].bt[0]);
967*1031c584SApple OSS Distributions 		uint64_t * bt64 = (typeof(bt64))((void *) &site->user[0].bt[0]);
968*1031c584SApple OSS Distributions 		for (uint32_t j = 0; j < kIOTrackingCallSiteBTs; j++) {
969*1031c584SApple OSS Distributions 			if (j >= site->user[0].userCount) {
970*1031c584SApple OSS Distributions 				siteInfo->bt[1][j] = 0;
971*1031c584SApple OSS Distributions 			} else if (site->user[0].user32) {
972*1031c584SApple OSS Distributions 				siteInfo->bt[1][j] = bt32[j];
973*1031c584SApple OSS Distributions 			} else {
974*1031c584SApple OSS Distributions 				siteInfo->bt[1][j] = bt64[j];
975*1031c584SApple OSS Distributions 			}
976*1031c584SApple OSS Distributions 		}
977*1031c584SApple OSS Distributions 	}
978*1031c584SApple OSS Distributions }
979*1031c584SApple OSS Distributions 
980*1031c584SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
981*1031c584SApple OSS Distributions 
982*1031c584SApple OSS Distributions static void
IOTrackingLeakScan(void * refcon)983*1031c584SApple OSS Distributions IOTrackingLeakScan(void * refcon)
984*1031c584SApple OSS Distributions {
985*1031c584SApple OSS Distributions 	IOTrackingLeaksRef * ref = (typeof(ref))refcon;
986*1031c584SApple OSS Distributions 	uintptr_t          * instances;
987*1031c584SApple OSS Distributions 	IOTracking         * instance;
988*1031c584SApple OSS Distributions 	uint64_t             vaddr, vincr;
989*1031c584SApple OSS Distributions 	ppnum_t              ppn;
990*1031c584SApple OSS Distributions 	uintptr_t            ptr, addr, vphysaddr, inst;
991*1031c584SApple OSS Distributions 	size_t               size, origsize;
992*1031c584SApple OSS Distributions 	uint32_t             baseIdx, lim, ptrIdx, count;
993*1031c584SApple OSS Distributions 	boolean_t            is;
994*1031c584SApple OSS Distributions 	AbsoluteTime         deadline;
995*1031c584SApple OSS Distributions 
996*1031c584SApple OSS Distributions 	instances       = ref->instances;
997*1031c584SApple OSS Distributions 	count           = ref->count;
998*1031c584SApple OSS Distributions 	size = origsize = ref->zoneSize;
999*1031c584SApple OSS Distributions 
1000*1031c584SApple OSS Distributions 	if (gIOTrackingLeakScanCallback) {
1001*1031c584SApple OSS Distributions 		gIOTrackingLeakScanCallback(kIOTrackingLeakScanStart);
1002*1031c584SApple OSS Distributions 	}
1003*1031c584SApple OSS Distributions 
1004*1031c584SApple OSS Distributions 	for (deadline = 0, vaddr = VM_MIN_KERNEL_AND_KEXT_ADDRESS;
1005*1031c584SApple OSS Distributions 	    ;
1006*1031c584SApple OSS Distributions 	    vaddr += vincr) {
1007*1031c584SApple OSS Distributions 		if ((mach_absolute_time() > deadline) || (vaddr >= VM_MAX_KERNEL_ADDRESS)) {
1008*1031c584SApple OSS Distributions 			if (deadline) {
1009*1031c584SApple OSS Distributions #if SCHED_HYGIENE_DEBUG
1010*1031c584SApple OSS Distributions 				if (is) {
1011*1031c584SApple OSS Distributions 					// Reset the interrupt timeout to avoid panics
1012*1031c584SApple OSS Distributions 					ml_spin_debug_clear_self();
1013*1031c584SApple OSS Distributions 				}
1014*1031c584SApple OSS Distributions #endif /* SCHED_HYGIENE_DEBUG */
1015*1031c584SApple OSS Distributions 				ml_set_interrupts_enabled(is);
1016*1031c584SApple OSS Distributions 				IODelay(10);
1017*1031c584SApple OSS Distributions 			}
1018*1031c584SApple OSS Distributions 			if (vaddr >= VM_MAX_KERNEL_ADDRESS) {
1019*1031c584SApple OSS Distributions 				break;
1020*1031c584SApple OSS Distributions 			}
1021*1031c584SApple OSS Distributions 			is = ml_set_interrupts_enabled(false);
1022*1031c584SApple OSS Distributions 			clock_interval_to_deadline(10, kMillisecondScale, &deadline);
1023*1031c584SApple OSS Distributions 		}
1024*1031c584SApple OSS Distributions 
1025*1031c584SApple OSS Distributions 		ppn = kernel_pmap_present_mapping(vaddr, &vincr, &vphysaddr);
1026*1031c584SApple OSS Distributions 		// check noencrypt to avoid VM structs (map entries) with pointers
1027*1031c584SApple OSS Distributions 		if (ppn && (!pmap_valid_page(ppn) || (!ref->zoneSize && pmap_is_noencrypt(ppn)))) {
1028*1031c584SApple OSS Distributions 			ppn = 0;
1029*1031c584SApple OSS Distributions 		}
1030*1031c584SApple OSS Distributions 		if (!ppn) {
1031*1031c584SApple OSS Distributions 			continue;
1032*1031c584SApple OSS Distributions 		}
1033*1031c584SApple OSS Distributions 
1034*1031c584SApple OSS Distributions 		for (ptrIdx = 0; ptrIdx < (page_size / sizeof(uintptr_t)); ptrIdx++) {
1035*1031c584SApple OSS Distributions 			ptr = ((uintptr_t *)vphysaddr)[ptrIdx];
1036*1031c584SApple OSS Distributions #if defined(HAS_APPLE_PAC)
1037*1031c584SApple OSS Distributions 			// strip possible ptrauth signature from candidate data pointer
1038*1031c584SApple OSS Distributions 			ptr = (uintptr_t)ptrauth_strip((void*)ptr, ptrauth_key_process_independent_data);
1039*1031c584SApple OSS Distributions #endif /* defined(HAS_APPLE_PAC) */
1040*1031c584SApple OSS Distributions 
1041*1031c584SApple OSS Distributions 			for (lim = count, baseIdx = 0; lim; lim >>= 1) {
1042*1031c584SApple OSS Distributions 				inst = instances[baseIdx + (lim >> 1)];
1043*1031c584SApple OSS Distributions 				instance = (typeof(instance))INSTANCE_GET(inst);
1044*1031c584SApple OSS Distributions 
1045*1031c584SApple OSS Distributions 				if (ref->zoneSize) {
1046*1031c584SApple OSS Distributions 					addr = INSTANCE_PUT(inst) & ~kInstanceFlags;
1047*1031c584SApple OSS Distributions 				} else if (kInstanceFlagAddress & inst) {
1048*1031c584SApple OSS Distributions 					addr            = ~((IOTrackingAddress *)instance)->address;
1049*1031c584SApple OSS Distributions 					origsize = size = ((IOTrackingAddress *)instance)->size;
1050*1031c584SApple OSS Distributions 					if (!size) {
1051*1031c584SApple OSS Distributions 						size = 1;
1052*1031c584SApple OSS Distributions 					}
1053*1031c584SApple OSS Distributions 				} else {
1054*1031c584SApple OSS Distributions 					addr            = (uintptr_t) (instance + 1);
1055*1031c584SApple OSS Distributions 					origsize = size = instance->site->queue->allocSize;
1056*1031c584SApple OSS Distributions 				}
1057*1031c584SApple OSS Distributions 				if ((ptr >= addr) && (ptr < (addr + size))
1058*1031c584SApple OSS Distributions 
1059*1031c584SApple OSS Distributions 				    && (((vaddr + ptrIdx * sizeof(uintptr_t)) < addr)
1060*1031c584SApple OSS Distributions 				    || ((vaddr + ptrIdx * sizeof(uintptr_t)) >= (addr + size)))) {
1061*1031c584SApple OSS Distributions 					if (!(kInstanceFlagReferenced & inst)) {
1062*1031c584SApple OSS Distributions 						inst |= kInstanceFlagReferenced;
1063*1031c584SApple OSS Distributions 						instances[baseIdx + (lim >> 1)] = inst;
1064*1031c584SApple OSS Distributions 						ref->found++;
1065*1031c584SApple OSS Distributions 						if (!origsize) {
1066*1031c584SApple OSS Distributions 							ref->foundzlen++;
1067*1031c584SApple OSS Distributions 						}
1068*1031c584SApple OSS Distributions 					}
1069*1031c584SApple OSS Distributions 					break;
1070*1031c584SApple OSS Distributions 				}
1071*1031c584SApple OSS Distributions 				if (ptr > addr) {
1072*1031c584SApple OSS Distributions 					// move right
1073*1031c584SApple OSS Distributions 					baseIdx += (lim >> 1) + 1;
1074*1031c584SApple OSS Distributions 					lim--;
1075*1031c584SApple OSS Distributions 				}
1076*1031c584SApple OSS Distributions 				// else move left
1077*1031c584SApple OSS Distributions 			}
1078*1031c584SApple OSS Distributions 		}
1079*1031c584SApple OSS Distributions 		ref->bytes += page_size;
1080*1031c584SApple OSS Distributions 	}
1081*1031c584SApple OSS Distributions 
1082*1031c584SApple OSS Distributions 	if (gIOTrackingLeakScanCallback) {
1083*1031c584SApple OSS Distributions 		gIOTrackingLeakScanCallback(kIOTrackingLeakScanEnd);
1084*1031c584SApple OSS Distributions 	}
1085*1031c584SApple OSS Distributions }
1086*1031c584SApple OSS Distributions 
1087*1031c584SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1088*1031c584SApple OSS Distributions 
1089*1031c584SApple OSS Distributions extern "C" void
zone_leaks_scan(uintptr_t * instances,uint32_t count,uint32_t zoneSize,uint32_t * found)1090*1031c584SApple OSS Distributions zone_leaks_scan(uintptr_t * instances, uint32_t count, uint32_t zoneSize, uint32_t * found)
1091*1031c584SApple OSS Distributions {
1092*1031c584SApple OSS Distributions 	IOTrackingLeaksRef       ref;
1093*1031c584SApple OSS Distributions 	IOTrackingCallSiteInfo   siteInfo;
1094*1031c584SApple OSS Distributions 	uint32_t                 idx;
1095*1031c584SApple OSS Distributions 
1096*1031c584SApple OSS Distributions 	qsort(instances, count, sizeof(*instances), &IOTrackingZoneElementCompare);
1097*1031c584SApple OSS Distributions 
1098*1031c584SApple OSS Distributions 	bzero(&siteInfo, sizeof(siteInfo));
1099*1031c584SApple OSS Distributions 	bzero(&ref, sizeof(ref));
1100*1031c584SApple OSS Distributions 	ref.instances = instances;
1101*1031c584SApple OSS Distributions 	ref.count = count;
1102*1031c584SApple OSS Distributions 	ref.zoneSize = zoneSize;
1103*1031c584SApple OSS Distributions 
1104*1031c584SApple OSS Distributions 	for (idx = 0; idx < 2; idx++) {
1105*1031c584SApple OSS Distributions 		ref.bytes = 0;
1106*1031c584SApple OSS Distributions 		IOTrackingLeakScan(&ref);
1107*1031c584SApple OSS Distributions 		IOLog("leaks(%d) scanned %ld MB, instance count %d, found %d\n", idx, ref.bytes / 1024 / 1024, count, ref.found);
1108*1031c584SApple OSS Distributions 		if (count <= ref.found) {
1109*1031c584SApple OSS Distributions 			break;
1110*1031c584SApple OSS Distributions 		}
1111*1031c584SApple OSS Distributions 	}
1112*1031c584SApple OSS Distributions 
1113*1031c584SApple OSS Distributions 	*found = ref.found;
1114*1031c584SApple OSS Distributions }
1115*1031c584SApple OSS Distributions 
1116*1031c584SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1117*1031c584SApple OSS Distributions 
1118*1031c584SApple OSS Distributions static OSData *
IOTrackingLeaks(LIBKERN_CONSUMED OSData * data)1119*1031c584SApple OSS Distributions IOTrackingLeaks(LIBKERN_CONSUMED OSData * data)
1120*1031c584SApple OSS Distributions {
1121*1031c584SApple OSS Distributions 	IOTrackingLeaksRef       ref;
1122*1031c584SApple OSS Distributions 	IOTrackingCallSiteInfo   siteInfo;
1123*1031c584SApple OSS Distributions 	IOTrackingCallSite     * site;
1124*1031c584SApple OSS Distributions 	OSData                 * leakData;
1125*1031c584SApple OSS Distributions 	uintptr_t              * instances;
1126*1031c584SApple OSS Distributions 	IOTracking             * instance;
1127*1031c584SApple OSS Distributions 	uintptr_t                inst;
1128*1031c584SApple OSS Distributions 	uint32_t                 count, idx, numSites, dups, siteCount;
1129*1031c584SApple OSS Distributions 
1130*1031c584SApple OSS Distributions 	instances = (typeof(instances))data->getBytesNoCopy();
1131*1031c584SApple OSS Distributions 	count = (data->getLength() / sizeof(*instances));
1132*1031c584SApple OSS Distributions 	qsort(instances, count, sizeof(*instances), &IOTrackingAddressCompare);
1133*1031c584SApple OSS Distributions 
1134*1031c584SApple OSS Distributions 	bzero(&siteInfo, sizeof(siteInfo));
1135*1031c584SApple OSS Distributions 	bzero(&ref, sizeof(ref));
1136*1031c584SApple OSS Distributions 	ref.instances = instances;
1137*1031c584SApple OSS Distributions 	ref.count = count;
1138*1031c584SApple OSS Distributions 	for (idx = 0; idx < 2; idx++) {
1139*1031c584SApple OSS Distributions 		ref.bytes = 0;
1140*1031c584SApple OSS Distributions 		IOTrackingLeakScan(&ref);
1141*1031c584SApple 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);
1142*1031c584SApple OSS Distributions 		if (count <= ref.found) {
1143*1031c584SApple OSS Distributions 			break;
1144*1031c584SApple OSS Distributions 		}
1145*1031c584SApple OSS Distributions 	}
1146*1031c584SApple OSS Distributions 
1147*1031c584SApple OSS Distributions 	leakData = OSData::withCapacity(128 * sizeof(IOTrackingCallSiteInfo));
1148*1031c584SApple OSS Distributions 
1149*1031c584SApple OSS Distributions 	for (numSites = 0, idx = 0; idx < count; idx++) {
1150*1031c584SApple OSS Distributions 		inst = instances[idx];
1151*1031c584SApple OSS Distributions 		if (kInstanceFlagReferenced & inst) {
1152*1031c584SApple OSS Distributions 			continue;
1153*1031c584SApple OSS Distributions 		}
1154*1031c584SApple OSS Distributions 		instance = (typeof(instance))INSTANCE_GET(inst);
1155*1031c584SApple OSS Distributions 		site = instance->site;
1156*1031c584SApple OSS Distributions 		instances[numSites] = (uintptr_t) site;
1157*1031c584SApple OSS Distributions 		numSites++;
1158*1031c584SApple OSS Distributions 	}
1159*1031c584SApple OSS Distributions 
1160*1031c584SApple OSS Distributions 	for (idx = 0; idx < numSites; idx++) {
1161*1031c584SApple OSS Distributions 		inst = instances[idx];
1162*1031c584SApple OSS Distributions 		if (!inst) {
1163*1031c584SApple OSS Distributions 			continue;
1164*1031c584SApple OSS Distributions 		}
1165*1031c584SApple OSS Distributions 		site = (typeof(site))inst;
1166*1031c584SApple OSS Distributions 		for (siteCount = 1, dups = (idx + 1); dups < numSites; dups++) {
1167*1031c584SApple OSS Distributions 			if (instances[dups] == (uintptr_t) site) {
1168*1031c584SApple OSS Distributions 				siteCount++;
1169*1031c584SApple OSS Distributions 				instances[dups] = 0;
1170*1031c584SApple OSS Distributions 			}
1171*1031c584SApple OSS Distributions 		}
1172*1031c584SApple OSS Distributions 		siteInfo.count   = siteCount;
1173*1031c584SApple OSS Distributions 		siteInfo.size[0] = (site->size[0] * site->count) / siteCount;
1174*1031c584SApple OSS Distributions 		siteInfo.size[1] = (site->size[1] * site->count) / siteCount;
1175*1031c584SApple OSS Distributions 		CopyOutBacktraces(site, &siteInfo);
1176*1031c584SApple OSS Distributions 		leakData->appendBytes(&siteInfo, sizeof(siteInfo));
1177*1031c584SApple OSS Distributions 	}
1178*1031c584SApple OSS Distributions 	data->release();
1179*1031c584SApple OSS Distributions 
1180*1031c584SApple OSS Distributions 	return leakData;
1181*1031c584SApple OSS Distributions }
1182*1031c584SApple OSS Distributions 
1183*1031c584SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1184*1031c584SApple OSS Distributions 
1185*1031c584SApple OSS Distributions static bool
SkipName(uint32_t options,const char * name,size_t namesLen,const char * names)1186*1031c584SApple OSS Distributions SkipName(uint32_t options, const char * name, size_t namesLen, const char * names)
1187*1031c584SApple OSS Distributions {
1188*1031c584SApple OSS Distributions 	const char * scan;
1189*1031c584SApple OSS Distributions 	const char * next;
1190*1031c584SApple OSS Distributions 	bool         exclude, found;
1191*1031c584SApple OSS Distributions 	size_t       qLen, sLen;
1192*1031c584SApple OSS Distributions 
1193*1031c584SApple OSS Distributions 	if (!namesLen || !names) {
1194*1031c584SApple OSS Distributions 		return false;
1195*1031c584SApple OSS Distributions 	}
1196*1031c584SApple OSS Distributions 	// <len><name>...<len><name><0>
1197*1031c584SApple OSS Distributions 	exclude = (0 != (kIOTrackingExcludeNames & options));
1198*1031c584SApple OSS Distributions 	qLen    = strlen(name);
1199*1031c584SApple OSS Distributions 	scan    = names;
1200*1031c584SApple OSS Distributions 	found   = false;
1201*1031c584SApple OSS Distributions 	do{
1202*1031c584SApple OSS Distributions 		sLen = scan[0];
1203*1031c584SApple OSS Distributions 		scan++;
1204*1031c584SApple OSS Distributions 		next = scan + sLen;
1205*1031c584SApple OSS Distributions 		if (next >= (names + namesLen)) {
1206*1031c584SApple OSS Distributions 			break;
1207*1031c584SApple OSS Distributions 		}
1208*1031c584SApple OSS Distributions 		found = ((sLen == qLen) && !strncmp(scan, name, sLen));
1209*1031c584SApple OSS Distributions 		scan = next;
1210*1031c584SApple OSS Distributions 	}while (!found && (scan < (names + namesLen)));
1211*1031c584SApple OSS Distributions 
1212*1031c584SApple OSS Distributions 	return !(exclude ^ found);
1213*1031c584SApple OSS Distributions }
1214*1031c584SApple OSS Distributions 
1215*1031c584SApple OSS Distributions #endif /* IOTRACKING */
1216*1031c584SApple OSS Distributions 
1217*1031c584SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1218*1031c584SApple OSS Distributions 
1219*1031c584SApple 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)1220*1031c584SApple OSS Distributions IOTrackingDebug(uint32_t selector, uint32_t options, uint64_t value,
1221*1031c584SApple OSS Distributions     uint32_t intag, uint32_t inzsize,
1222*1031c584SApple OSS Distributions     const char * names, size_t namesLen,
1223*1031c584SApple OSS Distributions     size_t size, OSObject ** result)
1224*1031c584SApple OSS Distributions {
1225*1031c584SApple OSS Distributions 	kern_return_t            ret;
1226*1031c584SApple OSS Distributions 	OSData                 * data;
1227*1031c584SApple OSS Distributions 
1228*1031c584SApple OSS Distributions 	if (result) {
1229*1031c584SApple OSS Distributions 		*result = NULL;
1230*1031c584SApple OSS Distributions 	}
1231*1031c584SApple OSS Distributions 	data = NULL;
1232*1031c584SApple OSS Distributions 	ret = kIOReturnNotReady;
1233*1031c584SApple OSS Distributions 
1234*1031c584SApple OSS Distributions #if IOTRACKING
1235*1031c584SApple OSS Distributions 
1236*1031c584SApple OSS Distributions 	kern_return_t            kr;
1237*1031c584SApple OSS Distributions 	IOTrackingQueue        * queue;
1238*1031c584SApple OSS Distributions 	IOTracking             * instance;
1239*1031c584SApple OSS Distributions 	IOTrackingCallSite     * site;
1240*1031c584SApple OSS Distributions 	IOTrackingCallSiteInfo   siteInfo;
1241*1031c584SApple OSS Distributions 	IOTrackingUser         * user;
1242*1031c584SApple OSS Distributions 	task_t                   mapTask;
1243*1031c584SApple OSS Distributions 	mach_vm_address_t        mapAddress;
1244*1031c584SApple OSS Distributions 	mach_vm_size_t           mapSize;
1245*1031c584SApple OSS Distributions 	uint32_t                 num, idx, qIdx;
1246*1031c584SApple OSS Distributions 	uintptr_t                instFlags;
1247*1031c584SApple OSS Distributions 	proc_t                   proc;
1248*1031c584SApple OSS Distributions 	bool                     addresses;
1249*1031c584SApple OSS Distributions 
1250*1031c584SApple OSS Distributions 	ret = kIOReturnNotFound;
1251*1031c584SApple OSS Distributions 	proc = NULL;
1252*1031c584SApple OSS Distributions 	if (kIOTrackingGetMappings == selector) {
1253*1031c584SApple OSS Distributions 		if (value != -1ULL) {
1254*1031c584SApple OSS Distributions 			proc = proc_find((pid_t) value);
1255*1031c584SApple OSS Distributions 			if (!proc) {
1256*1031c584SApple OSS Distributions 				return kIOReturnNotFound;
1257*1031c584SApple OSS Distributions 			}
1258*1031c584SApple OSS Distributions 		}
1259*1031c584SApple OSS Distributions 	}
1260*1031c584SApple OSS Distributions 
1261*1031c584SApple OSS Distributions 	bzero(&siteInfo, sizeof(siteInfo));
1262*1031c584SApple OSS Distributions 	lck_mtx_lock(gIOTrackingLock);
1263*1031c584SApple OSS Distributions 	queue_iterate(&gIOTrackingQ, queue, IOTrackingQueue *, link)
1264*1031c584SApple OSS Distributions 	{
1265*1031c584SApple OSS Distributions 		if (SkipName(options, queue->name, namesLen, names)) {
1266*1031c584SApple OSS Distributions 			continue;
1267*1031c584SApple OSS Distributions 		}
1268*1031c584SApple OSS Distributions 
1269*1031c584SApple OSS Distributions 		if (!(kIOTracking & gIOKitDebug) && (kIOTrackingQueueTypeAlloc & queue->type)) {
1270*1031c584SApple OSS Distributions 			continue;
1271*1031c584SApple OSS Distributions 		}
1272*1031c584SApple OSS Distributions 
1273*1031c584SApple OSS Distributions 		switch (selector) {
1274*1031c584SApple OSS Distributions 		case kIOTrackingResetTracking:
1275*1031c584SApple OSS Distributions 		{
1276*1031c584SApple OSS Distributions 			IOTrackingReset(queue);
1277*1031c584SApple OSS Distributions 			ret = kIOReturnSuccess;
1278*1031c584SApple OSS Distributions 			break;
1279*1031c584SApple OSS Distributions 		}
1280*1031c584SApple OSS Distributions 
1281*1031c584SApple OSS Distributions 		case kIOTrackingStartCapture:
1282*1031c584SApple OSS Distributions 		case kIOTrackingStopCapture:
1283*1031c584SApple OSS Distributions 		{
1284*1031c584SApple OSS Distributions 			queue->captureOn = (kIOTrackingStartCapture == selector);
1285*1031c584SApple OSS Distributions 			ret = kIOReturnSuccess;
1286*1031c584SApple OSS Distributions 			break;
1287*1031c584SApple OSS Distributions 		}
1288*1031c584SApple OSS Distributions 
1289*1031c584SApple OSS Distributions 		case kIOTrackingSetMinCaptureSize:
1290*1031c584SApple OSS Distributions 		{
1291*1031c584SApple OSS Distributions 			queue->minCaptureSize = size;
1292*1031c584SApple OSS Distributions 			ret = kIOReturnSuccess;
1293*1031c584SApple OSS Distributions 			break;
1294*1031c584SApple OSS Distributions 		}
1295*1031c584SApple OSS Distributions 
1296*1031c584SApple OSS Distributions 		case kIOTrackingLeaks:
1297*1031c584SApple OSS Distributions 		{
1298*1031c584SApple OSS Distributions 			if (!(kIOTrackingQueueTypeAlloc & queue->type)) {
1299*1031c584SApple OSS Distributions 				break;
1300*1031c584SApple OSS Distributions 			}
1301*1031c584SApple OSS Distributions 
1302*1031c584SApple OSS Distributions 			if (!data) {
1303*1031c584SApple OSS Distributions 				data = OSData::withCapacity(1024 * sizeof(uintptr_t));
1304*1031c584SApple OSS Distributions 			}
1305*1031c584SApple OSS Distributions 
1306*1031c584SApple OSS Distributions 			IOTRecursiveLockLock(&queue->lock);
1307*1031c584SApple OSS Distributions 			for (idx = 0; idx < queue->numSiteQs; idx++) {
1308*1031c584SApple OSS Distributions 				queue_iterate(&queue->sites[idx], site, IOTrackingCallSite *, link)
1309*1031c584SApple OSS Distributions 				{
1310*1031c584SApple OSS Distributions 					addresses = false;
1311*1031c584SApple OSS Distributions 					queue_iterate(&site->instances, instance, IOTracking *, link)
1312*1031c584SApple OSS Distributions 					{
1313*1031c584SApple OSS Distributions 						if (site->addresses) {
1314*1031c584SApple OSS Distributions 							for (uint32_t hashIdx = 0; !addresses && (hashIdx < queue->numSiteQs); hashIdx++) {
1315*1031c584SApple OSS Distributions 								if (instance == site->addresses[hashIdx]) {
1316*1031c584SApple OSS Distributions 									addresses = true;
1317*1031c584SApple OSS Distributions 								}
1318*1031c584SApple OSS Distributions 							}
1319*1031c584SApple OSS Distributions 						}
1320*1031c584SApple OSS Distributions 						instFlags = (typeof(instFlags))instance;
1321*1031c584SApple OSS Distributions 						if (addresses) {
1322*1031c584SApple OSS Distributions 							instFlags |= kInstanceFlagAddress;
1323*1031c584SApple OSS Distributions 						}
1324*1031c584SApple OSS Distributions 						data->appendValue(instFlags);
1325*1031c584SApple OSS Distributions 					}
1326*1031c584SApple OSS Distributions 				}
1327*1031c584SApple OSS Distributions 			}
1328*1031c584SApple OSS Distributions 			// queue is locked
1329*1031c584SApple OSS Distributions 			ret = kIOReturnSuccess;
1330*1031c584SApple OSS Distributions 			break;
1331*1031c584SApple OSS Distributions 		}
1332*1031c584SApple OSS Distributions 
1333*1031c584SApple OSS Distributions 
1334*1031c584SApple OSS Distributions 		case kIOTrackingGetTracking:
1335*1031c584SApple OSS Distributions 		{
1336*1031c584SApple OSS Distributions 			if (kIOTrackingQueueTypeMap & queue->type) {
1337*1031c584SApple OSS Distributions 				break;
1338*1031c584SApple OSS Distributions 			}
1339*1031c584SApple OSS Distributions 
1340*1031c584SApple OSS Distributions 			if (!data) {
1341*1031c584SApple OSS Distributions 				data = OSData::withCapacity(128 * sizeof(IOTrackingCallSiteInfo));
1342*1031c584SApple OSS Distributions 			}
1343*1031c584SApple OSS Distributions 
1344*1031c584SApple OSS Distributions 			IOTRecursiveLockLock(&queue->lock);
1345*1031c584SApple OSS Distributions 			num = queue->siteCount;
1346*1031c584SApple OSS Distributions 			idx = 0;
1347*1031c584SApple OSS Distributions 			for (qIdx = 0; qIdx < queue->numSiteQs; qIdx++) {
1348*1031c584SApple OSS Distributions 				queue_iterate(&queue->sites[qIdx], site, IOTrackingCallSite *, link)
1349*1031c584SApple OSS Distributions 				{
1350*1031c584SApple OSS Distributions 					assert(idx < num);
1351*1031c584SApple OSS Distributions 					idx++;
1352*1031c584SApple OSS Distributions 
1353*1031c584SApple OSS Distributions 					size_t tsize[2];
1354*1031c584SApple OSS Distributions 					uint32_t count = site->count;
1355*1031c584SApple OSS Distributions 					tsize[0] = site->size[0];
1356*1031c584SApple OSS Distributions 					tsize[1] = site->size[1];
1357*1031c584SApple OSS Distributions 
1358*1031c584SApple OSS Distributions 					if (intag || inzsize) {
1359*1031c584SApple OSS Distributions 						uintptr_t addr;
1360*1031c584SApple OSS Distributions 						vm_size_t size, zoneSize;
1361*1031c584SApple OSS Distributions 						vm_tag_t  tag;
1362*1031c584SApple OSS Distributions 
1363*1031c584SApple OSS Distributions 						if (kIOTrackingQueueTypeAlloc & queue->type) {
1364*1031c584SApple OSS Distributions 							addresses = false;
1365*1031c584SApple OSS Distributions 							count = 0;
1366*1031c584SApple OSS Distributions 							tsize[0] = tsize[1] = 0;
1367*1031c584SApple OSS Distributions 							queue_iterate(&site->instances, instance, IOTracking *, link)
1368*1031c584SApple OSS Distributions 							{
1369*1031c584SApple OSS Distributions 								if (site->addresses) {
1370*1031c584SApple OSS Distributions 									for (uint32_t hashIdx = 0; !addresses && (hashIdx < queue->numSiteQs); hashIdx++) {
1371*1031c584SApple OSS Distributions 										if (instance == site->addresses[hashIdx]) {
1372*1031c584SApple OSS Distributions 											addresses = true;
1373*1031c584SApple OSS Distributions 										}
1374*1031c584SApple OSS Distributions 									}
1375*1031c584SApple OSS Distributions 								}
1376*1031c584SApple OSS Distributions 
1377*1031c584SApple OSS Distributions 								if (addresses) {
1378*1031c584SApple OSS Distributions 									addr = ~((IOTrackingAddress *)instance)->address;
1379*1031c584SApple OSS Distributions 								} else {
1380*1031c584SApple OSS Distributions 									addr = (uintptr_t) (instance + 1);
1381*1031c584SApple OSS Distributions 								}
1382*1031c584SApple OSS Distributions 
1383*1031c584SApple OSS Distributions 								kr = vm_kern_allocation_info(addr, &size, &tag, &zoneSize);
1384*1031c584SApple OSS Distributions 								if (KERN_SUCCESS != kr) {
1385*1031c584SApple OSS Distributions 									continue;
1386*1031c584SApple OSS Distributions 								}
1387*1031c584SApple OSS Distributions 
1388*1031c584SApple OSS Distributions 								if ((VM_KERN_MEMORY_NONE != intag) && (intag != tag)) {
1389*1031c584SApple OSS Distributions 									continue;
1390*1031c584SApple OSS Distributions 								}
1391*1031c584SApple OSS Distributions 								if (inzsize && (inzsize != zoneSize)) {
1392*1031c584SApple OSS Distributions 									continue;
1393*1031c584SApple OSS Distributions 								}
1394*1031c584SApple OSS Distributions 
1395*1031c584SApple OSS Distributions 								count++;
1396*1031c584SApple OSS Distributions 								tsize[0] += size;
1397*1031c584SApple OSS Distributions 							}
1398*1031c584SApple OSS Distributions 						} else {
1399*1031c584SApple OSS Distributions 							if (!intag || inzsize || (intag != site->tag)) {
1400*1031c584SApple OSS Distributions 								continue;
1401*1031c584SApple OSS Distributions 							}
1402*1031c584SApple OSS Distributions 						}
1403*1031c584SApple OSS Distributions 					}
1404*1031c584SApple OSS Distributions 
1405*1031c584SApple OSS Distributions 					if (!count) {
1406*1031c584SApple OSS Distributions 						continue;
1407*1031c584SApple OSS Distributions 					}
1408*1031c584SApple OSS Distributions 					if (size && ((tsize[0] + tsize[1]) < size)) {
1409*1031c584SApple OSS Distributions 						continue;
1410*1031c584SApple OSS Distributions 					}
1411*1031c584SApple OSS Distributions 					siteInfo.count   = count;
1412*1031c584SApple OSS Distributions 					siteInfo.size[0] = tsize[0];
1413*1031c584SApple OSS Distributions 					siteInfo.size[1] = tsize[1];
1414*1031c584SApple OSS Distributions 					CopyOutBacktraces(site, &siteInfo);
1415*1031c584SApple OSS Distributions 					data->appendBytes(&siteInfo, sizeof(siteInfo));
1416*1031c584SApple OSS Distributions 				}
1417*1031c584SApple OSS Distributions 			}
1418*1031c584SApple OSS Distributions 			assert(idx == num);
1419*1031c584SApple OSS Distributions 			IOTRecursiveLockUnlock(&queue->lock);
1420*1031c584SApple OSS Distributions 			ret = kIOReturnSuccess;
1421*1031c584SApple OSS Distributions 			break;
1422*1031c584SApple OSS Distributions 		}
1423*1031c584SApple OSS Distributions 
1424*1031c584SApple OSS Distributions 		case kIOTrackingGetMappings:
1425*1031c584SApple OSS Distributions 		{
1426*1031c584SApple OSS Distributions 			if (!(kIOTrackingQueueTypeMap & queue->type)) {
1427*1031c584SApple OSS Distributions 				break;
1428*1031c584SApple OSS Distributions 			}
1429*1031c584SApple OSS Distributions 			if (!data) {
1430*1031c584SApple OSS Distributions 				data = OSData::withCapacity((unsigned int) page_size);
1431*1031c584SApple OSS Distributions 			}
1432*1031c584SApple OSS Distributions 
1433*1031c584SApple OSS Distributions 			IOTRecursiveLockLock(&queue->lock);
1434*1031c584SApple OSS Distributions 			num = queue->siteCount;
1435*1031c584SApple OSS Distributions 			idx = 0;
1436*1031c584SApple OSS Distributions 			for (qIdx = 0; qIdx < queue->numSiteQs; qIdx++) {
1437*1031c584SApple OSS Distributions 				queue_iterate(&queue->sites[qIdx], user, IOTrackingUser *, link)
1438*1031c584SApple OSS Distributions 				{
1439*1031c584SApple OSS Distributions 					assert(idx < num);
1440*1031c584SApple OSS Distributions 					idx++;
1441*1031c584SApple OSS Distributions 
1442*1031c584SApple OSS Distributions 					kr = IOMemoryMapTracking(user, &mapTask, &mapAddress, &mapSize);
1443*1031c584SApple OSS Distributions 					if (kIOReturnSuccess != kr) {
1444*1031c584SApple OSS Distributions 						continue;
1445*1031c584SApple OSS Distributions 					}
1446*1031c584SApple OSS Distributions 					if (proc && (mapTask != proc_task(proc))) {
1447*1031c584SApple OSS Distributions 						continue;
1448*1031c584SApple OSS Distributions 					}
1449*1031c584SApple OSS Distributions 					if (size && (mapSize < size)) {
1450*1031c584SApple OSS Distributions 						continue;
1451*1031c584SApple OSS Distributions 					}
1452*1031c584SApple OSS Distributions 
1453*1031c584SApple OSS Distributions 					siteInfo.count      = 1;
1454*1031c584SApple OSS Distributions 					siteInfo.size[0]    = mapSize;
1455*1031c584SApple OSS Distributions 					siteInfo.address    = mapAddress;
1456*1031c584SApple OSS Distributions 					siteInfo.addressPID = task_pid(mapTask);
1457*1031c584SApple OSS Distributions 					siteInfo.btPID      = user->btPID;
1458*1031c584SApple OSS Distributions 
1459*1031c584SApple OSS Distributions 					for (uint32_t j = 0; j < kIOTrackingCallSiteBTs; j++) {
1460*1031c584SApple OSS Distributions 						siteInfo.bt[0][j] = VM_KERNEL_UNSLIDE(user->bt[j]);
1461*1031c584SApple OSS Distributions 					}
1462*1031c584SApple OSS Distributions 					uint32_t * bt32 = (typeof(bt32)) & user->btUser[0];
1463*1031c584SApple OSS Distributions 					uint64_t * bt64 = (typeof(bt64))((void *) &user->btUser[0]);
1464*1031c584SApple OSS Distributions 					for (uint32_t j = 0; j < kIOTrackingCallSiteBTs; j++) {
1465*1031c584SApple OSS Distributions 						if (j >= user->userCount) {
1466*1031c584SApple OSS Distributions 							siteInfo.bt[1][j] = 0;
1467*1031c584SApple OSS Distributions 						} else if (user->user32) {
1468*1031c584SApple OSS Distributions 							siteInfo.bt[1][j] = bt32[j];
1469*1031c584SApple OSS Distributions 						} else {
1470*1031c584SApple OSS Distributions 							siteInfo.bt[1][j] = bt64[j];
1471*1031c584SApple OSS Distributions 						}
1472*1031c584SApple OSS Distributions 					}
1473*1031c584SApple OSS Distributions 					data->appendBytes(&siteInfo, sizeof(siteInfo));
1474*1031c584SApple OSS Distributions 				}
1475*1031c584SApple OSS Distributions 			}
1476*1031c584SApple OSS Distributions 			assert(idx == num);
1477*1031c584SApple OSS Distributions 			IOTRecursiveLockUnlock(&queue->lock);
1478*1031c584SApple OSS Distributions 			ret = kIOReturnSuccess;
1479*1031c584SApple OSS Distributions 			break;
1480*1031c584SApple OSS Distributions 		}
1481*1031c584SApple OSS Distributions 
1482*1031c584SApple OSS Distributions 		default:
1483*1031c584SApple OSS Distributions 			ret = kIOReturnUnsupported;
1484*1031c584SApple OSS Distributions 			break;
1485*1031c584SApple OSS Distributions 		}
1486*1031c584SApple OSS Distributions 	}
1487*1031c584SApple OSS Distributions 
1488*1031c584SApple OSS Distributions 	if ((kIOTrackingLeaks == selector) && data) {
1489*1031c584SApple OSS Distributions 		data = IOTrackingLeaks(data);
1490*1031c584SApple OSS Distributions 		queue_iterate(&gIOTrackingQ, queue, IOTrackingQueue *, link)
1491*1031c584SApple OSS Distributions 		{
1492*1031c584SApple OSS Distributions 			if (SkipName(options, queue->name, namesLen, names)) {
1493*1031c584SApple OSS Distributions 				continue;
1494*1031c584SApple OSS Distributions 			}
1495*1031c584SApple OSS Distributions 			if (!(kIOTrackingQueueTypeAlloc & queue->type)) {
1496*1031c584SApple OSS Distributions 				continue;
1497*1031c584SApple OSS Distributions 			}
1498*1031c584SApple OSS Distributions 			IOTRecursiveLockUnlock(&queue->lock);
1499*1031c584SApple OSS Distributions 		}
1500*1031c584SApple OSS Distributions 	}
1501*1031c584SApple OSS Distributions 
1502*1031c584SApple OSS Distributions 	lck_mtx_unlock(gIOTrackingLock);
1503*1031c584SApple OSS Distributions 
1504*1031c584SApple OSS Distributions 	if ((kIOTrackingLeaks == selector) && namesLen && names) {
1505*1031c584SApple OSS Distributions 		const char * scan;
1506*1031c584SApple OSS Distributions 		const char * next;
1507*1031c584SApple OSS Distributions 		uint8_t      sLen;
1508*1031c584SApple OSS Distributions 
1509*1031c584SApple OSS Distributions 		if (!data) {
1510*1031c584SApple OSS Distributions 			data = OSData::withCapacity(4096 * sizeof(uintptr_t));
1511*1031c584SApple OSS Distributions 		}
1512*1031c584SApple OSS Distributions 
1513*1031c584SApple OSS Distributions 		// <len><name>...<len><name><0>
1514*1031c584SApple OSS Distributions 		scan    = names;
1515*1031c584SApple OSS Distributions 		do{
1516*1031c584SApple OSS Distributions 			sLen = ((uint8_t) scan[0]);
1517*1031c584SApple OSS Distributions 			scan++;
1518*1031c584SApple OSS Distributions 			next = scan + sLen;
1519*1031c584SApple OSS Distributions 			if (next >= (names + namesLen)) {
1520*1031c584SApple OSS Distributions 				break;
1521*1031c584SApple OSS Distributions 			}
1522*1031c584SApple OSS Distributions 			kr = zone_leaks(scan, sLen, ^(uint32_t count, uint32_t eSize, btref_t ref) {
1523*1031c584SApple OSS Distributions 				IOTrackingCallSiteInfo siteInfo = {
1524*1031c584SApple OSS Distributions 				        .count   = count,
1525*1031c584SApple OSS Distributions 				        .size[0] = eSize * count,
1526*1031c584SApple OSS Distributions 				};
1527*1031c584SApple OSS Distributions 
1528*1031c584SApple OSS Distributions 				btref_decode_unslide(ref, siteInfo.bt[0]);
1529*1031c584SApple OSS Distributions 
1530*1031c584SApple OSS Distributions 				data->appendBytes(&siteInfo, sizeof(siteInfo));
1531*1031c584SApple OSS Distributions 			});
1532*1031c584SApple OSS Distributions 			if (KERN_SUCCESS == kr) {
1533*1031c584SApple OSS Distributions 				ret = kIOReturnSuccess;
1534*1031c584SApple OSS Distributions 			} else if (KERN_INVALID_NAME != kr) {
1535*1031c584SApple OSS Distributions 				ret = kIOReturnVMError;
1536*1031c584SApple OSS Distributions 			}
1537*1031c584SApple OSS Distributions 			scan = next;
1538*1031c584SApple OSS Distributions 		}while (scan < (names + namesLen));
1539*1031c584SApple OSS Distributions 	}
1540*1031c584SApple OSS Distributions 
1541*1031c584SApple OSS Distributions 	if (data) {
1542*1031c584SApple OSS Distributions 		switch (selector) {
1543*1031c584SApple OSS Distributions 		case kIOTrackingLeaks:
1544*1031c584SApple OSS Distributions 		case kIOTrackingGetTracking:
1545*1031c584SApple OSS Distributions 		case kIOTrackingGetMappings:
1546*1031c584SApple OSS Distributions 		{
1547*1031c584SApple OSS Distributions 			IOTrackingCallSiteInfo * siteInfos;
1548*1031c584SApple OSS Distributions 			siteInfos = (typeof(siteInfos))data->getBytesNoCopy();
1549*1031c584SApple OSS Distributions 			num = (data->getLength() / sizeof(*siteInfos));
1550*1031c584SApple OSS Distributions 			qsort(siteInfos, num, sizeof(*siteInfos), &IOTrackingCallSiteInfoCompare);
1551*1031c584SApple OSS Distributions 			break;
1552*1031c584SApple OSS Distributions 		}
1553*1031c584SApple OSS Distributions 		default: assert(false); break;
1554*1031c584SApple OSS Distributions 		}
1555*1031c584SApple OSS Distributions 	}
1556*1031c584SApple OSS Distributions 
1557*1031c584SApple OSS Distributions 	*result = data;
1558*1031c584SApple OSS Distributions 	if (proc) {
1559*1031c584SApple OSS Distributions 		proc_rele(proc);
1560*1031c584SApple OSS Distributions 	}
1561*1031c584SApple OSS Distributions 
1562*1031c584SApple OSS Distributions #endif /* IOTRACKING */
1563*1031c584SApple OSS Distributions 
1564*1031c584SApple OSS Distributions 	return ret;
1565*1031c584SApple OSS Distributions }
1566*1031c584SApple OSS Distributions 
1567*1031c584SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1568*1031c584SApple OSS Distributions 
1569*1031c584SApple OSS Distributions #include <IOKit/IOKitDiagnosticsUserClient.h>
1570*1031c584SApple OSS Distributions 
1571*1031c584SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1572*1031c584SApple OSS Distributions 
1573*1031c584SApple OSS Distributions #undef super
1574*1031c584SApple OSS Distributions #define super IOUserClient2022
1575*1031c584SApple OSS Distributions 
OSDefineMetaClassAndStructors(IOKitDiagnosticsClient,IOUserClient2022)1576*1031c584SApple OSS Distributions OSDefineMetaClassAndStructors(IOKitDiagnosticsClient, IOUserClient2022)
1577*1031c584SApple OSS Distributions 
1578*1031c584SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1579*1031c584SApple OSS Distributions 
1580*1031c584SApple OSS Distributions IOUserClient * IOKitDiagnosticsClient::withTask(task_t owningTask)
1581*1031c584SApple OSS Distributions {
1582*1031c584SApple OSS Distributions #if IOTRACKING
1583*1031c584SApple OSS Distributions 	IOKitDiagnosticsClient * inst;
1584*1031c584SApple OSS Distributions 
1585*1031c584SApple OSS Distributions 	inst = new IOKitDiagnosticsClient;
1586*1031c584SApple OSS Distributions 	if (inst && !inst->init()) {
1587*1031c584SApple OSS Distributions 		inst->release();
1588*1031c584SApple OSS Distributions 		inst = NULL;
1589*1031c584SApple OSS Distributions 	}
1590*1031c584SApple OSS Distributions 
1591*1031c584SApple OSS Distributions 	inst->setProperty(kIOUserClientDefaultLockingKey, kOSBooleanTrue);
1592*1031c584SApple OSS Distributions 	inst->setProperty(kIOUserClientDefaultLockingSetPropertiesKey, kOSBooleanTrue);
1593*1031c584SApple OSS Distributions 	inst->setProperty(kIOUserClientDefaultLockingSingleThreadExternalMethodKey, kOSBooleanTrue);
1594*1031c584SApple OSS Distributions 
1595*1031c584SApple OSS Distributions 	inst->setProperty(kIOUserClientEntitlementsKey, kOSBooleanFalse);
1596*1031c584SApple OSS Distributions 
1597*1031c584SApple OSS Distributions 	return inst;
1598*1031c584SApple OSS Distributions #else
1599*1031c584SApple OSS Distributions 	return NULL;
1600*1031c584SApple OSS Distributions #endif
1601*1031c584SApple OSS Distributions }
1602*1031c584SApple OSS Distributions 
1603*1031c584SApple OSS Distributions IOReturn
clientClose(void)1604*1031c584SApple OSS Distributions IOKitDiagnosticsClient::clientClose(void)
1605*1031c584SApple OSS Distributions {
1606*1031c584SApple OSS Distributions 	terminate();
1607*1031c584SApple OSS Distributions 	return kIOReturnSuccess;
1608*1031c584SApple OSS Distributions }
1609*1031c584SApple OSS Distributions 
1610*1031c584SApple OSS Distributions IOReturn
setProperties(OSObject * properties)1611*1031c584SApple OSS Distributions IOKitDiagnosticsClient::setProperties(OSObject * properties)
1612*1031c584SApple OSS Distributions {
1613*1031c584SApple OSS Distributions 	IOReturn kr = kIOReturnUnsupported;
1614*1031c584SApple OSS Distributions 	return kr;
1615*1031c584SApple OSS Distributions }
1616*1031c584SApple OSS Distributions 
1617*1031c584SApple OSS Distributions 
1618*1031c584SApple OSS Distributions IOReturn
IOTrackingMethodDispatched(OSObject * target,void * reference,IOExternalMethodArguments * args)1619*1031c584SApple OSS Distributions IOTrackingMethodDispatched(OSObject * target, void * reference,
1620*1031c584SApple OSS Distributions     IOExternalMethodArguments * args)
1621*1031c584SApple OSS Distributions {
1622*1031c584SApple OSS Distributions 	IOReturn                           ret = kIOReturnBadArgument;
1623*1031c584SApple OSS Distributions 	const IOKitDiagnosticsParameters * params;
1624*1031c584SApple OSS Distributions 	const char * names;
1625*1031c584SApple OSS Distributions 	size_t       namesLen;
1626*1031c584SApple OSS Distributions 	OSObject   * result;
1627*1031c584SApple OSS Distributions 
1628*1031c584SApple OSS Distributions 	if (args->structureInputSize < sizeof(IOKitDiagnosticsParameters)) {
1629*1031c584SApple OSS Distributions 		return kIOReturnBadArgument;
1630*1031c584SApple OSS Distributions 	}
1631*1031c584SApple OSS Distributions 	params = (typeof(params))args->structureInput;
1632*1031c584SApple OSS Distributions 	if (!params) {
1633*1031c584SApple OSS Distributions 		return kIOReturnBadArgument;
1634*1031c584SApple OSS Distributions 	}
1635*1031c584SApple OSS Distributions 
1636*1031c584SApple OSS Distributions 	names = NULL;
1637*1031c584SApple OSS Distributions 	namesLen = args->structureInputSize - sizeof(IOKitDiagnosticsParameters);
1638*1031c584SApple OSS Distributions 	if (namesLen) {
1639*1031c584SApple OSS Distributions 		names = (typeof(names))(params + 1);
1640*1031c584SApple OSS Distributions 	}
1641*1031c584SApple OSS Distributions 
1642*1031c584SApple OSS Distributions 	ret = IOTrackingDebug(args->selector, params->options, params->value, params->tag, params->zsize, names, namesLen, params->size, &result);
1643*1031c584SApple OSS Distributions 	if ((kIOReturnSuccess == ret) && args->structureVariableOutputData) {
1644*1031c584SApple OSS Distributions 		*args->structureVariableOutputData = result;
1645*1031c584SApple OSS Distributions 	} else if (result) {
1646*1031c584SApple OSS Distributions 		result->release();
1647*1031c584SApple OSS Distributions 	}
1648*1031c584SApple OSS Distributions 	return ret;
1649*1031c584SApple OSS Distributions }
1650*1031c584SApple OSS Distributions 
1651*1031c584SApple OSS Distributions IOReturn
externalMethod(uint32_t selector,IOExternalMethodArgumentsOpaque * args)1652*1031c584SApple OSS Distributions IOKitDiagnosticsClient::externalMethod(uint32_t selector, IOExternalMethodArgumentsOpaque * args)
1653*1031c584SApple OSS Distributions {
1654*1031c584SApple OSS Distributions 	static const IOExternalMethodDispatch2022 dispatchArray[] = {
1655*1031c584SApple OSS Distributions 		[kIOTrackingGetTracking] = {
1656*1031c584SApple OSS Distributions 			.function                             = &IOTrackingMethodDispatched,
1657*1031c584SApple OSS Distributions 			.checkScalarInputCount    = 0,
1658*1031c584SApple OSS Distributions 			.checkStructureInputSize  = kIOUCVariableStructureSize,
1659*1031c584SApple OSS Distributions 			.checkScalarOutputCount   = 0,
1660*1031c584SApple OSS Distributions 			.checkStructureOutputSize = 0,
1661*1031c584SApple OSS Distributions 			.allowAsync               = false,
1662*1031c584SApple OSS Distributions 			.checkEntitlement         = NULL,
1663*1031c584SApple OSS Distributions 		},
1664*1031c584SApple OSS Distributions 		[kIOTrackingGetMappings] = {
1665*1031c584SApple OSS Distributions 			.function                             = &IOTrackingMethodDispatched,
1666*1031c584SApple OSS Distributions 			.checkScalarInputCount    = 0,
1667*1031c584SApple OSS Distributions 			.checkStructureInputSize  = kIOUCVariableStructureSize,
1668*1031c584SApple OSS Distributions 			.checkScalarOutputCount   = 0,
1669*1031c584SApple OSS Distributions 			.checkStructureOutputSize = 0,
1670*1031c584SApple OSS Distributions 			.allowAsync               = false,
1671*1031c584SApple OSS Distributions 			.checkEntitlement         = NULL,
1672*1031c584SApple OSS Distributions 		},
1673*1031c584SApple OSS Distributions 		[kIOTrackingResetTracking] = {
1674*1031c584SApple OSS Distributions 			.function                             = &IOTrackingMethodDispatched,
1675*1031c584SApple OSS Distributions 			.checkScalarInputCount    = 0,
1676*1031c584SApple OSS Distributions 			.checkStructureInputSize  = kIOUCVariableStructureSize,
1677*1031c584SApple OSS Distributions 			.checkScalarOutputCount   = 0,
1678*1031c584SApple OSS Distributions 			.checkStructureOutputSize = 0,
1679*1031c584SApple OSS Distributions 			.allowAsync               = false,
1680*1031c584SApple OSS Distributions 			.checkEntitlement         = NULL,
1681*1031c584SApple OSS Distributions 		},
1682*1031c584SApple OSS Distributions 		[kIOTrackingStartCapture] = {
1683*1031c584SApple OSS Distributions 			.function                             = &IOTrackingMethodDispatched,
1684*1031c584SApple OSS Distributions 			.checkScalarInputCount    = 0,
1685*1031c584SApple OSS Distributions 			.checkStructureInputSize  = kIOUCVariableStructureSize,
1686*1031c584SApple OSS Distributions 			.checkScalarOutputCount   = 0,
1687*1031c584SApple OSS Distributions 			.checkStructureOutputSize = 0,
1688*1031c584SApple OSS Distributions 			.allowAsync               = false,
1689*1031c584SApple OSS Distributions 			.checkEntitlement         = NULL,
1690*1031c584SApple OSS Distributions 		},
1691*1031c584SApple OSS Distributions 		[kIOTrackingStopCapture] = {
1692*1031c584SApple OSS Distributions 			.function                             = &IOTrackingMethodDispatched,
1693*1031c584SApple OSS Distributions 			.checkScalarInputCount    = 0,
1694*1031c584SApple OSS Distributions 			.checkStructureInputSize  = kIOUCVariableStructureSize,
1695*1031c584SApple OSS Distributions 			.checkScalarOutputCount   = 0,
1696*1031c584SApple OSS Distributions 			.checkStructureOutputSize = 0,
1697*1031c584SApple OSS Distributions 			.allowAsync               = false,
1698*1031c584SApple OSS Distributions 			.checkEntitlement         = NULL,
1699*1031c584SApple OSS Distributions 		},
1700*1031c584SApple OSS Distributions 		[kIOTrackingSetMinCaptureSize] = {
1701*1031c584SApple OSS Distributions 			.function                             = &IOTrackingMethodDispatched,
1702*1031c584SApple OSS Distributions 			.checkScalarInputCount    = 0,
1703*1031c584SApple OSS Distributions 			.checkStructureInputSize  = kIOUCVariableStructureSize,
1704*1031c584SApple OSS Distributions 			.checkScalarOutputCount   = 0,
1705*1031c584SApple OSS Distributions 			.checkStructureOutputSize = 0,
1706*1031c584SApple OSS Distributions 			.allowAsync               = false,
1707*1031c584SApple OSS Distributions 			.checkEntitlement         = NULL,
1708*1031c584SApple OSS Distributions 		},
1709*1031c584SApple OSS Distributions 		[kIOTrackingLeaks] = {
1710*1031c584SApple OSS Distributions 			.function                             = &IOTrackingMethodDispatched,
1711*1031c584SApple OSS Distributions 			.checkScalarInputCount    = 0,
1712*1031c584SApple OSS Distributions 			.checkStructureInputSize  = kIOUCVariableStructureSize,
1713*1031c584SApple OSS Distributions 			.checkScalarOutputCount   = 0,
1714*1031c584SApple OSS Distributions 			.checkStructureOutputSize = 0,
1715*1031c584SApple OSS Distributions 			.allowAsync               = false,
1716*1031c584SApple OSS Distributions 			.checkEntitlement         = NULL,
1717*1031c584SApple OSS Distributions 		},
1718*1031c584SApple OSS Distributions 	};
1719*1031c584SApple OSS Distributions 
1720*1031c584SApple OSS Distributions 	return dispatchExternalMethod(selector, args, dispatchArray, sizeof(dispatchArray) / sizeof(dispatchArray[0]), this, NULL);
1721*1031c584SApple OSS Distributions }
1722*1031c584SApple OSS Distributions 
1723*1031c584SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1724