前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Android Tombstone 分析

Android Tombstone 分析

作者头像
天天Lotay
发布于 2024-03-03 01:33:54
发布于 2024-03-03 01:33:54
1.5K00
代码可运行
举报
文章被收录于专栏:嵌入式音视频嵌入式音视频
运行总次数:0
代码可运行

1.什么是tombstone

Tombstone是指在分布式系统中用于标记数据已被删除的记录,通常包含删除操作的时间戳和相关信息。

当一个动态库(native程序)开始执行时,系统会注册一些连接到 debuggerd 的signal handlers。当系统发生崩溃时,会保存一个tombstone文件到/data/tombstones目录下,并在Logcat中提供相应信息。这个tombstone文件类似于墓碑,记录了已终止进程的基本信息,包括进程号、线程号、崩溃地址等。此外,tombstone文件还会详细记录崩溃时的现场情况,包括一系列的堆栈调用信息,帮助开发人员分析问题并进行调试。

2.tombstone文件长什么样

一个tombstone文件大概包含以下信息

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
--------- beginning of crash
F/libc    (  244): invalid address or address of corrupt block 0xb82f54a0 passed to dlfree
I/libc    (  244): debuggerd_signal_handler called: signal=11, fn=0xb6fbdaa1
F/libc    (  244): Fatal signal 11 (SIGSEGV), code 1, fault addr 0xdeadbaad in tid 244 (mediaserver)
I/libc    (  244): exit from debuggerd_signal_handler
W/NativeCrashListener(  916): Couldn't find ProcessRecord for pid 244
I/DEBUG   (  241): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
E/DEBUG   (  241): AM write failure (32 / Broken pipe)
I/DEBUG   (  241): Build fingerprint: XXXXXXXXX
I/DEBUG   (  241): Revision: '0'
I/DEBUG   (  241): ABI: 'arm'
I/DEBUG   (  241): pid: 244, tid: 244, name: mediaserver  >>> /system/bin/mediaserver <<<
I/DEBUG   (  241): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xdeadbaad
I/art     ( 3078): now dumpable=1
I/DEBUG   (  241): Abort message: 'invalid address or address of corrupt block 0xb82f54a0 passed to dlfree'
I/DEBUG   (  241):     r0 00000000  r1 b6f20dec  r2 deadbaad  r3 00000000
I/DEBUG   (  241):     r4 b82f54a0  r5 b6f220f8  r6 00000000  r7 42424242
I/DEBUG   (  241):     r8 ffffffff  r9 b82f5460  sl 00000030  fp 00000000
I/DEBUG   (  241):     ip 00000000  sp beb2c020  lr b6ef1fa7  pc b6ef1fa8  cpsr 600e0030
I/DEBUG   (  241):     d0  0000000000000000  d1  6f2073736572646c
I/DEBUG   (  241):     d2  707572726f632066  d3  206b636f6c622072
I/DEBUG   (  241):     d4  4242424242424242  d5  4242424242424242
I/DEBUG   (  241):     d6  4242424242424242  d7  3ecccccd42424242
I/DEBUG   (  241):     d8  0000000000000000  d9  0000000000000000
I/DEBUG   (  241):     d10 0000000000000000  d11 0000000000000000
I/DEBUG   (  241):     d12 0000000000000000  d13 0000000000000000
I/DEBUG   (  241):     d14 0000000000000000  d15 0000000000000000
I/DEBUG   (  241):     d16 0000000000000000  d17 3ff0000000000000
I/DEBUG   (  241):     d18 7e37e43c8800759c  d19 bfd5f3f082400000
I/DEBUG   (  241):     d20 3e66376972bea4d0  d21 bf66b12699b6468f
I/DEBUG   (  241):     d22 3fc54aa75950670f  d23 bfd73498f0a5ef3a
I/DEBUG   (  241):     d24 3fe0000000000000  d25 bfaaf3ec933c988f
I/DEBUG   (  241):     d26 0000000000000000  d27 4000000000000000
I/DEBUG   (  241):     d28 4002e6931e14bde7  d29 3faaf3ec9198f99c
I/DEBUG   (  241):     d30 3ff0000000000000  d31 3fd29572efd86cee
I/DEBUG   (  241):     scr 20000010
I/DEBUG   (  241): 
I/DEBUG   (  241): backtrace:
I/DEBUG   (  241):     #00 pc 00028fa8  /system/lib/libc.so (dlfree+1239)
I/DEBUG   (  241):     #01 pc 0000f2cb  /system/lib/libc.so (free+10)
I/DEBUG   (  241):     #02 pc 0000a1cb  /system/lib/libstagefright_foundation.so (_ZN7android7ABufferD2Ev+42)
I/DEBUG   (  241):     #03 pc 0000a211  /system/lib/libstagefright_foundation.so (_ZN7android7ABufferD0Ev+4)
I/DEBUG   (  241):     #04 pc 0000d68d  /system/lib/libutils.so (_ZNK7android7RefBase9decStrongEPKv+40)
I/DEBUG   (  241):     #05 pc 0005adfd  /system/lib/libstagefright.so (_ZN7android2spINS_13GraphicBufferEED2Ev+10)
I/DEBUG   (  241):     #06 pc 0007cd0f  /system/lib/libstagefright.so (_ZN7android14MPEG4Extractor10parseChunkEPxi+634)
I/DEBUG   (  241):     #07 pc 0007d43d  /system/lib/libstagefright.so (_ZN7android14MPEG4Extractor10parseChunkEPxi+2472)
I/DEBUG   (  241):     #08 pc 0007e873  /system/lib/libstagefright.so (_ZN7android14MPEG4Extractor12readMetaDataEv+58)
I/DEBUG   (  241):     #09 pc 0007eaa1  /system/lib/libstagefright.so (_ZN7android14MPEG4Extractor11countTracksEv+4)
I/DEBUG   (  241):     #10 pc 000acf9d  /system/lib/libstagefright.so (_ZN7android13ExtendedUtils29MediaExtractor_CreateIfNeededENS_2spINS_14MediaExtractorEEERKNS1_INS_10DataSourceEEEPKc+60)
I/DEBUG   (  241):     #11 pc 0008e3f5  /system/lib/libstagefright.so (_ZN7android14MediaExtractor6CreateERKNS_2spINS_10DataSourceEEEPKc+624)
I/DEBUG   (  241):     #12 pc 0006ace9  /system/lib/libstagefright.so (_ZN7android13AwesomePlayer15setDataSource_lERKNS_2spINS_10DataSourceEEE+12)
I/DEBUG   (  241):     #13 pc 0006c0dd  /system/lib/libstagefright.so (_ZN7android13AwesomePlayer13setDataSourceEixx+228)
I/DEBUG   (  241):     #14 pc 0003d647  /system/lib/libmediaplayerservice.so (_ZN7android18MediaPlayerService6Client13setDataSourceEixx+362)
I/DEBUG   (  241):     #15 pc 0005ea03  /system/lib/libmedia.so (_ZN7android13BnMediaPlayer10onTransactEjRKNS_6ParcelEPS1_j+478)
I/DEBUG   (  241):     #16 pc 00017fad  /system/lib/libbinder.so (_ZN7android7BBinder8transactEjRKNS_6ParcelEPS1_j+60)
I/DEBUG   (  241):     #17 pc 0001cfdb  /system/lib/libbinder.so (_ZN7android14IPCThreadState14executeCommandEi+562)
I/DEBUG   (  241):     #18 pc 0001d12f  /system/lib/libbinder.so (_ZN7android14IPCThreadState20getAndExecuteCommandEv+38)
I/DEBUG   (  241):     #19 pc 0001d171  /system/lib/libbinder.so (_ZN7android14IPCThreadState14joinThreadPoolEb+48)
I/DEBUG   (  241):     #20 pc 00001721  /system/bin/mediaserver
I/DEBUG   (  241):     #21 pc 0000f411  /system/lib/libc.so (__libc_init+44)
I/DEBUG   (  241):     #22 pc 00001998  /system/bin/mediaserver
I/DEBUG   (  241): 
I/DEBUG   (  241): stack:
I/DEBUG   (  241):          beb2bfe0  00000000  
I/DEBUG   (  241):          beb2bfe4  29ec038f  
I/DEBUG   (  241):          beb2bfe8  0009eb34  
I/DEBUG   (  241):          beb2bfec  b82f54a0  [heap]
I/DEBUG   (  241):          beb2bff0  b6f220f8  
I/DEBUG   (  241):          beb2bff4  00000000  
I/DEBUG   (  241):          beb2bff8  42424242  
I/DEBUG   (  241):          beb2bffc  b6edb3d1  /system/lib/libc.so (__libc_fatal_no_abort+16)
I/DEBUG   (  241):          beb2c000  b6f12f97  /system/lib/libc.so
I/DEBUG   (  241):          beb2c004  beb2c014  [stack]
I/DEBUG   (  241):          beb2c008  b6f167be  /system/lib/libc.so
I/DEBUG   (  241):          beb2c00c  b6ef1fa7  /system/lib/libc.so (dlfree+1238)
I/DEBUG   (  241):          beb2c010  b6f12f97  /system/lib/libc.so
I/DEBUG   (  241):          beb2c014  b82f54a0  [heap]
I/DEBUG   (  241):          beb2c018  b6f167be  /system/lib/libc.so
I/DEBUG   (  241):          beb2c01c  b82f54b0  [heap]
I/DEBUG   (  241):     #00  beb2c020  b82f5460  [heap]
......

