Merge "gdbclient.py alternative frontend support" am: 24dc4630c7
am: c34956f0cc
Change-Id: I41c5f69291c9a6be944f10732e0b40e8c8c3e389
This commit is contained in:
@@ -17,11 +17,13 @@
|
|||||||
|
|
||||||
import adb
|
import adb
|
||||||
import argparse
|
import argparse
|
||||||
|
import json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
import textwrap
|
||||||
|
|
||||||
# Shared functions across gdbclient.py and ndk-gdb.py.
|
# Shared functions across gdbclient.py and ndk-gdb.py.
|
||||||
import gdbrunner
|
import gdbrunner
|
||||||
@@ -64,6 +66,11 @@ def parse_args():
|
|||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--user", nargs="?", default="root",
|
"--user", nargs="?", default="root",
|
||||||
help="user to run commands as on the device [default: root]")
|
help="user to run commands as on the device [default: root]")
|
||||||
|
parser.add_argument(
|
||||||
|
"--setup-forwarding", default=None, choices=["gdb", "vscode"],
|
||||||
|
help=("Setup the gdbserver and port forwarding. Prints commands or " +
|
||||||
|
".vscode/launch.json configuration needed to connect the debugging " +
|
||||||
|
"client to the server."))
|
||||||
|
|
||||||
return parser.parse_args()
|
return parser.parse_args()
|
||||||
|
|
||||||
@@ -153,33 +160,60 @@ def handle_switches(args, sysroot):
|
|||||||
|
|
||||||
return (binary_file, pid, run_cmd)
|
return (binary_file, pid, run_cmd)
|
||||||
|
|
||||||
|
def generate_vscode_script(gdbpath, root, sysroot, binary_name, port, dalvik_gdb_script, solib_search_path):
|
||||||
|
# TODO It would be nice if we didn't need to copy this or run the
|
||||||
|
# gdbclient.py program manually. Doing this would probably require
|
||||||
|
# writing a vscode extension or modifying an existing one.
|
||||||
|
res = {
|
||||||
|
"name": "(gdbclient.py) Attach {} (port: {})".format(binary_name.split("/")[-1], port),
|
||||||
|
"type": "cppdbg",
|
||||||
|
"request": "launch", # Needed for gdbserver.
|
||||||
|
"cwd": root,
|
||||||
|
"program": binary_name,
|
||||||
|
"MIMode": "gdb",
|
||||||
|
"miDebuggerServerAddress": "localhost:{}".format(port),
|
||||||
|
"miDebuggerPath": gdbpath,
|
||||||
|
"setupCommands": [
|
||||||
|
{
|
||||||
|
# Required for vscode.
|
||||||
|
"description": "Enable pretty-printing for gdb",
|
||||||
|
"text": "-enable-pretty-printing",
|
||||||
|
"ignoreFailures": True,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "gdb command: dir",
|
||||||
|
"text": "-environment-directory {}".format(root),
|
||||||
|
"ignoreFailures": False
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "gdb command: set solib-search-path",
|
||||||
|
"text": "-gdb-set solib-search-path {}".format(":".join(solib_search_path)),
|
||||||
|
"ignoreFailures": False
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "gdb command: set solib-absolute-prefix",
|
||||||
|
"text": "-gdb-set solib-absolute-prefix {}".format(sysroot),
|
||||||
|
"ignoreFailures": False
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
if dalvik_gdb_script:
|
||||||
|
res["setupCommands"].append({
|
||||||
|
"description": "gdb command: source art commands",
|
||||||
|
"text": "-interpreter-exec console \"source {}\"".format(dalvik_gdb_script),
|
||||||
|
"ignoreFailures": False,
|
||||||
|
})
|
||||||
|
return json.dumps(res, indent=4)
|
||||||
|
|
||||||
def generate_gdb_script(sysroot, binary_file, is64bit, port, connect_timeout=5):
|
def generate_gdb_script(root, sysroot, binary_name, port, dalvik_gdb_script, solib_search_path, connect_timeout):
|
||||||
# Generate a gdb script.
|
|
||||||
# TODO: Detect the zygote and run 'art-on' automatically.
|
|
||||||
root = os.environ["ANDROID_BUILD_TOP"]
|
|
||||||
symbols_dir = os.path.join(sysroot, "system", "lib64" if is64bit else "lib")
|
|
||||||
vendor_dir = os.path.join(sysroot, "vendor", "lib64" if is64bit else "lib")
|
|
||||||
|
|
||||||
solib_search_path = []
|
|
||||||
symbols_paths = ["", "hw", "ssl/engines", "drm", "egl", "soundfx"]
|
|
||||||
vendor_paths = ["", "hw", "egl"]
|
|
||||||
solib_search_path += [os.path.join(symbols_dir, x) for x in symbols_paths]
|
|
||||||
solib_search_path += [os.path.join(vendor_dir, x) for x in vendor_paths]
|
|
||||||
solib_search_path = ":".join(solib_search_path)
|
solib_search_path = ":".join(solib_search_path)
|
||||||
|
|
||||||
gdb_commands = ""
|
gdb_commands = ""
|
||||||
gdb_commands += "file '{}'\n".format(binary_file.name)
|
gdb_commands += "file '{}'\n".format(binary_name)
|
||||||
gdb_commands += "directory '{}'\n".format(root)
|
gdb_commands += "directory '{}'\n".format(root)
|
||||||
gdb_commands += "set solib-absolute-prefix {}\n".format(sysroot)
|
gdb_commands += "set solib-absolute-prefix {}\n".format(sysroot)
|
||||||
gdb_commands += "set solib-search-path {}\n".format(solib_search_path)
|
gdb_commands += "set solib-search-path {}\n".format(solib_search_path)
|
||||||
|
if dalvik_gdb_script:
|
||||||
dalvik_gdb_script = os.path.join(root, "development", "scripts", "gdb",
|
|
||||||
"dalvik.gdb")
|
|
||||||
if not os.path.exists(dalvik_gdb_script):
|
|
||||||
logging.warning(("couldn't find {} - ART debugging options will not " +
|
|
||||||
"be available").format(dalvik_gdb_script))
|
|
||||||
else:
|
|
||||||
gdb_commands += "source {}\n".format(dalvik_gdb_script)
|
gdb_commands += "source {}\n".format(dalvik_gdb_script)
|
||||||
|
|
||||||
# Try to connect for a few seconds, sometimes the device gdbserver takes
|
# Try to connect for a few seconds, sometimes the device gdbserver takes
|
||||||
@@ -209,6 +243,33 @@ end
|
|||||||
|
|
||||||
return gdb_commands
|
return gdb_commands
|
||||||
|
|
||||||
|
def generate_setup_script(gdbpath, sysroot, binary_file, is64bit, port, debugger, connect_timeout=5):
|
||||||
|
# Generate a setup script.
|
||||||
|
# TODO: Detect the zygote and run 'art-on' automatically.
|
||||||
|
root = os.environ["ANDROID_BUILD_TOP"]
|
||||||
|
symbols_dir = os.path.join(sysroot, "system", "lib64" if is64bit else "lib")
|
||||||
|
vendor_dir = os.path.join(sysroot, "vendor", "lib64" if is64bit else "lib")
|
||||||
|
|
||||||
|
solib_search_path = []
|
||||||
|
symbols_paths = ["", "hw", "ssl/engines", "drm", "egl", "soundfx"]
|
||||||
|
vendor_paths = ["", "hw", "egl"]
|
||||||
|
solib_search_path += [os.path.join(symbols_dir, x) for x in symbols_paths]
|
||||||
|
solib_search_path += [os.path.join(vendor_dir, x) for x in vendor_paths]
|
||||||
|
|
||||||
|
dalvik_gdb_script = os.path.join(root, "development", "scripts", "gdb", "dalvik.gdb")
|
||||||
|
if not os.path.exists(dalvik_gdb_script):
|
||||||
|
logging.warning(("couldn't find {} - ART debugging options will not " +
|
||||||
|
"be available").format(dalvik_gdb_script))
|
||||||
|
dalvik_gdb_script = None
|
||||||
|
|
||||||
|
if debugger == "vscode":
|
||||||
|
return generate_vscode_script(
|
||||||
|
gdbpath, root, sysroot, binary_file.name, port, dalvik_gdb_script, solib_search_path)
|
||||||
|
elif debugger == "gdb":
|
||||||
|
return generate_gdb_script(root, sysroot, binary_file.name, port, dalvik_gdb_script, solib_search_path, connect_timeout)
|
||||||
|
else:
|
||||||
|
raise Exception("Unknown debugger type " + debugger)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
required_env = ["ANDROID_BUILD_TOP",
|
required_env = ["ANDROID_BUILD_TOP",
|
||||||
@@ -258,12 +319,6 @@ def main():
|
|||||||
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))
|
||||||
|
|
||||||
# Generate a gdb script.
|
|
||||||
gdb_commands = generate_gdb_script(sysroot=sysroot,
|
|
||||||
binary_file=binary_file,
|
|
||||||
is64bit=is64bit,
|
|
||||||
port=args.port)
|
|
||||||
|
|
||||||
# Find where gdb is
|
# Find where gdb is
|
||||||
if sys.platform.startswith("linux"):
|
if sys.platform.startswith("linux"):
|
||||||
platform_name = "linux-x86"
|
platform_name = "linux-x86"
|
||||||
@@ -271,14 +326,39 @@ def main():
|
|||||||
platform_name = "darwin-x86"
|
platform_name = "darwin-x86"
|
||||||
else:
|
else:
|
||||||
sys.exit("Unknown platform: {}".format(sys.platform))
|
sys.exit("Unknown platform: {}".format(sys.platform))
|
||||||
|
|
||||||
gdb_path = os.path.join(root, "prebuilts", "gdb", platform_name, "bin",
|
gdb_path = os.path.join(root, "prebuilts", "gdb", platform_name, "bin",
|
||||||
"gdb")
|
"gdb")
|
||||||
|
# Generate a gdb script.
|
||||||
|
setup_commands = generate_setup_script(gdbpath=gdb_path,
|
||||||
|
sysroot=sysroot,
|
||||||
|
binary_file=binary_file,
|
||||||
|
is64bit=is64bit,
|
||||||
|
port=args.port,
|
||||||
|
debugger=args.setup_forwarding or "gdb")
|
||||||
|
|
||||||
# Print a newline to separate our messages from the GDB session.
|
if not args.setup_forwarding:
|
||||||
print("")
|
# Print a newline to separate our messages from the GDB session.
|
||||||
|
print("")
|
||||||
|
|
||||||
# Start gdb.
|
# Start gdb.
|
||||||
gdbrunner.start_gdb(gdb_path, gdb_commands)
|
gdbrunner.start_gdb(gdb_path, setup_commands)
|
||||||
|
else:
|
||||||
|
print("")
|
||||||
|
print setup_commands
|
||||||
|
print("")
|
||||||
|
if args.setup_forwarding == "vscode":
|
||||||
|
print textwrap.dedent("""
|
||||||
|
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
|
||||||
|
the gdbserver and close all the ports.""")
|
||||||
|
else:
|
||||||
|
print textwrap.dedent("""
|
||||||
|
Paste the above gdb commands into the gdb frontend to setup the gdbserver
|
||||||
|
connection. Press enter in this terminal once debugging is finished to
|
||||||
|
shutdown the gdbserver and close all the ports.""")
|
||||||
|
print("")
|
||||||
|
raw_input("Press enter to shutdown gdbserver")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|||||||
Reference in New Issue
Block a user