[lldb] Format Python files in scripts and utils (#66053)

Using:
black --exclude "third_party/" ./lldb/
This commit is contained in:
David Spickett 2023-09-14 08:54:02 +01:00 committed by GitHub
parent a1ef5a9437
commit 602e47c5f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 751 additions and 610 deletions

View File

@ -10,12 +10,21 @@ from collections import defaultdict
from use_lldb_suite import lldb_root
parser = argparse.ArgumentParser(
description='Analyze LLDB project #include dependencies.')
parser.add_argument('--show-counts', default=False, action='store_true',
help='When true, show the number of dependencies from each subproject')
parser.add_argument('--discover-cycles', default=False, action='store_true',
help='When true, find and display all project dependency cycles. Note,'
'this option is very slow')
description="Analyze LLDB project #include dependencies."
)
parser.add_argument(
"--show-counts",
default=False,
action="store_true",
help="When true, show the number of dependencies from each subproject",
)
parser.add_argument(
"--discover-cycles",
default=False,
action="store_true",
help="When true, find and display all project dependency cycles. Note,"
"this option is very slow",
)
args = parser.parse_args()
@ -24,12 +33,14 @@ inc_dir = os.path.join(lldb_root, "include")
src_map = {}
include_regex = re.compile('#include \"((lldb|Plugins|clang)(.*/)+).*\"')
include_regex = re.compile('#include "((lldb|Plugins|clang)(.*/)+).*"')
def is_sublist(small, big):
it = iter(big)
return all(c in it for c in small)
def normalize_host(str):
if str.startswith("lldb/Host"):
return "lldb/Host"
@ -39,6 +50,7 @@ def normalize_host(str):
return str.replace("lldb/../../source", "lldb")
return str
def scan_deps(this_dir, file):
global src_map
deps = {}
@ -62,7 +74,8 @@ def scan_deps(this_dir, file):
if this_dir not in src_map and len(deps) > 0:
src_map[this_dir] = deps
for (base, dirs, files) in os.walk(inc_dir):
for base, dirs, files in os.walk(inc_dir):
dir = os.path.basename(base)
relative = os.path.relpath(base, inc_dir)
inc_files = [x for x in files if os.path.splitext(x)[1] in [".h"]]
@ -71,7 +84,7 @@ for (base, dirs, files) in os.walk(inc_dir):
inc_path = os.path.join(base, inc)
scan_deps(relative, inc_path)
for (base, dirs, files) in os.walk(src_dir):
for base, dirs, files in os.walk(src_dir):
dir = os.path.basename(base)
relative = os.path.relpath(base, src_dir)
src_files = [x for x in files if os.path.splitext(x)[1] in [".cpp", ".h", ".mm"]]
@ -82,6 +95,7 @@ for (base, dirs, files) in os.walk(src_dir):
scan_deps(norm_base_path, src_path)
pass
def is_existing_cycle(path, cycles):
# If we have a cycle like # A -> B -> C (with an implicit -> A at the end)
# then we don't just want to check for an occurrence of A -> B -> C in the
@ -90,12 +104,13 @@ def is_existing_cycle(path, cycles):
# at the end), then A -> B -> C is also a cycle. This is an important
# optimization which reduces the search space by multiple orders of
# magnitude.
for i in range(0,len(path)):
for i in range(0, len(path)):
if any(is_sublist(x, path) for x in cycles):
return True
path = [path[-1]] + path[0:-1]
return False
def expand(path_queue, path_lengths, cycles, src_map):
# We do a breadth first search, to make sure we visit all paths in order
# of ascending length. This is an important optimization to make sure that
@ -127,54 +142,57 @@ def expand(path_queue, path_lengths, cycles, src_map):
path_queue.append(cur_path + [item])
pass
cycles = []
path_queue = [[x] for x in iter(src_map)]
path_lens = [1] * len(path_queue)
items = list(src_map.items())
items.sort(key = lambda A : A[0])
items.sort(key=lambda A: A[0])
for (path, deps) in items:
for path, deps in items:
print(path + ":")
sorted_deps = list(deps.items())
if args.show_counts:
sorted_deps.sort(key = lambda A: (A[1], A[0]))
sorted_deps.sort(key=lambda A: (A[1], A[0]))
for dep in sorted_deps:
print("\t{} [{}]".format(dep[0], dep[1]))
else:
sorted_deps.sort(key = lambda A: A[0])
sorted_deps.sort(key=lambda A: A[0])
for dep in sorted_deps:
print("\t{}".format(dep[0]))
def iter_cycles(cycles):
global src_map
for cycle in cycles:
cycle.append(cycle[0])
zipper = list(zip(cycle[0:-1], cycle[1:]))
result = [(x, src_map[x][y], y) for (x,y) in zipper]
result = [(x, src_map[x][y], y) for (x, y) in zipper]
total = 0
smallest = result[0][1]
for (first, value, last) in result:
for first, value, last in result:
total += value
smallest = min(smallest, value)
yield (total, smallest, result)
if args.discover_cycles:
print("Analyzing cycles...")
expand(path_queue, path_lens, cycles, src_map)
average = sum([len(x)+1 for x in cycles]) / len(cycles)
average = sum([len(x) + 1 for x in cycles]) / len(cycles)
print("Found {} cycles. Average cycle length = {}.".format(len(cycles), average))
counted = list(iter_cycles(cycles))
if args.show_counts:
counted.sort(key = lambda A: A[0])
for (total, smallest, cycle) in counted:
counted.sort(key=lambda A: A[0])
for total, smallest, cycle in counted:
sys.stdout.write("{} deps to break: ".format(total))
sys.stdout.write(cycle[0][0])
for (first, count, last) in cycle:
for first, count, last in cycle:
sys.stdout.write(" [{}->] {}".format(count, last))
sys.stdout.write("\n")
else:
@ -186,8 +204,8 @@ if args.discover_cycles:
islands = []
outgoing_counts = defaultdict(int)
incoming_counts = defaultdict(int)
for (total, smallest, cycle) in counted:
for (first, count, last) in cycle:
for total, smallest, cycle in counted:
for first, count, last in cycle:
outgoing_counts[first] += count
incoming_counts[last] += count
for cycle in cycles:
@ -201,8 +219,8 @@ if args.discover_cycles:
sorted = []
for node in island:
sorted.append((node, incoming_counts[node], outgoing_counts[node]))
sorted.sort(key = lambda x: x[1]+x[2])
for (node, inc, outg) in sorted:
sorted.sort(key=lambda x: x[1] + x[2])
for node, inc, outg in sorted:
print(" {} [{} in, {} out]".format(node, inc, outg))
sys.stdout.flush()
pass

View File