它包含了发生问题的进程ID信息

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
I/DEBUG   (  241): pid: 244, tid: 244, name: mediaserver  >>> /system/bin/mediaserver <<<

当 tid (线程ID)== pid (进程ID)时,问题发生在父进程,反之问题发生在子进程,从上面的日志信息可以看出发生问题的进程是mediaserver的子进程。

Terminated signal 和 fault address 信息

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
F/libc    (  244): Fatal signal 11 (SIGSEGV), code 1, fault addr 0xdeadbaad in tid 244 (mediaserver)

这里的信息说明出现进程 Crash 的原因是因为程序产生了段错误的信号,访问了非法的内存空间,而访问的非法地址是 0xdeadbaad

信号机制是 Linux 进程间通信的一种重要方式,Linux 信号一方面用于正常的进程间通信和同步,如任务控制(SIGINT, SIGTSTP,SIGKILL, SIGCONT,……);另一方面,它还负责监控系统异常及中断。 当应用程序运行异常时, Linux 内核将产生错误信号并通知当前进程。 当前进程在接收到该错误信号后,可以有三种不同的处理方式。

(1)忽略该信号。 (2)捕捉该信号并执行对应的信号处理函数(signal handler)。 (3)执行该信号的缺省操作(如 SIGSEGV, 其缺省操作是终止进程)。

