Android调试中addr2line工具的使用

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Android调试中addr2line工具的使用
我们在解bug的时候经常能碰到一些段错误。

下面是我从一个bug的log中截取的一个段错误:
[cpp]view plaincopy
1.//////////////////////////////////////////////////////////////// //////////////////////////////////////
2.08-
19 19:08:27.132 **** **** I DEBUG : pid: 134, tid: 2104, nam e: OMXCallbackDisp >>> /system/bin/mediaserver <<<
3.08-
19 19:08:27.132 **** **** I DEBUG : signal 11 (SIGSEGV), co de 2 (SEGV_ACCERR), fault addr 44c86948
4.08-
19 19:08:27.280 1803 1803 I SurfaceTextureClient: [STC::queue Buffer] (this:0x6162c9f8) fps:21.68, dur:1014.76, max:104.52, min :10.36
5.08-
19 19:08:27.281 130 1018 I BufferQueue: [com.android.gallery 3d/com.android.camera.Camera](this:0x41c1f008,api:1) [queue] fps:21.70, dur:1013.89, max:103.33, min:10.27
6.08-
19 19:08:27.293 130 321 I SurfaceTextureClient: [STC::queueB uffer] (this:0x406df2e0) fps:34.70, dur:1037.44, max:75.25, min:1 4.19
7.08-
19 19:08:27.294 130 321 I BufferQueue: [FramebufferSurface]( this:0x406de810,api:1) [release] fps:34.70, dur:1037.44, max:75.2 3, min:14.19
8.08-
19 19:08:27.294 130 321 I BufferQueue: [FramebufferSurface]( this:0x406de810,api:1) [queue] fps:34.70, dur:1037.43, max:75.23 , min:14.19
9.08-
19 19:08:27.294 130 321 I SurfaceFlinger: [SurfaceFlinger] fps: 34.701393,dur:1037.42,max:75.22,min:14.19
10.08-
19 19:08:27.452 465 538 D MDLOGGER: pMDEngine->m_bTer minate is false. busy for modem = 0,m_nM2ABufCnt = 8
11.08-
19 19:08:27.452 465 538 D MDLOGGER: thrDetectFilter: Detec ting catcher_filter.bin exist or not every 5 seconds!
12.08-
19 19:08:27.462 2105 2105 I DEBUG : r0 00000000 r1 0000 0081 r2 00000001 r3 ffffffe8
13.08-
19 19:08:27.462 2105 2105 I DEBUG : r4 46d4de60 r5 4267 1490 r6 40185d35 r7 00100000
14.08-
19 19:08:27.462 2105 2105 I DEBUG : r8 45661240 r9 0000 0000 sl 40dd0159 fp 46c4d930
15.08-
19 19:08:27.462 2105 2105 I DEBUG : ip ffffffea sp 46d4de 38 lr 4009915c pc 44c86948 cpsr 60000010
16.08-19 19:08:27.462 2105 2105 I DEBUG :
17.08-
19 19:08:27.462 2105 2105 I DEBUG : backtrace:
18.08-
19 19:08:27.462 2105 2105 I DEBUG : #00 pc 00042948 <u nknown>
19.08-
19 19:08:27.462 2105 2105 I DEBUG : #01 pc 0000d158 /s ystem/lib/libc.so
20.08-
19 19:08:27.462 2105 2105 I DEBUG : #02 pc 00032954 <u nknown>
21.08-19 19:08:27.462 2105 2105 I DEBUG :
22.08-19 19:08:27.462 2105 2105 I DEBUG : stack:
23.08-
19 19:08:27.462 2105 2105 I DEBUG : 46d4ddf8 000000 00
24.08-
19 19:08:27.462 2105 2105 I DEBUG : 46d4ddfc 000000
20
25.08-
19 19:08:27.462 2105 2105 I DEBUG : 46d4de00 000000 00
26.08-
19 19:08:27.462 2105 2105 I DEBUG : 46d4de04 000000 00
27.08-
19 19:08:27.462 2105 2105 I DEBUG : 46d4de08 000000 00
28.08-
19 19:08:27.462 2105 2105 I DEBUG : 46d4de0c 46d4de 34 [stack:2104]
29.08-
19 19:08:27.462 2105 2105 I DEBUG : 46d4de10 44c86a 04
30.08-
19 19:08:27.462 2105 2105 I DEBUG : 46d4de14 46d4de 60 [stack:2104]
31.08-
19 19:08:27.462 2105 2105 I DEBUG : 46d4de18 426714 90
32.08-
19 19:08:27.462 2105 2105 I DEBUG : 46d4de1c 40185d 35 /system/lib/libutils.so
33.08-
19 19:08:27.462 2105 2105 I DEBUG : 46d4de20 001000 00
34.08-
19 19:08:27.462 2105 2105 I DEBUG : 46d4de24 456612 40
35.08-
19 19:08:27.462 2105 2105 I DEBUG : 46d4de28 000000 00
36.08-
19 19:08:27.462 2105 2105 I DEBUG : 46d4de2c 40dd01 59 /system/lib/libstagefright.so
37.08-
19 19:08:27.462 2105 2105 I DEBUG : 46d4de30 df0027 ad
38.08-
19 19:08:27.462 2105 2105 I DEBUG : 46d4de34 000000 00
39.08-
19 19:08:27.462 2105 2105 I DEBUG : #00 46d4de38 46d4 de60 [stack:2104]
40.08-
19 19:08:27.463 2105 2105 I DEBUG : ........ ........
41.08-
19 19:08:27.463 2105 2105 I DEBUG : #01 46d4de38 46d4 de60 [stack:2104]
42.08-
19 19:08:27.463 2105 2105 I DEBUG : 46d4de3c 46c4d9 58
43.08-
19 19:08:27.463 2105 2105 I DEBUG : #02 46d4de40 46d4 de80 [stack:2104]
44.08-
19 19:08:27.463 2105 2105 I DEBUG : 46d4de44 40f01d 33 /system/lib/libstagefright_omx.so (android::OMXNodeInstan ce::onMessage(android::omx_message const&)+50)
45.08-
19 19:08:27.463 2105 2105 I DEBUG : 46d4de48 46c4db 48
46.08-
19 19:08:27.463 2105 2105 I DEBUG : 46d4de4c 46c4db 5c
47.08-
19 19:08:27.463 2105 2105 I DEBUG : 46d4de50 46d4de 80 [stack:2104]
48.08-
19 19:08:27.463 2105 2105 I DEBUG : 46d4de54 40f003 47 /system/lib/libstagefright_omx.so (android::OMX::CallbackDi spatcher::loop()+110)
49.08-
19 19:08:27.463 2105 2105 I DEBUG : 46d4de58 000000 00
50.08-
19 19:08:27.463 2105 2105 I DEBUG : 46d4de5c 46c4db
50
51.08-
19 19:08:27.463 2105 2105 I DEBUG : 46d4de60 000000 00
52.08-
19 19:08:27.463 2105 2105 I DEBUG : 46d4de64 000000 19
53.08-
19 19:08:27.463 2105 2105 I DEBUG : 46d4de68 000000 00
54.08-
19 19:08:27.463 2105 2105 I DEBUG : 46d4de6c 000000 00
55.08-
19 19:08:27.463 2105 2105 I DEBUG : 46d4de70 000000 02
56.08-
19 19:08:27.463 2105 2105 I DEBUG : 46d4de74 45def1 ac /system/lib/libMtkOmxVdec.so
57.08-
19 19:08:27.463 2105 2105 I DEBUG : 46d4de78 44c89f 38
58.08-
19 19:08:27.463 2105 2105 I DEBUG : 46d4de7c 45dede a1 /system/lib/libMtkOmxVdec.so (MtkOmxVdec::DeInitVideoD ecodeHW()+84)
59.///////////////////////////////////////////////////////////// /////////////////////////////////////////
有没有看起来很眼熟?
关于段错误的定义,我百科了一下:
所谓的段错误就是指访问的内存超出了系统所给这个程序的内存空间,通常这个值是由gd tr来保存的,他是一个48位的寄存器,其中的32位是保存由它指向的 gdt表,后13位保存相应于gdt的下标,最后3位包括了程序是否在内存中以及程序的在cpu中的运行级别,指向的gdt是由以64位为一个单位的表,在这张表中就保存着程序运行的代码段以及数据段的起始地址以及与此相应的段限和页面交换还有程序运行级别还有内存粒度等等的信息。

