summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Light <allight@google.com>2019-01-18 23:53:07 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2019-01-18 23:53:07 +0000
commit24dc4630c7a46477147c06845d3a939124fd6505 (patch)
tree9d0d01ea555ea95f7f26368f0b00b90376eeb04a
parentd4193fefd4986a93f8452badb736d613ecaa3ad6 (diff)
parent92476657e3fda2bc2b8f52e438c6fd4c698016c2 (diff)
downloaddevelopment-24dc4630c7a46477147c06845d3a939124fd6505.tar.gz
Merge "gdbclient.py alternative frontend support"
-rwxr-xr-xscripts/gdbclient.py146
1 files changed, 113 insertions, 33 deletions
diff --git a/scripts/gdbclient.py b/scripts/gdbclient.py
index ff0ee40d1..611b2e89b 100755
--- a/scripts/gdbclient.py
+++ b/scripts/gdbclient.py
@@ -17,11 +17,13 @@
import adb
import argparse
+import json
import logging
import os
import re
import subprocess
import sys
+import textwrap
# Shared functions across gdbclient.py and ndk-gdb.py.
import gdbrunner
@@ -64,6 +66,11 @@ def parse_args():
parser.add_argument(
"--user", nargs="?", 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()
@@ -153,33 +160,60 @@ def handle_switches(args, sysroot):
return (binary_file, pid, run_cmd)
-
-def generate_gdb_script(sysroot, binary_file, is64bit, port, connect_timeout=5):
- # 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]
+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(root, sysroot, binary_name, port, dalvik_gdb_script, solib_search_path, connect_timeout):
solib_search_path = ":".join(solib_search_path)
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 += "set solib-absolute-prefix {}\n".format(sysroot)
gdb_commands += "set solib-search-path {}\n".format(solib_search_path)
-
- 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:
+ if dalvik_gdb_script:
gdb_commands += "source {}\n".format(dalvik_gdb_script)
# Try to connect for a few seconds, sometimes the device gdbserver takes
@@ -209,6 +243,33 @@ end
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():
required_env = ["ANDROID_BUILD_TOP",
@@ -258,12 +319,6 @@ def main():
gdbrunner.forward_gdbserver_port(device, local=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
if sys.platform.startswith("linux"):
platform_name = "linux-x86"
@@ -271,14 +326,39 @@ def main():
platform_name = "darwin-x86"
else:
sys.exit("Unknown platform: {}".format(sys.platform))
+
gdb_path = os.path.join(root, "prebuilts", "gdb", platform_name, "bin",
"gdb")
-
- # Print a newline to separate our messages from the GDB session.
- print("")
-
- # Start gdb.
- gdbrunner.start_gdb(gdb_path, gdb_commands)
+ # 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")
+
+ if not args.setup_forwarding:
+ # Print a newline to separate our messages from the GDB session.
+ print("")
+
+ # Start gdb.
+ 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__":
main()