1""" 2A basic caching module for xnu debug macros to use. 3It is recommended to use [Get|Save][Static|Dynamic]CacheData() apis for 4your caching needs. These APIs will handle the case of clearing caches when 5a debugger continues and stops or hit a breakpoint. 6 7Use Static caches for data that will not change if the program is run and stopped again. e.g. typedata, version numbers etc. 8An example invocation could be like 9def getDSYMPathForUUID(uuid): 10 # Get the data from cache 11 cached_data = caching.GetStaticCacheData('dsym.for.uuid', {}) 12 13 if uuid in cached_data: 14 return cached_data[uuid] 15 else: 16 path = #get info for uuid 17 cached_data[uuid] = path 18 19 # save the cached_data object to cache. 20 caching.SaveStaticCacheData('dsym.for.uuid', cached_data) 21 22 return cached_data[uuid] 23 24And use Dynamic caches for things like thread data, zones information etc. 25These will automatically be dropped when debugger continues the target 26An example use of Dynamic cache could be as follows 27 28def GetExecutablePathForPid(pid): 29 # Get the data from cache 30 cached_data = caching.GetDynamicCacheData('exec_for_path', {}) 31 32 if pid in cached_data: 33 return cached_data[pid] 34 else: 35 exec_path = "/path/to/exec" #get exec path for pid 36 cached_data[pid] = path 37 38 # save the cached_data object to cache. 39 caching.SaveDynamicCacheData('exec_for_path', cached_data) 40 41 return cached_data[pid] 42 43""" 44 45#Private Routines and objects 46 47from configuration import * 48 49import sys 50 51""" 52The format for the saved data dictionaries is 53{ 54 'key' : (valueobj, versno), 55 ... 56} 57 58The versno is an int defining the version of obj. In case of version mismatch it will set valueobj to default upon access. 59 60""" 61_static_data = {} 62_dynamic_data = {} 63 64 65 66def _GetDebuggerSessionID(): 67 """ A default callable function that _GetCurrentSessionID uses to 68 identify a stopped session. 69 """ 70 return 0 71 72def _GetCurrentSessionID(): 73 """ Get the current session id. This will update whenever 74 system is continued or if there is new information that would 75 cause the dynamic cache to be deleted. 76 77 returns: int - session id number. 78 """ 79 session_id = _GetDebuggerSessionID() 80 return session_id; 81 82 83#Public APIs 84 85def GetSizeOfCache(): 86 """ Returns number of bytes held in cache. 87 returns: 88 int - size of cache including static and dynamic 89 """ 90 global _static_data, _dynamic_data 91 return sys.getsizeof(_static_data) + sys.getsizeof(_dynamic_data) 92 93 94def GetStaticCacheData(key, default_value = None): 95 """ Get cached object based on key from the cache of static information. 96 params: 97 key: str - a unique string identifying your data. 98 default_value : obj - an object that should be returned if key is not found. 99 returns: 100 default_value - if the static cache does not have your data. 101 obj - The data obj saved with SaveStaticCacheData() 102 """ 103 global _static_data 104 key = str(key) 105 if key in _static_data: 106 return _static_data[key][0] 107 return default_value 108 109def SaveStaticCacheData(key, value): 110 """ Save data into the cache identified by key. 111 It will overwrite any data that was previously associated with key 112 params: 113 key : str - a unique string identifying your data 114 value: obj - any object that is to be cached. 115 returns: 116 Nothing 117 """ 118 global _static_data 119 120 if not config['CacheStaticData']: 121 return 122 123 key = str(key) 124 _static_data[key] = (value, _GetCurrentSessionID()) 125 return 126 127 128def GetDynamicCacheData(key, default_value=None): 129 """ Get cached object based on key from the cache of dynamic information. 130 params: 131 key: str - a unique string identifying cached object 132 default_value : obj - an object that should be returned if key is not found. 133 returns: 134 default_value - if dynamic cache does not have data or if the saved version mismatches with current session id. 135 obj - The data obj saved with SaveDynamicCacheData() 136 """ 137 global _dynamic_data 138 key = str(key) 139 if key in _dynamic_data: 140 if _GetCurrentSessionID() == _dynamic_data[key][1]: 141 return _dynamic_data[key][0] 142 else: 143 del _dynamic_data[key] 144 145 return default_value 146 147 148def SaveDynamicCacheData(key, value): 149 """ Save data into the cache identified by key. 150 It will overwrite any data that was previously associated with key 151 params: 152 key : str - a unique string identifying your data 153 value: obj - any object that is to be cached. 154 returns: 155 Nothing 156 """ 157 global _dynamic_data 158 159 if not config['CacheDynamicData']: 160 return 161 162 key = str(key) 163 _dynamic_data[key] = (value, _GetCurrentSessionID()) 164 165 return 166