【不甚理解】在Android 的工程当中,有一部分文件会被编译成so 动态共享库供系统运行时不同模块链接使用。

若调用出错的话,会报出如上面文本中贴出来的段错误。

出了这种错误,我们一般都会通过 add2line 工具解析具体出错代码的位置,能精确到哪个文件,哪一行!再去具体位置的代码查看。

若你去找这个文件的时候却发现没有,不必要大惊小怪,MTK没有提供。

在MTK 提供的Android 的工程代码中,经常会出于一些保密方面的考虑,将一些核心文件编译成 so 库提供给客户。

让客户看不到这一部分的代码,但是能够正常使用。

诸如此类问题,可以提给MTK客服让其帮忙追查Bug!
1,在MTK的工程中,我们是这样来解析段错误的:
我们将backtrace 以下的段错误copy 到trace.txt中。

(trace.txt放到工程根目录下)
然后在linux 环境下面,进到工程根目录,执行如下命令:
./adbs -sout/target/product/bbk82_wet_jb5/symbols/ -l trace.txt>a.txt
将会解析得到 a.txt 文件,该文件中就能追溯到具体哪一个文件哪一行出错了。

trace.txt内容:
[cpp]view plaincopy
1.08-19 19:08:27.462 2105 2105 I DEBUG : backtrace:
2.08-
19 19:08:27.462 2105 2105 I DEBUG : #00 pc 00042948 <u nknown>
3.08-
19 19:08:27.462 2105 2105 I DEBUG : #01 pc 0000d158 /s ystem/lib/libc.so
4.08-
19 19:08:27.462 2105 2105 I DEBUG : #02 pc 00032954 <u nknown>
adbs 是一个脚本文件,它的作用是调用 arm-linux-androideabi-addr2line这个工具来解析trace.txt 中的内容,并将解析的结果存到一个具体的文件中去,譬如 a.txt
-s 和 -l 是参数
解析出来的结果 a.txt内容:
[cpp]view plaincopy
1.08-19 19:08:27.462 2105 2105 I DEBUG : backtrace:
2.
3.08-19 19:08:27.462 2105 2105 I DEBUG : backtrace:
4.08-
19 19:08:27.462 2105 2105 I DEBUG : #00 pc 00042948 <u nknown>
5.
6.08-
19 19:08:27.462 2105 2105 I DEBUG : #00 (unknown) (unk nown)
7.08-
19 19:08:27.462 2105 2105 I DEBUG : #01 pc 0000d158 /s ystem/lib/libc.so
8.
9.08-
19 19:08:27.462 2105 2105 I DEBUG : #01 __pthread_cond_ pulse /home/compiler/workspace/gphone/MT6582/PD1224CT/ ALPS.JB5.MP.V1.6_WET_20130810_trunk_user/bionic/libc/bionic/ pthread.c:1689
10.08-
19 19:08:27.462 2105 2105 I DEBUG : #02 pc 00032954 <u nknown>
11.
12.08-
19 19:08:27.462 2105 2105 I DEBUG : #02 (unknown) (unk nown)
13.08-19 19:08:27.462 2105 2105 I DEBUG :
adbs 内容:
[cpp]view plaincopy
1.#!/usr/bin/env python
2.
3.import os
4.import re
5.import string
6.import sys
7.import getopt
8.
9.########################################### ####################################
10.# match "#00 pc 0003f52e /system/lib/libdvm.so" for example
11.######################################## #######################################
12.trace_line = pile("(.*)(\#[0-9]+) (..) ([0-9a-
f]{8}) ([^\r\n \t]*)")
13.
14.
15.class Options(object):pass
16.OPTIONS = Options()
17.OPTIONS.symbols = ""
18.OPTIONS.log = ""
19.
20.# returns a list containing the function name and the f ile/lineno
21.def CallAddr2Line(lib, addr):
22.global symbols_dir
23.global addr2line_cmd
24.global cppfilt_cmd
25.
26.if lib != "":
27.cmd = addr2line_cmd + \
28." -f -e " + symbols_dir + lib + " 0x" + addr
29.stream = os.popen(cmd)
30.lines = stream.readlines()
31.list = map(string.strip, lines)
32.else:
33.list = []
34.if list != []:
35.# Name like "move_forward_type<JavaVMOption>" c
auses troubles
36.mangled_name = re.sub('<', '\<', list[0]);
37.mangled_name = re.sub('>', '\>', mangled_name);
38.cmd = cppfilt_cmd + " " + mangled_name
39.stream = os.popen(cmd)
40.list[0] = stream.readline()
41.stream.close()
42.list = map(string.strip, list)
43.else:
44.list = [ "(unknown)", "(unknown)" ]
45.return list
46.
47.
48.######################################## #######################################
49.# similar to CallAddr2Line, but using objdump to find out the name of the
50.# containing function of the specified address
51.######################################## #######################################
52.def CallObjdump(lib, addr):
53.global objdump_cmd
54.global symbols_dir
55.
56.unknown = "(unknown)"
57.uname = os.uname()[0]
58.if uname == "Darwin":
59.proc = os.uname()[-1]
60.if proc == "i386":
61.uname = "darwin-x86"
62.else:
63.uname = "darwin-ppc"
64.elif uname == "Linux":
65.uname = "linux-x86"
66.if lib != "":
67.next_addr = string.atoi(addr, 16) + 1
68.cmd = objdump_cmd \
69.+ " -C -d --start-address=0x" + addr + " --stop-address=" \
70.+ str(next_addr) \
71.+ " " + symbols_dir + lib
72.stream = os.popen(cmd)
73.lines = stream.readlines()
74.map(string.strip, lines)
75.stream.close()
76.else:
77.return unknown
78.
79.# output looks like
80.# file format elf32-littlearm
81.# Disassembly of section .text:
82.# 0000833c <func+0x4>:
83.# 833c: 701a strb r2, [r3, #0]
84.# we want to extract the "func" part
85.num_lines = len(lines)
86.if num_lines < 2:
87.return unknown
88.func_name = lines[num_lines-2]
89.func_regexp = pile("(^.*\<)(.*)(\+.*\>:$)")
ponents = func_regexp.match(func_name)
91.if components is None:
92.return unknown
93.return components.group(2)
94.
95.######################################## #######################################
96.# determine the symbols directory in the local build
97.######################################## #######################################
98.def FindSymbolsDir():
99.global symbols_dir
100.
101.try:
102.#path = "sourcecode/MT6575/ALPS.ICS.MP.V2_W_201 20504/out/target/product/bbk75_cu_ics/symbols/"
103.if (len(OPTIONS.symbols) == 0):
104.path = os.environ['ANDROID_PRODUCT_OUT'] + "/sy mbols"
105.else:
106.path = OPTIONS.symbols
107.except:
108.cmd = "CALLED_FROM_SETUP=true BUILD_SYSTEM=b uild/core " \
109.+ "SRC_TARGET_DIR=build/target make -
f build/core/config.mk " \
110.+ "dumpvar-abs-TARGET_OUT_UNSTRIPPED"
111.stream = os.popen(cmd)
112.str = stream.read()
113.stream.close()
114.path = str.strip()
115.
116.if (not os.path.exists(path)):
117.print path + " not found!"
118.sys.exit(1)
119.
120.symbols_dir = path
121.
122.######################################## ####################################### 123.# determine the path of binutils
124.######################################## ####################################### 125.def SetupT oolsPath():
126.global addr2line_cmd
127.global objdump_cmd
128.global cppfilt_cmd
129.global symbols_dir
130.
131.uname = os.uname()[0]
132.if uname == "Darwin":
133.proc = os.uname()[-1]
134.if proc == "i386":
135.uname = "darwin-x86"
136.else:
137.uname = "darwin-ppc"
138.elif uname == "Linux":
139.uname = "linux-x86"
140.prefix = "./prebuilts/gcc/" + uname + "/arm/arm-linux-androideabi-4.6/bin/"
141.addr2line_cmd = prefix + "arm-linux-androideabi-
addr2line"
142.
143.if (not os.path.exists(addr2line_cmd)):
144.try:
145.prefix = os.environ['ANDROID_BUILD_TOP'] + "/prebui lt/gcc/" + uname + \
146."/arm/arm-linux-androideabi-4.6/bin/"
147.except:
148.prefix = "";
149.
150.addr2line_cmd = prefix + "arm-linux-androideabi-addr2line"
151.if (not os.path.exists(addr2line_cmd)):
152.print addr2line_cmd + " not found!"
153.sys.exit(1)
154.
155.objdump_cmd = prefix + "arm-linux-androideabi-objdump"
156.cppfilt_cmd = prefix + "arm-linux-androideabi-
c++filt"
157.
158.######################################## ####################################### 159.# look up the function and file/line number for a raw s tack trace line
160.# groups[0]: log tag
161.# groups[1]: stack level
162.# groups[2]: "pc"
163.# groups[3]: code address
164.# groups[4]: library name
165.######################################## ####################################### 166.def SymbolTranslation(groups):
167.lib_name = groups[4]
168.code_addr = groups[3]
169.caller = CallObjdump(lib_name, code_addr)
170.func_line_pair = CallAddr2Line(lib_name, code_addr) 171.
172.# If a callee is inlined to the caller, objdump will see th e caller's
173.# address but addr2line will report the callee's address . So the printed
174.# format is desgined to be "caller<-callee file:line"
175.if (func_line_pair[0] != caller):
176.print groups[0] + groups[1] + " " + caller + "<-" + \ 177.' '.join(func_line_pair[:]) + " "
178.else:
179.print groups[0] + groups[1] + " " + ' '.join(func_line_p air[:]) + " "
180.
181.######################################## ####################################### 182.
MON_DOCSTRING = """
184.-s (--symbols) <symbols dir>
185.-l (--log) <logcat file>
186.
187.eg:
188.adbs -s out/target/product/bbk75_cu_ics/symbols/ -l logcat.txt
189.or
190.adbs -
s out/target/product/bbk75_cu_ics/symbols/ logcat 191."""
192.
193.def Usage():
194.print COMMON_DOCSTRING
195.
196.if __name__ == '__main__':
197.
198.try:
199.opts, args = getopt.getopt(sys.argv[1:], "hs:l:", 200.["help", "symbols=", "log="])
201.except getopt.GetOptError:
age()
203.
204.for o, a in opts:
205.if o in ("-h", "--help"):
age()
207.sys.exit()
208.elif o in ("-s", "--symbols"):
209.OPTIONS.symbols = a
210.elif o in ("-l", "--log="):
211.OPTIONS.log = a
212.
213.# pass the options to adb
214.#adb_cmd = "adb " + ' '.join(sys.argv[1:])
215.if (len(OPTIONS.log) == 0):
216.adb_cmd = "adb " + ' '.join(args)
217.else:
218.adb_cmd = "cat " + OPTIONS.log
219.
220.# setup addr2line_cmd and objdump_cmd 221.SetupT oolsPath()
222.
223.# setup the symbols directory
224.FindSymbolsDir()
225.
226.# invoke the adb command and filter its output 227.stream = os.popen(adb_cmd)
228.while (True):
229.line = stream.readline()
230.print line
231.# EOF reached
232.if (line == ''):
233.break
234.
235.# remove the trailing \n
236.line = line.strip()
237.
238.# see if this is a stack trace line
239.match = trace_line.match(line)
240.if (match):
241.groups = match.groups()
242.# translate raw address into symbols
243.SymbolTranslation(groups)
244.else:
245.print line
246.sys.stdout.flush()
247.
248.# adb itself aborts
249.stream.close()
通过分析,我们最终找到错误发生于 /home/compiler/workspace/gphone/MT6582/project_name/ ALPS.JB5.MP.V1.6_WET_20130810_trunk_user/bionic/libc/bionic/ pthread.c:1689
实际上libc.so 出错对我们的帮助不大,需要找更上层的出错的地方。

或者通过log去分析app层的错误。

注意:
需要注意的是symbols目录需要与 bug对应的版本号编译出来的那个symbols。

直接用本地目录下的symbols 解析出来的会与trace 中的错误不一致!如果没有相应的 symbols 目录,那么我们需要自己重新编译一个软件出来复现问题,再从头来分析该段错误并解析。

symbols 下面的库会多出来一些调试信息。

2,高通平台下解析段错误就很简单了。

同样需要对应出问题版本下编译出来的symbols目录解压覆盖原来的 out/product/project_name/symbols 目录。

通过如下方式来实现解析!
arm-eabi-addr2line-fe ./out-PD1225TMA/target/product/msm8960/symbols/system/lib/libc. so 0000e498
-fe 参数 libc.so 出问题的库, 0000e498 函数地址。

参考资料:
1,【百科段错误】/view/3994532.htm
2,【linux 下动态链接库、静态链接库】。

相关文档
最新文档