lldb随机crash
Android V代码里预编译好的lldb经常会在执行取类成员变量地址,或执行一些cast操作的时候出现crash,有时候在crash栈里能看到一些ndk相关的逻辑,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| source build/envsetup.sh
# 请根据实际项目选择实际要lunch的选项
lunch xxx
# 调试com.wwm.demo
lldbclient.py -n com.wwm.demo
(lldb) expr (art::mirror::String*)0x73de6320
LLDB diagnostics will be written to /tmp/diagnostics-9ef8bb
Please include the directory content when filing a bug report
PLEASE submit a bug report to https://github.com/android-ndk/ndk/issues and include the crash backtrace.
Stack dump:
0. Program arguments: /home/wwm/aosp/prebuilts/clang/host/linux-x86/clang-r522817/bin/lldb --source /tmp/tmpnij9jjx0
#0 0x0000559dd6cb4702 (/home/wwm/aosp/prebuilts/clang/host/linux-x86/clang-r522817/bin/lldb+0x82702)
#1 0x0000559dd6cb36d0 (/home/wwm/aosp/prebuilts/clang/host/linux-x86/clang-r522817/bin/lldb+0x816d0)
#2 0x0000559dd6cb4b82 (/home/wwm/aosp/prebuilts/clang/host/linux-x86/clang-r522817/bin/lldb+0x82b82)
#3 0x00007fdeb2b46520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
#4 0x00007fdeb5517ccf clang::CXXRecordDecl::addedMember(clang::Decl*) DeclCXX.cpp:0:0
#5 0x00007fdeb5513fe9 clang::DeclContext::addDecl(clang::Decl*) DeclBase.cpp:0:0
...
/home/wwm/aosp/prebuilts/clang/host/linux-x86/clang-r522817/bin/lldb.sh: line 6: 731181 Segmentation fault (core dumped) "$CURDIR/lldb" "$@"
|
怀疑是Google修改的部分代码有问题,但没时间去调查具体原因,就想先使用llvm官方的lldb,但发现它又不支持lzma压缩算法,没法正确读取.gne_debuginfo段,那就没法调试Android odex文件里的汇编了;
最终不得不我们自己编译一个支持lzma压缩算法的lldb使用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| # 下载最新的llvm整个项目代码
1.下载 https://github.com/llvm/llvm-project/archive/refs/tags/llvmorg-19.1.1.zip
2. 解压llvm-project-llvmorg-19.1.0.zip
3. mv llvm-project-llvmorg-19.1.0 llvm-project
# 安装依赖
sudo apt install build-essential \
libedit-dev libxml2-dev llvm-dev \
doxygen liblzma-dev
# 准备
cd llvm-project
mkdir mybuild && cd mybuild
# 把最终的工具安装到mybuild/out下
mkdir out
# 编译clang和lldb
cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX=$PWD/out -DLLVM_ENABLE_PROJECTS="clang;lldb" -DLLVM_ENABLE_LZMA=ON -DCMAKE_BUILD_TYPE=Release -DLLDB_TEST_COMPILER=/usr/bin/clang ../llvm
make -j32
# 待编译完成后,会在 mybuild/bin/目录下看到lldb,clang等可执行文件
|
把Android V源码里的prebuilts/clang/host/linux-x86/clang-r522817/bin/lldb.sh里的lldb路径换成我们编译好的lldb,然后再使用lldbclient.py就没再crash了
无法回溯出完整的调用栈
发现公司ROM的symbols文件中boot.oat等文件是在out/target/product/ssi/symbols/apex/art_boot_images/目录下,需把它们移动到out/target/product/ssi/symbols/apex/com.android.art/:
1
| mv out/target/product/ssi/symbols/apex/art_boot_images/javalib out/target/product/ssi/symbols/apex/com.android.art/
|
然后重行执行lldbclient/gdbclient后应该就可以回溯出完整的调用栈了
加载App的so/odex里的symbols
需要把app的so/odex目录放到symbols目录下的对应位置
1
2
3
4
5
6
7
8
| adb shell pm path com.wwm.demo
package:/data/app/~~cGEMvclUneLY3buiqk0CVA==/com.wwm.demo-nQ84CPYSeMSgWTm-mD7lTw==/base.apk
# 为了简单,把app的安装目录都pull出来,因为odex在/data/app/~~cGEMvclUneLY3buiqk0CVA==/com.wwm.demo-nQ84CPYSeMSgWTm-mD7lTw==/oat/arm64下
mkdir -p out/target/product/ssi/symbols/data/app
adb pull /data/app/~~cGEMvclUneLY3buiqk0CVA==/ out/target/product/ssi/symbols/data/app/
# 而so文件在/data/app/~~cGEMvclUneLY3buiqk0CVA==/com.wwm.demo-nQ84CPYSeMSgWTm-mD7lTw==/lib/arm64下
# 所以得把带有symbols的so文件再放到out/target/product/ssi/symbols/data/app/~~cGEMvclUneLY3buiqk0CVA==/com.wwm.demo-nQ84CPYSeMSgWTm-mD7lTw==/lib/arm64
|
查看一个lib的symbol文件是否被成功加载上了
以前用gdb的话,就很简单
1
| (gdb) info sharedlibrary libc.so
|
lldb的话,没有等价于info sharedlibrary的命令,但可以随便找这个lib的一个函数,例如libc里的malloc
1
2
3
4
5
6
7
8
9
10
11
12
| (lldb) image lookup -vn malloc
1 match found in /home/wwm/aosp/out/target/product/missi/symbols/apex/com.android.runtime/lib64/bionic/libc.so:
Address: libc.so[0x00000000000476bc] (libc.so.PT_LOAD[1]..text + 5820)
Summary: libc.so`::malloc(size_t) at malloc_common.cpp:136
Module: file = "/home/wwm/aosp/out/target/product/missi/symbols/apex/com.android.runtime/lib64/bionic/libc.so", arch = "aarch64"
CompileUnit: id = {0x00000004}, file = "bionic/libc/bionic/malloc_common.cpp", language = "c++14"
Function: id = {0x00004b8e}, name = "::malloc(size_t)", range = [0x0000007720d486bc-0x0000007720d48740)
FuncType: id = {0x00004b8e}, byte-size = 0, decl = malloc_common.cpp:136, compiler_type = "void *(size_t)"
Blocks: id = {0x00004b8e}, range = [0x7720d486bc-0x7720d48740)
LineEntry: [0x0000007720d486bc-0x0000007720d486cc): bionic/libc/bionic/malloc_common.cpp:136
Symbol: id = {0x000027c4}, range = [0x0000007720d486bc-0x0000007720d48740), name="malloc"
Variable: id = {0x00004b9d}, name = "bytes", type = "size_t", valid ranges = <block>, location = [0x00000000000476bc, 0x00000000000476d8) -> DW_OP_reg0 W0, decl = malloc_common.cpp:136
|
如果输出包含 CompileUnit: id = 则说明libc的symbol加载成功了