Android coredump生成与APK调试

本文详细介绍了如何在Android系统中生成和调试Coredump文件,针对由Zygote启动的APK,通过修改系统源码设置coredump开关,并调整大小和保存路径。调试时,利用gdb与可执行程序app_process配合,实现对Coredump的分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一直苦于Android底层C++代码的调试,以前都是通过打日志的方法调试的,效率极低。但是Linux下就可以用gdb 来调试coredump,那么Android应该也可以才对。
关于Linux下Coredump调试可以参考这篇文章:
Linux coredump 调试

然后我按照Linux的方法设置了ulimit -c 和 coredump生成位置。结果,根本就不生成coredump文件。

一、纯C\C++生成Coredump

=============================================
然后经过调研发现,需要在init.rc中setrlimit 13 40 40下增加一条记录: setrlimit 4 -1 -1。
结果,依然没有生成。
后面发现,这种方法只适用于纯C/C++程序运行。而由Zygote启动的APK还是不能生成。

二、Zygote启动的APK生成Coredump

====================================================
继续调研
Android的APK是由Zygote启动的。那么需要修改Zygote相关的代码。

如果一直打开coredump,可能会产生很多的coredump文件,极其占用空间。所以做个控制开关。
persist.debug.trace为0时关闭,设置为1时打开。

1.修改Zygote子进程的core dump size
打开art/runtime/native/dalvik_system_ZygoteHooks.cc,加入以下代码:

