Add a utility function smart_iter() which has knowledge of the getsize and the getelem

method names of all the lldb container objects and returns an iterator object when
passed an eligible lldb container object.

Example:

    from lldb_util import smart_iter
    for thread in smart_iter(process):
        ID = thread.GetThreadID()
        if thread.GetStopReason() == lldb.eStopReasonBreakpoint:
            stopped_due_to_breakpoint = True
        for frame in smart_iter(thread):
            self.assertTrue(frame.GetThread().GetThreadID() == ID)
        ...

Add a test case for lldb.smart_iter().

llvm-svn: 130332
This commit is contained in:
Johnny Chen 2011-04-27 21:44:09 +00:00
parent 3989776770
commit b2e1a5c998
2 changed files with 81 additions and 2 deletions

View File

@ -56,11 +56,55 @@ def lldb_iter(obj, getsize, getelem):
name = symbol.GetName()
...
"""
#import traceback
#traceback.print_stack()
size = getattr(obj, getsize)
elem = getattr(obj, getelem)
for i in range(size()):
yield elem(i)
def smart_iter(obj):
"""Returns an iterator for eligible lldb objects, or None otherwise.
An example of eligible lldb container object is SBModule, which contains
SBSymbols. While SBTarget contains SBModules and SBBreakpoints, because it
is ambiguous which containee type to iterate on, the best we can do is to
return None. API clients can use lldb_iter() to clarify their intentions.
SBSymbol does not have the notion of containee objects and is not eligible
for smart iterator.
Example usage:
from lldb_util import smart_iter
for thread in smart_iter(process):
ID = thread.GetThreadID()
if thread.GetStopReason() == lldb.eStopReasonBreakpoint:
stopped_due_to_breakpoint = True
for frame in smart_iter(thread):
self.assertTrue(frame.GetThread().GetThreadID() == ID)
...
"""
d = { lldb.SBBreakpoint: ('GetNumLocations', 'GetLocationAtIndex'),
lldb.SBCompileUnit: ('GetNumLineEntries', 'GetLineEntryAtIndex'),
lldb.SBDebugger: ('GetNumTargets', 'GetTargetAtIndex'),
lldb.SBModule: ('GetNumSymbols', 'GetSymbolAtIndex'),
lldb.SBProcess: ('GetNumThreads', 'GetThreadAtIndex'),
lldb.SBThread: ('GetNumFrames', 'GetFrameAtIndex'),
lldb.SBInstructionList: ('GetSize', 'GetInstructionAtIndex'),
lldb.SBStringList: ('GetSize', 'GetStringAtIndex',),
lldb.SBSymbolContextList: ('GetSize', 'GetContextAtIndex'),
lldb.SBValueList: ('GetSize', 'GetValueAtIndex'),
lldb.SBType: ('GetNumberChildren', 'GetChildAtIndex'),
lldb.SBValue: ('GetNumChildren', 'GetChildAtIndex')
}
if obj.__class__ in d:
val = d.get(obj.__class__)
return lldb_iter(obj, val[0], val[1])
else:
return None
# ===================================================
# Disassembly for an SBFunction or an SBSymbol object

View File

@ -1,6 +1,6 @@
"""
Test lldbutil.lldb_iter() which returns an iterator object for lldb's aggregate
data structures.
Test lldb_iter/smart_iter() which returns an iterator object for lldb container
objects.
"""
import os, time
@ -30,6 +30,11 @@ class LLDBIteratorTestCase(TestBase):
self.buildDefault()
self.lldb_iter_2()
def test_smart_iter_1(self):
"""Test smart_iter works correctly for SBProcess->SBThread->SBFrame."""
self.buildDefault()
self.smart_iter_1()
def lldb_iter_1(self):
exe = os.path.join(os.getcwd(), "a.out")
@ -91,6 +96,36 @@ class LLDBIteratorTestCase(TestBase):
self.assertTrue(yours[i].GetID() == mine[i].GetID(),
"ID of yours[{0}] and mine[{0}] matches".format(i))
def smart_iter_1(self):
exe = os.path.join(os.getcwd(), "a.out")
target = self.dbg.CreateTarget(exe)
self.assertTrue(target.IsValid(), VALID_TARGET)
breakpoint = target.BreakpointCreateByLocation("main.cpp", self.line1)
self.assertTrue(breakpoint.IsValid(), VALID_BREAKPOINT)
# Now launch the process, and do not stop at entry point.
rc = lldb.SBError()
self.process = target.Launch (self.dbg.GetListener(), None, None, os.ctermid(), os.ctermid(), os.ctermid(), None, 0, False, rc)
if not rc.Success() or not self.process.IsValid():
self.fail("SBTarget.LaunchProcess() failed")
from lldbutil import smart_iter, print_stacktrace
stopped_due_to_breakpoint = False
for thread in smart_iter(self.process):
if self.TraceOn():
print_stacktrace(thread)
ID = thread.GetThreadID()
if thread.GetStopReason() == lldb.eStopReasonBreakpoint:
stopped_due_to_breakpoint = True
for frame in smart_iter(thread):
self.assertTrue(frame.GetThread().GetThreadID() == ID)
if self.TraceOn():
print frame
self.assertTrue(stopped_due_to_breakpoint)
if __name__ == '__main__':
import atexit