当 Linux 应用程序在执行时发生严重错误,一般会导致程序 crash。其中,Linux 专门提供了一类 crash 信号,在程序接收到此类信号时,缺省操作是将 crash 的现场信息记录到 core 文件,然后终止进程。

crash 信号列表:

Signal

Description

SIGSEGV

Invalid memory reference.

SIGBUS

Access to an undefined portion of a memory object.

SIGFPE

Arithmetic operation error, like divide by zero.

SIGILL

Illegal instruction, like execute garbage or a privileged instruction

SIGSYS

Bad system call.

SIGXCPU

CPU time limit exceeded.

SIGXFSZ

File size limit exceeded.

定义在prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.8/sysroot/usr/include/bits/signum.h

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/* Signals.  */
#define SIGHUP          1       /* Hangup (POSIX).  */
#define SIGINT          2       /* Interrupt (ANSI).  */
#define SIGQUIT         3       /* Quit (POSIX).  */
#define SIGILL          4       /* Illegal instruction (ANSI).  */
#define SIGTRAP         5       /* Trace trap (POSIX).  */
#define SIGABRT         6       /* Abort (ANSI).  */
#define SIGIOT          6       /* IOT trap (4.2 BSD).  */
#define SIGBUS          7       /* BUS error (4.2 BSD).  */
#define SIGFPE          8       /* Floating-point exception (ANSI).  */
#define SIGKILL         9       /* Kill, unblockable (POSIX).  */
#define SIGUSR1         10      /* User-defined signal 1 (POSIX).  */
#define SIGSEGV         11      /* Segmentation violation (ANSI).  */
#define SIGUSR2         12      /* User-defined signal 2 (POSIX).  */
#define SIGPIPE         13      /* Broken pipe (POSIX).  */
#define SIGALRM         14      /* Alarm clock (POSIX).  */
#define SIGTERM         15      /* Termination (ANSI).  */
#define SIGSTKFLT       16      /* Stack fault.  */
#define SIGCLD          SIGCHLD /* Same as SIGCHLD (System V).  */
#define SIGCHLD         17      /* Child status has changed (POSIX).  */
#define SIGCONT         18      /* Continue (POSIX).  */
#define SIGSTOP         19      /* Stop, unblockable (POSIX).  */
#define SIGTSTP         20      /* Keyboard stop (POSIX).  */
#define SIGTTIN         21      /* Background read from tty (POSIX).  */
#define SIGTTOU         22      /* Background write to tty (POSIX).  */
#define SIGURG          23      /* Urgent condition on socket (4.2 BSD).  */
#define SIGXCPU         24      /* CPU limit exceeded (4.2 BSD).  */
#define SIGXFSZ         25      /* File size limit exceeded (4.2 BSD).  */
#define SIGVTALRM       26      /* Virtual alarm clock (4.2 BSD).  */
#define SIGPROF         27      /* Profiling alarm clock (4.2 BSD).  */
#define SIGWINCH        28      /* Window size change (4.3 BSD, Sun).  */
#define SIGPOLL         SIGIO   /* Pollable event occurred (System V).  */
#define SIGIO           29      /* I/O now possible (4.2 BSD).  */
#define SIGPWR          30      /* Power failure restart (System V).  */
#define SIGSYS          31      /* Bad system call.  */
#define SIGUNUSED       31

#define _NSIG           65      /* Biggest signal number + 1
                                   (including real-time signals).  */

3.怎么分析tombstone文件