diff --git a/runtime/native/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc
index 891cdfa..caea8c0 100644
--- a/[runtime/native/dalvik_system_ZygoteHooks.cc]
+++ b/[runtime/native/dalvik_system_ZygoteHooks.cc]
@@ -46,7 +46,9 @@
#if defined(__linux__)
#include <sys/prctl.h>
#endif
-
+#ifdef __ANDROID__
+#include <cutils/properties.h>
+#endif
#include <sys/resource.h>
namespace art {
@@ -78,7 +80,18 @@ static void EnableDebugger() {
#endif
  // We don't want core dumps, though, so set the core dump size to 0.
  rlimit rl;
+#ifdef __ANDROID__
+  char prop_value[PROPERTY_VALUE_MAX];
+  property_get("persist.debug.trace", prop_value, "0");
+  if (prop_value[0] == '1') {
+      LOG(INFO) << "setting RLIM to infinity for process " << getpid();
+      rl.rlim_cur = RLIM_INFINITY;
+  } else {
+      rl.rlim_cur = 0;
+  }
+#else
  rl.rlim_cur = 0;
+#endif
  rl.rlim_max = RLIM_INFINITY;
  if (setrlimit(RLIMIT_CORE, &rl) == -1) {
    PLOG(ERROR) << "setrlimit(RLIMIT_CORE) failed for pid " << getpid();

2.修改Native进程的core dump size
打开system/core/init/property_service.cpp,添加随系统属性“persist.debug.trace”的处理。

diff --git a/init/property_service.cpp b/init/property_service.cpp
index 4172ba7..cdc5998 100644
--- a/[init/property_service.cpp]
+++ b/[init/property_service.cpp]
@@ -698,6 +698,20 @@ static void load_override_properties() {
    }
}
+static int check_rlim_action() {
+    struct rlimit rl;
+    std::string value  = android::base::GetProperty("persist.debug.trace", "");
+
+    if(value == "1") {
+        rl.rlim_cur = RLIM_INFINITY;
+        rl.rlim_max = RLIM_INFINITY;
+        if (setrlimit(RLIMIT_CORE, &rl) < 0) {
+            PLOG(ERROR) << "could not enable core file generation";
+        }
+    }
+    return 0;
+}
+
/* When booting an encrypted system, /data is not mounted when the
  * property service is started, so any properties stored there are
  * not loaded.  Vold triggers init to load these properties once it
@@ -723,6 +737,8 @@ void load_persist_props(void) {
    }
    persistent_properties_loaded = true;
    property_set("ro.persistent_properties.ready", "true");
+    /*check for coredump*/
+    check_rlim_action();
}
void load_recovery_id_prop() {

3.设置coredump文件名称格式及保存路径
在system/core/rootdir/init.rc文件

diff --git a/rootdir/init.rc b/rootdir/init.rc
index f95d58e..7d0fdfb 100644
--- a/[rootdir/init.rc]
+++ b/[rootdir/init.rc]
@@ -700,6 +700,11 @@ on property:vold.decrypt=trigger_load_persist_props
    start logd
    start logd-reinit
+# corefile limit
+on property:persist.debug.trace=1
+  mkdir /data/core 0777 root root
+  write /proc/sys/kernel/core_pattern "/data/core/%E.%p.%e"
+
on property:vold.decrypt=trigger_post_fs_data
    trigger post-fs-data
    trigger zygote-start

这样,如果想生成coredump文件,就执行setprop persist.debug.trace 1;否则就设置为0.
当然,每次设置后要重启系统。

二、APK调试Coredump

终于生成了coredump文件了,很开心。但是准备调试的时候,傻眼了。
没有可执行程序啊,咋玩。
好在有万能的谷歌。

Zygote的可执行程序是app_process。既然APK是由Zygote启动的,那就调试它。

1、启动gdb命令(不必用ndk的gdb,直接用linux的gdb就可以)

ubuntu@ubuntu:~/imgs/system$ gdb 
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04.1) 9.2
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "aarch64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word".

2、设置动态库搜索加载路径:
这个路径可以是系统源码编译后的库路径,我是做成了镜像然后挂载在linux上的(/home/ubuntu/imgs)。

(gdb)  set solib-search-path /home/ubuntu/imgs/system/system/lib64/

3、加载启动程序:

(gdb) file /home/ubuntu/zyp/imgs/system/system/bin/app_process64                      
Reading symbols from /home/ubuntu/zyp/imgs/system/system/bin/app_process64...
Reading symbols from .gnu_debugdata for /home/ubuntu/zyp/imgs/system/system/bin/app_process64...
(No debugging symbols found in .gnu_debugdata for /home/ubuntu/zyp/imgs/system/system/bin/app_process64)

4、加载corefile

(gdb) corefile /home/ubuntu/zyp/core***



Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x0000f7cad281f7d4 in VCEncGetAsicConfig () from /home/ubuntu/zyp/imgs/system/system/lib64/libh2enc.so
[Current thread is 1 (LWP 1552)]
(gdb) bt
#0  0x0000f7cad281f7d4 in VCEncGetAsicConfig () from /home/ubuntu/imgs/system/system/lib64/libh2enc.so
#1  0x0000f7cad2828894 in VCEncSetCodingCtrl () from /home/ubuntu/imgs/system/system/lib64/libh2enc.so
#2  0x0000f7cad27a5fc0 in ?? () from /home/ubuntu/imgs/system/system/lib64/libinsvid.so
#3  0x0000f7cad27a9ac4 in insvid_h26xe_init () from /home/ubuntu/imgs/system/system/lib64/libinsvid.so

大功告成!

参考:
Android下生成core dump的方法
Android P 开启抓取Coredump功能
Android——coredump解析

<think>好的,用户这次提供了一个新的错误日志,看起来是关于Android应用程序崩溃的问题。首先,我需要仔细分析日志中的各个部分,确定问题所在。 首先,用户提到Cmdline是com.sisheng.aiaio,这说明崩溃发生在该应用程序的进程内。时间戳显示2025年,不过这可能是个测试或模拟环境的时间,暂时不用考虑时间问题。 接下来,日志中的关键部分是关于native层的崩溃:pid和tid都是18912,进程名是com.sisheng.aiaio,崩溃发生在libyolov8pose.so这个动态库中,具体是在Java_com_sisheng_funscreen_pose_Yolov8Pose_getCameraFrame函数的偏移地址0xaffac处,并且有BuildId。这说明崩溃是在调用JNI方法时发生的,可能是在处理相机帧数据的环节。 用户之前的问题是关于RKNN的卷积层提交失败,而这次是Android应用崩溃,两者看起来不同,但可能用户都是在处理深度学习模型相关的应用问题。用户可能是开发者,遇到了模型部署或JNI层的崩溃问题。 需要分析可能的原因。首先,libyolov8pose.so可能YOLOv8姿态估计模型相关,可能使用了RKNN或其他推理引擎。崩溃发生在native代码中,可能的原因包括: 1. **内存问题**:比如空指针解引用、内存越界访问、堆栈溢出等。 2. **JNI调用错误**:在JNI方法中没有正确处理参数或对象引用,导致崩溃。 3. **模型推理错误**:模型加载失败,输入数据格式不正确,导致底层库崩溃。 4. **多线程问题**:如果相机帧处理在子线程中进行,可能存在线程同步问题。 5. **库版本不兼容**:使用的动态库Android系统或设备架构不兼容,比如armeabi-v7aarm64-v8a不匹配。 6. **资源泄漏**:如未释放的句柄或内存,累积导致崩溃。 接下来,需要给出解决步骤。首先检查堆栈跟踪,但由于日志中只显示了#00的调用栈,信息有限。建议用户获取完整的堆栈跟踪,尤其是backtrace的所有帧。此外,查看logcat的完整日志,寻找崩溃前的警告或错误信息。 可能的解决方案包括: 1. **检查JNI代码**:确保JNI方法中的参数正确,没有错误的内存访问。特别是getCameraFrame方法,可能涉及图像数据的处理,需要检查数据指针是否正确,数组是否越界。 2. **验证模型输入**:确保输入给模型的数据格式(如尺寸、颜色空间)模型期望的一致。例如,如果模型需要RGB图像而输入是BGR,可能导致处理错误。 3. **内存分析**:使用AddressSanitizer或Valgrind检查内存问题,或者在代码中添加日志,追踪内存分配和释放的情况。 4. **多线程同步**:如果相机帧处理涉及多线程,检查是否有竞态条件或未同步的资源访问。 5. **库兼容性**:确认libyolov8pose.so是否针对当前设备的CPU架构编译,如arm64-v8a。如果应用打包了多个ABI版本的库,确保正确加载。 6. **更新依赖库**:如果使用了RKNN或其他推理库,确保其版本当前环境兼容,并更新到最新版本,特别是如果之前的问题建议更新RKNN工具链,可能相关。 另外,用户提供的BuildId可以用来唯一标识该库的构建版本,有助于对比是否使用了正确的版本。可以建议用户检查构建过程中是否有错误,或者尝试重新编译该库并替换。 最后,如果上述步骤无法解决,建议用户使用调试工具(如GDB或LLDB)附加到进程,或者在崩溃时生成core dump文件进行分析,以更精确地定位崩溃的代码行。</think>以下是对该错误日志的逐层解析和解决方案: --- ### **一、错误日志关键信息解读** 1. **进程信息** - `Cmdline: com.sisheng.aiaio` → 崩溃发生在 Android 应用 `com.sisheng.aiaio` 的进程内。 - `pid: 18912, tid: 18912` → 进程和线程 ID 相同,说明崩溃发生在主线程。 2. **崩溃位置** - `pc 00000000000affac` → 程序计数器指向崩溃时的代码地址。 - `libyolov8pose.so` → 崩溃发生在该动态链接库中,推测是 YOLOv8 姿态估计模型的推理库。 - `Java_com_sisheng_funscreen_pose_Yolov8Pose_getCameraFrame+316` → 崩溃位置在 JNI 方法 `getCameraFrame` 内,可能相机帧处理相关。 3. **其他线索** - `BuildId: 2b52cf67f4d0a322...` → 库的构建标识符,可用于验证库版本是否匹配。 --- ### **二、可能原因分析** 1. **Native 层代码问题** - JNI 方法 `getCameraFrame` 中存在空指针、内存越界或非法内存访问。 - 相机帧数据格式错误(如分辨率、颜色空间不匹配)。 2. **模型推理异常** - YOLOv8 模型输入/输出维度不匹配。 - 模型文件损坏或未正确加载。 3. **多线程冲突** - 相机帧处理线程 UI 主线程资源竞争。 4. **库兼容性问题** - `libyolov8pose.so` 未针对当前设备 CPU 架构(如 arm64-v8a)编译。 5. **资源泄漏** - 未释放模型推理上下文或相机资源。 --- ### **三、解决步骤** #### **1. 获取完整崩溃堆栈** - **通过 `adb logcat` 过滤完整日志**: ```bash adb logcat | grep "com.sisheng.aiaio" ``` - **重点检查 `backtrace` 所有帧**,定位具体崩溃代码位置。 #### **2. 检查 JNI 代码** - **验证 `getCameraFrame` 方法的参数和内存操作**: ```cpp // 示例:检查输入数据指针是否为空 JNIEXPORT void JNICALL Java_com_sisheng_funscreen_pose_Yolov8Pose_getCameraFrame( JNIEnv *env, jobject thiz, jbyteArray frameData) { jbyte *data = env->GetByteArrayElements(frameData, nullptr); if (data == nullptr) { // 处理空指针 return; } // 处理数据 env->ReleaseByteArrayElements(frameData, data, 0); } ``` #### **3. 验证模型输入输出** - **检查输入数据格式**(如 RGB/BGR、尺寸是否匹配模型要求): ```python # 示例:模型输入尺寸为 640x640 input_shape = (640, 640) ``` #### **4. 排查多线程问题** - **确保相机帧处理在子线程执行**,避免阻塞主线程: ```java // Java 中启动子线程处理相机帧 new Thread(() -> { nativeProcessFrame(frameData); }).start(); ``` #### **5. 检查库兼容性** - **确认 `libyolov8pose.so` 的 CPU 架构**: ```bash file libyolov8pose.so # 输出应为 arm64-v8a ``` #### **6. 使用调试工具** - **通过 AddressSanitizer 检测内存问题**: 在 Android NDK 编译时添加 `-fsanitize=address` 标志。 - **生成 Core Dump**: ```bash adb shell setprop debug.db.uid 32768 # 允许生成 core dump ``` --- ### **四、备选方案** 1. **降级依赖库版本**:若更新后出现崩溃,尝试回退到稳定版本。 2. **简化测试用例**:移除模型推理逻辑,逐步添加功能定位问题。 3. **联系库开发者**:提供 `BuildId` 和崩溃堆栈,请求技术支持。 --- ### **五、总结** ✅ **优先级建议**: 1. 检查 JNI 内存操作 → 2. 验证模型输入 → 3. 排查多线程 → 4. 库兼容性 此崩溃通常由 Native 层代码缺陷或资源竞争引起,需结合日志和调试工具深入分析。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值