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