@ -20,45 +20,59 @@ def host_art_bt(debugger, command, result, internal_dict):
thread = process.GetSelectedThread()
while lldb_frame_index < thread.GetNumFrames():
frame = thread.GetFrameAtIndex(lldb_frame_index)
if frame.GetModule() and re.match(r'JIT\(.*?\)',
frame.GetModule().GetFileSpec().GetFilename()):
if frame.GetModule() and re.match(
r"JIT\(.*?\)", frame.GetModule().GetFileSpec().GetFilename()
):
# Compiled Java frame
# Get function/filename/lineno from symbol context
symbol = frame.GetSymbol()
if not symbol:
print('No symbol info for compiled Java frame: ', frame)
print("No symbol info for compiled Java frame: ", frame)
sys.exit(1)
line_entry = frame.GetLineEntry()
prettified_frames.append({
'function': symbol.GetName(),
'file': str(line_entry.GetFileSpec()) if line_entry else None,
'line': line_entry.GetLine() if line_entry else -1
})
prettified_frames.append(
{
"function": symbol.GetName(),
"file": str(line_entry.GetFileSpec()) if line_entry else None,
"line": line_entry.GetLine() if line_entry else -1,
}
)
# Skip art frames
while True:
art_stack_visitor = frame.EvaluateExpression(
"""struct GetStackVisitor : public StackVisitor { GetStackVisitor(int depth_) : StackVisitor(Thread::Current(), NULL), depth(depth_) {} bool VisitFrame() { if (cur_depth_ == depth) { return false; } else { return true; } } int depth; }; GetStackVisitor visitor(""" +
str(art_frame_index) +
"""); visitor.WalkStack(true); visitor""")
"""struct GetStackVisitor : public StackVisitor { GetStackVisitor(int depth_) : StackVisitor(Thread::Current(), NULL), depth(depth_) {} bool VisitFrame() { if (cur_depth_ == depth) { return false; } else { return true; } } int depth; }; GetStackVisitor visitor("""
+ str(art_frame_index)
+ """); visitor.WalkStack(true); visitor"""
)
art_method = frame.EvaluateExpression(
art_stack_visitor.GetName() + """.GetMethod()""")
art_stack_visitor.GetName() + """.GetMethod()"""
)
if art_method.GetValueAsUnsigned() != 0:
art_method_name = frame.EvaluateExpression(
"""art::PrettyMethod(""" + art_method.GetName() + """, true)""")
"""art::PrettyMethod(""" + art_method.GetName() + """, true)"""
)
art_method_name_data = frame.EvaluateExpression(
art_method_name.GetName() + """.c_str()""").GetValueAsUnsigned()
art_method_name.GetName() + """.c_str()"""
).GetValueAsUnsigned()
art_method_name_size = frame.EvaluateExpression(
art_method_name.GetName() + """.length()""").GetValueAsUnsigned()
art_method_name.GetName() + """.length()"""
).GetValueAsUnsigned()
error = lldb.SBError()
art_method_name = process.ReadCStringFromMemory(
art_method_name_data, art_method_name_size + 1, error)
art_method_name_data, art_method_name_size + 1, error
)
if not error.Success:
print('Failed to read method name')
print("Failed to read method name")
sys.exit(1)
if art_method_name != symbol.GetName():
print('Function names in native symbol and art runtime stack do not match: ', symbol.GetName(), ' != ', art_method_name)
print(
"Function names in native symbol and art runtime stack do not match: ",
symbol.GetName(),
" != ",
art_method_name,
)
art_frame_index = art_frame_index + 1
break
art_frame_index = art_frame_index + 1
@ -68,53 +82,69 @@ def host_art_bt(debugger, command, result, internal_dict):
if lldb_frame_index < thread.GetNumFrames():
frame = thread.GetFrameAtIndex(lldb_frame_index)
if frame.GetModule() and re.match(
r'JIT\(.*?\)', frame.GetModule().GetFileSpec().GetFilename()):
r"JIT\(.*?\)", frame.GetModule().GetFileSpec().GetFilename()
):
# Another compile Java frame
# Don't skip; leave it to the next iteration
continue
elif frame.GetSymbol() and (frame.GetSymbol().GetName() == 'art_quick_invoke_stub' or frame.GetSymbol().GetName() == 'art_quick_invoke_static_stub'):
elif frame.GetSymbol() and (
frame.GetSymbol().GetName() == "art_quick_invoke_stub"
or frame.GetSymbol().GetName() == "art_quick_invoke_static_stub"
):
# art_quick_invoke_stub / art_quick_invoke_static_stub
# Skip until we get past the next ArtMethod::Invoke()
while True:
lldb_frame_index = lldb_frame_index + 1
if lldb_frame_index >= thread.GetNumFrames():
print('ArtMethod::Invoke not found below art_quick_invoke_stub/art_quick_invoke_static_stub')
print(
"ArtMethod::Invoke not found below art_quick_invoke_stub/art_quick_invoke_static_stub"
)
sys.exit(1)
frame = thread.GetFrameAtIndex(lldb_frame_index)
if frame.GetSymbol() and frame.GetSymbol().GetName(
) == 'art::mirror::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)':
if (
frame.GetSymbol()
and frame.GetSymbol().GetName()
== "art::mirror::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)"
):
lldb_frame_index = lldb_frame_index + 1
break
else:
print('Invalid frame below compiled Java frame: ', frame)
elif frame.GetSymbol() and frame.GetSymbol().GetName() == 'art_quick_generic_jni_trampoline':
print("Invalid frame below compiled Java frame: ", frame)
elif (
frame.GetSymbol()
and frame.GetSymbol().GetName() == "art_quick_generic_jni_trampoline"
):
# Interpreted JNI frame for x86_64
# Skip art frames
while True:
art_stack_visitor = frame.EvaluateExpression(
"""struct GetStackVisitor : public StackVisitor { GetStackVisitor(int depth_) : StackVisitor(Thread::Current(), NULL), depth(depth_) {} bool VisitFrame() { if (cur_depth_ == depth) { return false; } else { return true; } } int depth; }; GetStackVisitor visitor(""" +
str(art_frame_index) +
"""); visitor.WalkStack(true); visitor""")
"""struct GetStackVisitor : public StackVisitor { GetStackVisitor(int depth_) : StackVisitor(Thread::Current(), NULL), depth(depth_) {} bool VisitFrame() { if (cur_depth_ == depth) { return false; } else { return true; } } int depth; }; GetStackVisitor visitor("""
+ str(art_frame_index)
+ """); visitor.WalkStack(true); visitor"""
)
art_method = frame.EvaluateExpression(
art_stack_visitor.GetName() + """.GetMethod()""")
art_stack_visitor.GetName() + """.GetMethod()"""
)
if art_method.GetValueAsUnsigned() != 0:
# Get function/filename/lineno from ART runtime
art_method_name = frame.EvaluateExpression(
"""art::PrettyMethod(""" + art_method.GetName() + """, true)""")
"""art::PrettyMethod(""" + art_method.GetName() + """, true)"""
)
art_method_name_data = frame.EvaluateExpression(
art_method_name.GetName() + """.c_str()""").GetValueAsUnsigned()
art_method_name.GetName() + """.c_str()"""
).GetValueAsUnsigned()
art_method_name_size = frame.EvaluateExpression(
art_method_name.GetName() + """.length()""").GetValueAsUnsigned()
art_method_name.GetName() + """.length()"""
).GetValueAsUnsigned()
error = lldb.SBError()
function = process.ReadCStringFromMemory(
art_method_name_data, art_method_name_size + 1, error)
art_method_name_data, art_method_name_size + 1, error
)
prettified_frames.append({
'function': function,
'file': None,
'line': -1
})
prettified_frames.append(
{"function": function, "file": None, "line": -1}
)
art_frame_index = art_frame_index + 1
break
@ -124,78 +154,98 @@ def host_art_bt(debugger, command, result, internal_dict):
lldb_frame_index = lldb_frame_index + 1
if lldb_frame_index < thread.GetNumFrames():
frame = thread.GetFrameAtIndex(lldb_frame_index)
if frame.GetSymbol() and (frame.GetSymbol().GetName() ==
'art_quick_invoke_stub' or frame.GetSymbol().GetName() == 'art_quick_invoke_static_stub'):
if frame.GetSymbol() and (
frame.GetSymbol().GetName() == "art_quick_invoke_stub"
or frame.GetSymbol().GetName() == "art_quick_invoke_static_stub"
):
# art_quick_invoke_stub / art_quick_invoke_static_stub
# Skip until we get past the next ArtMethod::Invoke()
while True:
lldb_frame_index = lldb_frame_index + 1
if lldb_frame_index >= thread.GetNumFrames():
print('ArtMethod::Invoke not found below art_quick_invoke_stub/art_quick_invoke_static_stub')
print(
"ArtMethod::Invoke not found below art_quick_invoke_stub/art_quick_invoke_static_stub"
)
sys.exit(1)
frame = thread.GetFrameAtIndex(lldb_frame_index)
if frame.GetSymbol() and frame.GetSymbol().GetName(
) == 'art::mirror::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)':
if (
frame.GetSymbol()
and frame.GetSymbol().GetName()
== "art::mirror::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)"
):
lldb_frame_index = lldb_frame_index + 1
break
else:
print('Invalid frame below compiled Java frame: ', frame)
elif frame.GetSymbol() and re.search(r'art::interpreter::', frame.GetSymbol().GetName()):
print("Invalid frame below compiled Java frame: ", frame)
elif frame.GetSymbol() and re.search(
r"art::interpreter::", frame.GetSymbol().GetName()
):
# Interpreted Java frame
while True:
lldb_frame_index = lldb_frame_index + 1
if lldb_frame_index >= thread.GetNumFrames():
print('art::interpreter::Execute not found in interpreter frame')
print("art::interpreter::Execute not found in interpreter frame")
sys.exit(1)
frame = thread.GetFrameAtIndex(lldb_frame_index)
if frame.GetSymbol() and frame.GetSymbol().GetName(
) == 'art::interpreter::Execute(art::Thread*, art::MethodHelper&, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue)':
if (
frame.GetSymbol()
and frame.GetSymbol().GetName()
== "art::interpreter::Execute(art::Thread*, art::MethodHelper&, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue)"
):
break
# Skip art frames
while True:
art_stack_visitor = frame.EvaluateExpression(
"""struct GetStackVisitor : public StackVisitor { GetStackVisitor(int depth_) : StackVisitor(Thread::Current(), NULL), depth(depth_) {} bool VisitFrame() { if (cur_depth_ == depth) { return false; } else { return true; } } int depth; }; GetStackVisitor visitor(""" +
str(art_frame_index) +
"""); visitor.WalkStack(true); visitor""")
"""struct GetStackVisitor : public StackVisitor { GetStackVisitor(int depth_) : StackVisitor(Thread::Current(), NULL), depth(depth_) {} bool VisitFrame() { if (cur_depth_ == depth) { return false; } else { return true; } } int depth; }; GetStackVisitor visitor("""
+ str(art_frame_index)
+ """); visitor.WalkStack(true); visitor"""
)
art_method = frame.EvaluateExpression(
art_stack_visitor.GetName() + """.GetMethod()""")
art_stack_visitor.GetName() + """.GetMethod()"""
)
if art_method.GetValueAsUnsigned() != 0:
# Get function/filename/lineno from ART runtime
art_method_name = frame.EvaluateExpression(
"""art::PrettyMethod(""" + art_method.GetName() + """, true)""")
"""art::PrettyMethod(""" + art_method.GetName() + """, true)"""
)
art_method_name_data = frame.EvaluateExpression(
art_method_name.GetName() + """.c_str()""").GetValueAsUnsigned()
art_method_name.GetName() + """.c_str()"""
).GetValueAsUnsigned()
art_method_name_size = frame.EvaluateExpression(
art_method_name.GetName() + """.length()""").GetValueAsUnsigned()
art_method_name.GetName() + """.length()"""
).GetValueAsUnsigned()
error = lldb.SBError()
function = process.ReadCStringFromMemory(
art_method_name_data, art_method_name_size + 1, error)
art_method_name_data, art_method_name_size + 1, error
)
line = frame.EvaluateExpression(
art_stack_visitor.GetName() +
""".GetMethod()->GetLineNumFromDexPC(""" +
art_stack_visitor.GetName() +
""".GetDexPc(true))""").GetValueAsUnsigned()
art_stack_visitor.GetName()
+ """.GetMethod()->GetLineNumFromDexPC("""
+ art_stack_visitor.GetName()
+ """.GetDexPc(true))"""
).GetValueAsUnsigned()
file_name = frame.EvaluateExpression(
art_method.GetName() + """->GetDeclaringClassSourceFile()""")
art_method.GetName() + """->GetDeclaringClassSourceFile()"""
)
file_name_data = file_name.GetValueAsUnsigned()
file_name_size = frame.EvaluateExpression(
"""(size_t)strlen(""" + file_name.GetName() + """)""").GetValueAsUnsigned()
"""(size_t)strlen(""" + file_name.GetName() + """)"""
).GetValueAsUnsigned()
error = lldb.SBError()
file_name = process.ReadCStringFromMemory(
file_name_data, file_name_size + 1, error)
file_name_data, file_name_size + 1, error
)
if not error.Success():
print('Failed to read source file name')
print("Failed to read source file name")
sys.exit(1)
prettified_frames.append({
'function': function,
'file': file_name,
'line': line
})
prettified_frames.append(
{"function": function, "file": file_name, "line": line}
)
art_frame_index = art_frame_index + 1
break
@ -205,11 +255,12 @@ def host_art_bt(debugger, command, result, internal_dict):
while True:
lldb_frame_index = lldb_frame_index + 1
if lldb_frame_index >= thread.GetNumFrames():
print('Can not get past interpreter native frames')
print("Can not get past interpreter native frames")
sys.exit(1)
frame = thread.GetFrameAtIndex(lldb_frame_index)
if frame.GetSymbol() and not re.search(
r'art::interpreter::', frame.GetSymbol().GetName()):
r"art::interpreter::", frame.GetSymbol().GetName()
):
break
else:
# Other frames. Add them as-is.
@ -218,20 +269,32 @@ def host_art_bt(debugger, command, result, internal_dict):
if frame.GetModule():
module_name = frame.GetModule().GetFileSpec().GetFilename()
if not module_name in [
'libartd.so',
'dalvikvm32',
'dalvikvm64',
'libc.so.6']:
prettified_frames.append({
'function': frame.GetSymbol().GetName() if frame.GetSymbol() else None,
'file': str(frame.GetLineEntry().GetFileSpec()) if frame.GetLineEntry() else None,
'line': frame.GetLineEntry().GetLine() if frame.GetLineEntry() else -1
})
"libartd.so",
"dalvikvm32",
"dalvikvm64",
"libc.so.6",
]:
prettified_frames.append(
{
"function": frame.GetSymbol().GetName()
if frame.GetSymbol()
else None,
"file": str(frame.GetLineEntry().GetFileSpec())
if frame.GetLineEntry()
else None,
"line": frame.GetLineEntry().GetLine()
if frame.GetLineEntry()
else -1,
}
)
for prettified_frame in prettified_frames:
print(prettified_frame['function'], prettified_frame['file'], prettified_frame['line'])
print(
prettified_frame["function"],
prettified_frame["file"],
prettified_frame["line"],
)
def __lldb_init_module(debugger, internal_dict):
debugger.HandleCommand(
'command script add -f host_art_bt.host_art_bt host_art_bt')
debugger.HandleCommand("command script add -f host_art_bt.host_art_bt host_art_bt")

View File

