summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/lldb/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/llvm/lldb/scripts')
-rwxr-xr-xgnu/llvm/lldb/scripts/analyze-project-deps.py208
-rw-r--r--gnu/llvm/lldb/scripts/android/host_art_bt.py239
-rwxr-xr-xgnu/llvm/lldb/scripts/disasm-gdb-remote.pl2283
-rwxr-xr-xgnu/llvm/lldb/scripts/framework-header-fix.sh17
-rw-r--r--gnu/llvm/lldb/scripts/install_custom_python.py175
-rwxr-xr-xgnu/llvm/lldb/scripts/macos-setup-codesign.sh57
-rw-r--r--gnu/llvm/lldb/scripts/swig_bot_lib/__init__.py0
-rw-r--r--gnu/llvm/lldb/scripts/use_lldb_suite.py27
-rwxr-xr-xgnu/llvm/lldb/scripts/verify_api.py115
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:])