xref: /xnu-8792.61.2/tools/lldbmacros/core/caching.py (revision 42e220869062b56f8d7d0726fd4c88954f87902c)
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
46from __future__ import absolute_import
47from .configuration import config
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 ClearAllCache():
86    """ remove all cached data.
87    """
88    global _static_data, _dynamic_data
89    _static_data = {}
90    _dynamic_data = {}
91
92def GetSizeOfCache():
93    """ Returns number of bytes held in cache.
94        returns:
95            int - size of cache including static and dynamic
96    """
97    global _static_data, _dynamic_data
98    return sys.getsizeof(_static_data) + sys.getsizeof(_dynamic_data)
99
100
101def GetStaticCacheData(key, default_value = None):
102    """ Get cached object based on key from the cache of static information.
103        params:
104            key: str - a unique string identifying your data.
105            default_value : obj - an object that should be returned if key is not found.
106        returns:
107            default_value - if the static cache does not have your data.
108            obj  - The data obj saved with SaveStaticCacheData()
109    """
110    global _static_data
111    key = str(key)
112    if key in _static_data:
113        return _static_data[key][0]
114    return default_value
115
116def SaveStaticCacheData(key, value):
117    """ Save data into the cache identified by key.
118        It will overwrite any data that was previously associated with key
119        params:
120            key  : str - a unique string identifying your data
121            value: obj - any object that is to be cached.
122        returns:
123            Nothing
124    """
125    global _static_data
126
127    if not config['CacheStaticData']:
128        return
129
130    key = str(key)
131    _static_data[key] = (value, _GetCurrentSessionID())
132    return
133
134
135def GetDynamicCacheData(key, default_value=None):
136    """ Get cached object based on key from the cache of dynamic information.
137        params:
138            key: str - a unique string identifying cached object
139            default_value : obj - an object that should be returned if key is not found.
140        returns:
141            default_value - if dynamic cache does not have data or if the saved version mismatches with current session id.
142            obj  - The data obj saved with SaveDynamicCacheData()
143    """
144    global _dynamic_data
145    key = str(key)
146    if key in _dynamic_data:
147        if _GetCurrentSessionID() == _dynamic_data[key][1]:
148            return _dynamic_data[key][0]
149        else:
150            del _dynamic_data[key]
151
152    return default_value
153
154
155def SaveDynamicCacheData(key, value):
156    """ Save data into the cache identified by key.
157        It will overwrite any data that was previously associated with key
158        params:
159            key  : str - a unique string identifying your data
160            value: obj - any object that is to be cached.
161        returns:
162            Nothing
163    """
164    global _dynamic_data
165
166    if not config['CacheDynamicData']:
167        return
168
169    key = str(key)
170    _dynamic_data[key] = (value, _GetCurrentSessionID())
171
172    return
173