Android Tombstone 分析

1.什么是tombstone

Tombstone是指在分布式系統中用于標記數據已被刪除的記錄,通常包含刪除操作的時間戳和相關信息。

當一個動態庫(native程序)開始執行時,系統會注冊一些連接到 debuggerd 的signal handlers。當系統發生崩潰時,會保存一個tombstone文件到/data/tombstones目錄下,并在Logcat中提供相應信息。這個tombstone文件類似于墓碑,記錄了已終止進程的基本信息,包括進程號、線程號、崩潰地址等。此外,tombstone文件還會詳細記錄崩潰時的現場情況,包括一系列的堆棧調用信息,幫助開發人員分析問題并進行調試。

2.tombstone文件長什么樣

在這里插入圖片描述

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

--------- 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信息

I/DEBUG   (  241): pid: 244, tid: 244, name: mediaserver  >>> /system/bin/mediaserver <<<

當 tid (線程ID)== pid (進程ID)時,問題發生在父進程,反之問題發生在子進程,從上面的日志信息可以看出發生問題的進程是mediaserver的子進程。

Terminated signal 和 fault address 信息

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 信號列表:

SignalDescription
SIGSEGVInvalid memory reference.
SIGBUSAccess to an undefined portion of a memory object.
SIGFPEArithmetic operation error, like divide by zero.
SIGILLIllegal instruction, like execute garbage or a privileged instruction
SIGSYSBad system call.
SIGXCPUCPU time limit exceeded.
SIGXFSZFile size limit exceeded.

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

