blob: 34096fb630d6ad1100c775536ae73380afd7e8dc [file] [log] [blame]
<html devsite>
<head>
<title>Using GDB</title>
<meta name="project_path" value="/_project.yaml" />
<meta name="book_path" value="/_book.yaml" />
</head>
<body>
<!--
Copyright 2017 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<p>The GNU Project debugger (GDB) is a commonly used Unix debugger. This page
details using <code>gdb</code> to debug Android apps and processes for platform
developers. For third-party app development, see
<a class="external"
href="https://developer.android.com/studio/debug/index.html">Debug Your
App</a>.</p>
<h2 id="prerequisites">Prerequisites</h2>
<p>To use GDB for debugging apps and processes:</p>
<ul>
<li>Set up environment with <code>envsetup.sh</code>
<li>Run the <code>lunch</code> command</li>
</ul>
<p>For more help with setting up your environment, see
<a href="/setup/build/building#initialize">Preparing to Build</a>.</p>
<h2 id=running>Debugging running apps or processes</h2>
<p>To connect to an already-running app or native daemon, use
<code>gdbclient.py</code> with a PID. For example, to debug the process with PID
1234, run:</p>
<pre class="devsite-terminal devsite-click-to-copy">
gdbclient.py -p 1234
</pre>
<p>The script sets up port forwarding, starts the appropriate
<code>gdbserver</code> on the device, starts the appropriate <code>gdb</code> on
the host, configures <code>gdb</code> to find symbols, and connects
<code>gdb</code> to the remote <code>gdbserver</code>.</p>
<aside class="note"><strong>Note:</strong> In Android 6 and lower the script was
a shell script called <code>gdbclient</code> instead of a Python script called
<code>gdbclient.py</code>.</aside>
<h2 id=starts>Debugging native process startup</h2>
<p>To debug a process as it starts, use <code>gdbserver</code> or
<code>gdbserver64</code>. For a 64-bit executable:</p>
<pre class="devsite-terminal devsite-click-to-copy">
adb shell gdbserver64 :5039 /system/bin/<var>MY_TEST_64_BIT_APP</var>
</pre>
<p>For a 32-bit executable:</p>
<pre class="devsite-terminal devsite-click-to-copy">
adb shell gdbserver :5039 /system/bin/<var>MY_TEST_32_BIT_APP</var>
</pre>
<p>Example output:</p>
<pre class="devsite-click-to-copy">
Process <var>MY_TEST_64_BIT_APP</var> created; pid = 3460
Listening on port 5039
</pre>
<p>Next, identify the application PID from the <code>gdbserver</code> output and
use it in another terminal window:</p>
<pre class="devsite-terminal devsite-click-to-copy">
gdbclient.py -p <var>APP_PID</var>
</pre>
<p>Finally, enter <strong>continue</strong> at the <code>gdb</code> prompt.</p>
<p class="note"><strong>Note:</strong> If you specify the wrong
<code>gdbserver</code>, you'll get an unhelpful error message (such as
"<code>Reply contains invalid hex digit 59</code>").</p>
<h2 id="app-startup">Debugging app startup</h2>
<p>Sometimes you want to debug an app as it starts, such as when there's a crash
and you want to step through code to see what happens <em>before</em> the crash.
<a href="#running">Attaching</a> works in some cases, but in other cases is
impossible because the app crashes before you can attach. The
<code>logwrapper</code> approach (used for <code>strace</code> and
<code>valgrind</code>) does not always work because the app might not have
permissions to open a port, and <code>gdbserver</code> inherits that
restriction.</p>
<p>To debug app startup, use the developer options in Settings to instruct
the app to wait for a Java debugger to attach:</p>
<ol>
<li>Go to <em>Settings > Developer options > Select debug app</em> and choose
your app from the list, then press <strong>Wait for debugger</strong>.</li>
<li>Start the app, either from the launcher or by using the command line to run:
<pre class="devsite-terminal devsite-click-to-copy">
adb shell am start -a android.intent.action.MAIN -n <var>APP_NAME</var>/.<var>APP_ACTIVITY</var>
</pre></li>
<li>Wait for the app to load and a dialog to appear telling you the app is
waiting for a debugger.</li>
<li>Attach <code>gdbserver</code>/<code>gdbclient</code> normally, set
breakpoints, then continue the process.</li></ol>
<p>To let the app actually run, attach a Java Debug Wire Protocol (JDWP)
debugger such as Java Debugger (jdb):</p>
<pre class="devsite-click-to-copy">
<code class="devsite-terminal">adb forward tcp:12345 jdwp:<var>XXX</var> # (Where XXX is the pid of the debugged process.)</code>
<code class="devsite-terminal">jdb -attach localhost:12345</code>
</pre>
<h2 id=crash>Debugging apps or processes that crash</h2>
<p>If you want <code>debuggerd</code> to suspend crashed processes so you can
attach <code>gdb</code>, set the appropriate property:</p>
<pre class="devsite-click-to-copy">
# Android 7.0 Nougat and later.
<code class="devsite-terminal">adb shell setprop debug.debuggerd.wait_for_gdb true</code>
</pre>
<pre class="devsite-click-to-copy">
# Android 6.0 Marshmallow and earlier.
<code class="devsite-terminal">adb shell setprop debug.db.uid 999999</code>
</pre>
<p>At the end of the usual crash output, <code>debuggerd</code> provides
instructions on how to connect <code>gdb</code> using the command:
<pre class="devsite-terminal devsite-click-to-copy">
gdbclient.py -p <var>PID</var>
</pre>
<h2 id=symbols>Debugging without symbols</h2>
<p>For 32-bit ARM, if you don’t have symbols, <code>gdb</code> can get confused
about the instruction set it is disassembling (ARM or Thumb). To specify the
instruction set chosen as the default when symbol information is missing, set
the following property:</p>
<pre class="devsite-terminal devsite-click-to-copy">
set arm fallback-mode arm # or thumb
</pre>
<h2 id="vscode">Debugging with VS Code</h2>
<p>GDB supports debugging platform code on
<a href="https://code.visualstudio.com/" class="external">Visual Studio Code</a>.
You can use the
VS Code debugger frontend instead of the GDB CLI interface to control and
debug native code running on devices.</p>
<p>Before using VS Code for debugging, make sure you install the
<a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools" class="external">
C/C++ extension</a>.</p>
<p>To debug code using VS Code:</p>
<ol>
<li>Ensure all build artifacts (such as symbols) required to run
<code>gdbclient.py</code> are present.</li>
<li>
<p>Run the following command:</p>
<pre class="prettyprint"><code class="devsite-terminal">gdbclient.py <var>-p pid | -n proc-name | -r ...</var> --setup-forwarding vscode <var>ANY_OTHER_FLAGS</var></code></pre>
<p>This prints a JSON object and <code>gdbclient.py</code> continues running.
This is expected; do not kill the <code>gdbclient.py</code> program.</p>
</li>
<li>In the debugging tab in VS Code, select
<strong>add configuration</strong>, then select
<strong>C/C++ gdb attach</strong>.
This opens a <code>launch.json</code> file and adds a new JSON object to a
list.
</li>
<li>Delete the newly added debugger configuration.</li>
<li>Copy the JSON object printed by <code>gdbclient.py</code> and paste it
into the object you just deleted. Save the changes.
</li>
<li>To reload the window to refresh the debugger list, press
<strong>Ctrl+Shift+P</strong> and type "reload window".
</li>
<li>Select the new debugger configuration and press
<strong>run</strong>. The debugger should connect after 10 to 30 seconds.
</li>
<li>When you are done debugging, go to the terminal running
<code>gdbclient.py</code> and press <strong>enter</strong> to end the
<code>gdbclient.py</code> program.
</li>
</ol>
<p>After setting up the debugger configuration for the first time,
you can skip steps 3 through 6.</p>
</body>
</html>