11605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen"""
2b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny ChenThis LLDB module contains miscellaneous utilities.
330e4850a3f4687cab5b2465125072d5658786efaJohnny ChenSome of the test suite takes advantage of the utility functions defined here.
430e4850a3f4687cab5b2465125072d5658786efaJohnny ChenThey can also be useful for general purpose lldb scripting.
51605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen"""
61605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen
71605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chenimport lldb
80bfa859ea49d27efd89d5f152b8371b39919d92dJohnny Chenimport os, sys
9ed5f04ef51b18d6bedbc8589fa06544491977b9cJohnny Chenimport StringIO
101605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen
118a3b54eb714602c777d57ccc3626440c41dee46aJohnny Chen# ===================================================
128a3b54eb714602c777d57ccc3626440c41dee46aJohnny Chen# Utilities for locating/checking executable programs
138a3b54eb714602c777d57ccc3626440c41dee46aJohnny Chen# ===================================================
14979cb5da1f9aee5d23d8facfb7d5a781406cca28Johnny Chen
150bfa859ea49d27efd89d5f152b8371b39919d92dJohnny Chendef is_exe(fpath):
16efdc26a60c21852787e7bde326163c824d9e0491Johnny Chen    """Returns True if fpath is an executable."""
170bfa859ea49d27efd89d5f152b8371b39919d92dJohnny Chen    return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
180bfa859ea49d27efd89d5f152b8371b39919d92dJohnny Chen
190bfa859ea49d27efd89d5f152b8371b39919d92dJohnny Chendef which(program):
20efdc26a60c21852787e7bde326163c824d9e0491Johnny Chen    """Returns the full path to a program; None otherwise."""
210bfa859ea49d27efd89d5f152b8371b39919d92dJohnny Chen    fpath, fname = os.path.split(program)
220bfa859ea49d27efd89d5f152b8371b39919d92dJohnny Chen    if fpath:
230bfa859ea49d27efd89d5f152b8371b39919d92dJohnny Chen        if is_exe(program):
240bfa859ea49d27efd89d5f152b8371b39919d92dJohnny Chen            return program
250bfa859ea49d27efd89d5f152b8371b39919d92dJohnny Chen    else:
260bfa859ea49d27efd89d5f152b8371b39919d92dJohnny Chen        for path in os.environ["PATH"].split(os.pathsep):
270bfa859ea49d27efd89d5f152b8371b39919d92dJohnny Chen            exe_file = os.path.join(path, program)
280bfa859ea49d27efd89d5f152b8371b39919d92dJohnny Chen            if is_exe(exe_file):
290bfa859ea49d27efd89d5f152b8371b39919d92dJohnny Chen                return exe_file
300bfa859ea49d27efd89d5f152b8371b39919d92dJohnny Chen    return None
310bfa859ea49d27efd89d5f152b8371b39919d92dJohnny Chen
3251ed1b614f2c2b6970f50296d7d41c9de2c30ff4Johnny Chen# ===================================================
3351ed1b614f2c2b6970f50296d7d41c9de2c30ff4Johnny Chen# Disassembly for an SBFunction or an SBSymbol object
3451ed1b614f2c2b6970f50296d7d41c9de2c30ff4Johnny Chen# ===================================================
3551ed1b614f2c2b6970f50296d7d41c9de2c30ff4Johnny Chen
3651ed1b614f2c2b6970f50296d7d41c9de2c30ff4Johnny Chendef disassemble(target, function_or_symbol):
3751ed1b614f2c2b6970f50296d7d41c9de2c30ff4Johnny Chen    """Disassemble the function or symbol given a target.
3851ed1b614f2c2b6970f50296d7d41c9de2c30ff4Johnny Chen
3951ed1b614f2c2b6970f50296d7d41c9de2c30ff4Johnny Chen    It returns the disassembly content in a string object.
4051ed1b614f2c2b6970f50296d7d41c9de2c30ff4Johnny Chen    """
4151ed1b614f2c2b6970f50296d7d41c9de2c30ff4Johnny Chen    buf = StringIO.StringIO()
4251ed1b614f2c2b6970f50296d7d41c9de2c30ff4Johnny Chen    insts = function_or_symbol.GetInstructions(target)
43d643c08c3d80ab16308f395aaa5aa7664d506cd3Johnny Chen    for i in insts:
4451ed1b614f2c2b6970f50296d7d41c9de2c30ff4Johnny Chen        print >> buf, i
4551ed1b614f2c2b6970f50296d7d41c9de2c30ff4Johnny Chen    return buf.getvalue()
4651ed1b614f2c2b6970f50296d7d41c9de2c30ff4Johnny Chen
474c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen# ==========================================================
484c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen# Integer (byte size 1, 2, 4, and 8) to bytearray conversion
494c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen# ==========================================================
504c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen
514c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chendef int_to_bytearray(val, bytesize):
524c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen    """Utility function to convert an integer into a bytearray.
534c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen
54d2765fc8b9c9bd4d98dd5d6176b6108b6516e04cJohnny Chen    It returns the bytearray in the little endian format.  It is easy to get the
55d2765fc8b9c9bd4d98dd5d6176b6108b6516e04cJohnny Chen    big endian format, just do ba.reverse() on the returned object.
564c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen    """
57f4c0d1d8854f3ed87ca797628008386fdb9318afJohnny Chen    import struct
584c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen
594c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen    if bytesize == 1:
604c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen        return bytearray([val])
614c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen
624c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen    # Little endian followed by a format character.
634c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen    template = "<%c"
644c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen    if bytesize == 2:
654c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen        fmt = template % 'h'
664c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen    elif bytesize == 4:
674c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen        fmt = template % 'i'
684c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen    elif bytesize == 4:
694c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen        fmt = template % 'q'
704c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen    else:
714c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen        return None
724c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen
73f4c0d1d8854f3ed87ca797628008386fdb9318afJohnny Chen    packed = struct.pack(fmt, val)
744c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen    return bytearray(map(ord, packed))
754c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen
764c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chendef bytearray_to_int(bytes, bytesize):
774c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen    """Utility function to convert a bytearray into an integer.
784c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen
79d2765fc8b9c9bd4d98dd5d6176b6108b6516e04cJohnny Chen    It interprets the bytearray in the little endian format. For a big endian
80d2765fc8b9c9bd4d98dd5d6176b6108b6516e04cJohnny Chen    bytearray, just do ba.reverse() on the object before passing it in.
814c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen    """
82f4c0d1d8854f3ed87ca797628008386fdb9318afJohnny Chen    import struct
834c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen
844c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen    if bytesize == 1:
851ee6d9f49ca2e806197c2c6d7fa85e143b74da59Filipe Cabecinhas        return bytes[0]
864c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen
874c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen    # Little endian followed by a format character.
884c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen    template = "<%c"
894c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen    if bytesize == 2:
904c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen        fmt = template % 'h'
914c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen    elif bytesize == 4:
924c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen        fmt = template % 'i'
934c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen    elif bytesize == 4:
944c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen        fmt = template % 'q'
954c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen    else:
964c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen        return None
974c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen
98f4c0d1d8854f3ed87ca797628008386fdb9318afJohnny Chen    unpacked = struct.unpack(fmt, str(bytes))
994c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen    return unpacked[0]
1004c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen
1014c70f287ea336c4a0c599431bfc2b5a9a618ab5eJohnny Chen
102bc1a93e702cae42f87a8cbc58035877cb19e0840Johnny Chen# ==============================================================
103bc1a93e702cae42f87a8cbc58035877cb19e0840Johnny Chen# Get the description of an lldb object or None if not available
104bc1a93e702cae42f87a8cbc58035877cb19e0840Johnny Chen# ==============================================================
105bdc36bd05d156143d9f2e568a1aa1b5253bbe1f1Johnny Chendef get_description(obj, option=None):
106bdc36bd05d156143d9f2e568a1aa1b5253bbe1f1Johnny Chen    """Calls lldb_obj.GetDescription() and returns a string, or None.
107bdc36bd05d156143d9f2e568a1aa1b5253bbe1f1Johnny Chen
108ecd4feb5111432d2878e95461220c720cb2d24c8Johnny Chen    For SBTarget, SBBreakpointLocation, and SBWatchpoint lldb objects, an extra
109ecd4feb5111432d2878e95461220c720cb2d24c8Johnny Chen    option can be passed in to describe the detailed level of description
110ecd4feb5111432d2878e95461220c720cb2d24c8Johnny Chen    desired:
111bdc36bd05d156143d9f2e568a1aa1b5253bbe1f1Johnny Chen        o lldb.eDescriptionLevelBrief
112bdc36bd05d156143d9f2e568a1aa1b5253bbe1f1Johnny Chen        o lldb.eDescriptionLevelFull
113bdc36bd05d156143d9f2e568a1aa1b5253bbe1f1Johnny Chen        o lldb.eDescriptionLevelVerbose
114bdc36bd05d156143d9f2e568a1aa1b5253bbe1f1Johnny Chen    """
115bdc36bd05d156143d9f2e568a1aa1b5253bbe1f1Johnny Chen    method = getattr(obj, 'GetDescription')
116bc1a93e702cae42f87a8cbc58035877cb19e0840Johnny Chen    if not method:
117bc1a93e702cae42f87a8cbc58035877cb19e0840Johnny Chen        return None
118ecd4feb5111432d2878e95461220c720cb2d24c8Johnny Chen    tuple = (lldb.SBTarget, lldb.SBBreakpointLocation, lldb.SBWatchpoint)
1198a0d8971ba98e562091d3281620a5254048050a1Johnny Chen    if isinstance(obj, tuple):
120bdc36bd05d156143d9f2e568a1aa1b5253bbe1f1Johnny Chen        if option is None:
121bdc36bd05d156143d9f2e568a1aa1b5253bbe1f1Johnny Chen            option = lldb.eDescriptionLevelBrief
122bdc36bd05d156143d9f2e568a1aa1b5253bbe1f1Johnny Chen
123bc1a93e702cae42f87a8cbc58035877cb19e0840Johnny Chen    stream = lldb.SBStream()
124bc1a93e702cae42f87a8cbc58035877cb19e0840Johnny Chen    if option is None:
125bc1a93e702cae42f87a8cbc58035877cb19e0840Johnny Chen        success = method(stream)
126bc1a93e702cae42f87a8cbc58035877cb19e0840Johnny Chen    else:
127bc1a93e702cae42f87a8cbc58035877cb19e0840Johnny Chen        success = method(stream, option)
128bc1a93e702cae42f87a8cbc58035877cb19e0840Johnny Chen    if not success:
129bc1a93e702cae42f87a8cbc58035877cb19e0840Johnny Chen        return None
130bc1a93e702cae42f87a8cbc58035877cb19e0840Johnny Chen    return stream.GetData()
131bc1a93e702cae42f87a8cbc58035877cb19e0840Johnny Chen
132bc1a93e702cae42f87a8cbc58035877cb19e0840Johnny Chen
133168a61a9d1551d407240395942dc9e005c47ba30Johnny Chen# =================================================
134168a61a9d1551d407240395942dc9e005c47ba30Johnny Chen# Convert some enum value to its string counterpart
135168a61a9d1551d407240395942dc9e005c47ba30Johnny Chen# =================================================
136be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen
13747342d57ac5ac0bb2da765374229f94d98cb600aJohnny Chendef state_type_to_str(enum):
138be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    """Returns the stateType string given an enum."""
139be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    if enum == lldb.eStateInvalid:
14059b8477b020651df9b215396864e2e161a007d8cJohnny Chen        return "invalid"
141be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    elif enum == lldb.eStateUnloaded:
14259b8477b020651df9b215396864e2e161a007d8cJohnny Chen        return "unloaded"
14342da4dae5d7dccf98a57399d4689150b928ab545Johnny Chen    elif enum == lldb.eStateConnected:
14442da4dae5d7dccf98a57399d4689150b928ab545Johnny Chen        return "connected"
145be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    elif enum == lldb.eStateAttaching:
14659b8477b020651df9b215396864e2e161a007d8cJohnny Chen        return "attaching"
147be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    elif enum == lldb.eStateLaunching:
14859b8477b020651df9b215396864e2e161a007d8cJohnny Chen        return "launching"
149be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    elif enum == lldb.eStateStopped:
15059b8477b020651df9b215396864e2e161a007d8cJohnny Chen        return "stopped"
151be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    elif enum == lldb.eStateRunning:
15259b8477b020651df9b215396864e2e161a007d8cJohnny Chen        return "running"
153be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    elif enum == lldb.eStateStepping:
15459b8477b020651df9b215396864e2e161a007d8cJohnny Chen        return "stepping"
155be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    elif enum == lldb.eStateCrashed:
15659b8477b020651df9b215396864e2e161a007d8cJohnny Chen        return "crashed"
157be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    elif enum == lldb.eStateDetached:
15859b8477b020651df9b215396864e2e161a007d8cJohnny Chen        return "detached"
159be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    elif enum == lldb.eStateExited:
16059b8477b020651df9b215396864e2e161a007d8cJohnny Chen        return "exited"
161be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    elif enum == lldb.eStateSuspended:
16259b8477b020651df9b215396864e2e161a007d8cJohnny Chen        return "suspended"
163be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    else:
16442da4dae5d7dccf98a57399d4689150b928ab545Johnny Chen        raise Exception("Unknown StateType enum")
165be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen
16647342d57ac5ac0bb2da765374229f94d98cb600aJohnny Chendef stop_reason_to_str(enum):
167be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    """Returns the stopReason string given an enum."""
168be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    if enum == lldb.eStopReasonInvalid:
16959b8477b020651df9b215396864e2e161a007d8cJohnny Chen        return "invalid"
170be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    elif enum == lldb.eStopReasonNone:
17159b8477b020651df9b215396864e2e161a007d8cJohnny Chen        return "none"
172be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    elif enum == lldb.eStopReasonTrace:
17359b8477b020651df9b215396864e2e161a007d8cJohnny Chen        return "trace"
174be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    elif enum == lldb.eStopReasonBreakpoint:
17559b8477b020651df9b215396864e2e161a007d8cJohnny Chen        return "breakpoint"
176be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    elif enum == lldb.eStopReasonWatchpoint:
17759b8477b020651df9b215396864e2e161a007d8cJohnny Chen        return "watchpoint"
178be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    elif enum == lldb.eStopReasonSignal:
17959b8477b020651df9b215396864e2e161a007d8cJohnny Chen        return "signal"
180be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    elif enum == lldb.eStopReasonException:
18159b8477b020651df9b215396864e2e161a007d8cJohnny Chen        return "exception"
182be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    elif enum == lldb.eStopReasonPlanComplete:
18359b8477b020651df9b215396864e2e161a007d8cJohnny Chen        return "plancomplete"
184ff5c6d9c07c02c80b24a59c25d9f5edd518479c4Daniel Malea    elif enum == lldb.eStopReasonThreadExiting:
185ff5c6d9c07c02c80b24a59c25d9f5edd518479c4Daniel Malea        return "threadexiting"
186be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen    else:
18742da4dae5d7dccf98a57399d4689150b928ab545Johnny Chen        raise Exception("Unknown StopReason enum")
188be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen
189e70826104d551d48c5af91f56f9ed3937af14870Johnny Chendef symbol_type_to_str(enum):
190e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen    """Returns the symbolType string given an enum."""
191e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen    if enum == lldb.eSymbolTypeInvalid:
192e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen        return "invalid"
193e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen    elif enum == lldb.eSymbolTypeAbsolute:
194e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen        return "absolute"
195e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen    elif enum == lldb.eSymbolTypeCode:
196e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen        return "code"
197e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen    elif enum == lldb.eSymbolTypeData:
198e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen        return "data"
199e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen    elif enum == lldb.eSymbolTypeTrampoline:
200e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen        return "trampoline"
201e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen    elif enum == lldb.eSymbolTypeRuntime:
202e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen        return "runtime"
203e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen    elif enum == lldb.eSymbolTypeException:
204e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen        return "exception"
205e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen    elif enum == lldb.eSymbolTypeSourceFile:
206e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen        return "sourcefile"
207e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen    elif enum == lldb.eSymbolTypeHeaderFile:
208e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen        return "headerfile"
209e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen    elif enum == lldb.eSymbolTypeObjectFile:
210e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen        return "objectfile"
211e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen    elif enum == lldb.eSymbolTypeCommonBlock:
212e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen        return "commonblock"
213e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen    elif enum == lldb.eSymbolTypeBlock:
214e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen        return "block"
215e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen    elif enum == lldb.eSymbolTypeLocal:
216e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen        return "local"
217e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen    elif enum == lldb.eSymbolTypeParam:
218e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen        return "param"
219e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen    elif enum == lldb.eSymbolTypeVariable:
220e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen        return "variable"
221e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen    elif enum == lldb.eSymbolTypeVariableType:
222e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen        return "variabletype"
223e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen    elif enum == lldb.eSymbolTypeLineEntry:
224e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen        return "lineentry"
225e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen    elif enum == lldb.eSymbolTypeLineHeader:
226e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen        return "lineheader"
227e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen    elif enum == lldb.eSymbolTypeScopeBegin:
228e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen        return "scopebegin"
229e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen    elif enum == lldb.eSymbolTypeScopeEnd:
230e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen        return "scopeend"
231e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen    elif enum == lldb.eSymbolTypeAdditional:
232e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen        return "additional"
233e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen    elif enum == lldb.eSymbolTypeCompiler:
234e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen        return "compiler"
235e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen    elif enum == lldb.eSymbolTypeInstrumentation:
236e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen        return "instrumentation"
237e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen    elif enum == lldb.eSymbolTypeUndefined:
238e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen        return "undefined"
239e70826104d551d48c5af91f56f9ed3937af14870Johnny Chen
24047342d57ac5ac0bb2da765374229f94d98cb600aJohnny Chendef value_type_to_str(enum):
2412c8d1596ec40c321d6d39c2b32c33fd662b66c11Johnny Chen    """Returns the valueType string given an enum."""
2422c8d1596ec40c321d6d39c2b32c33fd662b66c11Johnny Chen    if enum == lldb.eValueTypeInvalid:
2432c8d1596ec40c321d6d39c2b32c33fd662b66c11Johnny Chen        return "invalid"
2442c8d1596ec40c321d6d39c2b32c33fd662b66c11Johnny Chen    elif enum == lldb.eValueTypeVariableGlobal:
2452c8d1596ec40c321d6d39c2b32c33fd662b66c11Johnny Chen        return "global_variable"
2462c8d1596ec40c321d6d39c2b32c33fd662b66c11Johnny Chen    elif enum == lldb.eValueTypeVariableStatic:
2472c8d1596ec40c321d6d39c2b32c33fd662b66c11Johnny Chen        return "static_variable"
2482c8d1596ec40c321d6d39c2b32c33fd662b66c11Johnny Chen    elif enum == lldb.eValueTypeVariableArgument:
2492c8d1596ec40c321d6d39c2b32c33fd662b66c11Johnny Chen        return "argument_variable"
2502c8d1596ec40c321d6d39c2b32c33fd662b66c11Johnny Chen    elif enum == lldb.eValueTypeVariableLocal:
2512c8d1596ec40c321d6d39c2b32c33fd662b66c11Johnny Chen        return "local_variable"
2522c8d1596ec40c321d6d39c2b32c33fd662b66c11Johnny Chen    elif enum == lldb.eValueTypeRegister:
2532c8d1596ec40c321d6d39c2b32c33fd662b66c11Johnny Chen        return "register"
2542c8d1596ec40c321d6d39c2b32c33fd662b66c11Johnny Chen    elif enum == lldb.eValueTypeRegisterSet:
2552c8d1596ec40c321d6d39c2b32c33fd662b66c11Johnny Chen        return "register_set"
2562c8d1596ec40c321d6d39c2b32c33fd662b66c11Johnny Chen    elif enum == lldb.eValueTypeConstResult:
2572c8d1596ec40c321d6d39c2b32c33fd662b66c11Johnny Chen        return "constant_result"
2582c8d1596ec40c321d6d39c2b32c33fd662b66c11Johnny Chen    else:
25942da4dae5d7dccf98a57399d4689150b928ab545Johnny Chen        raise Exception("Unknown ValueType enum")
2602c8d1596ec40c321d6d39c2b32c33fd662b66c11Johnny Chen
261be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen
262168a61a9d1551d407240395942dc9e005c47ba30Johnny Chen# ==================================================
263ff5c6d9c07c02c80b24a59c25d9f5edd518479c4Daniel Malea# Get stopped threads due to each stop reason.
264ff5c6d9c07c02c80b24a59c25d9f5edd518479c4Daniel Malea# ==================================================
265ff5c6d9c07c02c80b24a59c25d9f5edd518479c4Daniel Malea
266ff5c6d9c07c02c80b24a59c25d9f5edd518479c4Daniel Maleadef sort_stopped_threads(process,
267ff5c6d9c07c02c80b24a59c25d9f5edd518479c4Daniel Malea                         breakpoint_threads = None,
268ff5c6d9c07c02c80b24a59c25d9f5edd518479c4Daniel Malea                         crashed_threads = None,
269ff5c6d9c07c02c80b24a59c25d9f5edd518479c4Daniel Malea                         watchpoint_threads = None,
270ff5c6d9c07c02c80b24a59c25d9f5edd518479c4Daniel Malea                         signal_threads = None,
271ff5c6d9c07c02c80b24a59c25d9f5edd518479c4Daniel Malea                         exiting_threads = None,
272ff5c6d9c07c02c80b24a59c25d9f5edd518479c4Daniel Malea                         other_threads = None):
273ff5c6d9c07c02c80b24a59c25d9f5edd518479c4Daniel Malea    """ Fills array *_threads with threads stopped for the corresponding stop
274ff5c6d9c07c02c80b24a59c25d9f5edd518479c4Daniel Malea        reason.
275ff5c6d9c07c02c80b24a59c25d9f5edd518479c4Daniel Malea    """
276ff5c6d9c07c02c80b24a59c25d9f5edd518479c4Daniel Malea    for lst in [breakpoint_threads,
277ff5c6d9c07c02c80b24a59c25d9f5edd518479c4Daniel Malea                watchpoint_threads,
278ff5c6d9c07c02c80b24a59c25d9f5edd518479c4Daniel Malea                signal_threads,
279ff5c6d9c07c02c80b24a59c25d9f5edd518479c4Daniel Malea                exiting_threads,
280ff5c6d9c07c02c80b24a59c25d9f5edd518479c4Daniel Malea                other_threads]:
281ff5c6d9c07c02c80b24a59c25d9f5edd518479c4Daniel Malea        if lst is not None:
282ff5c6d9c07c02c80b24a59c25d9f5edd518479c4Daniel Malea            lst[:] = []
283ff5c6d9c07c02c80b24a59c25d9f5edd518479c4Daniel Malea
284ff5c6d9c07c02c80b24a59c25d9f5edd518479c4Daniel Malea    for thread in process:
285ff5c6d9c07c02c80b24a59c25d9f5edd518479c4Daniel Malea        dispatched = False
286ff5c6d9c07c02c80b24a59c25d9f5edd518479c4Daniel Malea        for (reason, list) in [(lldb.eStopReasonBreakpoint, breakpoint_threads),
287ff5c6d9c07c02c80b24a59c25d9f5edd518479c4Daniel Malea                               (lldb.eStopReasonException, crashed_threads),
288ff5c6d9c07c02c80b24a59c25d9f5edd518479c4Daniel Malea                               (lldb.eStopReasonWatchpoint, watchpoint_threads),
289ff5c6d9c07c02c80b24a59c25d9f5edd518479c4Daniel Malea                               (lldb.eStopReasonSignal, signal_threads),
290ff5c6d9c07c02c80b24a59c25d9f5edd518479c4Daniel Malea                               (lldb.eStopReasonThreadExiting, exiting_threads),
291ff5c6d9c07c02c80b24a59c25d9f5edd518479c4Daniel Malea                               (None, other_threads)]:
292ff5c6d9c07c02c80b24a59c25d9f5edd518479c4Daniel Malea            if not dispatched and list is not None:
293ff5c6d9c07c02c80b24a59c25d9f5edd518479c4Daniel Malea                if thread.GetStopReason() == reason or reason is None:
294ff5c6d9c07c02c80b24a59c25d9f5edd518479c4Daniel Malea                    list.append(thread)
295ff5c6d9c07c02c80b24a59c25d9f5edd518479c4Daniel Malea                    dispatched = True
296ff5c6d9c07c02c80b24a59c25d9f5edd518479c4Daniel Malea
297ff5c6d9c07c02c80b24a59c25d9f5edd518479c4Daniel Malea# ==================================================
298431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham# Utility functions for setting breakpoints
299431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham# ==================================================
300431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
301431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Inghamdef run_break_set_by_file_and_line (test, file_name, line_number, extra_options = None, num_expected_locations = 1, loc_exact=False, module_name=None):
302431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    """Set a breakpoint by file and line, returning the breakpoint number.
303431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
304431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    If extra_options is not None, then we append it to the breakpoint set command.
305431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
306431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    If num_expected_locations is -1 we check that we got AT LEAST one location, otherwise we check that num_expected_locations equals the number of locations.
307431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
308431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    If loc_exact is true, we check that there is one location, and that location must be at the input file and line number."""
309431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
310431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    if file_name == None:
311431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        command = 'breakpoint set -l %d'%(line_number)
312431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    else:
313431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        command = 'breakpoint set -f "%s" -l %d'%(file_name, line_number)
314431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
3152fcbf6e3d86ac0e6a95e11e5e232a9f72bd612d2Greg Clayton    if module_name:
3162fcbf6e3d86ac0e6a95e11e5e232a9f72bd612d2Greg Clayton        command += " --shlib '%s'" % (module_name)
3172fcbf6e3d86ac0e6a95e11e5e232a9f72bd612d2Greg Clayton
318431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    if extra_options:
319431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        command += " " + extra_options
320431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
321431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    break_results = run_break_set_command (test, command)
322431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
323431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    if num_expected_locations == 1 and loc_exact:
324431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        check_breakpoint_result (test, break_results, num_locations=num_expected_locations, file_name = file_name, line_number = line_number, module_name=module_name)
325431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    else:
326431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        check_breakpoint_result (test, break_results, num_locations = num_expected_locations)
327431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
328431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    return get_bpno_from_match (break_results)
329431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
330431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Inghamdef run_break_set_by_symbol (test, symbol, extra_options = None, num_expected_locations = -1, sym_exact = False, module_name=None):
331431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    """Set a breakpoint by symbol name.  Common options are the same as run_break_set_by_file_and_line.
332431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
333431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    If sym_exact is true, then the output symbol must match the input exactly, otherwise we do a substring match."""
334431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    command = 'breakpoint set -n "%s"'%(symbol)
3352fcbf6e3d86ac0e6a95e11e5e232a9f72bd612d2Greg Clayton
3362fcbf6e3d86ac0e6a95e11e5e232a9f72bd612d2Greg Clayton    if module_name:
3372fcbf6e3d86ac0e6a95e11e5e232a9f72bd612d2Greg Clayton        command += " --shlib '%s'" % (module_name)
3382fcbf6e3d86ac0e6a95e11e5e232a9f72bd612d2Greg Clayton
339431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    if extra_options:
340431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        command += " " + extra_options
341431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
342431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    break_results = run_break_set_command (test, command)
343431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
344431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    if num_expected_locations == 1 and sym_exact:
345431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        check_breakpoint_result (test, break_results, num_locations = num_expected_locations, symbol_name = symbol, module_name=module_name)
346431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    else:
347431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        check_breakpoint_result (test, break_results, num_locations = num_expected_locations)
348431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
349431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    return get_bpno_from_match (break_results)
350431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
351431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Inghamdef run_break_set_by_selector (test, selector, extra_options = None, num_expected_locations = -1, module_name=None):
352431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    """Set a breakpoint by selector.  Common options are the same as run_break_set_by_file_and_line."""
353431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
3542fcbf6e3d86ac0e6a95e11e5e232a9f72bd612d2Greg Clayton    command = 'breakpoint set -S "%s"' % (selector)
3552fcbf6e3d86ac0e6a95e11e5e232a9f72bd612d2Greg Clayton
3562fcbf6e3d86ac0e6a95e11e5e232a9f72bd612d2Greg Clayton    if module_name:
3572fcbf6e3d86ac0e6a95e11e5e232a9f72bd612d2Greg Clayton        command += ' --shlib "%s"' % (module_name)
3582fcbf6e3d86ac0e6a95e11e5e232a9f72bd612d2Greg Clayton
359431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    if extra_options:
360431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        command += " " + extra_options
361431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
362431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    break_results = run_break_set_command (test, command)
363431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
364431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    if num_expected_locations == 1:
365431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        check_breakpoint_result (test, break_results, num_locations = num_expected_locations, symbol_name = selector, symbol_match_exact=False, module_name=module_name)
366431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    else:
367431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        check_breakpoint_result (test, break_results, num_locations = num_expected_locations)
368431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
369431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    return get_bpno_from_match (break_results)
370431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
371431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Inghamdef run_break_set_by_regexp (test, regexp, extra_options=None, num_expected_locations=-1):
372431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    """Set a breakpoint by regular expression match on symbol name.  Common options are the same as run_break_set_by_file_and_line."""
373431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
374431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    command = 'breakpoint set -r "%s"'%(regexp)
375431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    if extra_options:
376431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        command += " " + extra_options
377431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
378431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    break_results = run_break_set_command (test, command)
379431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
380431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    check_breakpoint_result (test, break_results, num_locations=num_expected_locations)
381431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
382431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    return get_bpno_from_match (break_results)
383431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
384431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Inghamdef run_break_set_by_source_regexp (test, regexp, extra_options=None, num_expected_locations=-1):
385431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    """Set a breakpoint by source regular expression.  Common options are the same as run_break_set_by_file_and_line."""
386431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    command = 'breakpoint set -p "%s"'%(regexp)
387431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    if extra_options:
388431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        command += " " + extra_options
389431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
390431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    break_results = run_break_set_command (test, command)
391431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
392431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    check_breakpoint_result (test, break_results, num_locations=num_expected_locations)
393431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
394431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    return get_bpno_from_match (break_results)
395431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
396431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Inghamdef run_break_set_command (test, command):
397431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    """Run the command passed in - it must be some break set variant - and analyze the result.
398431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    Returns a dictionary of information gleaned from the command-line results.
399431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    Will assert if the breakpoint setting fails altogether.
400431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
401431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    Dictionary will contain:
402431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        bpno          - breakpoint of the newly created breakpoint, -1 on error.
403431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        num_locations - number of locations set for the breakpoint.
404431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
405431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    If there is only one location, the dictionary MAY contain:
406431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        file          - source file name
407431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        line_no       - source line number
408431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        symbol        - symbol name
409431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        inline_symbol - inlined symbol name
410431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        offset        - offset from the original symbol
411431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        module        - module
412431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        address       - address at which the breakpoint was set."""
413431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
414431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    patterns = [r"^Breakpoint (?P<bpno>[0-9]+): (?P<num_locations>[0-9]+) locations\.$",
415431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham                r"^Breakpoint (?P<bpno>[0-9]+): (?P<num_locations>no) locations \(pending\)\.",
416431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham                r"^Breakpoint (?P<bpno>[0-9]+): where = (?P<module>.*)`(?P<symbol>[+\-]{0,1}[^+]+)( \+ (?P<offset>[0-9]+)){0,1}( \[inlined\] (?P<inline_symbol>.*)){0,1} at (?P<file>[^:]+):(?P<line_no>[0-9]+), address = (?P<address>0x[0-9a-fA-F]+)$",
417431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham                r"^Breakpoint (?P<bpno>[0-9]+): where = (?P<module>.*)`(?P<symbol>.*)( \+ (?P<offset>[0-9]+)){0,1}, address = (?P<address>0x[0-9a-fA-F]+)$"]
418431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    match_object = test.match (command, patterns)
419431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    break_results = match_object.groupdict()
420431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
421431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    # We always insert the breakpoint number, setting it to -1 if we couldn't find it
422431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    # Also, make sure it gets stored as an integer.
423431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    if not 'bpno' in break_results:
424431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        break_results['bpno'] = -1
425431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    else:
426431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        break_results['bpno'] = int(break_results['bpno'])
427431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
428431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    # We always insert the number of locations
429431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    # If ONE location is set for the breakpoint, then the output doesn't mention locations, but it has to be 1...
430431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    # We also make sure it is an integer.
431431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
432431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    if not 'num_locations' in break_results:
433431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        num_locations = 1
434431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    else:
435431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        num_locations = break_results['num_locations']
436431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        if num_locations == 'no':
437431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham            num_locations = 0
438431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        else:
439431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham            num_locations = int(break_results['num_locations'])
440431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
441431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    break_results['num_locations'] = num_locations
442431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
443431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    if 'line_no' in break_results:
444431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        break_results['line_no'] = int(break_results['line_no'])
445431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
446431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    return break_results
447431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
448431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Inghamdef get_bpno_from_match (break_results):
449431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    return int (break_results['bpno'])
450431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
451431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Inghamdef check_breakpoint_result (test, break_results, file_name=None, line_number=-1, symbol_name=None, symbol_match_exact=True, module_name=None, offset=-1, num_locations=-1):
452431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
453431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    out_num_locations = break_results['num_locations']
454431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
455431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    if num_locations == -1:
456431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        test.assertTrue (out_num_locations > 0, "Expecting one or more locations, got none.")
457431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    else:
458431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        test.assertTrue (num_locations == out_num_locations, "Expecting %d locations, got %d."%(num_locations, out_num_locations))
459431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
460431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    if file_name:
461431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        out_file_name = ""
462431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        if 'file' in break_results:
463431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham            out_file_name = break_results['file']
464431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        test.assertTrue (file_name == out_file_name, "Breakpoint file name '%s' doesn't match resultant name '%s'."%(file_name, out_file_name))
465431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
466431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    if line_number != -1:
467431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        out_file_line = -1
468431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        if 'line_no' in break_results:
469431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham            out_line_number = break_results['line_no']
470431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
471431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        test.assertTrue (line_number == out_line_number, "Breakpoint line number %s doesn't match resultant line %s."%(line_number, out_line_number))
472431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
473431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    if symbol_name:
474431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        out_symbol_name = ""
475431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        # Look first for the inlined symbol name, otherwise use the symbol name:
476431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        if 'inline_symbol' in break_results and break_results['inline_symbol']:
477431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham            out_symbol_name = break_results['inline_symbol']
478431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        elif 'symbol' in break_results:
479431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham            out_symbol_name = break_results['symbol']
480431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
481431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        if symbol_match_exact:
482431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham            test.assertTrue(symbol_name == out_symbol_name, "Symbol name '%s' doesn't match resultant symbol '%s'."%(symbol_name, out_symbol_name))
483431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        else:
484431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham            test.assertTrue(out_symbol_name.find(symbol_name) != -1, "Symbol name '%s' isn't in resultant symbol '%s'."%(symbol_name, out_symbol_name))
485431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
486431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham    if module_name:
487431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        out_nodule_name = None
488431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        if 'module' in break_results:
489431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham            out_module_name = break_results['module']
490431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
491431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham        test.assertTrue (module_name.find(out_module_name) != -1, "Symbol module name '%s' isn't in expected module name '%s'."%(out_module_name, module_name))
492431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham
493431d839a33e9a274e705f7a268a1c9de2ffc2da2Jim Ingham# ==================================================
494168a61a9d1551d407240395942dc9e005c47ba30Johnny Chen# Utility functions related to Threads and Processes
495168a61a9d1551d407240395942dc9e005c47ba30Johnny Chen# ==================================================
496be683bc054db1f6c7fbe2bbf712266f9f70c6389Johnny Chen
497e428d33b3f09b789f0b5f70f973ebea5785d7feeJohnny Chendef get_stopped_threads(process, reason):
4985aba3f5e7964f9cdea53ab5f20487201f031d856Johnny Chen    """Returns the thread(s) with the specified stop reason in a list.
4995aba3f5e7964f9cdea53ab5f20487201f031d856Johnny Chen
5005aba3f5e7964f9cdea53ab5f20487201f031d856Johnny Chen    The list can be empty if no such thread exists.
5015aba3f5e7964f9cdea53ab5f20487201f031d856Johnny Chen    """
502e428d33b3f09b789f0b5f70f973ebea5785d7feeJohnny Chen    threads = []
503d643c08c3d80ab16308f395aaa5aa7664d506cd3Johnny Chen    for t in process:
504e428d33b3f09b789f0b5f70f973ebea5785d7feeJohnny Chen        if t.GetStopReason() == reason:
505e428d33b3f09b789f0b5f70f973ebea5785d7feeJohnny Chen            threads.append(t)
506e428d33b3f09b789f0b5f70f973ebea5785d7feeJohnny Chen    return threads
507e428d33b3f09b789f0b5f70f973ebea5785d7feeJohnny Chen
508e428d33b3f09b789f0b5f70f973ebea5785d7feeJohnny Chendef get_stopped_thread(process, reason):
509e428d33b3f09b789f0b5f70f973ebea5785d7feeJohnny Chen    """A convenience function which returns the first thread with the given stop
510e428d33b3f09b789f0b5f70f973ebea5785d7feeJohnny Chen    reason or None.
511e428d33b3f09b789f0b5f70f973ebea5785d7feeJohnny Chen
512e428d33b3f09b789f0b5f70f973ebea5785d7feeJohnny Chen    Example usages:
513e428d33b3f09b789f0b5f70f973ebea5785d7feeJohnny Chen
514e428d33b3f09b789f0b5f70f973ebea5785d7feeJohnny Chen    1. Get the stopped thread due to a breakpoint condition
515e428d33b3f09b789f0b5f70f973ebea5785d7feeJohnny Chen
516e428d33b3f09b789f0b5f70f973ebea5785d7feeJohnny Chen    ...
517e428d33b3f09b789f0b5f70f973ebea5785d7feeJohnny Chen        from lldbutil import get_stopped_thread
5183d8ae4681b81b42a404ad77a231c6f743040e644Johnny Chen        thread = get_stopped_thread(process, lldb.eStopReasonPlanComplete)
519166b89f089d6bec5bb9dd40470a4dc951ffc9daaGreg Clayton        self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint condition")
520e428d33b3f09b789f0b5f70f973ebea5785d7feeJohnny Chen    ...
521e428d33b3f09b789f0b5f70f973ebea5785d7feeJohnny Chen
522e428d33b3f09b789f0b5f70f973ebea5785d7feeJohnny Chen    2. Get the thread stopped due to a breakpoint
523e428d33b3f09b789f0b5f70f973ebea5785d7feeJohnny Chen
524e428d33b3f09b789f0b5f70f973ebea5785d7feeJohnny Chen    ...
525e428d33b3f09b789f0b5f70f973ebea5785d7feeJohnny Chen        from lldbutil import get_stopped_thread
5263d8ae4681b81b42a404ad77a231c6f743040e644Johnny Chen        thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint)
527166b89f089d6bec5bb9dd40470a4dc951ffc9daaGreg Clayton        self.assertTrue(thread.IsValid(), "There should be a thread stopped due to breakpoint")
528e428d33b3f09b789f0b5f70f973ebea5785d7feeJohnny Chen    ...
529e428d33b3f09b789f0b5f70f973ebea5785d7feeJohnny Chen
530e428d33b3f09b789f0b5f70f973ebea5785d7feeJohnny Chen    """
531e428d33b3f09b789f0b5f70f973ebea5785d7feeJohnny Chen    threads = get_stopped_threads(process, reason)
532e428d33b3f09b789f0b5f70f973ebea5785d7feeJohnny Chen    if len(threads) == 0:
533e428d33b3f09b789f0b5f70f973ebea5785d7feeJohnny Chen        return None
534e428d33b3f09b789f0b5f70f973ebea5785d7feeJohnny Chen    return threads[0]
535e428d33b3f09b789f0b5f70f973ebea5785d7feeJohnny Chen
536318aaa0b4b593ec3e69c5962bddab10c47066c4fJohnny Chendef get_threads_stopped_at_breakpoint (process, bkpt):
537318aaa0b4b593ec3e69c5962bddab10c47066c4fJohnny Chen    """ For a stopped process returns the thread stopped at the breakpoint passed in bkpt"""
538318aaa0b4b593ec3e69c5962bddab10c47066c4fJohnny Chen    stopped_threads = []
539318aaa0b4b593ec3e69c5962bddab10c47066c4fJohnny Chen    threads = []
540318aaa0b4b593ec3e69c5962bddab10c47066c4fJohnny Chen
541318aaa0b4b593ec3e69c5962bddab10c47066c4fJohnny Chen    stopped_threads = get_stopped_threads (process, lldb.eStopReasonBreakpoint)
542318aaa0b4b593ec3e69c5962bddab10c47066c4fJohnny Chen
543318aaa0b4b593ec3e69c5962bddab10c47066c4fJohnny Chen    if len(stopped_threads) == 0:
544318aaa0b4b593ec3e69c5962bddab10c47066c4fJohnny Chen        return threads
545318aaa0b4b593ec3e69c5962bddab10c47066c4fJohnny Chen
546318aaa0b4b593ec3e69c5962bddab10c47066c4fJohnny Chen    for thread in stopped_threads:
547ec95492f93f5610d23344adf10ea4224795a4d46Johnny Chen        # Make sure we've hit our breakpoint...
548318aaa0b4b593ec3e69c5962bddab10c47066c4fJohnny Chen        break_id = thread.GetStopReasonDataAtIndex (0)
549318aaa0b4b593ec3e69c5962bddab10c47066c4fJohnny Chen        if break_id == bkpt.GetID():
550318aaa0b4b593ec3e69c5962bddab10c47066c4fJohnny Chen            threads.append(thread)
551318aaa0b4b593ec3e69c5962bddab10c47066c4fJohnny Chen
552318aaa0b4b593ec3e69c5962bddab10c47066c4fJohnny Chen    return threads
553318aaa0b4b593ec3e69c5962bddab10c47066c4fJohnny Chen
554318aaa0b4b593ec3e69c5962bddab10c47066c4fJohnny Chendef continue_to_breakpoint (process, bkpt):
555318aaa0b4b593ec3e69c5962bddab10c47066c4fJohnny Chen    """ Continues the process, if it stops, returns the threads stopped at bkpt; otherwise, returns None"""
556318aaa0b4b593ec3e69c5962bddab10c47066c4fJohnny Chen    process.Continue()
557318aaa0b4b593ec3e69c5962bddab10c47066c4fJohnny Chen    if process.GetState() != lldb.eStateStopped:
558318aaa0b4b593ec3e69c5962bddab10c47066c4fJohnny Chen        return None
559318aaa0b4b593ec3e69c5962bddab10c47066c4fJohnny Chen    else:
560318aaa0b4b593ec3e69c5962bddab10c47066c4fJohnny Chen        return get_threads_stopped_at_breakpoint (process, bkpt)
561318aaa0b4b593ec3e69c5962bddab10c47066c4fJohnny Chen
56269af39d7e7c1988caf027956a6af5f17c55b5534Johnny Chendef get_caller_symbol(thread):
56369af39d7e7c1988caf027956a6af5f17c55b5534Johnny Chen    """
56469af39d7e7c1988caf027956a6af5f17c55b5534Johnny Chen    Returns the symbol name for the call site of the leaf function.
56569af39d7e7c1988caf027956a6af5f17c55b5534Johnny Chen    """
56669af39d7e7c1988caf027956a6af5f17c55b5534Johnny Chen    depth = thread.GetNumFrames()
56769af39d7e7c1988caf027956a6af5f17c55b5534Johnny Chen    if depth <= 1:
56869af39d7e7c1988caf027956a6af5f17c55b5534Johnny Chen        return None
56969af39d7e7c1988caf027956a6af5f17c55b5534Johnny Chen    caller = thread.GetFrameAtIndex(1).GetSymbol()
57069af39d7e7c1988caf027956a6af5f17c55b5534Johnny Chen    if caller:
57169af39d7e7c1988caf027956a6af5f17c55b5534Johnny Chen        return caller.GetName()
57269af39d7e7c1988caf027956a6af5f17c55b5534Johnny Chen    else:
57369af39d7e7c1988caf027956a6af5f17c55b5534Johnny Chen        return None
57469af39d7e7c1988caf027956a6af5f17c55b5534Johnny Chen
57569af39d7e7c1988caf027956a6af5f17c55b5534Johnny Chen
576318aaa0b4b593ec3e69c5962bddab10c47066c4fJohnny Chendef get_function_names(thread):
5771605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    """
5781605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    Returns a sequence of function names from the stack frames of this thread.
5791605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    """
5801605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    def GetFuncName(i):
58164abe46fa4d3b030ae525b40afe1bffccda166aaJohnny Chen        return thread.GetFrameAtIndex(i).GetFunctionName()
5821605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen
5831605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    return map(GetFuncName, range(thread.GetNumFrames()))
5841605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen
5851605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen
586318aaa0b4b593ec3e69c5962bddab10c47066c4fJohnny Chendef get_symbol_names(thread):
587b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen    """
588b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen    Returns a sequence of symbols for this thread.
589b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen    """
590b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen    def GetSymbol(i):
591b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen        return thread.GetFrameAtIndex(i).GetSymbol().GetName()
592b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen
593b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen    return map(GetSymbol, range(thread.GetNumFrames()))
594b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen
595b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen
596318aaa0b4b593ec3e69c5962bddab10c47066c4fJohnny Chendef get_pc_addresses(thread):
597b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen    """
598b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen    Returns a sequence of pc addresses for this thread.
599b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen    """
600b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen    def GetPCAddress(i):
601b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen        return thread.GetFrameAtIndex(i).GetPCAddress()
602b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen
603b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen    return map(GetPCAddress, range(thread.GetNumFrames()))
604b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen
605b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen
606318aaa0b4b593ec3e69c5962bddab10c47066c4fJohnny Chendef get_filenames(thread):
6071605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    """
6081605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    Returns a sequence of file names from the stack frames of this thread.
6091605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    """
6101605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    def GetFilename(i):
6111605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen        return thread.GetFrameAtIndex(i).GetLineEntry().GetFileSpec().GetFilename()
6121605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen
6131605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    return map(GetFilename, range(thread.GetNumFrames()))
6141605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen
6151605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen
616318aaa0b4b593ec3e69c5962bddab10c47066c4fJohnny Chendef get_line_numbers(thread):
6171605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    """
6181605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    Returns a sequence of line numbers from the stack frames of this thread.
6191605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    """
6201605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    def GetLineNumber(i):
6211605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen        return thread.GetFrameAtIndex(i).GetLineEntry().GetLine()
6221605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen
6231605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    return map(GetLineNumber, range(thread.GetNumFrames()))
6241605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen
6251605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen
626318aaa0b4b593ec3e69c5962bddab10c47066c4fJohnny Chendef get_module_names(thread):
6271605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    """
6281605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    Returns a sequence of module names from the stack frames of this thread.
6291605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    """
6301605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    def GetModuleName(i):
6311605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen        return thread.GetFrameAtIndex(i).GetModule().GetFileSpec().GetFilename()
6321605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen
6331605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    return map(GetModuleName, range(thread.GetNumFrames()))
6341605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen
6351605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen
636318aaa0b4b593ec3e69c5962bddab10c47066c4fJohnny Chendef get_stack_frames(thread):
63788866ac481cd5533c18e00233aeced2eb1fce42bJohnny Chen    """
63888866ac481cd5533c18e00233aeced2eb1fce42bJohnny Chen    Returns a sequence of stack frames for this thread.
63988866ac481cd5533c18e00233aeced2eb1fce42bJohnny Chen    """
64088866ac481cd5533c18e00233aeced2eb1fce42bJohnny Chen    def GetStackFrame(i):
64188866ac481cd5533c18e00233aeced2eb1fce42bJohnny Chen        return thread.GetFrameAtIndex(i)
64288866ac481cd5533c18e00233aeced2eb1fce42bJohnny Chen
64388866ac481cd5533c18e00233aeced2eb1fce42bJohnny Chen    return map(GetStackFrame, range(thread.GetNumFrames()))
64488866ac481cd5533c18e00233aeced2eb1fce42bJohnny Chen
64588866ac481cd5533c18e00233aeced2eb1fce42bJohnny Chen
646318aaa0b4b593ec3e69c5962bddab10c47066c4fJohnny Chendef print_stacktrace(thread, string_buffer = False):
6471605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    """Prints a simple stack trace of this thread."""
64830425e9677342cff9995cd4937fdc12354b6b24bJohnny Chen
649ed5f04ef51b18d6bedbc8589fa06544491977b9cJohnny Chen    output = StringIO.StringIO() if string_buffer else sys.stdout
650b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen    target = thread.GetProcess().GetTarget()
651b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen
6521605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen    depth = thread.GetNumFrames()
6531605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen
654318aaa0b4b593ec3e69c5962bddab10c47066c4fJohnny Chen    mods = get_module_names(thread)
655318aaa0b4b593ec3e69c5962bddab10c47066c4fJohnny Chen    funcs = get_function_names(thread)
656318aaa0b4b593ec3e69c5962bddab10c47066c4fJohnny Chen    symbols = get_symbol_names(thread)
657318aaa0b4b593ec3e69c5962bddab10c47066c4fJohnny Chen    files = get_filenames(thread)
658318aaa0b4b593ec3e69c5962bddab10c47066c4fJohnny Chen    lines = get_line_numbers(thread)
659318aaa0b4b593ec3e69c5962bddab10c47066c4fJohnny Chen    addrs = get_pc_addresses(thread)
66030425e9677342cff9995cd4937fdc12354b6b24bJohnny Chen
661ad5fd40cb92070593d248b8f44b9902be0bcb4bfJohnny Chen    if thread.GetStopReason() != lldb.eStopReasonInvalid:
66247342d57ac5ac0bb2da765374229f94d98cb600aJohnny Chen        desc =  "stop reason=" + stop_reason_to_str(thread.GetStopReason())
663ad5fd40cb92070593d248b8f44b9902be0bcb4bfJohnny Chen    else:
664ad5fd40cb92070593d248b8f44b9902be0bcb4bfJohnny Chen        desc = ""
665ad5fd40cb92070593d248b8f44b9902be0bcb4bfJohnny Chen    print >> output, "Stack trace for thread id={0:#x} name={1} queue={2} ".format(
666ad5fd40cb92070593d248b8f44b9902be0bcb4bfJohnny Chen        thread.GetThreadID(), thread.GetName(), thread.GetQueueName()) + desc
6671605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen
668b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen    for i in range(depth):
669b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen        frame = thread.GetFrameAtIndex(i)
670b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen        function = frame.GetFunction()
671b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen
672b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen        load_addr = addrs[i].GetLoadAddress(target)
673960ce1206dbe268c7f3142fcf279e6392a852024Johnny Chen        if not function:
674b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen            file_addr = addrs[i].GetFileAddress()
67549f3d81ab49270d85d1637797572a3bc38cce1d9Johnny Chen            start_addr = frame.GetSymbol().GetStartAddress().GetFileAddress()
67649f3d81ab49270d85d1637797572a3bc38cce1d9Johnny Chen            symbol_offset = file_addr - start_addr
67749f3d81ab49270d85d1637797572a3bc38cce1d9Johnny Chen            print >> output, "  frame #{num}: {addr:#016x} {mod}`{symbol} + {offset}".format(
67849f3d81ab49270d85d1637797572a3bc38cce1d9Johnny Chen                num=i, addr=load_addr, mod=mods[i], symbol=symbols[i], offset=symbol_offset)
679b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen        else:
68049f3d81ab49270d85d1637797572a3bc38cce1d9Johnny Chen            print >> output, "  frame #{num}: {addr:#016x} {mod}`{func} at {file}:{line} {args}".format(
68164abe46fa4d3b030ae525b40afe1bffccda166aaJohnny Chen                num=i, addr=load_addr, mod=mods[i],
68264abe46fa4d3b030ae525b40afe1bffccda166aaJohnny Chen                func='%s [inlined]' % funcs[i] if frame.IsInlined() else funcs[i],
6837d4c7fecd679c157804577313203c5212cb59a5eJohnny Chen                file=files[i], line=lines[i],
6847d4c7fecd679c157804577313203c5212cb59a5eJohnny Chen                args=get_args_as_string(frame, showFuncName=False) if not frame.IsInlined() else '()')
685b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen
686b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen    if string_buffer:
687ed5f04ef51b18d6bedbc8589fa06544491977b9cJohnny Chen        return output.getvalue()
688b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen
689b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen
690318aaa0b4b593ec3e69c5962bddab10c47066c4fJohnny Chendef print_stacktraces(process, string_buffer = False):
691b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen    """Prints the stack traces of all the threads."""
692b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen
693ed5f04ef51b18d6bedbc8589fa06544491977b9cJohnny Chen    output = StringIO.StringIO() if string_buffer else sys.stdout
694b51d87d4b31ca2bf024633d03aeeba8e095745e3Johnny Chen
6950a19a1b9c25117854f226256805239d95153ed2dGreg Clayton    print >> output, "Stack traces for " + str(process)
6961605cf6d06d95bfe381693ced84a216899ecac6fJohnny Chen
697311b1d69ef5cde8f70a1528f8c2d3b8e28c3d090Johnny Chen    for thread in process:
698311b1d69ef5cde8f70a1528f8c2d3b8e28c3d090Johnny Chen        print >> output, print_stacktrace(thread, string_buffer=True)
69930425e9677342cff9995cd4937fdc12354b6b24bJohnny Chen
70030425e9677342cff9995cd4937fdc12354b6b24bJohnny Chen    if string_buffer:
701ed5f04ef51b18d6bedbc8589fa06544491977b9cJohnny Chen        return output.getvalue()
702185e2c103c2af449262046495b3f8d1640794543Johnny Chen
703185e2c103c2af449262046495b3f8d1640794543Johnny Chen# ===================================
704185e2c103c2af449262046495b3f8d1640794543Johnny Chen# Utility functions related to Frames
705185e2c103c2af449262046495b3f8d1640794543Johnny Chen# ===================================
706185e2c103c2af449262046495b3f8d1640794543Johnny Chen
707abb3b2d796da9e081cd545b710d23c514489f895Johnny Chendef get_parent_frame(frame):
708abb3b2d796da9e081cd545b710d23c514489f895Johnny Chen    """
709abb3b2d796da9e081cd545b710d23c514489f895Johnny Chen    Returns the parent frame of the input frame object; None if not available.
710abb3b2d796da9e081cd545b710d23c514489f895Johnny Chen    """
711abb3b2d796da9e081cd545b710d23c514489f895Johnny Chen    thread = frame.GetThread()
712abb3b2d796da9e081cd545b710d23c514489f895Johnny Chen    parent_found = False
713abb3b2d796da9e081cd545b710d23c514489f895Johnny Chen    for f in thread:
714abb3b2d796da9e081cd545b710d23c514489f895Johnny Chen        if parent_found:
715abb3b2d796da9e081cd545b710d23c514489f895Johnny Chen            return f
716abb3b2d796da9e081cd545b710d23c514489f895Johnny Chen        if f.GetFrameID() == frame.GetFrameID():
717abb3b2d796da9e081cd545b710d23c514489f895Johnny Chen            parent_found = True
718abb3b2d796da9e081cd545b710d23c514489f895Johnny Chen
719abb3b2d796da9e081cd545b710d23c514489f895Johnny Chen    # If we reach here, no parent has been found, return None.
720abb3b2d796da9e081cd545b710d23c514489f895Johnny Chen    return None
721abb3b2d796da9e081cd545b710d23c514489f895Johnny Chen
72249f3d81ab49270d85d1637797572a3bc38cce1d9Johnny Chendef get_args_as_string(frame, showFuncName=True):
723abb3b2d796da9e081cd545b710d23c514489f895Johnny Chen    """
724abb3b2d796da9e081cd545b710d23c514489f895Johnny Chen    Returns the args of the input frame object as a string.
725abb3b2d796da9e081cd545b710d23c514489f895Johnny Chen    """
726abb3b2d796da9e081cd545b710d23c514489f895Johnny Chen    # arguments     => True
727abb3b2d796da9e081cd545b710d23c514489f895Johnny Chen    # locals        => False
728abb3b2d796da9e081cd545b710d23c514489f895Johnny Chen    # statics       => False
729abb3b2d796da9e081cd545b710d23c514489f895Johnny Chen    # in_scope_only => True
730abb3b2d796da9e081cd545b710d23c514489f895Johnny Chen    vars = frame.GetVariables(True, False, False, True) # type of SBValueList
731abb3b2d796da9e081cd545b710d23c514489f895Johnny Chen    args = [] # list of strings
732abb3b2d796da9e081cd545b710d23c514489f895Johnny Chen    for var in vars:
733abb3b2d796da9e081cd545b710d23c514489f895Johnny Chen        args.append("(%s)%s=%s" % (var.GetTypeName(),
734abb3b2d796da9e081cd545b710d23c514489f895Johnny Chen                                   var.GetName(),
7350fb0bcc9d4e951145e1b8c783652224c09b23af4Greg Clayton                                   var.GetValue()))
736960ce1206dbe268c7f3142fcf279e6392a852024Johnny Chen    if frame.GetFunction():
737bbc18b63544b1d81b5ea9d58c7e0672b07dd369bJohnny Chen        name = frame.GetFunction().GetName()
738960ce1206dbe268c7f3142fcf279e6392a852024Johnny Chen    elif frame.GetSymbol():
739bbc18b63544b1d81b5ea9d58c7e0672b07dd369bJohnny Chen        name = frame.GetSymbol().GetName()
740bbc18b63544b1d81b5ea9d58c7e0672b07dd369bJohnny Chen    else:
741bbc18b63544b1d81b5ea9d58c7e0672b07dd369bJohnny Chen        name = ""
74249f3d81ab49270d85d1637797572a3bc38cce1d9Johnny Chen    if showFuncName:
74349f3d81ab49270d85d1637797572a3bc38cce1d9Johnny Chen        return "%s(%s)" % (name, ", ".join(args))
74449f3d81ab49270d85d1637797572a3bc38cce1d9Johnny Chen    else:
74549f3d81ab49270d85d1637797572a3bc38cce1d9Johnny Chen        return "(%s)" % (", ".join(args))
74649f3d81ab49270d85d1637797572a3bc38cce1d9Johnny Chen
747185e2c103c2af449262046495b3f8d1640794543Johnny Chendef print_registers(frame, string_buffer = False):
748b299877fa8e5e94f9f86da47583bc2d3b85a41f5Johnny Chen    """Prints all the register sets of the frame."""
749185e2c103c2af449262046495b3f8d1640794543Johnny Chen
750185e2c103c2af449262046495b3f8d1640794543Johnny Chen    output = StringIO.StringIO() if string_buffer else sys.stdout
751185e2c103c2af449262046495b3f8d1640794543Johnny Chen
7520a19a1b9c25117854f226256805239d95153ed2dGreg Clayton    print >> output, "Register sets for " + str(frame)
753185e2c103c2af449262046495b3f8d1640794543Johnny Chen
754728255bc323e93a36644a4cdf225192c34c8472cJohnny Chen    registerSet = frame.GetRegisters() # Return type of SBValueList.
755728255bc323e93a36644a4cdf225192c34c8472cJohnny Chen    print >> output, "Frame registers (size of register set = %d):" % registerSet.GetSize()
756728255bc323e93a36644a4cdf225192c34c8472cJohnny Chen    for value in registerSet:
757185e2c103c2af449262046495b3f8d1640794543Johnny Chen        #print >> output, value
758185e2c103c2af449262046495b3f8d1640794543Johnny Chen        print >> output, "%s (number of children = %d):" % (value.GetName(), value.GetNumChildren())
759185e2c103c2af449262046495b3f8d1640794543Johnny Chen        for child in value:
7600fb0bcc9d4e951145e1b8c783652224c09b23af4Greg Clayton            print >> output, "Name: %s, Value: %s" % (child.GetName(), child.GetValue())
761185e2c103c2af449262046495b3f8d1640794543Johnny Chen
762185e2c103c2af449262046495b3f8d1640794543Johnny Chen    if string_buffer:
763185e2c103c2af449262046495b3f8d1640794543Johnny Chen        return output.getvalue()
764728255bc323e93a36644a4cdf225192c34c8472cJohnny Chen
765728255bc323e93a36644a4cdf225192c34c8472cJohnny Chendef get_registers(frame, kind):
766728255bc323e93a36644a4cdf225192c34c8472cJohnny Chen    """Returns the registers given the frame and the kind of registers desired.
767728255bc323e93a36644a4cdf225192c34c8472cJohnny Chen
768728255bc323e93a36644a4cdf225192c34c8472cJohnny Chen    Returns None if there's no such kind.
769728255bc323e93a36644a4cdf225192c34c8472cJohnny Chen    """
770728255bc323e93a36644a4cdf225192c34c8472cJohnny Chen    registerSet = frame.GetRegisters() # Return type of SBValueList.
771728255bc323e93a36644a4cdf225192c34c8472cJohnny Chen    for value in registerSet:
772728255bc323e93a36644a4cdf225192c34c8472cJohnny Chen        if kind.lower() in value.GetName().lower():
773728255bc323e93a36644a4cdf225192c34c8472cJohnny Chen            return value
774728255bc323e93a36644a4cdf225192c34c8472cJohnny Chen
775728255bc323e93a36644a4cdf225192c34c8472cJohnny Chen    return None
776728255bc323e93a36644a4cdf225192c34c8472cJohnny Chen
777728255bc323e93a36644a4cdf225192c34c8472cJohnny Chendef get_GPRs(frame):
778728255bc323e93a36644a4cdf225192c34c8472cJohnny Chen    """Returns the general purpose registers of the frame as an SBValue.
779728255bc323e93a36644a4cdf225192c34c8472cJohnny Chen
780fd1175c5d3152beb6fdee4b3b2ba3461b1ae1e0cJohnny Chen    The returned SBValue object is iterable.  An example:
781fd1175c5d3152beb6fdee4b3b2ba3461b1ae1e0cJohnny Chen        ...
782fd1175c5d3152beb6fdee4b3b2ba3461b1ae1e0cJohnny Chen        from lldbutil import get_GPRs
783fd1175c5d3152beb6fdee4b3b2ba3461b1ae1e0cJohnny Chen        regs = get_GPRs(frame)
784fd1175c5d3152beb6fdee4b3b2ba3461b1ae1e0cJohnny Chen        for reg in regs:
785fd1175c5d3152beb6fdee4b3b2ba3461b1ae1e0cJohnny Chen            print "%s => %s" % (reg.GetName(), reg.GetValue())
786fd1175c5d3152beb6fdee4b3b2ba3461b1ae1e0cJohnny Chen        ...
787728255bc323e93a36644a4cdf225192c34c8472cJohnny Chen    """
788728255bc323e93a36644a4cdf225192c34c8472cJohnny Chen    return get_registers(frame, "general purpose")
789728255bc323e93a36644a4cdf225192c34c8472cJohnny Chen
790728255bc323e93a36644a4cdf225192c34c8472cJohnny Chendef get_FPRs(frame):
791728255bc323e93a36644a4cdf225192c34c8472cJohnny Chen    """Returns the floating point registers of the frame as an SBValue.
792728255bc323e93a36644a4cdf225192c34c8472cJohnny Chen
793fd1175c5d3152beb6fdee4b3b2ba3461b1ae1e0cJohnny Chen    The returned SBValue object is iterable.  An example:
794fd1175c5d3152beb6fdee4b3b2ba3461b1ae1e0cJohnny Chen        ...
795fd1175c5d3152beb6fdee4b3b2ba3461b1ae1e0cJohnny Chen        from lldbutil import get_FPRs
796fd1175c5d3152beb6fdee4b3b2ba3461b1ae1e0cJohnny Chen        regs = get_FPRs(frame)
797fd1175c5d3152beb6fdee4b3b2ba3461b1ae1e0cJohnny Chen        for reg in regs:
798fd1175c5d3152beb6fdee4b3b2ba3461b1ae1e0cJohnny Chen            print "%s => %s" % (reg.GetName(), reg.GetValue())
799fd1175c5d3152beb6fdee4b3b2ba3461b1ae1e0cJohnny Chen        ...
800728255bc323e93a36644a4cdf225192c34c8472cJohnny Chen    """
801728255bc323e93a36644a4cdf225192c34c8472cJohnny Chen    return get_registers(frame, "floating point")
802728255bc323e93a36644a4cdf225192c34c8472cJohnny Chen
803728255bc323e93a36644a4cdf225192c34c8472cJohnny Chendef get_ESRs(frame):
804728255bc323e93a36644a4cdf225192c34c8472cJohnny Chen    """Returns the exception state registers of the frame as an SBValue.
805728255bc323e93a36644a4cdf225192c34c8472cJohnny Chen
806fd1175c5d3152beb6fdee4b3b2ba3461b1ae1e0cJohnny Chen    The returned SBValue object is iterable.  An example:
807fd1175c5d3152beb6fdee4b3b2ba3461b1ae1e0cJohnny Chen        ...
808fd1175c5d3152beb6fdee4b3b2ba3461b1ae1e0cJohnny Chen        from lldbutil import get_ESRs
809fd1175c5d3152beb6fdee4b3b2ba3461b1ae1e0cJohnny Chen        regs = get_ESRs(frame)
810fd1175c5d3152beb6fdee4b3b2ba3461b1ae1e0cJohnny Chen        for reg in regs:
811fd1175c5d3152beb6fdee4b3b2ba3461b1ae1e0cJohnny Chen            print "%s => %s" % (reg.GetName(), reg.GetValue())
812fd1175c5d3152beb6fdee4b3b2ba3461b1ae1e0cJohnny Chen        ...
813728255bc323e93a36644a4cdf225192c34c8472cJohnny Chen    """
814728255bc323e93a36644a4cdf225192c34c8472cJohnny Chen    return get_registers(frame, "exception state")
815084fd8945b922818e069adfb72ac39936466e221Johnny Chen
8168c06276d9d97d969f2c0c4dc0b7d25eb693d8e74Johnny Chen# ======================================
8178c06276d9d97d969f2c0c4dc0b7d25eb693d8e74Johnny Chen# Utility classes/functions for SBValues
8188c06276d9d97d969f2c0c4dc0b7d25eb693d8e74Johnny Chen# ======================================
819084fd8945b922818e069adfb72ac39936466e221Johnny Chen
820084fd8945b922818e069adfb72ac39936466e221Johnny Chenclass BasicFormatter(object):
821638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen    """The basic formatter inspects the value object and prints the value."""
822084fd8945b922818e069adfb72ac39936466e221Johnny Chen    def format(self, value, buffer=None, indent=0):
823084fd8945b922818e069adfb72ac39936466e221Johnny Chen        if not buffer:
824084fd8945b922818e069adfb72ac39936466e221Johnny Chen            output = StringIO.StringIO()
825084fd8945b922818e069adfb72ac39936466e221Johnny Chen        else:
826084fd8945b922818e069adfb72ac39936466e221Johnny Chen            output = buffer
827638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen        # If there is a summary, it suffices.
828638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen        val = value.GetSummary()
829638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen        # Otherwise, get the value.
830638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen        if val == None:
831638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen            val = value.GetValue()
832638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen        if val == None and value.GetNumChildren() > 0:
833638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen            val = "%s (location)" % value.GetLocation()
834638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen        print >> output, "{indentation}({type}) {name} = {value}".format(
835084fd8945b922818e069adfb72ac39936466e221Johnny Chen            indentation = ' ' * indent,
836084fd8945b922818e069adfb72ac39936466e221Johnny Chen            type = value.GetTypeName(),
837084fd8945b922818e069adfb72ac39936466e221Johnny Chen            name = value.GetName(),
838638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen            value = val)
839084fd8945b922818e069adfb72ac39936466e221Johnny Chen        return output.getvalue()
840084fd8945b922818e069adfb72ac39936466e221Johnny Chen
841084fd8945b922818e069adfb72ac39936466e221Johnny Chenclass ChildVisitingFormatter(BasicFormatter):
842638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen    """The child visiting formatter prints the value and its immediate children.
843638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen
844638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen    The constructor takes a keyword arg: indent_child, which defaults to 2.
845638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen    """
846638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen    def __init__(self, indent_child=2):
847638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen        """Default indentation of 2 SPC's for the children."""
848638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen        self.cindent = indent_child
849084fd8945b922818e069adfb72ac39936466e221Johnny Chen    def format(self, value, buffer=None):
850084fd8945b922818e069adfb72ac39936466e221Johnny Chen        if not buffer:
851084fd8945b922818e069adfb72ac39936466e221Johnny Chen            output = StringIO.StringIO()
852084fd8945b922818e069adfb72ac39936466e221Johnny Chen        else:
853084fd8945b922818e069adfb72ac39936466e221Johnny Chen            output = buffer
854084fd8945b922818e069adfb72ac39936466e221Johnny Chen
855084fd8945b922818e069adfb72ac39936466e221Johnny Chen        BasicFormatter.format(self, value, buffer=output)
856084fd8945b922818e069adfb72ac39936466e221Johnny Chen        for child in value:
857638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen            BasicFormatter.format(self, child, buffer=output, indent=self.cindent)
858638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen
859638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen        return output.getvalue()
860638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen
861638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chenclass RecursiveDecentFormatter(BasicFormatter):
862638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen    """The recursive decent formatter prints the value and the decendents.
863638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen
864638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen    The constructor takes two keyword args: indent_level, which defaults to 0,
865638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen    and indent_child, which defaults to 2.  The current indentation level is
866638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen    determined by indent_level, while the immediate children has an additional
867638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen    indentation by inden_child.
868638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen    """
869638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen    def __init__(self, indent_level=0, indent_child=2):
870638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen        self.lindent = indent_level
871638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen        self.cindent = indent_child
872638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen    def format(self, value, buffer=None):
873638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen        if not buffer:
874638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen            output = StringIO.StringIO()
875638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen        else:
876638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen            output = buffer
877638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen
878638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen        BasicFormatter.format(self, value, buffer=output, indent=self.lindent)
879638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen        new_indent = self.lindent + self.cindent
880638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen        for child in value:
881638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen            if child.GetSummary() != None:
882638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen                BasicFormatter.format(self, child, buffer=output, indent=new_indent)
883638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen            else:
884638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen                if child.GetNumChildren() > 0:
885638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen                    rdf = RecursiveDecentFormatter(indent_level=new_indent)
886638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen                    rdf.format(child, buffer=output)
887638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen                else:
888638ebcfea6328816ba5e9fd21e40cf5d3f060e2eJohnny Chen                    BasicFormatter.format(self, child, buffer=output, indent=new_indent)
889084fd8945b922818e069adfb72ac39936466e221Johnny Chen
890084fd8945b922818e069adfb72ac39936466e221Johnny Chen        return output.getvalue()
891