@ -30,122 +30,112 @@ import sys
def copy_one_file(dest_dir, source_dir, filename):
source_path = os.path.join(source_dir, filename)
dest_path = os.path.join(dest_dir, filename)
print('Copying file %s ==> %s...' % (source_path, dest_path))
print("Copying file %s ==> %s..." % (source_path, dest_path))
shutil.copyfile(source_path, dest_path)
def copy_named_files(
dest_dir,
source_dir,
files,
extensions,
copy_debug_suffix_also):
for (file, ext) in itertools.product(files, extensions):
copy_one_file(dest_dir, source_dir, file + '.' + ext)
def copy_named_files(dest_dir, source_dir, files, extensions, copy_debug_suffix_also):
for file, ext in itertools.product(files, extensions):
copy_one_file(dest_dir, source_dir, file + "." + ext)
if copy_debug_suffix_also:
copy_one_file(dest_dir, source_dir, file + '_d.' + ext)
copy_one_file(dest_dir, source_dir, file + "_d." + ext)
def copy_subdirectory(dest_dir, source_dir, subdir):
dest_dir = os.path.join(dest_dir, subdir)
source_dir = os.path.join(source_dir, subdir)
print('Copying directory %s ==> %s...' % (source_dir, dest_dir))
print("Copying directory %s ==> %s..." % (source_dir, dest_dir))
shutil.copytree(source_dir, dest_dir)
def copy_distro(dest_dir, dest_subdir, source_dir, source_prefix):
dest_dir = os.path.join(dest_dir, dest_subdir)
print('Copying distribution %s ==> %s' % (source_dir, dest_dir))
print("Copying distribution %s ==> %s" % (source_dir, dest_dir))
os.mkdir(dest_dir)
PCbuild_dir = os.path.join(source_dir, 'PCbuild')
PCbuild_dir = os.path.join(source_dir, "PCbuild")
if source_prefix:
PCbuild_dir = os.path.join(PCbuild_dir, source_prefix)
# First copy the files that go into the root of the new distribution. This
# includes the Python executables, python27(_d).dll, and relevant PDB
# files.
print('Copying Python executables...')
print("Copying Python executables...")
copy_named_files(dest_dir, PCbuild_dir, ["w9xpopen"], ["exe", "pdb"], False)
copy_named_files(dest_dir, PCbuild_dir, ["python_d", "pythonw_d"], ["exe"], False)
copy_named_files(
dest_dir, PCbuild_dir, ['w9xpopen'], [
'exe', 'pdb'], False)
copy_named_files(
dest_dir, PCbuild_dir, [
'python_d', 'pythonw_d'], ['exe'], False)
copy_named_files(
dest_dir, PCbuild_dir, [
'python', 'pythonw'], [
'exe', 'pdb'], False)
copy_named_files(dest_dir, PCbuild_dir, ['python27'], ['dll', 'pdb'], True)
dest_dir, PCbuild_dir, ["python", "pythonw"], ["exe", "pdb"], False
)
copy_named_files(dest_dir, PCbuild_dir, ["python27"], ["dll", "pdb"], True)
# Next copy everything in the Include directory.
print('Copying Python include directory')
copy_subdirectory(dest_dir, source_dir, 'Include')
print("Copying Python include directory")
copy_subdirectory(dest_dir, source_dir, "Include")
# Copy Lib folder (builtin Python modules)
print('Copying Python Lib directory')
copy_subdirectory(dest_dir, source_dir, 'Lib')
print("Copying Python Lib directory")
copy_subdirectory(dest_dir, source_dir, "Lib")
# Copy tools folder. These are probably not necessary, but we copy them anyway to
# match an official distribution as closely as possible. Note that we don't just copy
# the subdirectory recursively. The source distribution ships with many more tools
# than what you get by installing python regularly. We only copy the tools that appear
# in an installed distribution.
tools_dest_dir = os.path.join(dest_dir, 'Tools')
tools_source_dir = os.path.join(source_dir, 'Tools')
tools_dest_dir = os.path.join(dest_dir, "Tools")
tools_source_dir = os.path.join(source_dir, "Tools")
os.mkdir(tools_dest_dir)
copy_subdirectory(tools_dest_dir, tools_source_dir, 'i18n')
copy_subdirectory(tools_dest_dir, tools_source_dir, 'pynche')
copy_subdirectory(tools_dest_dir, tools_source_dir, 'scripts')
copy_subdirectory(tools_dest_dir, tools_source_dir, 'versioncheck')
copy_subdirectory(tools_dest_dir, tools_source_dir, 'webchecker')
copy_subdirectory(tools_dest_dir, tools_source_dir, "i18n")
copy_subdirectory(tools_dest_dir, tools_source_dir, "pynche")
copy_subdirectory(tools_dest_dir, tools_source_dir, "scripts")
copy_subdirectory(tools_dest_dir, tools_source_dir, "versioncheck")
copy_subdirectory(tools_dest_dir, tools_source_dir, "webchecker")
pyd_names = [
'_ctypes',
'_ctypes_test',
'_elementtree',
'_multiprocessing',
'_socket',
'_testcapi',
'pyexpat',
'select',
'unicodedata',
'winsound']
"_ctypes",
"_ctypes_test",
"_elementtree",
"_multiprocessing",
"_socket",
"_testcapi",
"pyexpat",
"select",
"unicodedata",
"winsound",
]
# Copy builtin extension modules (pyd files)
dlls_dir = os.path.join(dest_dir, 'DLLs')
dlls_dir = os.path.join(dest_dir, "DLLs")
os.mkdir(dlls_dir)
print('Copying DLLs directory')
copy_named_files(dlls_dir, PCbuild_dir, pyd_names, ['pyd', 'pdb'], True)
print("Copying DLLs directory")
copy_named_files(dlls_dir, PCbuild_dir, pyd_names, ["pyd", "pdb"], True)
# Copy libs folder (implibs for the pyd files)
libs_dir = os.path.join(dest_dir, 'libs')
libs_dir = os.path.join(dest_dir, "libs")
os.mkdir(libs_dir)
print('Copying libs directory')
copy_named_files(libs_dir, PCbuild_dir, pyd_names, ['lib'], False)
copy_named_files(libs_dir, PCbuild_dir, ['python27'], ['lib'], True)
print("Copying libs directory")
copy_named_files(libs_dir, PCbuild_dir, pyd_names, ["lib"], False)
copy_named_files(libs_dir, PCbuild_dir, ["python27"], ["lib"], True)
parser = argparse.ArgumentParser(
description='Install a custom Python distribution')
parser = argparse.ArgumentParser(description="Install a custom Python distribution")
parser.add_argument(
'--source',
required=True,
help='The root of the source tree where Python is built.')
"--source", required=True, help="The root of the source tree where Python is built."
)
parser.add_argument(
'--dest',
required=True,
help='The location to install the Python distributions.')
"--dest", required=True, help="The location to install the Python distributions."
)
parser.add_argument(
'--overwrite',
"--overwrite",
default=False,
action='store_true',
help='If the destination directory already exists, destroys its contents first.')
action="store_true",
help="If the destination directory already exists, destroys its contents first.",
)
parser.add_argument(
'--silent',
"--silent",
default=False,
action='store_true',
help='If --overwite was specified, suppress confirmation before deleting a directory tree.')
action="store_true",
help="If --overwite was specified, suppress confirmation before deleting a directory tree.",
)
args = parser.parse_args()
@ -153,23 +143,31 @@ args.source = os.path.normpath(args.source)
args.dest = os.path.normpath(args.dest)
if not os.path.exists(args.source):
print('The source directory %s does not exist. Exiting...')
print("The source directory %s does not exist. Exiting...")
sys.exit(1)
if os.path.exists(args.dest):
if not args.overwrite:
print('The destination directory \'%s\' already exists and --overwrite was not specified. Exiting...' % args.dest)
print(
"The destination directory '%s' already exists and --overwrite was not specified. Exiting..."
% args.dest
)
sys.exit(1)
while not args.silent:
print('Ok to recursively delete \'%s\' and all contents (Y/N)? Choosing Y will permanently delete the contents.' % args.dest)
print(
"Ok to recursively delete '%s' and all contents (Y/N)? Choosing Y will permanently delete the contents."
% args.dest
)
result = str.upper(sys.stdin.read(1))
if result == 'N':
print('Unable to copy files to the destination. The destination already exists.')
if result == "N":
print(
"Unable to copy files to the destination. The destination already exists."
)
sys.exit(1)
elif result == 'Y':
elif result == "Y":
break
shutil.rmtree(args.dest)
os.mkdir(args.dest)
copy_distro(args.dest, 'x86', args.source, None)
copy_distro(args.dest, 'x64', args.source, 'amd64')
copy_distro(args.dest, "x86", args.source, None)
copy_distro(args.dest, "x64", args.source, "amd64")

View File

@ -10,39 +10,39 @@ import subprocess
def run_reproducer(path):
proc = subprocess.Popen([LLDB, '--replay', path],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
proc = subprocess.Popen(
[LLDB, "--replay", path], stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
reason = None
try:
outs, errs = proc.communicate(timeout=TIMEOUT)
success = proc.returncode == 0
result = 'PASSED' if success else 'FAILED'
result = "PASSED" if success else "FAILED"
if not success:
outs = outs.decode()
errs = errs.decode()
# Do some pattern matching to find out the cause of the failure.
if 'Encountered unexpected packet during replay' in errs:
reason = 'Unexpected packet'
elif 'Assertion failed' in errs:
reason = 'Assertion failed'
elif 'UNREACHABLE' in errs:
reason = 'Unreachable executed'
elif 'Segmentation fault' in errs:
reason = 'Segmentation fault'
elif 'Illegal instruction' in errs:
reason = 'Illegal instruction'
if "Encountered unexpected packet during replay" in errs:
reason = "Unexpected packet"
elif "Assertion failed" in errs:
reason = "Assertion failed"
elif "UNREACHABLE" in errs:
reason = "Unreachable executed"
elif "Segmentation fault" in errs:
reason = "Segmentation fault"
elif "Illegal instruction" in errs:
reason = "Illegal instruction"
else:
reason = f'Exit code {proc.returncode}'
reason = f"Exit code {proc.returncode}"
except subprocess.TimeoutExpired:
proc.kill()
success = False
outs, errs = proc.communicate()
result = 'TIMEOUT'
result = "TIMEOUT"
if not FAILURE_ONLY or not success:
reason_str = f' ({reason})' if reason else ''
print(f'{result}: {path}{reason_str}')
reason_str = f" ({reason})" if reason else ""
print(f"{result}: {path}{reason_str}")
if VERBOSE:
if outs:
print(outs)
@ -54,49 +54,51 @@ def find_reproducers(path):
for root, dirs, files in os.walk(path):
for dir in dirs:
_, extension = os.path.splitext(dir)
if dir.startswith('Test') and extension == '.py':
if dir.startswith("Test") and extension == ".py":
yield os.path.join(root, dir)
if __name__ == '__main__':
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description='LLDB API Test Replay Driver. '
'Replay one or more reproducers in parallel using the specified LLDB driver. '
'The script will look for reproducers generated by the API lit test suite. '
'To generate the reproducers, pass --param \'lldb-run-with-repro=capture\' to lit.'
description="LLDB API Test Replay Driver. "
"Replay one or more reproducers in parallel using the specified LLDB driver. "
"The script will look for reproducers generated by the API lit test suite. "
"To generate the reproducers, pass --param 'lldb-run-with-repro=capture' to lit."
)
parser.add_argument(
'-j',
'--threads',
"-j",
"--threads",
type=int,
default=multiprocessing.cpu_count(),
help='Number of threads. The number of CPU threads if not specified.')
help="Number of threads. The number of CPU threads if not specified.",
)
parser.add_argument(
'-t',
'--timeout',
"-t",
"--timeout",
type=int,
default=60,
help='Replay timeout in seconds. 60 seconds if not specified.')
help="Replay timeout in seconds. 60 seconds if not specified.",
)
parser.add_argument(
'-p',
'--path',
"-p",
"--path",
type=str,
default=os.getcwd(),
help=
'Path to the directory containing the reproducers. The current working directory if not specified.'
help="Path to the directory containing the reproducers. The current working directory if not specified.",
)
parser.add_argument(
"-l",
"--lldb",
type=str,
required=True,
help="Path to the LLDB command line driver",
)
parser.add_argument(
"-v", "--verbose", help="Print replay output.", action="store_true"
)
parser.add_argument(
"--failure-only", help="Only log failures.", action="store_true"
)
parser.add_argument('-l',
'--lldb',
type=str,
required=True,
help='Path to the LLDB command line driver')
parser.add_argument('-v',
'--verbose',
help='Print replay output.',
action='store_true')
parser.add_argument('--failure-only',
help='Only log failures.',
action='store_true')
args = parser.parse_args()
global LLDB
@ -109,11 +111,11 @@ if __name__ == '__main__':
FAILURE_ONLY = args.failure_only
print(
f'Replaying reproducers in {args.path} with {args.threads} threads and a {args.timeout} seconds timeout'
f"Replaying reproducers in {args.path} with {args.threads} threads and a {args.timeout} seconds timeout"
)
try:
pool = Pool(args.threads)
pool.map(run_reproducer, find_reproducers(args.path))
except KeyboardInterrupt:
print('Interrupted')
print("Interrupted")