/* 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 日志中,我們通過

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強指針。

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 中帶的):

~/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 stdinThe 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 的基本用法如下所示:

./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,會出現運行上面命令之后顯示

??
??:0

因為這個動態庫是最后要打包到最后生成的system.ing中的,所以它不包含調試符號信息。

(2)ndk-stack

Android NDK 自從版本 r6開始, 提供了一個工具 ndk-stack。這個工具能自動分析 tombstone 文件, 能將崩潰時的調用內存地址和 c++ 代碼一行一行對應起來.

它的使用方法為

./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 willread input data from stdinSee 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文件

ndk-stack -sym xxx.so -dump logfile

所以我們在調試android系統源碼的時候也可以直接分析log中的crash信息。

adb shell logcat | ndk-stack -sym out/debug/target/product/XXXX/symbols/system/lib/xxx.so

(3)stack.py

stack.py工具就是要把backtrace通過addr2line工具一次性把addr對應到代碼

#!/usr/bin/python2.4 -E
import getopt
import os
import re
import string
import sys
import getpass
import urllib
import subprocess
def PrintUsage():printprint "  usage: " + sys.argv[0] + " [options] [FILE]"printprint "  --symbols-dir=path"print "       the path to a symbols dir, such as =/tmp/out/target/product/dream/symbols"printprint "  --symbols-zip=path"print "       the path to a symbols zip file, such as =dream-symbols-12345.zip"printprint "  --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"printprint "  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."printsys.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" + addrstream = os.popen(cmd)lines = stream.readlines()list = map(string.strip, lines)else:list = []if list != []:# Name like "move_forward_type<JavaVMOption>" causes troublesmangled_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_namestream = 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 = cookienameself.keeper = keepself.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 SSOresponse = 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 noneclass 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 traceand 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 CLparams = {'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 + symbolfilelocalsyms = symdir + symbolfileif not os.path.exists(localsyms):print "downloading %s ..." % symurlcurlcmd = ("""/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" % errif code != "200":raise SymbolDownloadException, "Faied to download %s" % symurlelse:print "using existing cache for symbols"print "extracting %s..." % symbolfilesaveddir = 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 unzipReturns:A tuple containing (the directory into which the zip file was unzipped,the path to the "symbols" directory in the unzipped file).  To cleanup, 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..." % symbolfilesaveddir = 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))printprint "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):printprint "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)continueheader = SIGNAL_LINE.search(line)if header:print header.group(1)continueheader = REGISTER_LINE.search(line)if header:print header.group(1)continueif 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 = []printprint "-----------------------------------------------------\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 = FalsezipArg = Nonefor option, value in options:if option == "--help":PrintUsage()elif option == "--symbols-dir":SYMBOLS_DIR = valueelif option == "--symbols-zip":zipArg = valueelif option == "--auto":AUTO = Trueif 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.stdinelse:print "Searching for native crashes in %s" % arguments[0]f = open(arguments[0], "r")lines = f.readlines()rootdir = Noneif AUTO:fingerprint = FindBuildFingerprint(lines)print "fingerprint:", fingerprintrootdir, SYMBOLS_DIR = DownloadSymbols(fingerprint, cookie)elif zipArg is not None:rootdir, SYMBOLS_DIR = UnzipSymbols(zipArg)print "Reading symbols from", SYMBOLS_DIRlines = ConvertTrace(lines)if rootdir is not None:# be a good citizen and clean up...os.rmdir and os.removedirs() don't workcmd = "rm -rf \"%s\"" % rootdirprint "\ncleaning up (%s)" % cmdos.system(cmd)# vi: ts=2 sw=2

使用方法:

python stack.py --symbols-dir=out/target/profuct/XXX/sysbols/  tombstone-00(tombstone文件)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/713352.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/713352.shtml
英文地址,請注明出處:http://en.pswp.cn/news/713352.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

wpa_supplicant與用戶態程序的交互分析

1 wpa_supplicant與用戶態程序wpa_cli的交互過程 1.1 交互接口類型 wpa_supplicant與用戶態程序交互的主要接口包括以下幾種&#xff1a; 1&#xff09;命令行界面&#xff1a;通過命令行工具 wpa_cli 可以與 wpa_supplicant 進行交互。wpa_cli 允許用戶執行各種 wpa_suppli…

Spark Shuffle Tracking 原理分析

Shuffle Tracking Shuffle Tracking 是 Spark 在沒有 ESS(External Shuffle Service)情況&#xff0c;并且開啟 Dynamic Allocation 的重要功能。如在 K8S 上運行 spark 沒有 ESS。本文檔所有的前提都是基于以上條件的。 如果開啟了 ESS&#xff0c;那么 Executor 計算完后&a…

MySQL 表的基本操作,結合項目的表自動初始化來講

有了數據庫以后&#xff0c;我們就可以在數據庫中對表進行增刪改查了&#xff0c;這也就意味著&#xff0c;一名真正的 CRUD Boy 即將到來&#xff08;&#x1f601;&#xff09;。 查表 查看當前數據庫中所有的表&#xff0c;使用 show tables; 命令 由于當前數據庫中還沒有…

基于Python3的數據結構與算法 - 09 希爾排序

一、引入 希爾排序是一種分組插入排序的算法。 二、排序思路 首先取一個整數d1 n/2&#xff0c;將元素分為d1個組&#xff0c;每組相鄰量取元素距離為d1&#xff0c;在各組內直接進行插入排序&#xff1b;取第二個整數d2 d1/2&#xff0c; 重復上述分組排序過程&#xff0…

Angular 2 中的樣式綁定和 NgStyle

在 Angular 2 模板中綁定內聯樣式很容易。以下是一個綁定單個樣式值的示例&#xff1a; 你還可以指定單位&#xff0c;例如在這里我們將單位設置為 em&#xff0c;但也可以使用 px、% 或 rem&#xff1a; <p [style.font-size.em]"3">A paragraph at 3em! &l…

CSS 自測題 -- 用 flex 布局繪制骰子(一、二、三【含斜三點】、四、五、六點)

一點 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>css flex布局-畫骰子</title><sty…

vue3 滾動條觸底監聽

問題&#xff1a;指定區域內&#xff0c;顯示返回的數據&#xff0c;要求先顯示20條&#xff0c;區域超出部分滾動顯示&#xff0c;對滾動條進行監聽&#xff0c;滾動條觸底后&#xff0c;繼續顯示下20條... 解決過程&#xff1a; 1.在區域的div上&#xff0c;添加scroll事件…

Unity 切換場景

場景切換前必須要將場景拖動到Build中 同步加載場景 using System.Collections; using System.Collections.Generic; //using UnityEditor.SearchService; using UnityEngine; // 場景管理 需要導入該類 using UnityEngine.SceneManagement;public class c3 : MonoBehaviour {…

redis五大基礎類型【重點】

之前寫過一點小知識&#xff1a;https://blog.csdn.net/qq_45927881/article/details/134959181?spm1001.2014.3001.5501 參考鏈接 https://xiaolincoding.com/redis/data_struct/command.html#%E4%BB%8B%E7%BB%8D 目錄 1. string&#xff08;字符串&#xff09;2. Hash&#…

MySql安全加固:配置不同用戶不同賬號禁止使用舊密碼禁止MySql進程管理員權限

MySql安全加固&#xff1a;配置不同用戶不同賬號&禁止使用舊密碼&禁止MySql進程管理員權限 1.1 檢查是否配置不同用戶不同賬號1.2 檢查是否禁止使用舊密碼1.3 禁止MySql進程管理員權限 &#x1f496;The Begin&#x1f496;點點關注&#xff0c;收藏不迷路&#x1f496…

【c++】通訊錄管理系統

1.系統功能介紹及展示 2.創建項目 3.菜單實現 4.退出功能實現 5.添加聯系人—結構體設計 6.添加聯系人—功能實現 7.顯示聯系人 8.刪除練習人—檢測聯系人是否存在 9.刪除聯系人—功能實現 10.查找聯系人 11.修改聯系人 12.清空通訊錄 #include <iostream> #include <…

什么是VR虛擬社區|VR元宇宙平臺|VR主題館加盟

VR虛擬社區是指一種基于虛擬現實技術構建的在線社交平臺或環境&#xff0c;用戶可以在其中創建虛擬化的個人形象&#xff08;也稱為avatars&#xff09;并與其他用戶進行交流、互動和合作。在VR虛擬社區中&#xff0c;用戶可以選擇不同的虛擬場景和環境&#xff0c;如虛擬公園、…

fly-barrage 前端彈幕庫(3):滾動彈幕的設計與實現

項目官網地址&#xff1a;https://fly-barrage.netlify.app/&#xff1b; &#x1f451;&#x1f40b;&#x1f389;如果感覺項目還不錯的話&#xff0c;還請點下 star &#x1f31f;&#x1f31f;&#x1f31f;。 Gitee&#xff1a;https://gitee.com/fei_fei27/fly-barrage&a…

顯示器開機正常,插入HDMI線卻不顯示畫面,換了HDMI線還是不行?

環境&#xff1a; 惠普/P24VG4 DELL筆記本 問題描述&#xff1a; 顯示器開機正常&#xff0c;插入HDMI線卻不顯示畫面&#xff0c;換了HDMI線還是不行&#xff0c;是不是顯示器壞了&#xff1f; 解決方案&#xff1a; 1.前往顯示器設置菜單里面查看input 2.把輸入源默認設…

二百二十五、海豚調度器——用DolphinScheduler調度執行Flume數據采集任務

一、目的 數倉的數據源是Kafka&#xff0c;因此離線數倉需要用Flume采集Kafka中的數據到HDFS中 在實際項目中&#xff0c;不可能一直在Xshell中啟動Flume任務&#xff0c;一是項目的Flume任務很多&#xff0c;二是一旦Xshell頁面關閉Flume任務就會停止&#xff0c;這樣非常不…

案例研究|DataEase助力眾陶聯應對產業鏈數據可視化挑戰

佛山眾陶聯供應鏈服務有限公司&#xff08;以下簡稱為“眾陶聯”&#xff09;成立于2016年&#xff0c;是由34家陶瓷企業共同創辦的建陶行業工業互聯網平臺&#xff0c;股東產值占整個行業的22.5%。眾陶聯以數據賦能為核心&#xff0c;積極探索新的交易和服務模式&#xff0c;構…

ant-design-vue如何限制圖片上傳的尺寸?

handleBeforeUpload(file, fileList) {// fileList 只包含了當次上傳的文件列表&#xff0c;不包含已上傳的文件列表// 所以長度要加上已上傳的文件列表的長度const isLimit this.fileList.length fileList.length > this.limit;const indexOfFile fileList.findIndex(it…

C++ STL 之容器 vector 常見用法

一. 什么是vector vector為“變長數組”&#xff0c;即長度根據需要而自動改變的數組。 頭文件&#xff1a; #include <vector>using namespace std;單獨定義一個vector&#xff1a;vector<typename> name&#xff0c;相當于一維數組 name[SIZE] &#xff0c;其長…

mac-docker-php容器連接mac中的pgsql數據庫失敗以及出現table_msg存錯誤時的解決方法

以php中的thinkphp 5.1為例&#xff0c;php容器連接mac中的pgsql數據庫失敗時&#xff0c;出現如下錯誤 [7] PDOException in Connection.php line 528 SQLSTATE[08006] [7] could not connect to server: Connection refused Is the server running on host "localhost&…

Git 配置處理客戶端無法正常訪問到 github 原網站時,npm 下載依賴包失敗的問題

Git 配置處理客戶端無法正常訪問到 github 原網站時&#xff0c;npm 下載依賴包失敗的問題 使用 github 的鏡像網站地址或類似的替代產品地址&#xff0c;代替到 npm 拉取依賴包的 git 地址本地Git配置 例如&#xff1a;執行一下命令&#xff0c;則是以https://kgithub.com 替…