lldbutil.py revision bdc36bd05d156143d9f2e568a1aa1b5253bbe1f1
11605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen"""
2b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny ChenThis LLDB module contains miscellaneous utilities.
31605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen"""
41605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen
51605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chenimport lldb
60bfa859ea49d27efd89d5f152b8371b39919d92dJohnny Chenimport os, sys
7ed5f04ef51b18d6bedbc8589fa06544491977b9cJohnny Chenimport StringIO
81605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen
90bfa859ea49d27efd89d5f152b8371b39919d92dJohnny Chendef is_exe(fpath):
100bfa859ea49d27efd89d5f152b8371b39919d92dJohnny Chen    return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
110bfa859ea49d27efd89d5f152b8371b39919d92dJohnny Chen
120bfa859ea49d27efd89d5f152b8371b39919d92dJohnny Chendef which(program):
130b4dfac85ae7fc774fb7dc8b820daa0a89ad8281Johnny Chen    """Find the full path to a program, or return None."""
140bfa859ea49d27efd89d5f152b8371b39919d92dJohnny Chen    fpath, fname = os.path.split(program)
150bfa859ea49d27efd89d5f152b8371b39919d92dJohnny Chen    if fpath:
160bfa859ea49d27efd89d5f152b8371b39919d92dJohnny Chen        if is_exe(program):
170bfa859ea49d27efd89d5f152b8371b39919d92dJohnny Chen            return program
180bfa859ea49d27efd89d5f152b8371b39919d92dJohnny Chen    else:
190bfa859ea49d27efd89d5f152b8371b39919d92dJohnny Chen        for path in os.environ["PATH"].split(os.pathsep):
200bfa859ea49d27efd89d5f152b8371b39919d92dJohnny Chen            exe_file = os.path.join(path, program)
210bfa859ea49d27efd89d5f152b8371b39919d92dJohnny Chen            if is_exe(exe_file):
220bfa859ea49d27efd89d5f152b8371b39919d92dJohnny Chen                return exe_file
230bfa859ea49d27efd89d5f152b8371b39919d92dJohnny Chen    return None
240bfa859ea49d27efd89d5f152b8371b39919d92dJohnny Chen
2577356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen# ===========================================
2677356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen# Iterator for lldb aggregate data structures
2777356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen# ===========================================
2877356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen
2977356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chendef lldb_iter(obj, getsize, getelem):
3077356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen    """A generator adaptor for lldb aggregate data structures.
3177356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen
3277356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen    API clients pass in an aggregate object or a container of it, the name of
3377356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen    the method to get the size of the aggregate, and the name of the method to
3477356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen    get the element by index.
3577356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen
3677356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen    Example usages:
3777356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen
3877356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen    1. Pass an aggregate as the first argument:
3977356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen
4077356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen    def disassemble_instructions (insts):
4177356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen        from lldbutil import lldb_iter
4277356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen        for i in lldb_iter(insts, 'GetSize', 'GetInstructionAtIndex'):
4377356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen            print i
4477356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen
4577356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen    2. Pass a container of aggregate which provides APIs to get to the size and
4677356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen       the element of the aggregate:
4777356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen
4877356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen    # Module is a container of symbol table
4977356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen    module = target.FindModule(filespec)
5077356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen    for symbol in lldb_iter(module, 'GetNumSymbols', 'GetSymbolAtIndex'):
5177356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen        name = symbol.GetName()
5277356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen        ...
5377356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen    """
5477356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen    size = getattr(obj, getsize)
5577356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen    elem = getattr(obj, getelem)
5677356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen    for i in range(size()):
5777356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen        yield elem(i)
5877356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen
5977356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen
6051ed1b614f2c2b6970f50296d7d41c9de2c30ff4Johnny Chen# ===================================================
6151ed1b614f2c2b6970f50296d7d41c9de2c30ff4Johnny Chen# Disassembly for an SBFunction or an SBSymbol object
6251ed1b614f2c2b6970f50296d7d41c9de2c30ff4Johnny Chen# ===================================================
6351ed1b614f2c2b6970f50296d7d41c9de2c30ff4Johnny Chen
6451ed1b614f2c2b6970f50296d7d41c9de2c30ff4Johnny Chendef disassemble(target, function_or_symbol):
6551ed1b614f2c2b6970f50296d7d41c9de2c30ff4Johnny Chen    """Disassemble the function or symbol given a target.
6651ed1b614f2c2b6970f50296d7d41c9de2c30ff4Johnny Chen
6751ed1b614f2c2b6970f50296d7d41c9de2c30ff4Johnny Chen    It returns the disassembly content in a string object.
6851ed1b614f2c2b6970f50296d7d41c9de2c30ff4Johnny Chen    """
6951ed1b614f2c2b6970f50296d7d41c9de2c30ff4Johnny Chen    buf = StringIO.StringIO()
7051ed1b614f2c2b6970f50296d7d41c9de2c30ff4Johnny Chen    insts = function_or_symbol.GetInstructions(target)
7151ed1b614f2c2b6970f50296d7d41c9de2c30ff4Johnny Chen    for i in lldb_iter(insts, 'GetSize', 'GetInstructionAtIndex'):
7251ed1b614f2c2b6970f50296d7d41c9de2c30ff4Johnny Chen        print >> buf, i
7351ed1b614f2c2b6970f50296d7d41c9de2c30ff4Johnny Chen    return buf.getvalue()
7451ed1b614f2c2b6970f50296d7d41c9de2c30ff4Johnny Chen
7551ed1b614f2c2b6970f50296d7d41c9de2c30ff4Johnny Chen
764c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen# ==========================================================
774c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen# Integer (byte size 1, 2, 4, and 8) to bytearray conversion
784c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen# ==========================================================
794c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen
804c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chendef int_to_bytearray(val, bytesize):
814c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen    """Utility function to convert an integer into a bytearray.
824c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen
83d2765fc8b9c9bd4d98dd5d6176b6108b6516e04cJohnny Chen    It returns the bytearray in the little endian format.  It is easy to get the
84d2765fc8b9c9bd4d98dd5d6176b6108b6516e04cJohnny Chen    big endian format, just do ba.reverse() on the returned object.
854c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen    """
86f4c0d1d8854f3ed87ca797628008386fdb9318afJohnny Chen    import struct
874c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen
884c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen    if bytesize == 1:
894c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen        return bytearray([val])
904c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen
914c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen    # Little endian followed by a format character.
924c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen    template = "<%c"
934c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen    if bytesize == 2:
944c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen        fmt = template % 'h'
954c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen    elif bytesize == 4:
964c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen        fmt = template % 'i'
974c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen    elif bytesize == 4:
984c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen        fmt = template % 'q'
994c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen    else:
1004c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen        return None
1014c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen
102f4c0d1d8854f3ed87ca797628008386fdb9318afJohnny Chen    packed = struct.pack(fmt, val)
1034c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen    return bytearray(map(ord, packed))
1044c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen
1054c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chendef bytearray_to_int(bytes, bytesize):
1064c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen    """Utility function to convert a bytearray into an integer.
1074c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen
108d2765fc8b9c9bd4d98dd5d6176b6108b6516e04cJohnny Chen    It interprets the bytearray in the little endian format. For a big endian
109d2765fc8b9c9bd4d98dd5d6176b6108b6516e04cJohnny Chen    bytearray, just do ba.reverse() on the object before passing it in.
1104c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen    """
111f4c0d1d8854f3ed87ca797628008386fdb9318afJohnny Chen    import struct
1124c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen
1134c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen    if bytesize == 1:
1144c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen        return ba[0]
1154c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen
1164c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen    # Little endian followed by a format character.
1174c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen    template = "<%c"
1184c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen    if bytesize == 2:
1194c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen        fmt = template % 'h'
1204c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen    elif bytesize == 4:
1214c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen        fmt = template % 'i'
1224c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen    elif bytesize == 4:
1234c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen        fmt = template % 'q'
1244c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen    else:
1254c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen        return None
1264c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen
127f4c0d1d8854f3ed87ca797628008386fdb9318afJohnny Chen    unpacked = struct.unpack(fmt, str(bytes))
1284c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen    return unpacked[0]
1294c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen
1304c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen
13177356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen# ===========================================================
13277356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen# Returns the list of stopped thread(s) given an lldb process
13377356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen# ===========================================================
13484a6d6f10f3010accf9b717b2995f9acb6bee60cJohnny Chen
13577356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chendef get_stopped_threads(process, reason):
13677356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen    """Returns the thread(s) with the specified stop reason in a list."""
13777356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen    threads = []
13877356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen    for t in lldb_iter(process, 'GetNumThreads', 'GetThreadAtIndex'):
13977356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen        if t.GetStopReason() == reason:
14077356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen            threads.append(t)
14177356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen    return threads
142deaf884abce0117add8ed0e83491c10eeb8bf220Johnny Chen
14377356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chendef get_stopped_thread(process, reason):
14477356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen    """A convenience function which returns the first thread with the given stop
14577356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen    reason or None.
146164bf887534ab18c939dc46525efb3db9de2613dJohnny Chen
147deaf884abce0117add8ed0e83491c10eeb8bf220Johnny Chen    Example usages:
148164bf887534ab18c939dc46525efb3db9de2613dJohnny Chen
14977356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen    1. Get the stopped thread due to a breakpoint condition
150164bf887534ab18c939dc46525efb3db9de2613dJohnny Chen
15177356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen    ...
15277356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen        from lldbutil import get_stopped_thread
15377356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen        thread = get_stopped_thread(self.process, lldb.eStopReasonPlanComplete)
15477356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen        self.assertTrue(thread != None, "There should be a thread stopped due to breakpoint condition")
15577356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen    ...
156deaf884abce0117add8ed0e83491c10eeb8bf220Johnny Chen
15777356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen    2. Get the thread stopped due to a breakpoint
158deaf884abce0117add8ed0e83491c10eeb8bf220Johnny Chen
15977356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen    ...
16077356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen        from lldbutil import get_stopped_thread
16177356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen        thread = get_stopped_thread(self.process, lldb.eStopReasonBreakpoint)
16277356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen        self.assertTrue(thread != None, "There should be a thread stopped due to breakpoint")
16377356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen    ...
164164bf887534ab18c939dc46525efb3db9de2613dJohnny Chen
16577356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen    """
16677356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen    threads = get_stopped_threads(process, reason)
16777356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen    if len(threads) == 0:
16877356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen        return None
16977356a0e9bec77c6ed7eb23151bcd8de27fef902Johnny Chen    return threads[0]
170164bf887534ab18c939dc46525efb3db9de2613dJohnny Chen
171bc1a93e702cae42f87a8cbc58035877cb19e0840Johnny Chen# ==============================================================
172bc1a93e702cae42f87a8cbc58035877cb19e0840Johnny Chen# Get the description of an lldb object or None if not available
173bc1a93e702cae42f87a8cbc58035877cb19e0840Johnny Chen# ==============================================================
174bdc36bd05d156143d9f2e568a1aa1b5253bbe1f1Johnny Chendef get_description(obj, option=None):
175bdc36bd05d156143d9f2e568a1aa1b5253bbe1f1Johnny Chen    """Calls lldb_obj.GetDescription() and returns a string, or None.
176bdc36bd05d156143d9f2e568a1aa1b5253bbe1f1Johnny Chen
177bdc36bd05d156143d9f2e568a1aa1b5253bbe1f1Johnny Chen    For SBTarget and SBBreakpointLocation lldb objects, an extra option can be
178bdc36bd05d156143d9f2e568a1aa1b5253bbe1f1Johnny Chen    passed in to describe the detailed level of description desired:
179bdc36bd05d156143d9f2e568a1aa1b5253bbe1f1Johnny Chen        o lldb.eDescriptionLevelBrief
180bdc36bd05d156143d9f2e568a1aa1b5253bbe1f1Johnny Chen        o lldb.eDescriptionLevelFull
181bdc36bd05d156143d9f2e568a1aa1b5253bbe1f1Johnny Chen        o lldb.eDescriptionLevelVerbose
182bdc36bd05d156143d9f2e568a1aa1b5253bbe1f1Johnny Chen    """
183bdc36bd05d156143d9f2e568a1aa1b5253bbe1f1Johnny Chen    method = getattr(obj, 'GetDescription')
184bc1a93e702cae42f87a8cbc58035877cb19e0840Johnny Chen    if not method:
185bc1a93e702cae42f87a8cbc58035877cb19e0840Johnny Chen        return None
186bdc36bd05d156143d9f2e568a1aa1b5253bbe1f1Johnny Chen    if isinstance(obj, lldb.SBTarget) or isinstance(obj, lldb.SBBreakpointLocation):
187bdc36bd05d156143d9f2e568a1aa1b5253bbe1f1Johnny Chen        if option is None:
188bdc36bd05d156143d9f2e568a1aa1b5253bbe1f1Johnny Chen            option = lldb.eDescriptionLevelBrief
189bdc36bd05d156143d9f2e568a1aa1b5253bbe1f1Johnny Chen
190bc1a93e702cae42f87a8cbc58035877cb19e0840Johnny Chen    stream = lldb.SBStream()
191bc1a93e702cae42f87a8cbc58035877cb19e0840Johnny Chen    if option is None:
192bc1a93e702cae42f87a8cbc58035877cb19e0840Johnny Chen        success = method(stream)
193bc1a93e702cae42f87a8cbc58035877cb19e0840Johnny Chen    else:
194bc1a93e702cae42f87a8cbc58035877cb19e0840Johnny Chen        success = method(stream, option)
195bc1a93e702cae42f87a8cbc58035877cb19e0840Johnny Chen    if not success:
196bc1a93e702cae42f87a8cbc58035877cb19e0840Johnny Chen        return None
197bc1a93e702cae42f87a8cbc58035877cb19e0840Johnny Chen    return stream.GetData()
198bc1a93e702cae42f87a8cbc58035877cb19e0840Johnny Chen
199bc1a93e702cae42f87a8cbc58035877cb19e0840Johnny Chen
200168a61a9d1551d407240395942dc9e005c47ba30Johnny Chen# =================================================
201168a61a9d1551d407240395942dc9e005c47ba30Johnny Chen# Convert some enum value to its string counterpart
202168a61a9d1551d407240395942dc9e005c47ba30Johnny Chen# =================================================
203be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen
204be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chendef StateTypeString(enum):
205be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    """Returns the stateType string given an enum."""
206be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    if enum == lldb.eStateInvalid:
20759b8477b020651df9b215396864e2e161a007d8cJohnny Chen        return "invalid"
208be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    elif enum == lldb.eStateUnloaded:
20959b8477b020651df9b215396864e2e161a007d8cJohnny Chen        return "unloaded"
21042da4dae5d7dccf98a57399d4689150b928ab545Johnny Chen    elif enum == lldb.eStateConnected:
21142da4dae5d7dccf98a57399d4689150b928ab545Johnny Chen        return "connected"
212be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    elif enum == lldb.eStateAttaching:
21359b8477b020651df9b215396864e2e161a007d8cJohnny Chen        return "attaching"
214be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    elif enum == lldb.eStateLaunching:
21559b8477b020651df9b215396864e2e161a007d8cJohnny Chen        return "launching"
216be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    elif enum == lldb.eStateStopped:
21759b8477b020651df9b215396864e2e161a007d8cJohnny Chen        return "stopped"
218be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    elif enum == lldb.eStateRunning:
21959b8477b020651df9b215396864e2e161a007d8cJohnny Chen        return "running"
220be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    elif enum == lldb.eStateStepping:
22159b8477b020651df9b215396864e2e161a007d8cJohnny Chen        return "stepping"
222be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    elif enum == lldb.eStateCrashed:
22359b8477b020651df9b215396864e2e161a007d8cJohnny Chen        return "crashed"
224be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    elif enum == lldb.eStateDetached:
22559b8477b020651df9b215396864e2e161a007d8cJohnny Chen        return "detached"
226be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    elif enum == lldb.eStateExited:
22759b8477b020651df9b215396864e2e161a007d8cJohnny Chen        return "exited"
228be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    elif enum == lldb.eStateSuspended:
22959b8477b020651df9b215396864e2e161a007d8cJohnny Chen        return "suspended"
230be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    else:
23142da4dae5d7dccf98a57399d4689150b928ab545Johnny Chen        raise Exception("Unknown StateType enum")
232be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen
233be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chendef StopReasonString(enum):
234be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    """Returns the stopReason string given an enum."""
235be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    if enum == lldb.eStopReasonInvalid:
23659b8477b020651df9b215396864e2e161a007d8cJohnny Chen        return "invalid"
237be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    elif enum == lldb.eStopReasonNone:
23859b8477b020651df9b215396864e2e161a007d8cJohnny Chen        return "none"
239be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    elif enum == lldb.eStopReasonTrace:
24059b8477b020651df9b215396864e2e161a007d8cJohnny Chen        return "trace"
241be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    elif enum == lldb.eStopReasonBreakpoint:
24259b8477b020651df9b215396864e2e161a007d8cJohnny Chen        return "breakpoint"
243be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    elif enum == lldb.eStopReasonWatchpoint:
24459b8477b020651df9b215396864e2e161a007d8cJohnny Chen        return "watchpoint"
245be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    elif enum == lldb.eStopReasonSignal:
24659b8477b020651df9b215396864e2e161a007d8cJohnny Chen        return "signal"
247be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    elif enum == lldb.eStopReasonException:
24859b8477b020651df9b215396864e2e161a007d8cJohnny Chen        return "exception"
249be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    elif enum == lldb.eStopReasonPlanComplete:
25059b8477b020651df9b215396864e2e161a007d8cJohnny Chen        return "plancomplete"
251be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    else:
25242da4dae5d7dccf98a57399d4689150b928ab545Johnny Chen        raise Exception("Unknown StopReason enum")
253be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen
2542c8d1596ec40c321d6d39c2b32c33fd662b66c11Johnny Chendef ValueTypeString(enum):
2552c8d1596ec40c321d6d39c2b32c33fd662b66c11Johnny Chen    """Returns the valueType string given an enum."""
2562c8d1596ec40c321d6d39c2b32c33fd662b66c11Johnny Chen    if enum == lldb.eValueTypeInvalid:
2572c8d1596ec40c321d6d39c2b32c33fd662b66c11Johnny Chen        return "invalid"
2582c8d1596ec40c321d6d39c2b32c33fd662b66c11Johnny Chen    elif enum == lldb.eValueTypeVariableGlobal:
2592c8d1596ec40c321d6d39c2b32c33fd662b66c11Johnny Chen        return "global_variable"
2602c8d1596ec40c321d6d39c2b32c33fd662b66c11Johnny Chen    elif enum == lldb.eValueTypeVariableStatic:
2612c8d1596ec40c321d6d39c2b32c33fd662b66c11Johnny Chen        return "static_variable"
2622c8d1596ec40c321d6d39c2b32c33fd662b66c11Johnny Chen    elif enum == lldb.eValueTypeVariableArgument:
2632c8d1596ec40c321d6d39c2b32c33fd662b66c11Johnny Chen        return "argument_variable"
2642c8d1596ec40c321d6d39c2b32c33fd662b66c11Johnny Chen    elif enum == lldb.eValueTypeVariableLocal:
2652c8d1596ec40c321d6d39c2b32c33fd662b66c11Johnny Chen        return "local_variable"
2662c8d1596ec40c321d6d39c2b32c33fd662b66c11Johnny Chen    elif enum == lldb.eValueTypeRegister:
2672c8d1596ec40c321d6d39c2b32c33fd662b66c11Johnny Chen        return "register"
2682c8d1596ec40c321d6d39c2b32c33fd662b66c11Johnny Chen    elif enum == lldb.eValueTypeRegisterSet:
2692c8d1596ec40c321d6d39c2b32c33fd662b66c11Johnny Chen        return "register_set"
2702c8d1596ec40c321d6d39c2b32c33fd662b66c11Johnny Chen    elif enum == lldb.eValueTypeConstResult:
2712c8d1596ec40c321d6d39c2b32c33fd662b66c11Johnny Chen        return "constant_result"
2722c8d1596ec40c321d6d39c2b32c33fd662b66c11Johnny Chen    else:
27342da4dae5d7dccf98a57399d4689150b928ab545Johnny Chen        raise Exception("Unknown ValueType enum")
2742c8d1596ec40c321d6d39c2b32c33fd662b66c11Johnny Chen
275be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen
276168a61a9d1551d407240395942dc9e005c47ba30Johnny Chen# ==================================================
277168a61a9d1551d407240395942dc9e005c47ba30Johnny Chen# Utility functions related to Threads and Processes
278168a61a9d1551d407240395942dc9e005c47ba30Johnny Chen# ==================================================
279be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen
28069af39d7e7c1988caf027956a6af5f17c55b5534Johnny Chendef get_caller_symbol(thread):
28169af39d7e7c1988caf027956a6af5f17c55b5534Johnny Chen    """
28269af39d7e7c1988caf027956a6af5f17c55b5534Johnny Chen    Returns the symbol name for the call site of the leaf function.
28369af39d7e7c1988caf027956a6af5f17c55b5534Johnny Chen    """
28469af39d7e7c1988caf027956a6af5f17c55b5534Johnny Chen    depth = thread.GetNumFrames()
28569af39d7e7c1988caf027956a6af5f17c55b5534Johnny Chen    if depth <= 1:
28669af39d7e7c1988caf027956a6af5f17c55b5534Johnny Chen        return None
28769af39d7e7c1988caf027956a6af5f17c55b5534Johnny Chen    caller = thread.GetFrameAtIndex(1).GetSymbol()
28869af39d7e7c1988caf027956a6af5f17c55b5534Johnny Chen    if caller:
28969af39d7e7c1988caf027956a6af5f17c55b5534Johnny Chen        return caller.GetName()
29069af39d7e7c1988caf027956a6af5f17c55b5534Johnny Chen    else:
29169af39d7e7c1988caf027956a6af5f17c55b5534Johnny Chen        return None
29269af39d7e7c1988caf027956a6af5f17c55b5534Johnny Chen
29369af39d7e7c1988caf027956a6af5f17c55b5534Johnny Chen
2941605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chendef GetFunctionNames(thread):
2951605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    """
2961605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    Returns a sequence of function names from the stack frames of this thread.
2971605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    """
2981605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    def GetFuncName(i):
2991605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen        return thread.GetFrameAtIndex(i).GetFunction().GetName()
3001605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen
3011605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    return map(GetFuncName, range(thread.GetNumFrames()))
3021605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen
3031605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen
304b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chendef GetSymbolNames(thread):
305b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen    """
306b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen    Returns a sequence of symbols for this thread.
307b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen    """
308b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen    def GetSymbol(i):
309b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen        return thread.GetFrameAtIndex(i).GetSymbol().GetName()
310b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen
311b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen    return map(GetSymbol, range(thread.GetNumFrames()))
312b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen
313b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen
314b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chendef GetPCAddresses(thread):
315b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen    """
316b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen    Returns a sequence of pc addresses for this thread.
317b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen    """
318b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen    def GetPCAddress(i):
319b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen        return thread.GetFrameAtIndex(i).GetPCAddress()
320b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen
321b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen    return map(GetPCAddress, range(thread.GetNumFrames()))
322b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen
323b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen
3241605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chendef GetFilenames(thread):
3251605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    """
3261605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    Returns a sequence of file names from the stack frames of this thread.
3271605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    """
3281605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    def GetFilename(i):
3291605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen        return thread.GetFrameAtIndex(i).GetLineEntry().GetFileSpec().GetFilename()
3301605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen
3311605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    return map(GetFilename, range(thread.GetNumFrames()))
3321605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen
3331605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen
3341605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chendef GetLineNumbers(thread):
3351605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    """
3361605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    Returns a sequence of line numbers from the stack frames of this thread.
3371605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    """
3381605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    def GetLineNumber(i):
3391605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen        return thread.GetFrameAtIndex(i).GetLineEntry().GetLine()
3401605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen
3411605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    return map(GetLineNumber, range(thread.GetNumFrames()))
3421605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen
3431605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen
3441605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chendef GetModuleNames(thread):
3451605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    """
3461605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    Returns a sequence of module names from the stack frames of this thread.
3471605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    """
3481605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    def GetModuleName(i):
3491605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen        return thread.GetFrameAtIndex(i).GetModule().GetFileSpec().GetFilename()
3501605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen
3511605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    return map(GetModuleName, range(thread.GetNumFrames()))
3521605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen
3531605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen
35488866ac481cd5533c18e00233aeced2eb1fce42bJohnny Chendef GetStackFrames(thread):
35588866ac481cd5533c18e00233aeced2eb1fce42bJohnny Chen    """
35688866ac481cd5533c18e00233aeced2eb1fce42bJohnny Chen    Returns a sequence of stack frames for this thread.
35788866ac481cd5533c18e00233aeced2eb1fce42bJohnny Chen    """
35888866ac481cd5533c18e00233aeced2eb1fce42bJohnny Chen    def GetStackFrame(i):
35988866ac481cd5533c18e00233aeced2eb1fce42bJohnny Chen        return thread.GetFrameAtIndex(i)
36088866ac481cd5533c18e00233aeced2eb1fce42bJohnny Chen
36188866ac481cd5533c18e00233aeced2eb1fce42bJohnny Chen    return map(GetStackFrame, range(thread.GetNumFrames()))
36288866ac481cd5533c18e00233aeced2eb1fce42bJohnny Chen
36388866ac481cd5533c18e00233aeced2eb1fce42bJohnny Chen
36430425e9677342cff9995cd4937fdc12354b6b24bJohnny Chendef PrintStackTrace(thread, string_buffer = False):
3651605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    """Prints a simple stack trace of this thread."""
36630425e9677342cff9995cd4937fdc12354b6b24bJohnny Chen
367ed5f04ef51b18d6bedbc8589fa06544491977b9cJohnny Chen    output = StringIO.StringIO() if string_buffer else sys.stdout
368b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen    target = thread.GetProcess().GetTarget()
369b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen
3701605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    depth = thread.GetNumFrames()
3711605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen
3721605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    mods = GetModuleNames(thread)
3731605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    funcs = GetFunctionNames(thread)
374b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen    symbols = GetSymbolNames(thread)
3751605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    files = GetFilenames(thread)
3761605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    lines = GetLineNumbers(thread)
377b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen    addrs = GetPCAddresses(thread)
37830425e9677342cff9995cd4937fdc12354b6b24bJohnny Chen
379ad5fd40cb92070593d248b8f44b9902be0bcb4bfJohnny Chen    if thread.GetStopReason() != lldb.eStopReasonInvalid:
380ad5fd40cb92070593d248b8f44b9902be0bcb4bfJohnny Chen        desc =  "stop reason=" + StopReasonString(thread.GetStopReason())
381ad5fd40cb92070593d248b8f44b9902be0bcb4bfJohnny Chen    else:
382ad5fd40cb92070593d248b8f44b9902be0bcb4bfJohnny Chen        desc = ""
383ad5fd40cb92070593d248b8f44b9902be0bcb4bfJohnny Chen    print >> output, "Stack trace for thread id={0:#x} name={1} queue={2} ".format(
384ad5fd40cb92070593d248b8f44b9902be0bcb4bfJohnny Chen        thread.GetThreadID(), thread.GetName(), thread.GetQueueName()) + desc
3851605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen
386b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen    for i in range(depth):
387b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen        frame = thread.GetFrameAtIndex(i)
388b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen        function = frame.GetFunction()
389b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen
390b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen        load_addr = addrs[i].GetLoadAddress(target)
391b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen        if not function.IsValid():
392b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen            file_addr = addrs[i].GetFileAddress()
393b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen            print >> output, "  frame #{num}: {addr:#016x} {mod}`{symbol} + ????".format(
394b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen                num=i, addr=load_addr, mod=mods[i], symbol=symbols[i])
395b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen        else:
396b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen            print >> output, "  frame #{num}: {addr:#016x} {mod}`{func} at {file}:{line}".format(
397b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen                num=i, addr=load_addr, mod=mods[i], func=funcs[i], file=files[i], line=lines[i])
398b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen
399b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen    if string_buffer:
400ed5f04ef51b18d6bedbc8589fa06544491977b9cJohnny Chen        return output.getvalue()
401b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen
402b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen
403b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chendef PrintStackTraces(process, string_buffer = False):
404b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen    """Prints the stack traces of all the threads."""
405b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen
406ed5f04ef51b18d6bedbc8589fa06544491977b9cJohnny Chen    output = StringIO.StringIO() if string_buffer else sys.stdout
407b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen
408b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen    print >> output, "Stack traces for " + repr(process)
4091605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen
410b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen    for i in range(process.GetNumThreads()):
411b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen        print >> output, PrintStackTrace(process.GetThreadAtIndex(i), string_buffer=True)
41230425e9677342cff9995cd4937fdc12354b6b24bJohnny Chen
41330425e9677342cff9995cd4937fdc12354b6b24bJohnny Chen    if string_buffer:
414ed5f04ef51b18d6bedbc8589fa06544491977b9cJohnny Chen        return output.getvalue()
415e41494a9092e15192012a5e0a8a1ffd66c70b8bbJim Ingham
416e41494a9092e15192012a5e0a8a1ffd66c70b8bbJim Inghamdef GetThreadsStoppedAtBreakpoint (process, bkpt):
41737ac00bdbf6c1cfb4a21b50fec8b0e4ba9735cfaJohnny Chen    """ For a stopped process returns the thread stopped at the breakpoint passed in bkpt"""
418e41494a9092e15192012a5e0a8a1ffd66c70b8bbJim Ingham    stopped_threads = []
419e41494a9092e15192012a5e0a8a1ffd66c70b8bbJim Ingham    threads = []
420e41494a9092e15192012a5e0a8a1ffd66c70b8bbJim Ingham
421e41494a9092e15192012a5e0a8a1ffd66c70b8bbJim Ingham    stopped_threads = get_stopped_threads (process, lldb.eStopReasonBreakpoint)
422e41494a9092e15192012a5e0a8a1ffd66c70b8bbJim Ingham
423e41494a9092e15192012a5e0a8a1ffd66c70b8bbJim Ingham    if len(stopped_threads) == 0:
424e41494a9092e15192012a5e0a8a1ffd66c70b8bbJim Ingham        return threads
425e41494a9092e15192012a5e0a8a1ffd66c70b8bbJim Ingham
426e41494a9092e15192012a5e0a8a1ffd66c70b8bbJim Ingham    for thread in stopped_threads:
427e41494a9092e15192012a5e0a8a1ffd66c70b8bbJim Ingham    # Make sure we've hit our breakpoint...
428e41494a9092e15192012a5e0a8a1ffd66c70b8bbJim Ingham        break_id = thread.GetStopReasonDataAtIndex (0)
429e41494a9092e15192012a5e0a8a1ffd66c70b8bbJim Ingham        if break_id == bkpt.GetID():
430e41494a9092e15192012a5e0a8a1ffd66c70b8bbJim Ingham            threads.append(thread)
431e41494a9092e15192012a5e0a8a1ffd66c70b8bbJim Ingham
432e41494a9092e15192012a5e0a8a1ffd66c70b8bbJim Ingham    return threads
433e41494a9092e15192012a5e0a8a1ffd66c70b8bbJim Ingham
434e41494a9092e15192012a5e0a8a1ffd66c70b8bbJim Inghamdef ContinueToBreakpoint (process, bkpt):
43537ac00bdbf6c1cfb4a21b50fec8b0e4ba9735cfaJohnny Chen    """ Continues the process, if it stops, returns the threads stopped at bkpt; otherwise, returns None"""
436e41494a9092e15192012a5e0a8a1ffd66c70b8bbJim Ingham    process.Continue()
437e41494a9092e15192012a5e0a8a1ffd66c70b8bbJim Ingham    if process.GetState() != lldb.eStateStopped:
438e41494a9092e15192012a5e0a8a1ffd66c70b8bbJim Ingham        return None
439e41494a9092e15192012a5e0a8a1ffd66c70b8bbJim Ingham    else:
440e41494a9092e15192012a5e0a8a1ffd66c70b8bbJim Ingham        return GetThreadsStoppedAtBreakpoint (process, bkpt)
441e41494a9092e15192012a5e0a8a1ffd66c70b8bbJim Ingham
442