| <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> |