TraceView issue
使用traceview時,遇到一個這樣的問題:
Exception in thread "main" java.lang.RuntimeException: Method exit (android/widget/AbsListView.startScrollIfNeeded (I)Z) does not match current method (java/lang/Math.abs (I)I)
這個是google自己bug,貌似出現在android4.0-4.2之間,主要是在mips架構里面發現的,不過現在的最新版本已修復此bug。
如果不幸拿到的android源碼還存在這個bug,需要自己修復。
traceiew的工作原理是跟蹤函數的調用路徑,然后計算整條調用路徑或者單個函數的執行時間,進而測試系統或者應用程序的性能。實際上,traceiew只是在pc端運行的一個工具,它用來解析目標設備上生成的.trace文件。所以,traceview本身沒有問題,只是目標設備上生成的.trace文件有問題。目標設備上是使用profile生成.trace文件的。profile把函數的進入(entry)和退出(exit)都記錄在.trace文件中,記錄的存儲方式是按照棧(stack)的方式,所以traceiew解析.trace文件時也需要用棧的方式。
現在出現錯誤的原因是函數的進入(entry)和退出(exit)不配對,也就是說有些函數的進入或者退出沒有被記錄下來。這就需要跟蹤.trace文件是如何生成的。
詳細的過程就不螯述了,這里只說一下跟蹤的路徑吧,有興趣的朋友可以看下。經過的文件有:
frameworks/base/cmds/am/src/com/android/commands/am/Am.java
frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
frameworks/base/core/java/android/app/ActivityThread.java
frameworks/base/core/java/android/os/Debug.java
libcore/dalvik/src/main/java/dalvik/system/VMDebug.java
dalvik/vm/native/dalvik_system_VMDebug.cpp
dalvik/vm/Profile.cpp
.trace最主要的生成過程是在dalvik/vm/Profile.cpp中,后來發現最可能出錯的地方是,其中只有一個記錄函數進入的地方,然而卻有兩個記錄退出的地方。所以有可能是退出時使用了錯誤的函數。
記錄進入的函數:
dvmFastMethodTraceEnter
記錄退出的兩個函數:
dvmFastNativeMethodTraceExit
dvmFastMethodTraceExit
這些函數是在匯編代碼里邊調用的,涉及到匯編代碼就是架構相關了。android支持的架構有ARM,MIPS和X86。既然是在MIPS發現了這個問題,所以就看MIPS架構相關的代碼,后來發現在:
dalvik/vm/mterp/mips/OP_EXECUTE_INLINE.S
dalvik/vm/mterp/mips/OP_EXECUTE_INLINE_RANGE.S
dalvik/vm/mterp/out/InterpAsm-mips.S
這三個文件里面都調用了上面的函數。第三個文件是由很多.S文件(包括第一和第二個文件)生成的,可以忽視。所以調查前兩個文件。
OP_EXECUTE_INLINE.S里調用的代碼片段:
.L${opcode}_debugmode:move a0, rBIXJAL(dvmResolveInlineNative)beqz v0, .L${opcode}_resume # did it resolve? no, just move onmove rOBJ, v0 # remember methodmove a0, v0move a1, rSELFJAL(dvmFastMethodTraceEnter) # (method, self)addu a1, rSELF, offThread_retval # a1<- &self->retvalGET_OPB(a0) # a0 <- B# Stack should have 16/20 availablesw a1, 16(sp) # push &self->retvalBAL(.L${opcode}_continue) # make call; will return afterlw gp, STACK_OFFSET_GP(sp) # restore gpmove rINST, v0 # save result of inlinemove a0, rOBJ # a0<- methodmove a1, rSELF # a1<- selfJAL(dvmFastMethodTraceExit) # (method, self)beqz v0, common_exceptionThrown # returned false, handle exceptionFETCH_ADVANCE_INST(3) # advance rPC, load rINSTGET_INST_OPCODE(t0) # extract opcode from rINSTGOTO_OPCODE(t0) # jump to next instructionOP_EXECUTE_INLINE_RANGE.S里面的調用片段:
/** We're debugging or profiling.* rBIX: opIndex*/ .L${opcode}_debugmode:move a0, rBIXJAL(dvmResolveInlineNative)beqz v0, .L${opcode}_resume # did it resolve? no, just move onmove rOBJ, v0 # remember methodmove a0, v0move a1, rSELFJAL(dvmFastMethodTraceEnter) # (method, self)addu a1, rSELF, offThread_retval # a1<- &self->retvalGET_OPA(a0) # a0 <- A# Stack should have 16/20 availablesw a1, 16(sp) # push &self->retvalmove rINST, rOBJ # rINST<- methodBAL(.L${opcode}_continue) # make call; will return afterlw gp, STACK_OFFSET_GP(sp) # restore gpmove rOBJ, v0 # save result of inlinemove a0, rINST # a0<- methodmove a1, rSELF # a1<- selfJAL(dvmFastNativeMethodTraceExit) # (method, self)beqz rOBJ, common_exceptionThrown # returned false, handle exceptionFETCH_ADVANCE_INST(3) # advance rPC, load rINSTGET_INST_OPCODE(t0) # extract opcode from rINSTGOTO_OPCODE(t0) # jump to next instruction其中,OP_EXECUTE_INLINE.S調用的組合是:
dvmFastMethodTraceEnter
dvmFastMethodTraceExit
OP_EXECUTE_INLINE_RANGE.S調用的組合是:
dvmFastMethodTraceEnter
dvmFastNativeMethodTraceExit
但是,我發現OP_EXECUTE_INLINE.S里面的調用是不符合邏輯的。
請看:
move a0, rOBJ # a0<- methodmove a1, rSELF # a1<- selfJAL(dvmFastMethodTraceExit) # (method, self)這段代碼,程序準備了a0 和a1兩個參數,但是回頭看看dvmFastMethodTraceExit和dvmFastNativeMethodTraceExit的函數原型:void dvmFastMethodTraceExit(Thread* self)
void dvmFastNativeMethodTraceExit(const Method* method, Thread* self)
很明顯,dvmFastMethodTraceExit只有一個參數,所以沒必要準備兩個參數。所以,這段代碼的編寫者原意應該是想要調用dvmFastNativeMethodTraceExit的。把OP_EXECUTE_INLINE.S里面的dvmFastMethodTraceExit換成dvmFastNativeMethodTraceExit,執行dalvik/vm/mterp/rebuild.sh重新生成dalvik/vm/mterp/out/InterpAsm-mips.S,然后重編dalvik,啟動運行,生成.trace文件,traceiew解析,成功了!
總結
以上是生活随笔為你收集整理的TraceView issue的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ctfmon.exe频繁出错的一个解决办
- 下一篇: 【VS2015】 C++实现硬件ID的查