breakpad的学习与使用笔记

TIPS总结

使用AS自带的minidump_stackwalk

不一定要下载Breakpad的源码去编译才可以使用minidump_staackwalk去读/解析minidump文件的内容和查看崩溃崩溃信息,我们可以使用Android Studio自带的minidump_stackwalk。如在macOS下,minidump_stackwalk的位置如下

# AS安装目录下的bin/lldb/bin下
Applications/Android Studio.app/Contents/bin/lldb/bin/minidump_stackwalk
或
Applications/Android Studio.app/Contents/plugins/android-ndk/resources/lldb/bin

各个平台下编译的dump_syms只能处理各个平台的库的符号

breakpad 是跨平台的,支持linux、window和Mac os系统,不同平台上的编译配置也是不同的

  • linux 平台编译出来的dump_syms 仅能再linux上运行,来处理该平台的动态库(*.so)和符号信息
  • macOS 平台编译出来的dump_syms 仅能再mac OS 上运行,来处理该平台的动态库(*.dylib)的符号信息
  • window 平台编译出来的dump_syms,仅能在Window上运行,来处理该平台的动态库(*.dll)的符号信息
    如果在macOS使用dump_sym对动态库so文件,生成调试信息,为提示如下出错信息
file is neither a fat binary file nor a Mach-O object file

minidump_stackwalk + addr2line

使用minidump_stackwalk读取minidump文件时没有dump_sysms生成的调试符号信息时,输出的崩溃堆栈会缺少函数符号和行号等信息,

// -s 输出崩溃堆栈信息
$ /Applications/Android\ Studio.app/Contents/bin/lldb/bin/minidump_stackwalk -s 887982de-b87e-4d1a-bce21485-c7ae0dab.dmp >>result.log

//如下是输出示例的部分内容

Operating system: Android
                  0.0.0 Linux 4.14.186+ #1 SMP PREEMPT Tue Jul 19 21:15:54 CST 2022 armv8l
CPU: arm
     ARMv1 ARM part(0x4100d450) features: half,thumb,fastmult,vfpv2,edsp,neon,vfpv3,tls,vfpv4,idiva,idivt
     8 CPUs

Crash reason:  SIGSEGV
Crash address: 0x0
Process uptime: not available

Thread 47 (crashed)
 0  0x0
     r0 = 0xede684a0    r1 = 0x00000000    r2 = 0x62fa1229    r3 = 0x00000000
     r4 = 0xb29bcebc    r5 = 0x00000001    r6 = 0xe0d05704    r7 = 0xb29bcfc8
     r8 = 0xb29bcf00    r9 = 0xffffffff   r10 = 0xe0d05704   r12 = 0xc9c029e4
     fp = 0xe0d056ec    sp = 0xb29bce08    lr = 0xb3e8a7e3    pc = 0x00000000
    Found by: given as instruction pointer in context

    Stack contents:
     b29bce08 bc ce 9b b2 00 00 00 00 45 92 9f c5 00 00 00 00  ........E.......
     b29bce18 10 cf 9b b2 04 57 d0 e0 00 00 00 00 01 00 00 00  .....W..........
     b29bce28 5c 72 e4 ea 61 60 e4 b3                          \r..a`..        
    Possible instruction pointers:

 1  libXXX.so + 0x3f05f //这个址址值是库的相对地址了,结合使用addr2line的时候不会做转化了!
     sp = 0xb29bce30    pc = 0xb3e46061
    Found by: stack scanning

    Stack contents:
     b29bce30 c8 00 00 00 38 ac f2 b3                          ....8...        
    Possible instruction pointers:

 2  libXXX.so + 0x123c36
     sp = 0xb29bce38    pc = 0xb3f2ac38
    Found by: stack scanning

此时如果我们有对应的带有调试信息版本的so( 即with debug_info, not stripped的版本),我们就可以用addr2line等命令行工具去手动的解析地址对应的函数名和行号。即有dump文件跟so就可以手动解析崩溃堆栈

addr2line的使用示例如下

llvm-addr2line -p -f -C -e libXXX.so 0x3f05f 0x123c36
// llvm-addr2line is /Users/username/Library/Android/sdk/ndk/23.0.7599858/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-addr2line

有关 debug identifier

在这里插入图片描述
在这里插入图片描述
关键的代码是file_id.cc下的FileID::ConvertIdentifierToUUIDString跟FileID::ElfFileIdentifierFromMappedFile这两个方法,debug identifiers的值在非PDB格式下是读取so的build_id的值,如果没有build_id就读取so代码段的前面部份字节的值,然后对读取后的值转为UUID的格式

bool FileID::ElfFileIdentifierFromMappedFile(const void* base,
                                             wasteful_vector<uint8_t>& identifier) {
  // Look for a build id note first.
  if (FindElfBuildIDNote(base, identifier))
    return true;

  // Fall back on hashing the first page of the text section.
  return HashElfTextSection(base, identifier);
}
// These three functions are not ever called in an unsafe context, so it's OK
// to allocate memory and use libc.
static string bytes_to_hex_string(const uint8_t* bytes, size_t count) {
  string result;
  for (unsigned int idx = 0; idx < count; ++idx) {
    char buf[3];
    snprintf(buf, sizeof(buf), "%02X", bytes[idx]);
    result.append(buf);
  }
  return result;
}

// static
string FileID::ConvertIdentifierToUUIDString(
    const wasteful_vector<uint8_t>& identifier) {
  uint8_t identifier_swapped[kMDGUIDSize] = { 0 };

  // Endian-ness swap to match dump processor expectation.
  memcpy(identifier_swapped, &identifier[0],
         std::min(kMDGUIDSize, identifier.size()));
  uint32_t* data1 = reinterpret_cast<uint32_t*>(identifier_swapped);
  *data1 = htonl(*data1);
  uint16_t* data2 = reinterpret_cast<uint16_t*>(identifier_swapped + 4);
  *data2 =  (*data2);
  uint16_t* data3 = reinterpret_cast<uint16_t*>(identifier_swapped + 6);
  *data3 = htons(*data3);

  return bytes_to_hex_string(identifier_swapped, kMDGUIDSize);
}

// static
string FileID::ConvertIdentifierToString(
    const wasteful_vector<uint8_t>& identifier) {
  return bytes_to_hex_string(&identifier[0], identifier.size());
}

在这里插入图片描述

arm-linux-androideabi-addr2line -C -f -e ${SOPATH} ${Address}
# -C -f           //打印错误行数所在的函数名称
#    -e                //打印错误地址的对应路径及行数
#  ${SOPATH}         //so库路径 
# ${Address}        //需要转换的堆栈错误信息地址,可以添加多个,但是中间要用空格隔开

有关于动态库

//TODO

有关于breakpad

//TODO

有关于崩溃日志分析

//TODO

参考文章

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值