View File

@ -7,7 +7,7 @@ def find_lldb_root():
lldb_root = os.path.dirname(inspect.getfile(inspect.currentframe()))
while True:
parent = os.path.dirname(lldb_root)
if parent == lldb_root: # dirname('/') == '/'
if parent == lldb_root: # dirname('/') == '/'
raise Exception("use_lldb_suite_root.py not found")
lldb_root = parent
@ -15,8 +15,10 @@ def find_lldb_root():
if os.path.isfile(test_path):
return lldb_root
lldb_root = find_lldb_root()
import imp
fp, pathname, desc = imp.find_module("use_lldb_suite_root", [lldb_root])
try:
imp.load_module("use_lldb_suite_root", fp, pathname, desc)

View File

@ -10,58 +10,67 @@ import sys
def extract_exe_symbol_names(arch, exe_path, match_str):
command = 'dsymutil --arch %s -s "%s" | grep "%s" | colrm 1 69' % (
arch, exe_path, match_str)
arch,
exe_path,
match_str,
)
(command_exit_status, command_output) = subprocess.getstatusoutput(command)
if command_exit_status == 0:
if command_output:
return command_output[0:-1].split("'\n")
else:
print('error: command returned no output')
print("error: command returned no output")
else:
print('error: command failed with exit status %i\n command: %s' % (command_exit_status, command))
print(
"error: command failed with exit status %i\n command: %s"
% (command_exit_status, command)
)
return list()
def verify_api(all_args):
'''Verify the API in the specified library is valid given one or more binaries.'''
"""Verify the API in the specified library is valid given one or more binaries."""
usage = "usage: verify_api --library <path> [ --library <path> ...] executable1 [executable2 ...]"
description = '''Verify the API in the specified library is valid given one or more binaries.
description = """Verify the API in the specified library is valid given one or more binaries.
Example:
verify_api.py --library ~/Documents/src/lldb/build/Debug/LLDB.framework/LLDB --arch x86_64 /Applications/Xcode.app/Contents/PlugIns/DebuggerLLDB.ideplugin/Contents/MacOS/DebuggerLLDB --api-regex lldb
'''
"""
parser = optparse.OptionParser(
description=description,
prog='verify_api',
usage=usage)
description=description, prog="verify_api", usage=usage
)
parser.add_option(
'-v',
'--verbose',
action='store_true',
dest='verbose',
help='display verbose debug info',
default=False)
"-v",
"--verbose",
action="store_true",
dest="verbose",
help="display verbose debug info",
default=False,
)
parser.add_option(
'-a',
'--arch',
type='string',
action='append',
dest='archs',
help='architecture to use when checking the api')
"-a",
"--arch",
type="string",
action="append",
dest="archs",
help="architecture to use when checking the api",
)
parser.add_option(
'-r',
'--api-regex',
type='string',
dest='api_regex_str',
help='Exclude any undefined symbols that do not match this regular expression when searching for missing APIs.')
"-r",
"--api-regex",
type="string",
dest="api_regex_str",
help="Exclude any undefined symbols that do not match this regular expression when searching for missing APIs.",
)
parser.add_option(
'-l',
'--library',
type='string',
action='append',
dest='libraries',
help='Specify one or more libraries that will contain all needed APIs for the executables.')
"-l",
"--library",
type="string",
action="append",
dest="libraries",
help="Specify one or more libraries that will contain all needed APIs for the executables.",
)
(options, args) = parser.parse_args(all_args)
api_external_symbols = list()
@ -69,18 +78,19 @@ def verify_api(all_args):
for arch in options.archs:
for library in options.libraries:
external_symbols = extract_exe_symbol_names(
arch, library, "( SECT EXT)")
arch, library, "( SECT EXT)"
)
if external_symbols:
for external_symbol in external_symbols:
api_external_symbols.append(external_symbol)
else:
sys.exit(1)
else:
print('error: must specify one or more architectures with the --arch option')
print("error: must specify one or more architectures with the --arch option")
sys.exit(4)
if options.verbose:
print("API symbols:")
for (i, external_symbol) in enumerate(api_external_symbols):
for i, external_symbol in enumerate(api_external_symbols):
print("[%u] %s" % (i, external_symbol))
api_regex = None
@ -92,24 +102,29 @@ def verify_api(all_args):
print('Verifying (%s) "%s"...' % (arch, exe_path))
exe_errors = 0
undefined_symbols = extract_exe_symbol_names(
arch, exe_path, "( UNDF EXT)")
arch, exe_path, "( UNDF EXT)"
)
for undefined_symbol in undefined_symbols:
if api_regex:
match = api_regex.search(undefined_symbol)
if not match:
if options.verbose:
print('ignoring symbol: %s' % (undefined_symbol))
print("ignoring symbol: %s" % (undefined_symbol))
continue
if undefined_symbol in api_external_symbols:
if options.verbose:
print('verified symbol: %s' % (undefined_symbol))
print("verified symbol: %s" % (undefined_symbol))
else:
print('missing symbol: %s' % (undefined_symbol))
print("missing symbol: %s" % (undefined_symbol))
exe_errors += 1
if exe_errors:
print('error: missing %u API symbols from %s' % (exe_errors, options.libraries))
print(
"error: missing %u API symbols from %s"
% (exe_errors, options.libraries)
)
else:
print('success')
print("success")
if __name__ == '__main__':
if __name__ == "__main__":
verify_api(sys.argv[1:])

View File

@ -34,23 +34,27 @@ def main():
# Compute an MD5 hash based on the input arguments and the current working
# directory.
h = hashlib.md5()
h.update(' '.join(sys.argv[2:]).encode('utf-8'))
h.update(os.getcwd().encode('utf-8'))
h.update(" ".join(sys.argv[2:]).encode("utf-8"))
h.update(os.getcwd().encode("utf-8"))
input_hash = h.hexdigest()
# Use the hash to "uniquely" identify a reproducer path.
reproducer_path = os.path.join(tempfile.gettempdir(), input_hash)
# Create a new lldb invocation with capture or replay enabled.
lldb = os.path.join(os.path.dirname(sys.argv[0]), 'lldb')
lldb = os.path.join(os.path.dirname(sys.argv[0]), "lldb")
new_args = [lldb]
if sys.argv[1] == "replay":
new_args.extend(['--replay', reproducer_path])
new_args.extend(["--replay", reproducer_path])
elif sys.argv[1] == "capture":
new_args.extend([
'--capture', '--capture-path', reproducer_path,
'--reproducer-generate-on-exit'
])
new_args.extend(
[
"--capture",
"--capture-path",
reproducer_path,
"--reproducer-generate-on-exit",
]
)
new_args.extend(sys.argv[2:])
else:
help()
@ -60,10 +64,10 @@ def main():
# The driver always exists with a zero exit code during replay. Store the
# exit code and return that for tests that expect a non-zero exit code.
exit_code_path = os.path.join(reproducer_path, 'exit_code.txt')
exit_code_path = os.path.join(reproducer_path, "exit_code.txt")
if sys.argv[1] == "replay":
replay_exit_code = exit_code
with open(exit_code_path, 'r') as f:
with open(exit_code_path, "r") as f:
exit_code = int(f.read())
if replay_exit_code != 0:
print("error: replay failed with exit code {}".format(replay_exit_code))
@ -72,11 +76,11 @@ def main():
return 1 if (exit_code == 0) else 0
shutil.rmtree(reproducer_path, True)
elif sys.argv[1] == "capture":
with open(exit_code_path, 'w') as f:
f.write('%d' % exit_code)
with open(exit_code_path, "w") as f:
f.write("%d" % exit_code)
return exit_code
if __name__ == '__main__':
if __name__ == "__main__":
exit(main())

View File

@ -14,7 +14,6 @@ import re
class BreakWin(cui.ListWin):
def __init__(self, driver, x, y, w, h):
super(BreakWin, self).__init__(x, y, w, h)
self.driver = driver
@ -26,7 +25,7 @@ class BreakWin(cui.ListWin):
if lldb.SBBreakpoint.EventIsBreakpointEvent(event):
self.update()
if isinstance(event, int):
if event == ord('d'):
if event == ord("d"):
self.deleteSelected()
if event == curses.ascii.NL or event == curses.ascii.SP:
self.toggleSelected()
@ -72,14 +71,14 @@ class BreakWin(cui.ListWin):
continue
text = lldbutil.get_description(bp)
# FIXME: Use an API for this, not parsing the description.
match = re.search('SBBreakpoint: id = ([^,]+), (.*)', text)
match = re.search("SBBreakpoint: id = ([^,]+), (.*)", text)
try:
id = match.group(1)
desc = match.group(2).strip()
if bp.IsEnabled():
text = '%s: %s' % (id, desc)
text = "%s: %s" % (id, desc)
else:
text = '%s: (disabled) %s' % (id, desc)
text = "%s: (disabled) %s" % (id, desc)
except ValueError as e:
# bp unparsable
pass
@ -87,7 +86,8 @@ class BreakWin(cui.ListWin):
if self.showDetails.setdefault(bp.id, False):
for location in bp:
desc = lldbutil.get_description(
location, lldb.eDescriptionLevelFull)
text += '\n ' + desc
location, lldb.eDescriptionLevelFull
)
text += "\n " + desc
self.addItem(text)
self.setSelected(selected)

View File

@ -13,21 +13,20 @@ from itertools import islice
class History(object):
def __init__(self):
self.data = {}
self.pos = 0
self.tempEntry = ''
self.tempEntry = ""
def previous(self, curr):
if self.pos == len(self.data):
self.tempEntry = curr
if self.pos < 0:
return ''
return ""
if self.pos == 0:
self.pos -= 1
return ''
return ""
if self.pos > 0:
self.pos -= 1
return self.data[self.pos]
@ -38,13 +37,13 @@ class History(object):
if self.pos < len(self.data):
return self.data[self.pos]
elif self.tempEntry != '':
elif self.tempEntry != "":
return self.tempEntry
else:
return ''
return ""
def add(self, c):
self.tempEntry = ''
self.tempEntry = ""
self.pos = len(self.data)
if self.pos == 0 or self.data[self.pos - 1] != c:
self.data[self.pos] = c
@ -52,7 +51,6 @@ class History(object):
class CommandWin(cui.TitledWin):
def __init__(self, driver, x, y, w, h):
super(CommandWin, self).__init__(x, y, w, h, "Commands")
self.command = ""
@ -72,7 +70,8 @@ class CommandWin(cui.TitledWin):
matches = lldb.SBStringList()
commandinterpreter = self.getCommandInterpreter()
commandinterpreter.HandleCompletion(
self.data, self.el.index, 0, -1, matches)
self.data, self.el.index, 0, -1, matches
)
if matches.GetSize() == 2:
self.el.content += matches.GetStringAtIndex(0)
self.el.index = len(self.el.content)
@ -90,19 +89,17 @@ class CommandWin(cui.TitledWin):
self.startline = self.win.getmaxyx()[0] - 2
self.el = cui.CursesEditLine(
self.win,
self.history,
enterCallback,
tabCompleteCallback)
self.win, self.history, enterCallback, tabCompleteCallback
)
self.el.prompt = self.driver.getPrompt()
self.el.showPrompt(self.startline, 0)
def handleCommand(self, cmd):
# enter!
# enter!
self.win.scroll(1) # TODO: scroll more for longer commands
if cmd == '':
cmd = self.history.previous('')
elif cmd in ('q', 'quit'):
if cmd == "":
cmd = self.history.previous("")
elif cmd in ("q", "quit"):
self.driver.terminate()
return
@ -114,13 +111,13 @@ class CommandWin(cui.TitledWin):
else:
out = ret.GetError()
attr = curses.color_pair(3) # red on black
self.win.addstr(self.startline, 0, out + '\n', attr)
self.win.addstr(self.startline, 0, out + "\n", attr)
self.win.scroll(1)
self.el.showPrompt(self.startline, 0)
def handleEvent(self, event):
if isinstance(event, int):
if event == curses.ascii.EOT and self.el.content == '':
if event == curses.ascii.EOT and self.el.content == "":
# When the command is empty, treat CTRL-D as EOF.
self.driver.terminate()
return

View File

@ -12,7 +12,6 @@ import threading
class CursesWin(object):
def __init__(self, x, y, w, h):
self.win = curses.newwin(h, w, y, x)
self.focus = False
@ -34,11 +33,10 @@ class CursesWin(object):
class TextWin(CursesWin):
def __init__(self, x, y, w):
super(TextWin, self).__init__(x, y, w, 1)
self.win.bkgd(curses.color_pair(1))
self.text = ''
self.text = ""
self.reverse = False
def canFocus(self):
@ -48,8 +46,8 @@ class TextWin(CursesWin):
w = self.win.getmaxyx()[1]
text = self.text
if len(text) > w:
#trunc_length = len(text) - w
text = text[-w + 1:]
# trunc_length = len(text) - w
text = text[-w + 1 :]
if self.reverse:
self.win.addstr(0, 0, text, curses.A_REVERSE)
else:
@ -64,7 +62,6 @@ class TextWin(CursesWin):
class TitledWin(CursesWin):
def __init__(self, x, y, w, h, title):
super(TitledWin, self).__init__(x, y + 1, w, h - 1)
self.title = title
@ -82,7 +79,6 @@ class TitledWin(CursesWin):
class ListWin(CursesWin):
def __init__(self, x, y, w, h):
super(ListWin, self).__init__(x, y, w, h)
self.items = []
@ -101,10 +97,10 @@ class ListWin(CursesWin):
firstSelected = -1
lastSelected = -1
for i, item in enumerate(self.items):
lines = self.items[i].split('\n')
lines = lines if lines[len(lines) - 1] != '' else lines[:-1]
lines = self.items[i].split("\n")
lines = lines if lines[len(lines) - 1] != "" else lines[:-1]
if len(lines) == 0:
lines = ['']
lines = [""]
if i == self.getSelected():
firstSelected = len(allLines)
@ -127,7 +123,7 @@ class ListWin(CursesWin):
attr = curses.A_NORMAL
if i >= firstSelected and i <= lastSelected:
attr = curses.A_REVERSE
line = '{0:{width}}'.format(line, width=w - 1)
line = "{0:{width}}".format(line, width=w - 1)
# Ignore the error we get from drawing over the bottom-right char.
try:
@ -170,7 +166,6 @@ class ListWin(CursesWin):
class InputHandler(threading.Thread):
def __init__(self, screen, queue):
super(InputHandler, self).__init__()
self.screen = screen
@ -183,7 +178,7 @@ class InputHandler(threading.Thread):
class CursesUI(object):
""" Responsible for updating the console UI with curses. """
"""Responsible for updating the console UI with curses."""
def __init__(self, screen, event_queue):
self.screen = screen
@ -220,7 +215,6 @@ class CursesUI(object):
self.focusNext()
def eventLoop(self):
self.input_handler.start()
self.wins[self.focus].setFocus(True)
@ -247,7 +241,7 @@ class CursesUI(object):
class CursesEditLine(object):
""" Embed an 'editline'-compatible prompt inside a CursesWin. """
"""Embed an 'editline'-compatible prompt inside a CursesWin."""
def __init__(self, win, history, enterCallback, tabCompleteCallback):
self.win = win
@ -255,8 +249,8 @@ class CursesEditLine(object):
self.enterCallback = enterCallback
self.tabCompleteCallback = tabCompleteCallback
self.prompt = ''
self.content = ''
self.prompt = ""
self.content = ""
self.index = 0
self.startx = -1
self.starty = -1
@ -269,16 +263,16 @@ class CursesEditLine(object):
self.win.scroll(1)
self.starty -= 1
if self.starty < 0:
raise RuntimeError('Input too long; aborting')
raise RuntimeError("Input too long; aborting")
(y, x) = (self.starty, self.startx)
self.win.move(y, x)
self.win.clrtobot()
self.win.addstr(y, x, prompt)
remain = self.content
self.win.addstr(remain[:w - len(prompt)])
remain = remain[w - len(prompt):]
while remain != '':
self.win.addstr(remain[: w - len(prompt)])
remain = remain[w - len(prompt) :]
while remain != "":
y += 1
self.win.addstr(y, 0, remain[:w])
remain = remain[w:]
@ -287,7 +281,7 @@ class CursesEditLine(object):
self.win.move(self.starty + length / w, length % w)
def showPrompt(self, y, x, prompt=None):
self.content = ''
self.content = ""
self.index = 0
self.startx = x
self.starty = y
@ -299,26 +293,27 @@ class CursesEditLine(object):
key = event
if self.startx == -1:
raise RuntimeError('Trying to handle input without prompt')
raise RuntimeError("Trying to handle input without prompt")
if key == curses.ascii.NL:
self.enterCallback(self.content)
elif key == curses.ascii.TAB:
self.tabCompleteCallback(self.content)
elif curses.ascii.isprint(key):
self.content = self.content[:self.index] + \
chr(key) + self.content[self.index:]
self.content = (
self.content[: self.index] + chr(key) + self.content[self.index :]
)
self.index += 1
elif key == curses.KEY_BACKSPACE or key == curses.ascii.BS:
if self.index > 0:
self.index -= 1
self.content = self.content[
:self.index] + self.content[self.index + 1:]
self.content = (
self.content[: self.index] + self.content[self.index + 1 :]
)
elif key == curses.KEY_DC or key == curses.ascii.DEL or key == curses.ascii.EOT:
self.content = self.content[
:self.index] + self.content[self.index + 1:]
self.content = self.content[: self.index] + self.content[self.index + 1 :]
elif key == curses.ascii.VT: # CTRL-K
self.content = self.content[:self.index]
self.content = self.content[: self.index]
elif key == curses.KEY_LEFT or key == curses.ascii.STX: # left or CTRL-B
if self.index > 0:
self.index -= 1

View File

@ -14,7 +14,7 @@ from threading import Thread
class DebuggerDriver(Thread):
""" Drives the debugger and responds to events. """
"""Drives the debugger and responds to events."""
def __init__(self, debugger, event_queue):
Thread.__init__(self)
@ -31,41 +31,45 @@ class DebuggerDriver(Thread):
if not self.listener.IsValid():
raise "Invalid listener"
self.listener.StartListeningForEventClass(self.debugger,
lldb.SBTarget.GetBroadcasterClassName(),
lldb.SBTarget.eBroadcastBitBreakpointChanged
#| lldb.SBTarget.eBroadcastBitModuleLoaded
#| lldb.SBTarget.eBroadcastBitModuleUnloaded
| lldb.SBTarget.eBroadcastBitWatchpointChanged
#| lldb.SBTarget.eBroadcastBitSymbolLoaded
)
self.listener.StartListeningForEventClass(
self.debugger,
lldb.SBTarget.GetBroadcasterClassName(),
lldb.SBTarget.eBroadcastBitBreakpointChanged
# | lldb.SBTarget.eBroadcastBitModuleLoaded
# | lldb.SBTarget.eBroadcastBitModuleUnloaded
| lldb.SBTarget.eBroadcastBitWatchpointChanged
# | lldb.SBTarget.eBroadcastBitSymbolLoaded
)
self.listener.StartListeningForEventClass(self.debugger,
lldb.SBThread.GetBroadcasterClassName(),
lldb.SBThread.eBroadcastBitStackChanged
# lldb.SBThread.eBroadcastBitBreakpointChanged
| lldb.SBThread.eBroadcastBitThreadSuspended
| lldb.SBThread.eBroadcastBitThreadResumed
| lldb.SBThread.eBroadcastBitSelectedFrameChanged
| lldb.SBThread.eBroadcastBitThreadSelected
)
self.listener.StartListeningForEventClass(
self.debugger,
lldb.SBThread.GetBroadcasterClassName(),
lldb.SBThread.eBroadcastBitStackChanged
# lldb.SBThread.eBroadcastBitBreakpointChanged
| lldb.SBThread.eBroadcastBitThreadSuspended
| lldb.SBThread.eBroadcastBitThreadResumed
| lldb.SBThread.eBroadcastBitSelectedFrameChanged
| lldb.SBThread.eBroadcastBitThreadSelected,
)
self.listener.StartListeningForEventClass(self.debugger,
lldb.SBProcess.GetBroadcasterClassName(),
lldb.SBProcess.eBroadcastBitStateChanged
| lldb.SBProcess.eBroadcastBitInterrupt
| lldb.SBProcess.eBroadcastBitSTDOUT
| lldb.SBProcess.eBroadcastBitSTDERR
| lldb.SBProcess.eBroadcastBitProfileData
)
self.listener.StartListeningForEventClass(self.debugger,
lldb.SBCommandInterpreter.GetBroadcasterClass(),
lldb.SBCommandInterpreter.eBroadcastBitThreadShouldExit
| lldb.SBCommandInterpreter.eBroadcastBitResetPrompt
| lldb.SBCommandInterpreter.eBroadcastBitQuitCommandReceived
| lldb.SBCommandInterpreter.eBroadcastBitAsynchronousOutputData
| lldb.SBCommandInterpreter.eBroadcastBitAsynchronousErrorData
)
self.listener.StartListeningForEventClass(
self.debugger,
lldb.SBProcess.GetBroadcasterClassName(),
lldb.SBProcess.eBroadcastBitStateChanged
| lldb.SBProcess.eBroadcastBitInterrupt
| lldb.SBProcess.eBroadcastBitSTDOUT
| lldb.SBProcess.eBroadcastBitSTDERR
| lldb.SBProcess.eBroadcastBitProfileData,
)
self.listener.StartListeningForEventClass(
self.debugger,
lldb.SBCommandInterpreter.GetBroadcasterClass(),
lldb.SBCommandInterpreter.eBroadcastBitThreadShouldExit
| lldb.SBCommandInterpreter.eBroadcastBitResetPrompt
| lldb.SBCommandInterpreter.eBroadcastBitQuitCommandReceived
| lldb.SBCommandInterpreter.eBroadcastBitAsynchronousOutputData
| lldb.SBCommandInterpreter.eBroadcastBitAsynchronousErrorData,
)
def createTarget(self, target_image, args=None):
self.handleCommand("target create %s" % target_image)

View File

@ -12,9 +12,8 @@ import lldbutil
class EventWin(cui.TitledWin):
def __init__(self, x, y, w, h):
super(EventWin, self).__init__(x, y, w, h, 'LLDB Event Log')
super(EventWin, self).__init__(x, y, w, h, "LLDB Event Log")
self.win.scrollok(1)
super(EventWin, self).draw()

View File

@ -40,6 +40,7 @@ def which(program):
return exe_file
return None
# ===================================================
# Disassembly for an SBFunction or an SBSymbol object
# ===================================================
@ -56,6 +57,7 @@ def disassemble(target, function_or_symbol):
print(i, file=buf)
return buf.getvalue()
# ==========================================================
# Integer (byte size 1, 2, 4, and 8) to bytearray conversion
# ==========================================================
@ -75,11 +77,11 @@ def int_to_bytearray(val, bytesize):
# Little endian followed by a format character.
template = "<%c"
if bytesize == 2:
fmt = template % 'h'
fmt = template % "h"
elif bytesize == 4:
fmt = template % 'i'
fmt = template % "i"
elif bytesize == 4:
fmt = template % 'q'
fmt = template % "q"
else:
return None
@ -101,11 +103,11 @@ def bytearray_to_int(bytes, bytesize):
# Little endian followed by a format character.
template = "<%c"
if bytesize == 2:
fmt = template % 'h'
fmt = template % "h"
elif bytesize == 4:
fmt = template % 'i'
fmt = template % "i"
elif bytesize == 4:
fmt = template % 'q'
fmt = template % "q"
else:
return None
@ -126,7 +128,7 @@ def get_description(obj, option=None):
o lldb.eDescriptionLevelFull
o lldb.eDescriptionLevelVerbose
"""
method = getattr(obj, 'GetDescription')
method = getattr(obj, "GetDescription")
if not method:
return None
tuple = (lldb.SBTarget, lldb.SBBreakpointLocation, lldb.SBWatchpoint)
@ -148,6 +150,7 @@ def get_description(obj, option=None):
# Convert some enum value to its string counterpart
# =================================================
def state_type_to_str(enum):
"""Returns the stateType string given an enum."""
if enum == lldb.eStateInvalid:
@ -280,60 +283,70 @@ def value_type_to_str(enum):
# Get stopped threads due to each stop reason.
# ==================================================
def sort_stopped_threads(process,
breakpoint_threads=None,
crashed_threads=None,
watchpoint_threads=None,
signal_threads=None,
exiting_threads=None,
other_threads=None):
""" Fills array *_threads with threads stopped for the corresponding stop
reason.
def sort_stopped_threads(
process,
breakpoint_threads=None,
crashed_threads=None,
watchpoint_threads=None,
signal_threads=None,
exiting_threads=None,
other_threads=None,
):
"""Fills array *_threads with threads stopped for the corresponding stop
reason.
"""
for lst in [breakpoint_threads,
watchpoint_threads,
signal_threads,
exiting_threads,
other_threads]:
for lst in [
breakpoint_threads,
watchpoint_threads,
signal_threads,
exiting_threads,
other_threads,
]:
if lst is not None:
lst[:] = []
for thread in process:
dispatched = False
for (reason, list) in [(lldb.eStopReasonBreakpoint, breakpoint_threads),
(lldb.eStopReasonException, crashed_threads),
(lldb.eStopReasonWatchpoint, watchpoint_threads),
(lldb.eStopReasonSignal, signal_threads),
(lldb.eStopReasonThreadExiting, exiting_threads),
(None, other_threads)]:
for reason, list in [
(lldb.eStopReasonBreakpoint, breakpoint_threads),
(lldb.eStopReasonException, crashed_threads),
(lldb.eStopReasonWatchpoint, watchpoint_threads),
(lldb.eStopReasonSignal, signal_threads),
(lldb.eStopReasonThreadExiting, exiting_threads),
(None, other_threads),
]:
if not dispatched and list is not None:
if thread.GetStopReason() == reason or reason is None:
list.append(thread)
dispatched = True
# ==================================================
# Utility functions for setting breakpoints
# ==================================================
def 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):
test,
file_name,
line_number,
extra_options=None,
num_expected_locations=1,
loc_exact=False,
module_name=None,
):
"""Set a breakpoint by file and line, returning the breakpoint number.
If extra_options is not None, then we append it to the breakpoint set command.
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.
If loc_exact is true, we check that there is one location, and that location must be at the input file and line number."""
If loc_exact is true, we check that there is one location, and that location must be at the input file and line number.
"""
if file_name is None:
command = 'breakpoint set -l %d' % (line_number)
command = "breakpoint set -l %d" % (line_number)
else:
command = 'breakpoint set -f "%s" -l %d' % (file_name, line_number)
@ -352,26 +365,28 @@ def run_break_set_by_file_and_line(
num_locations=num_expected_locations,
file_name=file_name,
line_number=line_number,
module_name=module_name)
module_name=module_name,
)
else:
check_breakpoint_result(
test,
break_results,
num_locations=num_expected_locations)
test, break_results, num_locations=num_expected_locations
)
return get_bpno_from_match(break_results)
def run_break_set_by_symbol(
test,
symbol,
extra_options=None,
num_expected_locations=-1,
sym_exact=False,
module_name=None):
test,
symbol,
extra_options=None,
num_expected_locations=-1,
sym_exact=False,
module_name=None,
):
"""Set a breakpoint by symbol name. Common options are the same as run_break_set_by_file_and_line.
If sym_exact is true, then the output symbol must match the input exactly, otherwise we do a substring match."""
If sym_exact is true, then the output symbol must match the input exactly, otherwise we do a substring match.
"""
command = 'breakpoint set -n "%s"' % (symbol)
if module_name:
@ -388,22 +403,19 @@ def run_break_set_by_symbol(
break_results,
num_locations=num_expected_locations,
symbol_name=symbol,
module_name=module_name)
module_name=module_name,
)
else:
check_breakpoint_result(
test,
break_results,
num_locations=num_expected_locations)
test, break_results, num_locations=num_expected_locations
)
return get_bpno_from_match(break_results)
def run_break_set_by_selector(
test,
selector,
extra_options=None,
num_expected_locations=-1,
module_name=None):
test, selector, extra_options=None, num_expected_locations=-1, module_name=None
):
"""Set a breakpoint by selector. Common options are the same as run_break_set_by_file_and_line."""
command = 'breakpoint set -S "%s"' % (selector)
@ -423,21 +435,19 @@ def run_break_set_by_selector(
num_locations=num_expected_locations,
symbol_name=selector,
symbol_match_exact=False,
module_name=module_name)
module_name=module_name,
)
else:
check_breakpoint_result(
test,
break_results,
num_locations=num_expected_locations)
test, break_results, num_locations=num_expected_locations
)
return get_bpno_from_match(break_results)
def run_break_set_by_regexp(
test,
regexp,
extra_options=None,
num_expected_locations=-1):
test, regexp, extra_options=None, num_expected_locations=-1
):
"""Set a breakpoint by regular expression match on symbol name. Common options are the same as run_break_set_by_file_and_line."""
command = 'breakpoint set -r "%s"' % (regexp)
@ -446,19 +456,14 @@ def run_break_set_by_regexp(
break_results = run_break_set_command(test, command)
check_breakpoint_result(
test,
break_results,
num_locations=num_expected_locations)
check_breakpoint_result(test, break_results, num_locations=num_expected_locations)
return get_bpno_from_match(break_results)
def run_break_set_by_source_regexp(
test,
regexp,
extra_options=None,
num_expected_locations=-1):
test, regexp, extra_options=None, num_expected_locations=-1
):
"""Set a breakpoint by source regular expression. Common options are the same as run_break_set_by_file_and_line."""
command = 'breakpoint set -p "%s"' % (regexp)
if extra_options:
@ -466,10 +471,7 @@ def run_break_set_by_source_regexp(
break_results = run_break_set_command(test, command)
check_breakpoint_result(
test,
break_results,
num_locations=num_expected_locations)
check_breakpoint_result(test, break_results, num_locations=num_expected_locations)
return get_bpno_from_match(break_results)
@ -496,120 +498,120 @@ def run_break_set_command(test, command):
r"^Breakpoint (?P<bpno>[0-9]+): (?P<num_locations>[0-9]+) locations\.$",
r"^Breakpoint (?P<bpno>[0-9]+): (?P<num_locations>no) locations \(pending\)\.",
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]+)$",
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]+)$"]
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]+)$",
]
match_object = test.match(command, patterns)
break_results = match_object.groupdict()
# We always insert the breakpoint number, setting it to -1 if we couldn't find it
# Also, make sure it gets stored as an integer.
if not 'bpno' in break_results:
break_results['bpno'] = -1
if not "bpno" in break_results:
break_results["bpno"] = -1
else:
break_results['bpno'] = int(break_results['bpno'])
break_results["bpno"] = int(break_results["bpno"])
# We always insert the number of locations
# If ONE location is set for the breakpoint, then the output doesn't mention locations, but it has to be 1...
# We also make sure it is an integer.
if not 'num_locations' in break_results:
if not "num_locations" in break_results:
num_locations = 1
else:
num_locations = break_results['num_locations']
if num_locations == 'no':
num_locations = break_results["num_locations"]
if num_locations == "no":
num_locations = 0
else:
num_locations = int(break_results['num_locations'])
num_locations = int(break_results["num_locations"])
break_results['num_locations'] = num_locations
break_results["num_locations"] = num_locations
if 'line_no' in break_results:
break_results['line_no'] = int(break_results['line_no'])
if "line_no" in break_results:
break_results["line_no"] = int(break_results["line_no"])
return break_results
def get_bpno_from_match(break_results):
return int(break_results['bpno'])
return int(break_results["bpno"])
def 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):
out_num_locations = break_results['num_locations']
test,
break_results,
file_name=None,
line_number=-1,
symbol_name=None,
symbol_match_exact=True,
module_name=None,
offset=-1,
num_locations=-1,
):
out_num_locations = break_results["num_locations"]
if num_locations == -1:
test.assertTrue(out_num_locations > 0,
"Expecting one or more locations, got none.")
test.assertTrue(
out_num_locations > 0, "Expecting one or more locations, got none."
)
else:
test.assertTrue(
num_locations == out_num_locations,
"Expecting %d locations, got %d." %
(num_locations,
out_num_locations))
"Expecting %d locations, got %d." % (num_locations, out_num_locations),
)
if file_name:
out_file_name = ""
if 'file' in break_results:
out_file_name = break_results['file']
if "file" in break_results:
out_file_name = break_results["file"]
test.assertTrue(
file_name == out_file_name,
"Breakpoint file name '%s' doesn't match resultant name '%s'." %
(file_name,
out_file_name))
"Breakpoint file name '%s' doesn't match resultant name '%s'."
% (file_name, out_file_name),
)
if line_number != -1:
out_file_line = -1
if 'line_no' in break_results:
out_line_number = break_results['line_no']
if "line_no" in break_results:
out_line_number = break_results["line_no"]
test.assertTrue(
line_number == out_line_number,
"Breakpoint line number %s doesn't match resultant line %s." %
(line_number,
out_line_number))
"Breakpoint line number %s doesn't match resultant line %s."
% (line_number, out_line_number),
)
if symbol_name:
out_symbol_name = ""
# Look first for the inlined symbol name, otherwise use the symbol
# name:
if 'inline_symbol' in break_results and break_results['inline_symbol']:
out_symbol_name = break_results['inline_symbol']
elif 'symbol' in break_results:
out_symbol_name = break_results['symbol']
if "inline_symbol" in break_results and break_results["inline_symbol"]:
out_symbol_name = break_results["inline_symbol"]
elif "symbol" in break_results:
out_symbol_name = break_results["symbol"]
if symbol_match_exact:
test.assertTrue(
symbol_name == out_symbol_name,
"Symbol name '%s' doesn't match resultant symbol '%s'." %
(symbol_name,
out_symbol_name))
"Symbol name '%s' doesn't match resultant symbol '%s'."
% (symbol_name, out_symbol_name),
)
else:
test.assertTrue(
out_symbol_name.find(symbol_name) != -
1,
"Symbol name '%s' isn't in resultant symbol '%s'." %
(symbol_name,
out_symbol_name))
out_symbol_name.find(symbol_name) != -1,
"Symbol name '%s' isn't in resultant symbol '%s'."
% (symbol_name, out_symbol_name),
)
if module_name:
out_nodule_name = None
if 'module' in break_results:
out_module_name = break_results['module']
if "module" in break_results:
out_module_name = break_results["module"]
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))
module_name.find(out_module_name) != -1,
"Symbol module name '%s' isn't in expected module name '%s'."
% (out_module_name, module_name),
)
# ==================================================
# Utility functions related to Threads and Processes
@ -658,7 +660,7 @@ def get_stopped_thread(process, reason):
def get_threads_stopped_at_breakpoint(process, bkpt):
""" For a stopped process returns the thread stopped at the breakpoint passed in bkpt"""
"""For a stopped process returns the thread stopped at the breakpoint passed in bkpt"""
stopped_threads = []
threads = []
@ -677,7 +679,7 @@ def get_threads_stopped_at_breakpoint(process, bkpt):
def continue_to_breakpoint(process, bkpt):
""" Continues the process, if it stops, returns the threads stopped at bkpt; otherwise, returns None"""
"""Continues the process, if it stops, returns the threads stopped at bkpt; otherwise, returns None"""
process.Continue()
if process.GetState() != lldb.eStateStopped:
return None
@ -703,6 +705,7 @@ def get_function_names(thread):
"""
Returns a sequence of function names from the stack frames of this thread.
"""
def GetFuncName(i):
return thread.GetFrameAtIndex(i).GetFunctionName()
@ -713,6 +716,7 @@ def get_symbol_names(thread):
"""
Returns a sequence of symbols for this thread.
"""
def GetSymbol(i):
return thread.GetFrameAtIndex(i).GetSymbol().GetName()
@ -723,6 +727,7 @@ def get_pc_addresses(thread):
"""
Returns a sequence of pc addresses for this thread.
"""
def GetPCAddress(i):
return thread.GetFrameAtIndex(i).GetPCAddress()
@ -733,9 +738,9 @@ def get_filenames(thread):
"""
Returns a sequence of file names from the stack frames of this thread.
"""
def GetFilename(i):
return thread.GetFrameAtIndex(
i).GetLineEntry().GetFileSpec().GetFilename()
return thread.GetFrameAtIndex(i).GetLineEntry().GetFileSpec().GetFilename()
return [GetFilename(i) for i in range(thread.GetNumFrames())]
@ -744,6 +749,7 @@ def get_line_numbers(thread):
"""
Returns a sequence of line numbers from the stack frames of this thread.
"""
def GetLineNumber(i):
return thread.GetFrameAtIndex(i).GetLineEntry().GetLine()
@ -754,9 +760,9 @@ def get_module_names(thread):
"""
Returns a sequence of module names from the stack frames of this thread.
"""
def GetModuleName(i):
return thread.GetFrameAtIndex(
i).GetModule().GetFileSpec().GetFilename()
return thread.GetFrameAtIndex(i).GetModule().GetFileSpec().GetFilename()
return [GetModuleName(i) for i in range(thread.GetNumFrames())]
@ -765,6 +771,7 @@ def get_stack_frames(thread):
"""
Returns a sequence of stack frames for this thread.
"""
def GetStackFrame(i):
return thread.GetFrameAtIndex(i)
@ -790,8 +797,13 @@ def print_stacktrace(thread, string_buffer=False):
desc = "stop reason=" + stop_reason_to_str(thread.GetStopReason())
else:
desc = ""
print("Stack trace for thread id={0:#x} name={1} queue={2} ".format(
thread.GetThreadID(), thread.GetName(), thread.GetQueueName()) + desc, file=output)
print(
"Stack trace for thread id={0:#x} name={1} queue={2} ".format(
thread.GetThreadID(), thread.GetName(), thread.GetQueueName()
)
+ desc,
file=output,
)
for i in range(depth):
frame = thread.GetFrameAtIndex(i)
@ -802,13 +814,31 @@ def print_stacktrace(thread, string_buffer=False):
file_addr = addrs[i].GetFileAddress()
start_addr = frame.GetSymbol().GetStartAddress().GetFileAddress()
symbol_offset = file_addr - start_addr
print(" frame #{num}: {addr:#016x} {mod}`{symbol} + {offset}".format(
num=i, addr=load_addr, mod=mods[i], symbol=symbols[i], offset=symbol_offset), file=output)
print(
" frame #{num}: {addr:#016x} {mod}`{symbol} + {offset}".format(
num=i,
addr=load_addr,
mod=mods[i],
symbol=symbols[i],
offset=symbol_offset,
),
file=output,
)
else:
print(" frame #{num}: {addr:#016x} {mod}`{func} at {file}:{line} {args}".format(
num=i, addr=load_addr, mod=mods[i], func='%s [inlined]' %
funcs[i] if frame.IsInlined() else funcs[i], file=files[i], line=lines[i], args=get_args_as_string(
frame, showFuncName=False) if not frame.IsInlined() else '()'), file=output)
print(
" frame #{num}: {addr:#016x} {mod}`{func} at {file}:{line} {args}".format(
num=i,
addr=load_addr,
mod=mods[i],
func="%s [inlined]" % funcs[i] if frame.IsInlined() else funcs[i],
file=files[i],
line=lines[i],
args=get_args_as_string(frame, showFuncName=False)
if not frame.IsInlined()
else "()",
),
file=output,
)
if string_buffer:
return output.getvalue()
@ -827,6 +857,7 @@ def print_stacktraces(process, string_buffer=False):
if string_buffer:
return output.getvalue()
# ===================================
# Utility functions related to Frames
# ===================================
@ -859,9 +890,7 @@ def get_args_as_string(frame, showFuncName=True):
vars = frame.GetVariables(True, False, False, True) # type of SBValueList
args = [] # list of strings
for var in vars:
args.append("(%s)%s=%s" % (var.GetTypeName(),
var.GetName(),
var.GetValue()))
args.append("(%s)%s=%s" % (var.GetTypeName(), var.GetName(), var.GetValue()))
if frame.GetFunction():
name = frame.GetFunction().GetName()
elif frame.GetSymbol():
@ -882,15 +911,20 @@ def print_registers(frame, string_buffer=False):
print("Register sets for " + str(frame), file=output)
registerSet = frame.GetRegisters() # Return type of SBValueList.
print("Frame registers (size of register set = %d):" % registerSet.GetSize(
), file=output)
print(
"Frame registers (size of register set = %d):" % registerSet.GetSize(),
file=output,
)
for value in registerSet:
#print >> output, value
print("%s (number of children = %d):" % (
value.GetName(), value.GetNumChildren()), file=output)
# print >> output, value
print(
"%s (number of children = %d):" % (value.GetName(), value.GetNumChildren()),
file=output,
)
for child in value:
print("Name: %s, Value: %s" % (
child.GetName(), child.GetValue()), file=output)
print(
"Name: %s, Value: %s" % (child.GetName(), child.GetValue()), file=output
)
if string_buffer:
return output.getvalue()
@ -950,6 +984,7 @@ def get_ESRs(frame):
"""
return get_registers(frame, "exception state")
# ======================================
# Utility classes/functions for SBValues
# ======================================
@ -970,11 +1005,15 @@ class BasicFormatter(object):
val = value.GetValue()
if val is None and value.GetNumChildren() > 0:
val = "%s (location)" % value.GetLocation()
print("{indentation}({type}) {name} = {value}".format(
indentation=' ' * indent,
type=value.GetTypeName(),
name=value.GetName(),
value=val), file=output)
print(
"{indentation}({type}) {name} = {value}".format(
indentation=" " * indent,
type=value.GetTypeName(),
name=value.GetName(),
value=val,
),
file=output,
)
return output.getvalue()
@ -996,8 +1035,7 @@ class ChildVisitingFormatter(BasicFormatter):
BasicFormatter.format(self, value, buffer=output)
for child in value:
BasicFormatter.format(
self, child, buffer=output, indent=self.cindent)
BasicFormatter.format(self, child, buffer=output, indent=self.cindent)
return output.getvalue()
@ -1025,14 +1063,12 @@ class RecursiveDecentFormatter(BasicFormatter):
new_indent = self.lindent + self.cindent
for child in value:
if child.GetSummary() is not None:
BasicFormatter.format(
self, child, buffer=output, indent=new_indent)
BasicFormatter.format(self, child, buffer=output, indent=new_indent)
else:
if child.GetNumChildren() > 0:
rdf = RecursiveDecentFormatter(indent_level=new_indent)
rdf.format(child, buffer=output)
else:
BasicFormatter.format(
self, child, buffer=output, indent=new_indent)
BasicFormatter.format(self, child, buffer=output, indent=new_indent)
return output.getvalue()

