1c1dac77fSApple OSS Distributions /* 288cc0b97SApple OSS Distributions * Copyright (c) 1998-2016 Apple Inc. All rights reserved. 3c1dac77fSApple OSS Distributions * 4e13b1fa5SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5c1dac77fSApple OSS Distributions * 6e13b1fa5SApple OSS Distributions * This file contains Original Code and/or Modifications of Original Code 7e13b1fa5SApple OSS Distributions * as defined in and that are subject to the Apple Public Source License 8e13b1fa5SApple OSS Distributions * Version 2.0 (the 'License'). You may not use this file except in 9e13b1fa5SApple OSS Distributions * compliance with the License. The rights granted to you under the License 10e13b1fa5SApple OSS Distributions * may not be used to create, or enable the creation or redistribution of, 11e13b1fa5SApple OSS Distributions * unlawful or unlicensed copies of an Apple operating system, or to 12e13b1fa5SApple OSS Distributions * circumvent, violate, or enable the circumvention or violation of, any 13e13b1fa5SApple OSS Distributions * terms of an Apple operating system software license agreement. 14c1dac77fSApple OSS Distributions * 15e13b1fa5SApple OSS Distributions * Please obtain a copy of the License at 16e13b1fa5SApple OSS Distributions * http://www.opensource.apple.com/apsl/ and read it before using this file. 17e13b1fa5SApple OSS Distributions * 18e13b1fa5SApple OSS Distributions * The Original Code and all software distributed under the License are 19e13b1fa5SApple OSS Distributions * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20c1dac77fSApple OSS Distributions * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21c1dac77fSApple OSS Distributions * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22e13b1fa5SApple OSS Distributions * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23e13b1fa5SApple OSS Distributions * Please see the License for the specific language governing rights and 24e13b1fa5SApple OSS Distributions * limitations under the License. 25c1dac77fSApple OSS Distributions * 26e13b1fa5SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27c1dac77fSApple OSS Distributions */ 28c1dac77fSApple OSS Distributions 290f3703acSApple OSS Distributions 3014e3d835SApple OSS Distributions #include <sys/sysctl.h> 310f3703acSApple OSS Distributions extern "C" { 320f3703acSApple OSS Distributions #include <vm/vm_kern.h> 3388cc0b97SApple OSS Distributions #include <kern/task.h> 3488cc0b97SApple OSS Distributions #include <kern/debug.h> 350f3703acSApple OSS Distributions } 3614e3d835SApple OSS Distributions 37855239e5SApple OSS Distributions #include <libkern/c++/OSContainers.h> 380f3703acSApple OSS Distributions #include <libkern/OSDebug.h> 39855239e5SApple OSS Distributions #include <libkern/c++/OSCPPDebug.h> 4088cc0b97SApple OSS Distributions #include <kern/backtrace.h> 41855239e5SApple OSS Distributions 42c1dac77fSApple OSS Distributions #include <IOKit/IOKitDebug.h> 43c1dac77fSApple OSS Distributions #include <IOKit/IOLib.h> 44c1dac77fSApple OSS Distributions #include <IOKit/assert.h> 45c1dac77fSApple OSS Distributions #include <IOKit/IODeviceTreeSupport.h> 46c1dac77fSApple OSS Distributions #include <IOKit/IOService.h> 47c1dac77fSApple OSS Distributions 4888cc0b97SApple OSS Distributions #include "IOKitKernelInternal.h" 4988cc0b97SApple OSS Distributions 50c1dac77fSApple OSS Distributions #ifdef IOKITDEBUG 5114e3d835SApple OSS Distributions #define DEBUG_INIT_VALUE IOKITDEBUG 5214e3d835SApple OSS Distributions #else 5314e3d835SApple OSS Distributions #define DEBUG_INIT_VALUE 0 54c1dac77fSApple OSS Distributions #endif 5514e3d835SApple OSS Distributions 5614e3d835SApple OSS Distributions SInt64 gIOKitDebug = DEBUG_INIT_VALUE; 57855239e5SApple OSS Distributions SInt64 gIOKitTrace = 0; 58855239e5SApple OSS Distributions 59a3bb9fccSApple OSS Distributions #if DEVELOPMENT || DEBUG 60a3bb9fccSApple OSS Distributions #define IODEBUG_CTLFLAGS CTLFLAG_RW 61a3bb9fccSApple OSS Distributions #else 62a3bb9fccSApple OSS Distributions #define IODEBUG_CTLFLAGS CTLFLAG_RD 63a3bb9fccSApple OSS Distributions #endif 64a3bb9fccSApple OSS Distributions 65855239e5SApple OSS Distributions SYSCTL_QUAD(_debug, OID_AUTO, iotrace, CTLFLAG_RW | CTLFLAG_LOCKED, &gIOKitTrace, "trace io"); 6614e3d835SApple OSS Distributions 6776e12aa3SApple OSS Distributions static int 6876e12aa3SApple OSS Distributions sysctl_debug_iokit 6976e12aa3SApple OSS Distributions (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req) 7076e12aa3SApple OSS Distributions { 7176e12aa3SApple OSS Distributions SInt64 newValue; 7276e12aa3SApple OSS Distributions int changed, error = sysctl_io_number(req, gIOKitDebug, sizeof(gIOKitDebug), &newValue, &changed); 7376e12aa3SApple OSS Distributions if (changed) { 7476e12aa3SApple OSS Distributions gIOKitDebug = ((gIOKitDebug & ~kIOKitDebugUserOptions) | (newValue & kIOKitDebugUserOptions)); 7576e12aa3SApple OSS Distributions } 76a5e72196SApple OSS Distributions return error; 7776e12aa3SApple OSS Distributions } 7876e12aa3SApple OSS Distributions 7976e12aa3SApple OSS Distributions SYSCTL_PROC(_debug, OID_AUTO, iokit, 8076e12aa3SApple OSS Distributions CTLTYPE_QUAD | IODEBUG_CTLFLAGS | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED, 8176e12aa3SApple OSS Distributions &gIOKitDebug, 0, sysctl_debug_iokit, "Q", "boot_arg io"); 82c1dac77fSApple OSS Distributions 83*bb611c8fSApple OSS Distributions size_t debug_malloc_size; 84*bb611c8fSApple OSS Distributions size_t debug_iomalloc_size; 85e13b1fa5SApple OSS Distributions 8614e3d835SApple OSS Distributions vm_size_t debug_iomallocpageable_size; 87*bb611c8fSApple OSS Distributions size_t debug_container_malloc_size; 88c1dac77fSApple OSS Distributions // int debug_ivars_size; // in OSObject.cpp 89c1dac77fSApple OSS Distributions 9014e3d835SApple OSS Distributions extern "C" { 913ca3bd55SApple OSS Distributions #if 0 923ca3bd55SApple OSS Distributions #define DEBG(fmt, args...) { kprintf(fmt, ## args); } 933ca3bd55SApple OSS Distributions #else 943ca3bd55SApple OSS Distributions #define DEBG(fmt, args...) { IOLog(fmt, ## args); } 953ca3bd55SApple OSS Distributions #endif 9614e3d835SApple OSS Distributions 97a5e72196SApple OSS Distributions void 98a5e72196SApple OSS Distributions IOPrintPlane( const IORegistryPlane * plane ) 99c1dac77fSApple OSS Distributions { 100c1dac77fSApple OSS Distributions IORegistryEntry * next; 101c1dac77fSApple OSS Distributions IORegistryIterator * iter; 102c1dac77fSApple OSS Distributions OSOrderedSet * all; 103c1dac77fSApple OSS Distributions char format[] = "%xxxs"; 104c1dac77fSApple OSS Distributions IOService * service; 105c1dac77fSApple OSS Distributions 106c1dac77fSApple OSS Distributions iter = IORegistryIterator::iterateOver( plane ); 107c1dac77fSApple OSS Distributions assert( iter ); 108c1dac77fSApple OSS Distributions all = iter->iterateAll(); 109c1dac77fSApple OSS Distributions if (all) { 1103ca3bd55SApple OSS Distributions DEBG("Count %d\n", all->getCount()); 111c1dac77fSApple OSS Distributions all->release(); 112a5e72196SApple OSS Distributions } else { 1133ca3bd55SApple OSS Distributions DEBG("Empty\n"); 114a5e72196SApple OSS Distributions } 115c1dac77fSApple OSS Distributions 116c1dac77fSApple OSS Distributions iter->reset(); 117c1dac77fSApple OSS Distributions while ((next = iter->getNextObjectRecursive())) { 118e13b1fa5SApple OSS Distributions snprintf(format + 1, sizeof(format) - 1, "%ds", 2 * next->getDepth( plane )); 1193ca3bd55SApple OSS Distributions DEBG( format, ""); 1203ca3bd55SApple OSS Distributions DEBG( "\033[33m%s", next->getName( plane )); 121a5e72196SApple OSS Distributions if ((next->getLocation( plane ))) { 1223ca3bd55SApple OSS Distributions DEBG("@%s", next->getLocation( plane )); 123a5e72196SApple OSS Distributions } 1243ca3bd55SApple OSS Distributions DEBG("\033[0m <class %s", next->getMetaClass()->getClassName()); 125a5e72196SApple OSS Distributions if ((service = OSDynamicCast(IOService, next))) { 1263ca3bd55SApple OSS Distributions DEBG(", busy %ld", (long) service->getBusyState()); 127a5e72196SApple OSS Distributions } 1283ca3bd55SApple OSS Distributions DEBG( ">\n"); 1293ca3bd55SApple OSS Distributions // IOSleep(250); 130c1dac77fSApple OSS Distributions } 131c1dac77fSApple OSS Distributions iter->release(); 132c1dac77fSApple OSS Distributions } 133c1dac77fSApple OSS Distributions 134a5e72196SApple OSS Distributions void 135a5e72196SApple OSS Distributions db_piokjunk(void) 136368ad365SApple OSS Distributions { 137368ad365SApple OSS Distributions } 138d0c1fef6SApple OSS Distributions 139a5e72196SApple OSS Distributions void 140a5e72196SApple OSS Distributions db_dumpiojunk( const IORegistryPlane * plane __unused ) 141d0c1fef6SApple OSS Distributions { 142368ad365SApple OSS Distributions } 143368ad365SApple OSS Distributions 144a5e72196SApple OSS Distributions void 145a5e72196SApple OSS Distributions IOPrintMemory( void ) 146c1dac77fSApple OSS Distributions { 147c1dac77fSApple OSS Distributions // OSMetaClass::printInstanceCounts(); 148c1dac77fSApple OSS Distributions 149c1dac77fSApple OSS Distributions IOLog("\n" 150*bb611c8fSApple OSS Distributions "ivar kalloc() 0x%08lx\n" 151*bb611c8fSApple OSS Distributions "malloc() 0x%08lx\n" 152*bb611c8fSApple OSS Distributions "containers kalloc() 0x%08lx\n" 153*bb611c8fSApple OSS Distributions "IOMalloc() 0x%08lx\n" 154c1dac77fSApple OSS Distributions "----------------------------------------\n", 155c1dac77fSApple OSS Distributions debug_ivars_size, 156c1dac77fSApple OSS Distributions debug_malloc_size, 157c1dac77fSApple OSS Distributions debug_container_malloc_size, 158c1dac77fSApple OSS Distributions debug_iomalloc_size 159c1dac77fSApple OSS Distributions ); 160c1dac77fSApple OSS Distributions } 161c1dac77fSApple OSS Distributions } /* extern "C" */ 162c1dac77fSApple OSS Distributions 1630f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 164c1dac77fSApple OSS Distributions 165c1dac77fSApple OSS Distributions #define super OSObject 166c1dac77fSApple OSS Distributions OSDefineMetaClassAndStructors(IOKitDiagnostics, OSObject) 167c1dac77fSApple OSS Distributions 1680f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 169c1dac77fSApple OSS Distributions 170c1dac77fSApple OSS Distributions OSObject * IOKitDiagnostics::diagnostics( void ) 171c1dac77fSApple OSS Distributions { 172c1dac77fSApple OSS Distributions IOKitDiagnostics * diags; 173c1dac77fSApple OSS Distributions 174c1dac77fSApple OSS Distributions diags = new IOKitDiagnostics; 175c1dac77fSApple OSS Distributions if (diags && !diags->init()) { 176c1dac77fSApple OSS Distributions diags->release(); 177a5e72196SApple OSS Distributions diags = NULL; 178c1dac77fSApple OSS Distributions } 179c1dac77fSApple OSS Distributions 180a5e72196SApple OSS Distributions return diags; 181c1dac77fSApple OSS Distributions } 182c1dac77fSApple OSS Distributions 183a5e72196SApple OSS Distributions void 184a5e72196SApple OSS Distributions IOKitDiagnostics::updateOffset( OSDictionary * dict, 1850f3703acSApple OSS Distributions UInt64 value, const char * name ) 186c1dac77fSApple OSS Distributions { 187c1dac77fSApple OSS Distributions OSNumber * off; 188c1dac77fSApple OSS Distributions 1890f3703acSApple OSS Distributions off = OSNumber::withNumber( value, 64 ); 190a5e72196SApple OSS Distributions if (!off) { 191c1dac77fSApple OSS Distributions return; 192a5e72196SApple OSS Distributions } 193c1dac77fSApple OSS Distributions 194c1dac77fSApple OSS Distributions dict->setObject( name, off ); 195c1dac77fSApple OSS Distributions off->release(); 196c1dac77fSApple OSS Distributions } 197c1dac77fSApple OSS Distributions 198a5e72196SApple OSS Distributions bool 199a5e72196SApple OSS Distributions IOKitDiagnostics::serialize(OSSerialize *s) const 200c1dac77fSApple OSS Distributions { 201c1dac77fSApple OSS Distributions OSDictionary * dict; 202c1dac77fSApple OSS Distributions bool ok; 203c1dac77fSApple OSS Distributions 204c1dac77fSApple OSS Distributions dict = OSDictionary::withCapacity( 5 ); 205a5e72196SApple OSS Distributions if (!dict) { 206a5e72196SApple OSS Distributions return false; 207a5e72196SApple OSS Distributions } 208c1dac77fSApple OSS Distributions 209c1dac77fSApple OSS Distributions updateOffset( dict, debug_ivars_size, "Instance allocation" ); 210c1dac77fSApple OSS Distributions updateOffset( dict, debug_container_malloc_size, "Container allocation" ); 211c1dac77fSApple OSS Distributions updateOffset( dict, debug_iomalloc_size, "IOMalloc allocation" ); 21214e3d835SApple OSS Distributions updateOffset( dict, debug_iomallocpageable_size, "Pageable allocation" ); 213c1dac77fSApple OSS Distributions 214368ad365SApple OSS Distributions OSMetaClass::serializeClassDictionary(dict); 215c1dac77fSApple OSS Distributions 216c1dac77fSApple OSS Distributions ok = dict->serialize( s ); 217c1dac77fSApple OSS Distributions 218c1dac77fSApple OSS Distributions dict->release(); 219c1dac77fSApple OSS Distributions 220a5e72196SApple OSS Distributions return ok; 221c1dac77fSApple OSS Distributions } 222c1dac77fSApple OSS Distributions 2230f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 2240f3703acSApple OSS Distributions 2250f3703acSApple OSS Distributions #if IOTRACKING 2260f3703acSApple OSS Distributions 2270f3703acSApple OSS Distributions #include <libkern/c++/OSCPPDebug.h> 2280f3703acSApple OSS Distributions #include <libkern/c++/OSKext.h> 2290f3703acSApple OSS Distributions #include <kern/zalloc.h> 2300f3703acSApple OSS Distributions 2310f3703acSApple OSS Distributions __private_extern__ "C" void qsort( 2320f3703acSApple OSS Distributions void * array, 2330f3703acSApple OSS Distributions size_t nmembers, 2340f3703acSApple OSS Distributions size_t member_size, 2350f3703acSApple OSS Distributions int (*)(const void *, const void *)); 2360f3703acSApple OSS Distributions 2370f3703acSApple OSS Distributions extern "C" ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va); 2380f3703acSApple OSS Distributions extern "C" ppnum_t pmap_valid_page(ppnum_t pn); 2390f3703acSApple OSS Distributions 2400f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 2410f3703acSApple OSS Distributions 242a5e72196SApple OSS Distributions struct IOTRecursiveLock { 2430f3703acSApple OSS Distributions lck_mtx_t * mutex; 2440f3703acSApple OSS Distributions thread_t thread; 2450f3703acSApple OSS Distributions UInt32 count; 2460f3703acSApple OSS Distributions }; 2470f3703acSApple OSS Distributions 248a5e72196SApple OSS Distributions struct IOTrackingQueue { 2490f3703acSApple OSS Distributions queue_chain_t link; 2500f3703acSApple OSS Distributions IOTRecursiveLock lock; 2510f3703acSApple OSS Distributions const char * name; 25288cc0b97SApple OSS Distributions uintptr_t btEntry; 2530f3703acSApple OSS Distributions size_t allocSize; 2540f3703acSApple OSS Distributions size_t minCaptureSize; 2550f3703acSApple OSS Distributions uint32_t siteCount; 25688cc0b97SApple OSS Distributions uint32_t type; 25788cc0b97SApple OSS Distributions uint32_t numSiteQs; 2580f3703acSApple OSS Distributions uint8_t captureOn; 25988cc0b97SApple OSS Distributions queue_head_t sites[]; 2600f3703acSApple OSS Distributions }; 2610f3703acSApple OSS Distributions 262*bb611c8fSApple OSS Distributions 263*bb611c8fSApple OSS Distributions struct IOTrackingCallSiteUser { 264*bb611c8fSApple OSS Distributions pid_t pid; 265*bb611c8fSApple OSS Distributions uint8_t user32; 266*bb611c8fSApple OSS Distributions uint8_t userCount; 267*bb611c8fSApple OSS Distributions uintptr_t bt[kIOTrackingCallSiteBTs]; 268*bb611c8fSApple OSS Distributions }; 269*bb611c8fSApple OSS Distributions 270a5e72196SApple OSS Distributions struct IOTrackingCallSite { 2710f3703acSApple OSS Distributions queue_chain_t link; 272*bb611c8fSApple OSS Distributions queue_head_t instances; 2730f3703acSApple OSS Distributions IOTrackingQueue * queue; 274*bb611c8fSApple OSS Distributions IOTracking * addresses; 275*bb611c8fSApple OSS Distributions size_t size[2]; 2760f3703acSApple OSS Distributions uint32_t crc; 277*bb611c8fSApple OSS Distributions uint32_t count; 27888cc0b97SApple OSS Distributions 27976e12aa3SApple OSS Distributions vm_tag_t tag; 280*bb611c8fSApple OSS Distributions uint8_t user32; 281*bb611c8fSApple OSS Distributions uint8_t userCount; 282*bb611c8fSApple OSS Distributions pid_t btPID; 28388cc0b97SApple OSS Distributions 284*bb611c8fSApple OSS Distributions uintptr_t bt[kIOTrackingCallSiteBTs]; 285*bb611c8fSApple OSS Distributions IOTrackingCallSiteUser user[0]; 2860f3703acSApple OSS Distributions }; 2870f3703acSApple OSS Distributions 288*bb611c8fSApple OSS Distributions 289a5e72196SApple OSS Distributions struct IOTrackingLeaksRef { 2900f3703acSApple OSS Distributions uintptr_t * instances; 29188cc0b97SApple OSS Distributions uint32_t zoneSize; 2920f3703acSApple OSS Distributions uint32_t count; 2930f3703acSApple OSS Distributions uint32_t found; 29476e12aa3SApple OSS Distributions uint32_t foundzlen; 2950f3703acSApple OSS Distributions size_t bytes; 2960f3703acSApple OSS Distributions }; 2970f3703acSApple OSS Distributions 2980f3703acSApple OSS Distributions lck_mtx_t * gIOTrackingLock; 2990f3703acSApple OSS Distributions queue_head_t gIOTrackingQ; 3000f3703acSApple OSS Distributions 301a5e72196SApple OSS Distributions enum{ 3020f3703acSApple OSS Distributions kTrackingAddressFlagAllocated = 0x00000001 3030f3703acSApple OSS Distributions }; 3040f3703acSApple OSS Distributions 3050f3703acSApple OSS Distributions #if defined(__LP64__) 3060f3703acSApple OSS Distributions #define IOTrackingAddressFlags(ptr) (ptr->flags) 3070f3703acSApple OSS Distributions #else 3080f3703acSApple OSS Distributions #define IOTrackingAddressFlags(ptr) (ptr->tracking.flags) 3090f3703acSApple OSS Distributions #endif 3100f3703acSApple OSS Distributions 3110f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3120f3703acSApple OSS Distributions 3130f3703acSApple OSS Distributions static void 3140f3703acSApple OSS Distributions IOTRecursiveLockLock(IOTRecursiveLock * lock) 3150f3703acSApple OSS Distributions { 316a5e72196SApple OSS Distributions if (lock->thread == current_thread()) { 317a5e72196SApple OSS Distributions lock->count++; 318a5e72196SApple OSS Distributions } else { 3190f3703acSApple OSS Distributions lck_mtx_lock(lock->mutex); 320a5e72196SApple OSS Distributions assert(lock->thread == NULL); 3210f3703acSApple OSS Distributions assert(lock->count == 0); 3220f3703acSApple OSS Distributions lock->thread = current_thread(); 3230f3703acSApple OSS Distributions lock->count = 1; 3240f3703acSApple OSS Distributions } 3250f3703acSApple OSS Distributions } 3260f3703acSApple OSS Distributions 3270f3703acSApple OSS Distributions static void 3280f3703acSApple OSS Distributions IOTRecursiveLockUnlock(IOTRecursiveLock * lock) 3290f3703acSApple OSS Distributions { 3300f3703acSApple OSS Distributions assert(lock->thread == current_thread()); 331a5e72196SApple OSS Distributions if (0 == (--lock->count)) { 332a5e72196SApple OSS Distributions lock->thread = NULL; 3330f3703acSApple OSS Distributions lck_mtx_unlock(lock->mutex); 3340f3703acSApple OSS Distributions } 3350f3703acSApple OSS Distributions } 3360f3703acSApple OSS Distributions 3370f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3380f3703acSApple OSS Distributions 3390f3703acSApple OSS Distributions void 3400f3703acSApple OSS Distributions IOTrackingInit(void) 3410f3703acSApple OSS Distributions { 3420f3703acSApple OSS Distributions queue_init(&gIOTrackingQ); 3430f3703acSApple OSS Distributions gIOTrackingLock = lck_mtx_alloc_init(IOLockGroup, LCK_ATTR_NULL); 3440f3703acSApple OSS Distributions } 3450f3703acSApple OSS Distributions 3460f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3470f3703acSApple OSS Distributions 3480f3703acSApple OSS Distributions IOTrackingQueue * 34988cc0b97SApple OSS Distributions IOTrackingQueueAlloc(const char * name, uintptr_t btEntry, 35088cc0b97SApple OSS Distributions size_t allocSize, size_t minCaptureSize, 35188cc0b97SApple OSS Distributions uint32_t type, uint32_t numSiteQs) 3520f3703acSApple OSS Distributions { 3530f3703acSApple OSS Distributions IOTrackingQueue * queue; 35488cc0b97SApple OSS Distributions uint32_t idx; 35588cc0b97SApple OSS Distributions 356a5e72196SApple OSS Distributions if (!numSiteQs) { 357a5e72196SApple OSS Distributions numSiteQs = 1; 358a5e72196SApple OSS Distributions } 35988cc0b97SApple OSS Distributions queue = (typeof(queue))kalloc(sizeof(IOTrackingQueue) + numSiteQs * sizeof(queue->sites[0])); 3600f3703acSApple OSS Distributions bzero(queue, sizeof(IOTrackingQueue)); 3610f3703acSApple OSS Distributions 3620f3703acSApple OSS Distributions queue->name = name; 36388cc0b97SApple OSS Distributions queue->btEntry = btEntry; 3640f3703acSApple OSS Distributions queue->allocSize = allocSize; 3650f3703acSApple OSS Distributions queue->minCaptureSize = minCaptureSize; 3660f3703acSApple OSS Distributions queue->lock.mutex = lck_mtx_alloc_init(IOLockGroup, LCK_ATTR_NULL); 36788cc0b97SApple OSS Distributions queue->numSiteQs = numSiteQs; 36888cc0b97SApple OSS Distributions queue->type = type; 36988cc0b97SApple OSS Distributions enum { kFlags = (kIOTracking | kIOTrackingBoot) }; 37088cc0b97SApple OSS Distributions queue->captureOn = (kFlags == (kFlags & gIOKitDebug)) 37188cc0b97SApple OSS Distributions || (kIOTrackingQueueTypeDefaultOn & type); 3720f3703acSApple OSS Distributions 373a5e72196SApple OSS Distributions for (idx = 0; idx < numSiteQs; idx++) { 374a5e72196SApple OSS Distributions queue_init(&queue->sites[idx]); 375a5e72196SApple OSS Distributions } 3760f3703acSApple OSS Distributions 3770f3703acSApple OSS Distributions lck_mtx_lock(gIOTrackingLock); 3780f3703acSApple OSS Distributions queue_enter(&gIOTrackingQ, queue, IOTrackingQueue *, link); 3790f3703acSApple OSS Distributions lck_mtx_unlock(gIOTrackingLock); 3800f3703acSApple OSS Distributions 381a5e72196SApple OSS Distributions return queue; 3820f3703acSApple OSS Distributions }; 3830f3703acSApple OSS Distributions 384*bb611c8fSApple OSS Distributions void 385*bb611c8fSApple OSS Distributions IOTrackingQueueCollectUser(IOTrackingQueue * queue) 386*bb611c8fSApple OSS Distributions { 387*bb611c8fSApple OSS Distributions assert(0 == queue->siteCount); 388*bb611c8fSApple OSS Distributions queue->type |= kIOTrackingQueueTypeUser; 389*bb611c8fSApple OSS Distributions } 390*bb611c8fSApple OSS Distributions 3910f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 3920f3703acSApple OSS Distributions 3930f3703acSApple OSS Distributions void 3940f3703acSApple OSS Distributions IOTrackingQueueFree(IOTrackingQueue * queue) 3950f3703acSApple OSS Distributions { 3960f3703acSApple OSS Distributions lck_mtx_lock(gIOTrackingLock); 3970f3703acSApple OSS Distributions IOTrackingReset(queue); 3980f3703acSApple OSS Distributions remque(&queue->link); 3990f3703acSApple OSS Distributions lck_mtx_unlock(gIOTrackingLock); 4000f3703acSApple OSS Distributions 4010f3703acSApple OSS Distributions lck_mtx_free(queue->lock.mutex, IOLockGroup); 4020f3703acSApple OSS Distributions 40388cc0b97SApple OSS Distributions kfree(queue, sizeof(IOTrackingQueue) + queue->numSiteQs * sizeof(queue->sites[0])); 4040f3703acSApple OSS Distributions }; 4050f3703acSApple OSS Distributions 4060f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 4070f3703acSApple OSS Distributions 4080f3703acSApple OSS Distributions /* fasthash 409a5e72196SApple OSS Distributions * The MIT License 410a5e72196SApple OSS Distributions * 411a5e72196SApple OSS Distributions * Copyright (C) 2012 Zilong Tan ([email protected]) 412a5e72196SApple OSS Distributions * 413a5e72196SApple OSS Distributions * Permission is hereby granted, free of charge, to any person 414a5e72196SApple OSS Distributions * obtaining a copy of this software and associated documentation 415a5e72196SApple OSS Distributions * files (the "Software"), to deal in the Software without 416a5e72196SApple OSS Distributions * restriction, including without limitation the rights to use, copy, 417a5e72196SApple OSS Distributions * modify, merge, publish, distribute, sublicense, and/or sell copies 418a5e72196SApple OSS Distributions * of the Software, and to permit persons to whom the Software is 419a5e72196SApple OSS Distributions * furnished to do so, subject to the following conditions: 420a5e72196SApple OSS Distributions * 421a5e72196SApple OSS Distributions * The above copyright notice and this permission notice shall be 422a5e72196SApple OSS Distributions * included in all copies or substantial portions of the Software. 423a5e72196SApple OSS Distributions * 424a5e72196SApple OSS Distributions * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 425a5e72196SApple OSS Distributions * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 426a5e72196SApple OSS Distributions * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 427a5e72196SApple OSS Distributions * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 428a5e72196SApple OSS Distributions * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 429a5e72196SApple OSS Distributions * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 430a5e72196SApple OSS Distributions * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 431a5e72196SApple OSS Distributions * SOFTWARE. 4320f3703acSApple OSS Distributions */ 4330f3703acSApple OSS Distributions 4340f3703acSApple OSS Distributions 4350f3703acSApple OSS Distributions // Compression function for Merkle-Damgard construction. 4360f3703acSApple OSS Distributions // This function is generated using the framework provided. 4370f3703acSApple OSS Distributions #define mix(h) ({ \ 4380f3703acSApple OSS Distributions (h) ^= (h) >> 23; \ 4390f3703acSApple OSS Distributions (h) *= 0x2127599bf4325c37ULL; \ 4400f3703acSApple OSS Distributions (h) ^= (h) >> 47; }) 4410f3703acSApple OSS Distributions 4420f3703acSApple OSS Distributions static uint64_t 4430f3703acSApple OSS Distributions fasthash64(const void *buf, size_t len, uint64_t seed) 4440f3703acSApple OSS Distributions { 4450f3703acSApple OSS Distributions const uint64_t m = 0x880355f21e6d1965ULL; 4460f3703acSApple OSS Distributions const uint64_t *pos = (const uint64_t *)buf; 4470f3703acSApple OSS Distributions const uint64_t *end = pos + (len / 8); 4480f3703acSApple OSS Distributions const unsigned char *pos2; 4490f3703acSApple OSS Distributions uint64_t h = seed ^ (len * m); 4500f3703acSApple OSS Distributions uint64_t v; 4510f3703acSApple OSS Distributions 4520f3703acSApple OSS Distributions while (pos != end) { 4530f3703acSApple OSS Distributions v = *pos++; 4540f3703acSApple OSS Distributions h ^= mix(v); 4550f3703acSApple OSS Distributions h *= m; 4560f3703acSApple OSS Distributions } 4570f3703acSApple OSS Distributions 4580f3703acSApple OSS Distributions pos2 = (const unsigned char*)pos; 4590f3703acSApple OSS Distributions v = 0; 4600f3703acSApple OSS Distributions 4610f3703acSApple OSS Distributions switch (len & 7) { 4620f3703acSApple OSS Distributions case 7: v ^= (uint64_t)pos2[6] << 48; 46388cc0b97SApple OSS Distributions [[clang::fallthrough]]; 4640f3703acSApple OSS Distributions case 6: v ^= (uint64_t)pos2[5] << 40; 46588cc0b97SApple OSS Distributions [[clang::fallthrough]]; 4660f3703acSApple OSS Distributions case 5: v ^= (uint64_t)pos2[4] << 32; 46788cc0b97SApple OSS Distributions [[clang::fallthrough]]; 4680f3703acSApple OSS Distributions case 4: v ^= (uint64_t)pos2[3] << 24; 46988cc0b97SApple OSS Distributions [[clang::fallthrough]]; 4700f3703acSApple OSS Distributions case 3: v ^= (uint64_t)pos2[2] << 16; 47188cc0b97SApple OSS Distributions [[clang::fallthrough]]; 4720f3703acSApple OSS Distributions case 2: v ^= (uint64_t)pos2[1] << 8; 47388cc0b97SApple OSS Distributions [[clang::fallthrough]]; 4740f3703acSApple OSS Distributions case 1: v ^= (uint64_t)pos2[0]; 4750f3703acSApple OSS Distributions h ^= mix(v); 4760f3703acSApple OSS Distributions h *= m; 4770f3703acSApple OSS Distributions } 4780f3703acSApple OSS Distributions 4790f3703acSApple OSS Distributions return mix(h); 4800f3703acSApple OSS Distributions } 4810f3703acSApple OSS Distributions 4820f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 4830f3703acSApple OSS Distributions 4840f3703acSApple OSS Distributions static uint32_t 4850f3703acSApple OSS Distributions fasthash32(const void *buf, size_t len, uint32_t seed) 4860f3703acSApple OSS Distributions { 4870f3703acSApple OSS Distributions // the following trick converts the 64-bit hashcode to Fermat 4880f3703acSApple OSS Distributions // residue, which shall retain information from both the higher 4890f3703acSApple OSS Distributions // and lower parts of hashcode. 4900f3703acSApple OSS Distributions uint64_t h = fasthash64(buf, len, seed); 491*bb611c8fSApple OSS Distributions return (uint32_t) (h - (h >> 32)); 4920f3703acSApple OSS Distributions } 4930f3703acSApple OSS Distributions 4940f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 4950f3703acSApple OSS Distributions 4960f3703acSApple OSS Distributions void 49788cc0b97SApple OSS Distributions IOTrackingAddUser(IOTrackingQueue * queue, IOTrackingUser * mem, vm_size_t size) 49888cc0b97SApple OSS Distributions { 49988cc0b97SApple OSS Distributions uint32_t num; 500*bb611c8fSApple OSS Distributions int pid; 50188cc0b97SApple OSS Distributions 502a5e72196SApple OSS Distributions if (!queue->captureOn) { 503a5e72196SApple OSS Distributions return; 504a5e72196SApple OSS Distributions } 505a5e72196SApple OSS Distributions if (size < queue->minCaptureSize) { 506a5e72196SApple OSS Distributions return; 507a5e72196SApple OSS Distributions } 50888cc0b97SApple OSS Distributions 50988cc0b97SApple OSS Distributions assert(!mem->link.next); 51088cc0b97SApple OSS Distributions 511a5e72196SApple OSS Distributions num = backtrace(&mem->bt[0], kIOTrackingCallSiteBTs, NULL); 51288cc0b97SApple OSS Distributions num = 0; 513*bb611c8fSApple OSS Distributions if ((kernel_task != current_task()) && (pid = proc_selfpid())) { 514a5e72196SApple OSS Distributions bool user_64 = false; 515*bb611c8fSApple OSS Distributions mem->btPID = pid; 516*bb611c8fSApple OSS Distributions num = backtrace_user(&mem->btUser[0], kIOTrackingCallSiteBTs - 1, NULL, 517a5e72196SApple OSS Distributions &user_64, NULL); 51888cc0b97SApple OSS Distributions mem->user32 = !user_64; 51988cc0b97SApple OSS Distributions } 52088cc0b97SApple OSS Distributions assert(num <= kIOTrackingCallSiteBTs); 521*bb611c8fSApple OSS Distributions static_assert(kIOTrackingCallSiteBTs <= UINT8_MAX); 522*bb611c8fSApple OSS Distributions mem->userCount = ((uint8_t) num); 52388cc0b97SApple OSS Distributions 52488cc0b97SApple OSS Distributions IOTRecursiveLockLock(&queue->lock); 52588cc0b97SApple OSS Distributions queue_enter/*last*/ (&queue->sites[0], mem, IOTrackingUser *, link); 52688cc0b97SApple OSS Distributions queue->siteCount++; 52788cc0b97SApple OSS Distributions IOTRecursiveLockUnlock(&queue->lock); 52888cc0b97SApple OSS Distributions } 52988cc0b97SApple OSS Distributions 53088cc0b97SApple OSS Distributions void 53188cc0b97SApple OSS Distributions IOTrackingRemoveUser(IOTrackingQueue * queue, IOTrackingUser * mem) 53288cc0b97SApple OSS Distributions { 533a5e72196SApple OSS Distributions if (!mem->link.next) { 534a5e72196SApple OSS Distributions return; 535a5e72196SApple OSS Distributions } 53688cc0b97SApple OSS Distributions 53788cc0b97SApple OSS Distributions IOTRecursiveLockLock(&queue->lock); 538a5e72196SApple OSS Distributions if (mem->link.next) { 53988cc0b97SApple OSS Distributions remque(&mem->link); 54088cc0b97SApple OSS Distributions assert(queue->siteCount); 54188cc0b97SApple OSS Distributions queue->siteCount--; 54288cc0b97SApple OSS Distributions } 54388cc0b97SApple OSS Distributions IOTRecursiveLockUnlock(&queue->lock); 54488cc0b97SApple OSS Distributions } 54588cc0b97SApple OSS Distributions 54688cc0b97SApple OSS Distributions uint64_t gIOTrackingAddTime; 54788cc0b97SApple OSS Distributions 54888cc0b97SApple OSS Distributions void 54976e12aa3SApple OSS Distributions IOTrackingAdd(IOTrackingQueue * queue, IOTracking * mem, size_t size, bool address, vm_tag_t tag) 5500f3703acSApple OSS Distributions { 5510f3703acSApple OSS Distributions IOTrackingCallSite * site; 5520f3703acSApple OSS Distributions uint32_t crc, num; 5530f3703acSApple OSS Distributions uintptr_t bt[kIOTrackingCallSiteBTs + 1]; 554*bb611c8fSApple OSS Distributions uintptr_t btUser[kIOTrackingCallSiteBTs]; 55588cc0b97SApple OSS Distributions queue_head_t * que; 556*bb611c8fSApple OSS Distributions bool user; 557*bb611c8fSApple OSS Distributions int pid; 558*bb611c8fSApple OSS Distributions int userCount; 559*bb611c8fSApple OSS Distributions bool user64; 5600f3703acSApple OSS Distributions 561a5e72196SApple OSS Distributions if (mem->site) { 562a5e72196SApple OSS Distributions return; 563a5e72196SApple OSS Distributions } 564a5e72196SApple OSS Distributions if (!queue->captureOn) { 565a5e72196SApple OSS Distributions return; 566a5e72196SApple OSS Distributions } 567a5e72196SApple OSS Distributions if (size < queue->minCaptureSize) { 568a5e72196SApple OSS Distributions return; 569a5e72196SApple OSS Distributions } 5700f3703acSApple OSS Distributions 571*bb611c8fSApple OSS Distributions user = (0 != (kIOTrackingQueueTypeUser & queue->type)); 572*bb611c8fSApple OSS Distributions 5730f3703acSApple OSS Distributions assert(!mem->link.next); 5740f3703acSApple OSS Distributions 575a5e72196SApple OSS Distributions num = backtrace(&bt[0], kIOTrackingCallSiteBTs + 1, NULL); 576a5e72196SApple OSS Distributions if (!num) { 577a5e72196SApple OSS Distributions return; 578a5e72196SApple OSS Distributions } 5790f3703acSApple OSS Distributions num--; 5800f3703acSApple OSS Distributions crc = fasthash32(&bt[1], num * sizeof(bt[0]), 0x04C11DB7); 5810f3703acSApple OSS Distributions 582*bb611c8fSApple OSS Distributions userCount = 0; 583*bb611c8fSApple OSS Distributions user64 = false; 584*bb611c8fSApple OSS Distributions pid = 0; 585*bb611c8fSApple OSS Distributions if (user) { 586*bb611c8fSApple OSS Distributions if ((kernel_task != current_task()) && (pid = proc_selfpid())) { 587*bb611c8fSApple OSS Distributions userCount = backtrace_user(&btUser[0], kIOTrackingCallSiteBTs, NULL, &user64, NULL); 588*bb611c8fSApple OSS Distributions assert(userCount <= kIOTrackingCallSiteBTs); 589*bb611c8fSApple OSS Distributions crc = fasthash32(&btUser[0], userCount * sizeof(bt[0]), crc); 590*bb611c8fSApple OSS Distributions } 591*bb611c8fSApple OSS Distributions } 592*bb611c8fSApple OSS Distributions 5930f3703acSApple OSS Distributions IOTRecursiveLockLock(&queue->lock); 59488cc0b97SApple OSS Distributions que = &queue->sites[crc % queue->numSiteQs]; 59588cc0b97SApple OSS Distributions queue_iterate(que, site, IOTrackingCallSite *, link) 5960f3703acSApple OSS Distributions { 597a5e72196SApple OSS Distributions if (tag != site->tag) { 598a5e72196SApple OSS Distributions continue; 599a5e72196SApple OSS Distributions } 600*bb611c8fSApple OSS Distributions if (user && (pid != site->user[0].pid)) { 601*bb611c8fSApple OSS Distributions continue; 602*bb611c8fSApple OSS Distributions } 603a5e72196SApple OSS Distributions if (crc == site->crc) { 604a5e72196SApple OSS Distributions break; 605a5e72196SApple OSS Distributions } 6060f3703acSApple OSS Distributions } 6070f3703acSApple OSS Distributions 608a5e72196SApple OSS Distributions if (queue_end(que, (queue_entry_t) site)) { 609*bb611c8fSApple OSS Distributions size_t siteSize = sizeof(IOTrackingCallSite); 610*bb611c8fSApple OSS Distributions if (user) { 611*bb611c8fSApple OSS Distributions siteSize += sizeof(IOTrackingCallSiteUser); 612*bb611c8fSApple OSS Distributions } 613*bb611c8fSApple OSS Distributions site = (typeof(site))kalloc(siteSize); 6140f3703acSApple OSS Distributions 6150f3703acSApple OSS Distributions queue_init(&site->instances); 6160f3703acSApple OSS Distributions site->addresses = (IOTracking *) &site->instances; 6170f3703acSApple OSS Distributions site->queue = queue; 6180f3703acSApple OSS Distributions site->crc = crc; 61988cc0b97SApple OSS Distributions site->count = 0; 62076e12aa3SApple OSS Distributions site->tag = tag; 62188cc0b97SApple OSS Distributions memset(&site->size[0], 0, sizeof(site->size)); 62288cc0b97SApple OSS Distributions bcopy(&bt[1], &site->bt[0], num * sizeof(site->bt[0])); 6230f3703acSApple OSS Distributions assert(num <= kIOTrackingCallSiteBTs); 62488cc0b97SApple OSS Distributions bzero(&site->bt[num], (kIOTrackingCallSiteBTs - num) * sizeof(site->bt[0])); 625*bb611c8fSApple OSS Distributions if (user) { 626*bb611c8fSApple OSS Distributions bcopy(&btUser[0], &site->user[0].bt[0], userCount * sizeof(site->user[0].bt[0])); 627*bb611c8fSApple OSS Distributions assert(userCount <= kIOTrackingCallSiteBTs); 628*bb611c8fSApple OSS Distributions bzero(&site->user[0].bt[userCount], (kIOTrackingCallSiteBTs - userCount) * sizeof(site->user[0].bt[0])); 629*bb611c8fSApple OSS Distributions site->user[0].pid = pid; 630*bb611c8fSApple OSS Distributions site->user[0].user32 = !user64; 631*bb611c8fSApple OSS Distributions static_assert(kIOTrackingCallSiteBTs <= UINT8_MAX); 632*bb611c8fSApple OSS Distributions site->user[0].userCount = ((uint8_t) userCount); 633*bb611c8fSApple OSS Distributions } 63488cc0b97SApple OSS Distributions queue_enter_first(que, site, IOTrackingCallSite *, link); 6350f3703acSApple OSS Distributions queue->siteCount++; 6360f3703acSApple OSS Distributions } 6370f3703acSApple OSS Distributions 638a5e72196SApple OSS Distributions if (address) { 63988cc0b97SApple OSS Distributions queue_enter/*last*/ (&site->instances, mem, IOTracking *, link); 640a5e72196SApple OSS Distributions if (queue_end(&site->instances, (queue_entry_t)site->addresses)) { 641a5e72196SApple OSS Distributions site->addresses = mem; 6420f3703acSApple OSS Distributions } 643a5e72196SApple OSS Distributions } else { 644a5e72196SApple OSS Distributions queue_enter_first(&site->instances, mem, IOTracking *, link); 645a5e72196SApple OSS Distributions } 6460f3703acSApple OSS Distributions 6470f3703acSApple OSS Distributions mem->site = site; 64888cc0b97SApple OSS Distributions site->size[0] += size; 64988cc0b97SApple OSS Distributions site->count++; 6500f3703acSApple OSS Distributions 6510f3703acSApple OSS Distributions IOTRecursiveLockUnlock(&queue->lock); 6520f3703acSApple OSS Distributions } 6530f3703acSApple OSS Distributions 6540f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 6550f3703acSApple OSS Distributions 6560f3703acSApple OSS Distributions void 6570f3703acSApple OSS Distributions IOTrackingRemove(IOTrackingQueue * queue, IOTracking * mem, size_t size) 6580f3703acSApple OSS Distributions { 659a5e72196SApple OSS Distributions if (!mem->link.next) { 660a5e72196SApple OSS Distributions return; 661a5e72196SApple OSS Distributions } 6620f3703acSApple OSS Distributions 6630f3703acSApple OSS Distributions IOTRecursiveLockLock(&queue->lock); 664a5e72196SApple OSS Distributions if (mem->link.next) { 6650f3703acSApple OSS Distributions assert(mem->site); 6660f3703acSApple OSS Distributions 667a5e72196SApple OSS Distributions if (mem == mem->site->addresses) { 668a5e72196SApple OSS Distributions mem->site->addresses = (IOTracking *) queue_next(&mem->link); 669a5e72196SApple OSS Distributions } 6700f3703acSApple OSS Distributions remque(&mem->link); 6710f3703acSApple OSS Distributions 67288cc0b97SApple OSS Distributions assert(mem->site->count); 67388cc0b97SApple OSS Distributions mem->site->count--; 67488cc0b97SApple OSS Distributions assert(mem->site->size[0] >= size); 67588cc0b97SApple OSS Distributions mem->site->size[0] -= size; 676a5e72196SApple OSS Distributions if (!mem->site->count) { 6770f3703acSApple OSS Distributions assert(queue_empty(&mem->site->instances)); 67888cc0b97SApple OSS Distributions assert(!mem->site->size[0]); 67988cc0b97SApple OSS Distributions assert(!mem->site->size[1]); 6800f3703acSApple OSS Distributions 6810f3703acSApple OSS Distributions remque(&mem->site->link); 6820f3703acSApple OSS Distributions assert(queue->siteCount); 6830f3703acSApple OSS Distributions queue->siteCount--; 684*bb611c8fSApple OSS Distributions size_t siteSize = sizeof(IOTrackingCallSite); 685*bb611c8fSApple OSS Distributions if (kIOTrackingQueueTypeUser & queue->type) { 686*bb611c8fSApple OSS Distributions siteSize += sizeof(IOTrackingCallSiteUser); 687*bb611c8fSApple OSS Distributions } 688*bb611c8fSApple OSS Distributions kfree(mem->site, siteSize); 6890f3703acSApple OSS Distributions } 69076e12aa3SApple OSS Distributions mem->site = NULL; 69188cc0b97SApple OSS Distributions } 6920f3703acSApple OSS Distributions IOTRecursiveLockUnlock(&queue->lock); 6930f3703acSApple OSS Distributions } 6940f3703acSApple OSS Distributions 6950f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 6960f3703acSApple OSS Distributions 6970f3703acSApple OSS Distributions void 6980f3703acSApple OSS Distributions IOTrackingAlloc(IOTrackingQueue * queue, uintptr_t address, size_t size) 6990f3703acSApple OSS Distributions { 7000f3703acSApple OSS Distributions IOTrackingAddress * tracking; 7010f3703acSApple OSS Distributions 702a5e72196SApple OSS Distributions if (!queue->captureOn) { 703a5e72196SApple OSS Distributions return; 704a5e72196SApple OSS Distributions } 705a5e72196SApple OSS Distributions if (size < queue->minCaptureSize) { 706a5e72196SApple OSS Distributions return; 707a5e72196SApple OSS Distributions } 7080f3703acSApple OSS Distributions 7090f3703acSApple OSS Distributions address = ~address; 7100f3703acSApple OSS Distributions tracking = (typeof(tracking))kalloc(sizeof(IOTrackingAddress)); 7110f3703acSApple OSS Distributions bzero(tracking, sizeof(IOTrackingAddress)); 7120f3703acSApple OSS Distributions IOTrackingAddressFlags(tracking) |= kTrackingAddressFlagAllocated; 7130f3703acSApple OSS Distributions tracking->address = address; 7140f3703acSApple OSS Distributions tracking->size = size; 7150f3703acSApple OSS Distributions 71676e12aa3SApple OSS Distributions IOTrackingAdd(queue, &tracking->tracking, size, true, VM_KERN_MEMORY_NONE); 7170f3703acSApple OSS Distributions } 7180f3703acSApple OSS Distributions 7190f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 7200f3703acSApple OSS Distributions 7210f3703acSApple OSS Distributions void 7220f3703acSApple OSS Distributions IOTrackingFree(IOTrackingQueue * queue, uintptr_t address, size_t size) 7230f3703acSApple OSS Distributions { 7240f3703acSApple OSS Distributions IOTrackingCallSite * site; 7250f3703acSApple OSS Distributions IOTrackingAddress * tracking; 72688cc0b97SApple OSS Distributions uint32_t idx; 7270f3703acSApple OSS Distributions bool done; 7280f3703acSApple OSS Distributions 7290f3703acSApple OSS Distributions address = ~address; 7300f3703acSApple OSS Distributions IOTRecursiveLockLock(&queue->lock); 7310f3703acSApple OSS Distributions done = false; 732a5e72196SApple OSS Distributions for (idx = 0; idx < queue->numSiteQs; idx++) { 73388cc0b97SApple OSS Distributions queue_iterate(&queue->sites[idx], site, IOTrackingCallSite *, link) 7340f3703acSApple OSS Distributions { 735a5e72196SApple OSS Distributions tracking = (IOTrackingAddress *) site->addresses; 736a5e72196SApple OSS Distributions while (!queue_end(&site->instances, &tracking->tracking.link)) { 737a5e72196SApple OSS Distributions if ((done = (address == tracking->address))) { 7380f3703acSApple OSS Distributions IOTrackingRemove(queue, &tracking->tracking, size); 7390f3703acSApple OSS Distributions kfree(tracking, sizeof(IOTrackingAddress)); 740a5e72196SApple OSS Distributions break; 741a5e72196SApple OSS Distributions } else { 742a5e72196SApple OSS Distributions tracking = (IOTrackingAddress *) queue_next(&tracking->tracking.link); 7430f3703acSApple OSS Distributions } 7440f3703acSApple OSS Distributions } 745a5e72196SApple OSS Distributions if (done) { 746a5e72196SApple OSS Distributions break; 7470f3703acSApple OSS Distributions } 748a5e72196SApple OSS Distributions } 749a5e72196SApple OSS Distributions if (done) { 750a5e72196SApple OSS Distributions break; 751a5e72196SApple OSS Distributions } 75288cc0b97SApple OSS Distributions } 7530f3703acSApple OSS Distributions IOTRecursiveLockUnlock(&queue->lock); 7540f3703acSApple OSS Distributions } 7550f3703acSApple OSS Distributions 7560f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 7570f3703acSApple OSS Distributions 7580f3703acSApple OSS Distributions void 7590f3703acSApple OSS Distributions IOTrackingAccumSize(IOTrackingQueue * queue, IOTracking * mem, size_t size) 7600f3703acSApple OSS Distributions { 7610f3703acSApple OSS Distributions IOTRecursiveLockLock(&queue->lock); 762a5e72196SApple OSS Distributions if (mem->link.next) { 7630f3703acSApple OSS Distributions assert(mem->site); 76488cc0b97SApple OSS Distributions assert((size > 0) || (mem->site->size[1] >= -size)); 76588cc0b97SApple OSS Distributions mem->site->size[1] += size; 766a5e72196SApple OSS Distributions } 767a5e72196SApple OSS Distributions ; 7680f3703acSApple OSS Distributions IOTRecursiveLockUnlock(&queue->lock); 7690f3703acSApple OSS Distributions } 7700f3703acSApple OSS Distributions 7710f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 7720f3703acSApple OSS Distributions 7730f3703acSApple OSS Distributions void 7740f3703acSApple OSS Distributions IOTrackingReset(IOTrackingQueue * queue) 7750f3703acSApple OSS Distributions { 7760f3703acSApple OSS Distributions IOTrackingCallSite * site; 77788cc0b97SApple OSS Distributions IOTrackingUser * user; 7780f3703acSApple OSS Distributions IOTracking * tracking; 7790f3703acSApple OSS Distributions IOTrackingAddress * trackingAddress; 78088cc0b97SApple OSS Distributions uint32_t idx; 7810f3703acSApple OSS Distributions bool addresses; 7820f3703acSApple OSS Distributions 7830f3703acSApple OSS Distributions IOTRecursiveLockLock(&queue->lock); 784a5e72196SApple OSS Distributions for (idx = 0; idx < queue->numSiteQs; idx++) { 785a5e72196SApple OSS Distributions while (!queue_empty(&queue->sites[idx])) { 786a5e72196SApple OSS Distributions if (kIOTrackingQueueTypeMap & queue->type) { 78788cc0b97SApple OSS Distributions queue_remove_first(&queue->sites[idx], user, IOTrackingUser *, link); 78888cc0b97SApple OSS Distributions user->link.next = user->link.prev = NULL; 789a5e72196SApple OSS Distributions } else { 79088cc0b97SApple OSS Distributions queue_remove_first(&queue->sites[idx], site, IOTrackingCallSite *, link); 7910f3703acSApple OSS Distributions addresses = false; 792a5e72196SApple OSS Distributions while (!queue_empty(&site->instances)) { 7930f3703acSApple OSS Distributions queue_remove_first(&site->instances, tracking, IOTracking *, link); 794a5e72196SApple OSS Distributions if (tracking == site->addresses) { 795a5e72196SApple OSS Distributions addresses = true; 796a5e72196SApple OSS Distributions } 797a5e72196SApple OSS Distributions if (addresses) { 7980f3703acSApple OSS Distributions trackingAddress = (typeof(trackingAddress))tracking; 799a5e72196SApple OSS Distributions if (kTrackingAddressFlagAllocated & IOTrackingAddressFlags(trackingAddress)) { 8000f3703acSApple OSS Distributions kfree(tracking, sizeof(IOTrackingAddress)); 8010f3703acSApple OSS Distributions } 8020f3703acSApple OSS Distributions } 8030f3703acSApple OSS Distributions } 804*bb611c8fSApple OSS Distributions size_t siteSize = sizeof(IOTrackingCallSite); 805*bb611c8fSApple OSS Distributions if (kIOTrackingQueueTypeUser & queue->type) { 806*bb611c8fSApple OSS Distributions siteSize += sizeof(IOTrackingCallSiteUser); 807*bb611c8fSApple OSS Distributions } 808*bb611c8fSApple OSS Distributions kfree(site, siteSize); 8090f3703acSApple OSS Distributions } 81088cc0b97SApple OSS Distributions } 81188cc0b97SApple OSS Distributions } 8120f3703acSApple OSS Distributions queue->siteCount = 0; 8130f3703acSApple OSS Distributions IOTRecursiveLockUnlock(&queue->lock); 8140f3703acSApple OSS Distributions } 8150f3703acSApple OSS Distributions 8160f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 8170f3703acSApple OSS Distributions 8180f3703acSApple OSS Distributions static int 8190f3703acSApple OSS Distributions IOTrackingCallSiteInfoCompare(const void * left, const void * right) 8200f3703acSApple OSS Distributions { 8210f3703acSApple OSS Distributions IOTrackingCallSiteInfo * l = (typeof(l))left; 8220f3703acSApple OSS Distributions IOTrackingCallSiteInfo * r = (typeof(r))right; 8230f3703acSApple OSS Distributions size_t lsize, rsize; 8240f3703acSApple OSS Distributions 8250f3703acSApple OSS Distributions rsize = r->size[0] + r->size[1]; 8260f3703acSApple OSS Distributions lsize = l->size[0] + l->size[1]; 8270f3703acSApple OSS Distributions 828a5e72196SApple OSS Distributions return (rsize > lsize) ? 1 : ((rsize == lsize) ? 0 : -1); 8290f3703acSApple OSS Distributions } 8300f3703acSApple OSS Distributions 8310f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 8320f3703acSApple OSS Distributions 8330f3703acSApple OSS Distributions static int 8340f3703acSApple OSS Distributions IOTrackingAddressCompare(const void * left, const void * right) 8350f3703acSApple OSS Distributions { 8360f3703acSApple OSS Distributions IOTracking * instance; 8370f3703acSApple OSS Distributions uintptr_t inst, laddr, raddr; 8380f3703acSApple OSS Distributions 8390f3703acSApple OSS Distributions inst = ((typeof(inst) *)left)[0]; 84088cc0b97SApple OSS Distributions instance = (typeof(instance))INSTANCE_GET(inst); 841a5e72196SApple OSS Distributions if (kInstanceFlagAddress & inst) { 842a5e72196SApple OSS Distributions laddr = ~((IOTrackingAddress *)instance)->address; 843a5e72196SApple OSS Distributions } else { 844a5e72196SApple OSS Distributions laddr = (uintptr_t) (instance + 1); 845a5e72196SApple OSS Distributions } 8460f3703acSApple OSS Distributions 8470f3703acSApple OSS Distributions inst = ((typeof(inst) *)right)[0]; 8480f3703acSApple OSS Distributions instance = (typeof(instance))(inst & ~kInstanceFlags); 849a5e72196SApple OSS Distributions if (kInstanceFlagAddress & inst) { 850a5e72196SApple OSS Distributions raddr = ~((IOTrackingAddress *)instance)->address; 851a5e72196SApple OSS Distributions } else { 852a5e72196SApple OSS Distributions raddr = (uintptr_t) (instance + 1); 853a5e72196SApple OSS Distributions } 8540f3703acSApple OSS Distributions 855a5e72196SApple OSS Distributions return (laddr > raddr) ? 1 : ((laddr == raddr) ? 0 : -1); 8560f3703acSApple OSS Distributions } 8570f3703acSApple OSS Distributions 85888cc0b97SApple OSS Distributions 85988cc0b97SApple OSS Distributions static int 86088cc0b97SApple OSS Distributions IOTrackingZoneElementCompare(const void * left, const void * right) 86188cc0b97SApple OSS Distributions { 86288cc0b97SApple OSS Distributions uintptr_t inst, laddr, raddr; 86388cc0b97SApple OSS Distributions 86488cc0b97SApple OSS Distributions inst = ((typeof(inst) *)left)[0]; 86588cc0b97SApple OSS Distributions laddr = INSTANCE_PUT(inst); 86688cc0b97SApple OSS Distributions inst = ((typeof(inst) *)right)[0]; 86788cc0b97SApple OSS Distributions raddr = INSTANCE_PUT(inst); 86888cc0b97SApple OSS Distributions 869a5e72196SApple OSS Distributions return (laddr > raddr) ? 1 : ((laddr == raddr) ? 0 : -1); 87088cc0b97SApple OSS Distributions } 87188cc0b97SApple OSS Distributions 87288cc0b97SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 87388cc0b97SApple OSS Distributions 87488cc0b97SApple OSS Distributions static void 875*bb611c8fSApple OSS Distributions CopyOutBacktraces(IOTrackingCallSite * site, IOTrackingCallSiteInfo * siteInfo) 87688cc0b97SApple OSS Distributions { 87788cc0b97SApple OSS Distributions uint32_t j; 87888cc0b97SApple OSS Distributions mach_vm_address_t bt, btEntry; 87988cc0b97SApple OSS Distributions 88088cc0b97SApple OSS Distributions btEntry = site->queue->btEntry; 881a5e72196SApple OSS Distributions for (j = 0; j < kIOTrackingCallSiteBTs; j++) { 88288cc0b97SApple OSS Distributions bt = site->bt[j]; 88388cc0b97SApple OSS Distributions if (btEntry 884a5e72196SApple OSS Distributions && (!bt || (j == (kIOTrackingCallSiteBTs - 1)))) { 88588cc0b97SApple OSS Distributions bt = btEntry; 88688cc0b97SApple OSS Distributions btEntry = 0; 88788cc0b97SApple OSS Distributions } 88888cc0b97SApple OSS Distributions siteInfo->bt[0][j] = VM_KERNEL_UNSLIDE(bt); 88988cc0b97SApple OSS Distributions } 890*bb611c8fSApple OSS Distributions 891*bb611c8fSApple OSS Distributions siteInfo->btPID = 0; 892*bb611c8fSApple OSS Distributions if (kIOTrackingQueueTypeUser & site->queue->type) { 893*bb611c8fSApple OSS Distributions siteInfo->btPID = site->user[0].pid; 894*bb611c8fSApple OSS Distributions uint32_t * bt32 = (typeof(bt32))((void *) &site->user[0].bt[0]); 895*bb611c8fSApple OSS Distributions uint64_t * bt64 = (typeof(bt64))((void *) &site->user[0].bt[0]); 896*bb611c8fSApple OSS Distributions for (uint32_t j = 0; j < kIOTrackingCallSiteBTs; j++) { 897*bb611c8fSApple OSS Distributions if (j >= site->user[0].userCount) { 898*bb611c8fSApple OSS Distributions siteInfo->bt[1][j] = 0; 899*bb611c8fSApple OSS Distributions } else if (site->user[0].user32) { 900*bb611c8fSApple OSS Distributions siteInfo->bt[1][j] = bt32[j]; 901*bb611c8fSApple OSS Distributions } else { 902*bb611c8fSApple OSS Distributions siteInfo->bt[1][j] = bt64[j]; 903*bb611c8fSApple OSS Distributions } 904*bb611c8fSApple OSS Distributions } 905*bb611c8fSApple OSS Distributions } 90688cc0b97SApple OSS Distributions } 90788cc0b97SApple OSS Distributions 9080f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 9090f3703acSApple OSS Distributions 9100f3703acSApple OSS Distributions static void 9110f3703acSApple OSS Distributions IOTrackingLeakScan(void * refcon) 9120f3703acSApple OSS Distributions { 9130f3703acSApple OSS Distributions IOTrackingLeaksRef * ref = (typeof(ref))refcon; 9140f3703acSApple OSS Distributions uintptr_t * instances; 9150f3703acSApple OSS Distributions IOTracking * instance; 9160f3703acSApple OSS Distributions uint64_t vaddr, vincr; 9170f3703acSApple OSS Distributions ppnum_t ppn; 91888cc0b97SApple OSS Distributions uintptr_t ptr, addr, vphysaddr, inst; 91976e12aa3SApple OSS Distributions size_t size, origsize; 9200f3703acSApple OSS Distributions uint32_t baseIdx, lim, ptrIdx, count; 9210f3703acSApple OSS Distributions boolean_t is; 92288cc0b97SApple OSS Distributions AbsoluteTime deadline; 9230f3703acSApple OSS Distributions 9240f3703acSApple OSS Distributions instances = ref->instances; 9250f3703acSApple OSS Distributions count = ref->count; 92676e12aa3SApple OSS Distributions size = origsize = ref->zoneSize; 9270f3703acSApple OSS Distributions 92888cc0b97SApple OSS Distributions for (deadline = 0, vaddr = VM_MIN_KERNEL_AND_KEXT_ADDRESS; 92988cc0b97SApple OSS Distributions ; 930a5e72196SApple OSS Distributions vaddr += vincr) { 931a5e72196SApple OSS Distributions if ((mach_absolute_time() > deadline) || (vaddr >= VM_MAX_KERNEL_ADDRESS)) { 932a5e72196SApple OSS Distributions if (deadline) { 93388cc0b97SApple OSS Distributions ml_set_interrupts_enabled(is); 93488cc0b97SApple OSS Distributions IODelay(10); 93588cc0b97SApple OSS Distributions } 936a5e72196SApple OSS Distributions if (vaddr >= VM_MAX_KERNEL_ADDRESS) { 937a5e72196SApple OSS Distributions break; 938a5e72196SApple OSS Distributions } 9390f3703acSApple OSS Distributions is = ml_set_interrupts_enabled(false); 94088cc0b97SApple OSS Distributions clock_interval_to_deadline(10, kMillisecondScale, &deadline); 94188cc0b97SApple OSS Distributions } 9420f3703acSApple OSS Distributions 94388cc0b97SApple OSS Distributions ppn = kernel_pmap_present_mapping(vaddr, &vincr, &vphysaddr); 9440f3703acSApple OSS Distributions // check noencrypt to avoid VM structs (map entries) with pointers 945a5e72196SApple OSS Distributions if (ppn && (!pmap_valid_page(ppn) || (!ref->zoneSize && pmap_is_noencrypt(ppn)))) { 946a5e72196SApple OSS Distributions ppn = 0; 947a5e72196SApple OSS Distributions } 948a5e72196SApple OSS Distributions if (!ppn) { 949a5e72196SApple OSS Distributions continue; 950a5e72196SApple OSS Distributions } 9510f3703acSApple OSS Distributions 952a5e72196SApple OSS Distributions for (ptrIdx = 0; ptrIdx < (page_size / sizeof(uintptr_t)); ptrIdx++) { 95388cc0b97SApple OSS Distributions ptr = ((uintptr_t *)vphysaddr)[ptrIdx]; 954*bb611c8fSApple OSS Distributions #if defined(HAS_APPLE_PAC) 955*bb611c8fSApple OSS Distributions // strip possible ptrauth signature from candidate data pointer 956*bb611c8fSApple OSS Distributions ptr = (uintptr_t)ptrauth_strip((void*)ptr, ptrauth_key_process_independent_data); 957*bb611c8fSApple OSS Distributions #endif /* defined(HAS_APPLE_PAC) */ 9580f3703acSApple OSS Distributions 959a5e72196SApple OSS Distributions for (lim = count, baseIdx = 0; lim; lim >>= 1) { 9600f3703acSApple OSS Distributions inst = instances[baseIdx + (lim >> 1)]; 96188cc0b97SApple OSS Distributions instance = (typeof(instance))INSTANCE_GET(inst); 96288cc0b97SApple OSS Distributions 963a5e72196SApple OSS Distributions if (ref->zoneSize) { 96488cc0b97SApple OSS Distributions addr = INSTANCE_PUT(inst) & ~kInstanceFlags; 965a5e72196SApple OSS Distributions } else if (kInstanceFlagAddress & inst) { 9660f3703acSApple OSS Distributions addr = ~((IOTrackingAddress *)instance)->address; 96776e12aa3SApple OSS Distributions origsize = size = ((IOTrackingAddress *)instance)->size; 968a5e72196SApple OSS Distributions if (!size) { 969a5e72196SApple OSS Distributions size = 1; 9700f3703acSApple OSS Distributions } 971a5e72196SApple OSS Distributions } else { 9720f3703acSApple OSS Distributions addr = (uintptr_t) (instance + 1); 97376e12aa3SApple OSS Distributions origsize = size = instance->site->queue->allocSize; 9740f3703acSApple OSS Distributions } 97588cc0b97SApple OSS Distributions if ((ptr >= addr) && (ptr < (addr + size)) 97688cc0b97SApple OSS Distributions 97788cc0b97SApple OSS Distributions && (((vaddr + ptrIdx * sizeof(uintptr_t)) < addr) 978a5e72196SApple OSS Distributions || ((vaddr + ptrIdx * sizeof(uintptr_t)) >= (addr + size)))) { 979a5e72196SApple OSS Distributions if (!(kInstanceFlagReferenced & inst)) { 9800f3703acSApple OSS Distributions inst |= kInstanceFlagReferenced; 9810f3703acSApple OSS Distributions instances[baseIdx + (lim >> 1)] = inst; 9820f3703acSApple OSS Distributions ref->found++; 983a5e72196SApple OSS Distributions if (!origsize) { 984a5e72196SApple OSS Distributions ref->foundzlen++; 985a5e72196SApple OSS Distributions } 9860f3703acSApple OSS Distributions } 9870f3703acSApple OSS Distributions break; 9880f3703acSApple OSS Distributions } 989a5e72196SApple OSS Distributions if (ptr > addr) { 9900f3703acSApple OSS Distributions // move right 9910f3703acSApple OSS Distributions baseIdx += (lim >> 1) + 1; 9920f3703acSApple OSS Distributions lim--; 9930f3703acSApple OSS Distributions } 9940f3703acSApple OSS Distributions // else move left 9950f3703acSApple OSS Distributions } 9960f3703acSApple OSS Distributions } 9970f3703acSApple OSS Distributions ref->bytes += page_size; 9980f3703acSApple OSS Distributions } 9990f3703acSApple OSS Distributions } 10000f3703acSApple OSS Distributions 10010f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 10020f3703acSApple OSS Distributions 100388cc0b97SApple OSS Distributions extern "C" void 100488cc0b97SApple OSS Distributions zone_leaks_scan(uintptr_t * instances, uint32_t count, uint32_t zoneSize, uint32_t * found) 100588cc0b97SApple OSS Distributions { 100688cc0b97SApple OSS Distributions IOTrackingLeaksRef ref; 100788cc0b97SApple OSS Distributions IOTrackingCallSiteInfo siteInfo; 100888cc0b97SApple OSS Distributions uint32_t idx; 100988cc0b97SApple OSS Distributions 101088cc0b97SApple OSS Distributions qsort(instances, count, sizeof(*instances), &IOTrackingZoneElementCompare); 101188cc0b97SApple OSS Distributions 101288cc0b97SApple OSS Distributions bzero(&siteInfo, sizeof(siteInfo)); 101388cc0b97SApple OSS Distributions bzero(&ref, sizeof(ref)); 101488cc0b97SApple OSS Distributions ref.instances = instances; 101588cc0b97SApple OSS Distributions ref.count = count; 101688cc0b97SApple OSS Distributions ref.zoneSize = zoneSize; 101788cc0b97SApple OSS Distributions 1018a5e72196SApple OSS Distributions for (idx = 0; idx < 2; idx++) { 101988cc0b97SApple OSS Distributions ref.bytes = 0; 102088cc0b97SApple OSS Distributions IOTrackingLeakScan(&ref); 102188cc0b97SApple OSS Distributions IOLog("leaks(%d) scanned %ld MB, instance count %d, found %d\n", idx, ref.bytes / 1024 / 1024, count, ref.found); 1022a5e72196SApple OSS Distributions if (count <= ref.found) { 1023a5e72196SApple OSS Distributions break; 1024a5e72196SApple OSS Distributions } 102588cc0b97SApple OSS Distributions } 102688cc0b97SApple OSS Distributions 102788cc0b97SApple OSS Distributions *found = ref.found; 102888cc0b97SApple OSS Distributions } 102988cc0b97SApple OSS Distributions 103088cc0b97SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 103188cc0b97SApple OSS Distributions 103288cc0b97SApple OSS Distributions static void 103388cc0b97SApple OSS Distributions ZoneSiteProc(void * refCon, uint32_t siteCount, uint32_t zoneSize, 103488cc0b97SApple OSS Distributions uintptr_t * backtrace, uint32_t btCount) 103588cc0b97SApple OSS Distributions { 103688cc0b97SApple OSS Distributions IOTrackingCallSiteInfo siteInfo; 103788cc0b97SApple OSS Distributions OSData * leakData; 103888cc0b97SApple OSS Distributions uint32_t idx; 103988cc0b97SApple OSS Distributions 104088cc0b97SApple OSS Distributions leakData = (typeof(leakData))refCon; 104188cc0b97SApple OSS Distributions 104288cc0b97SApple OSS Distributions bzero(&siteInfo, sizeof(siteInfo)); 104388cc0b97SApple OSS Distributions siteInfo.count = siteCount; 104488cc0b97SApple OSS Distributions siteInfo.size[0] = zoneSize * siteCount; 104588cc0b97SApple OSS Distributions 1046a5e72196SApple OSS Distributions for (idx = 0; (idx < btCount) && (idx < kIOTrackingCallSiteBTs); idx++) { 104788cc0b97SApple OSS Distributions siteInfo.bt[0][idx] = VM_KERNEL_UNSLIDE(backtrace[idx]); 104888cc0b97SApple OSS Distributions } 104988cc0b97SApple OSS Distributions 105088cc0b97SApple OSS Distributions leakData->appendBytes(&siteInfo, sizeof(siteInfo)); 105188cc0b97SApple OSS Distributions } 105288cc0b97SApple OSS Distributions 105388cc0b97SApple OSS Distributions 105488cc0b97SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 105588cc0b97SApple OSS Distributions 10560f3703acSApple OSS Distributions static OSData * 1057a5e72196SApple OSS Distributions IOTrackingLeaks(LIBKERN_CONSUMED OSData * data) 10580f3703acSApple OSS Distributions { 10590f3703acSApple OSS Distributions IOTrackingLeaksRef ref; 106088cc0b97SApple OSS Distributions IOTrackingCallSiteInfo siteInfo; 10610f3703acSApple OSS Distributions IOTrackingCallSite * site; 10620f3703acSApple OSS Distributions OSData * leakData; 10630f3703acSApple OSS Distributions uintptr_t * instances; 10640f3703acSApple OSS Distributions IOTracking * instance; 10650f3703acSApple OSS Distributions uintptr_t inst; 10660f3703acSApple OSS Distributions uint32_t count, idx, numSites, dups, siteCount; 10670f3703acSApple OSS Distributions 10680f3703acSApple OSS Distributions instances = (typeof(instances))data->getBytesNoCopy(); 10690f3703acSApple OSS Distributions count = (data->getLength() / sizeof(*instances)); 10700f3703acSApple OSS Distributions qsort(instances, count, sizeof(*instances), &IOTrackingAddressCompare); 10710f3703acSApple OSS Distributions 107288cc0b97SApple OSS Distributions bzero(&siteInfo, sizeof(siteInfo)); 10730f3703acSApple OSS Distributions bzero(&ref, sizeof(ref)); 10740f3703acSApple OSS Distributions ref.instances = instances; 10750f3703acSApple OSS Distributions ref.count = count; 1076a5e72196SApple OSS Distributions for (idx = 0; idx < 2; idx++) { 107788cc0b97SApple OSS Distributions ref.bytes = 0; 10780f3703acSApple OSS Distributions IOTrackingLeakScan(&ref); 107976e12aa3SApple 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); 1080a5e72196SApple OSS Distributions if (count <= ref.found) { 1081a5e72196SApple OSS Distributions break; 1082a5e72196SApple OSS Distributions } 108388cc0b97SApple OSS Distributions } 10840f3703acSApple OSS Distributions 10850f3703acSApple OSS Distributions leakData = OSData::withCapacity(128 * sizeof(IOTrackingCallSiteInfo)); 10860f3703acSApple OSS Distributions 1087a5e72196SApple OSS Distributions for (numSites = 0, idx = 0; idx < count; idx++) { 10880f3703acSApple OSS Distributions inst = instances[idx]; 1089a5e72196SApple OSS Distributions if (kInstanceFlagReferenced & inst) { 1090a5e72196SApple OSS Distributions continue; 1091a5e72196SApple OSS Distributions } 109288cc0b97SApple OSS Distributions instance = (typeof(instance))INSTANCE_GET(inst); 10930f3703acSApple OSS Distributions site = instance->site; 10940f3703acSApple OSS Distributions instances[numSites] = (uintptr_t) site; 10950f3703acSApple OSS Distributions numSites++; 10960f3703acSApple OSS Distributions } 10970f3703acSApple OSS Distributions 1098a5e72196SApple OSS Distributions for (idx = 0; idx < numSites; idx++) { 10990f3703acSApple OSS Distributions inst = instances[idx]; 1100a5e72196SApple OSS Distributions if (!inst) { 1101a5e72196SApple OSS Distributions continue; 1102a5e72196SApple OSS Distributions } 11030f3703acSApple OSS Distributions site = (typeof(site))inst; 1104a5e72196SApple OSS Distributions for (siteCount = 1, dups = (idx + 1); dups < numSites; dups++) { 1105a5e72196SApple OSS Distributions if (instances[dups] == (uintptr_t) site) { 11060f3703acSApple OSS Distributions siteCount++; 11070f3703acSApple OSS Distributions instances[dups] = 0; 11080f3703acSApple OSS Distributions } 11090f3703acSApple OSS Distributions } 111088cc0b97SApple OSS Distributions siteInfo.count = siteCount; 111188cc0b97SApple OSS Distributions siteInfo.size[0] = (site->size[0] * site->count) / siteCount; 111288cc0b97SApple OSS Distributions siteInfo.size[1] = (site->size[1] * site->count) / siteCount;; 1113*bb611c8fSApple OSS Distributions CopyOutBacktraces(site, &siteInfo); 111488cc0b97SApple OSS Distributions leakData->appendBytes(&siteInfo, sizeof(siteInfo)); 11150f3703acSApple OSS Distributions } 11160f3703acSApple OSS Distributions data->release(); 11170f3703acSApple OSS Distributions 1118a5e72196SApple OSS Distributions return leakData; 11190f3703acSApple OSS Distributions } 11200f3703acSApple OSS Distributions 11210f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 11220f3703acSApple OSS Distributions 11230f3703acSApple OSS Distributions static bool 11240f3703acSApple OSS Distributions SkipName(uint32_t options, const char * name, size_t namesLen, const char * names) 11250f3703acSApple OSS Distributions { 11260f3703acSApple OSS Distributions const char * scan; 11270f3703acSApple OSS Distributions const char * next; 11280f3703acSApple OSS Distributions bool exclude, found; 11290f3703acSApple OSS Distributions size_t qLen, sLen; 11300f3703acSApple OSS Distributions 1131a5e72196SApple OSS Distributions if (!namesLen || !names) { 1132a5e72196SApple OSS Distributions return false; 1133a5e72196SApple OSS Distributions } 11340f3703acSApple OSS Distributions // <len><name>...<len><name><0> 11350f3703acSApple OSS Distributions exclude = (0 != (kIOTrackingExcludeNames & options)); 11360f3703acSApple OSS Distributions qLen = strlen(name); 11370f3703acSApple OSS Distributions scan = names; 11380f3703acSApple OSS Distributions found = false; 1139a5e72196SApple OSS Distributions do{ 11400f3703acSApple OSS Distributions sLen = scan[0]; 11410f3703acSApple OSS Distributions scan++; 11420f3703acSApple OSS Distributions next = scan + sLen; 1143a5e72196SApple OSS Distributions if (next >= (names + namesLen)) { 1144a5e72196SApple OSS Distributions break; 1145a5e72196SApple OSS Distributions } 11460f3703acSApple OSS Distributions found = ((sLen == qLen) && !strncmp(scan, name, sLen)); 11470f3703acSApple OSS Distributions scan = next; 1148a5e72196SApple OSS Distributions }while (!found && (scan < (names + namesLen))); 11490f3703acSApple OSS Distributions 1150a5e72196SApple OSS Distributions return !(exclude ^ found); 11510f3703acSApple OSS Distributions } 11520f3703acSApple OSS Distributions 11530f3703acSApple OSS Distributions #endif /* IOTRACKING */ 11540f3703acSApple OSS Distributions 11550f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 11560f3703acSApple OSS Distributions 115776e12aa3SApple OSS Distributions static kern_return_t 115888cc0b97SApple OSS Distributions IOTrackingDebug(uint32_t selector, uint32_t options, uint64_t value, 115976e12aa3SApple OSS Distributions uint32_t intag, uint32_t inzsize, 11600f3703acSApple OSS Distributions const char * names, size_t namesLen, 11610f3703acSApple OSS Distributions size_t size, OSObject ** result) 11620f3703acSApple OSS Distributions { 11630f3703acSApple OSS Distributions kern_return_t ret; 11640f3703acSApple OSS Distributions OSData * data; 11650f3703acSApple OSS Distributions 1166a5e72196SApple OSS Distributions if (result) { 1167a5e72196SApple OSS Distributions *result = NULL; 1168a5e72196SApple OSS Distributions } 1169a5e72196SApple OSS Distributions data = NULL; 11700f3703acSApple OSS Distributions ret = kIOReturnNotReady; 11710f3703acSApple OSS Distributions 11720f3703acSApple OSS Distributions #if IOTRACKING 11730f3703acSApple OSS Distributions 117488cc0b97SApple OSS Distributions kern_return_t kr; 11750f3703acSApple OSS Distributions IOTrackingQueue * queue; 11760f3703acSApple OSS Distributions IOTracking * instance; 11770f3703acSApple OSS Distributions IOTrackingCallSite * site; 117888cc0b97SApple OSS Distributions IOTrackingCallSiteInfo siteInfo; 117988cc0b97SApple OSS Distributions IOTrackingUser * user; 118088cc0b97SApple OSS Distributions task_t mapTask; 118188cc0b97SApple OSS Distributions mach_vm_address_t mapAddress; 118288cc0b97SApple OSS Distributions mach_vm_size_t mapSize; 118388cc0b97SApple OSS Distributions uint32_t num, idx, qIdx; 11840f3703acSApple OSS Distributions uintptr_t instFlags; 118588cc0b97SApple OSS Distributions proc_t proc; 118688cc0b97SApple OSS Distributions bool addresses; 11870f3703acSApple OSS Distributions 11880f3703acSApple OSS Distributions ret = kIOReturnNotFound; 118988cc0b97SApple OSS Distributions proc = NULL; 1190a5e72196SApple OSS Distributions if (kIOTrackingGetMappings == selector) { 1191a5e72196SApple OSS Distributions if (value != -1ULL) { 1192*bb611c8fSApple OSS Distributions proc = proc_find((pid_t) value); 1193a5e72196SApple OSS Distributions if (!proc) { 1194a5e72196SApple OSS Distributions return kIOReturnNotFound; 1195a5e72196SApple OSS Distributions } 119688cc0b97SApple OSS Distributions } 119788cc0b97SApple OSS Distributions } 11980f3703acSApple OSS Distributions 119988cc0b97SApple OSS Distributions bzero(&siteInfo, sizeof(siteInfo)); 12000f3703acSApple OSS Distributions lck_mtx_lock(gIOTrackingLock); 12010f3703acSApple OSS Distributions queue_iterate(&gIOTrackingQ, queue, IOTrackingQueue *, link) 12020f3703acSApple OSS Distributions { 1203a5e72196SApple OSS Distributions if (SkipName(options, queue->name, namesLen, names)) { 1204a5e72196SApple OSS Distributions continue; 1205a5e72196SApple OSS Distributions } 12060f3703acSApple OSS Distributions 1207a5e72196SApple OSS Distributions if (!(kIOTracking & gIOKitDebug) && (kIOTrackingQueueTypeAlloc & queue->type)) { 1208a5e72196SApple OSS Distributions continue; 1209a5e72196SApple OSS Distributions } 121088cc0b97SApple OSS Distributions 1211a5e72196SApple OSS Distributions switch (selector) { 12120f3703acSApple OSS Distributions case kIOTrackingResetTracking: 12130f3703acSApple OSS Distributions { 12140f3703acSApple OSS Distributions IOTrackingReset(queue); 12150f3703acSApple OSS Distributions ret = kIOReturnSuccess; 12160f3703acSApple OSS Distributions break; 12170f3703acSApple OSS Distributions } 12180f3703acSApple OSS Distributions 12190f3703acSApple OSS Distributions case kIOTrackingStartCapture: 12200f3703acSApple OSS Distributions case kIOTrackingStopCapture: 12210f3703acSApple OSS Distributions { 12220f3703acSApple OSS Distributions queue->captureOn = (kIOTrackingStartCapture == selector); 12230f3703acSApple OSS Distributions ret = kIOReturnSuccess; 12240f3703acSApple OSS Distributions break; 12250f3703acSApple OSS Distributions } 12260f3703acSApple OSS Distributions 12270f3703acSApple OSS Distributions case kIOTrackingSetMinCaptureSize: 12280f3703acSApple OSS Distributions { 12290f3703acSApple OSS Distributions queue->minCaptureSize = size; 12300f3703acSApple OSS Distributions ret = kIOReturnSuccess; 12310f3703acSApple OSS Distributions break; 12320f3703acSApple OSS Distributions } 12330f3703acSApple OSS Distributions 12340f3703acSApple OSS Distributions case kIOTrackingLeaks: 12350f3703acSApple OSS Distributions { 1236a5e72196SApple OSS Distributions if (!(kIOTrackingQueueTypeAlloc & queue->type)) { 1237a5e72196SApple OSS Distributions break; 1238a5e72196SApple OSS Distributions } 12390f3703acSApple OSS Distributions 1240a5e72196SApple OSS Distributions if (!data) { 1241a5e72196SApple OSS Distributions data = OSData::withCapacity(1024 * sizeof(uintptr_t)); 1242a5e72196SApple OSS Distributions } 12430f3703acSApple OSS Distributions 12440f3703acSApple OSS Distributions IOTRecursiveLockLock(&queue->lock); 1245a5e72196SApple OSS Distributions for (idx = 0; idx < queue->numSiteQs; idx++) { 124688cc0b97SApple OSS Distributions queue_iterate(&queue->sites[idx], site, IOTrackingCallSite *, link) 12470f3703acSApple OSS Distributions { 12480f3703acSApple OSS Distributions addresses = false; 12490f3703acSApple OSS Distributions queue_iterate(&site->instances, instance, IOTracking *, link) 12500f3703acSApple OSS Distributions { 1251a5e72196SApple OSS Distributions if (instance == site->addresses) { 1252a5e72196SApple OSS Distributions addresses = true; 1253a5e72196SApple OSS Distributions } 12540f3703acSApple OSS Distributions instFlags = (typeof(instFlags))instance; 1255a5e72196SApple OSS Distributions if (addresses) { 1256a5e72196SApple OSS Distributions instFlags |= kInstanceFlagAddress; 1257a5e72196SApple OSS Distributions } 12580f3703acSApple OSS Distributions data->appendBytes(&instFlags, sizeof(instFlags)); 12590f3703acSApple OSS Distributions } 12600f3703acSApple OSS Distributions } 126188cc0b97SApple OSS Distributions } 12620f3703acSApple OSS Distributions // queue is locked 12630f3703acSApple OSS Distributions ret = kIOReturnSuccess; 12640f3703acSApple OSS Distributions break; 12650f3703acSApple OSS Distributions } 12660f3703acSApple OSS Distributions 126776e12aa3SApple OSS Distributions 12680f3703acSApple OSS Distributions case kIOTrackingGetTracking: 12690f3703acSApple OSS Distributions { 1270a5e72196SApple OSS Distributions if (kIOTrackingQueueTypeMap & queue->type) { 1271a5e72196SApple OSS Distributions break; 1272a5e72196SApple OSS Distributions } 127388cc0b97SApple OSS Distributions 1274a5e72196SApple OSS Distributions if (!data) { 1275a5e72196SApple OSS Distributions data = OSData::withCapacity(128 * sizeof(IOTrackingCallSiteInfo)); 1276a5e72196SApple OSS Distributions } 12770f3703acSApple OSS Distributions 12780f3703acSApple OSS Distributions IOTRecursiveLockLock(&queue->lock); 12790f3703acSApple OSS Distributions num = queue->siteCount; 12800f3703acSApple OSS Distributions idx = 0; 1281a5e72196SApple OSS Distributions for (qIdx = 0; qIdx < queue->numSiteQs; qIdx++) { 128288cc0b97SApple OSS Distributions queue_iterate(&queue->sites[qIdx], site, IOTrackingCallSite *, link) 12830f3703acSApple OSS Distributions { 12840f3703acSApple OSS Distributions assert(idx < num); 12850f3703acSApple OSS Distributions idx++; 12860f3703acSApple OSS Distributions 128776e12aa3SApple OSS Distributions size_t tsize[2]; 128876e12aa3SApple OSS Distributions uint32_t count = site->count; 128976e12aa3SApple OSS Distributions tsize[0] = site->size[0]; 129076e12aa3SApple OSS Distributions tsize[1] = site->size[1]; 12910f3703acSApple OSS Distributions 1292a5e72196SApple OSS Distributions if (intag || inzsize) { 129376e12aa3SApple OSS Distributions uintptr_t addr; 129476e12aa3SApple OSS Distributions vm_size_t size, zoneSize; 129576e12aa3SApple OSS Distributions vm_tag_t tag; 129676e12aa3SApple OSS Distributions 1297a5e72196SApple OSS Distributions if (kIOTrackingQueueTypeAlloc & queue->type) { 129876e12aa3SApple OSS Distributions addresses = false; 129976e12aa3SApple OSS Distributions count = 0; 130076e12aa3SApple OSS Distributions tsize[0] = tsize[1] = 0; 130176e12aa3SApple OSS Distributions queue_iterate(&site->instances, instance, IOTracking *, link) 130276e12aa3SApple OSS Distributions { 1303a5e72196SApple OSS Distributions if (instance == site->addresses) { 1304a5e72196SApple OSS Distributions addresses = true; 1305a5e72196SApple OSS Distributions } 130676e12aa3SApple OSS Distributions 1307a5e72196SApple OSS Distributions if (addresses) { 1308a5e72196SApple OSS Distributions addr = ~((IOTrackingAddress *)instance)->address; 1309a5e72196SApple OSS Distributions } else { 1310a5e72196SApple OSS Distributions addr = (uintptr_t) (instance + 1); 1311a5e72196SApple OSS Distributions } 131276e12aa3SApple OSS Distributions 131376e12aa3SApple OSS Distributions kr = vm_kern_allocation_info(addr, &size, &tag, &zoneSize); 1314a5e72196SApple OSS Distributions if (KERN_SUCCESS != kr) { 1315a5e72196SApple OSS Distributions continue; 1316a5e72196SApple OSS Distributions } 131776e12aa3SApple OSS Distributions 1318a5e72196SApple OSS Distributions if ((VM_KERN_MEMORY_NONE != intag) && (intag != tag)) { 1319a5e72196SApple OSS Distributions continue; 1320a5e72196SApple OSS Distributions } 1321a5e72196SApple OSS Distributions if (inzsize && (inzsize != zoneSize)) { 1322a5e72196SApple OSS Distributions continue; 1323a5e72196SApple OSS Distributions } 132476e12aa3SApple OSS Distributions 132576e12aa3SApple OSS Distributions count++; 132676e12aa3SApple OSS Distributions tsize[0] += size; 132776e12aa3SApple OSS Distributions } 1328a5e72196SApple OSS Distributions } else { 1329a5e72196SApple OSS Distributions if (!intag || inzsize || (intag != site->tag)) { 1330a5e72196SApple OSS Distributions continue; 133176e12aa3SApple OSS Distributions } 133276e12aa3SApple OSS Distributions } 133376e12aa3SApple OSS Distributions } 133476e12aa3SApple OSS Distributions 1335a5e72196SApple OSS Distributions if (!count) { 1336a5e72196SApple OSS Distributions continue; 1337a5e72196SApple OSS Distributions } 1338a5e72196SApple OSS Distributions if (size && ((tsize[0] + tsize[1]) < size)) { 1339a5e72196SApple OSS Distributions continue; 1340a5e72196SApple OSS Distributions } 134176e12aa3SApple OSS Distributions siteInfo.count = count; 134276e12aa3SApple OSS Distributions siteInfo.size[0] = tsize[0]; 134376e12aa3SApple OSS Distributions siteInfo.size[1] = tsize[1]; 1344*bb611c8fSApple OSS Distributions CopyOutBacktraces(site, &siteInfo); 134588cc0b97SApple OSS Distributions data->appendBytes(&siteInfo, sizeof(siteInfo)); 13460f3703acSApple OSS Distributions } 13470f3703acSApple OSS Distributions } 13480f3703acSApple OSS Distributions assert(idx == num); 13490f3703acSApple OSS Distributions IOTRecursiveLockUnlock(&queue->lock); 13500f3703acSApple OSS Distributions ret = kIOReturnSuccess; 13510f3703acSApple OSS Distributions break; 13520f3703acSApple OSS Distributions } 135388cc0b97SApple OSS Distributions 135488cc0b97SApple OSS Distributions case kIOTrackingGetMappings: 135588cc0b97SApple OSS Distributions { 1356a5e72196SApple OSS Distributions if (!(kIOTrackingQueueTypeMap & queue->type)) { 1357a5e72196SApple OSS Distributions break; 1358a5e72196SApple OSS Distributions } 1359a5e72196SApple OSS Distributions if (!data) { 1360*bb611c8fSApple OSS Distributions data = OSData::withCapacity((unsigned int) page_size); 1361a5e72196SApple OSS Distributions } 136288cc0b97SApple OSS Distributions 136388cc0b97SApple OSS Distributions IOTRecursiveLockLock(&queue->lock); 136488cc0b97SApple OSS Distributions num = queue->siteCount; 136588cc0b97SApple OSS Distributions idx = 0; 1366a5e72196SApple OSS Distributions for (qIdx = 0; qIdx < queue->numSiteQs; qIdx++) { 136788cc0b97SApple OSS Distributions queue_iterate(&queue->sites[qIdx], user, IOTrackingUser *, link) 136888cc0b97SApple OSS Distributions { 136988cc0b97SApple OSS Distributions assert(idx < num); 137088cc0b97SApple OSS Distributions idx++; 137188cc0b97SApple OSS Distributions 137288cc0b97SApple OSS Distributions kr = IOMemoryMapTracking(user, &mapTask, &mapAddress, &mapSize); 1373a5e72196SApple OSS Distributions if (kIOReturnSuccess != kr) { 1374a5e72196SApple OSS Distributions continue; 1375a5e72196SApple OSS Distributions } 1376a5e72196SApple OSS Distributions if (proc && (mapTask != proc_task(proc))) { 1377a5e72196SApple OSS Distributions continue; 1378a5e72196SApple OSS Distributions } 1379a5e72196SApple OSS Distributions if (size && (mapSize < size)) { 1380a5e72196SApple OSS Distributions continue; 1381a5e72196SApple OSS Distributions } 138288cc0b97SApple OSS Distributions 138388cc0b97SApple OSS Distributions siteInfo.count = 1; 138488cc0b97SApple OSS Distributions siteInfo.size[0] = mapSize; 138588cc0b97SApple OSS Distributions siteInfo.address = mapAddress; 138688cc0b97SApple OSS Distributions siteInfo.addressPID = task_pid(mapTask); 138788cc0b97SApple OSS Distributions siteInfo.btPID = user->btPID; 138888cc0b97SApple OSS Distributions 1389a5e72196SApple OSS Distributions for (uint32_t j = 0; j < kIOTrackingCallSiteBTs; j++) { 139088cc0b97SApple OSS Distributions siteInfo.bt[0][j] = VM_KERNEL_UNSLIDE(user->bt[j]); 139188cc0b97SApple OSS Distributions } 139288cc0b97SApple OSS Distributions uint32_t * bt32 = (typeof(bt32)) & user->btUser[0]; 139388cc0b97SApple OSS Distributions uint64_t * bt64 = (typeof(bt64))((void *) &user->btUser[0]); 1394a5e72196SApple OSS Distributions for (uint32_t j = 0; j < kIOTrackingCallSiteBTs; j++) { 1395a5e72196SApple OSS Distributions if (j >= user->userCount) { 1396a5e72196SApple OSS Distributions siteInfo.bt[1][j] = 0; 1397a5e72196SApple OSS Distributions } else if (user->user32) { 1398a5e72196SApple OSS Distributions siteInfo.bt[1][j] = bt32[j]; 1399a5e72196SApple OSS Distributions } else { 1400a5e72196SApple OSS Distributions siteInfo.bt[1][j] = bt64[j]; 1401a5e72196SApple OSS Distributions } 140288cc0b97SApple OSS Distributions } 140388cc0b97SApple OSS Distributions data->appendBytes(&siteInfo, sizeof(siteInfo)); 140488cc0b97SApple OSS Distributions } 140588cc0b97SApple OSS Distributions } 140688cc0b97SApple OSS Distributions assert(idx == num); 140788cc0b97SApple OSS Distributions IOTRecursiveLockUnlock(&queue->lock); 140888cc0b97SApple OSS Distributions ret = kIOReturnSuccess; 140988cc0b97SApple OSS Distributions break; 141088cc0b97SApple OSS Distributions } 141188cc0b97SApple OSS Distributions 14120f3703acSApple OSS Distributions default: 14130f3703acSApple OSS Distributions ret = kIOReturnUnsupported; 14140f3703acSApple OSS Distributions break; 14150f3703acSApple OSS Distributions } 14160f3703acSApple OSS Distributions } 14170f3703acSApple OSS Distributions 1418a5e72196SApple OSS Distributions if ((kIOTrackingLeaks == selector) && data) { 14190f3703acSApple OSS Distributions data = IOTrackingLeaks(data); 14200f3703acSApple OSS Distributions queue_iterate(&gIOTrackingQ, queue, IOTrackingQueue *, link) 14210f3703acSApple OSS Distributions { 1422a5e72196SApple OSS Distributions if (SkipName(options, queue->name, namesLen, names)) { 1423a5e72196SApple OSS Distributions continue; 1424a5e72196SApple OSS Distributions } 1425a5e72196SApple OSS Distributions if (!(kIOTrackingQueueTypeAlloc & queue->type)) { 1426a5e72196SApple OSS Distributions continue; 1427a5e72196SApple OSS Distributions } 14280f3703acSApple OSS Distributions IOTRecursiveLockUnlock(&queue->lock); 14290f3703acSApple OSS Distributions } 14300f3703acSApple OSS Distributions } 14310f3703acSApple OSS Distributions 14320f3703acSApple OSS Distributions lck_mtx_unlock(gIOTrackingLock); 14330f3703acSApple OSS Distributions 1434a5e72196SApple OSS Distributions if ((kIOTrackingLeaks == selector) && namesLen && names) { 143588cc0b97SApple OSS Distributions const char * scan; 143688cc0b97SApple OSS Distributions const char * next; 1437*bb611c8fSApple OSS Distributions uint8_t sLen; 14380f3703acSApple OSS Distributions 1439a5e72196SApple OSS Distributions if (!data) { 1440a5e72196SApple OSS Distributions data = OSData::withCapacity(4096 * sizeof(uintptr_t)); 1441a5e72196SApple OSS Distributions } 144288cc0b97SApple OSS Distributions 144388cc0b97SApple OSS Distributions // <len><name>...<len><name><0> 144488cc0b97SApple OSS Distributions scan = names; 1445a5e72196SApple OSS Distributions do{ 1446*bb611c8fSApple OSS Distributions sLen = ((uint8_t) scan[0]); 144788cc0b97SApple OSS Distributions scan++; 144888cc0b97SApple OSS Distributions next = scan + sLen; 1449a5e72196SApple OSS Distributions if (next >= (names + namesLen)) { 1450a5e72196SApple OSS Distributions break; 145188cc0b97SApple OSS Distributions } 1452a5e72196SApple OSS Distributions kr = zone_leaks(scan, sLen, &ZoneSiteProc, data); 1453a5e72196SApple OSS Distributions if (KERN_SUCCESS == kr) { 1454a5e72196SApple OSS Distributions ret = kIOReturnSuccess; 1455a5e72196SApple OSS Distributions } else if (KERN_INVALID_NAME != kr) { 1456a5e72196SApple OSS Distributions ret = kIOReturnVMError; 1457a5e72196SApple OSS Distributions } 1458a5e72196SApple OSS Distributions scan = next; 1459a5e72196SApple OSS Distributions }while (scan < (names + namesLen)); 146088cc0b97SApple OSS Distributions } 146188cc0b97SApple OSS Distributions 1462a5e72196SApple OSS Distributions if (data) { 1463a5e72196SApple OSS Distributions switch (selector) { 146488cc0b97SApple OSS Distributions case kIOTrackingLeaks: 146588cc0b97SApple OSS Distributions case kIOTrackingGetTracking: 146688cc0b97SApple OSS Distributions case kIOTrackingGetMappings: 146788cc0b97SApple OSS Distributions { 146888cc0b97SApple OSS Distributions IOTrackingCallSiteInfo * siteInfos; 146988cc0b97SApple OSS Distributions siteInfos = (typeof(siteInfos))data->getBytesNoCopy(); 147088cc0b97SApple OSS Distributions num = (data->getLength() / sizeof(*siteInfos)); 147188cc0b97SApple OSS Distributions qsort(siteInfos, num, sizeof(*siteInfos), &IOTrackingCallSiteInfoCompare); 147288cc0b97SApple OSS Distributions break; 14730f3703acSApple OSS Distributions } 147488cc0b97SApple OSS Distributions default: assert(false); break; 14750f3703acSApple OSS Distributions } 1476a5e72196SApple OSS Distributions } 14770f3703acSApple OSS Distributions 14780f3703acSApple OSS Distributions *result = data; 1479a5e72196SApple OSS Distributions if (proc) { 1480a5e72196SApple OSS Distributions proc_rele(proc); 1481a5e72196SApple OSS Distributions } 14820f3703acSApple OSS Distributions 14830f3703acSApple OSS Distributions #endif /* IOTRACKING */ 14840f3703acSApple OSS Distributions 1485a5e72196SApple OSS Distributions return ret; 14860f3703acSApple OSS Distributions } 14870f3703acSApple OSS Distributions 14880f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 14890f3703acSApple OSS Distributions 14900f3703acSApple OSS Distributions #include <IOKit/IOKitDiagnosticsUserClient.h> 14910f3703acSApple OSS Distributions 14920f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 14930f3703acSApple OSS Distributions 14940f3703acSApple OSS Distributions #undef super 14950f3703acSApple OSS Distributions #define super IOUserClient 14960f3703acSApple OSS Distributions 14970f3703acSApple OSS Distributions OSDefineMetaClassAndStructors(IOKitDiagnosticsClient, IOUserClient) 14980f3703acSApple OSS Distributions 14990f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 15000f3703acSApple OSS Distributions 15010f3703acSApple OSS Distributions IOUserClient * IOKitDiagnosticsClient::withTask(task_t owningTask) 15020f3703acSApple OSS Distributions { 15030f3703acSApple OSS Distributions IOKitDiagnosticsClient * inst; 15040f3703acSApple OSS Distributions 15050f3703acSApple OSS Distributions inst = new IOKitDiagnosticsClient; 1506a5e72196SApple OSS Distributions if (inst && !inst->init()) { 15070f3703acSApple OSS Distributions inst->release(); 1508a5e72196SApple OSS Distributions inst = NULL; 15090f3703acSApple OSS Distributions } 15100f3703acSApple OSS Distributions 1511a5e72196SApple OSS Distributions return inst; 15120f3703acSApple OSS Distributions } 15130f3703acSApple OSS Distributions 1514a5e72196SApple OSS Distributions IOReturn 1515a5e72196SApple OSS Distributions IOKitDiagnosticsClient::clientClose(void) 15160f3703acSApple OSS Distributions { 15170f3703acSApple OSS Distributions terminate(); 1518a5e72196SApple OSS Distributions return kIOReturnSuccess; 15190f3703acSApple OSS Distributions } 15200f3703acSApple OSS Distributions 1521a5e72196SApple OSS Distributions IOReturn 1522a5e72196SApple OSS Distributions IOKitDiagnosticsClient::setProperties(OSObject * properties) 15230f3703acSApple OSS Distributions { 15240f3703acSApple OSS Distributions IOReturn kr = kIOReturnUnsupported; 1525a5e72196SApple OSS Distributions return kr; 15260f3703acSApple OSS Distributions } 15270f3703acSApple OSS Distributions 1528a5e72196SApple OSS Distributions IOReturn 1529a5e72196SApple OSS Distributions IOKitDiagnosticsClient::externalMethod(uint32_t selector, IOExternalMethodArguments * args, 15300f3703acSApple OSS Distributions IOExternalMethodDispatch * dispatch, OSObject * target, void * reference) 15310f3703acSApple OSS Distributions { 15320f3703acSApple OSS Distributions IOReturn ret = kIOReturnBadArgument; 15330f3703acSApple OSS Distributions const IOKitDiagnosticsParameters * params; 15340f3703acSApple OSS Distributions const char * names; 15350f3703acSApple OSS Distributions size_t namesLen; 15360f3703acSApple OSS Distributions OSObject * result; 15370f3703acSApple OSS Distributions 1538a5e72196SApple OSS Distributions if (args->structureInputSize < sizeof(IOKitDiagnosticsParameters)) { 1539a5e72196SApple OSS Distributions return kIOReturnBadArgument; 1540a5e72196SApple OSS Distributions } 15410f3703acSApple OSS Distributions params = (typeof(params))args->structureInput; 1542a5e72196SApple OSS Distributions if (!params) { 1543a5e72196SApple OSS Distributions return kIOReturnBadArgument; 1544a5e72196SApple OSS Distributions } 15450f3703acSApple OSS Distributions 1546a5e72196SApple OSS Distributions names = NULL; 15470f3703acSApple OSS Distributions namesLen = args->structureInputSize - sizeof(IOKitDiagnosticsParameters); 1548a5e72196SApple OSS Distributions if (namesLen) { 1549a5e72196SApple OSS Distributions names = (typeof(names))(params + 1); 1550a5e72196SApple OSS Distributions } 15510f3703acSApple OSS Distributions 155276e12aa3SApple OSS Distributions ret = IOTrackingDebug(selector, params->options, params->value, params->tag, params->zsize, names, namesLen, params->size, &result); 15530f3703acSApple OSS Distributions 1554a5e72196SApple OSS Distributions if ((kIOReturnSuccess == ret) && args->structureVariableOutputData) { 1555a5e72196SApple OSS Distributions *args->structureVariableOutputData = result; 1556a5e72196SApple OSS Distributions } else if (result) { 1557a5e72196SApple OSS Distributions result->release(); 1558a5e72196SApple OSS Distributions } 15590f3703acSApple OSS Distributions 1560a5e72196SApple OSS Distributions return ret; 15610f3703acSApple OSS Distributions } 15620f3703acSApple OSS Distributions 15630f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 1564