| <html devsite><head> |
| <title>调试 Android 平台原生代码</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>本部分总结了开发平台级功能时,可用于调试、跟踪和分析原生 Android 平台代码的实用工具和相关命令。</p> |
| |
| <p class="note"><strong>注意</strong>:本节和本网站其他部分的页面建议您使用 <code>adb</code> 与 <code>setprop</code> 参数一起调试 Android 的某些方面。请注意,在 Android 操作系统的 O 版本之前,属性名称的长度上限为 32 个字符。也就是说,要创建一个包含应用名称的 wrap 属性,您需要截断该名称以使其符合字符数限制。在 Android O 及更高版本中,此字符数上限值要大得多,应该不需要截断。</p> |
| |
| <p>本页面介绍了 <code>debuggerd</code> 的用法,debuggerd 是一种用于在应用崩溃后收集错误信息的守护进程。本部分的其他页面介绍了如何通过 <a href="https://developer.android.com/studio/command-line/dumpsys.html">Dumpsys</a> 了解系统服务状况,其中包括查看<a href="/devices/tech/debug/native-memory.html">本地内存</a>、<a href="https://developer.android.com/studio/command-line/dumpsys.html#network">网络</a>和 <a href="https://developer.android.com/studio/command-line/dumpsys.html#procstats">RAM</a> 使用情况、使用 <a href="/devices/tech/debug/asan.html">AddressSanitizer</a> 检测原生代码中的内存错误、评估<a href="/devices/tech/debug/eval_perf.html">性能问题</a>(包括 <a href="/devices/tech/debug/systrace">systrace</a>),以及使用 <a href="/devices/tech/debug/gdb.html">GNU 项目调试程序 (GDB)</a> 和其他调试工具。</p> |
| |
| <h2 id="debuggerd">使用 debuggerd</h2> |
| |
| <p><code>debuggerd</code> 进程会转储寄存器并展开堆栈。当动态链接的可执行文件启动时,系统会注册多个信号处理程序,这些处理程序会在 SIGSEGV 或 SIGABRT 等信号发送至相应进程时连接到 <code>debuggerd</code>(或 <code>debuggerd64)</code>)。</p> |
| |
| <p><code>debuggerd</code> 仅在未连接任何其他内容时才可连接。这意味着,在使用 <code>strace</code> 或 <code>gdb</code> 等工具时,将无法使用 <code>debuggerd</code>。此外,您还可以通过调用 <code>prctl(PR_SET_DUMPABLE, 0)</code> 明确阻止 <code>debuggerd</code> 进行连接,这一点在您需要选择停用崩溃报告时非常有用。</p> |
| |
| <p><code>debuggerd</code> 输出示例(已去除时间戳和无关信息):</p> |
| |
| <pre class="devsite-click-to-copy"> |
| *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** |
| Build fingerprint: 'Android/aosp_angler/angler:7.1.1/NYC/enh12211018:eng/test-keys' |
| Revision: '0' |
| ABI: 'arm' |
| pid: 17946, tid: 17949, name: crasher >>> crasher <<< |
| signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xc |
| r0 0000000c r1 00000000 r2 00000000 r3 00000000 |
| r4 00000000 r5 0000000c r6 eccdd920 r7 00000078 |
| r8 0000461a r9 ffc78c19 sl ab209441 fp fffff924 |
| ip ed01b834 sp eccdd800 lr ecfa9a1f pc ecfd693e cpsr 600e0030 |
| |
| backtrace: |
| #00 pc 0004793e /system/lib/libc.so (pthread_mutex_lock+1) |
| #01 pc 0001aa1b /system/lib/libc.so (readdir+10) |
| #02 pc 00001b91 /system/xbin/crasher (readdir_null+20) |
| #03 pc 0000184b /system/xbin/crasher (do_action+978) |
| #04 pc 00001459 /system/xbin/crasher (thread_callback+24) |
| #05 pc 00047317 /system/lib/libc.so (_ZL15__pthread_startPv+22) |
| #06 pc 0001a7e5 /system/lib/libc.so (__start_thread+34) |
| Tombstone written to: /data/tombstones/tombstone_06 |
| </pre> |
| |
| <p><code>debuggerd</code> 输出的最后一行会向日志转储一个摘要,并向磁盘写入完整的 tombstone。<em></em>tombstone 仅仅是一个包含与崩溃进程相关的额外数据的文件;文件中的信息在调试崩溃时会非常有用,尤其是对崩溃进程中的所有线程(而不只是捕捉到信号的线程)和完整内存映射进行堆栈跟踪时。</p> |
| |
| <p>假设可以找到未剥离的二进制文件,您可以将上述示例粘贴到 <code>development/scripts/stack</code>,从而获取更详细的展开信息(包含行数信息):</p> |
| |
| <p class="key-point"><strong>提示</strong>:为方便起见,如果您已启动 <code>stack</code>,它将在您的 $PATH 上显示,因此您无需提供完整路径。</p> |
| |
| <pre class="devsite-terminal devsite-click-to-copy"> |
| development/tools/stack |
| </pre> |
| |
| <p>输出示例:</p> |
| <pre class="devsite-click-to-copy"> |
| Reading native crash info from stdin |
| 03-02 23:53:49.477 17951 17951 F DEBUG : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** |
| 03-02 23:53:49.477 17951 17951 F DEBUG : Build fingerprint: 'Android/aosp_angler/angler:7.1.1/NYC/enh12211018:eng/test-keys' |
| 03-02 23:53:49.477 17951 17951 F DEBUG : Revision: '0' |
| 03-02 23:53:49.477 17951 17951 F DEBUG : ABI: 'arm' |
| 03-02 23:53:49.478 17951 17951 F DEBUG : pid: 17946, tid: 17949, name: crasher >>> crasher <<< |
| 03-02 23:53:49.478 17951 17951 F DEBUG : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xc |
| 03-02 23:53:49.478 17951 17951 F DEBUG : r0 0000000c r1 00000000 r2 00000000 r3 00000000 |
| 03-02 23:53:49.478 17951 17951 F DEBUG : r4 00000000 r5 0000000c r6 eccdd920 r7 00000078 |
| 03-02 23:53:49.478 17951 17951 F DEBUG : r8 0000461a r9 ffc78c19 sl ab209441 fp fffff924 |
| 03-02 23:53:49.478 17951 17951 F DEBUG : ip ed01b834 sp eccdd800 lr ecfa9a1f pc ecfd693e cpsr 600e0030 |
| 03-02 23:53:49.491 17951 17951 F DEBUG : |
| 03-02 23:53:49.491 17951 17951 F DEBUG : backtrace: |
| 03-02 23:53:49.492 17951 17951 F DEBUG : #00 pc 0004793e /system/lib/libc.so (pthread_mutex_lock+1) |
| 03-02 23:53:49.492 17951 17951 F DEBUG : #01 pc 0001aa1b /system/lib/libc.so (readdir+10) |
| 03-02 23:53:49.492 17951 17951 F DEBUG : #02 pc 00001b91 /system/xbin/crasher (readdir_null+20) |
| 03-02 23:53:49.492 17951 17951 F DEBUG : #03 pc 0000184b /system/xbin/crasher (do_action+978) |
| 03-02 23:53:49.492 17951 17951 F DEBUG : #04 pc 00001459 /system/xbin/crasher (thread_callback+24) |
| 03-02 23:53:49.492 17951 17951 F DEBUG : #05 pc 00047317 /system/lib/libc.so (_ZL15__pthread_startPv+22) |
| 03-02 23:53:49.492 17951 17951 F DEBUG : #06 pc 0001a7e5 /system/lib/libc.so (__start_thread+34) |
| 03-02 23:53:49.492 17951 17951 F DEBUG : Tombstone written to: /data/tombstones/tombstone_06 |
| Reading symbols from /huge-ssd/aosp-arm64/out/target/product/angler/symbols |
| Revision: '0' |
| pid: 17946, tid: 17949, name: crasher >>> crasher <<< |
| signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xc |
| r0 0000000c r1 00000000 r2 00000000 r3 00000000 |
| r4 00000000 r5 0000000c r6 eccdd920 r7 00000078 |
| r8 0000461a r9 ffc78c19 sl ab209441 fp fffff924 |
| ip ed01b834 sp eccdd800 lr ecfa9a1f pc ecfd693e cpsr 600e0030 |
| Using arm toolchain from: /huge-ssd/aosp-arm64/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/bin/ |
| |
| Stack Trace: |
| RELADDR FUNCTION FILE:LINE |
| 0004793e pthread_mutex_lock+2 bionic/libc/bionic/pthread_mutex.cpp:515 |
| v------> ScopedPthreadMutexLocker bionic/libc/private/ScopedPthreadMutexLocker.h:27 |
| 0001aa1b readdir+10 bionic/libc/bionic/dirent.cpp:120 |
| 00001b91 readdir_null+20 system/core/debuggerd/crasher.cpp:131 |
| 0000184b do_action+978 system/core/debuggerd/crasher.cpp:228 |
| 00001459 thread_callback+24 system/core/debuggerd/crasher.cpp:90 |
| 00047317 __pthread_start(void*)+22 bionic/libc/bionic/pthread_create.cpp:202 (discriminator 1) |
| 0001a7e5 __start_thread+34 bionic/libc/bionic/clone.cpp:46 (discriminator 1) |
| </pre> |
| |
| <p class="note"><strong>注意</strong>:某些系统库是使用 <code>LOCAL_STRIP_MODULE := keep_symbols</code> 编译的,可直接从 <code>debuggerd</code> 提供可用的回溯,而不会像未剥离版本那样占用较大的空间。</p> |
| |
| <p>您也可以 <code>stack</code> 整个 tombstone。示例:</p> |
| <pre class="devsite-terminal devsite-click-to-copy"> |
| stack < FS/data/tombstones/tombstone_05 |
| </pre> |
| <p>如果您刚刚在当前目录中解压过错误报告,这将非常有用。要详细了解如何诊断原生代码崩溃和 tombstone,请参阅<a href="/devices/tech/debug/native-crash.html">诊断原生代码崩溃</a>。 |
| </p> |
| |
| <h2 id="tombstone">从正在运行的进程获取堆栈跟踪/tombstone</h2> |
| |
| <p>您也可以对正在运行的进程使用 <code>debuggerd</code>。在命令行中,使用进程 ID (PID) 调用 <code>debuggerd</code>,以将完整的 tombstone 转储至 <code>stdout</code>。要确切获取进程中每个线程的堆栈,请添加 <code>-b</code> 或 <code>--backtrace</code> 标记。</p> |
| |
| </body></html> |