diff options
Diffstat (limited to 'gnu/llvm/lldb/scripts')
-rwxr-xr-x | gnu/llvm/lldb/scripts/analyze-project-deps.py | 208 | ||||
-rw-r--r-- | gnu/llvm/lldb/scripts/android/host_art_bt.py | 239 | ||||
-rwxr-xr-x | gnu/llvm/lldb/scripts/disasm-gdb-remote.pl | 2283 | ||||
-rwxr-xr-x | gnu/llvm/lldb/scripts/framework-header-fix.sh | 17 | ||||
-rw-r--r-- | gnu/llvm/lldb/scripts/install_custom_python.py | 175 | ||||
-rwxr-xr-x | gnu/llvm/lldb/scripts/macos-setup-codesign.sh | 57 | ||||
-rw-r--r-- | gnu/llvm/lldb/scripts/swig_bot_lib/__init__.py | 0 | ||||
-rw-r--r-- | gnu/llvm/lldb/scripts/use_lldb_suite.py | 27 | ||||
-rwxr-xr-x | gnu/llvm/lldb/scripts/verify_api.py | 115 |
9 files changed, 3121 insertions, 0 deletions
diff --git a/gnu/llvm/lldb/scripts/analyze-project-deps.py b/gnu/llvm/lldb/scripts/analyze-project-deps.py new file mode 100755 index 00000000000..c6e3263a2f2 --- /dev/null +++ b/gnu/llvm/lldb/scripts/analyze-project-deps.py @@ -0,0 +1,208 @@ +#! /usr/bin/env python + +import argparse +import itertools +import os +import re +import sys +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') + +args = parser.parse_args() + +src_dir = os.path.join(lldb_root, "source") +inc_dir = os.path.join(lldb_root, "include") + +src_map = {} + +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" + if str.startswith("Plugins"): + return "lldb/" + str + if str.startswith("lldb/../../source"): + return str.replace("lldb/../../source", "lldb") + return str + +def scan_deps(this_dir, file): + global src_map + deps = {} + this_dir = normalize_host(this_dir) + if this_dir in src_map: + deps = src_map[this_dir] + + with open(file) as f: + for line in list(f): + m = include_regex.match(line) + if m is None: + continue + relative = m.groups()[0].rstrip("/") + if relative == this_dir: + continue + relative = normalize_host(relative) + if relative in deps: + deps[relative] += 1 + elif relative != this_dir: + deps[relative] = 1 + 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): + 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"]] + relative = relative.replace("\\", "/") + for inc in inc_files: + inc_path = os.path.join(base, inc) + scan_deps(relative, inc_path) + +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"]] + norm_base_path = os.path.normpath(os.path.join("lldb", relative)) + norm_base_path = norm_base_path.replace("\\", "/") + for src in src_files: + src_path = os.path.join(base, src) + 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 + # list of known cycles, but every possible rotation of A -> B -> C. For + # example, if we previously encountered B -> C -> A (with an implicit -> B + # 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)): + 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 + # short cycles are discovered first, which will allow us to discard longer + # cycles which grow the search space exponentially the longer they get. + while len(path_queue) > 0: + cur_path = path_queue.pop(0) + if is_existing_cycle(cur_path, cycles): + continue + + next_len = path_lengths.pop(0) + 1 + last_component = cur_path[-1] + + for item in src_map[last_component]: + if item.startswith("clang"): + continue + + if item in cur_path: + # This is a cycle. Minimize it and then check if the result is + # already in the list of cycles. Insert it (or not) and then + # exit. + new_index = cur_path.index(item) + cycle = cur_path[new_index:] + if not is_existing_cycle(cycle, cycles): + cycles.append(cycle) + continue + + path_lengths.append(next_len) + 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]) + +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])) + for dep in sorted_deps: + print("\t{} [{}]".format(dep[0], dep[1])) + else: + 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] + total = 0 + smallest = result[0][1] + 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) + + 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: + sys.stdout.write("{} deps to break: ".format(total)) + sys.stdout.write(cycle[0][0]) + for (first, count, last) in cycle: + sys.stdout.write(" [{}->] {}".format(count, last)) + sys.stdout.write("\n") + else: + for cycle in cycles: + cycle.append(cycle[0]) + print(" -> ".join(cycle)) + + print("Analyzing islands...") + islands = [] + outgoing_counts = defaultdict(int) + incoming_counts = defaultdict(int) + for (total, smallest, cycle) in counted: + for (first, count, last) in cycle: + outgoing_counts[first] += count + incoming_counts[last] += count + for cycle in cycles: + this_cycle = set(cycle) + disjoints = [x for x in islands if this_cycle.isdisjoint(x)] + overlaps = [x for x in islands if not this_cycle.isdisjoint(x)] + islands = disjoints + [set.union(this_cycle, *overlaps)] + print("Found {} disjoint cycle islands...".format(len(islands))) + for island in islands: + print("Island ({} elements)".format(len(island))) + 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: + print(" {} [{} in, {} out]".format(node, inc, outg)) + sys.stdout.flush() +pass diff --git a/gnu/llvm/lldb/scripts/android/host_art_bt.py b/gnu/llvm/lldb/scripts/android/host_art_bt.py new file mode 100644 index 00000000000..b4e9d7e3027 --- /dev/null +++ b/gnu/llvm/lldb/scripts/android/host_art_bt.py @@ -0,0 +1,239 @@ +# Usage: +# art/test/run-test --host --gdb [--64] [--interpreter] 004-JniTest +# 'b Java_Main_shortMethod' +# 'r' +# 'command script import host_art_bt.py' +# 'host_art_bt' + +from __future__ import print_function + +import sys +import re + +import lldb + + +def host_art_bt(debugger, command, result, internal_dict): + prettified_frames = [] + lldb_frame_index = 0 + art_frame_index = 0 + target = debugger.GetSelectedTarget() + process = target.GetProcess() + 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()): + # 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) + 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 + }) + + # 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""") + art_method = frame.EvaluateExpression( + art_stack_visitor.GetName() + """.GetMethod()""") + if art_method.GetValueAsUnsigned() != 0: + art_method_name = frame.EvaluateExpression( + """art::PrettyMethod(""" + art_method.GetName() + """, true)""") + art_method_name_data = frame.EvaluateExpression( + art_method_name.GetName() + """.c_str()""").GetValueAsUnsigned() + art_method_name_size = frame.EvaluateExpression( + art_method_name.GetName() + """.length()""").GetValueAsUnsigned() + error = lldb.SBError() + art_method_name = process.ReadCStringFromMemory( + art_method_name_data, art_method_name_size + 1, error) + if not error.Success: + 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) + art_frame_index = art_frame_index + 1 + break + art_frame_index = art_frame_index + 1 + + # Skip native frames + lldb_frame_index = lldb_frame_index + 1 + if lldb_frame_index < thread.GetNumFrames(): + frame = thread.GetFrameAtIndex(lldb_frame_index) + if frame.GetModule() and re.match( + 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'): + # 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') + 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*)': + 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': + # 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""") + art_method = frame.EvaluateExpression( + 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_method_name_data = frame.EvaluateExpression( + art_method_name.GetName() + """.c_str()""").GetValueAsUnsigned() + art_method_name_size = frame.EvaluateExpression( + art_method_name.GetName() + """.length()""").GetValueAsUnsigned() + error = lldb.SBError() + function = process.ReadCStringFromMemory( + art_method_name_data, art_method_name_size + 1, error) + + prettified_frames.append({ + 'function': function, + 'file': None, + 'line': -1 + }) + + art_frame_index = art_frame_index + 1 + break + art_frame_index = art_frame_index + 1 + + # Skip native frames + 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'): + # 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') + 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*)': + 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()): + # 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') + 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)': + 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""") + art_method = frame.EvaluateExpression( + 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_method_name_data = frame.EvaluateExpression( + art_method_name.GetName() + """.c_str()""").GetValueAsUnsigned() + art_method_name_size = frame.EvaluateExpression( + art_method_name.GetName() + """.length()""").GetValueAsUnsigned() + error = lldb.SBError() + function = process.ReadCStringFromMemory( + 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() + + file_name = frame.EvaluateExpression( + art_method.GetName() + """->GetDeclaringClassSourceFile()""") + file_name_data = file_name.GetValueAsUnsigned() + file_name_size = frame.EvaluateExpression( + """(size_t)strlen(""" + file_name.GetName() + """)""").GetValueAsUnsigned() + error = lldb.SBError() + file_name = process.ReadCStringFromMemory( + file_name_data, file_name_size + 1, error) + if not error.Success(): + print('Failed to read source file name') + sys.exit(1) + + prettified_frames.append({ + 'function': function, + 'file': file_name, + 'line': line + }) + + art_frame_index = art_frame_index + 1 + break + art_frame_index = art_frame_index + 1 + + # Skip native frames + while True: + lldb_frame_index = lldb_frame_index + 1 + if lldb_frame_index >= thread.GetNumFrames(): + 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()): + break + else: + # Other frames. Add them as-is. + frame = thread.GetFrameAtIndex(lldb_frame_index) + lldb_frame_index = lldb_frame_index + 1 + 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 + }) + + for prettified_frame in prettified_frames: + 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') diff --git a/gnu/llvm/lldb/scripts/disasm-gdb-remote.pl b/gnu/llvm/lldb/scripts/disasm-gdb-remote.pl new file mode 100755 index 00000000000..e4c7066ff21 --- /dev/null +++ b/gnu/llvm/lldb/scripts/disasm-gdb-remote.pl @@ -0,0 +1,2283 @@ +#!/usr/bin/perl + +use strict; + +#---------------------------------------------------------------------- +# Globals +#---------------------------------------------------------------------- +our $unimplemented_str = "UNIMPLEMENTED"; +our $success_str = "OK"; +our $swap = 1; +our $addr_size = 4; +our $thread_suffix_supported = 0; +our $max_bytes_per_line = 32; +our $addr_format = sprintf("0x%%%u.%ux", $addr_size*2, $addr_size*2); +our $pid_format = "%04.4x"; +our $tid_format = "%04.4x"; +our $reg8_href = { extract => \&get8, format => "0x%2.2x" }; +our $reg16_href = { extract => \&get16, format => "0x%4.4x" }; +our $reg32_href = { extract => \&get32, format => "0x%8.8x" }; +our $reg64_href = { extract => \&get64, format => "0x%s" }; +our $reg80_href = { extract => \&get80, format => "0x%s" }; +our $reg128_href = { extract => \&get128, format => "0x%s" }; +our $reg256_href = { extract => \&get256, format => "0x%s" }; +our $float32_href = { extract => \&get32, format => "0x%8.8x" }; +our $float64_href = { extract => \&get64, format => "0x%s" }; +our $float96_href = { extract => \&get96, format => "0x%s" }; +our $curr_cmd = undef; +our $curr_full_cmd = undef; +our %packet_times; +our $curr_time = 0.0; +our $last_time = 0.0; +our $base_time = 0.0; +our $packet_start_time = 0.0; +our $reg_cmd_reg; +our %reg_map = ( + 'i386-gdb' => [ + { name => 'eax', info => $reg32_href }, + { name => 'ecx', info => $reg32_href }, + { name => 'edx', info => $reg32_href }, + { name => 'ebx', info => $reg32_href }, + { name => 'esp', info => $reg32_href }, + { name => 'ebp', info => $reg32_href }, + { name => 'esi', info => $reg32_href }, + { name => 'edi', info => $reg32_href }, + { name => 'eip', info => $reg32_href }, + { name => 'eflags', info => $reg32_href }, + { name => 'cs', info => $reg32_href }, + { name => 'ss', info => $reg32_href }, + { name => 'ds', info => $reg32_href }, + { name => 'es', info => $reg32_href }, + { name => 'fs', info => $reg32_href }, + { name => 'gs', info => $reg32_href }, + { name => 'st0', info => $reg80_href }, + { name => 'st1', info => $reg80_href }, + { name => 'st2', info => $reg80_href }, + { name => 'st3', info => $reg80_href }, + { name => 'st4', info => $reg80_href }, + { name => 'st5', info => $reg80_href }, + { name => 'st6', info => $reg80_href }, + { name => 'st7', info => $reg80_href }, + { name => 'fctrl', info => $reg32_href }, + { name => 'fstat', info => $reg32_href }, + { name => 'ftag', info => $reg32_href }, + { name => 'fiseg', info => $reg32_href }, + { name => 'fioff', info => $reg32_href }, + { name => 'foseg', info => $reg32_href }, + { name => 'fooff', info => $reg32_href }, + { name => 'fop', info => $reg32_href }, + { name => 'xmm0', info => $reg128_href }, + { name => 'xmm1', info => $reg128_href }, + { name => 'xmm2', info => $reg128_href }, + { name => 'xmm3', info => $reg128_href }, + { name => 'xmm4', info => $reg128_href }, + { name => 'xmm5', info => $reg128_href }, + { name => 'xmm6', info => $reg128_href }, + { name => 'xmm7', info => $reg128_href }, + { name => 'mxcsr', info => $reg32_href }, + { name => 'mm0', info => $reg64_href }, + { name => 'mm1', info => $reg64_href }, + { name => 'mm2', info => $reg64_href }, + { name => 'mm3', info => $reg64_href }, + { name => 'mm4', info => $reg64_href }, + { name => 'mm5', info => $reg64_href }, + { name => 'mm6', info => $reg64_href }, + { name => 'mm7', info => $reg64_href }, + ], + + 'i386-lldb' => [ + { name => 'eax', info => $reg32_href }, + { name => 'ebx', info => $reg32_href }, + { name => 'ecx', info => $reg32_href }, + { name => 'edx', info => $reg32_href }, + { name => 'edi', info => $reg32_href }, + { name => 'esi', info => $reg32_href }, + { name => 'ebp', info => $reg32_href }, + { name => 'esp', info => $reg32_href }, + { name => 'ss', info => $reg32_href }, + { name => 'eflags', info => $reg32_href }, + { name => 'eip', info => $reg32_href }, + { name => 'cs', info => $reg32_href }, + { name => 'ds', info => $reg32_href }, + { name => 'es', info => $reg32_href }, + { name => 'fs', info => $reg32_href }, + { name => 'gs', info => $reg32_href }, + { name => 'fctrl', info => $reg16_href }, + { name => 'fstat', info => $reg16_href }, + { name => 'ftag', info => $reg8_href }, + { name => 'fop', info => $reg16_href }, + { name => 'fioff', info => $reg32_href }, + { name => 'fiseg', info => $reg16_href }, + { name => 'fooff', info => $reg32_href }, + { name => 'foseg', info => $reg16_href }, + { name => 'mxcsr', info => $reg32_href }, + { name => 'mxcsrmask', info => $reg32_href }, + { name => 'stmm0', info => $reg80_href }, + { name => 'stmm1', info => $reg80_href }, + { name => 'stmm2', info => $reg80_href }, + { name => 'stmm3', info => $reg80_href }, + { name => 'stmm4', info => $reg80_href }, + { name => 'stmm5', info => $reg80_href }, + { name => 'stmm6', info => $reg80_href }, + { name => 'stmm7', info => $reg80_href }, + { name => 'xmm0', info => $reg128_href }, + { name => 'xmm1', info => $reg128_href }, + { name => 'xmm2', info => $reg128_href }, + { name => 'xmm3', info => $reg128_href }, + { name => 'xmm4', info => $reg128_href }, + { name => 'xmm5', info => $reg128_href }, + { name => 'xmm6', info => $reg128_href }, + { name => 'xmm7', info => $reg128_href }, + { name => 'trapno', info => $reg32_href }, + { name => 'err', info => $reg32_href }, + { name => 'faultvaddr', info => $reg32_href }, + ], + + 'arm-gdb' => [ + { name => 'r0' , info => $reg32_href }, + { name => 'r1' , info => $reg32_href }, + { name => 'r2' , info => $reg32_href }, + { name => 'r3' , info => $reg32_href }, + { name => 'r4' , info => $reg32_href }, + { name => 'r5' , info => $reg32_href }, + { name => 'r6' , info => $reg32_href }, + { name => 'r7' , info => $reg32_href }, + { name => 'r8' , info => $reg32_href }, + { name => 'r9' , info => $reg32_href }, + { name => 'r10' , info => $reg32_href }, + { name => 'r11' , info => $reg32_href }, + { name => 'r12' , info => $reg32_href }, + { name => 'sp' , info => $reg32_href }, + { name => 'lr' , info => $reg32_href }, + { name => 'pc' , info => $reg32_href }, + { name => 'f0' , info => $float96_href }, + { name => 'f1' , info => $float96_href }, + { name => 'f2' , info => $float96_href }, + { name => 'f3' , info => $float96_href }, + { name => 'f4' , info => $float96_href }, + { name => 'f5' , info => $float96_href }, + { name => 'f6' , info => $float96_href }, + { name => 'f7' , info => $float96_href }, + { name => 'fps' , info => $reg32_href }, + { name => 'cpsr' , info => $reg32_href }, + { name => 's0' , info => $float32_href }, + { name => 's1' , info => $float32_href }, + { name => 's2' , info => $float32_href }, + { name => 's3' , info => $float32_href }, + { name => 's4' , info => $float32_href }, + { name => 's5' , info => $float32_href }, + { name => 's6' , info => $float32_href }, + { name => 's7' , info => $float32_href }, + { name => 's8' , info => $float32_href }, + { name => 's9' , info => $float32_href }, + { name => 's10' , info => $float32_href }, + { name => 's11' , info => $float32_href }, + { name => 's12' , info => $float32_href }, + { name => 's13' , info => $float32_href }, + { name => 's14' , info => $float32_href }, + { name => 's15' , info => $float32_href }, + { name => 's16' , info => $float32_href }, + { name => 's17' , info => $float32_href }, + { name => 's18' , info => $float32_href }, + { name => 's19' , info => $float32_href }, + { name => 's20' , info => $float32_href }, + { name => 's21' , info => $float32_href }, + { name => 's22' , info => $float32_href }, + { name => 's23' , info => $float32_href }, + { name => 's24' , info => $float32_href }, + { name => 's25' , info => $float32_href }, + { name => 's26' , info => $float32_href }, + { name => 's27' , info => $float32_href }, + { name => 's28' , info => $float32_href }, + { name => 's29' , info => $float32_href }, + { name => 's30' , info => $float32_href }, + { name => 's31' , info => $float32_href }, + { name => 'fpscr' , info => $reg32_href }, + { name => 'd16' , info => $float64_href }, + { name => 'd17' , info => $float64_href }, + { name => 'd18' , info => $float64_href }, + { name => 'd19' , info => $float64_href }, + { name => 'd20' , info => $float64_href }, + { name => 'd21' , info => $float64_href }, + { name => 'd22' , info => $float64_href }, + { name => 'd23' , info => $float64_href }, + { name => 'd24' , info => $float64_href }, + { name => 'd25' , info => $float64_href }, + { name => 'd26' , info => $float64_href }, + { name => 'd27' , info => $float64_href }, + { name => 'd28' , info => $float64_href }, + { name => 'd29' , info => $float64_href }, + { name => 'd30' , info => $float64_href }, + { name => 'd31' , info => $float64_href }, + ], + + + 'arm-lldb' => [ + { name => 'r0' , info => $reg32_href }, + { name => 'r1' , info => $reg32_href }, + { name => 'r2' , info => $reg32_href }, + { name => 'r3' , info => $reg32_href }, + { name => 'r4' , info => $reg32_href }, + { name => 'r5' , info => $reg32_href }, + { name => 'r6' , info => $reg32_href }, + { name => 'r7' , info => $reg32_href }, + { name => 'r8' , info => $reg32_href }, + { name => 'r9' , info => $reg32_href }, + { name => 'r10' , info => $reg32_href }, + { name => 'r11' , info => $reg32_href }, + { name => 'r12' , info => $reg32_href }, + { name => 'sp' , info => $reg32_href }, + { name => 'lr' , info => $reg32_href }, + { name => 'pc' , info => $reg32_href }, + { name => 'cpsr' , info => $reg32_href }, + { name => 's0' , info => $float32_href }, + { name => 's1' , info => $float32_href }, + { name => 's2' , info => $float32_href }, + { name => 's3' , info => $float32_href }, + { name => 's4' , info => $float32_href }, + { name => 's5' , info => $float32_href }, + { name => 's6' , info => $float32_href }, + { name => 's7' , info => $float32_href }, + { name => 's8' , info => $float32_href }, + { name => 's9' , info => $float32_href }, + { name => 's10' , info => $float32_href }, + { name => 's11' , info => $float32_href }, + { name => 's12' , info => $float32_href }, + { name => 's13' , info => $float32_href }, + { name => 's14' , info => $float32_href }, + { name => 's15' , info => $float32_href }, + { name => 's16' , info => $float32_href }, + { name => 's17' , info => $float32_href }, + { name => 's18' , info => $float32_href }, + { name => 's19' , info => $float32_href }, + { name => 's20' , info => $float32_href }, + { name => 's21' , info => $float32_href }, + { name => 's22' , info => $float32_href }, + { name => 's23' , info => $float32_href }, + { name => 's24' , info => $float32_href }, + { name => 's25' , info => $float32_href }, + { name => 's26' , info => $float32_href }, + { name => 's27' , info => $float32_href }, + { name => 's28' , info => $float32_href }, + { name => 's29' , info => $float32_href }, + { name => 's30' , info => $float32_href }, + { name => 's31' , info => $float32_href }, + { name => 'd0' , info => $float64_href }, + { name => 'd1' , info => $float64_href }, + { name => 'd2' , info => $float64_href }, + { name => 'd3' , info => $float64_href }, + { name => 'd4' , info => $float64_href }, + { name => 'd5' , info => $float64_href }, + { name => 'd6' , info => $float64_href }, + { name => 'd7' , info => $float64_href }, + { name => 'd8' , info => $float64_href }, + { name => 'd9' , info => $float64_href }, + { name => 'd10' , info => $float64_href }, + { name => 'd11' , info => $float64_href }, + { name => 'd12' , info => $float64_href }, + { name => 'd13' , info => $float64_href }, + { name => 'd14' , info => $float64_href }, + { name => 'd15' , info => $float64_href }, + { name => 'd16' , info => $float64_href }, + { name => 'd17' , info => $float64_href }, + { name => 'd18' , info => $float64_href }, + { name => 'd19' , info => $float64_href }, + { name => 'd20' , info => $float64_href }, + { name => 'd21' , info => $float64_href }, + { name => 'd22' , info => $float64_href }, + { name => 'd23' , info => $float64_href }, + { name => 'd24' , info => $float64_href }, + { name => 'd25' , info => $float64_href }, + { name => 'd26' , info => $float64_href }, + { name => 'd27' , info => $float64_href }, + { name => 'd28' , info => $float64_href }, + { name => 'd29' , info => $float64_href }, + { name => 'd30' , info => $float64_href }, + { name => 'd31' , info => $float64_href }, + { name => 'fpscr' , info => $reg32_href }, + { name => 'exc' , info => $reg32_href }, + { name => 'fsr' , info => $reg32_href }, + { name => 'far' , info => $reg32_href }, + ], + + 'x86_64-gdb' => [ + { name => 'rax' , info => $reg64_href }, + { name => 'rbx' , info => $reg64_href }, + { name => 'rcx' , info => $reg64_href }, + { name => 'rdx' , info => $reg64_href }, + { name => 'rsi' , info => $reg64_href }, + { name => 'rdi' , info => $reg64_href }, + { name => 'rbp' , info => $reg64_href }, + { name => 'rsp' , info => $reg64_href }, + { name => 'r8' , info => $reg64_href }, + { name => 'r9' , info => $reg64_href }, + { name => 'r10' , info => $reg64_href }, + { name => 'r11' , info => $reg64_href }, + { name => 'r12' , info => $reg64_href }, + { name => 'r13' , info => $reg64_href }, + { name => 'r14' , info => $reg64_href }, + { name => 'r15' , info => $reg64_href }, + { name => 'rip' , info => $reg64_href }, + { name => 'eflags' , info => $reg32_href }, + { name => 'cs' , info => $reg32_href }, + { name => 'ss' , info => $reg32_href }, + { name => 'ds' , info => $reg32_href }, + { name => 'es' , info => $reg32_href }, + { name => 'fs' , info => $reg32_href }, + { name => 'gs' , info => $reg32_href }, + { name => 'stmm0' , info => $reg80_href }, + { name => 'stmm1' , info => $reg80_href }, + { name => 'stmm2' , info => $reg80_href }, + { name => 'stmm3' , info => $reg80_href }, + { name => 'stmm4' , info => $reg80_href }, + { name => 'stmm5' , info => $reg80_href }, + { name => 'stmm6' , info => $reg80_href }, + { name => 'stmm7' , info => $reg80_href }, + { name => 'fctrl' , info => $reg32_href }, + { name => 'fstat' , info => $reg32_href }, + { name => 'ftag' , info => $reg32_href }, + { name => 'fiseg' , info => $reg32_href }, + { name => 'fioff' , info => $reg32_href }, + { name => 'foseg' , info => $reg32_href }, + { name => 'fooff' , info => $reg32_href }, + { name => 'fop' , info => $reg32_href }, + { name => 'xmm0' , info => $reg128_href }, + { name => 'xmm1' , info => $reg128_href }, + { name => 'xmm2' , info => $reg128_href }, + { name => 'xmm3' , info => $reg128_href }, + { name => 'xmm4' , info => $reg128_href }, + { name => 'xmm5' , info => $reg128_href }, + { name => 'xmm6' , info => $reg128_href }, + { name => 'xmm7' , info => $reg128_href }, + { name => 'xmm8' , info => $reg128_href }, + { name => 'xmm9' , info => $reg128_href }, + { name => 'xmm10' , info => $reg128_href }, + { name => 'xmm11' , info => $reg128_href }, + { name => 'xmm12' , info => $reg128_href }, + { name => 'xmm13' , info => $reg128_href }, + { name => 'xmm14' , info => $reg128_href }, + { name => 'xmm15' , info => $reg128_href }, + { name => 'mxcsr' , info => $reg32_href }, + ], + + 'x86_64-lldb' => [ + { name => 'rax' , info => $reg64_href }, + { name => 'rbx' , info => $reg64_href }, + { name => 'rcx' , info => $reg64_href }, + { name => 'rdx' , info => $reg64_href }, + { name => 'rdi' , info => $reg64_href }, + { name => 'rsi' , info => $reg64_href }, + { name => 'rbp' , info => $reg64_href }, + { name => 'rsp' , info => $reg64_href }, + { name => 'r8 ' , info => $reg64_href }, + { name => 'r9 ' , info => $reg64_href }, + { name => 'r10' , info => $reg64_href }, + { name => 'r11' , info => $reg64_href }, + { name => 'r12' , info => $reg64_href }, + { name => 'r13' , info => $reg64_href }, + { name => 'r14' , info => $reg64_href }, + { name => 'r15' , info => $reg64_href }, + { name => 'rip' , info => $reg64_href }, + { name => 'rflags' , info => $reg64_href }, + { name => 'cs' , info => $reg64_href }, + { name => 'fs' , info => $reg64_href }, + { name => 'gs' , info => $reg64_href }, + { name => 'fctrl' , info => $reg16_href }, + { name => 'fstat' , info => $reg16_href }, + { name => 'ftag' , info => $reg8_href }, + { name => 'fop' , info => $reg16_href }, + { name => 'fioff' , info => $reg32_href }, + { name => 'fiseg' , info => $reg16_href }, + { name => 'fooff' , info => $reg32_href }, + { name => 'foseg' , info => $reg16_href }, + { name => 'mxcsr' , info => $reg32_href }, + { name => 'mxcsrmask' , info => $reg32_href }, + { name => 'stmm0' , info => $reg80_href }, + { name => 'stmm1' , info => $reg80_href }, + { name => 'stmm2' , info => $reg80_href }, + { name => 'stmm3' , info => $reg80_href }, + { name => 'stmm4' , info => $reg80_href }, + { name => 'stmm5' , info => $reg80_href }, + { name => 'stmm6' , info => $reg80_href }, + { name => 'stmm7' , info => $reg80_href }, + { name => 'xmm0' , info => $reg128_href }, + { name => 'xmm1' , info => $reg128_href }, + { name => 'xmm2' , info => $reg128_href }, + { name => 'xmm3' , info => $reg128_href }, + { name => 'xmm4' , info => $reg128_href }, + { name => 'xmm5' , info => $reg128_href }, + { name => 'xmm6' , info => $reg128_href }, + { name => 'xmm7' , info => $reg128_href }, + { name => 'xmm8' , info => $reg128_href }, + { name => 'xmm9' , info => $reg128_href }, + { name => 'xmm10' , info => $reg128_href }, + { name => 'xmm11' , info => $reg128_href }, + { name => 'xmm12' , info => $reg128_href }, + { name => 'xmm13' , info => $reg128_href }, + { name => 'xmm14' , info => $reg128_href }, + { name => 'xmm15' , info => $reg128_href }, + { name => 'trapno' , info => $reg32_href }, + { name => 'err' , info => $reg32_href }, + { name => 'faultvaddr' , info => $reg64_href }, + ] +); + +our $max_register_name_len = 0; +calculate_max_register_name_length(); +our @point_types = ( "software_bp", "hardware_bp", "write_wp", "read_wp", "access_wp" ); +our $opt_v = 0; # verbose +our $opt_g = 0; # debug +our $opt_q = 0; # quiet +our $opt_r = undef; +use Getopt::Std; +getopts('gvqr:'); + +our $registers_aref = undef; + +if (length($opt_r)) +{ + if (exists $reg_map{$opt_r}) + { + $registers_aref = $reg_map{$opt_r}; + } + else + { + die "Can't get registers group for '$opt_r'\n"; + } +} + +sub extract_key_value_pairs +{ + my $kv_href = {}; + my $arrayref = shift; + my $str = join('',@$arrayref); + my @kv_strs = split(/;/, $str); + foreach my $kv_str (@kv_strs) + { + my ($key, $value) = split(/:/, $kv_str); + $kv_href->{$key} = $value; + } + return $kv_href; +} + +sub get_thread_from_thread_suffix +{ + if ($thread_suffix_supported) + { + my $arrayref = shift; + # Skip leading semi-colon if needed + $$arrayref[0] == ';' and shift @$arrayref; + my $thread_href = extract_key_value_pairs ($arrayref); + if (exists $thread_href->{thread}) + { + return $thread_href->{thread}; + } + } + return undef; +} + +sub calculate_max_register_name_length +{ + $max_register_name_len = 7; + foreach my $reg_href (@$registers_aref) + { + my $name_len = length($reg_href->{name}); + if ($max_register_name_len < $name_len) + { + $max_register_name_len = $name_len; + } + } +} +#---------------------------------------------------------------------- +# Hash that maps command characters to the appropriate functions using +# the command character as the key and the value being a reference to +# the dump function for dumping the command itself. +#---------------------------------------------------------------------- +our %cmd_callbacks = +( + '?' => \&dump_last_signal_cmd, + 'H' => \&dump_set_thread_cmd, + 'T' => \&dump_thread_is_alive_cmd, + 'q' => \&dump_general_query_cmd, + 'Q' => \&dump_general_set_cmd, + 'g' => \&dump_read_regs_cmd, + 'G' => \&dump_write_regs_cmd, + 'p' => \&dump_read_single_register_cmd, + 'P' => \&dump_write_single_register_cmd, + 'm' => \&dump_read_mem_cmd, + 'M' => \&dump_write_mem_cmd, + 'X' => \&dump_write_mem_binary_cmd, + 'Z' => \&dump_bp_wp_command, + 'z' => \&dump_bp_wp_command, + 'k' => \&dump_kill_cmd, + 'A' => \&dump_A_command, + 'c' => \&dump_continue_cmd, + 's' => \&dump_continue_cmd, + 'C' => \&dump_continue_with_signal_cmd, + 'S' => \&dump_continue_with_signal_cmd, + '_M' => \&dump_allocate_memory_cmd, + '_m' => \&dump_deallocate_memory_cmd, + # extended commands + 'v' => \&dump_extended_cmd +); + +#---------------------------------------------------------------------- +# Hash that maps command characters to the appropriate functions using +# the command character as the key and the value being a reference to +# the dump function for the response to the command. +#---------------------------------------------------------------------- +our %rsp_callbacks = +( + 'c' => \&dump_stop_reply_packet, + 's' => \&dump_stop_reply_packet, + 'C' => \&dump_stop_reply_packet, + '?' => \&dump_stop_reply_packet, + 'T' => \&dump_thread_is_alive_rsp, + 'H' => \&dump_set_thread_rsp, + 'q' => \&dump_general_query_rsp, + 'g' => \&dump_read_regs_rsp, + 'p' => \&dump_read_single_register_rsp, + 'm' => \&dump_read_mem_rsp, + '_M' => \&dump_allocate_memory_rsp, + + # extended commands + 'v' => \&dump_extended_rsp, +); + + +sub dump_register_value +{ + my $indent = shift; + my $arrayref = shift; + my $reg_num = shift; + + if ($reg_num >= @$registers_aref) + { + printf("\tinvalid register index %d\n", $reg_num); + return; + } + + my $reg_href = $$registers_aref[$reg_num]; + my $reg_name = $reg_href->{name}; + if ($$arrayref[0] eq '#') + { + printf("\t%*s: error: EOS reached when trying to read register %d\n", $max_register_name_len, $reg_name, $reg_num); + } + + my $reg_info = $reg_href->{info}; + my $reg_extract = $reg_info->{extract}; + my $reg_format = $reg_info->{format}; + my $reg_val = &$reg_extract($arrayref); + if ($indent) { + printf("\t%*s = $reg_format", $max_register_name_len, $reg_name, $reg_val); + } else { + printf("%s = $reg_format", $reg_name, $reg_val); + } +} + +#---------------------------------------------------------------------- +# Extract the command into an array of ASCII char strings for easy +# processing +#---------------------------------------------------------------------- +sub extract_command +{ + my $cmd_str = shift; + my @cmd_chars = split(/ */, $cmd_str); + if ($cmd_chars[0] ne '$') + { + # only set the current command if it isn't a reply + $curr_cmd = $cmd_chars[0]; + } + return @cmd_chars; +} + +#---------------------------------------------------------------------- +# Strip the 3 checksum array entries after we don't need them anymore +#---------------------------------------------------------------------- +sub strip_checksum +{ + my $arrayref = shift; + splice(@$arrayref, -3); +} + +#---------------------------------------------------------------------- +# Dump all strings in array by joining them together with no space +# between them +#---------------------------------------------------------------------- +sub dump_chars +{ + print join('',@_); +} + +#---------------------------------------------------------------------- +# Check if the response is an error 'EXX' +#---------------------------------------------------------------------- +sub is_error_response +{ + if ($_[0] eq 'E') + { + shift; + print "ERROR = " . join('',@_) . "\n"; + return 1; + } + return 0; +} + +#---------------------------------------------------------------------- +# 'H' command +#---------------------------------------------------------------------- +sub dump_set_thread_cmd +{ + my $cmd = shift; + my $mod = shift; + print "set_thread ( $mod, " . join('',@_) . " )\n"; +} + +#---------------------------------------------------------------------- +# 'T' command +#---------------------------------------------------------------------- +our $T_cmd_tid = -1; +sub dump_thread_is_alive_cmd +{ + my $cmd = shift; + $T_cmd_tid = get_hex(\@_); + printf("thread_is_alive ( $tid_format )\n", $T_cmd_tid); +} + +sub dump_thread_is_alive_rsp +{ + my $rsp = join('',@_); + + printf("thread_is_alive ( $tid_format ) =>", $T_cmd_tid); + if ($rsp eq 'OK') + { + print " alive.\n"; + } + else + { + print " dead.\n"; + } +} + +#---------------------------------------------------------------------- +# 'H' response +#---------------------------------------------------------------------- +sub dump_set_thread_rsp +{ + if (!is_error_response(@_)) + { + print join('',@_) . "\n"; + } +} + +#---------------------------------------------------------------------- +# 'q' command +#---------------------------------------------------------------------- +our $gen_query_cmd; +our $qRegisterInfo_reg_num = -1; +sub dump_general_query_cmd +{ + $gen_query_cmd = join('',@_); + if ($gen_query_cmd eq 'qC') + { + print 'get_current_pid ()'; + } + elsif ($gen_query_cmd eq 'qfThreadInfo') + { + print 'get_first_active_threads ()'; + } + elsif ($gen_query_cmd eq 'qsThreadInfo') + { + print 'get_subsequent_active_threads ()'; + } + elsif (index($gen_query_cmd, 'qThreadExtraInfo') == 0) + { + # qThreadExtraInfo,id + print 'get_thread_extra_info ()'; + } + elsif (index($gen_query_cmd, 'qThreadStopInfo') == 0) + { + # qThreadStopInfoXXXX + @_ = splice(@_, length('qThreadStopInfo')); + my $tid = get_addr(\@_); + printf('get_thread_stop_info ( thread = 0x%4.4x )', $tid); + } + elsif (index($gen_query_cmd, 'qSymbol:') == 0) + { + # qCRC:addr,length + print 'gdb_ready_to_serve_symbol_lookups ()'; + } + elsif (index($gen_query_cmd, 'qCRC:') == 0) + { + # qCRC:addr,length + @_ = splice(@_, length('qCRC:')); + my $address = get_addr(\@_); + shift @_; + my $length = join('', @_); + printf("compute_crc (addr = $addr_format, length = $length)", $address); + } + elsif (index($gen_query_cmd, 'qGetTLSAddr:') == 0) + { + # qGetTLSAddr:thread-id,offset,lm + @_ = splice(@_, length('qGetTLSAddr:')); + my ($tid, $offset, $lm) = split (/,/, join('', @_)); + print "get_thread_local_storage_addr (thread-id = $tid, offset = $offset, lm = $lm)"; + } + elsif ($gen_query_cmd eq 'qOffsets') + { + print 'get_section_offsets ()'; + } + elsif (index($gen_query_cmd, 'qRegisterInfo') == 0) + { + @_ = splice(@_, length('qRegisterInfo')); + $qRegisterInfo_reg_num = get_hex(\@_); + + printf "get_dynamic_register_info ($qRegisterInfo_reg_num)"; + } + else + { + print $gen_query_cmd; + } + print "\n"; +} + +#---------------------------------------------------------------------- +# 'q' response +#---------------------------------------------------------------------- +sub dump_general_query_rsp +{ + my $gen_query_rsp = join('',@_); + my $gen_query_rsp_len = length ($gen_query_rsp); + if ($gen_query_cmd eq 'qC' and index($gen_query_rsp, 'QC') == 0) + { + shift @_; shift @_; + my $pid = get_hex(\@_); + printf("pid = $pid_format\n", $pid); + return; + } + elsif (index($gen_query_cmd, 'qRegisterInfo') == 0) + { + if ($gen_query_rsp_len == 0) + { + print "$unimplemented_str\n"; + } + else + { + if (index($gen_query_rsp, 'name') == 0) + { + $qRegisterInfo_reg_num == 0 and $registers_aref = []; + + my @name_and_values = split (/;/, $gen_query_rsp); + + my $reg_name = undef; + my $byte_size = 0; + my $pseudo = 0; + foreach (@name_and_values) + { + my ($name, $value) = split /:/; + if ($name eq "name") { $reg_name = $value; } + elsif ($name eq "bitsize") { $byte_size = $value / 8; } + elsif ($name eq "container-regs") { $pseudo = 1; } + } + if (defined $reg_name and $byte_size > 0) + { + if ($byte_size == 4) {push @$registers_aref, { name => $reg_name, info => $reg32_href , pseudo => $pseudo };} + elsif ($byte_size == 8) {push @$registers_aref, { name => $reg_name, info => $reg64_href , pseudo => $pseudo };} + elsif ($byte_size == 1) {push @$registers_aref, { name => $reg_name, info => $reg8_href , pseudo => $pseudo };} + elsif ($byte_size == 2) {push @$registers_aref, { name => $reg_name, info => $reg16_href , pseudo => $pseudo };} + elsif ($byte_size == 10) {push @$registers_aref, { name => $reg_name, info => $reg80_href , pseudo => $pseudo };} + elsif ($byte_size == 12) {push @$registers_aref, { name => $reg_name, info => $float96_href , pseudo => $pseudo };} + elsif ($byte_size == 16) {push @$registers_aref, { name => $reg_name, info => $reg128_href , pseudo => $pseudo };} + elsif ($byte_size == 32) {push @$registers_aref, { name => $reg_name, info => $reg256_href , pseudo => $pseudo };} + } + } + elsif ($gen_query_rsp_len == 3 and index($gen_query_rsp, 'E') == 0) + { + calculate_max_register_name_length(); + } + } + } + elsif ($gen_query_cmd =~ 'qThreadStopInfo') + { + dump_stop_reply_packet (@_); + } + if (dump_standard_response(\@_)) + { + # Do nothing... + } + else + { + print join('',@_) . "\n"; + } +} + +#---------------------------------------------------------------------- +# 'Q' command +#---------------------------------------------------------------------- +our $gen_set_cmd; +sub dump_general_set_cmd +{ + $gen_query_cmd = join('',@_); + if ($gen_query_cmd eq 'QStartNoAckMode') + { + print "StartNoAckMode ()" + } + elsif ($gen_query_cmd eq 'QThreadSuffixSupported') + { + $thread_suffix_supported = 1; + print "ThreadSuffixSupported ()" + } + elsif (index($gen_query_cmd, 'QSetMaxPayloadSize:') == 0) + { + @_ = splice(@_, length('QSetMaxPayloadSize:')); + my $max_payload_size = get_hex(\@_); + # QSetMaxPayloadSize:XXXX where XXXX is a hex length of the max + # packet payload size supported by gdb + printf("SetMaxPayloadSize ( 0x%x (%u))", $max_payload_size, $max_payload_size); + } + elsif (index ($gen_query_cmd, 'QSetSTDIN:') == 0) + { + @_ = splice(@_, length('QSetSTDIN:')); + printf ("SetSTDIN (path ='%s')\n", get_hex_string (\@_)); + } + elsif (index ($gen_query_cmd, 'QSetSTDOUT:') == 0) + { + @_ = splice(@_, length('QSetSTDOUT:')); + printf ("SetSTDOUT (path ='%s')\n", get_hex_string (\@_)); + } + elsif (index ($gen_query_cmd, 'QSetSTDERR:') == 0) + { + @_ = splice(@_, length('QSetSTDERR:')); + printf ("SetSTDERR (path ='%s')\n", get_hex_string (\@_)); + } + else + { + print $gen_query_cmd; + } + print "\n"; +} + +#---------------------------------------------------------------------- +# 'k' command +#---------------------------------------------------------------------- +sub dump_kill_cmd +{ + my $cmd = shift; + print "kill (" . join('',@_) . ")\n"; +} + +#---------------------------------------------------------------------- +# 'g' command +#---------------------------------------------------------------------- +sub dump_read_regs_cmd +{ + my $cmd = shift; + print "read_registers ()\n"; +} + +#---------------------------------------------------------------------- +# 'G' command +#---------------------------------------------------------------------- +sub dump_write_regs_cmd +{ + print "write_registers:\n"; + my $cmd = shift; + foreach my $reg_href (@$registers_aref) + { + last if ($_[0] eq '#'); + if ($reg_href->{pseudo} == 0) + { + my $reg_info_href = $reg_href->{info}; + my $reg_name = $reg_href->{name}; + my $reg_extract = $reg_info_href->{extract}; + my $reg_format = $reg_info_href->{format}; + my $reg_val = &$reg_extract(\@_); + printf("\t%*s = $reg_format\n", $max_register_name_len, $reg_name, $reg_val); + } + } +} + +sub dump_read_regs_rsp +{ + print "read_registers () =>\n"; + if (!is_error_response(@_)) + { + # print join('',@_) . "\n"; + foreach my $reg_href (@$registers_aref) + { + last if ($_[0] eq '#'); + if ($reg_href->{pseudo} == 0) + { + my $reg_info_href = $reg_href->{info}; + my $reg_name = $reg_href->{name}; + my $reg_extract = $reg_info_href->{extract}; + my $reg_format = $reg_info_href->{format}; + my $reg_val = &$reg_extract(\@_); + printf("\t%*s = $reg_format\n", $max_register_name_len, $reg_name, $reg_val); + } + } + } +} + +sub dump_read_single_register_rsp +{ + dump_register_value(0, \@_, $reg_cmd_reg); + print "\n"; +} + +#---------------------------------------------------------------------- +# '_M' - allocate memory command (LLDB extension) +# +# Command: '_M' +# Arg1: Hex byte size as big endian hex string +# Separator: ',' +# Arg2: permissions as string that must be a string that contains any +# combination of 'r' (readable) 'w' (writable) or 'x' (executable) +# +# Returns: The address that was allocated as a big endian hex string +# on success, else an error "EXX" where XX are hex bytes +# that indicate an error code. +# +# Examples: +# _M10,rw # allocate 16 bytes with read + write permissions +# _M100,rx # allocate 256 bytes with read + execute permissions +#---------------------------------------------------------------------- +sub dump_allocate_memory_cmd +{ + shift; shift; # shift off the '_' and the 'M' + my $byte_size = get_addr(\@_); + shift; # Skip ',' + printf("allocate_memory ( byte_size = %u (0x%x), permissions = %s)\n", $byte_size, $byte_size, join('',@_)); +} + +sub dump_allocate_memory_rsp +{ + if (@_ == 3 and $_[0] == 'E') + { + printf("allocated memory addr = ERROR (%s))\n", join('',@_)); + } + else + { + printf("allocated memory addr = 0x%s\n", join('',@_)); + } +} + +#---------------------------------------------------------------------- +# '_m' - deallocate memory command (LLDB extension) +# +# Command: '_m' +# Arg1: Hex address as big endian hex string +# +# Returns: "OK" on success "EXX" on error +# +# Examples: +# _m201000 # Free previously allocated memory at address 0x201000 +#---------------------------------------------------------------------- +sub dump_deallocate_memory_cmd +{ + shift; shift; # shift off the '_' and the 'm' + printf("deallocate_memory ( addr = 0x%s)\n", join('',@_)); +} + + +#---------------------------------------------------------------------- +# 'p' command +#---------------------------------------------------------------------- +sub dump_read_single_register_cmd +{ + my $cmd = shift; + $reg_cmd_reg = get_hex(\@_); + my $thread = get_thread_from_thread_suffix (\@_); + my $reg_href = $$registers_aref[$reg_cmd_reg]; + + if (defined $thread) + { + print "read_register ( reg = \"$reg_href->{name}\", thread = $thread )\n"; + } + else + { + print "read_register ( reg = \"$reg_href->{name}\" )\n"; + } +} + + +#---------------------------------------------------------------------- +# 'P' command +#---------------------------------------------------------------------- +sub dump_write_single_register_cmd +{ + my $cmd = shift; + my $reg_num = get_hex(\@_); + shift (@_); # Discard the '=' + + print "write_register ( "; + dump_register_value(0, \@_, $reg_num); + my $thread = get_thread_from_thread_suffix (\@_); + if (defined $thread) + { + print ", thread = $thread"; + } + print " )\n"; +} + +#---------------------------------------------------------------------- +# 'm' command +#---------------------------------------------------------------------- +our $read_mem_address = 0; +sub dump_read_mem_cmd +{ + my $cmd = shift; + $read_mem_address = get_addr(\@_); + shift; # Skip ',' + printf("read_mem ( $addr_format, %s )\n", $read_mem_address, join('',@_)); +} + +#---------------------------------------------------------------------- +# 'm' response +#---------------------------------------------------------------------- +sub dump_read_mem_rsp +{ + # If the memory read was 2 or 4 bytes, print it out in native format + # instead of just as bytes. + my $num_nibbles = @_; + if ($num_nibbles == 2) + { + printf(" 0x%2.2x", get8(\@_)); + } + elsif ($num_nibbles == 4) + { + printf(" 0x%4.4x", get16(\@_)); + } + elsif ($num_nibbles == 8) + { + printf(" 0x%8.8x", get32(\@_)); + } + elsif ($num_nibbles == 16) + { + printf(" 0x%s", get64(\@_)); + } + else + { + my $curr_address = $read_mem_address; + my $nibble; + my $nibble_offset = 0; + my $max_nibbles_per_line = 2 * $max_bytes_per_line; + foreach $nibble (@_) + { + if (($nibble_offset % $max_nibbles_per_line) == 0) + { + ($nibble_offset > 0) and print "\n "; + printf("$addr_format: ", $curr_address + $nibble_offset/2); + } + (($nibble_offset % 2) == 0) and print ' '; + print $nibble; + $nibble_offset++; + } + } + print "\n"; +} + +#---------------------------------------------------------------------- +# 'c' or 's' command +#---------------------------------------------------------------------- +sub dump_continue_cmd +{ + my $cmd = shift; + my $cmd_str; + $cmd eq 'c' and $cmd_str = 'continue'; + $cmd eq 's' and $cmd_str = 'step'; + my $address = -1; + if (@_) + { + my $address = get_addr(\@_); + printf("%s ($addr_format)\n", $cmd_str, $address); + } + else + { + printf("%s ()\n", $cmd_str); + } +} + +#---------------------------------------------------------------------- +# 'Css' continue (C) with signal (ss where 'ss' is two hex digits) +# 'Sss' step (S) with signal (ss where 'ss' is two hex digits) +#---------------------------------------------------------------------- +sub dump_continue_with_signal_cmd +{ + my $cmd = shift; + my $address = -1; + my $cmd_str; + $cmd eq 'c' and $cmd_str = 'continue'; + $cmd eq 's' and $cmd_str = 'step'; + my $signal = get_hex(\@_); + if (@_) + { + my $address = 0; + if (@_ && $_[0] == ';') + { + shift; + $address = get_addr(\@_); + } + } + + if ($address != -1) + { + printf("%s_with_signal (signal = 0x%2.2x, address = $addr_format)\n", $cmd_str, $signal, $address); + } + else + { + printf("%s_with_signal (signal = 0x%2.2x)\n", $cmd_str, $signal); + } +} + +#---------------------------------------------------------------------- +# 'A' command +#---------------------------------------------------------------------- +sub dump_A_command +{ + my $cmd = get_expected_char(\@_, 'A') or print "error: incorrect command letter for argument packet, expected 'A'\n"; + printf("set_program_arguments (\n"); + do + { + my $arg_len = get_uint(\@_); + get_expected_char(\@_, ',') or die "error: missing comma after argument length...?\n"; + my $arg_idx = get_uint(\@_); + get_expected_char(\@_, ',') or die "error: missing comma after argument number...?\n"; + + my $arg = ''; + my $num_hex8_bytes = $arg_len/2; + for (1 .. $num_hex8_bytes) + { + $arg .= sprintf("%c", get8(\@_)) + } + printf(" <%3u> argv[%u] = '%s'\n", $arg_len, $arg_idx, $arg); + if (@_ > 0) + { + get_expected_char(\@_, ',') or die "error: missing comma after argument argument ASCII hex bytes...?\n"; + } + } while (@_ > 0); + printf(" )\n"); +} + + +#---------------------------------------------------------------------- +# 'z' and 'Z' command +#---------------------------------------------------------------------- +sub dump_bp_wp_command +{ + my $cmd = shift; + my $type = shift; + shift; # Skip ',' + my $address = get_addr(\@_); + shift; # Skip ',' + my $length = join('',@_); + if ($cmd eq 'z') + { + printf("remove $point_types[$type]($addr_format, %d)\n", $address, $length); + } + else + { + printf("insert $point_types[$type]($addr_format, %d)\n", $address, $length); + } +} + + +#---------------------------------------------------------------------- +# 'X' command +#---------------------------------------------------------------------- +sub dump_write_mem_binary_cmd +{ + my $cmd = shift; + my $address = get_addr(\@_); + shift; # Skip ',' + + my ($length, $binary) = split(/:/, join('',@_)); + printf("write_mem_binary ( $addr_format, %d, %s)\n", $address, $length, $binary); + +} + +#---------------------------------------------------------------------- +# 'M' command +#---------------------------------------------------------------------- +sub dump_write_mem_cmd +{ + my $cmd = shift; + my $address = get_addr(\@_); + shift; # Skip ',' + my ($length, $hex_bytes) = split(/:/, join('',@_)); +# printf("write_mem ( $addr_format, %d, %s)\n", $address, $length, $hex_bytes); + printf("write_mem ( addr = $addr_format, len = %d (0x%x), bytes = ", $address, $length, $length); + splice(@_, 0, length($length)+1); + + my $curr_address = $address; + my $nibble; + my $nibble_count = 0; + my $max_nibbles_per_line = 2 * $max_bytes_per_line; + foreach $nibble (@_) + { + (($nibble_count % 2) == 0) and print ' '; + print $nibble; + $nibble_count++; + } + + # If the memory to write is 2 or 4 bytes, print it out in native format + # instead of just as bytes. + if (@_ == 4) + { + printf(" ( 0x%4.4x )", get16(\@_)); + } + elsif (@_ == 8) + { + printf(" ( 0x%8.8x )", get32(\@_)); + } + print " )\n"; + +} + +#---------------------------------------------------------------------- +# 'v' command +#---------------------------------------------------------------------- +our $extended_rsp_callback = 0; +sub dump_extended_cmd +{ + $extended_rsp_callback = 0; + if (join('', @_[0..4]) eq "vCont") + { + dump_extended_continue_cmd(splice(@_,5)); + } + elsif (join('', @_[0..7]) eq 'vAttach;') + { + dump_attach_command (splice(@_,8)); + } + elsif (join('', @_[0..11]) eq 'vAttachWait;') + { + dump_attach_wait_command (splice(@_,12)); + } +} + +#---------------------------------------------------------------------- +# 'v' response +#---------------------------------------------------------------------- +sub dump_extended_rsp +{ + if ($extended_rsp_callback) + { + &$extended_rsp_callback(@_); + } + $extended_rsp_callback = 0; +} + +#---------------------------------------------------------------------- +# 'vAttachWait' command +#---------------------------------------------------------------------- +sub dump_attach_wait_command +{ + print "attach_wait ( "; + while (@_) + { + printf("%c", get8(\@_)) + } + printf " )\n"; + +} + +#---------------------------------------------------------------------- +# 'vAttach' command +#---------------------------------------------------------------------- +sub dump_attach_command +{ + printf("attach ( pid = %i )", get_hex(\@_)); + $extended_rsp_callback = \&dump_stop_reply_packet; +} + +#---------------------------------------------------------------------- +# 'vCont' command +#---------------------------------------------------------------------- +sub dump_extended_continue_cmd +{ + print "extended_continue ( "; + my $cmd = shift; + if ($cmd eq '?') + { + print "list supported modes )\n"; + $extended_rsp_callback = \&dump_extended_continue_rsp; + } + elsif ($cmd eq ';') + { + $extended_rsp_callback = \&dump_stop_reply_packet; + my $i = 0; + while ($#_ >= 0) + { + if ($i > 0) + { + print ", "; + } + my $continue_cmd = shift; + my $tmp; + if ($continue_cmd eq 'c') + { + print "continue"; + } + elsif ($continue_cmd eq 'C') + { + print "continue with signal "; + print shift; + print shift; + } + elsif ($continue_cmd eq 's') + { + print "step"; + } + elsif ($continue_cmd eq 'S') + { + print "step with signal "; + print shift; + print shift; + } + + if ($_[0] eq ':') + { + shift; # Skip ':' + print " for thread "; + while ($#_ >= 0) + { + $tmp = shift; + if (length($tmp) > 0 && $tmp ne ';') { + print $tmp; + } else { + last; + } + } + } + $i++; + } + + printf " )\n"; + } +} + +#---------------------------------------------------------------------- +# 'vCont' response +#---------------------------------------------------------------------- +sub dump_extended_continue_rsp +{ + if (scalar(@_) == 0) + { + print "$unimplemented_str\n"; + } + else + { + print "extended_continue supports " . join('',@_) . "\n"; + } +} + +#---------------------------------------------------------------------- +# Dump the command ascii for any unknown commands +#---------------------------------------------------------------------- +sub dump_other_cmd +{ + print "other = " . join('',@_) . "\n"; +} + +#---------------------------------------------------------------------- +# Check to see if the response was unsupported with appropriate checksum +#---------------------------------------------------------------------- +sub rsp_is_unsupported +{ + return join('',@_) eq "#00"; +} + +#---------------------------------------------------------------------- +# Check to see if the response was "OK" with appropriate checksum +#---------------------------------------------------------------------- +sub rsp_is_OK +{ + return join('',@_) eq "OK#9a"; +} + +#---------------------------------------------------------------------- +# Dump a response for an unknown command +#---------------------------------------------------------------------- +sub dump_other_rsp +{ + print "other = " . join('',@_) . "\n"; +} + +#---------------------------------------------------------------------- +# Get a byte from the ascii string assuming that the 2 nibble ascii +# characters are in hex. +# +# The argument for this function needs to be a reference to an array +# that contains single character strings and the array will get +# updated by shifting characters off the front of it (no leading # "0x") +#---------------------------------------------------------------------- +sub get8 +{ + my $arrayref = shift; + my $val = hex(shift(@$arrayref) . shift(@$arrayref)); + return $val; +} + +#---------------------------------------------------------------------- +# Get a 16 bit integer and swap if $swap global is set to a non-zero +# value. +# +# The argument for this function needs to be a reference to an array +# that contains single character strings and the array will get +# updated by shifting characters off the front of it (no leading # "0x") +#---------------------------------------------------------------------- +sub get16 +{ + my $arrayref = shift; + my $val = 0; + if ($swap) + { + $val = get8($arrayref) | + get8($arrayref) << 8; + } + else + { + $val = get8($arrayref) << 8 | + get8($arrayref) ; + } + return $val; +} + +#---------------------------------------------------------------------- +# Get a 32 bit integer and swap if $swap global is set to a non-zero +# value. +# +# The argument for this function needs to be a reference to an array +# that contains single character strings and the array will get +# updated by shifting characters off the front of it (no leading # "0x") +#---------------------------------------------------------------------- +sub get32 +{ + my $arrayref = shift; + my $val = 0; + if ($swap) + { + $val = get8($arrayref) | + get8($arrayref) << 8 | + get8($arrayref) << 16 | + get8($arrayref) << 24 ; + } + else + { + $val = get8($arrayref) << 24 | + get8($arrayref) << 16 | + get8($arrayref) << 8 | + get8($arrayref) ; + } + return $val; +} + +#---------------------------------------------------------------------- +# Get a 64 bit hex value as a string +# +# The argument for this function needs to be a reference to an array +# that contains single character strings and the array will get +# updated by shifting characters off the front of it (no leading # "0x") +#---------------------------------------------------------------------- +sub get64 +{ + my $arrayref = shift; + my $val = ''; + my @nibbles; + if ($swap) + { + push @nibbles, splice(@$arrayref, 14, 2); + push @nibbles, splice(@$arrayref, 12, 2); + push @nibbles, splice(@$arrayref, 10, 2); + push @nibbles, splice(@$arrayref, 8, 2); + push @nibbles, splice(@$arrayref, 6, 2); + push @nibbles, splice(@$arrayref, 4, 2); + push @nibbles, splice(@$arrayref, 2, 2); + push @nibbles, splice(@$arrayref, 0, 2); + } + else + { + (@nibbles) = splice(@$arrayref, 0, ((64/8) * 2)); + } + $val = join('', @nibbles); + return $val; +} + +#---------------------------------------------------------------------- +# Get a 80 bit hex value as a string +# +# The argument for this function needs to be a reference to an array +# that contains single character strings and the array will get +# updated by shifting characters off the front of it (no leading # "0x") +#---------------------------------------------------------------------- +sub get80 +{ + my $arrayref = shift; + my $val = ''; + my @nibbles; + if ($swap) + { + push @nibbles, splice(@$arrayref, 18, 2); + push @nibbles, splice(@$arrayref, 16, 2); + push @nibbles, splice(@$arrayref, 14, 2); + push @nibbles, splice(@$arrayref, 12, 2); + push @nibbles, splice(@$arrayref, 10, 2); + push @nibbles, splice(@$arrayref, 8, 2); + push @nibbles, splice(@$arrayref, 6, 2); + push @nibbles, splice(@$arrayref, 4, 2); + push @nibbles, splice(@$arrayref, 2, 2); + push @nibbles, splice(@$arrayref, 0, 2); + } + else + { + (@nibbles) = splice(@$arrayref, 0, ((80/8) * 2)); + } + $val = join('', @nibbles); + return $val; +} + +#---------------------------------------------------------------------- +# Get a 96 bit hex value as a string +# +# The argument for this function needs to be a reference to an array +# that contains single character strings and the array will get +# updated by shifting characters off the front of it (no leading # "0x") +#---------------------------------------------------------------------- +sub get96 +{ + my $arrayref = shift; + my $val = ''; + my @nibbles; + if ($swap) + { + push @nibbles, splice(@$arrayref, 22, 2); + push @nibbles, splice(@$arrayref, 20, 2); + push @nibbles, splice(@$arrayref, 18, 2); + push @nibbles, splice(@$arrayref, 16, 2); + push @nibbles, splice(@$arrayref, 14, 2); + push @nibbles, splice(@$arrayref, 12, 2); + push @nibbles, splice(@$arrayref, 10, 2); + push @nibbles, splice(@$arrayref, 8, 2); + push @nibbles, splice(@$arrayref, 6, 2); + push @nibbles, splice(@$arrayref, 4, 2); + push @nibbles, splice(@$arrayref, 2, 2); + push @nibbles, splice(@$arrayref, 0, 2); + } + else + { + (@nibbles) = splice(@$arrayref, 0, ((96/8) * 2)); + } + $val = join('', @nibbles); + return $val; +} + +#---------------------------------------------------------------------- +# Get a 128 bit hex value as a string +# +# The argument for this function needs to be a reference to an array +# that contains single character strings and the array will get +# updated by shifting characters off the front of it (no leading # "0x") +#---------------------------------------------------------------------- +sub get128 +{ + my $arrayref = shift; + my $val = ''; + my @nibbles; + if ($swap) + { + push @nibbles, splice(@$arrayref, 30, 2); + push @nibbles, splice(@$arrayref, 28, 2); + push @nibbles, splice(@$arrayref, 26, 2); + push @nibbles, splice(@$arrayref, 24, 2); + push @nibbles, splice(@$arrayref, 22, 2); + push @nibbles, splice(@$arrayref, 20, 2); + push @nibbles, splice(@$arrayref, 18, 2); + push @nibbles, splice(@$arrayref, 16, 2); + push @nibbles, splice(@$arrayref, 14, 2); + push @nibbles, splice(@$arrayref, 12, 2); + push @nibbles, splice(@$arrayref, 10, 2); + push @nibbles, splice(@$arrayref, 8, 2); + push @nibbles, splice(@$arrayref, 6, 2); + push @nibbles, splice(@$arrayref, 4, 2); + push @nibbles, splice(@$arrayref, 2, 2); + push @nibbles, splice(@$arrayref, 0, 2); + } + else + { + (@nibbles) = splice(@$arrayref, 0, ((128/8) * 2)); + } + $val = join('', @nibbles); + return $val; +} + +#---------------------------------------------------------------------- +# Get a 256 bit hex value as a string +# +# The argument for this function needs to be a reference to an array +# that contains single character strings and the array will get +# updated by shifting characters off the front of it (no leading # "0x") +#---------------------------------------------------------------------- +sub get256 +{ + my $arrayref = shift; + my $val = ''; + my @nibbles; + if ($swap) + { + push @nibbles, splice(@$arrayref, 62, 2); + push @nibbles, splice(@$arrayref, 60, 2); + push @nibbles, splice(@$arrayref, 58, 2); + push @nibbles, splice(@$arrayref, 56, 2); + push @nibbles, splice(@$arrayref, 54, 2); + push @nibbles, splice(@$arrayref, 52, 2); + push @nibbles, splice(@$arrayref, 50, 2); + push @nibbles, splice(@$arrayref, 48, 2); + push @nibbles, splice(@$arrayref, 46, 2); + push @nibbles, splice(@$arrayref, 44, 2); + push @nibbles, splice(@$arrayref, 42, 2); + push @nibbles, splice(@$arrayref, 40, 2); + push @nibbles, splice(@$arrayref, 38, 2); + push @nibbles, splice(@$arrayref, 36, 2); + push @nibbles, splice(@$arrayref, 34, 2); + push @nibbles, splice(@$arrayref, 32, 2); + push @nibbles, splice(@$arrayref, 30, 2); + push @nibbles, splice(@$arrayref, 28, 2); + push @nibbles, splice(@$arrayref, 26, 2); + push @nibbles, splice(@$arrayref, 24, 2); + push @nibbles, splice(@$arrayref, 22, 2); + push @nibbles, splice(@$arrayref, 20, 2); + push @nibbles, splice(@$arrayref, 18, 2); + push @nibbles, splice(@$arrayref, 16, 2); + push @nibbles, splice(@$arrayref, 14, 2); + push @nibbles, splice(@$arrayref, 12, 2); + push @nibbles, splice(@$arrayref, 10, 2); + push @nibbles, splice(@$arrayref, 8, 2); + push @nibbles, splice(@$arrayref, 6, 2); + push @nibbles, splice(@$arrayref, 4, 2); + push @nibbles, splice(@$arrayref, 2, 2); + push @nibbles, splice(@$arrayref, 0, 2); + } + else + { + (@nibbles) = splice(@$arrayref, 0, ((256/8) * 2)); + } + $val = join('', @nibbles); + return $val; +} + +#---------------------------------------------------------------------- +# Get an unsigned integer value by grabbing items off the front of +# the array stopping when a non-digit char string is encountered. +# +# The argument for this function needs to be a reference to an array +# that contains single character strings and the array will get +# updated by shifting characters off the front of it +#---------------------------------------------------------------------- +sub get_uint +{ + my $arrayref = shift; + @$arrayref == 0 and return 0; + my $val = 0; + while ($$arrayref[0] =~ /[0-9]/) + { + $val = $val * 10 + int(shift(@$arrayref)); + } + return $val; +} + +#---------------------------------------------------------------------- +# Check the first character in the array and if it matches the expected +# character, return that character, else return undef; +# +# The argument for this function needs to be a reference to an array +# that contains single character strings and the array will get +# updated by shifting characters off the front of it. If the expected +# character doesn't match, it won't touch the array. If the first +# character does match, it will shift it off and return it. +#---------------------------------------------------------------------- +sub get_expected_char +{ + my $arrayref = shift; + my $expected_char = shift; + if ($expected_char eq $$arrayref[0]) + { + return shift(@$arrayref); + } + return undef; +} +#---------------------------------------------------------------------- +# Get a hex value by grabbing items off the front of the array and +# stopping when a non-hex char string is encountered. +# +# The argument for this function needs to be a reference to an array +# that contains single character strings and the array will get +# updated by shifting characters off the front of it (no leading # "0x") +#---------------------------------------------------------------------- +sub get_hex +{ + my $arrayref = shift; + my $my_swap = @_ ? shift : 0; + my $shift = 0; + my $val = 0; + while ($$arrayref[0] =~ /[0-9a-fA-F]/) + { + if ($my_swap) + { + my $byte = hex(shift(@$arrayref)) << 4 | hex(shift(@$arrayref)); + $val |= $byte << $shift; + $shift += 8; + } + else + { + $val <<= 4; + $val |= hex(shift(@$arrayref)); + } + } + return $val; +} + +#---------------------------------------------------------------------- +# Get an address value by grabbing items off the front of the array. +# +# The argument for this function needs to be a reference to an array +# that contains single character strings and the array will get +# updated by shifting characters off the front of it (no leading # "0x") +#---------------------------------------------------------------------- +sub get_addr +{ + get_hex(shift); +} + +sub get_hex_string +{ + my $arrayref = shift; + my $str = ''; + while ($$arrayref[0] =~ /[0-9a-fA-F]/ and $$arrayref[1] =~ /[0-9a-fA-F]/) + { + my $hi_nibble = hex(shift(@$arrayref)); + my $lo_nibble = hex(shift(@$arrayref)); + my $byte = ($hi_nibble << 4) | $lo_nibble; + $str .= chr($byte); + } + return $str; +} + +sub dump_stop_reply_data +{ + while ($#_ >= 0) + { + last unless ($_[0] ne '#'); + + + my $key = ''; + my $value = ''; + my $comment = ''; + if ($_[0] =~ /[0-9a-fA-F]/ && $_[1] =~ /[0-9a-fA-F]/) + { + my $reg_num = get8(\@_); + shift(@_); # Skip ':' + if (defined ($registers_aref) && $reg_num < @$registers_aref) + { + dump_register_value(1, \@_, $reg_num); + print "\n"; + shift(@_); # Skip ';' + next; + } + $key = sprintf("reg %u", $reg_num); + } + my $char; + + if (length($key) == 0) + { + while (1) + { + $char = shift(@_); + if (length($char) == 0 or $char eq ':' or $char eq '#') { last; } + $key .= $char; + } + } + + while (1) + { + $char = shift(@_); + if (length($char) == 0 or $char eq ';' or $char eq '#') { last; } + $value .= $char; + } + if ($key eq 'metype') + { + our %metype_to_name = ( + '1' => ' (EXC_BAD_ACCESS)', + '2' => ' (EXC_BAD_INSTRUCTION)', + '3' => ' (EXC_ARITHMETIC)', + '4' => ' (EXC_EMULATION)', + '5' => ' (EXC_SOFTWARE)', + '6' => ' (EXC_BREAKPOINT)', + '7' => ' (EXC_SYSCALL)', + '8' => ' (EXC_MACH_SYSCALL)', + '9' => ' (EXC_RPC_ALERT)', + '10' => ' (EXC_CRASH)' + ); + if (exists $metype_to_name{$value}) + { + $comment = $metype_to_name{$value}; + } + } + printf("\t%*s = %s$comment\n", $max_register_name_len, $key, $value); + } +} + +#---------------------------------------------------------------------- +# Dumps a Stop Reply Packet which happens in response to a step, +# continue, last signal, and probably a few other commands. +#---------------------------------------------------------------------- +sub dump_stop_reply_packet +{ + my $what = shift(@_); + if ($what eq 'S' or $what eq 'T') + { + my $signo = get8(\@_); + + our %signo_to_name = ( + '1' => ' SIGHUP', + '2' => ' SIGINT', + '3' => ' SIGQUIT', + '4' => ' SIGILL', + '5' => ' SIGTRAP', + '6' => ' SIGABRT', + '7' => ' SIGPOLL/SIGEMT', + '8' => ' SIGFPE', + '9' => ' SIGKILL', + '10' => ' SIGBUS', + '11' => ' SIGSEGV', + '12' => ' SIGSYS', + '13' => ' SIGPIPE', + '14' => ' SIGALRM', + '15' => ' SIGTERM', + '16' => ' SIGURG', + '17' => ' SIGSTOP', + '18' => ' SIGTSTP', + '19' => ' SIGCONT', + '20' => ' SIGCHLD', + '21' => ' SIGTTIN', + '22' => ' SIGTTOU', + '23' => ' SIGIO', + '24' => ' SIGXCPU', + '25' => ' SIGXFSZ', + '26' => ' SIGVTALRM', + '27' => ' SIGPROF', + '28' => ' SIGWINCH', + '29' => ' SIGINFO', + '30' => ' SIGUSR1', + '31' => ' SIGUSR2', + '145' => ' TARGET_EXC_BAD_ACCESS', # 0x91 + '146' => ' TARGET_EXC_BAD_INSTRUCTION', # 0x92 + '147' => ' TARGET_EXC_ARITHMETIC', # 0x93 + '148' => ' TARGET_EXC_EMULATION', # 0x94 + '149' => ' TARGET_EXC_SOFTWARE', # 0x95 + '150' => ' TARGET_EXC_BREAKPOINT' # 0x96 + ); + my $signo_str = sprintf("%i", $signo); + my $signo_name = ''; + if (exists $signo_to_name{$signo_str}) + { + $signo_name = $signo_to_name{$signo_str}; + } + printf ("signal (signo=%u$signo_name)\n", $signo); + dump_stop_reply_data (@_); + } + elsif ($what eq 'W') + { + print 'process_exited( ' . shift(@_) . shift(@_) . " )\n"; + } + elsif ($what eq 'X') + { + print 'process_terminated( ' . shift(@_) . shift(@_) . " )\n"; + } + elsif ($what eq 'O') + { + my $console_output = ''; + my $num_hex8_bytes = @_/2; + for (1 .. $num_hex8_bytes) + { + $console_output .= sprintf("%c", get8(\@_)) + } + + print "program_console_output('$console_output')\n"; + } +} + +#---------------------------------------------------------------------- +# '?' command +#---------------------------------------------------------------------- +sub dump_last_signal_cmd +{ + my $cmd = shift; + print 'last_signal (' . join('',@_) . ")\n"; +} + +sub dump_raw_command +{ + my $cmd_aref = shift; + my $callback_ref; + $curr_cmd = $$cmd_aref[0]; + + if ($curr_cmd eq 'q' or $curr_cmd eq 'Q' or $curr_cmd eq '_') + { + $curr_full_cmd = ''; + foreach my $ch (@$cmd_aref) + { + $ch !~ /[A-Za-z_]/ and last; + $curr_full_cmd .= $ch; + } + } + else + { + $curr_full_cmd = $curr_cmd; + } + + $curr_cmd eq '_' and $curr_cmd .= $$cmd_aref[1]; + $callback_ref = $cmd_callbacks{$curr_cmd}; + if ($callback_ref) + { + &$callback_ref(@$cmd_aref); + } + else + { + # Strip the command byte for responses since we injected that above + dump_other_cmd(@$cmd_aref); + } +} + +sub dump_standard_response +{ + my $cmd_aref = shift; + + my $cmd_len = scalar(@$cmd_aref); + if ($cmd_len == 0) + { + print "$unimplemented_str\n"; + return 1; + } + + my $response = join('', @$cmd_aref); + if ($response eq 'OK') + { + print "$success_str\n"; + return 1; + } + + if ($cmd_len == 3 and index($response, 'E') == 0) + { + print "ERROR: " . substr($response, 1) . "\n"; + return 1; + } + + return 0; +} +sub dump_raw_response +{ + my $cmd_aref = shift; + my $callback_ref; + + if ($packet_start_time != 0.0) + { + if (length($curr_full_cmd) > 0) + { + $packet_times{$curr_full_cmd} += $curr_time - $packet_start_time; + } + else + { + $packet_times{$curr_cmd} += $curr_time - $packet_start_time; + } + $packet_start_time = 0.0; + } + + $callback_ref = $rsp_callbacks{$curr_cmd}; + + if ($callback_ref) + { + &$callback_ref(@$cmd_aref); + } + else + { + dump_standard_response($cmd_aref) or dump_other_rsp(@$cmd_aref); + } + +} +#---------------------------------------------------------------------- +# Dumps any command and handles simple error checking on the responses +# for commands that are unsupported or OK. +#---------------------------------------------------------------------- +sub dump_command +{ + my $cmd_str = shift; + + # Dump the original command string if verbose is on + if ($opt_v) + { + print "dump_command($cmd_str)\n "; + } + + my @cmd_chars = extract_command($cmd_str); + my $is_cmd = 1; + + my $cmd = $cmd_chars[0]; + if ($cmd eq '$') + { + $is_cmd = 0; # Note that this is a reply + $cmd = $curr_cmd; # set the command byte appropriately + shift @cmd_chars; # remove the '$' from the cmd bytes + } + + # Check for common responses across all commands and handle them + # if we can + if ( $is_cmd == 0 ) + { + if (rsp_is_unsupported(@cmd_chars)) + { + print "$unimplemented_str\n"; + return; + } + elsif (rsp_is_OK(@cmd_chars)) + { + print "$success_str\n"; + return; + } + # Strip the checksum information for responses + strip_checksum(\@cmd_chars); + } + + my $callback_ref; + if ($is_cmd) { + $callback_ref = $cmd_callbacks{$cmd}; + } else { + $callback_ref = $rsp_callbacks{$cmd}; + } + + if ($callback_ref) + { + &$callback_ref(@cmd_chars); + } + else + { + # Strip the command byte for responses since we injected that above + if ($is_cmd) { + dump_other_cmd(@cmd_chars); + } else { + dump_other_rsp(@cmd_chars); + } + + } +} + + +#---------------------------------------------------------------------- +# Process a gdbserver log line by looking for getpkt and putkpt and +# tossing any other lines. + +#---------------------------------------------------------------------- +sub process_log_line +{ + my $line = shift; + #($opt_v and $opt_g) and print "# $line"; + + my $extract_cmd = 0; + my $delta_time = 0.0; + if ($line =~ /^(\s*)([1-9][0-9]+\.[0-9]+)([^0-9].*)$/) + { + my $leading_space = $1; + $curr_time = $2; + $line = $3; + if ($base_time == 0.0) + { + $base_time = $curr_time; + } + else + { + $delta_time = $curr_time - $last_time; + } + printf ("(%.6f, %+.6f): ", $curr_time - $base_time, $delta_time); + $last_time = $curr_time; + } + else + { + $curr_time = 0.0 + } + + if ($line =~ /getpkt /) + { + $extract_cmd = 1; + print "\n--> "; + $packet_start_time = $curr_time; + } + elsif ($line =~ /putpkt /) + { + $extract_cmd = 1; + print "<-- "; + } + elsif ($line =~ /.*Sent: \[[0-9]+\.[0-9]+[:0-9]*\] (.*)/) + { + $opt_g and print "maintenance dump-packets command: $1\n"; + my @raw_cmd_bytes = split(/ */, $1); + $packet_start_time = $curr_time; + print "\n--> "; + dump_raw_command(\@raw_cmd_bytes); + process_log_line($2); + } + elsif ($line =~ /.*Recvd: \[[0-9]+\.[0-9]+[:0-9]*\] (.*)/) + { + $opt_g and print "maintenance dump-packets reply: $1\n"; + my @raw_rsp_bytes = split(/ */, $1); + print "<-- "; + dump_raw_response(\@raw_rsp_bytes); + print "\n"; + } + elsif ($line =~ /getpkt: (.*)/) + { + if ($1 =~ /\$([^#]+)#[0-9a-fA-F]{2}/) + { + $opt_g and print "command: $1\n"; + my @raw_cmd_bytes = split(/ */, $1); + print "--> "; + $packet_start_time = $curr_time; + dump_raw_command(\@raw_cmd_bytes); + } + elsif ($1 =~ /\+/) + { + #print "--> ACK\n"; + } + elsif ($1 =~ /-/) + { + #print "--> NACK\n"; + } + } + elsif ($line =~ /putpkt: (.*)/) + { + if ($1 =~ /\$([^#]+)#[0-9a-fA-F]{2}/) + { + $opt_g and print "response: $1\n"; + my @raw_rsp_bytes = split(/ */, $1); + print "<-- "; + dump_raw_response(\@raw_rsp_bytes); + print "\n"; + } + elsif ($1 =~ /\+/) + { + #print "<-- ACK\n"; + } + elsif ($1 =~ /-/) + { + #print "<-- NACK\n"; + } + } + elsif ($line =~ /send packet: (.*)/) + { + if ($1 =~ /\$([^#]+)#[0-9a-fA-F]{2}/) + { + $opt_g and print "command: $1\n"; + my @raw_cmd_bytes = split(/ */, $1); + print "--> "; + $packet_start_time = $curr_time; + dump_raw_command(\@raw_cmd_bytes); + } + elsif ($1 =~ /\+/) + { + #print "--> ACK\n"; + } + elsif ($1 =~ /-/) + { + #print "--> NACK\n"; + } + } + elsif ($line =~ /read packet: (.*)/) + { + if ($1 =~ /\$([^#]*)#[0-9a-fA-F]{2}/) + { + $opt_g and print "response: $1\n"; + my @raw_rsp_bytes = split(/ */, $1); + print "<-- "; + dump_raw_response(\@raw_rsp_bytes); + print "\n"; + } + elsif ($1 =~ /\+/) + { + #print "<-- ACK\n"; + } + elsif ($1 =~ /-/) + { + #print "<-- NACK\n"; + } + } + elsif ($line =~ /Sending packet: \$([^#]+)#[0-9a-fA-F]{2}\.\.\.(.*)/) + { + $opt_g and print "command: $1\n"; + my @raw_cmd_bytes = split(/ */, $1); + print "\n--> "; + $packet_start_time = $curr_time; + dump_raw_command(\@raw_cmd_bytes); + process_log_line($2); + } + elsif ($line =~ /Packet received: (.*)/) + { + $opt_g and print "response: $1\n"; + my @raw_rsp_bytes = split(/ */, $1); + print "<-- "; + dump_raw_response(\@raw_rsp_bytes); + print "\n"; + } + + if ($extract_cmd) + { + my $beg = index($line, '("') + 2; + my $end = rindex($line, '");'); + $packet_start_time = $curr_time; + dump_command(substr($line, $beg, $end - $beg)); + } +} + + +our $line_num = 0; +while(<>) +{ + $line_num++; + $opt_q or printf("# %5d: $_", $line_num); + process_log_line($_); +} + +if (%packet_times) +{ + print "----------------------------------------------------------------------\n"; + print "Packet timing summary:\n"; + print "----------------------------------------------------------------------\n"; + print "Packet Time %\n"; + print "---------------------- -------- ------\n"; + my @packet_names = keys %packet_times; + my $total_packet_times = 0.0; + foreach my $key (@packet_names) + { + $total_packet_times += $packet_times{$key}; + } + + foreach my $value (sort {$packet_times{$b} cmp $packet_times{$a}} @packet_names) + { + my $percent = ($packet_times{$value} / $total_packet_times) * 100.0; + if ($percent < 10.0) + { + printf("%22s %1.6f %2.2f\n", $value, $packet_times{$value}, $percent); + + } + else + { + printf("%22s %1.6f %2.2f\n", $value, $packet_times{$value}, $percent); + } + } + print "---------------------- -------- ------\n"; + printf (" Total %1.6f 100.00\n", $total_packet_times); +} + + + + + + + diff --git a/gnu/llvm/lldb/scripts/framework-header-fix.sh b/gnu/llvm/lldb/scripts/framework-header-fix.sh new file mode 100755 index 00000000000..3459dd91c9e --- /dev/null +++ b/gnu/llvm/lldb/scripts/framework-header-fix.sh @@ -0,0 +1,17 @@ +#!/bin/sh +# Usage: framework-header-fix.sh <source header dir> <LLDB Version> + +set -e + +for file in `find $1 -name "*.h"` +do + /usr/bin/sed -i.bak 's/\(#include\)[ ]*"lldb\/\(API\/\)\{0,1\}\(.*\)"/\1 <LLDB\/\3>/1' "$file" + /usr/bin/sed -i.bak 's|<LLDB/Utility|<LLDB|' "$file" + LLDB_VERSION=`echo $2 | /usr/bin/sed -E 's/^([0-9]+).([0-9]+).([0-9]+)(.[0-9]+)?$/\\1/g'` + LLDB_REVISION=`echo $2 | /usr/bin/sed -E 's/^([0-9]+).([0-9]+).([0-9]+)(.[0-9]+)?$/\\3/g'` + LLDB_VERSION_STRING=`echo $2` + /usr/bin/sed -i.bak "s|//#define LLDB_VERSION$|#define LLDB_VERSION $LLDB_VERSION |" "$file" + /usr/bin/sed -i.bak "s|//#define LLDB_REVISION|#define LLDB_REVISION $LLDB_REVISION |" "$file" + /usr/bin/sed -i.bak "s|//#define LLDB_VERSION_STRING|#define LLDB_VERSION_STRING \"$LLDB_VERSION_STRING\" |" "$file" + rm -f "$file.bak" +done diff --git a/gnu/llvm/lldb/scripts/install_custom_python.py b/gnu/llvm/lldb/scripts/install_custom_python.py new file mode 100644 index 00000000000..6e263fa714e --- /dev/null +++ b/gnu/llvm/lldb/scripts/install_custom_python.py @@ -0,0 +1,175 @@ +""" Copies the build output of a custom python interpreter to a directory + structure that mirrors that of an official Python distribution. + + -------------------------------------------------------------------------- + File: install_custom_python.py + + Overview: Most users build LLDB by linking against the standard + Python distribution installed on their system. Occasionally + a user may want to build their own version of Python, and on + platforms such as Windows this is a hard requirement. This + script will take the build output of a custom interpreter and + install it into a canonical structure that mirrors that of an + official Python distribution, thus allowing PYTHONHOME to be + set appropriately. + + Gotchas: None. + + Copyright: None. + -------------------------------------------------------------------------- + +""" + +import argparse +import itertools +import os +import shutil +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)) + 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) + if copy_debug_suffix_also: + 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)) + 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)) + + os.mkdir(dest_dir) + 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...') + 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) + + # Next copy everything in the Include directory. + 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') + + # 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') + 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') + + pyd_names = [ + '_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') + os.mkdir(dlls_dir) + 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') + 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) + + +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.') +parser.add_argument( + '--dest', + required=True, + help='The location to install the Python distributions.') +parser.add_argument( + '--overwrite', + default=False, + action='store_true', + help='If the destination directory already exists, destroys its contents first.') +parser.add_argument( + '--silent', + default=False, + action='store_true', + help='If --overwite was specified, suppress confirmation before deleting a directory tree.') + +args = parser.parse_args() + +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...') + 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) + 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) + result = str.upper(sys.stdin.read(1)) + if result == 'N': + print('Unable to copy files to the destination. The destination already exists.') + sys.exit(1) + 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') diff --git a/gnu/llvm/lldb/scripts/macos-setup-codesign.sh b/gnu/llvm/lldb/scripts/macos-setup-codesign.sh new file mode 100755 index 00000000000..6e8ad768d5f --- /dev/null +++ b/gnu/llvm/lldb/scripts/macos-setup-codesign.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +CERT="lldb_codesign" + +function error() { + echo error: "$@" + exit 1 +} + +function cleanup { + # Remove generated files + rm -f "$TMPDIR/$CERT.tmpl" "$TMPDIR/$CERT.cer" "$TMPDIR/$CERT.key" > /dev/null 2>&1 +} + +trap cleanup EXIT + +# Check if the certificate is already present in the system keychain +security find-certificate -Z -p -c "$CERT" /Library/Keychains/System.keychain > /dev/null 2>&1 +if [ $? -eq 0 ]; then + echo Certificate has already been generated and installed + exit 0 +fi + +# Create the certificate template +cat <<EOF >$TMPDIR/$CERT.tmpl +[ req ] +default_bits = 2048 # RSA key size +encrypt_key = no # Protect private key +default_md = sha512 # MD to use +prompt = no # Prompt for DN +distinguished_name = codesign_dn # DN template +[ codesign_dn ] +commonName = "$CERT" +[ codesign_reqext ] +keyUsage = critical,digitalSignature +extendedKeyUsage = critical,codeSigning +EOF + +echo Generating and installing lldb_codesign certificate + +# Generate a new certificate +openssl req -new -newkey rsa:2048 -x509 -days 3650 -nodes -config "$TMPDIR/$CERT.tmpl" -extensions codesign_reqext -batch -out "$TMPDIR/$CERT.cer" -keyout "$TMPDIR/$CERT.key" > /dev/null 2>&1 +[ $? -eq 0 ] || error Something went wrong when generating the certificate + +# Install the certificate in the system keychain +sudo security add-trusted-cert -d -r trustRoot -p codeSign -k /Library/Keychains/System.keychain "$TMPDIR/$CERT.cer" > /dev/null 2>&1 +[ $? -eq 0 ] || error Something went wrong when installing the certificate + +# Install the key for the certificate in the system keychain +sudo security import "$TMPDIR/$CERT.key" -A -k /Library/Keychains/System.keychain > /dev/null 2>&1 +[ $? -eq 0 ] || error Something went wrong when installing the key + +# Kill task_for_pid access control daemon +sudo pkill -f /usr/libexec/taskgated > /dev/null 2>&1 + +# Exit indicating the certificate is now generated and installed +exit 0 diff --git a/gnu/llvm/lldb/scripts/swig_bot_lib/__init__.py b/gnu/llvm/lldb/scripts/swig_bot_lib/__init__.py new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/gnu/llvm/lldb/scripts/swig_bot_lib/__init__.py diff --git a/gnu/llvm/lldb/scripts/use_lldb_suite.py b/gnu/llvm/lldb/scripts/use_lldb_suite.py new file mode 100644 index 00000000000..a1a2e8b9367 --- /dev/null +++ b/gnu/llvm/lldb/scripts/use_lldb_suite.py @@ -0,0 +1,27 @@ +import inspect +import os +import sys + + +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('/') == '/' + break + lldb_root = parent + + test_path = os.path.join(lldb_root, "use_lldb_suite_root.py") + if os.path.isfile(test_path): + return lldb_root + return None + +lldb_root = find_lldb_root() +if lldb_root is not None: + 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) + finally: + if fp: + fp.close() diff --git a/gnu/llvm/lldb/scripts/verify_api.py b/gnu/llvm/lldb/scripts/verify_api.py new file mode 100755 index 00000000000..d422cded8c2 --- /dev/null +++ b/gnu/llvm/lldb/scripts/verify_api.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python + +import subprocess +import optparse +import os +import os.path +import re +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) + (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') + else: + 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.''' + 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. + + 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) + parser.add_option( + '-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='architecure 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.') + 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.') + (options, args) = parser.parse_args(all_args) + + api_external_symbols = list() + if options.archs: + for arch in options.archs: + for library in options.libraries: + external_symbols = extract_exe_symbol_names( + 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') + sys.exit(4) + if options.verbose: + print("API symbols:") + for (i, external_symbol) in enumerate(api_external_symbols): + print("[%u] %s" % (i, external_symbol)) + + api_regex = None + if options.api_regex_str: + api_regex = re.compile(options.api_regex_str) + + for arch in options.archs: + for exe_path in args: + print('Verifying (%s) "%s"...' % (arch, exe_path)) + exe_errors = 0 + undefined_symbols = extract_exe_symbol_names( + 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)) + continue + if undefined_symbol in api_external_symbols: + if options.verbose: + print('verified symbol: %s' % (undefined_symbol)) + else: + print('missing symbol: %s' % (undefined_symbol)) + exe_errors += 1 + if exe_errors: + print('error: missing %u API symbols from %s' % (exe_errors, options.libraries)) + else: + print('success') + +if __name__ == '__main__': + verify_api(sys.argv[1:]) |