View File

@ -38,17 +38,11 @@ event_queue = None
def handle_args(driver, argv):
parser = OptionParser()
parser.add_option(
"-p",
"--attach",
dest="pid",
help="Attach to specified Process ID",
type="int")
"-p", "--attach", dest="pid", help="Attach to specified Process ID", type="int"
)
parser.add_option(
"-c",
"--core",
dest="core",
help="Load specified core file",
type="string")
"-c", "--core", dest="core", help="Load specified core file", type="string"
)
(options, args) = parser.parse_args(argv)
@ -60,9 +54,7 @@ def handle_args(driver, argv):
print("Error: expecting integer PID, got '%s'" % options.pid)
elif options.core is not None:
if not os.path.exists(options.core):
raise Exception(
"Specified core file '%s' does not exist." %
options.core)
raise Exception("Specified core file '%s' does not exist." % options.core)
driver.loadCore(options.core)
elif len(args) == 2:
if not os.path.isfile(args[1]):
@ -80,7 +72,6 @@ def sigint_handler(signal, frame):
class LLDBUI(cui.CursesUI):
def __init__(self, screen, event_queue, driver):
super(LLDBUI, self).__init__(screen, event_queue)
@ -94,19 +85,21 @@ class LLDBUI(cui.CursesUI):
self.status_win = statuswin.StatusWin(0, h - 1, w, 1)
h -= 1
self.command_win = commandwin.CommandWin(
driver, 0, h - command_win_height, w, command_win_height)
driver, 0, h - command_win_height, w, command_win_height
)
h -= command_win_height
self.source_win = sourcewin.SourceWin(driver, 0, 0,
w - break_win_width - 1, h)
self.break_win = breakwin.BreakWin(driver, w - break_win_width, 0,
break_win_width, h)
self.source_win = sourcewin.SourceWin(driver, 0, 0, w - break_win_width - 1, h)
self.break_win = breakwin.BreakWin(
driver, w - break_win_width, 0, break_win_width, h
)
self.wins = [self.status_win,
# self.event_win,
self.source_win,
self.break_win,
self.command_win,
]
self.wins = [
self.status_win,
# self.event_win,
self.source_win,
self.break_win,
self.command_win,
]
self.focus = len(self.wins) - 1 # index of command window;
@ -116,12 +109,14 @@ class LLDBUI(cui.CursesUI):
if event == curses.KEY_F10:
self.driver.terminate()
if event == 20: # ctrl-T
def foo(cmd):
ret = lldb.SBCommandReturnObject()
self.driver.getCommandInterpreter().HandleCommand(cmd, ret)
foo('target create a.out')
foo('b main')
foo('run')
foo("target create a.out")
foo("b main")
foo("run")
super(LLDBUI, self).handleEvent(event)
@ -145,6 +140,7 @@ def main(screen):
handle_args(driver, sys.argv)
view.eventLoop()
if __name__ == "__main__":
try:
curses.wrapper(main)