我们主要关注 backtrace 下面的内容,它保存了发生 crash 时候的函数调用关系,但是需要注意的是它的调用顺序是从下向上执行的(#XX pc -->#00 pc),通过这些函数调用关系,我们就可以大概定位出问题发生的地方,在本次 tombstone 日志中,我们通过

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
I/DEBUG   (  241):     #00 pc 00028fa8  /system/lib/libc.so (dlfree+1239)
I/DEBUG   (  241):     #01 pc 0000f2cb  /system/lib/libc.so (free+10)
I/DEBUG   (  241):     #02 pc 0000a1cb  /system/lib/libstagefright_foundation.so (_ZN7android7ABufferD2Ev+42)
I/DEBUG   (  241):     #03 pc 0000a211  /system/lib/libstagefright_foundation.so (_ZN7android7ABufferD0Ev+4)
I/DEBUG   (  241):     #04 pc 0000d68d  /system/lib/libutils.so (_ZNK7android7RefBase9decStrongEPKv+40)

可以分析出问题是在调用free函数时发生了指针错误,还可以看出问题发生的原因是libstagefright_foundation.so中释放了两次ABuffer引用,接着就去分析是谁谁释放的AUbffer强指针。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
I/DEBUG   (  241):     #05 pc 0005adfd  /system/lib/libstagefright.so (_ZN7android2spINS_13GraphicBufferEED2Ev+10)
I/DEBUG   (  241):     #06 pc 0007cd0f  /system/lib/libstagefright.so (_ZN7android14MPEG4Extractor10parseChunkEPxi+634)
I/DEBUG   (  241):     #07 pc 0007d43d  /system/lib/libstagefright.so (_ZN7android14MPEG4Extractor10parseChunkEPxi+2472)
I/DEBUG   (  241):     #08 pc 0007e873  /system/lib/libstagefright.so (_ZN7android14MPEG4Extractor12readMetaDataEv+58)

可以看出来在 libstagefright 动态库中的MPEG4Extractor.cpp 的 parseChunk函数出现的错误。

4.一些分析工具

虽然通过 tombstone 的日志文件我们就可以大致定位出引发 crash 的代码的位置,但是通过借助一些分析工具,可以大大的提高工作效率和准确性,下面就来介绍以下这些工具。

(1)addr2line

addr2line 是 用来获得指定动态链接库文件或者可执行文件中指定地址对应的源代码信息的工具

它的各种参数如下所示(这个是google aosp android M 中带的):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
~/source/google_android/prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9/bin$ ./x86_64-linux-android-addr2line -h
Usage: ./x86_64-linux-android-addr2line [option(s)] [addr(s)]
 Convert addresses into line number/file name pairs.
 If no addresses are specified on the command line, they will be read from stdin
 The options are:
  @<file>                Read options from <file>
  -a --addresses         Show addresses
  -b --target=<bfdname>  Set the binary file format
  -e --exe=<executable>  Set the input file name (default is a.out)
  -i --inlines           Unwind inlined functions
  -j --section=<name>    Read section-relative offsets instead of addresses
  -p --pretty-print      Make the output easier to read for humans
  -s --basenames         Strip directory names
  -f --functions         Show function names
  -C --demangle[=style]  Demangle function names
  -h --help              Display this information
  -v --version           Display the program's version
./x86_64-linux-android-addr2line: supported targets: elf64-x86-64 elf32-i386 elf32-x86-64 a.out-i386-linux pei-i386 pei-x86-64 elf64-l1om elf64-k1om elf64-little elf64-big elf32-little elf32-big plugin srec symbolsrec verilog tekhex binary ihex
Report bugs to <http://source.android.com/source/report-bugs.html>

addr2line 的基本用法如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
./prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8/bin/arm-linux-androideabi-addr2line -f -e out/debug/target/product/XXXX/symbols/system/lib/libstagefright.so  0007cd0f 
_ZN7android14MPEG4Extractor10parseChunkEPxi
/home/XXX/source/XXX/LINUX/android/frameworks/av/media/libstagefright/MPEG4Extractor.cpp:2180 (discriminator 1)

这里需要注意的是不能直接使用out/debug/target/product/XXX/system/lib/libstagefright.so,会出现运行上面命令之后显示

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
??
??:0

因为这个动态库是最后要打包到最后生成的system.ing中的,所以它不包含调试符号信息。

(2)ndk-stack

Android NDK 自从版本 r6开始, 提供了一个工具 ndk-stack。这个工具能自动分析 tombstone 文件, 能将崩溃时的调用内存地址和 c++ 代码一行一行对应起来.

它的使用方法为

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
./ndk-stack 
Usage:
   ndk-stack -sym <path> [-dump <path>]
      -sym  Contains full path to the root directory for symbols.
      -dump Contains full path to the file containing the crash dump.
            This is an optional parameter. If ommited, ndk-stack will
            read input data from stdin
   See docs/NDK-STACK.html in your NDK installation tree for more details.
  1. dump 参数很容易理解, 即 dump 下来的 log 文本文件. ndk-stack会分析此文件。
  2. sym 参数就是你android项目下,编译成功之后,obj目录下的文件(android系统源码o 中带有符号信息的文件)。

我们可以使用它来分析我们的log文件

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ndk-stack -sym xxx.so -dump logfile

所以我们在调试android系统源码的时候也可以直接分析log中的crash信息。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
adb shell logcat | ndk-stack -sym out/debug/target/product/XXXX/symbols/system/lib/xxx.so

(3)stack.py

stack.py工具就是要把backtrace通过addr2line工具一次性把addr对应到代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#!/usr/bin/python2.4 -E
import getopt
import os
import re
import string
import sys
import getpass
import urllib
import subprocess
def PrintUsage():
  print
  print "  usage: " + sys.argv[0] + " [options] [FILE]"
  print
  print "  --symbols-dir=path"
  print "       the path to a symbols dir, such as =/tmp/out/target/product/dream/symbols"
  print
  print "  --symbols-zip=path"
  print "       the path to a symbols zip file, such as =dream-symbols-12345.zip"
  print
  print "  --auto"
  print "       attempt to:"
  print "         1) automatically find the build number in the crash"
  print "         2) if it's an official build, download the symbols "
  print "            from the build server, and use them"
  print
  print "  FILE should contain a stack trace in it somewhere"
  print "       the tool will find that and re-print it with"
  print "       source files and line numbers.  If you don't"
  print "       pass FILE, or if file is -, it reads from"
  print "       stdin."
  print
  sys.exit(1)
def FindSymbolsDir():
  cmd = "CALLED_FROM_SETUP=true make -f build/core/envsetup.mk " \
      + "dumpvar-abs-TARGET_OUT_UNSTRIPPED"
  stream = os.popen(cmd)
  str = stream.read()
  stream.close()
  return str.strip()
# returns a list containing the function name and the file/lineno
def CallAddr2Line(lib, addr):
  uname = os.uname()[0]
  if uname == "Darwin":
    proc = os.uname()[-1]
    if proc == "i386":
      uname = "darwin-x86"
    else:
      uname = "darwin-ppc"
  if lib != "":
    #cmd = "./prebuilt/" + uname + "/toolchain-eabi-4.2.1/bin/arm-eabi-addr2line" \
    #cmd = "./prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7/bin/arm-linux-androideabi-addr2line" \
    cmd = " arm-eabi-addr2line" \
        + " -f -e " + SYMBOLS_DIR + lib \
        + " 0x" + addr
    stream = os.popen(cmd)
    lines = stream.readlines()
    list = map(string.strip, lines)
  else:
    list = []
  if list != []:
    # Name like "move_forward_type<JavaVMOption>" causes troubles
    mangled_name = re.sub('<', '\<', list[0]);
    mangled_name = re.sub('>', '\>', mangled_name);
    #cmd = "./prebuilt/" + uname + "/toolchain-eabi-4.2.1/bin/arm-eabi-c++filt "\
    cmd = "./prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7/bin/arm-linux-androideabi-c++filt "\
          + mangled_name
    stream = os.popen(cmd)
    list[0] = stream.readline()
    stream.close()
    list = map(string.strip, list)
  else:
    list = [ "(unknown)", "(unknown)" ]
  return list
class SSOCookie(object):
  """
  creates a cookie file so we can download files from the build server
  """
  def __init__(self, cookiename=".sso.cookie", keep=False):
    self.sso_server = "login.corp.google.com"
    self.name = cookiename
    self.keeper = keep
    self.tmp_opts = ".curl.options"
    if not os.path.exists(self.name):
      user = os.environ['USER']
      print "\n%s, to access the symbols, please enter your LDAP " % user,
      password = getpass.getpass()
      params = urllib.urlencode({"u": user, "pw": password})
      fd = os.open(self.tmp_opts, os.O_RDWR | os.O_CREAT, 0600)
      os.write(fd, '-b "%s"\n' % self.name)
      os.write(fd, '-c "%s"\n' % self.name)
      os.write(fd, '-s"\n-L\n-d "%s"\n' % params)
      os.write(fd, 'url = "https://%s/login?ssoformat=CORP_SSO"\n' % 
               self.sso_server)
      # login to SSO
      response = os.popen("/usr/bin/curl -K %s" % self.tmp_opts)
      response.close()
      if os.path.exists(self.tmp_opts):
        os.remove(self.tmp_opts)
      if os.path.exists(self.name):
        os.chmod(self.name, 0600)
      else:
        print "Could not log in to SSO"
        sys.exit(1)
  def __del__(self):
      """clean up"""
      if not self.keeper:
        os.remove(self.name)
class NoBuildIDException(Exception):
  pass
def FindBuildFingerprint(lines):
  """
  Searches the given file (array of lines) for the build fingerprint information
  """
  fingerprint_regex = re.compile("^.*Build fingerprint:\s'(?P<fingerprint>.*)'")
  for line in lines:
    fingerprint_search = fingerprint_regex.match(line.strip())
    if fingerprint_search:
      return fingerprint_search.group('fingerprint')
      
  return None  # didn't find the fingerprint string, so return none
  
class SymbolDownloadException(Exception):
  pass
DEFAULT_SYMROOT = "/tmp/symbols"
def DownloadSymbols(fingerprint, cookie):
  """
  Attempts to download the symbols from the build server, extracts them,
  and returns the path.  Takes the fingerprint from the pasted stack trace
  and the SSOCookie
  """
  if fingerprint is None:
    return (None, None)
  symdir = "%s/%s" % (DEFAULT_SYMROOT, hash(fingerprint))
  if not os.path.exists(symdir):
    os.makedirs(symdir)
  # build server figures out the branch based on the CL
  params = {
              'op': "GET-SYMBOLS-LINK",
              'fingerprint': fingerprint,
           }
  url = urllib.urlopen("http://android-build/buildbot-update?",
                            urllib.urlencode(params)).readlines()[0]
  if url == "":
    raise SymbolDownloadException, "Build server down? Failed to find syms..."
  regex_str = (r'(?P<baseURL>http\:\/\/android-build\/builds\/.*\/[0-9]+' + 
           r'\/)(?P<img>.*)')
  url_regex = re.compile(regex_str)
  url_match = url_regex.match(url)
  if url_match is None:
    raise SymbolDownloadException, "Unexpected results from build server URL..."
  
  baseURL = url_match.group('baseURL')
  img =  url_match.group('img')
  symbolfile = img.replace("-img-", "-symbols-")
  symurl = baseURL + symbolfile
  localsyms = symdir + symbolfile
  if not os.path.exists(localsyms):
    print "downloading %s ..." % symurl
    curlcmd = ("""/usr/bin/curl -b %s -sL -w %%{http_code} -o %s %s""" % 
                          (cookie.name, localsyms, symurl))
    (fi,fo,fe) = os.popen3(curlcmd)
    fi.close()
    code = fo.read()
    err = fe.read()
    if err != "":
      raise SymbolDownloadException, "stderr from curl download: %s" % err
    if code != "200":
      raise SymbolDownloadException, "Faied to download %s" % symurl
  else:
    print "using existing cache for symbols"
  print "extracting %s..." % symbolfile
  saveddir = os.getcwd()
  os.chdir(symdir)
  unzipcode = subprocess.call(["unzip", "-qq", "-o", localsyms])
  if unzipcode > 0:
    raise SymbolDownloadException, ("failed to extract symbol files (%s)." 
                             % localsyms)
  os.chdir(saveddir)
  
  return (symdir, "%s/out/target/product/dream/symbols" % symdir)
def UnzipSymbols(symbolfile):
  """Unzips a file to DEFAULT_SYMROOT and returns the unzipped location.
  Args:
    symbolfile: The .zip file to unzip
  Returns:
    A tuple containing (the directory into which the zip file was unzipped,
    the path to the "symbols" directory in the unzipped file).  To clean
    up, the caller can delete the first element of the tuple.
  Raises:
    SymbolDownloadException: When the unzip fails.
  """
  symdir = "%s/%s" % (DEFAULT_SYMROOT, hash(symbolfile))
  if not os.path.exists(symdir):
    os.makedirs(symdir)
  print "extracting %s..." % symbolfile
  saveddir = os.getcwd()
  os.chdir(symdir)
  unzipcode = subprocess.call(["unzip", "-qq", "-o", symbolfile])
  if unzipcode > 0:
    raise SymbolDownloadException, ("failed to extract symbol files (%s)." 
                             % symbolfile)
  os.chdir(saveddir)
  
  return (symdir, "%s/out/target/product/dream/symbols" % symdir)
def PrintTraceLines(traceLines):
    maxlen = max(map(lambda tl: len(tl[1]), traceLines))
    print
    print "Stack Trace:"
    print "  ADDR      " + "FUNCTION".ljust(maxlen) + "  FILE:LINE"
    for tl in traceLines:
      print "  " + tl[0] + "  " + tl[1].ljust(maxlen) + "  " + tl[2]
    return
def PrintValueLines(valueLines):
    print
    print "Stack Data:"
    print "  ADDR      VALUE     " + "FILE:LINE/FUNCTION"
    for vl in valueLines:
      print "  " + vl[1] + "  " + vl[2] + "  " + vl[4]
      if vl[4] != "":
        print "                      " + vl[3]
    return
def ConvertTrace(lines):
  PROCESS_INFO_LINE = re.compile("(pid: [0-9]+, tid: [0-9]+.*)")
  SIGNAL_LINE = re.compile("(signal [0-9]+ \(.*\).*)")
  REGISTER_LINE = re.compile("(([ ]*[0-9a-z]{2} [0-9a-f]{8}){4})")
  TRACE_LINE = re.compile("(.*)\#([0-9]+)  (..) ([0-9a-f]{3})([0-9a-f]{5})  ([^\r\n \t]*)")
  VALUE_LINE = re.compile("(.*)([0-9a-f]{2})([0-9a-f]{6})  ([0-9a-f]{3})([0-9a-f]{5})  ([^\r\n \t]*)")
  THREAD_LINE = re.compile("(.*)(\-\-\- ){15}\-\-\-")
  traceLines = []
  valueLines = []
  for line in lines:
    header = PROCESS_INFO_LINE.search(line)
    if header:
      print header.group(1)
      continue
    header = SIGNAL_LINE.search(line)
    if header:
      print header.group(1)
      continue
    header = REGISTER_LINE.search(line)
    if header:
      print header.group(1)
      continue
    if TRACE_LINE.match(line):
      match = TRACE_LINE.match(line)
      groups = match.groups()
      if groups[5] == "<unknown>" or groups[5] == "[heap]" or groups[5] == "[stack]":
        traceLines.append((groups[3]+groups[4], groups[5], groups[5]))
      else:
        info = CallAddr2Line(groups[5], groups[4])
        traceLines.append((groups[3]+groups[4], info[0], info[1]))
    if VALUE_LINE.match(line):
      match = VALUE_LINE.match(line)
      groups = match.groups()
      if groups[5] == "<unknown>" or groups[5] == "[heap]" or groups[5] == "[stack]" or groups[5] == "":
        valueLines.append((groups[0], groups[1]+groups[2], groups[3]+groups[4], groups[5], ""))
      else:
        info = CallAddr2Line(groups[5], groups[4])
        valueLines.append((groups[0], groups[1]+groups[2], groups[3]+groups[4], info[0], info[1]))
    header = THREAD_LINE.search(line)
    if header:
      if len(traceLines) > 0:
        PrintTraceLines(traceLines)
      if len(valueLines) > 0:
        PrintValueLines(valueLines)
      traceLines = []
      valueLines = []
      print
      print "-----------------------------------------------------\n"
  if len(traceLines) > 0:
    PrintTraceLines(traceLines)
  if len(valueLines) > 0:
    PrintValueLines(valueLines)
SYMBOLS_DIR = FindSymbolsDir()
if __name__ == '__main__':
  try:
    options, arguments = getopt.getopt(sys.argv[1:], "",
                             ["auto", "symbols-dir=", "symbols-zip=", "help"])
  except getopt.GetoptError, error:
    PrintUsage()
  
  AUTO = False
  zipArg = None
  for option, value in options:
    if option == "--help":
      PrintUsage()
    elif option == "--symbols-dir":
      SYMBOLS_DIR = value
    elif option == "--symbols-zip":
      zipArg = value
    elif option == "--auto":
      AUTO = True
  
  if len(arguments) > 1:
    PrintUsage()
  if AUTO:
    cookie = SSOCookie(".symbols.cookie")
  
  if len(arguments) == 0 or arguments[0] == "-":
    print "Reading native crash info from stdin"
    f = sys.stdin
  else:
    print "Searching for native crashes in %s" % arguments[0]
    f = open(arguments[0], "r")
  lines = f.readlines()
  rootdir = None
  if AUTO:
    fingerprint = FindBuildFingerprint(lines)
    print "fingerprint:", fingerprint
    rootdir, SYMBOLS_DIR = DownloadSymbols(fingerprint, cookie)
  elif zipArg is not None:
    rootdir, SYMBOLS_DIR = UnzipSymbols(zipArg)
  
  print "Reading symbols from", SYMBOLS_DIR
  lines = ConvertTrace(lines)
  
  if rootdir is not None:
    # be a good citizen and clean up...os.rmdir and os.removedirs() don't work
    cmd = "rm -rf \"%s\"" % rootdir
    print "\ncleaning up (%s)" % cmd
    os.system(cmd)
  
  # vi: ts=2 sw=2

使用方法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
python stack.py --symbols-dir=out/target/profuct/XXX/sysbols/  tombstone-00(tombstone文件)
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-03-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
微软、AWS后,英伟达也已接入DeepSeek,扎克伯格:是的,我们也将“偷师”DeepSeek
新春伊始,DeepSeek 凭借其极有竞争性的价格优势和精准的算法火遍了硅谷和华尔街。与此同时,各大科技巨头也迅速行动,纷纷下场无缝接入 DeepSeek 的 R1 模型服务,以期抢占 AI 领域先机。
深度学习与Python
2025/02/03
1970
微软、AWS后,英伟达也已接入DeepSeek,扎克伯格:是的,我们也将“偷师”DeepSeek
服软了?爆料英伟达联手DeepSeek推出NIM服务
北京时间1月31日,英伟达正式宣布在其官网上发布了基于DeepSeek R1 671b模型的“英伟达NIM微服务”预览版,并高调宣称DeepSeek-R1的推理能力处于“最先进”水平。
用户11203141
2025/03/06
610
服软了?爆料英伟达联手DeepSeek推出NIM服务
什么是检索增强生成(又名 RAG-Retrieval-Augmented Generation)及相关引用文档
检索增强生成是一种利用来自特定相关数据源的信息来增强生成式 AI 模型的准确性和可靠性的技术。
晓兵
2025/03/23
1670
什么是检索增强生成(又名 RAG-Retrieval-Augmented Generation)及相关引用文档
刚刚,老黄携GB300震撼登场!DeepSeek推理暴涨40倍加速全球最快,26年Rubin问世
更令人瞩目的是,DeepSeek R1推动的推理时Scaling,让Scaling Law出现了全新的发展路线。
新智元
2025/03/20
650
刚刚,老黄携GB300震撼登场!DeepSeek推理暴涨40倍加速全球最快,26年Rubin问世
DeepSeek霸榜一周:奥特曼终于承认在开源问题上处于“历史错误的一边”;迅雷斥资5亿收购“直男社区”虎扑 | Q资讯
DeepSeek-R1 霸榜一周:性能、价格与开源三重冲击;网传梁文锋回应冯骥国运论;阿里巴巴发布 AI 模型,声称超越 DeepSeek;马斯克掀起“硬核裁员”风暴:百万雇员面临“自愿离职”抉择;谷歌为 Pixel、Android 部门员工提供“自愿离职”机会;迅雷将以 5 亿元收购“直男社区”虎扑,曾最高估值达 77 亿元;Linux 基金会发布指南应对 OFAC 制裁挑战;谷歌开源 PebbleOS 操作系统......
深度学习与Python
2025/02/03
1620
DeepSeek霸榜一周:奥特曼终于承认在开源问题上处于“历史错误的一边”;迅雷斥资5亿收购“直男社区”虎扑 | Q资讯
对DeepSeek事件的复盘和展望
作者简介:腾讯云TVP、北京交通大学计算机学院教授、计算机科学系主任、交通大数据与人工智能教育部重点实验室副主任。主要研究方向为多模态计算、网络数据挖掘、可信与对齐、AI Agent等。曾获中科院院长特别奖、ACM中国新星奖,作为负责人先后承担相关方向的国家自然科学基金重点项目、(首批)新一代人工智能重大项目课题、北京市杰出青年基金和国家级青年人才计划,第一/二作者论文7次获得中国计算机学会推荐国际会议的主会论文奖项,以第二完成人获得中国电子学会自然科学一等奖和北京市科学技术奖。
TVP官方团队
2025/02/03
1.1K0
对DeepSeek事件的复盘和展望
英伟达B200打破摩尔定律!老黄顺便公开GPT-4的秘密
时隔两年,英伟达官宣新一代Blackwell架构,为AI带来30倍推理加速。定位直指“新工业革命的引擎” 。
量子位
2024/03/20
1670
英伟达B200打破摩尔定律!老黄顺便公开GPT-4的秘密
刚刚,DeepSeek开源MoE训练、推理EP通信库DeepEP,真太Open了!
上周五,DeepSeek 发推说本周将是开源周(OpenSourceWeek),并将连续开源五个软件库。
机器之心
2025/02/25
1650
刚刚,DeepSeek开源MoE训练、推理EP通信库DeepEP,真太Open了!
网上关于DeepSeek的说法,哪些是错误的?
这是个流传很广的说法,意指DeepSeek通过绕过CUDA,彻底摆脱了NVIDIA的依赖。
小白学视觉
2025/02/10
1510
网上关于DeepSeek的说法,哪些是错误的?
揭秘 NVIDIA Dynamo:分布式AI推理的高效引擎
随着生成式AI模型规模的爆炸式增长,企业面临推理成本激增、分布式部署复杂度高、资源利用率低等挑战。传统推理框架在跨多节点扩展时,常因KV缓存重复计算、GPU负载不均、通信延迟等问题导致性能瓶颈。NVIDIA Dynamo作为新一代开源推理框架,专为大规模分布式环境设计,通过解耦式服务、智能路由、动态资源调度等创新技术,将推理吞吐量提升30倍以上。本文将深入解析其核心架构、技术优势及实际应用场景,帮助开发者高效部署生成式AI模型,降低推理成本并释放GPU潜能。
数据存储前沿技术
2025/03/29
5980
揭秘 NVIDIA Dynamo:分布式AI推理的高效引擎
DeepSeek爆了,问问它《哪吒2》今年为啥爆火
最近,国产大模型 DeepSeek 因其惊人的文本生成以及推理能力(深度思考)在 AI 界刷屏,并且《哪吒 2》也勇夺国产电影票房冠军。
wayn
2025/02/08
1640
DeepSeek爆了,问问它《哪吒2》今年为啥爆火
NVIDIA AI应用平台NIM开发人员指南
英伟达 NIM 通过提供灵活的微服务套件,为 AI 推理提供了一个强大、可扩展且安全的平台。
云云众生s
2024/08/16
3490
NVIDIA AI应用平台NIM开发人员指南
AI届的拼多多登临iOS榜,DeepSeek到底是什么来头?
DeepSeek的App目前已经登陆iOS免费榜前十,并超过了Google Gemini和微软的Copilot等同类竞品,可谓异军突起。
AntDream
2025/02/04
2120
AI届的拼多多登临iOS榜,DeepSeek到底是什么来头?
DeepSeek遭暴力破解,攻击IP均来自美国!
今天是大年初一,鱼皮祝大家在新的一年里阖家幸福,天天暴富! 接下来我们进入正题,说一说DeepSeek的最新情况。 DeepSeek可以说是近期最耀眼的新星
程序员鱼皮
2025/02/04
5830
DeepSeek遭暴力破解,攻击IP均来自美国!
DeepSeek 全面分析报告
DeepSeek 是一款由中国人工智能初创公司 DeepSeek 开发的大型语言模型 (LLM),于 2025 年 1 月发布,迅速成为全球人工智能领域的一匹黑马。DeepSeek 不仅在性能上可与 OpenAI、Google 等巨头的模型相媲美,而且其训练成本和运行效率都显著优于竞争对手,引发了业界和市场的广泛关注。本报告将对 DeepSeek 进行全面分析,涵盖其公司概况、产品服务、技术优势、竞争格局、商业模式、财务状况以及未来发展前景等方面。
@小森
2025/02/23
4360
DeepSeek 全面分析报告
关于Grok3和DeepSeek背后苦涩教训引发的思考
Ilya Sutskever(前 OpenAI 联合创始人兼首席科学家)曾在在召开的 NeurIPS 会议上表示,大模型的预训练已经走到了尽头。 而 Noam Brown(OpenAI 研究员,曾带领团队开发出在德州扑克中战胜职业选手的 AI 系统 Pluribus)在关于 OpenAI O1 发布的采访中提到,提升 Test-Time Compute 是提升大模型答案质量的关键。2024 年的圣诞节前夕,一片节日气氛下,湾区的硅谷 AI 大佬、机构和投资者们正在深入探讨从 “Scaling Learning” 向 “Scaling Search” 转变的路径。而这一切的思考,都可以追溯到 Rich Sutton(强化学习领域的奠基人之一)在 2019 年发表的经典短文 The Bitter Lesson (苦涩的教训)。
致Great
2025/02/24
1580
关于Grok3和DeepSeek背后苦涩教训引发的思考
开发者:为NVIDIA基于NIM的AI应用商店做好准备
NIM(NVIDIA 推理微服务)是一个虚拟化容器,用于提供 AI 功能;该技术将为 NVIDIA AI 应用商店提供支持。
云云众生s
2024/06/13
1260
60页PPT全解:DeepSeek系列论文技术要点整理
经过断断续续的整理,终于把DeepSeek系列论文的核心知识点汇总PPT完成差不多可以和大家分享了。虽然现在发布实在太晚,已经有铺天盖地的对deepseek技术解读文章和分享,但我依然希望将自己对DeepSeek V1到DeepSeek R1的理解与总结呈现给大家。
languageX
2025/03/15
1.3K0
60页PPT全解:DeepSeek系列论文技术要点整理
DeepSeek大讨论:中国AI在成本、真实训练成本和封闭模型利润率影响方面的领导地位
在过去一周里,DeepSeek 成为全球唯一的话题。目前,DeepSeek 的日流量已经远远超过 Claude、Perplexity 甚至 Gemini。但对行业观察者来说,这并非“新”闻。我们已经讨论 DeepSeek 数月之久。这家公司并不新。SemiAnalysis 一直认为 DeepSeek 极具天赋,但公众此前并不关心。
用户11468091
2025/02/05
7480
DeepSeek大讨论:中国AI在成本、真实训练成本和封闭模型利润率影响方面的领导地位
0 帧起步,腾讯云 TI 平台 5 分钟 私有化 DeepSeek
新年本应该祝福满屏的朋友圈,忽然间被 Deepseek 刷屏,这款被《黑神话:悟空》的制作人冯骥的评述:“DeepSeek可能是国运级别的科技成果。至今已在160多个国家的应用商店屠榜。
不惑
2025/02/05
7290
0 帧起步,腾讯云 TI 平台 5 分钟 私有化 DeepSeek
推荐阅读
相关推荐
微软、AWS后,英伟达也已接入DeepSeek,扎克伯格:是的,我们也将“偷师”DeepSeek
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档