blob: 0893662869f25b3d9d7f8071e357b48697935efa [file] [log] [blame]
Todd Fiala5bc56a42014-09-23 16:28:01 +00001# Usage:
2# art/test/run-test --host --gdb [--64] [--interpreter] 004-JniTest
3# 'b Java_Main_shortMethod'
4# 'r'
5# 'command script import host_art_bt.py'
6# 'host_art_bt'
7
8import sys
9import re
10
11import lldb
12
13def host_art_bt(debugger, command, result, internal_dict):
14 prettified_frames = []
15 lldb_frame_index = 0
16 art_frame_index = 0
17 target = debugger.GetSelectedTarget()
18 process = target.GetProcess()
19 thread = process.GetSelectedThread()
20 while lldb_frame_index < thread.GetNumFrames():
21 frame = thread.GetFrameAtIndex(lldb_frame_index)
22 if frame.GetModule() and re.match(r'JIT\(.*?\)', frame.GetModule().GetFileSpec().GetFilename()):
23 # Compiled Java frame
24
25 # Get function/filename/lineno from symbol context
26 symbol = frame.GetSymbol()
27 if not symbol:
28 print 'No symbol info for compiled Java frame: ', frame
29 sys.exit(1)
30 line_entry = frame.GetLineEntry()
31 prettified_frames.append({
32 'function': symbol.GetName(),
33 'file' : str(line_entry.GetFileSpec()) if line_entry else None,
34 'line' : line_entry.GetLine() if line_entry else -1
35 })
36
37 # Skip art frames
38 while True:
39 art_stack_visitor = frame.EvaluateExpression("""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(""" + str(art_frame_index) + """); visitor.WalkStack(true); visitor""")
40 art_method = frame.EvaluateExpression(art_stack_visitor.GetName() + """.GetMethod()""")
41 if art_method.GetValueAsUnsigned() != 0:
42 art_method_name = frame.EvaluateExpression("""art::PrettyMethod(""" + art_method.GetName() + """, true)""")
43 art_method_name_data = frame.EvaluateExpression(art_method_name.GetName() + """.c_str()""").GetValueAsUnsigned()
44 art_method_name_size = frame.EvaluateExpression(art_method_name.GetName() + """.length()""").GetValueAsUnsigned()
45 error = lldb.SBError()
46 art_method_name = process.ReadCStringFromMemory(art_method_name_data, art_method_name_size + 1, error)
47 if not error.Success:
48 print 'Failed to read method name'
49 sys.exit(1)
50 if art_method_name != symbol.GetName():
51 print 'Function names in native symbol and art runtime stack do not match: ', symbol.GetName(), ' != ', art_method_name
52 art_frame_index = art_frame_index + 1
53 break
54 art_frame_index = art_frame_index + 1
55
56 # Skip native frames
57 lldb_frame_index = lldb_frame_index + 1
58 if lldb_frame_index < thread.GetNumFrames():
59 frame = thread.GetFrameAtIndex(lldb_frame_index)
60 if frame.GetModule() and re.match(r'JIT\(.*?\)', frame.GetModule().GetFileSpec().GetFilename()):
61 # Another compile Java frame
62 # Don't skip; leave it to the next iteration
63 continue
64 elif frame.GetSymbol() and (frame.GetSymbol().GetName() == 'art_quick_invoke_stub' or frame.GetSymbol().GetName() == 'art_quick_invoke_static_stub'):
65 # art_quick_invoke_stub / art_quick_invoke_static_stub
66 # Skip until we get past the next ArtMethod::Invoke()
67 while True:
68 lldb_frame_index = lldb_frame_index + 1
69 if lldb_frame_index >= thread.GetNumFrames():
70 print 'ArtMethod::Invoke not found below art_quick_invoke_stub/art_quick_invoke_static_stub'
71 sys.exit(1)
72 frame = thread.GetFrameAtIndex(lldb_frame_index)
73 if frame.GetSymbol() and frame.GetSymbol().GetName() == 'art::mirror::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)':
74 lldb_frame_index = lldb_frame_index + 1
75 break
76 else:
77 print 'Invalid frame below compiled Java frame: ', frame
78 elif frame.GetSymbol() and frame.GetSymbol().GetName() == 'art_quick_generic_jni_trampoline':
79 # Interpreted JNI frame for x86_64
80
81 # Skip art frames
82 while True:
83 art_stack_visitor = frame.EvaluateExpression("""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(""" + str(art_frame_index) + """); visitor.WalkStack(true); visitor""")
84 art_method = frame.EvaluateExpression(art_stack_visitor.GetName() + """.GetMethod()""")
85 if art_method.GetValueAsUnsigned() != 0:
86 # Get function/filename/lineno from ART runtime
87 art_method_name = frame.EvaluateExpression("""art::PrettyMethod(""" + art_method.GetName() + """, true)""")
88 art_method_name_data = frame.EvaluateExpression(art_method_name.GetName() + """.c_str()""").GetValueAsUnsigned()
89 art_method_name_size = frame.EvaluateExpression(art_method_name.GetName() + """.length()""").GetValueAsUnsigned()
90 error = lldb.SBError()
91 function = process.ReadCStringFromMemory(art_method_name_data, art_method_name_size + 1, error)
92
93 prettified_frames.append({
94 'function': function,
95 'file' : None,
96 'line' : -1
97 })
98
99 art_frame_index = art_frame_index + 1
100 break
101 art_frame_index = art_frame_index + 1
102
103 # Skip native frames
104 lldb_frame_index = lldb_frame_index + 1
105 if lldb_frame_index < thread.GetNumFrames():
106 frame = thread.GetFrameAtIndex(lldb_frame_index)
107 if frame.GetSymbol() and (frame.GetSymbol().GetName() == 'art_quick_invoke_stub' or frame.GetSymbol().GetName() == 'art_quick_invoke_static_stub'):
108 # art_quick_invoke_stub / art_quick_invoke_static_stub
109 # Skip until we get past the next ArtMethod::Invoke()
110 while True:
111 lldb_frame_index = lldb_frame_index + 1
112 if lldb_frame_index >= thread.GetNumFrames():
113 print 'ArtMethod::Invoke not found below art_quick_invoke_stub/art_quick_invoke_static_stub'
114 sys.exit(1)
115 frame = thread.GetFrameAtIndex(lldb_frame_index)
116 if frame.GetSymbol() and frame.GetSymbol().GetName() == 'art::mirror::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)':
117 lldb_frame_index = lldb_frame_index + 1
118 break
119 else:
120 print 'Invalid frame below compiled Java frame: ', frame
121 elif frame.GetSymbol() and re.search(r'art::interpreter::', frame.GetSymbol().GetName()):
122 # Interpreted Java frame
123
124 while True:
125 lldb_frame_index = lldb_frame_index + 1
126 if lldb_frame_index >= thread.GetNumFrames():
127 print 'art::interpreter::Execute not found in interpreter frame'
128 sys.exit(1)
129 frame = thread.GetFrameAtIndex(lldb_frame_index)
130 if frame.GetSymbol() and frame.GetSymbol().GetName() == 'art::interpreter::Execute(art::Thread*, art::MethodHelper&, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue)':
131 break
132
133 # Skip art frames
134 while True:
135 art_stack_visitor = frame.EvaluateExpression("""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(""" + str(art_frame_index) + """); visitor.WalkStack(true); visitor""")
136 art_method = frame.EvaluateExpression(art_stack_visitor.GetName() + """.GetMethod()""")
137 if art_method.GetValueAsUnsigned() != 0:
138 # Get function/filename/lineno from ART runtime
139 art_method_name = frame.EvaluateExpression("""art::PrettyMethod(""" + art_method.GetName() + """, true)""")
140 art_method_name_data = frame.EvaluateExpression(art_method_name.GetName() + """.c_str()""").GetValueAsUnsigned()
141 art_method_name_size = frame.EvaluateExpression(art_method_name.GetName() + """.length()""").GetValueAsUnsigned()
142 error = lldb.SBError()
143 function = process.ReadCStringFromMemory(art_method_name_data, art_method_name_size + 1, error)
144
145 line = frame.EvaluateExpression(art_stack_visitor.GetName() + """.GetMethod()->GetLineNumFromDexPC(""" + art_stack_visitor.GetName() + """.GetDexPc(true))""").GetValueAsUnsigned()
146
147 file_name = frame.EvaluateExpression(art_method.GetName() + """->GetDeclaringClassSourceFile()""")
148 file_name_data = file_name.GetValueAsUnsigned()
149 file_name_size = frame.EvaluateExpression("""(size_t)strlen(""" + file_name.GetName() + """)""").GetValueAsUnsigned()
150 error = lldb.SBError()
151 file_name = process.ReadCStringFromMemory(file_name_data, file_name_size + 1, error)
152 if not error.Success():
153 print 'Failed to read source file name'
154 sys.exit(1)
155
156 prettified_frames.append({
157 'function': function,
158 'file' : file_name,
159 'line' : line
160 })
161
162 art_frame_index = art_frame_index + 1
163 break
164 art_frame_index = art_frame_index + 1
165
166 # Skip native frames
167 while True:
168 lldb_frame_index = lldb_frame_index + 1
169 if lldb_frame_index >= thread.GetNumFrames():
170 print 'Can not get past interpreter native frames'
171 sys.exit(1)
172 frame = thread.GetFrameAtIndex(lldb_frame_index)
173 if frame.GetSymbol() and not re.search(r'art::interpreter::', frame.GetSymbol().GetName()):
174 break
175 else:
176 # Other frames. Add them as-is.
177 frame = thread.GetFrameAtIndex(lldb_frame_index)
178 lldb_frame_index = lldb_frame_index + 1
179 if frame.GetModule():
180 module_name = frame.GetModule().GetFileSpec().GetFilename()
181 if not module_name in ['libartd.so', 'dalvikvm32', 'dalvikvm64', 'libc.so.6']:
182 prettified_frames.append({
183 'function': frame.GetSymbol().GetName() if frame.GetSymbol() else None,
184 'file' : str(frame.GetLineEntry().GetFileSpec()) if frame.GetLineEntry() else None,
185 'line' : frame.GetLineEntry().GetLine() if frame.GetLineEntry() else -1
186 })
187
188 for prettified_frame in prettified_frames:
189 print prettified_frame['function'], prettified_frame['file'], prettified_frame['line']
190
191def __lldb_init_module(debugger, internal_dict):
192 debugger.HandleCommand('command script add -f host_art_bt.host_art_bt host_art_bt')