View File

@ -25,7 +25,6 @@ event_queue = None
class SandboxUI(cui.CursesUI):
def __init__(self, screen, event_queue):
super(SandboxUI, self).__init__(screen, event_queue)
@ -34,10 +33,10 @@ class SandboxUI(cui.CursesUI):
h2 = height / 2
self.wins = []
#self.wins.append(cui.TitledWin(w2, h2, w2, h2, "Test Window 4"))
# self.wins.append(cui.TitledWin(w2, h2, w2, h2, "Test Window 4"))
list_win = cui.ListWin(w2, h2, w2, h2)
for i in range(0, 40):
list_win.addItem('Item %s' % i)
list_win.addItem("Item %s" % i)
self.wins.append(list_win)
self.wins.append(cui.TitledWin(0, 0, w2, h2, "Test Window 1"))
self.wins.append(cui.TitledWin(w2, 0, w2, h2, "Test Window 2"))
@ -52,12 +51,12 @@ class SandboxUI(cui.CursesUI):
# self.wins[0].win.scrollok(1)
# self.el = cui.CursesEditLine(self.wins[0].win, None,
# lambda c: callback('got', c), lambda c: callback('tab', c))
#self.el.prompt = '>>> '
#self.el.showPrompt(10, 0)
# self.el.prompt = '>>> '
# self.el.showPrompt(10, 0)
def handleEvent(self, event):
if isinstance(event, int):
if event == ord('q'):
if event == ord("q"):
sys.exit(0)
# self.el.handleEvent(event)
super(SandboxUI, self).handleEvent(event)
@ -70,6 +69,7 @@ def main(screen):
sandbox = SandboxUI(screen, event_queue)
sandbox.eventLoop()
if __name__ == "__main__":
try:
curses.wrapper(main)

