Add --lldb to gdbclient.py
Test: `gdbclient.py --lldb -r /system/bin/toybox` and try `b main` `c` Test: `/data/local/tmp/arm64-lldb-server gdbserver :5039 /system/bin/toybox` and `gdbclient.py --lldb -p 4909` Change-Id: If7b6895e9c778cdee3764a4058cf70238bdd6b8a
This commit is contained in:
@@ -33,6 +33,27 @@ import gdbrunner
|
|||||||
|
|
||||||
g_temp_dirs = []
|
g_temp_dirs = []
|
||||||
|
|
||||||
|
|
||||||
|
def read_toolchain_config(root):
|
||||||
|
"""Finds out current toolchain path and version."""
|
||||||
|
def get_value(str):
|
||||||
|
return str[str.index('"') + 1:str.rindex('"')]
|
||||||
|
|
||||||
|
config_path = os.path.join(root, 'build', 'soong', 'cc', 'config',
|
||||||
|
'global.go')
|
||||||
|
with open(config_path) as f:
|
||||||
|
contents = f.readlines()
|
||||||
|
clang_base = ""
|
||||||
|
clang_version = ""
|
||||||
|
for line in contents:
|
||||||
|
line = line.strip()
|
||||||
|
if line.startswith('ClangDefaultBase'):
|
||||||
|
clang_base = get_value(line)
|
||||||
|
elif line.startswith('ClangDefaultVersion'):
|
||||||
|
clang_version = get_value(line)
|
||||||
|
return (clang_base, clang_version)
|
||||||
|
|
||||||
|
|
||||||
def get_gdbserver_path(root, arch):
|
def get_gdbserver_path(root, arch):
|
||||||
path = "{}/prebuilts/misc/gdbserver/android-{}/gdbserver{}"
|
path = "{}/prebuilts/misc/gdbserver/android-{}/gdbserver{}"
|
||||||
if arch.endswith("64"):
|
if arch.endswith("64"):
|
||||||
@@ -41,6 +62,17 @@ def get_gdbserver_path(root, arch):
|
|||||||
return path.format(root, arch, "")
|
return path.format(root, arch, "")
|
||||||
|
|
||||||
|
|
||||||
|
def get_lldb_server_path(root, clang_base, clang_version, arch):
|
||||||
|
arch = {
|
||||||
|
'arm': 'arm',
|
||||||
|
'arm64': 'aarch64',
|
||||||
|
'x86': 'i386',
|
||||||
|
'x86_64': 'x86_64',
|
||||||
|
}[arch]
|
||||||
|
return os.path.join(root, clang_base, "linux-x86",
|
||||||
|
clang_version, "runtimes_ndk_cxx", arch, "lldb-server")
|
||||||
|
|
||||||
|
|
||||||
def get_tracer_pid(device, pid):
|
def get_tracer_pid(device, pid):
|
||||||
if pid is None:
|
if pid is None:
|
||||||
return 0
|
return 0
|
||||||
@@ -77,6 +109,10 @@ def parse_args():
|
|||||||
".vscode/launch.json configuration needed to connect the debugging " +
|
".vscode/launch.json configuration needed to connect the debugging " +
|
||||||
"client to the server."))
|
"client to the server."))
|
||||||
|
|
||||||
|
lldb_group = parser.add_mutually_exclusive_group()
|
||||||
|
lldb_group.add_argument("--lldb", action="store_true", help="Use lldb.")
|
||||||
|
lldb_group.add_argument("--no-lldb", action="store_true", help="Do not use lldb.")
|
||||||
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--env", nargs=1, action="append", metavar="VAR=VALUE",
|
"--env", nargs=1, action="append", metavar="VAR=VALUE",
|
||||||
help="set environment variable when running a binary")
|
help="set environment variable when running a binary")
|
||||||
@@ -300,7 +336,19 @@ end
|
|||||||
|
|
||||||
return gdb_commands
|
return gdb_commands
|
||||||
|
|
||||||
def generate_setup_script(gdbpath, sysroot, linker_search_dir, binary_file, is64bit, port, debugger, connect_timeout=5):
|
|
||||||
|
def generate_lldb_script(sysroot, binary_name, port, solib_search_path):
|
||||||
|
commands = []
|
||||||
|
commands.append(
|
||||||
|
'settings append target.exec-search-paths {}'.format(' '.join(solib_search_path)))
|
||||||
|
|
||||||
|
commands.append('target create {}'.format(binary_name))
|
||||||
|
commands.append('target modules search-paths add / {}/'.format(sysroot))
|
||||||
|
commands.append('gdb-remote {}'.format(port))
|
||||||
|
return '\n'.join(commands)
|
||||||
|
|
||||||
|
|
||||||
|
def generate_setup_script(debugger_path, sysroot, linker_search_dir, binary_file, is64bit, port, debugger, connect_timeout=5):
|
||||||
# Generate a setup script.
|
# Generate a setup script.
|
||||||
# TODO: Detect the zygote and run 'art-on' automatically.
|
# TODO: Detect the zygote and run 'art-on' automatically.
|
||||||
root = os.environ["ANDROID_BUILD_TOP"]
|
root = os.environ["ANDROID_BUILD_TOP"]
|
||||||
@@ -323,9 +371,12 @@ def generate_setup_script(gdbpath, sysroot, linker_search_dir, binary_file, is64
|
|||||||
|
|
||||||
if debugger == "vscode":
|
if debugger == "vscode":
|
||||||
return generate_vscode_script(
|
return generate_vscode_script(
|
||||||
gdbpath, root, sysroot, binary_file.name, port, dalvik_gdb_script, solib_search_path)
|
debugger_path, root, sysroot, binary_file.name, port, dalvik_gdb_script, solib_search_path)
|
||||||
elif debugger == "gdb":
|
elif debugger == "gdb":
|
||||||
return generate_gdb_script(root, sysroot, binary_file.name, port, dalvik_gdb_script, solib_search_path, connect_timeout)
|
return generate_gdb_script(root, sysroot, binary_file.name, port, dalvik_gdb_script, solib_search_path, connect_timeout)
|
||||||
|
elif debugger == 'lldb':
|
||||||
|
return generate_lldb_script(
|
||||||
|
sysroot, binary_file.name, port, solib_search_path)
|
||||||
else:
|
else:
|
||||||
raise Exception("Unknown debugger type " + debugger)
|
raise Exception("Unknown debugger type " + debugger)
|
||||||
|
|
||||||
@@ -369,60 +420,78 @@ def do_main():
|
|||||||
is64bit = arch.endswith("64")
|
is64bit = arch.endswith("64")
|
||||||
|
|
||||||
# Make sure we have the linker
|
# Make sure we have the linker
|
||||||
llvm_readobj_path = os.path.join(root, "prebuilts", "clang", "host", platform_name,
|
clang_base, clang_version = read_toolchain_config(root)
|
||||||
"llvm-binutils-stable", "llvm-readobj")
|
toolchain_path = os.path.join(root, clang_base, platform_name,
|
||||||
|
clang_version)
|
||||||
|
llvm_readobj_path = os.path.join(toolchain_path, "bin", "llvm-readobj")
|
||||||
interp = gdbrunner.get_binary_interp(binary_file.name, llvm_readobj_path)
|
interp = gdbrunner.get_binary_interp(binary_file.name, llvm_readobj_path)
|
||||||
linker_search_dir = ensure_linker(device, sysroot, interp)
|
linker_search_dir = ensure_linker(device, sysroot, interp)
|
||||||
|
|
||||||
tracer_pid = get_tracer_pid(device, pid)
|
tracer_pid = get_tracer_pid(device, pid)
|
||||||
|
use_lldb = args.lldb
|
||||||
if tracer_pid == 0:
|
if tracer_pid == 0:
|
||||||
cmd_prefix = args.su_cmd
|
cmd_prefix = args.su_cmd
|
||||||
if args.env:
|
if args.env:
|
||||||
cmd_prefix += ['env'] + [v[0] for v in args.env]
|
cmd_prefix += ['env'] + [v[0] for v in args.env]
|
||||||
|
|
||||||
# Start gdbserver.
|
# Start gdbserver.
|
||||||
gdbserver_local_path = get_gdbserver_path(root, arch)
|
if use_lldb:
|
||||||
gdbserver_remote_path = "/data/local/tmp/{}-gdbserver".format(arch)
|
server_local_path = get_lldb_server_path(
|
||||||
gdbrunner.start_gdbserver(
|
root, clang_base, clang_version, arch)
|
||||||
device, gdbserver_local_path, gdbserver_remote_path,
|
server_remote_path = "/data/local/tmp/{}-lldb-server".format(
|
||||||
target_pid=pid, run_cmd=run_cmd, debug_socket=debug_socket,
|
arch)
|
||||||
port=args.port, run_as_cmd=cmd_prefix)
|
|
||||||
else:
|
else:
|
||||||
print "Connecting to tracing pid {} using local port {}".format(tracer_pid, args.port)
|
server_local_path = get_gdbserver_path(root, arch)
|
||||||
|
server_remote_path = "/data/local/tmp/{}-gdbserver".format(
|
||||||
|
arch)
|
||||||
|
gdbrunner.start_gdbserver(
|
||||||
|
device, server_local_path, server_remote_path,
|
||||||
|
target_pid=pid, run_cmd=run_cmd, debug_socket=debug_socket,
|
||||||
|
port=args.port, run_as_cmd=cmd_prefix, lldb=use_lldb)
|
||||||
|
else:
|
||||||
|
print(
|
||||||
|
"Connecting to tracing pid {} using local port {}".format(
|
||||||
|
tracer_pid, args.port))
|
||||||
gdbrunner.forward_gdbserver_port(device, local=args.port,
|
gdbrunner.forward_gdbserver_port(device, local=args.port,
|
||||||
remote="tcp:{}".format(args.port))
|
remote="tcp:{}".format(args.port))
|
||||||
|
|
||||||
gdb_path = os.path.join(root, "prebuilts", "gdb", platform_name, "bin",
|
if use_lldb:
|
||||||
"gdb")
|
debugger_path = os.path.join(toolchain_path, "bin", "lldb")
|
||||||
|
debugger = 'lldb'
|
||||||
|
else:
|
||||||
|
debugger_path = os.path.join(
|
||||||
|
root, "prebuilts", "gdb", platform_name, "bin", "gdb")
|
||||||
|
debugger = args.setup_forwarding or "gdb"
|
||||||
|
|
||||||
# Generate a gdb script.
|
# Generate a gdb script.
|
||||||
setup_commands = generate_setup_script(gdbpath=gdb_path,
|
setup_commands = generate_setup_script(debugger_path=debugger_path,
|
||||||
sysroot=sysroot,
|
sysroot=sysroot,
|
||||||
linker_search_dir=linker_search_dir,
|
linker_search_dir=linker_search_dir,
|
||||||
binary_file=binary_file,
|
binary_file=binary_file,
|
||||||
is64bit=is64bit,
|
is64bit=is64bit,
|
||||||
port=args.port,
|
port=args.port,
|
||||||
debugger=args.setup_forwarding or "gdb")
|
debugger=debugger)
|
||||||
|
|
||||||
if not args.setup_forwarding:
|
if use_lldb or not args.setup_forwarding:
|
||||||
# Print a newline to separate our messages from the GDB session.
|
# Print a newline to separate our messages from the GDB session.
|
||||||
print("")
|
print("")
|
||||||
|
|
||||||
# Start gdb.
|
# Start gdb.
|
||||||
gdbrunner.start_gdb(gdb_path, setup_commands)
|
gdbrunner.start_gdb(debugger_path, setup_commands, lldb=use_lldb)
|
||||||
else:
|
else:
|
||||||
print("")
|
print("")
|
||||||
print setup_commands
|
print(setup_commands)
|
||||||
print("")
|
print("")
|
||||||
if args.setup_forwarding == "vscode":
|
if args.setup_forwarding == "vscode":
|
||||||
print textwrap.dedent("""
|
print(textwrap.dedent("""
|
||||||
Paste the above json into .vscode/launch.json and start the debugger as
|
Paste the above json into .vscode/launch.json and start the debugger as
|
||||||
normal. Press enter in this terminal once debugging is finished to shutdown
|
normal. Press enter in this terminal once debugging is finished to shutdown
|
||||||
the gdbserver and close all the ports.""")
|
the gdbserver and close all the ports."""))
|
||||||
else:
|
else:
|
||||||
print textwrap.dedent("""
|
print(textwrap.dedent("""
|
||||||
Paste the above gdb commands into the gdb frontend to setup the gdbserver
|
Paste the above gdb commands into the gdb frontend to setup the gdbserver
|
||||||
connection. Press enter in this terminal once debugging is finished to
|
connection. Press enter in this terminal once debugging is finished to
|
||||||
shutdown the gdbserver and close all the ports.""")
|
shutdown the gdbserver and close all the ports."""))
|
||||||
print("")
|
print("")
|
||||||
raw_input("Press enter to shutdown gdbserver")
|
raw_input("Press enter to shutdown gdbserver")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user