17c47a371SJonas Devlieghere# Usage: 27c47a371SJonas Devlieghere# art/test/run-test --host --gdb [--64] [--interpreter] 004-JniTest 37c47a371SJonas Devlieghere# 'b Java_Main_shortMethod' 47c47a371SJonas Devlieghere# 'r' 57c47a371SJonas Devlieghere# 'command script import host_art_bt.py' 67c47a371SJonas Devlieghere# 'host_art_bt' 77c47a371SJonas Devlieghere 87c47a371SJonas Devlieghereimport sys 97c47a371SJonas Devlieghereimport re 107c47a371SJonas Devlieghere 117c47a371SJonas Devlieghereimport lldb 127c47a371SJonas Devlieghere 137c47a371SJonas Devlieghere 147c47a371SJonas Devliegheredef host_art_bt(debugger, command, result, internal_dict): 157c47a371SJonas Devlieghere prettified_frames = [] 167c47a371SJonas Devlieghere lldb_frame_index = 0 177c47a371SJonas Devlieghere art_frame_index = 0 187c47a371SJonas Devlieghere target = debugger.GetSelectedTarget() 197c47a371SJonas Devlieghere process = target.GetProcess() 207c47a371SJonas Devlieghere thread = process.GetSelectedThread() 217c47a371SJonas Devlieghere while lldb_frame_index < thread.GetNumFrames(): 227c47a371SJonas Devlieghere frame = thread.GetFrameAtIndex(lldb_frame_index) 23*602e47c5SDavid Spickett if frame.GetModule() and re.match( 24*602e47c5SDavid Spickett r"JIT\(.*?\)", frame.GetModule().GetFileSpec().GetFilename() 25*602e47c5SDavid Spickett ): 267c47a371SJonas Devlieghere # Compiled Java frame 277c47a371SJonas Devlieghere 287c47a371SJonas Devlieghere # Get function/filename/lineno from symbol context 297c47a371SJonas Devlieghere symbol = frame.GetSymbol() 307c47a371SJonas Devlieghere if not symbol: 31*602e47c5SDavid Spickett print("No symbol info for compiled Java frame: ", frame) 327c47a371SJonas Devlieghere sys.exit(1) 337c47a371SJonas Devlieghere line_entry = frame.GetLineEntry() 34*602e47c5SDavid Spickett prettified_frames.append( 35*602e47c5SDavid Spickett { 36*602e47c5SDavid Spickett "function": symbol.GetName(), 37*602e47c5SDavid Spickett "file": str(line_entry.GetFileSpec()) if line_entry else None, 38*602e47c5SDavid Spickett "line": line_entry.GetLine() if line_entry else -1, 39*602e47c5SDavid Spickett } 40*602e47c5SDavid Spickett ) 417c47a371SJonas Devlieghere 427c47a371SJonas Devlieghere # Skip art frames 437c47a371SJonas Devlieghere while True: 447c47a371SJonas Devlieghere art_stack_visitor = frame.EvaluateExpression( 45*602e47c5SDavid Spickett """struct GetStackVisitor : public StackVisitor { GetStackVisitor(int depth_) : StackVisitor(Thread::Current(), NULL), depth(depth_) {} bool VisitFrame() { if (cur_depth_ == depth) { return false; } else { return true; } } int depth; }; GetStackVisitor visitor(""" 46*602e47c5SDavid Spickett + str(art_frame_index) 47*602e47c5SDavid Spickett + """); visitor.WalkStack(true); visitor""" 48*602e47c5SDavid Spickett ) 497c47a371SJonas Devlieghere art_method = frame.EvaluateExpression( 50*602e47c5SDavid Spickett art_stack_visitor.GetName() + """.GetMethod()""" 51*602e47c5SDavid Spickett ) 527c47a371SJonas Devlieghere if art_method.GetValueAsUnsigned() != 0: 537c47a371SJonas Devlieghere art_method_name = frame.EvaluateExpression( 54*602e47c5SDavid Spickett """art::PrettyMethod(""" + art_method.GetName() + """, true)""" 55*602e47c5SDavid Spickett ) 567c47a371SJonas Devlieghere art_method_name_data = frame.EvaluateExpression( 57*602e47c5SDavid Spickett art_method_name.GetName() + """.c_str()""" 58*602e47c5SDavid Spickett ).GetValueAsUnsigned() 597c47a371SJonas Devlieghere art_method_name_size = frame.EvaluateExpression( 60*602e47c5SDavid Spickett art_method_name.GetName() + """.length()""" 61*602e47c5SDavid Spickett ).GetValueAsUnsigned() 627c47a371SJonas Devlieghere error = lldb.SBError() 637c47a371SJonas Devlieghere art_method_name = process.ReadCStringFromMemory( 64*602e47c5SDavid Spickett art_method_name_data, art_method_name_size + 1, error 65*602e47c5SDavid Spickett ) 667c47a371SJonas Devlieghere if not error.Success: 67*602e47c5SDavid Spickett print("Failed to read method name") 687c47a371SJonas Devlieghere sys.exit(1) 697c47a371SJonas Devlieghere if art_method_name != symbol.GetName(): 70*602e47c5SDavid Spickett print( 71*602e47c5SDavid Spickett "Function names in native symbol and art runtime stack do not match: ", 72*602e47c5SDavid Spickett symbol.GetName(), 73*602e47c5SDavid Spickett " != ", 74*602e47c5SDavid Spickett art_method_name, 75*602e47c5SDavid Spickett ) 767c47a371SJonas Devlieghere art_frame_index = art_frame_index + 1 777c47a371SJonas Devlieghere break 787c47a371SJonas Devlieghere art_frame_index = art_frame_index + 1 797c47a371SJonas Devlieghere 807c47a371SJonas Devlieghere # Skip native frames 817c47a371SJonas Devlieghere lldb_frame_index = lldb_frame_index + 1 827c47a371SJonas Devlieghere if lldb_frame_index < thread.GetNumFrames(): 837c47a371SJonas Devlieghere frame = thread.GetFrameAtIndex(lldb_frame_index) 847c47a371SJonas Devlieghere if frame.GetModule() and re.match( 85*602e47c5SDavid Spickett r"JIT\(.*?\)", frame.GetModule().GetFileSpec().GetFilename() 86*602e47c5SDavid Spickett ): 877c47a371SJonas Devlieghere # Another compile Java frame 887c47a371SJonas Devlieghere # Don't skip; leave it to the next iteration 897c47a371SJonas Devlieghere continue 90*602e47c5SDavid Spickett elif frame.GetSymbol() and ( 91*602e47c5SDavid Spickett frame.GetSymbol().GetName() == "art_quick_invoke_stub" 92*602e47c5SDavid Spickett or frame.GetSymbol().GetName() == "art_quick_invoke_static_stub" 93*602e47c5SDavid Spickett ): 947c47a371SJonas Devlieghere # art_quick_invoke_stub / art_quick_invoke_static_stub 957c47a371SJonas Devlieghere # Skip until we get past the next ArtMethod::Invoke() 967c47a371SJonas Devlieghere while True: 977c47a371SJonas Devlieghere lldb_frame_index = lldb_frame_index + 1 987c47a371SJonas Devlieghere if lldb_frame_index >= thread.GetNumFrames(): 99*602e47c5SDavid Spickett print( 100*602e47c5SDavid Spickett "ArtMethod::Invoke not found below art_quick_invoke_stub/art_quick_invoke_static_stub" 101*602e47c5SDavid Spickett ) 1027c47a371SJonas Devlieghere sys.exit(1) 1037c47a371SJonas Devlieghere frame = thread.GetFrameAtIndex(lldb_frame_index) 104*602e47c5SDavid Spickett if ( 105*602e47c5SDavid Spickett frame.GetSymbol() 106*602e47c5SDavid Spickett and frame.GetSymbol().GetName() 107*602e47c5SDavid Spickett == "art::mirror::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)" 108*602e47c5SDavid Spickett ): 1097c47a371SJonas Devlieghere lldb_frame_index = lldb_frame_index + 1 1107c47a371SJonas Devlieghere break 1117c47a371SJonas Devlieghere else: 112*602e47c5SDavid Spickett print("Invalid frame below compiled Java frame: ", frame) 113*602e47c5SDavid Spickett elif ( 114*602e47c5SDavid Spickett frame.GetSymbol() 115*602e47c5SDavid Spickett and frame.GetSymbol().GetName() == "art_quick_generic_jni_trampoline" 116*602e47c5SDavid Spickett ): 1177c47a371SJonas Devlieghere # Interpreted JNI frame for x86_64 1187c47a371SJonas Devlieghere 1197c47a371SJonas Devlieghere # Skip art frames 1207c47a371SJonas Devlieghere while True: 1217c47a371SJonas Devlieghere art_stack_visitor = frame.EvaluateExpression( 122*602e47c5SDavid Spickett """struct GetStackVisitor : public StackVisitor { GetStackVisitor(int depth_) : StackVisitor(Thread::Current(), NULL), depth(depth_) {} bool VisitFrame() { if (cur_depth_ == depth) { return false; } else { return true; } } int depth; }; GetStackVisitor visitor(""" 123*602e47c5SDavid Spickett + str(art_frame_index) 124*602e47c5SDavid Spickett + """); visitor.WalkStack(true); visitor""" 125*602e47c5SDavid Spickett ) 1267c47a371SJonas Devlieghere art_method = frame.EvaluateExpression( 127*602e47c5SDavid Spickett art_stack_visitor.GetName() + """.GetMethod()""" 128*602e47c5SDavid Spickett ) 1297c47a371SJonas Devlieghere if art_method.GetValueAsUnsigned() != 0: 1307c47a371SJonas Devlieghere # Get function/filename/lineno from ART runtime 1317c47a371SJonas Devlieghere art_method_name = frame.EvaluateExpression( 132*602e47c5SDavid Spickett """art::PrettyMethod(""" + art_method.GetName() + """, true)""" 133*602e47c5SDavid Spickett ) 1347c47a371SJonas Devlieghere art_method_name_data = frame.EvaluateExpression( 135*602e47c5SDavid Spickett art_method_name.GetName() + """.c_str()""" 136*602e47c5SDavid Spickett ).GetValueAsUnsigned() 1377c47a371SJonas Devlieghere art_method_name_size = frame.EvaluateExpression( 138*602e47c5SDavid Spickett art_method_name.GetName() + """.length()""" 139*602e47c5SDavid Spickett ).GetValueAsUnsigned() 1407c47a371SJonas Devlieghere error = lldb.SBError() 1417c47a371SJonas Devlieghere function = process.ReadCStringFromMemory( 142*602e47c5SDavid Spickett art_method_name_data, art_method_name_size + 1, error 143*602e47c5SDavid Spickett ) 1447c47a371SJonas Devlieghere 145*602e47c5SDavid Spickett prettified_frames.append( 146*602e47c5SDavid Spickett {"function": function, "file": None, "line": -1} 147*602e47c5SDavid Spickett ) 1487c47a371SJonas Devlieghere 1497c47a371SJonas Devlieghere art_frame_index = art_frame_index + 1 1507c47a371SJonas Devlieghere break 1517c47a371SJonas Devlieghere art_frame_index = art_frame_index + 1 1527c47a371SJonas Devlieghere 1537c47a371SJonas Devlieghere # Skip native frames 1547c47a371SJonas Devlieghere lldb_frame_index = lldb_frame_index + 1 1557c47a371SJonas Devlieghere if lldb_frame_index < thread.GetNumFrames(): 1567c47a371SJonas Devlieghere frame = thread.GetFrameAtIndex(lldb_frame_index) 157*602e47c5SDavid Spickett if frame.GetSymbol() and ( 158*602e47c5SDavid Spickett frame.GetSymbol().GetName() == "art_quick_invoke_stub" 159*602e47c5SDavid Spickett or frame.GetSymbol().GetName() == "art_quick_invoke_static_stub" 160*602e47c5SDavid Spickett ): 1617c47a371SJonas Devlieghere # art_quick_invoke_stub / art_quick_invoke_static_stub 1627c47a371SJonas Devlieghere # Skip until we get past the next ArtMethod::Invoke() 1637c47a371SJonas Devlieghere while True: 1647c47a371SJonas Devlieghere lldb_frame_index = lldb_frame_index + 1 1657c47a371SJonas Devlieghere if lldb_frame_index >= thread.GetNumFrames(): 166*602e47c5SDavid Spickett print( 167*602e47c5SDavid Spickett "ArtMethod::Invoke not found below art_quick_invoke_stub/art_quick_invoke_static_stub" 168*602e47c5SDavid Spickett ) 1697c47a371SJonas Devlieghere sys.exit(1) 1707c47a371SJonas Devlieghere frame = thread.GetFrameAtIndex(lldb_frame_index) 171*602e47c5SDavid Spickett if ( 172*602e47c5SDavid Spickett frame.GetSymbol() 173*602e47c5SDavid Spickett and frame.GetSymbol().GetName() 174*602e47c5SDavid Spickett == "art::mirror::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)" 175*602e47c5SDavid Spickett ): 1767c47a371SJonas Devlieghere lldb_frame_index = lldb_frame_index + 1 1777c47a371SJonas Devlieghere break 1787c47a371SJonas Devlieghere else: 179*602e47c5SDavid Spickett print("Invalid frame below compiled Java frame: ", frame) 180*602e47c5SDavid Spickett elif frame.GetSymbol() and re.search( 181*602e47c5SDavid Spickett r"art::interpreter::", frame.GetSymbol().GetName() 182*602e47c5SDavid Spickett ): 1837c47a371SJonas Devlieghere # Interpreted Java frame 1847c47a371SJonas Devlieghere 1857c47a371SJonas Devlieghere while True: 1867c47a371SJonas Devlieghere lldb_frame_index = lldb_frame_index + 1 1877c47a371SJonas Devlieghere if lldb_frame_index >= thread.GetNumFrames(): 188*602e47c5SDavid Spickett print("art::interpreter::Execute not found in interpreter frame") 1897c47a371SJonas Devlieghere sys.exit(1) 1907c47a371SJonas Devlieghere frame = thread.GetFrameAtIndex(lldb_frame_index) 191*602e47c5SDavid Spickett if ( 192*602e47c5SDavid Spickett frame.GetSymbol() 193*602e47c5SDavid Spickett and frame.GetSymbol().GetName() 194*602e47c5SDavid Spickett == "art::interpreter::Execute(art::Thread*, art::MethodHelper&, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue)" 195*602e47c5SDavid Spickett ): 1967c47a371SJonas Devlieghere break 1977c47a371SJonas Devlieghere 1987c47a371SJonas Devlieghere # Skip art frames 1997c47a371SJonas Devlieghere while True: 2007c47a371SJonas Devlieghere art_stack_visitor = frame.EvaluateExpression( 201*602e47c5SDavid Spickett """struct GetStackVisitor : public StackVisitor { GetStackVisitor(int depth_) : StackVisitor(Thread::Current(), NULL), depth(depth_) {} bool VisitFrame() { if (cur_depth_ == depth) { return false; } else { return true; } } int depth; }; GetStackVisitor visitor(""" 202*602e47c5SDavid Spickett + str(art_frame_index) 203*602e47c5SDavid Spickett + """); visitor.WalkStack(true); visitor""" 204*602e47c5SDavid Spickett ) 2057c47a371SJonas Devlieghere art_method = frame.EvaluateExpression( 206*602e47c5SDavid Spickett art_stack_visitor.GetName() + """.GetMethod()""" 207*602e47c5SDavid Spickett ) 2087c47a371SJonas Devlieghere if art_method.GetValueAsUnsigned() != 0: 2097c47a371SJonas Devlieghere # Get function/filename/lineno from ART runtime 2107c47a371SJonas Devlieghere art_method_name = frame.EvaluateExpression( 211*602e47c5SDavid Spickett """art::PrettyMethod(""" + art_method.GetName() + """, true)""" 212*602e47c5SDavid Spickett ) 2137c47a371SJonas Devlieghere art_method_name_data = frame.EvaluateExpression( 214*602e47c5SDavid Spickett art_method_name.GetName() + """.c_str()""" 215*602e47c5SDavid Spickett ).GetValueAsUnsigned() 2167c47a371SJonas Devlieghere art_method_name_size = frame.EvaluateExpression( 217*602e47c5SDavid Spickett art_method_name.GetName() + """.length()""" 218*602e47c5SDavid Spickett ).GetValueAsUnsigned() 2197c47a371SJonas Devlieghere error = lldb.SBError() 2207c47a371SJonas Devlieghere function = process.ReadCStringFromMemory( 221*602e47c5SDavid Spickett art_method_name_data, art_method_name_size + 1, error 222*602e47c5SDavid Spickett ) 2237c47a371SJonas Devlieghere 2247c47a371SJonas Devlieghere line = frame.EvaluateExpression( 225*602e47c5SDavid Spickett art_stack_visitor.GetName() 226*602e47c5SDavid Spickett + """.GetMethod()->GetLineNumFromDexPC(""" 227*602e47c5SDavid Spickett + art_stack_visitor.GetName() 228*602e47c5SDavid Spickett + """.GetDexPc(true))""" 229*602e47c5SDavid Spickett ).GetValueAsUnsigned() 2307c47a371SJonas Devlieghere 2317c47a371SJonas Devlieghere file_name = frame.EvaluateExpression( 232*602e47c5SDavid Spickett art_method.GetName() + """->GetDeclaringClassSourceFile()""" 233*602e47c5SDavid Spickett ) 2347c47a371SJonas Devlieghere file_name_data = file_name.GetValueAsUnsigned() 2357c47a371SJonas Devlieghere file_name_size = frame.EvaluateExpression( 236*602e47c5SDavid Spickett """(size_t)strlen(""" + file_name.GetName() + """)""" 237*602e47c5SDavid Spickett ).GetValueAsUnsigned() 2387c47a371SJonas Devlieghere error = lldb.SBError() 2397c47a371SJonas Devlieghere file_name = process.ReadCStringFromMemory( 240*602e47c5SDavid Spickett file_name_data, file_name_size + 1, error 241*602e47c5SDavid Spickett ) 2427c47a371SJonas Devlieghere if not error.Success(): 243*602e47c5SDavid Spickett print("Failed to read source file name") 2447c47a371SJonas Devlieghere sys.exit(1) 2457c47a371SJonas Devlieghere 246*602e47c5SDavid Spickett prettified_frames.append( 247*602e47c5SDavid Spickett {"function": function, "file": file_name, "line": line} 248*602e47c5SDavid Spickett ) 2497c47a371SJonas Devlieghere 2507c47a371SJonas Devlieghere art_frame_index = art_frame_index + 1 2517c47a371SJonas Devlieghere break 2527c47a371SJonas Devlieghere art_frame_index = art_frame_index + 1 2537c47a371SJonas Devlieghere 2547c47a371SJonas Devlieghere # Skip native frames 2557c47a371SJonas Devlieghere while True: 2567c47a371SJonas Devlieghere lldb_frame_index = lldb_frame_index + 1 2577c47a371SJonas Devlieghere if lldb_frame_index >= thread.GetNumFrames(): 258*602e47c5SDavid Spickett print("Can not get past interpreter native frames") 2597c47a371SJonas Devlieghere sys.exit(1) 2607c47a371SJonas Devlieghere frame = thread.GetFrameAtIndex(lldb_frame_index) 2617c47a371SJonas Devlieghere if frame.GetSymbol() and not re.search( 262*602e47c5SDavid Spickett r"art::interpreter::", frame.GetSymbol().GetName() 263*602e47c5SDavid Spickett ): 2647c47a371SJonas Devlieghere break 2657c47a371SJonas Devlieghere else: 2667c47a371SJonas Devlieghere # Other frames. Add them as-is. 2677c47a371SJonas Devlieghere frame = thread.GetFrameAtIndex(lldb_frame_index) 2687c47a371SJonas Devlieghere lldb_frame_index = lldb_frame_index + 1 2697c47a371SJonas Devlieghere if frame.GetModule(): 2707c47a371SJonas Devlieghere module_name = frame.GetModule().GetFileSpec().GetFilename() 2717c47a371SJonas Devlieghere if not module_name in [ 272*602e47c5SDavid Spickett "libartd.so", 273*602e47c5SDavid Spickett "dalvikvm32", 274*602e47c5SDavid Spickett "dalvikvm64", 275*602e47c5SDavid Spickett "libc.so.6", 276*602e47c5SDavid Spickett ]: 277*602e47c5SDavid Spickett prettified_frames.append( 278*602e47c5SDavid Spickett { 279*602e47c5SDavid Spickett "function": frame.GetSymbol().GetName() 280*602e47c5SDavid Spickett if frame.GetSymbol() 281*602e47c5SDavid Spickett else None, 282*602e47c5SDavid Spickett "file": str(frame.GetLineEntry().GetFileSpec()) 283*602e47c5SDavid Spickett if frame.GetLineEntry() 284*602e47c5SDavid Spickett else None, 285*602e47c5SDavid Spickett "line": frame.GetLineEntry().GetLine() 286*602e47c5SDavid Spickett if frame.GetLineEntry() 287*602e47c5SDavid Spickett else -1, 288*602e47c5SDavid Spickett } 289*602e47c5SDavid Spickett ) 2907c47a371SJonas Devlieghere 2917c47a371SJonas Devlieghere for prettified_frame in prettified_frames: 292*602e47c5SDavid Spickett print( 293*602e47c5SDavid Spickett prettified_frame["function"], 294*602e47c5SDavid Spickett prettified_frame["file"], 295*602e47c5SDavid Spickett prettified_frame["line"], 296*602e47c5SDavid Spickett ) 2977c47a371SJonas Devlieghere 2987c47a371SJonas Devlieghere 2997c47a371SJonas Devliegheredef __lldb_init_module(debugger, internal_dict): 300*602e47c5SDavid Spickett debugger.HandleCommand("command script add -f host_art_bt.host_art_bt host_art_bt") 301