View File

@ -15,7 +15,6 @@ import os
class SourceWin(cui.TitledWin):
def __init__(self, driver, x, y, w, h):
super(SourceWin, self).__init__(x, y, w, h, "Source")
self.sourceman = driver.getSourceManager()
@ -35,9 +34,10 @@ class SourceWin(cui.TitledWin):
try:
from pygments.formatters import TerminalFormatter
self.formatter = TerminalFormatter()
except ImportError:
#self.win.addstr("\nWarning: no 'pygments' library found. Syntax highlighting is disabled.")
# self.win.addstr("\nWarning: no 'pygments' library found. Syntax highlighting is disabled.")
self.lexer = None
self.formatter = None
pass
@ -55,8 +55,9 @@ class SourceWin(cui.TitledWin):
if lldb.SBBreakpoint.EventIsBreakpointEvent(event):
self.handleBPEvent(event)
if lldb.SBProcess.EventIsProcessEvent(event) and \
not lldb.SBProcess.GetRestartedFromEvent(event):
if lldb.SBProcess.EventIsProcessEvent(
event
) and not lldb.SBProcess.GetRestartedFromEvent(event):
process = lldb.SBProcess.GetProcessFromEvent(event)
if not process.IsValid():
return
@ -71,8 +72,8 @@ class SourceWin(cui.TitledWin):
pid = process.GetProcessID()
ec = process.GetExitStatus()
self.win.addstr(
"\nProcess %s [%d] has exited with exit-code %d" %
(target, pid, ec))
"\nProcess %s [%d] has exited with exit-code %d" % (target, pid, ec)
)
def pageUp(self):
if self.viewline > 0:
@ -100,8 +101,8 @@ class SourceWin(cui.TitledWin):
if self.viewline < 0:
raise Exception(
"negative viewline: pc=%d viewline=%d" %
(self.pc_line, self.viewline))
"negative viewline: pc=%d viewline=%d" % (self.pc_line, self.viewline)
)
def refreshSource(self, process=None):
(self.height, self.width) = self.win.getmaxyx()
@ -126,9 +127,14 @@ class SourceWin(cui.TitledWin):
if self.formatter is not None:
from pygments.lexers import get_lexer_for_filename
self.lexer = get_lexer_for_filename(self.filename)
bps = [] if not self.filename in self.breakpoints else self.breakpoints[self.filename]
bps = (
[]
if not self.filename in self.breakpoints
else self.breakpoints[self.filename]
)
self.win.erase()
if self.content:
self.formatContent(self.content, self.pc_line, bps)
@ -159,7 +165,7 @@ class SourceWin(cui.TitledWin):
marker = self.markerBP
line = "%s%3d %s" % (marker, line_num, self.highlight(content[i]))
if len(line) >= self.width:
line = line[0:self.width - 1] + "\n"
line = line[0 : self.width - 1] + "\n"
self.win.addstr(line, attr)
source += line
count = count + 1
@ -168,6 +174,7 @@ class SourceWin(cui.TitledWin):
def highlight(self, source):
if self.lexer and self.formatter:
from pygments import highlight
return highlight(source, self.lexer, self.formatter)
else:
return source
@ -202,9 +209,8 @@ class SourceWin(cui.TitledWin):
# hack! getting the LineEntry via SBBreakpointLocation.GetAddress.GetLineEntry does not work good for
# inlined frames, so we get the description (which does take
# into account inlined functions) and parse it.
desc = lldbutil.get_description(
location, lldb.eDescriptionLevelFull)
match = re.search('at\ ([^:]+):([\d]+)', desc)
desc = lldbutil.get_description(location, lldb.eDescriptionLevelFull)
match = re.search("at\ ([^:]+):([\d]+)", desc)
try:
path = match.group(1)
line = int(match.group(2).strip())
@ -219,20 +225,26 @@ class SourceWin(cui.TitledWin):
return locs
event_type = lldb.SBBreakpoint.GetBreakpointEventTypeFromEvent(event)
if event_type == lldb.eBreakpointEventTypeEnabled \
or event_type == lldb.eBreakpointEventTypeAdded \
or event_type == lldb.eBreakpointEventTypeLocationsResolved \
or event_type == lldb.eBreakpointEventTypeLocationsAdded:
if (
event_type == lldb.eBreakpointEventTypeEnabled
or event_type == lldb.eBreakpointEventTypeAdded
or event_type == lldb.eBreakpointEventTypeLocationsResolved
or event_type == lldb.eBreakpointEventTypeLocationsAdded
):
self.addBPLocations(getLocations(event))
elif event_type == lldb.eBreakpointEventTypeRemoved \
or event_type == lldb.eBreakpointEventTypeLocationsRemoved \
or event_type == lldb.eBreakpointEventTypeDisabled:
elif (
event_type == lldb.eBreakpointEventTypeRemoved
or event_type == lldb.eBreakpointEventTypeLocationsRemoved
or event_type == lldb.eBreakpointEventTypeDisabled
):
self.removeBPLocations(getLocations(event))
elif event_type == lldb.eBreakpointEventTypeCommandChanged \
or event_type == lldb.eBreakpointEventTypeConditionChanged \
or event_type == lldb.eBreakpointEventTypeIgnoreChanged \
or event_type == lldb.eBreakpointEventTypeThreadChanged \
or event_type == lldb.eBreakpointEventTypeInvalidType:
elif (
event_type == lldb.eBreakpointEventTypeCommandChanged
or event_type == lldb.eBreakpointEventTypeConditionChanged
or event_type == lldb.eBreakpointEventTypeIgnoreChanged
or event_type == lldb.eBreakpointEventTypeThreadChanged
or event_type == lldb.eBreakpointEventTypeInvalidType
):
# no-op
pass
self.refreshSource()

View File

@ -13,19 +13,19 @@ import curses
class StatusWin(cui.TextWin):
def __init__(self, x, y, w, h):
super(StatusWin, self).__init__(x, y, w)
self.keys = [ # ('F1', 'Help', curses.KEY_F1),
('F3', 'Cycle-focus', curses.KEY_F3),
('F10', 'Quit', curses.KEY_F10)]
("F3", "Cycle-focus", curses.KEY_F3),
("F10", "Quit", curses.KEY_F10),
]
def draw(self):
self.win.addstr(0, 0, '')
self.win.addstr(0, 0, "")
for key in self.keys:
self.win.addstr('{0}'.format(key[0]), curses.A_REVERSE)
self.win.addstr(' {0} '.format(key[1]), curses.A_NORMAL)
self.win.addstr("{0}".format(key[0]), curses.A_REVERSE)
self.win.addstr(" {0} ".format(key[1]), curses.A_NORMAL)
super(StatusWin, self).draw()
def handleEvent(self, event):